xref: /freebsd/usr.sbin/ppp/vjcomp.c (revision 26af0ae96638b0453bcc87cae6031eb0b3988171)
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  *
2097d92980SPeter Wemm  * $FreeBSD$
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>
31eb6e5e05SBrian Somers #include <string.h>		/* strlen/memcpy */
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 
6926af0ae9SBrian Somers   bp = m_pullup(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");
8426af0ae9SBrian Somers       m_settype(bp, MB_VJOUT);
855d9e6103SBrian Somers       break;
865d9e6103SBrian Somers 
875d9e6103SBrian Somers     case TYPE_COMPRESSED_TCP:
885d9e6103SBrian Somers       *proto = PROTO_VJCOMP;
896815097bSBrian Somers       log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n");
9026af0ae9SBrian Somers       m_settype(bp, MB_VJOUT);
915d9e6103SBrian Somers       break;
925d9e6103SBrian Somers 
935d9e6103SBrian Somers     default:
946815097bSBrian Somers       log_Printf(LogERROR, "vj_LayerPush: Unknown frame type %x\n", type);
9526af0ae9SBrian Somers       m_freem(bp);
965d9e6103SBrian Somers       return NULL;
975d9e6103SBrian Somers     }
985d9e6103SBrian Somers   }
995d9e6103SBrian Somers 
1005d9e6103SBrian Somers   return bp;
101af57ed9fSAtsushi Murai }
102af57ed9fSAtsushi Murai 
103af57ed9fSAtsushi Murai static struct mbuf *
104eaa4df37SBrian Somers VjUncompressTcp(struct ipcp *ipcp, struct mbuf *bp, u_char type)
105af57ed9fSAtsushi Murai {
106af57ed9fSAtsushi Murai   u_char *bufp;
107af57ed9fSAtsushi Murai   int len, olen, rlen;
108af57ed9fSAtsushi Murai   struct mbuf *nbp;
109af57ed9fSAtsushi Murai   u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
110af57ed9fSAtsushi Murai 
11126af0ae9SBrian Somers   bp = m_pullup(bp);
11226af0ae9SBrian Somers   olen = len = m_length(bp);
113af57ed9fSAtsushi Murai   if (type == TYPE_UNCOMPRESSED_TCP) {
114af57ed9fSAtsushi Murai     /*
115944f7098SBrian Somers      * Uncompressed packet does NOT change its size, so that we can use mbuf
116944f7098SBrian Somers      * space for uncompression job.
117af57ed9fSAtsushi Murai      */
118af57ed9fSAtsushi Murai     bufp = MBUF_CTOP(bp);
11942c57c86SBrian Somers     len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
12042c57c86SBrian Somers                             (ipcp->my_compproto >> 8) & 255);
12153c9f6c0SAtsushi Murai     if (len <= 0) {
12226af0ae9SBrian Somers       m_freem(bp);
123aa8e0519SBrian Somers       bp = NULL;
124411675baSBrian Somers     } else
12526af0ae9SBrian Somers       m_settype(bp, MB_VJIN);
1265d9e6103SBrian Somers     return bp;
127af57ed9fSAtsushi Murai   }
128944f7098SBrian Somers 
129af57ed9fSAtsushi Murai   /*
130944f7098SBrian Somers    * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
131944f7098SBrian Somers    * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
132944f7098SBrian Somers    * Copy unread data info there.
133af57ed9fSAtsushi Murai    */
134944f7098SBrian Somers   if (len > MAX_VJHEADER)
135944f7098SBrian Somers     len = MAX_VJHEADER;
136af57ed9fSAtsushi Murai   rlen = len;
137af57ed9fSAtsushi Murai   bufp = work + MAX_HDR;
138dd7e2610SBrian Somers   bp = mbuf_Read(bp, bufp, rlen);
13942c57c86SBrian Somers   len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
14042c57c86SBrian Somers                           (ipcp->my_compproto >> 8) & 255);
14153c9f6c0SAtsushi Murai   if (len <= 0) {
14226af0ae9SBrian Somers     m_freem(bp);
143aa8e0519SBrian Somers     return NULL;
14453c9f6c0SAtsushi Murai   }
145af57ed9fSAtsushi Murai   len -= olen;
146af57ed9fSAtsushi Murai   len += rlen;
14726af0ae9SBrian Somers   nbp = m_get(len, MB_VJIN);
14875240ed1SBrian Somers   memcpy(MBUF_CTOP(nbp), bufp, len);
14926af0ae9SBrian Somers   m_settype(bp, MB_VJIN);
15026af0ae9SBrian Somers   nbp->m_next = bp;
1515d9e6103SBrian Somers   return nbp;
152af57ed9fSAtsushi Murai }
153af57ed9fSAtsushi Murai 
1545d9e6103SBrian Somers static struct mbuf *
1555d9e6103SBrian Somers vj_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
1565d9e6103SBrian Somers              u_short *proto)
157af57ed9fSAtsushi Murai {
158af57ed9fSAtsushi Murai   u_char type;
159af57ed9fSAtsushi Murai 
1605d9e6103SBrian Somers   switch (*proto) {
161af57ed9fSAtsushi Murai   case PROTO_VJCOMP:
162af57ed9fSAtsushi Murai     type = TYPE_COMPRESSED_TCP;
1636815097bSBrian Somers     log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJCOMP -> PROTO_IP\n");
164af57ed9fSAtsushi Murai     break;
165af57ed9fSAtsushi Murai   case PROTO_VJUNCOMP:
166af57ed9fSAtsushi Murai     type = TYPE_UNCOMPRESSED_TCP;
1676815097bSBrian Somers     log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJUNCOMP -> PROTO_IP\n");
168af57ed9fSAtsushi Murai     break;
169af57ed9fSAtsushi Murai   default:
1705d9e6103SBrian Somers     return bp;
171af57ed9fSAtsushi Murai   }
1725d9e6103SBrian Somers 
1735d9e6103SBrian Somers   *proto = PROTO_IP;
1745d9e6103SBrian Somers   return VjUncompressTcp(&bundle->ncp.ipcp, bp, type);
175af57ed9fSAtsushi Murai }
1760053cc58SBrian Somers 
1770053cc58SBrian Somers const char *
1783a70c9f7SBrian Somers vj2asc(u_int32_t val)
1790053cc58SBrian Somers {
180d93d3a9cSBrian Somers   static char asc[50];		/* The return value is used immediately */
1810053cc58SBrian Somers 
1821342caedSBrian Somers   if (val)
1835d9e6103SBrian Somers     snprintf(asc, sizeof asc, "%d VJ slots with%s slot compression",
1845d9e6103SBrian Somers             (int)((val>>8)&15)+1, val & 1 ?  "" : "out");
1851342caedSBrian Somers   else
1861342caedSBrian Somers     strcpy(asc, "VJ disabled");
1870053cc58SBrian Somers   return asc;
1880053cc58SBrian Somers }
1895d9e6103SBrian Somers 
1905d9e6103SBrian Somers struct layer vjlayer = { LAYER_VJ, "vj", vj_LayerPush, vj_LayerPull };
191