vjcomp.c revision 30715
1243791Sdim/*
2243791Sdim *	       Input/Output VJ Compressed packets
3243791Sdim *
4243791Sdim *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5243791Sdim *
6243791Sdim *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7243791Sdim *
8243791Sdim * Redistribution and use in source and binary forms are permitted
9243791Sdim * provided that the above copyright notice and this paragraph are
10243791Sdim * duplicated in all such forms and that any documentation,
11243791Sdim * advertising materials, and other materials related to such
12243791Sdim * distribution and use acknowledge that the software was developed
13243791Sdim * by the Internet Initiative Japan, Inc.  The name of the
14243791Sdim * IIJ may not be used to endorse or promote products derived
15243791Sdim * from this software without specific prior written permission.
16243791Sdim * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17243791Sdim * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18243791Sdim * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19243791Sdim *
20243791Sdim * $Id: vjcomp.c,v 1.10 1997/10/07 00:56:58 brian Exp $
21243791Sdim *
22243791Sdim *  TODO:
23243791Sdim */
24243791Sdim#include <sys/types.h>
25243791Sdim#include <netinet/in.h>
26243791Sdim#include <netinet/in_systm.h>
27243791Sdim#include <netinet/ip.h>
28243791Sdim
29243791Sdim#include <string.h>
30243791Sdim
31243791Sdim#include "mbuf.h"
32243791Sdim#include "log.h"
33243791Sdim#include "defs.h"
34243791Sdim#include "timer.h"
35243791Sdim#include "fsm.h"
36243791Sdim#include "lcpproto.h"
37243791Sdim#include "slcompress.h"
38243791Sdim#include "hdlc.h"
39243791Sdim#include "ipcp.h"
40243791Sdim#include "vjcomp.h"
41243791Sdim
42243791Sdim#define MAX_VJHEADER 16		/* Maximum size of compressed header */
43263508Sdim
44243791Sdimstruct slcompress cslc;
45263508Sdim
46243791Sdimvoid
47243791SdimVjInit(int max_state)
48243791Sdim{
49243791Sdim  sl_compress_init(&cslc, max_state);
50249423Sdim}
51249423Sdim
52263508Sdimvoid
53263508SdimSendPppFrame(struct mbuf * bp)
54263508Sdim{
55249423Sdim  int type;
56249423Sdim  int proto;
57249423Sdim  int cproto = IpcpInfo.his_compproto >> 16;
58243791Sdim
59243791Sdim  LogPrintf(LogDEBUG, "SendPppFrame: proto = %x\n", IpcpInfo.his_compproto);
60243791Sdim  if (((struct ip *) MBUF_CTOP(bp))->ip_p == IPPROTO_TCP
61243791Sdim      && cproto == PROTO_VJCOMP) {
62243791Sdim    type = sl_compress_tcp(bp, (struct ip *) MBUF_CTOP(bp), &cslc, IpcpInfo.his_compproto & 0xff);
63243791Sdim
64243791Sdim    LogPrintf(LogDEBUG, "SendPppFrame: type = %x\n", type);
65243791Sdim    switch (type) {
66243791Sdim    case TYPE_IP:
67243791Sdim      proto = PROTO_IP;
68243791Sdim      break;
69243791Sdim    case TYPE_UNCOMPRESSED_TCP:
70243791Sdim      proto = PROTO_VJUNCOMP;
71243791Sdim      break;
72243791Sdim    case TYPE_COMPRESSED_TCP:
73243791Sdim      proto = PROTO_VJCOMP;
74243791Sdim      break;
75243791Sdim    default:
76243791Sdim      LogPrintf(LogERROR, "Unknown frame type %x\n", type);
77243791Sdim      pfree(bp);
78243791Sdim      return;
79243791Sdim    }
80243791Sdim  } else
81243791Sdim    proto = PROTO_IP;
82243791Sdim  HdlcOutput(PRI_NORMAL, proto, bp);
83243791Sdim}
84243791Sdim
85243791Sdimstatic struct mbuf *
86243791SdimVjUncompressTcp(struct mbuf * bp, u_char type)
87243791Sdim{
88243791Sdim  u_char *bufp;
89243791Sdim  int len, olen, rlen;
90243791Sdim  struct mbuf *nbp;
91243791Sdim  u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
92243791Sdim
93243791Sdim  olen = len = plength(bp);
94243791Sdim  if (type == TYPE_UNCOMPRESSED_TCP) {
95243791Sdim
96243791Sdim    /*
97243791Sdim     * Uncompressed packet does NOT change its size, so that we can use mbuf
98243791Sdim     * space for uncompression job.
99243791Sdim     */
100243791Sdim    bufp = MBUF_CTOP(bp);
101243791Sdim    len = sl_uncompress_tcp(&bufp, len, type, &cslc);
102243791Sdim    if (len <= 0) {
103243791Sdim      pfree(bp);
104243791Sdim      bp = NULLBUFF;
105243791Sdim    }
106243791Sdim    return (bp);
107243791Sdim  }
108243791Sdim
109243791Sdim  /*
110243791Sdim   * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
111243791Sdim   * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
112243791Sdim   * Copy unread data info there.
113243791Sdim   */
114243791Sdim  if (len > MAX_VJHEADER)
115243791Sdim    len = MAX_VJHEADER;
116243791Sdim  rlen = len;
117243791Sdim  bufp = work + MAX_HDR;
118243791Sdim  bp = mbread(bp, bufp, rlen);
119243791Sdim  len = sl_uncompress_tcp(&bufp, olen, type, &cslc);
120243791Sdim  if (len <= 0) {
121243791Sdim    pfree(bp);
122243791Sdim    return NULLBUFF;
123243791Sdim  }
124243791Sdim  len -= olen;
125243791Sdim  len += rlen;
126243791Sdim  nbp = mballoc(len, MB_VJCOMP);
127243791Sdim  memcpy(MBUF_CTOP(nbp), bufp, len);
128243791Sdim  nbp->next = bp;
129243791Sdim  return (nbp);
130243791Sdim}
131243791Sdim
132243791Sdimstruct mbuf *
133243791SdimVjCompInput(struct mbuf * bp, int proto)
134243791Sdim{
135243791Sdim  u_char type;
136243791Sdim
137243791Sdim  LogPrintf(LogDEBUG, "VjCompInput: proto %02x\n", proto);
138243791Sdim  LogDumpBp(LogDEBUG, "Raw packet info:", bp);
139243791Sdim
140243791Sdim  switch (proto) {
141243791Sdim  case PROTO_VJCOMP:
142243791Sdim    type = TYPE_COMPRESSED_TCP;
143243791Sdim    break;
144243791Sdim  case PROTO_VJUNCOMP:
145243791Sdim    type = TYPE_UNCOMPRESSED_TCP;
146243791Sdim    break;
147243791Sdim  default:
148243791Sdim    LogPrintf(LogERROR, "VjCompInput...???\n");
149243791Sdim    return (bp);
150263508Sdim  }
151243791Sdim  bp = VjUncompressTcp(bp, type);
152243791Sdim  return (bp);
153243791Sdim}
154243791Sdim