xref: /freebsd/usr.sbin/ppp/vjcomp.c (revision 0de89efe5c443f213c7ea28773ef2dc6cf3af2ed)
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.8 1997/06/09 03:27:43 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(struct mbuf * bp)
44 {
45   int type;
46   int proto;
47   int cproto = IpcpInfo.his_compproto >> 16;
48 
49   LogPrintf(LogDEBUG, "SendPppFrame: proto = %x\n", IpcpInfo.his_compproto);
50   if (((struct ip *) MBUF_CTOP(bp))->ip_p == IPPROTO_TCP
51       && cproto == PROTO_VJCOMP) {
52     type = sl_compress_tcp(bp, (struct ip *) MBUF_CTOP(bp), &cslc, IpcpInfo.his_compproto & 0xff);
53 
54     LogPrintf(LogDEBUG, "SendPppFrame: type = %x\n", type);
55     switch (type) {
56     case TYPE_IP:
57       proto = PROTO_IP;
58       break;
59     case TYPE_UNCOMPRESSED_TCP:
60       proto = PROTO_VJUNCOMP;
61       break;
62     case TYPE_COMPRESSED_TCP:
63       proto = PROTO_VJCOMP;
64       break;
65     default:
66       LogPrintf(LogERROR, "Unknown frame type %x\n", type);
67       pfree(bp);
68       return;
69     }
70   } else
71     proto = PROTO_IP;
72   HdlcOutput(PRI_NORMAL, proto, bp);
73 }
74 
75 static struct mbuf *
76 VjUncompressTcp(struct mbuf * bp, u_char type)
77 {
78   u_char *bufp;
79   int len, olen, rlen;
80   struct mbuf *nbp;
81   u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
82 
83   olen = len = plength(bp);
84   if (type == TYPE_UNCOMPRESSED_TCP) {
85 
86     /*
87      * Uncompressed packet does NOT change its size, so that we can use mbuf
88      * space for uncompression job.
89      */
90     bufp = MBUF_CTOP(bp);
91     len = sl_uncompress_tcp(&bufp, len, type, &cslc);
92     if (len <= 0) {
93       pfree(bp);
94       bp = NULLBUFF;
95     }
96     return (bp);
97   }
98 
99   /*
100    * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
101    * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
102    * Copy unread data info there.
103    */
104   if (len > MAX_VJHEADER)
105     len = MAX_VJHEADER;
106   rlen = len;
107   bufp = work + MAX_HDR;
108   bp = mbread(bp, bufp, rlen);
109   len = sl_uncompress_tcp(&bufp, olen, type, &cslc);
110   if (len <= 0) {
111     pfree(bp);
112     return NULLBUFF;
113   }
114   len -= olen;
115   len += rlen;
116   nbp = mballoc(len, MB_VJCOMP);
117   bcopy(bufp, MBUF_CTOP(nbp), len);
118   nbp->next = bp;
119   return (nbp);
120 }
121 
122 struct mbuf *
123 VjCompInput(struct mbuf * bp, int proto)
124 {
125   u_char type;
126 
127   LogPrintf(LogDEBUG, "VjCompInput: proto %02x\n", proto);
128   LogDumpBp(LogDEBUG, "Raw packet info:", bp);
129 
130   switch (proto) {
131   case PROTO_VJCOMP:
132     type = TYPE_COMPRESSED_TCP;
133     break;
134   case PROTO_VJUNCOMP:
135     type = TYPE_UNCOMPRESSED_TCP;
136     break;
137   default:
138     LogPrintf(LogERROR, "VjCompInput...???\n");
139     return (bp);
140   }
141   bp = VjUncompressTcp(bp, type);
142   return (bp);
143 }
144