vjcomp.c revision 50479
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 *
2050479Speter * $FreeBSD: head/usr.sbin/ppp/vjcomp.c 50479 1999-08-28 01:35:59Z peter $
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>
3149472Sbrian#include <string.h>		/* strlen/memcpy */
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
6945103Sbrian  bp = mbuf_Contiguous(bp);
7045103Sbrian  pip = (struct ip *)MBUF_CTOP(bp);
7146686Sbrian  if (*proto == PROTO_IP && pip->ip_p == IPPROTO_TCP &&
7246686Sbrian      cproto == PROTO_VJCOMP) {
7345103Sbrian    type = sl_compress_tcp(bp, pip, &bundle->ncp.ipcp.vj.cslc,
7436285Sbrian                           &bundle->ncp.ipcp.vj.slstat,
7536285Sbrian                           bundle->ncp.ipcp.peer_compproto & 0xff);
7646686Sbrian    log_Printf(LogDEBUG, "vj_LayerWrite: type = %x\n", type);
776059Samurai    switch (type) {
786059Samurai    case TYPE_IP:
796059Samurai      break;
8046686Sbrian
816059Samurai    case TYPE_UNCOMPRESSED_TCP:
8246686Sbrian      *proto = PROTO_VJUNCOMP;
8347061Sbrian      log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n");
8447695Sbrian      mbuf_SetType(bp, MB_VJOUT);
856059Samurai      break;
8646686Sbrian
876059Samurai    case TYPE_COMPRESSED_TCP:
8846686Sbrian      *proto = PROTO_VJCOMP;
8947061Sbrian      log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n");
9047695Sbrian      mbuf_SetType(bp, MB_VJOUT);
916059Samurai      break;
9246686Sbrian
936059Samurai    default:
9447061Sbrian      log_Printf(LogERROR, "vj_LayerPush: Unknown frame type %x\n", type);
9536285Sbrian      mbuf_Free(bp);
9646686Sbrian      return NULL;
976059Samurai    }
9846686Sbrian  }
9936285Sbrian
10046686Sbrian  return bp;
1016059Samurai}
1026059Samurai
1036059Samuraistatic struct mbuf *
10446828SbrianVjUncompressTcp(struct ipcp *ipcp, struct mbuf *bp, u_char type)
1056059Samurai{
1066059Samurai  u_char *bufp;
1076059Samurai  int len, olen, rlen;
1086059Samurai  struct mbuf *nbp;
10928679Sbrian  u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
1106059Samurai
11145103Sbrian  bp = mbuf_Contiguous(bp);
11236285Sbrian  olen = len = mbuf_Length(bp);
1136059Samurai  if (type == TYPE_UNCOMPRESSED_TCP) {
1146059Samurai    /*
11528679Sbrian     * Uncompressed packet does NOT change its size, so that we can use mbuf
11628679Sbrian     * space for uncompression job.
1176059Samurai     */
1186059Samurai    bufp = MBUF_CTOP(bp);
11936960Sbrian    len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
12036960Sbrian                            (ipcp->my_compproto >> 8) & 255);
1216735Samurai    if (len <= 0) {
12236285Sbrian      mbuf_Free(bp);
12332663Sbrian      bp = NULL;
12447695Sbrian    } else
12547695Sbrian      mbuf_SetType(bp, MB_VJIN);
12646686Sbrian    return bp;
1276059Samurai  }
12828679Sbrian
1296059Samurai  /*
13028679Sbrian   * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
13128679Sbrian   * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
13228679Sbrian   * Copy unread data info there.
1336059Samurai   */
13428679Sbrian  if (len > MAX_VJHEADER)
13528679Sbrian    len = MAX_VJHEADER;
1366059Samurai  rlen = len;
1376059Samurai  bufp = work + MAX_HDR;
13836285Sbrian  bp = mbuf_Read(bp, bufp, rlen);
13936960Sbrian  len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
14036960Sbrian                          (ipcp->my_compproto >> 8) & 255);
1416735Samurai  if (len <= 0) {
14236285Sbrian    mbuf_Free(bp);
14332663Sbrian    return NULL;
1446735Samurai  }
1456059Samurai  len -= olen;
1466059Samurai  len += rlen;
14747695Sbrian  nbp = mbuf_Alloc(len, MB_VJIN);
14830715Sbrian  memcpy(MBUF_CTOP(nbp), bufp, len);
14947695Sbrian  mbuf_SetType(bp, MB_VJIN);
1506059Samurai  nbp->next = bp;
15146686Sbrian  return nbp;
1526059Samurai}
1536059Samurai
15446686Sbrianstatic struct mbuf *
15546686Sbrianvj_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
15646686Sbrian             u_short *proto)
1576059Samurai{
1586059Samurai  u_char type;
1596059Samurai
16046686Sbrian  switch (*proto) {
1616059Samurai  case PROTO_VJCOMP:
1626059Samurai    type = TYPE_COMPRESSED_TCP;
16347061Sbrian    log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJCOMP -> PROTO_IP\n");
1646059Samurai    break;
1656059Samurai  case PROTO_VJUNCOMP:
1666059Samurai    type = TYPE_UNCOMPRESSED_TCP;
16747061Sbrian    log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJUNCOMP -> PROTO_IP\n");
1686059Samurai    break;
1696059Samurai  default:
17046686Sbrian    return bp;
1716059Samurai  }
17246686Sbrian
17346686Sbrian  *proto = PROTO_IP;
17446686Sbrian  return VjUncompressTcp(&bundle->ncp.ipcp, bp, type);
1756059Samurai}
17631514Sbrian
17731514Sbrianconst char *
17832439Sbrianvj2asc(u_int32_t val)
17931514Sbrian{
18037010Sbrian  static char asc[50];		/* The return value is used immediately */
18131514Sbrian
18236285Sbrian  if (val)
18346686Sbrian    snprintf(asc, sizeof asc, "%d VJ slots with%s slot compression",
18446686Sbrian            (int)((val>>8)&15)+1, val & 1 ?  "" : "out");
18536285Sbrian  else
18636285Sbrian    strcpy(asc, "VJ disabled");
18731514Sbrian  return asc;
18831514Sbrian}
18946686Sbrian
19046686Sbrianstruct layer vjlayer = { LAYER_VJ, "vj", vj_LayerPush, vj_LayerPull };
191