1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * Input/Output VJ Compressed packets 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 206815097bSBrian Somers * $Id: vjcomp.c,v 1.29 1999/05/09 20:02:29 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai */ 24972a1bcfSBrian Somers #include <sys/param.h> 2575240ed1SBrian Somers #include <netinet/in.h> 26af57ed9fSAtsushi Murai #include <netinet/in_systm.h> 27af57ed9fSAtsushi Murai #include <netinet/ip.h> 281fa665f5SBrian Somers #include <sys/un.h> 2975240ed1SBrian Somers 305106c671SBrian Somers #include <stdio.h> 31eb2d27cfSBrian Somers #include <string.h> 325d9e6103SBrian Somers #include <termios.h> 3375240ed1SBrian Somers 345d9e6103SBrian Somers #include "layer.h" 3575240ed1SBrian Somers #include "mbuf.h" 3675240ed1SBrian Somers #include "log.h" 3775240ed1SBrian Somers #include "timer.h" 3875240ed1SBrian Somers #include "fsm.h" 395d9e6103SBrian Somers #include "proto.h" 40af57ed9fSAtsushi Murai #include "slcompress.h" 41879ed6faSBrian Somers #include "lqr.h" 42af57ed9fSAtsushi Murai #include "hdlc.h" 4329e275ceSBrian Somers #include "defs.h" 4429e275ceSBrian Somers #include "iplist.h" 4529e275ceSBrian Somers #include "throughput.h" 46af57ed9fSAtsushi Murai #include "ipcp.h" 47f4768038SBrian Somers #include "lcp.h" 48f4768038SBrian Somers #include "ccp.h" 49f4768038SBrian Somers #include "link.h" 505ca5389aSBrian Somers #include "filter.h" 512f786681SBrian Somers #include "descriptor.h" 523b0f8d2eSBrian Somers #include "mp.h" 53972a1bcfSBrian Somers #ifndef NORADIUS 54972a1bcfSBrian Somers #include "radius.h" 55972a1bcfSBrian Somers #endif 56f4768038SBrian Somers #include "bundle.h" 5775240ed1SBrian Somers #include "vjcomp.h" 58af57ed9fSAtsushi Murai 59af57ed9fSAtsushi Murai #define MAX_VJHEADER 16 /* Maximum size of compressed header */ 60af57ed9fSAtsushi Murai 615d9e6103SBrian Somers static struct mbuf * 625d9e6103SBrian Somers vj_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp, int pri, 635d9e6103SBrian Somers u_short *proto) 64af57ed9fSAtsushi Murai { 65af57ed9fSAtsushi Murai int type; 66aad80d9fSBrian Somers struct ip *pip; 675828db6dSBrian Somers u_short cproto = bundle->ncp.ipcp.peer_compproto >> 16; 68af57ed9fSAtsushi Murai 69aad80d9fSBrian Somers bp = mbuf_Contiguous(bp); 70aad80d9fSBrian Somers pip = (struct ip *)MBUF_CTOP(bp); 715d9e6103SBrian Somers if (*proto == PROTO_IP && pip->ip_p == IPPROTO_TCP && 725d9e6103SBrian Somers cproto == PROTO_VJCOMP) { 73aad80d9fSBrian Somers type = sl_compress_tcp(bp, pip, &bundle->ncp.ipcp.vj.cslc, 74eaa4df37SBrian Somers &bundle->ncp.ipcp.vj.slstat, 755828db6dSBrian Somers bundle->ncp.ipcp.peer_compproto & 0xff); 765d9e6103SBrian Somers log_Printf(LogDEBUG, "vj_LayerWrite: type = %x\n", type); 77af57ed9fSAtsushi Murai switch (type) { 78af57ed9fSAtsushi Murai case TYPE_IP: 79af57ed9fSAtsushi Murai break; 80f4768038SBrian Somers 815d9e6103SBrian Somers case TYPE_UNCOMPRESSED_TCP: 825d9e6103SBrian Somers *proto = PROTO_VJUNCOMP; 836815097bSBrian Somers log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n"); 845d9e6103SBrian Somers break; 855d9e6103SBrian Somers 865d9e6103SBrian Somers case TYPE_COMPRESSED_TCP: 875d9e6103SBrian Somers *proto = PROTO_VJCOMP; 886815097bSBrian Somers log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n"); 895d9e6103SBrian Somers break; 905d9e6103SBrian Somers 915d9e6103SBrian Somers default: 926815097bSBrian Somers log_Printf(LogERROR, "vj_LayerPush: Unknown frame type %x\n", type); 935d9e6103SBrian Somers mbuf_Free(bp); 945d9e6103SBrian Somers return NULL; 955d9e6103SBrian Somers } 965d9e6103SBrian Somers } 975d9e6103SBrian Somers 985d9e6103SBrian Somers return bp; 99af57ed9fSAtsushi Murai } 100af57ed9fSAtsushi Murai 101af57ed9fSAtsushi Murai static struct mbuf * 102eaa4df37SBrian Somers VjUncompressTcp(struct ipcp *ipcp, struct mbuf *bp, u_char type) 103af57ed9fSAtsushi Murai { 104af57ed9fSAtsushi Murai u_char *bufp; 105af57ed9fSAtsushi Murai int len, olen, rlen; 106af57ed9fSAtsushi Murai struct mbuf *nbp; 107af57ed9fSAtsushi Murai u_char work[MAX_HDR + MAX_VJHEADER]; /* enough to hold TCP/IP header */ 108af57ed9fSAtsushi Murai 109aad80d9fSBrian Somers bp = mbuf_Contiguous(bp); 110dd7e2610SBrian Somers olen = len = mbuf_Length(bp); 111af57ed9fSAtsushi Murai if (type == TYPE_UNCOMPRESSED_TCP) { 112af57ed9fSAtsushi Murai /* 113944f7098SBrian Somers * Uncompressed packet does NOT change its size, so that we can use mbuf 114944f7098SBrian Somers * space for uncompression job. 115af57ed9fSAtsushi Murai */ 116af57ed9fSAtsushi Murai bufp = MBUF_CTOP(bp); 11742c57c86SBrian Somers len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat, 11842c57c86SBrian Somers (ipcp->my_compproto >> 8) & 255); 11953c9f6c0SAtsushi Murai if (len <= 0) { 120dd7e2610SBrian Somers mbuf_Free(bp); 121aa8e0519SBrian Somers bp = NULL; 12253c9f6c0SAtsushi Murai } 1235d9e6103SBrian Somers return bp; 124af57ed9fSAtsushi Murai } 125944f7098SBrian Somers 126af57ed9fSAtsushi Murai /* 127944f7098SBrian Somers * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work 128944f7098SBrian Somers * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4) 129944f7098SBrian Somers * Copy unread data info there. 130af57ed9fSAtsushi Murai */ 131944f7098SBrian Somers if (len > MAX_VJHEADER) 132944f7098SBrian Somers len = MAX_VJHEADER; 133af57ed9fSAtsushi Murai rlen = len; 134af57ed9fSAtsushi Murai bufp = work + MAX_HDR; 135dd7e2610SBrian Somers bp = mbuf_Read(bp, bufp, rlen); 13642c57c86SBrian Somers len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat, 13742c57c86SBrian Somers (ipcp->my_compproto >> 8) & 255); 13853c9f6c0SAtsushi Murai if (len <= 0) { 139dd7e2610SBrian Somers mbuf_Free(bp); 140aa8e0519SBrian Somers return NULL; 14153c9f6c0SAtsushi Murai } 142af57ed9fSAtsushi Murai len -= olen; 143af57ed9fSAtsushi Murai len += rlen; 144dd7e2610SBrian Somers nbp = mbuf_Alloc(len, MB_VJCOMP); 14575240ed1SBrian Somers memcpy(MBUF_CTOP(nbp), bufp, len); 146af57ed9fSAtsushi Murai nbp->next = bp; 1475d9e6103SBrian Somers return nbp; 148af57ed9fSAtsushi Murai } 149af57ed9fSAtsushi Murai 1505d9e6103SBrian Somers static struct mbuf * 1515d9e6103SBrian Somers vj_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp, 1525d9e6103SBrian Somers u_short *proto) 153af57ed9fSAtsushi Murai { 154af57ed9fSAtsushi Murai u_char type; 155af57ed9fSAtsushi Murai 1565d9e6103SBrian Somers switch (*proto) { 157af57ed9fSAtsushi Murai case PROTO_VJCOMP: 158af57ed9fSAtsushi Murai type = TYPE_COMPRESSED_TCP; 1596815097bSBrian Somers log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJCOMP -> PROTO_IP\n"); 160af57ed9fSAtsushi Murai break; 161af57ed9fSAtsushi Murai case PROTO_VJUNCOMP: 162af57ed9fSAtsushi Murai type = TYPE_UNCOMPRESSED_TCP; 1636815097bSBrian Somers log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJUNCOMP -> PROTO_IP\n"); 164af57ed9fSAtsushi Murai break; 165af57ed9fSAtsushi Murai default: 1665d9e6103SBrian Somers return bp; 167af57ed9fSAtsushi Murai } 1685d9e6103SBrian Somers 1695d9e6103SBrian Somers *proto = PROTO_IP; 1705d9e6103SBrian Somers return VjUncompressTcp(&bundle->ncp.ipcp, bp, type); 171af57ed9fSAtsushi Murai } 1720053cc58SBrian Somers 1730053cc58SBrian Somers const char * 1743a70c9f7SBrian Somers vj2asc(u_int32_t val) 1750053cc58SBrian Somers { 176d93d3a9cSBrian Somers static char asc[50]; /* The return value is used immediately */ 1770053cc58SBrian Somers 1781342caedSBrian Somers if (val) 1795d9e6103SBrian Somers snprintf(asc, sizeof asc, "%d VJ slots with%s slot compression", 1805d9e6103SBrian Somers (int)((val>>8)&15)+1, val & 1 ? "" : "out"); 1811342caedSBrian Somers else 1821342caedSBrian Somers strcpy(asc, "VJ disabled"); 1830053cc58SBrian Somers return asc; 1840053cc58SBrian Somers } 1855d9e6103SBrian Somers 1865d9e6103SBrian Somers struct layer vjlayer = { LAYER_VJ, "vj", vj_LayerPush, vj_LayerPull }; 187