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