xref: /freebsd/usr.sbin/ppp/vjcomp.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
1 /*
2  *	       Input/Output VJ Compressed packets
3  *
4  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5  *
6  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the Internet Initiative Japan, Inc.  The name of the
14  * IIJ may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * $Id: vjcomp.c,v 1.7 1997/05/07 23:30:50 brian Exp $
21  *
22  *  TODO:
23  */
24 #include "fsm.h"
25 #include "lcpproto.h"
26 #include <netinet/in_systm.h>
27 #include <netinet/ip.h>
28 #include "slcompress.h"
29 #include "hdlc.h"
30 #include "ipcp.h"
31 
32 #define MAX_VJHEADER 16	/* Maximum size of compressed header */
33 
34 struct slcompress cslc;
35 
36 void
37 VjInit()
38 {
39   sl_compress_init(&cslc);
40 }
41 
42 void
43 SendPppFrame(bp)
44 struct mbuf *bp;
45 {
46   int type;
47   int proto;
48   int cproto = IpcpInfo.his_compproto >> 16;
49 
50   LogPrintf(LogDEBUG, "SendPppFrame: proto = %x\n", IpcpInfo.his_compproto);
51   if (((struct ip *)MBUF_CTOP(bp))->ip_p == IPPROTO_TCP
52       && cproto== PROTO_VJCOMP) {
53     type = sl_compress_tcp(bp, (struct ip *)MBUF_CTOP(bp), &cslc, IpcpInfo.his_compproto & 0xff);
54 
55     LogPrintf(LogDEBUG, "SendPppFrame: type = %x\n", type);
56     switch (type) {
57     case TYPE_IP:
58       proto = PROTO_IP;
59       break;
60     case TYPE_UNCOMPRESSED_TCP:
61       proto = PROTO_VJUNCOMP;
62       break;
63     case TYPE_COMPRESSED_TCP:
64       proto = PROTO_VJCOMP;
65       break;
66     default:
67       LogPrintf(LogERROR, "Unknown frame type %x\n", type);
68       pfree(bp);
69       return;
70     }
71   } else
72     proto = PROTO_IP;
73   HdlcOutput(PRI_NORMAL, proto, bp);
74 }
75 
76 static struct mbuf *
77 VjUncompressTcp(bp, type)
78 struct mbuf *bp;
79 u_char type;
80 {
81   u_char *bufp;
82   int len, olen, rlen;
83   struct mbuf *nbp;
84   u_char work[MAX_HDR+MAX_VJHEADER];   /* enough to hold TCP/IP header */
85 
86   olen = len = plength(bp);
87   if (type == TYPE_UNCOMPRESSED_TCP) {
88     /*
89      * Uncompressed packet does NOT change its size, so that we can
90      * use mbuf space for uncompression job.
91      */
92     bufp = MBUF_CTOP(bp);
93     len = sl_uncompress_tcp(&bufp, len, type, &cslc);
94     if (len <= 0) {
95       pfree(bp);
96       bp = NULLBUFF;
97     }
98     return(bp);
99   }
100   /*
101    *  Handle compressed packet.
102    *    1) Read upto MAX_VJHEADER bytes into work space.
103    *	2) Try to uncompress it.
104    *    3) Compute amount of necesary space.
105    *    4) Copy unread data info there.
106    */
107   if (len > MAX_VJHEADER) len = MAX_VJHEADER;
108   rlen = len;
109   bufp = work + MAX_HDR;
110   bp = mbread(bp, bufp, rlen);
111   len = sl_uncompress_tcp(&bufp, olen, type, &cslc);
112   if (len <= 0) {
113     pfree(bp);
114     return NULLBUFF;
115   }
116   len -= olen;
117   len += rlen;
118   nbp = mballoc(len, MB_VJCOMP);
119   bcopy(bufp, MBUF_CTOP(nbp), len);
120   nbp->next = bp;
121   return(nbp);
122 }
123 
124 struct mbuf *
125 VjCompInput(bp, proto)
126 struct mbuf *bp;
127 int proto;
128 {
129   u_char type;
130 
131   LogPrintf(LogDEBUG, "VjCompInput: proto %02x\n", proto);
132   LogDumpBp(LogDEBUG, "Raw packet info:", bp);
133 
134   switch (proto) {
135   case PROTO_VJCOMP:
136     type = TYPE_COMPRESSED_TCP;
137     break;
138   case PROTO_VJUNCOMP:
139     type = TYPE_UNCOMPRESSED_TCP;
140     break;
141   default:
142     LogPrintf(LogERROR, "VjCompInput...???\n");
143     return(bp);
144   }
145   bp = VjUncompressTcp(bp, type);
146   return(bp);
147 }
148