NetBSD Problem Report #8536
Received: (qmail 27007 invoked from network); 2 Oct 1999 18:37:09 -0000
Message-Id: <199910021454.QAA02693@yacht.domestic.de>
Date: Sat, 2 Oct 1999 16:54:06 +0200 (CEST)
From: kuebart@mathematik.uni-ulm.de (Joachim Kuebart)
To: gnats-bugs@gnats.netbsd.org
Subject: SPPP does not support Van Jacobson header compression
X-Send-Pr-Version: 3.95
>Number: 8536
>Category: kern
>Synopsis: SPPP does not support Van Jacobson header compression
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: martin
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Oct 02 11:50:01 +0000 1999
>Closed-Date:
>Last-Modified: Tue Apr 01 18:55:25 +0000 2003
>Originator: Joachim Kuebart
>Release: NetBSD-current, Oct 2, 1999
>Organization:
>Environment:
i386, NetBSD-current, i4b package 0.81 beta
System: NetBSD yacht 1.4K NetBSD 1.4K (YACHT) #40: Sat Oct 2 16:15:23 CEST 1999 joki@yacht:/usr/src/sys/arch/i386/compile/YACHT i386
>Description:
During IPCP negotiation, NetBSD's sppp-driver rejects VJ
header compression and does not suggest to use it from its
side.
>How-To-Repeat:
Use i4b or some other driver that relies on
/sys/net/if_spppsubr.c to connect to a modern router. If the
device is in debug mode, attempts to configure VJ compression
and their rejection are logged.
>Fix:
The following patch is based on my submission to FreeBSD's
problem database a while ago. Unfortunately, it was never
commited there.
The code was tested with i4b-0.81 beta and worked well
for almost a year under FreeBSD. I did the port to NetBSD
today, but it looks OK.
PS: Due to the use of "#ifdef SPPP_VJ", SPPP_VJ might become
a kernel option if that seems appropriate.
Index: if_sppp.h
===================================================================
RCS file: /home/cvs/netbsd/src/sys/net/if_sppp.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 if_sppp.h
--- if_sppp.h 1999/06/14 20:07:37 1.1.1.1
+++ if_sppp.h 1999/10/02 14:40:02
@@ -23,8 +23,8 @@
* From: Id: if_sppp.h,v 1.7 1998/12/01 20:20:19 hm Exp
*/
-#ifndef _NET_IF_HDLC_H_
-#define _NET_IF_HDLC_H_ 1
+#ifndef _NET_IF_SPPP_H_
+#define _NET_IF_SPPP_H_ 1
#define IDX_LCP 0 /* idx into state table */
@@ -50,6 +50,9 @@
#define IPCP_HISADDR_SEEN 1 /* have seen his address already */
#define IPCP_MYADDR_DYN 2 /* my address is dynamically assigned */
#define IPCP_MYADDR_SEEN 4 /* have seen his address already */
+#define IPCP_VJ 8 /* We can use VJ compression */
+ int max_state; /* Max-Slot-Id */
+ int compress_cid; /* Comp-Slot-Id */
};
#define AUTHNAMELEN 32
@@ -105,6 +108,7 @@
struct sipcp ipcp; /* IPCP params */
struct sauth myauth; /* auth params, i'm peer */
struct sauth hisauth; /* auth params, i'm authenticator */
+ struct slcompress *pp_comp; /* for VJ compression */
/*
* These functions are filled in by sppp_attach(), and are
* expected to be used by the lower layer (hardware) drivers
@@ -134,8 +138,8 @@
void (*pp_chg)(struct sppp *sp, int new_state);
};
-#define PP_KEEPALIVE 0x01 /* use keepalive protocol */
-#define PP_CISCO 0x02 /* use Cisco protocol instead of PPP */
+#define PP_KEEPALIVE 0x01 /* use keepalive protocol */
+#define PP_CISCO 0x02 /* use Cisco protocol instead of PPP */
/* 0x04 was PP_TIMO */
#define PP_CALLIN 0x08 /* we are being called */
#define PP_NEEDAUTH 0x10 /* remote requested authentication */
@@ -186,4 +190,4 @@
void sppp_flush (struct ifnet *ifp);
#endif
-#endif /* _NET_IF_HDLC_H_ */
+#endif /* _NET_IF_SPPP_H_ */
Index: if_spppsubr.c
===================================================================
RCS file: /home/cvs/netbsd/src/sys/net/if_spppsubr.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 if_spppsubr.c
--- if_spppsubr.c 1999/10/01 18:44:06 1.1.1.2
+++ if_spppsubr.c 1999/10/02 14:03:44
@@ -33,6 +33,8 @@
#include <sys/param.h>
+#define SPPP_VJ
+
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/sockio.h>
@@ -54,6 +56,10 @@
#include <net/netisr.h>
#include <net/if_types.h>
#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <net/slcompress.h>
#include <machine/stdarg.h>
@@ -130,6 +136,8 @@
#define PPP_ISO 0x0023 /* ISO OSI Protocol */
#define PPP_XNS 0x0025 /* Xerox NS Protocol */
#define PPP_IPX 0x002b /* Novell IPX Protocol */
+#define PPP_VJ_COMP 0x002d /* VJ compressed TCP/IP */
+#define PPP_VJ_UCOMP 0x002f /* VJ uncompressed TCP/IP */
#define PPP_IPV6 0x0057 /* Internet Protocol version 6 */
#define PPP_LCP 0xc021 /* Link Control Protocol */
#define PPP_PAP 0xc023 /* Password Authentication Protocol */
@@ -161,6 +169,8 @@
#define IPCP_OPT_COMPRESSION 2 /* IP compression protocol (VJ) */
#define IPCP_OPT_ADDRESS 3 /* local IP address */
+#define IPCP_COMP_VJ 0x2d /* Code for VJ compression */
+
#define PAP_REQ 1 /* PAP name/password request */
#define PAP_ACK 2 /* PAP acknowledge */
#define PAP_NAK 3 /* PAP fail */
@@ -505,7 +515,35 @@
inq = &ipintrq;
}
break;
+#ifdef SPPP_VJ
+ case PPP_VJ_COMP:
+ if (sp->state[IDX_IPCP] == STATE_OPENED) {
+ int len;
+
+ if ((len = sl_uncompress_tcp(
+ (u_char **)&m->m_data, m->m_len,
+ TYPE_COMPRESSED_TCP, sp->pp_comp)) <= 0)
+ goto drop;
+ m->m_len = m->m_pkthdr.len = len;
+ schednetisr (NETISR_IP);
+ inq = &ipintrq;
+ }
+ break;
+ case PPP_VJ_UCOMP:
+ if (sp->state[IDX_IPCP] == STATE_OPENED) {
+ int len;
+
+ if ((len = sl_uncompress_tcp(
+ (u_char **)&m->m_data, m->m_len,
+ TYPE_UNCOMPRESSED_TCP, sp->pp_comp)) <= 0)
+ goto drop;
+ m->m_len = m->m_pkthdr.len = len;
+ schednetisr (NETISR_IP);
+ inq = &ipintrq;
+ }
+ break;
#endif
+#endif
#ifdef IPX
case PPP_IPX:
/* IPX IPXCP not implemented yet */
@@ -615,6 +653,9 @@
struct ppp_header *h;
struct ifqueue *ifq;
int s, rv = 0;
+#ifdef SPPP_VJ
+ int ipproto = PPP_IP;
+#endif
s = splimp();
@@ -639,8 +680,7 @@
ifq = &ifp->if_snd;
#ifdef INET
- if (dst->sa_family == AF_INET)
- {
+ if (dst->sa_family == AF_INET) {
/* Check mbuf length here??? */
struct ip *ip = mtod (m, struct ip*);
struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl);
@@ -670,14 +710,38 @@
* Put low delay, telnet, rlogin and ftp control packets
* in front of the queue.
*/
-
+
if (! IF_QFULL (&sp->pp_fastq) &&
((ip->ip_tos & IPTOS_LOWDELAY) ||
- ((ip->ip_p == IPPROTO_TCP &&
- m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) &&
- (INTERACTIVE (ntohs (tcp->th_sport)))) ||
- INTERACTIVE (ntohs (tcp->th_dport)))))
+ ((ip->ip_p == IPPROTO_TCP &&
+ m->m_len >= sizeof (struct ip) + sizeof (struct tcphdr) &&
+ (INTERACTIVE (ntohs (tcp->th_sport)))) ||
+ INTERACTIVE (ntohs (tcp->th_dport)))))
ifq = &sp->pp_fastq;
+#ifdef SPPP_VJ
+ /*
+ * Do IP Header compression
+ */
+ if ((sp->pp_flags & PP_CISCO) == 0 &&
+ (sp->ipcp.flags & IPCP_VJ) != 0 &&
+ ip->ip_p == IPPROTO_TCP)
+ switch (sl_compress_tcp(m, ip, sp->pp_comp,
+ sp->ipcp.compress_cid)) {
+ case TYPE_COMPRESSED_TCP:
+ ipproto = PPP_VJ_COMP;
+ break;
+ case TYPE_UNCOMPRESSED_TCP:
+ ipproto = PPP_VJ_UCOMP;
+ break;
+ case TYPE_IP:
+ ipproto = PPP_IP;
+ break;
+ default:
+ m_freem(m);
+ splx(s);
+ return (EINVAL);
+ }
+#endif
}
#endif
@@ -727,7 +791,11 @@
* not ready to carry IP packets, and return
* ENETDOWN, as opposed to ENOBUFS.
*/
+#ifdef SPPP_VJ
+ h->protocol = htons(ipproto);
+#else
h->protocol = htons(PPP_IP);
+#endif
if (sp->state[IDX_IPCP] != STATE_OPENED)
rv = ENETDOWN;
}
@@ -813,7 +881,7 @@
/* Initialize keepalive handler. */
if (! spppq)
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- keepalive_ch =
+ keepalive_ch =
#endif
timeout(sppp_keepalive, 0, hz * 10);
@@ -833,6 +901,11 @@
sp->pp_up = lcp.Up;
sp->pp_down = lcp.Down;
+#ifdef SPPP_VJ
+ sp->pp_comp = malloc (sizeof (*sp->pp_comp), M_DEVBUF, M_NOWAIT);
+ sl_compress_init(sp->pp_comp);
+#endif
+
sppp_lcp_init(sp);
sppp_ipcp_init(sp);
sppp_pap_init(sp);
@@ -871,6 +944,10 @@
, sp->pap_my_to_ch
#endif
);
+
+#ifdef SPPP_VJ
+ free(sp->pp_comp, M_DEVBUF);
+#endif
}
/*
@@ -1778,7 +1855,7 @@
case STATE_ACK_SENT:
(cp->scr)(sp);
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- sp->ch[cp->protoidx] =
+ sp->ch[cp->protoidx] =
#endif
timeout(cp->TO, (void *)sp, sp->lcp.timeout);
break;
@@ -2329,10 +2406,8 @@
sp->pp_phase = PHASE_NETWORK;
if(debug)
- {
log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
sppp_phase_name(sp->pp_phase));
- }
/*
* Open all authentication protocols. This is even required
@@ -2376,10 +2451,8 @@
sp->pp_phase = PHASE_TERMINATE;
if(debug)
- {
log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
sppp_phase_name(sp->pp_phase));
- }
/*
* Take upper layers down. We send the Down event first and
@@ -2402,10 +2475,8 @@
sp->pp_phase = PHASE_ESTABLISH;
if(debug)
- {
log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
sppp_phase_name(sp->pp_phase));
- }
/* Notify lower layer if desired. */
if (sp->pp_tls)
@@ -2420,10 +2491,8 @@
sp->pp_phase = PHASE_DEAD;
if(debug)
- {
log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
sppp_phase_name(sp->pp_phase));
- }
/* Notify lower layer if desired. */
if (sp->pp_tlf)
@@ -2542,7 +2611,8 @@
STDDCL;
u_long myaddr, hisaddr;
- sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN);
+ sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN | IPCP_MYADDR_SEEN |
+ IPCP_MYADDR_DYN | IPCP_VJ);
sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0);
/*
@@ -2559,6 +2629,11 @@
return;
}
+#ifdef SPPP_VJ
+ sp->ipcp.opts |= (1 << IPCP_OPT_COMPRESSION);
+ sp->ipcp.max_state = MAX_STATES - 1;
+ sp->ipcp.compress_cid = 1;
+#endif
if (myaddr == 0L) {
/*
* I don't have an assigned address, so i need to
@@ -2602,6 +2677,9 @@
int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
u_long hisaddr, desiredaddr;
int gotmyaddr = 0;
+#ifdef SPPP_VJ
+ int desiredcomp;
+#endif
len -= 4;
origlen = len;
@@ -2622,7 +2700,7 @@
if (debug)
addlog(" %s ", sppp_ipcp_opt_name(*p));
switch (*p) {
-#ifdef notyet
+#ifdef SPPP_VJ
case IPCP_OPT_COMPRESSION:
if (len >= 6 && p[1] >= 6) {
/* correctly formed compress option */
@@ -2670,27 +2748,42 @@
if (debug)
addlog(" %s ", sppp_ipcp_opt_name(*p));
switch (*p) {
-#ifdef notyet
+#ifdef SPPP_VJ
case IPCP_OPT_COMPRESSION:
- continue;
+ desiredcomp = p[2] << 8 | p[3];
+ /* We only support VJ */
+ if (desiredcomp == IPCP_COMP_VJ) {
+ if (debug)
+ addlog("VJ [ack] ");
+ sp->ipcp.flags |= IPCP_VJ;
+ sl_compress_setup(sp->pp_comp, p[4]);
+ sp->ipcp.max_state = p[4];
+ sp->ipcp.compress_cid = p[5];
+ continue;
+ }
+ if (debug)
+ addlog("%#04x [not supported] ", desiredcomp);
+ p[2] = IPCP_COMP_VJ >> 8;
+ p[3] = IPCP_COMP_VJ;
+ break;
#endif
case IPCP_OPT_ADDRESS:
desiredaddr = p[2] << 24 | p[3] << 16 |
p[4] << 8 | p[5];
if (!(sp->ipcp.flags & IPCP_MYADDR_SEEN) &&
- (sp->ipcp.flags & IPCP_MYADDR_DYN)) {
+ (sp->ipcp.flags & IPCP_MYADDR_DYN)) {
/*
* hopefully this is our address !!
*/
- if (debug)
+ if (debug)
addlog("[wantmyaddr %s] ",
sppp_dotted_quad(desiredaddr));
/*
* When doing dynamic address assignment,
- * we accept his offer. Otherwise, we
- * ignore it and thus continue to negotiate
- * our already existing value.
- */
+ * we accept his offer. Otherwise, we
+ * ignore it and thus continue to negotiate
+ * our already existing value.
+ */
sppp_set_ip_addr(sp, desiredaddr);
if (debug)
addlog("[agree] ");
@@ -2699,32 +2792,32 @@
continue;
} else {
if (desiredaddr == hisaddr ||
- (hisaddr == 1 && desiredaddr != 0)) {
+ (hisaddr == 1 && desiredaddr != 0)) {
/*
- * Peer's address is same as our value,
- * this is agreeable. Gonna conf-ack
- * it.
- */
+ * Peer's address is same as our value,
+ * this is agreeable. Gonna conf-ack
+ * it.
+ */
if (debug)
addlog("%s [ack] ",
- sppp_dotted_quad(hisaddr));
+ sppp_dotted_quad(hisaddr));
/* record that we've seen it already */
sp->ipcp.flags |= IPCP_HISADDR_SEEN;
continue;
}
/*
- * The address wasn't agreeable. This is either
- * he sent us 0.0.0.0, asking to assign him an
- * address, or he send us another address not
- * matching our value. Either case, we gonna
- * conf-nak it with our value.
- */
+ * The address wasn't agreeable. This is either
+ * he sent us 0.0.0.0, asking to assign him an
+ * address, or he send us another address not
+ * matching our value. Either case, we gonna
+ * conf-nak it with our value.
+ */
if (debug) {
if (desiredaddr == 0)
addlog("[addr requested] ");
else
addlog("%s [not agreed] ",
- sppp_dotted_quad(desiredaddr));
+ sppp_dotted_quad(desiredaddr));
}
p[2] = hisaddr >> 24;
@@ -2809,9 +2902,9 @@
*/
sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS);
break;
-#ifdef notyet
- case IPCP_OPT_COMPRESS:
- sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS);
+#ifdef SPPP_VJ
+ case IPCP_OPT_COMPRESSION:
+ sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESSION);
break;
#endif
}
@@ -2832,6 +2925,9 @@
u_char *buf, *p;
struct ifnet *ifp = &sp->pp_if;
int debug = ifp->if_flags & IFF_DEBUG;
+#ifdef SPPP_VJ
+ int desiredcomp;
+#endif
u_long wantaddr;
len -= 4;
@@ -2875,11 +2971,25 @@
}
}
break;
-#ifdef notyet
- case IPCP_OPT_COMPRESS:
+#ifdef SPPP_VJ
+ case IPCP_OPT_COMPRESSION:
/*
* Peer wants different compression parameters.
*/
+ if (len >= 6 && p[1] == 6) {
+ desiredcomp = p[2] << 8 | p[3];
+ if (debug)
+ addlog("[wantcomp %#04x] ",
+ desiredcomp);
+ if (desiredcomp == IPCP_COMP_VJ) {
+ sl_compress_setup(sp->pp_comp, p[4]);
+ sp->ipcp.max_state = p[4];
+ sp->ipcp.compress_cid = p[5];
+ addlog("[agree] ");
+ } else
+ sp->ipcp.opts &=
+ ~(1 << IPCP_OPT_COMPRESSION);
+ }
break;
#endif
}
@@ -2925,14 +3035,14 @@
u_long ouraddr;
int i = 0;
-#ifdef notyet
+#ifdef SPPP_VJ
if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) {
opt[i++] = IPCP_OPT_COMPRESSION;
opt[i++] = 6;
- opt[i++] = 0; /* VJ header compression */
- opt[i++] = 0x2d; /* VJ header compression */
- opt[i++] = max_slot_id;
- opt[i++] = comp_slot_id;
+ opt[i++] = IPCP_COMP_VJ >> 8;
+ opt[i++] = IPCP_COMP_VJ;
+ opt[i++] = sp->ipcp.max_state;
+ opt[i++] = sp->ipcp.compress_cid;
}
#endif
@@ -4168,10 +4278,8 @@
sp->pp_phase = PHASE_NETWORK;
if(debug)
- {
log(LOG_INFO, SPP_FMT "phase %s\n", SPP_ARGS(ifp),
sppp_phase_name(sp->pp_phase));
- }
/* Notify NCPs now. */
for (i = 0; i < IDX_COUNT; i++)
@@ -4360,10 +4468,3 @@
{
/* do just nothing */
}
-/*
- * This file is large. Tell emacs to highlight it nevertheless.
- *
- * Local Variables:
- * hilit-auto-highlight-maxout: 120000
- * End:
- */
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: kern-bug-people->martin
Responsible-Changed-By: perry
Responsible-Changed-When: Tue Apr 1 10:55:02 PST 2003
Responsible-Changed-Why:
Martin handles sync PPP issues
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.