xref: /freebsd/usr.sbin/ppp/vjcomp.c (revision 6815097bf774651c1f6c3b4052fd7eb5ee9aaac0)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *	       Input/Output VJ Compressed packets
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
206815097bSBrian Somers  * $Id: vjcomp.c,v 1.29 1999/05/09 20:02:29 brian Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *  TODO:
23af57ed9fSAtsushi Murai  */
24972a1bcfSBrian Somers #include <sys/param.h>
2575240ed1SBrian Somers #include <netinet/in.h>
26af57ed9fSAtsushi Murai #include <netinet/in_systm.h>
27af57ed9fSAtsushi Murai #include <netinet/ip.h>
281fa665f5SBrian Somers #include <sys/un.h>
2975240ed1SBrian Somers 
305106c671SBrian Somers #include <stdio.h>
31eb2d27cfSBrian Somers #include <string.h>
325d9e6103SBrian Somers #include <termios.h>
3375240ed1SBrian Somers 
345d9e6103SBrian Somers #include "layer.h"
3575240ed1SBrian Somers #include "mbuf.h"
3675240ed1SBrian Somers #include "log.h"
3775240ed1SBrian Somers #include "timer.h"
3875240ed1SBrian Somers #include "fsm.h"
395d9e6103SBrian Somers #include "proto.h"
40af57ed9fSAtsushi Murai #include "slcompress.h"
41879ed6faSBrian Somers #include "lqr.h"
42af57ed9fSAtsushi Murai #include "hdlc.h"
4329e275ceSBrian Somers #include "defs.h"
4429e275ceSBrian Somers #include "iplist.h"
4529e275ceSBrian Somers #include "throughput.h"
46af57ed9fSAtsushi Murai #include "ipcp.h"
47f4768038SBrian Somers #include "lcp.h"
48f4768038SBrian Somers #include "ccp.h"
49f4768038SBrian Somers #include "link.h"
505ca5389aSBrian Somers #include "filter.h"
512f786681SBrian Somers #include "descriptor.h"
523b0f8d2eSBrian Somers #include "mp.h"
53972a1bcfSBrian Somers #ifndef NORADIUS
54972a1bcfSBrian Somers #include "radius.h"
55972a1bcfSBrian Somers #endif
56f4768038SBrian Somers #include "bundle.h"
5775240ed1SBrian Somers #include "vjcomp.h"
58af57ed9fSAtsushi Murai 
59af57ed9fSAtsushi Murai #define MAX_VJHEADER 16		/* Maximum size of compressed header */
60af57ed9fSAtsushi Murai 
615d9e6103SBrian Somers static struct mbuf *
625d9e6103SBrian Somers vj_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp, int pri,
635d9e6103SBrian Somers              u_short *proto)
64af57ed9fSAtsushi Murai {
65af57ed9fSAtsushi Murai   int type;
66aad80d9fSBrian Somers   struct ip *pip;
675828db6dSBrian Somers   u_short cproto = bundle->ncp.ipcp.peer_compproto >> 16;
68af57ed9fSAtsushi Murai 
69aad80d9fSBrian Somers   bp = mbuf_Contiguous(bp);
70aad80d9fSBrian Somers   pip = (struct ip *)MBUF_CTOP(bp);
715d9e6103SBrian Somers   if (*proto == PROTO_IP && pip->ip_p == IPPROTO_TCP &&
725d9e6103SBrian Somers       cproto == PROTO_VJCOMP) {
73aad80d9fSBrian Somers     type = sl_compress_tcp(bp, pip, &bundle->ncp.ipcp.vj.cslc,
74eaa4df37SBrian Somers                            &bundle->ncp.ipcp.vj.slstat,
755828db6dSBrian Somers                            bundle->ncp.ipcp.peer_compproto & 0xff);
765d9e6103SBrian Somers     log_Printf(LogDEBUG, "vj_LayerWrite: type = %x\n", type);
77af57ed9fSAtsushi Murai     switch (type) {
78af57ed9fSAtsushi Murai     case TYPE_IP:
79af57ed9fSAtsushi Murai       break;
80f4768038SBrian Somers 
815d9e6103SBrian Somers     case TYPE_UNCOMPRESSED_TCP:
825d9e6103SBrian Somers       *proto = PROTO_VJUNCOMP;
836815097bSBrian Somers       log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n");
845d9e6103SBrian Somers       break;
855d9e6103SBrian Somers 
865d9e6103SBrian Somers     case TYPE_COMPRESSED_TCP:
875d9e6103SBrian Somers       *proto = PROTO_VJCOMP;
886815097bSBrian Somers       log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n");
895d9e6103SBrian Somers       break;
905d9e6103SBrian Somers 
915d9e6103SBrian Somers     default:
926815097bSBrian Somers       log_Printf(LogERROR, "vj_LayerPush: Unknown frame type %x\n", type);
935d9e6103SBrian Somers       mbuf_Free(bp);
945d9e6103SBrian Somers       return NULL;
955d9e6103SBrian Somers     }
965d9e6103SBrian Somers   }
975d9e6103SBrian Somers 
985d9e6103SBrian Somers   return bp;
99af57ed9fSAtsushi Murai }
100af57ed9fSAtsushi Murai 
101af57ed9fSAtsushi Murai static struct mbuf *
102eaa4df37SBrian Somers VjUncompressTcp(struct ipcp *ipcp, struct mbuf *bp, u_char type)
103af57ed9fSAtsushi Murai {
104af57ed9fSAtsushi Murai   u_char *bufp;
105af57ed9fSAtsushi Murai   int len, olen, rlen;
106af57ed9fSAtsushi Murai   struct mbuf *nbp;
107af57ed9fSAtsushi Murai   u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
108af57ed9fSAtsushi Murai 
109aad80d9fSBrian Somers   bp = mbuf_Contiguous(bp);
110dd7e2610SBrian Somers   olen = len = mbuf_Length(bp);
111af57ed9fSAtsushi Murai   if (type == TYPE_UNCOMPRESSED_TCP) {
112af57ed9fSAtsushi Murai     /*
113944f7098SBrian Somers      * Uncompressed packet does NOT change its size, so that we can use mbuf
114944f7098SBrian Somers      * space for uncompression job.
115af57ed9fSAtsushi Murai      */
116af57ed9fSAtsushi Murai     bufp = MBUF_CTOP(bp);
11742c57c86SBrian Somers     len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
11842c57c86SBrian Somers                             (ipcp->my_compproto >> 8) & 255);
11953c9f6c0SAtsushi Murai     if (len <= 0) {
120dd7e2610SBrian Somers       mbuf_Free(bp);
121aa8e0519SBrian Somers       bp = NULL;
12253c9f6c0SAtsushi Murai     }
1235d9e6103SBrian Somers     return bp;
124af57ed9fSAtsushi Murai   }
125944f7098SBrian Somers 
126af57ed9fSAtsushi Murai   /*
127944f7098SBrian Somers    * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
128944f7098SBrian Somers    * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
129944f7098SBrian Somers    * Copy unread data info there.
130af57ed9fSAtsushi Murai    */
131944f7098SBrian Somers   if (len > MAX_VJHEADER)
132944f7098SBrian Somers     len = MAX_VJHEADER;
133af57ed9fSAtsushi Murai   rlen = len;
134af57ed9fSAtsushi Murai   bufp = work + MAX_HDR;
135dd7e2610SBrian Somers   bp = mbuf_Read(bp, bufp, rlen);
13642c57c86SBrian Somers   len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
13742c57c86SBrian Somers                           (ipcp->my_compproto >> 8) & 255);
13853c9f6c0SAtsushi Murai   if (len <= 0) {
139dd7e2610SBrian Somers     mbuf_Free(bp);
140aa8e0519SBrian Somers     return NULL;
14153c9f6c0SAtsushi Murai   }
142af57ed9fSAtsushi Murai   len -= olen;
143af57ed9fSAtsushi Murai   len += rlen;
144dd7e2610SBrian Somers   nbp = mbuf_Alloc(len, MB_VJCOMP);
14575240ed1SBrian Somers   memcpy(MBUF_CTOP(nbp), bufp, len);
146af57ed9fSAtsushi Murai   nbp->next = bp;
1475d9e6103SBrian Somers   return nbp;
148af57ed9fSAtsushi Murai }
149af57ed9fSAtsushi Murai 
1505d9e6103SBrian Somers static struct mbuf *
1515d9e6103SBrian Somers vj_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
1525d9e6103SBrian Somers              u_short *proto)
153af57ed9fSAtsushi Murai {
154af57ed9fSAtsushi Murai   u_char type;
155af57ed9fSAtsushi Murai 
1565d9e6103SBrian Somers   switch (*proto) {
157af57ed9fSAtsushi Murai   case PROTO_VJCOMP:
158af57ed9fSAtsushi Murai     type = TYPE_COMPRESSED_TCP;
1596815097bSBrian Somers     log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJCOMP -> PROTO_IP\n");
160af57ed9fSAtsushi Murai     break;
161af57ed9fSAtsushi Murai   case PROTO_VJUNCOMP:
162af57ed9fSAtsushi Murai     type = TYPE_UNCOMPRESSED_TCP;
1636815097bSBrian Somers     log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJUNCOMP -> PROTO_IP\n");
164af57ed9fSAtsushi Murai     break;
165af57ed9fSAtsushi Murai   default:
1665d9e6103SBrian Somers     return bp;
167af57ed9fSAtsushi Murai   }
1685d9e6103SBrian Somers 
1695d9e6103SBrian Somers   *proto = PROTO_IP;
1705d9e6103SBrian Somers   return VjUncompressTcp(&bundle->ncp.ipcp, bp, type);
171af57ed9fSAtsushi Murai }
1720053cc58SBrian Somers 
1730053cc58SBrian Somers const char *
1743a70c9f7SBrian Somers vj2asc(u_int32_t val)
1750053cc58SBrian Somers {
176d93d3a9cSBrian Somers   static char asc[50];		/* The return value is used immediately */
1770053cc58SBrian Somers 
1781342caedSBrian Somers   if (val)
1795d9e6103SBrian Somers     snprintf(asc, sizeof asc, "%d VJ slots with%s slot compression",
1805d9e6103SBrian Somers             (int)((val>>8)&15)+1, val & 1 ?  "" : "out");
1811342caedSBrian Somers   else
1821342caedSBrian Somers     strcpy(asc, "VJ disabled");
1830053cc58SBrian Somers   return asc;
1840053cc58SBrian Somers }
1855d9e6103SBrian Somers 
1865d9e6103SBrian Somers struct layer vjlayer = { LAYER_VJ, "vj", vj_LayerPush, vj_LayerPull };
187