xref: /freebsd/usr.sbin/ppp/vjcomp.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
165309e5cSBrian Somers /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
465309e5cSBrian Somers  * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
565309e5cSBrian Somers  *          based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
665309e5cSBrian Somers  *                           Internet Initiative Japan, Inc (IIJ)
765309e5cSBrian Somers  * All rights reserved.
8af57ed9fSAtsushi Murai  *
965309e5cSBrian Somers  * Redistribution and use in source and binary forms, with or without
1065309e5cSBrian Somers  * modification, are permitted provided that the following conditions
1165309e5cSBrian Somers  * are met:
1265309e5cSBrian Somers  * 1. Redistributions of source code must retain the above copyright
1365309e5cSBrian Somers  *    notice, this list of conditions and the following disclaimer.
1465309e5cSBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
1565309e5cSBrian Somers  *    notice, this list of conditions and the following disclaimer in the
1665309e5cSBrian Somers  *    documentation and/or other materials provided with the distribution.
17af57ed9fSAtsushi Murai  *
1865309e5cSBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1965309e5cSBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2065309e5cSBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2165309e5cSBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2265309e5cSBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2365309e5cSBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2465309e5cSBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2565309e5cSBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2665309e5cSBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2765309e5cSBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2865309e5cSBrian Somers  * SUCH DAMAGE.
29af57ed9fSAtsushi Murai  */
3065309e5cSBrian Somers 
31972a1bcfSBrian Somers #include <sys/param.h>
3275240ed1SBrian Somers #include <netinet/in.h>
33af57ed9fSAtsushi Murai #include <netinet/in_systm.h>
34af57ed9fSAtsushi Murai #include <netinet/ip.h>
3530949fd4SBrian Somers #include <sys/socket.h>
361fa665f5SBrian Somers #include <sys/un.h>
3775240ed1SBrian Somers 
385106c671SBrian Somers #include <stdio.h>
39eb6e5e05SBrian Somers #include <string.h>		/* strlen/memcpy */
405d9e6103SBrian Somers #include <termios.h>
4175240ed1SBrian Somers 
425d9e6103SBrian Somers #include "layer.h"
4375240ed1SBrian Somers #include "mbuf.h"
4475240ed1SBrian Somers #include "log.h"
4575240ed1SBrian Somers #include "timer.h"
4675240ed1SBrian Somers #include "fsm.h"
475d9e6103SBrian Somers #include "proto.h"
48af57ed9fSAtsushi Murai #include "slcompress.h"
49879ed6faSBrian Somers #include "lqr.h"
50af57ed9fSAtsushi Murai #include "hdlc.h"
5129e275ceSBrian Somers #include "defs.h"
5229e275ceSBrian Somers #include "iplist.h"
5329e275ceSBrian Somers #include "throughput.h"
5430949fd4SBrian Somers #include "ncpaddr.h"
55af57ed9fSAtsushi Murai #include "ipcp.h"
56f4768038SBrian Somers #include "lcp.h"
57f4768038SBrian Somers #include "ccp.h"
58f4768038SBrian Somers #include "link.h"
595ca5389aSBrian Somers #include "filter.h"
602f786681SBrian Somers #include "descriptor.h"
613b0f8d2eSBrian Somers #include "mp.h"
62972a1bcfSBrian Somers #ifndef NORADIUS
63972a1bcfSBrian Somers #include "radius.h"
64972a1bcfSBrian Somers #endif
6530949fd4SBrian Somers #include "ipv6cp.h"
6630949fd4SBrian Somers #include "ncp.h"
67f4768038SBrian Somers #include "bundle.h"
6875240ed1SBrian Somers #include "vjcomp.h"
69af57ed9fSAtsushi Murai 
70af57ed9fSAtsushi Murai #define MAX_VJHEADER 16		/* Maximum size of compressed header */
71af57ed9fSAtsushi Murai 
725d9e6103SBrian Somers static struct mbuf *
vj_LayerPush(struct bundle * bundle,struct link * l __unused,struct mbuf * bp,int pri __unused,u_short * proto)73057f1760SBrian Somers vj_LayerPush(struct bundle *bundle, struct link *l __unused, struct mbuf *bp,
74057f1760SBrian Somers 	     int pri __unused, u_short *proto)
75af57ed9fSAtsushi Murai {
76af57ed9fSAtsushi Murai   int type;
77aad80d9fSBrian Somers   struct ip *pip;
785828db6dSBrian Somers   u_short cproto = bundle->ncp.ipcp.peer_compproto >> 16;
79af57ed9fSAtsushi Murai 
8026af0ae9SBrian Somers   bp = m_pullup(bp);
81aad80d9fSBrian Somers   pip = (struct ip *)MBUF_CTOP(bp);
825d9e6103SBrian Somers   if (*proto == PROTO_IP && pip->ip_p == IPPROTO_TCP &&
835d9e6103SBrian Somers       cproto == PROTO_VJCOMP) {
84aad80d9fSBrian Somers     type = sl_compress_tcp(bp, pip, &bundle->ncp.ipcp.vj.cslc,
85eaa4df37SBrian Somers                            &bundle->ncp.ipcp.vj.slstat,
865828db6dSBrian Somers                            bundle->ncp.ipcp.peer_compproto & 0xff);
875d9e6103SBrian Somers     log_Printf(LogDEBUG, "vj_LayerWrite: type = %x\n", type);
88af57ed9fSAtsushi Murai     switch (type) {
89af57ed9fSAtsushi Murai     case TYPE_IP:
90af57ed9fSAtsushi Murai       break;
91f4768038SBrian Somers 
925d9e6103SBrian Somers     case TYPE_UNCOMPRESSED_TCP:
935d9e6103SBrian Somers       *proto = PROTO_VJUNCOMP;
946815097bSBrian Somers       log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n");
9526af0ae9SBrian Somers       m_settype(bp, MB_VJOUT);
965d9e6103SBrian Somers       break;
975d9e6103SBrian Somers 
985d9e6103SBrian Somers     case TYPE_COMPRESSED_TCP:
995d9e6103SBrian Somers       *proto = PROTO_VJCOMP;
1006815097bSBrian Somers       log_Printf(LogDEBUG, "vj_LayerPush: PROTO_IP -> PROTO_VJUNCOMP\n");
10126af0ae9SBrian Somers       m_settype(bp, MB_VJOUT);
1025d9e6103SBrian Somers       break;
1035d9e6103SBrian Somers 
1045d9e6103SBrian Somers     default:
1056815097bSBrian Somers       log_Printf(LogERROR, "vj_LayerPush: Unknown frame type %x\n", type);
10626af0ae9SBrian Somers       m_freem(bp);
1075d9e6103SBrian Somers       return NULL;
1085d9e6103SBrian Somers     }
1095d9e6103SBrian Somers   }
1105d9e6103SBrian Somers 
1115d9e6103SBrian Somers   return bp;
112af57ed9fSAtsushi Murai }
113af57ed9fSAtsushi Murai 
114af57ed9fSAtsushi Murai static struct mbuf *
VjUncompressTcp(struct ipcp * ipcp,struct mbuf * bp,u_char type)115eaa4df37SBrian Somers VjUncompressTcp(struct ipcp *ipcp, struct mbuf *bp, u_char type)
116af57ed9fSAtsushi Murai {
117af57ed9fSAtsushi Murai   u_char *bufp;
118af57ed9fSAtsushi Murai   int len, olen, rlen;
119af57ed9fSAtsushi Murai   u_char work[MAX_HDR + MAX_VJHEADER];	/* enough to hold TCP/IP header */
120af57ed9fSAtsushi Murai 
12126af0ae9SBrian Somers   bp = m_pullup(bp);
12226af0ae9SBrian Somers   olen = len = m_length(bp);
123af57ed9fSAtsushi Murai   if (type == TYPE_UNCOMPRESSED_TCP) {
124af57ed9fSAtsushi Murai     /*
125944f7098SBrian Somers      * Uncompressed packet does NOT change its size, so that we can use mbuf
126944f7098SBrian Somers      * space for uncompression job.
127af57ed9fSAtsushi Murai      */
128af57ed9fSAtsushi Murai     bufp = MBUF_CTOP(bp);
12942c57c86SBrian Somers     len = sl_uncompress_tcp(&bufp, len, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
13042c57c86SBrian Somers                             (ipcp->my_compproto >> 8) & 255);
13153c9f6c0SAtsushi Murai     if (len <= 0) {
13226af0ae9SBrian Somers       m_freem(bp);
133aa8e0519SBrian Somers       bp = NULL;
134411675baSBrian Somers     } else
13526af0ae9SBrian Somers       m_settype(bp, MB_VJIN);
1365d9e6103SBrian Somers     return bp;
137af57ed9fSAtsushi Murai   }
138944f7098SBrian Somers 
139af57ed9fSAtsushi Murai   /*
140944f7098SBrian Somers    * Handle compressed packet. 1) Read up to MAX_VJHEADER bytes into work
141c007b102SBrian Somers    * space. 2) Try to uncompress it. 3) Compute amount of necessary space. 4)
142944f7098SBrian Somers    * Copy unread data info there.
143af57ed9fSAtsushi Murai    */
144944f7098SBrian Somers   if (len > MAX_VJHEADER)
145944f7098SBrian Somers     len = MAX_VJHEADER;
146af57ed9fSAtsushi Murai   rlen = len;
147af57ed9fSAtsushi Murai   bufp = work + MAX_HDR;
148dd7e2610SBrian Somers   bp = mbuf_Read(bp, bufp, rlen);
14942c57c86SBrian Somers   len = sl_uncompress_tcp(&bufp, olen, type, &ipcp->vj.cslc, &ipcp->vj.slstat,
15042c57c86SBrian Somers                           (ipcp->my_compproto >> 8) & 255);
15153c9f6c0SAtsushi Murai   if (len <= 0) {
15226af0ae9SBrian Somers     m_freem(bp);
153aa8e0519SBrian Somers     return NULL;
15453c9f6c0SAtsushi Murai   }
155af57ed9fSAtsushi Murai   len -= olen;
156af57ed9fSAtsushi Murai   len += rlen;
157dae8dd31SBrian Somers 
158dae8dd31SBrian Somers   bp = m_prepend(bp, bufp, len, 0);
15926af0ae9SBrian Somers   m_settype(bp, MB_VJIN);
160dae8dd31SBrian Somers 
161dae8dd31SBrian Somers   return bp;
162af57ed9fSAtsushi Murai }
163af57ed9fSAtsushi Murai 
1645d9e6103SBrian Somers static struct mbuf *
vj_LayerPull(struct bundle * bundle,struct link * l __unused,struct mbuf * bp,u_short * proto)165057f1760SBrian Somers vj_LayerPull(struct bundle *bundle, struct link *l __unused, struct mbuf *bp,
1665d9e6103SBrian Somers              u_short *proto)
167af57ed9fSAtsushi Murai {
168af57ed9fSAtsushi Murai   u_char type;
169af57ed9fSAtsushi Murai 
1705d9e6103SBrian Somers   switch (*proto) {
171af57ed9fSAtsushi Murai   case PROTO_VJCOMP:
172af57ed9fSAtsushi Murai     type = TYPE_COMPRESSED_TCP;
1736815097bSBrian Somers     log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJCOMP -> PROTO_IP\n");
174af57ed9fSAtsushi Murai     break;
175af57ed9fSAtsushi Murai   case PROTO_VJUNCOMP:
176af57ed9fSAtsushi Murai     type = TYPE_UNCOMPRESSED_TCP;
1776815097bSBrian Somers     log_Printf(LogDEBUG, "vj_LayerPull: PROTO_VJUNCOMP -> PROTO_IP\n");
178af57ed9fSAtsushi Murai     break;
179af57ed9fSAtsushi Murai   default:
1805d9e6103SBrian Somers     return bp;
181af57ed9fSAtsushi Murai   }
1825d9e6103SBrian Somers 
1835d9e6103SBrian Somers   *proto = PROTO_IP;
1845d9e6103SBrian Somers   return VjUncompressTcp(&bundle->ncp.ipcp, bp, type);
185af57ed9fSAtsushi Murai }
1860053cc58SBrian Somers 
1870053cc58SBrian Somers const char *
vj2asc(u_int32_t val)1883a70c9f7SBrian Somers vj2asc(u_int32_t val)
1890053cc58SBrian Somers {
190d93d3a9cSBrian Somers   static char asc[50];		/* The return value is used immediately */
1910053cc58SBrian Somers 
1921342caedSBrian Somers   if (val)
1935d9e6103SBrian Somers     snprintf(asc, sizeof asc, "%d VJ slots with%s slot compression",
1945d9e6103SBrian Somers             (int)((val>>8)&15)+1, val & 1 ?  "" : "out");
1951342caedSBrian Somers   else
1961342caedSBrian Somers     strcpy(asc, "VJ disabled");
1970053cc58SBrian Somers   return asc;
1980053cc58SBrian Somers }
1995d9e6103SBrian Somers 
2005d9e6103SBrian Somers struct layer vjlayer = { LAYER_VJ, "vj", vj_LayerPush, vj_LayerPull };
201