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 * 2097d92980SPeter Wemm * $FreeBSD$ 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> 31eb6e5e05SBrian Somers #include <string.h> /* strlen/memcpy */ 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 6926af0ae9SBrian Somers bp = m_pullup(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"); 8426af0ae9SBrian Somers m_settype(bp, MB_VJOUT); 855d9e6103SBrian Somers break; 865d9e6103SBrian Somers 875d9e6103SBrian Somers case TYPE_COMPRESSED_TCP: 885d9e6103SBrian Somers *proto = PROTO_VJCOMP; 896815097bSBrian Somers log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n"); 9026af0ae9SBrian Somers m_settype(bp, MB_VJOUT); 915d9e6103SBrian Somers break; 925d9e6103SBrian Somers 935d9e6103SBrian Somers default: 946815097bSBrian Somers log_Printf(LogERROR, "vj_LayerPush: Unknown frame type %x\n", type); 9526af0ae9SBrian Somers m_freem(bp); 965d9e6103SBrian Somers return NULL; 975d9e6103SBrian Somers } 985d9e6103SBrian Somers } 995d9e6103SBrian Somers 1005d9e6103SBrian Somers return bp; 101af57ed9fSAtsushi Murai } 102af57ed9fSAtsushi Murai 103af57ed9fSAtsushi Murai static struct mbuf * 104eaa4df37SBrian Somers VjUncompressTcp(struct ipcp *ipcp, struct mbuf *bp, u_char type) 105af57ed9fSAtsushi Murai { 106af57ed9fSAtsushi Murai u_char *bufp; 107af57ed9fSAtsushi Murai int len, olen, rlen; 108af57ed9fSAtsushi Murai struct mbuf *nbp; 109af57ed9fSAtsushi Murai u_char work[MAX_HDR + MAX_VJHEADER]; /* enough to hold TCP/IP header */ 110af57ed9fSAtsushi Murai 11126af0ae9SBrian Somers bp = m_pullup(bp); 11226af0ae9SBrian Somers olen = len = m_length(bp); 113af57ed9fSAtsushi Murai if (type == TYPE_UNCOMPRESSED_TCP) { 114af57ed9fSAtsushi Murai /* 115944f7098SBrian Somers * Uncompressed packet does NOT change its size, so that we can use mbuf 116944f7098SBrian Somers * space for uncompression job. 117af57ed9fSAtsushi Murai */ 118af57ed9fSAtsushi Murai bufp = MBUF_CTOP(bp); 11942c57c86SBrian Somers len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat, 12042c57c86SBrian Somers (ipcp->my_compproto >> 8) & 255); 12153c9f6c0SAtsushi Murai if (len <= 0) { 12226af0ae9SBrian Somers m_freem(bp); 123aa8e0519SBrian Somers bp = NULL; 124411675baSBrian Somers } else 12526af0ae9SBrian Somers m_settype(bp, MB_VJIN); 1265d9e6103SBrian Somers return bp; 127af57ed9fSAtsushi Murai } 128944f7098SBrian Somers 129af57ed9fSAtsushi Murai /* 130944f7098SBrian Somers * Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work 131944f7098SBrian Somers * space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4) 132944f7098SBrian Somers * Copy unread data info there. 133af57ed9fSAtsushi Murai */ 134944f7098SBrian Somers if (len > MAX_VJHEADER) 135944f7098SBrian Somers len = MAX_VJHEADER; 136af57ed9fSAtsushi Murai rlen = len; 137af57ed9fSAtsushi Murai bufp = work + MAX_HDR; 138dd7e2610SBrian Somers bp = mbuf_Read(bp, bufp, rlen); 13942c57c86SBrian Somers len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat, 14042c57c86SBrian Somers (ipcp->my_compproto >> 8) & 255); 14153c9f6c0SAtsushi Murai if (len <= 0) { 14226af0ae9SBrian Somers m_freem(bp); 143aa8e0519SBrian Somers return NULL; 14453c9f6c0SAtsushi Murai } 145af57ed9fSAtsushi Murai len -= olen; 146af57ed9fSAtsushi Murai len += rlen; 14726af0ae9SBrian Somers nbp = m_get(len, MB_VJIN); 14875240ed1SBrian Somers memcpy(MBUF_CTOP(nbp), bufp, len); 14926af0ae9SBrian Somers m_settype(bp, MB_VJIN); 15026af0ae9SBrian Somers nbp->m_next = bp; 1515d9e6103SBrian Somers return nbp; 152af57ed9fSAtsushi Murai } 153af57ed9fSAtsushi Murai 1545d9e6103SBrian Somers static struct mbuf * 1555d9e6103SBrian Somers vj_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp, 1565d9e6103SBrian Somers u_short *proto) 157af57ed9fSAtsushi Murai { 158af57ed9fSAtsushi Murai u_char type; 159af57ed9fSAtsushi Murai 1605d9e6103SBrian Somers switch (*proto) { 161af57ed9fSAtsushi Murai case PROTO_VJCOMP: 162af57ed9fSAtsushi Murai type = TYPE_COMPRESSED_TCP; 1636815097bSBrian Somers log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJCOMP -> PROTO_IP\n"); 164af57ed9fSAtsushi Murai break; 165af57ed9fSAtsushi Murai case PROTO_VJUNCOMP: 166af57ed9fSAtsushi Murai type = TYPE_UNCOMPRESSED_TCP; 1676815097bSBrian Somers log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJUNCOMP -> PROTO_IP\n"); 168af57ed9fSAtsushi Murai break; 169af57ed9fSAtsushi Murai default: 1705d9e6103SBrian Somers return bp; 171af57ed9fSAtsushi Murai } 1725d9e6103SBrian Somers 1735d9e6103SBrian Somers *proto = PROTO_IP; 1745d9e6103SBrian Somers return VjUncompressTcp(&bundle->ncp.ipcp, bp, type); 175af57ed9fSAtsushi Murai } 1760053cc58SBrian Somers 1770053cc58SBrian Somers const char * 1783a70c9f7SBrian Somers vj2asc(u_int32_t val) 1790053cc58SBrian Somers { 180d93d3a9cSBrian Somers static char asc[50]; /* The return value is used immediately */ 1810053cc58SBrian Somers 1821342caedSBrian Somers if (val) 1835d9e6103SBrian Somers snprintf(asc, sizeof asc, "%d VJ slots with%s slot compression", 1845d9e6103SBrian Somers (int)((val>>8)&15)+1, val & 1 ? "" : "out"); 1851342caedSBrian Somers else 1861342caedSBrian Somers strcpy(asc, "VJ disabled"); 1870053cc58SBrian Somers return asc; 1880053cc58SBrian Somers } 1895d9e6103SBrian Somers 1905d9e6103SBrian Somers struct layer vjlayer = { LAYER_VJ, "vj", vj_LayerPush, vj_LayerPull }; 191