vjcomp.c revision 46686
16059Samurai/*
26059Samurai *	       Input/Output VJ Compressed packets
36059Samurai *
46059Samurai *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
56059Samurai *
66059Samurai *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
76059Samurai *
86059Samurai * Redistribution and use in source and binary forms are permitted
96059Samurai * provided that the above copyright notice and this paragraph are
106059Samurai * duplicated in all such forms and that any documentation,
116059Samurai * advertising materials, and other materials related to such
126059Samurai * distribution and use acknowledge that the software was developed
136059Samurai * by the Internet Initiative Japan, Inc.  The name of the
146059Samurai * IIJ may not be used to endorse or promote products derived
156059Samurai * from this software without specific prior written permission.
166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
196059Samurai *
2046686Sbrian * $Id: vjcomp.c,v 1.27 1999/03/31 14:21:46 brian Exp $
218857Srgrimes *
226059Samurai *  TODO:
236059Samurai */
2443313Sbrian#include <sys/param.h>
2530715Sbrian#include <netinet/in.h>
2630715Sbrian#include <netinet/in_systm.h>
2730715Sbrian#include <netinet/ip.h>
2836285Sbrian#include <sys/un.h>
2930715Sbrian
3031061Sbrian#include <stdio.h>
3145193Sbrian#include <string.h>
3246686Sbrian#include <termios.h>
3330715Sbrian
3446686Sbrian#include "layer.h"
3530715Sbrian#include "mbuf.h"
3630715Sbrian#include "log.h"
3730715Sbrian#include "timer.h"
386059Samurai#include "fsm.h"
3946686Sbrian#include "proto.h"
406059Samurai#include "slcompress.h"
4136285Sbrian#include "lqr.h"
426059Samurai#include "hdlc.h"
4336285Sbrian#include "defs.h"
4436285Sbrian#include "iplist.h"
4536285Sbrian#include "throughput.h"
466059Samurai#include "ipcp.h"
4736285Sbrian#include "lcp.h"
4836285Sbrian#include "ccp.h"
4936285Sbrian#include "link.h"
5036285Sbrian#include "filter.h"
5136285Sbrian#include "descriptor.h"
5236285Sbrian#include "mp.h"
5343313Sbrian#ifndef NORADIUS
5443313Sbrian#include "radius.h"
5543313Sbrian#endif
5636285Sbrian#include "bundle.h"
5730715Sbrian#include "vjcomp.h"
586059Samurai
5928679Sbrian#define MAX_VJHEADER 16		/* Maximum size of compressed header */
606059Samurai
6146686Sbrianstatic struct mbuf *
6246686Sbrianvj_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp, int pri,
6346686Sbrian             u_short *proto)
646059Samurai{
656059Samurai  int type;
6645103Sbrian  struct ip *pip;
6736285Sbrian  u_short cproto = bundle->ncp.ipcp.peer_compproto >> 16;
686059Samurai
6946686Sbrian  log_Printf(LogDEBUG, "vj_LayerWrite: COMPPROTO = %x\n",
7036285Sbrian            bundle->ncp.ipcp.peer_compproto);
7145103Sbrian  bp = mbuf_Contiguous(bp);
7245103Sbrian  pip = (struct ip *)MBUF_CTOP(bp);
7346686Sbrian  if (*proto == PROTO_IP && pip->ip_p == IPPROTO_TCP &&
7446686Sbrian      cproto == PROTO_VJCOMP) {
7545103Sbrian    type = sl_compress_tcp(bp, pip, &bundle->ncp.ipcp.vj.cslc,
7636285Sbrian                           &bundle->ncp.ipcp.vj.slstat,
7736285Sbrian                           bundle->ncp.ipcp.peer_compproto & 0xff);
7846686Sbrian    log_Printf(LogDEBUG, "vj_LayerWrite: type = %x\n", type);
796059Samurai    switch (type) {
806059Samurai    case TYPE_IP:
816059Samurai      break;
8246686Sbrian
836059Samurai    case TYPE_UNCOMPRESSED_TCP:
8446686Sbrian      *proto = PROTO_VJUNCOMP;
856059Samurai      break;
8646686Sbrian
876059Samurai    case TYPE_COMPRESSED_TCP:
8846686Sbrian      *proto = PROTO_VJCOMP;
896059Samurai      break;
9046686Sbrian
916059Samurai    default:
9246686Sbrian      log_Printf(LogERROR, "Unknown frame type %x\n", type);
9336285Sbrian      mbuf_Free(bp);
9446686Sbrian      return NULL;
956059Samurai    }
9646686Sbrian  }
9736285Sbrian
9846686Sbrian  return bp;
996059Samurai}
1006059Samurai
1016059Samuraistatic struct mbuf *
10236285SbrianVjUncompressTcp(struct ipcp *ipcp, struct mbuf * bp, u_char type)
1036059Samurai{
1046059Samurai  u_char *bufp;
1056059Samurai  int len, olen, rlen;
1066059Samurai  struct mbuf *nbp;
10728679Sbrian  u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
1086059Samurai
10945103Sbrian  bp = mbuf_Contiguous(bp);
11036285Sbrian  olen = len = mbuf_Length(bp);
1116059Samurai  if (type == TYPE_UNCOMPRESSED_TCP) {
1126059Samurai    /*
11328679Sbrian     * Uncompressed packet does NOT change its size, so that we can use mbuf
11428679Sbrian     * space for uncompression job.
1156059Samurai     */
1166059Samurai    bufp = MBUF_CTOP(bp);
11736960Sbrian    len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
11836960Sbrian                            (ipcp->my_compproto >> 8) & 255);
1196735Samurai    if (len <= 0) {
12036285Sbrian      mbuf_Free(bp);
12132663Sbrian      bp = NULL;
1226735Samurai    }
12346686Sbrian    return bp;
1246059Samurai  }
12528679Sbrian
1266059Samurai  /*
12728679Sbrian   * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
12828679Sbrian   * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
12928679Sbrian   * Copy unread data info there.
1306059Samurai   */
13128679Sbrian  if (len > MAX_VJHEADER)
13228679Sbrian    len = MAX_VJHEADER;
1336059Samurai  rlen = len;
1346059Samurai  bufp = work + MAX_HDR;
13536285Sbrian  bp = mbuf_Read(bp, bufp, rlen);
13636960Sbrian  len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
13736960Sbrian                          (ipcp->my_compproto >> 8) & 255);
1386735Samurai  if (len <= 0) {
13936285Sbrian    mbuf_Free(bp);
14032663Sbrian    return NULL;
1416735Samurai  }
1426059Samurai  len -= olen;
1436059Samurai  len += rlen;
14436285Sbrian  nbp = mbuf_Alloc(len, MB_VJCOMP);
14530715Sbrian  memcpy(MBUF_CTOP(nbp), bufp, len);
1466059Samurai  nbp->next = bp;
14746686Sbrian  return nbp;
1486059Samurai}
1496059Samurai
15046686Sbrianstatic struct mbuf *
15146686Sbrianvj_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
15246686Sbrian             u_short *proto)
1536059Samurai{
1546059Samurai  u_char type;
1556059Samurai
15646686Sbrian  log_Printf(LogDEBUG, "vj_LayerPull: proto %02x\n", *proto);
15736285Sbrian  log_DumpBp(LogDEBUG, "Raw packet info:", bp);
1586059Samurai
15946686Sbrian  switch (*proto) {
1606059Samurai  case PROTO_VJCOMP:
1616059Samurai    type = TYPE_COMPRESSED_TCP;
1626059Samurai    break;
1636059Samurai  case PROTO_VJUNCOMP:
1646059Samurai    type = TYPE_UNCOMPRESSED_TCP;
1656059Samurai    break;
1666059Samurai  default:
16746686Sbrian    return bp;
1686059Samurai  }
16946686Sbrian
17046686Sbrian  *proto = PROTO_IP;
17146686Sbrian  return VjUncompressTcp(&bundle->ncp.ipcp, bp, type);
1726059Samurai}
17331514Sbrian
17431514Sbrianconst char *
17532439Sbrianvj2asc(u_int32_t val)
17631514Sbrian{
17737010Sbrian  static char asc[50];		/* The return value is used immediately */
17831514Sbrian
17936285Sbrian  if (val)
18046686Sbrian    snprintf(asc, sizeof asc, "%d VJ slots with%s slot compression",
18146686Sbrian            (int)((val>>8)&15)+1, val & 1 ?  "" : "out");
18236285Sbrian  else
18336285Sbrian    strcpy(asc, "VJ disabled");
18431514Sbrian  return asc;
18531514Sbrian}
18646686Sbrian
18746686Sbrianstruct layer vjlayer = { LAYER_VJ, "vj", vj_LayerPush, vj_LayerPull };
188