xref: /freebsd/usr.sbin/ppp/vjcomp.c (revision 02f2e93b60c2b91feac8f45c4c889a5a8e40d8a2)
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.10 1997/10/07 00:56:58 brian Exp $
21  *
22  *  TODO:
23  */
24 #include <sys/types.h>
25 #include <netinet/in.h>
26 #include <netinet/in_systm.h>
27 #include <netinet/ip.h>
28 
29 #include <string.h>
30 
31 #include "mbuf.h"
32 #include "log.h"
33 #include "defs.h"
34 #include "timer.h"
35 #include "fsm.h"
36 #include "lcpproto.h"
37 #include "slcompress.h"
38 #include "hdlc.h"
39 #include "ipcp.h"
40 #include "vjcomp.h"
41 
42 #define MAX_VJHEADER 16		/* Maximum size of compressed header */
43 
44 struct slcompress cslc;
45 
46 void
47 VjInit(int max_state)
48 {
49   sl_compress_init(&cslc, max_state);
50 }
51 
52 void
53 SendPppFrame(struct mbuf * bp)
54 {
55   int type;
56   int proto;
57   int cproto = IpcpInfo.his_compproto >> 16;
58 
59   LogPrintf(LogDEBUG, "SendPppFrame: proto = %x\n", IpcpInfo.his_compproto);
60   if (((struct ip *) MBUF_CTOP(bp))->ip_p == IPPROTO_TCP
61       && cproto == PROTO_VJCOMP) {
62     type = sl_compress_tcp(bp, (struct ip *) MBUF_CTOP(bp), &cslc, IpcpInfo.his_compproto & 0xff);
63 
64     LogPrintf(LogDEBUG, "SendPppFrame: type = %x\n", type);
65     switch (type) {
66     case TYPE_IP:
67       proto = PROTO_IP;
68       break;
69     case TYPE_UNCOMPRESSED_TCP:
70       proto = PROTO_VJUNCOMP;
71       break;
72     case TYPE_COMPRESSED_TCP:
73       proto = PROTO_VJCOMP;
74       break;
75     default:
76       LogPrintf(LogERROR, "Unknown frame type %x\n", type);
77       pfree(bp);
78       return;
79     }
80   } else
81     proto = PROTO_IP;
82   HdlcOutput(PRI_NORMAL, proto, bp);
83 }
84 
85 static struct mbuf *
86 VjUncompressTcp(struct mbuf * bp, u_char type)
87 {
88   u_char *bufp;
89   int len, olen, rlen;
90   struct mbuf *nbp;
91   u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
92 
93   olen = len = plength(bp);
94   if (type == TYPE_UNCOMPRESSED_TCP) {
95 
96     /*
97      * Uncompressed packet does NOT change its size, so that we can use mbuf
98      * space for uncompression job.
99      */
100     bufp = MBUF_CTOP(bp);
101     len = sl_uncompress_tcp(&bufp, len, type, &cslc);
102     if (len <= 0) {
103       pfree(bp);
104       bp = NULLBUFF;
105     }
106     return (bp);
107   }
108 
109   /*
110    * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
111    * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
112    * Copy unread data info there.
113    */
114   if (len > MAX_VJHEADER)
115     len = MAX_VJHEADER;
116   rlen = len;
117   bufp = work + MAX_HDR;
118   bp = mbread(bp, bufp, rlen);
119   len = sl_uncompress_tcp(&bufp, olen, type, &cslc);
120   if (len <= 0) {
121     pfree(bp);
122     return NULLBUFF;
123   }
124   len -= olen;
125   len += rlen;
126   nbp = mballoc(len, MB_VJCOMP);
127   memcpy(MBUF_CTOP(nbp), bufp, len);
128   nbp->next = bp;
129   return (nbp);
130 }
131 
132 struct mbuf *
133 VjCompInput(struct mbuf * bp, int proto)
134 {
135   u_char type;
136 
137   LogPrintf(LogDEBUG, "VjCompInput: proto %02x\n", proto);
138   LogDumpBp(LogDEBUG, "Raw packet info:", bp);
139 
140   switch (proto) {
141   case PROTO_VJCOMP:
142     type = TYPE_COMPRESSED_TCP;
143     break;
144   case PROTO_VJUNCOMP:
145     type = TYPE_UNCOMPRESSED_TCP;
146     break;
147   default:
148     LogPrintf(LogERROR, "VjCompInput...???\n");
149     return (bp);
150   }
151   bp = VjUncompressTcp(bp, type);
152   return (bp);
153 }
154