NetBSD Problem Report #43959

From mouse@Sparkle.Rodents-Montreal.ORG  Sun Oct 10 08:31:59 2010
Return-Path: <mouse@Sparkle.Rodents-Montreal.ORG>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id 0AFB663BBD6
	for <gnats-bugs@gnats.NetBSD.org>; Sun, 10 Oct 2010 08:31:59 +0000 (UTC)
Message-Id: <201010100831.EAA27894@Sparkle.Rodents-Montreal.ORG>
Date: Sun, 10 Oct 2010 04:31:56 -0400 (EDT)
From: der Mouse <mouse@Rodents-Montreal.ORG>
Reply-To: mouse@Rodents-Montreal.ORG
To: gnats-bugs@gnats.NetBSD.org
Subject: [dM] sl(4) IPv6 support
X-Send-Pr-Version: 3.95

>Number:         43959
>Category:       kern
>Synopsis:       [dM] Add IPv6 support to sl(4)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Oct 10 08:35:00 +0000 2010
>Originator:     der Mouse
>Release:        NetBSD 4.0.1
>Organization:
	Dis-
>Environment:
	Any 4.0.1
>Description:
	sl(4) does not support any protocols except IPv4.  This is an
	implementation of an extension of it to support IPv6 as well,
	as outlined in ftp.rodents-montreal.org:/mouse/misc/ipv6-slip.
>How-To-Repeat:
	Want to send v6 over SLIP.  Discover it isn't supported.
>Fix:
	If this is adopted, the document mentioned in "Description"
	probably should be imported somewhere and referenced from
	sl(4).  I'm not sure where would be most appropriate, though,
	so I've made no attempt to do that here.

	--- base/sys/net/if_slvar.h	Wed Jun  7 18:33:43 2006
	+++ live/sys/net/if_slvar.h	Sun Oct 10 04:10:48 2010
	@@ -52,6 +52,7 @@
	 	struct mbuf *sc_mbuf;		/* input buffer */
	 	u_int	sc_flags;		/* see below */
	 	u_int	sc_escape;	/* =1 if last char input was FRAME_ESCAPE */
	+	int	sc_af;			/* AF_INET, AF_INET6, etc - input */
	 	long	sc_lasttime;		/* last time a char arrived */
	 	long	sc_abortcount;		/* number of abort esacpe chars */
	 	long	sc_starttime;		/* time of first abort in window */

	--- base/sys/net/if_sl.c	Wed Nov 15 20:33:40 2006
	+++ live/sys/net/if_sl.c	Sun Oct 10 04:10:47 2010
	@@ -90,11 +90,16 @@
	 #include <net/netisr.h>
	 #include <net/route.h>

	-#ifdef INET
	+#if defined(INET) || defined(INET6)
	 #include <netinet/in.h>
	 #include <netinet/in_systm.h>
	 #include <netinet/in_var.h>
	 #include <netinet/ip.h>
	+#else
	+#error "SLIP with neither INET nor INET6?"
	+#endif
	+#ifdef INET6
	+#include <netinet/ip6.h>
	 #endif

	 #include <net/slcompress.h>
	@@ -186,6 +191,8 @@
	 #define FRAME_ESCAPE		0xdb		/* Frame Esc */
	 #define TRANS_FRAME_END		0xdc		/* transposed frame end */
	 #define TRANS_FRAME_ESCAPE	0xdd		/* transposed frame esc */
	+#define TRANS_PKTTYPE_BASE	0x80		/* packet type base */
	+#define PKTTYPE_IPv6		0		/* packet is a v6 packet */

	 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
	 void	slnetisr(void);
	@@ -252,6 +259,7 @@
	 #if NBPFILTER > 0
	 	bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
	 #endif
	+	sc->sc_af = AF_INET;
	 	LIST_INSERT_HEAD(&sl_softc_list, sc, sc_iflist);
	 	return 0;
	 }
	@@ -463,16 +471,23 @@

	 	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);

	-	/*
	-	 * `Cannot happen' (see slioctl).  Someday we will extend
	-	 * the line protocol to support other address families.
	-	 */
	-	if (dst->sa_family != AF_INET) {
	-		printf("%s: af%d not supported\n", sc->sc_if.if_xname,
	-		    dst->sa_family);
	-		m_freem(m);
	-		sc->sc_if.if_noproto++;
	-		return EAFNOSUPPORT;
	+	switch (dst->sa_family) {
	+#ifdef INET
	+		case AF_INET:
	+			break;
	+#endif
	+#ifdef INET6
	+		case AF_INET6:
	+			break;
	+#endif
	+		default:
	+			/* "can't happen"; slioctl won't set others */
	+			printf("%s: af%d not supported\n",
	+				&sc->sc_if.if_xname[0], dst->sa_family);
	+			m_freem(m);
	+			sc->sc_if.if_noproto++;
	+			return EAFNOSUPPORT;
	+			break;
	 	}

	 	if (sc->sc_ttyp == NULL) {
	@@ -485,13 +500,24 @@
	 		printf("%s: no carrier and not local\n", sc->sc_if.if_xname);
	 		return EHOSTUNREACH;
	 	}
	-	ip = mtod(m, struct ip *);
	 #ifdef INET
	-	if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
	-		m_freem(m);
	-		return ENETRESET;		/* XXX ? */
	+	/* XXX really should do likewise for icmp6! */
	+	if (dst->sa_family == AF_INET) {
	+		ip = mtod(m, struct ip *);
	+		if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
	+			m_freem(m);
	+			return ENETRESET;		/* XXX ? */
	+		}
	+		if ((ip->ip_tos & IPTOS_LOWDELAY) != 0)
	+			ifq = &sc->sc_fastq;
	 	}
	 #endif
	+	M_PREPEND(m,dst->sa_len,M_DONTWAIT);
	+	if (m == 0) {
	+		sc->sc_if.if_oerrors ++;
	+		return(ENOBUFS);
	+	}
	+	bcopy(dst,mtod(m,char *),dst->sa_len);

	 	s = spltty();
	 	if (sc->sc_oqlen && sc->sc_ttyp->t_outq.c_cc == sc->sc_oqlen) {
	@@ -508,10 +534,6 @@
	 	splx(s);

	 	s = splnet();
	-#ifdef INET
	-	if ((ip->ip_tos & IPTOS_LOWDELAY) != 0)
	-		ifq = &sc->sc_fastq;
	-#endif
	 	if ((error = ifq_enqueue2(ifp, ifq, m ALTQ_COMMA
	 	    ALTQ_DECL(&pktattr))) != 0) {
	 		splx(s);
	@@ -660,6 +682,14 @@
	 			c = FRAME_END;
	 		break;

	+	case TRANS_PKTTYPE_BASE + PKTTYPE_IPv6:
	+		if (sc->sc_escape) {
	+			sc->sc_af = AF_INET6;
	+			sc->sc_escape = 0;
	+			return(0);
	+		}
	+		break;
	+
	 	case FRAME_ESCAPE:
	 		sc->sc_escape = 1;
	 		return 0;
	@@ -678,6 +708,12 @@
	 		if (m == NULL)
	 			goto error;

	+		M_PREPEND(m,sizeof(int),M_DONTWAIT);
	+		if (m == 0)
	+			goto error;
	+
	+		bcopy(&sc->sc_af,mtod(m,int *),sizeof(int));
	+
	 		IF_ENQUEUE(&sc->sc_inq, m);
	 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
	 		softintr_schedule(sc->sc_si);
	@@ -705,6 +741,7 @@
	 	sc->sc_mp = sc->sc_pktstart = (u_char *)sc->sc_mbuf->m_ext.ext_buf +
	 	    BUFOFFSET;
	 	sc->sc_escape = 0;
	+	sc->sc_af = AF_INET;

	 	return 0;
	 }
	@@ -748,6 +785,8 @@
	 		struct ip *ip;
	 #endif
	 		struct mbuf *m2;
	+		struct sockaddr_storage dst;
	+		struct sockaddr *dstp;
	 #if NBPFILTER > 0
	 		struct mbuf *bpf_m;
	 #endif
	@@ -781,6 +820,14 @@
	 			break;

	 		/*
	+		 * We know (because we added it ourselves) that the
	+		 *  destination address is entirely in the first mbuf.
	+		 */
	+		dstp = mtod(m,struct sockaddr *);
	+		bcopy(dstp,&dst,dstp->sa_len);
	+		m_adj(m,dst.ss_len);
	+
	+		/*
	 		 * We do the header compression here rather than in
	 		 * sloutput() because the packets will be out of order
	 		 * if we are using TOS queueing, and the connection
	@@ -802,7 +849,8 @@
	 			bpf_m = NULL;
	 #endif
	 #ifdef INET
	-		if ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) {
	+		if ( (dst.ss_family == AF_INET) &&
	+		     ((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) ) {
	 			if (sc->sc_if.if_flags & SC_COMPRESS)
	 				*mtod(m, u_char *) |=
	 				    sl_compress_tcp(m, ip, &sc->sc_comp, 1);
	@@ -828,6 +876,31 @@
	 			(void)putc(FRAME_END, &tp->t_outq);
	 		}

	+		switch (dst.ss_family) {
	+#ifdef INET
	+			case AF_INET:
	+				break;
	+#endif
	+#ifdef INET6
	+			case AF_INET6:
	+				if (! putc(FRAME_ESCAPE,&tp->t_outq)) {
	+					if (! putc(TRANS_PKTTYPE_BASE+PKTTYPE_IPv6,&tp->t_outq)) {
	+						sc->sc_if.if_obytes += 2;
	+					} else {
	+						unputc(&tp->t_outq);
	+					}
	+				} else {
	+					sc->sc_if.if_oerrors ++;
	+					m_freem(m);
	+					continue;
	+				}
	+				break;
	+#endif
	+			default:
	+				panic("slstart: impossible dst.ss_family");
	+				break;
	+		}
	+
	 		while (m) {
	 			u_char *bp, *cp, *ep;

	@@ -910,11 +983,16 @@
	 	 * Input processing loop.
	 	 */
	 	for (;;) {
	+		int af;
	+		struct ifqueue *queue;
	+		int isr;
	 		s = spltty();
	 		IF_DEQUEUE(&sc->sc_inq, m);
	 		splx(s);
	 		if (m == NULL)
	 			break;
	+		bcopy(mtod(m,int *),&af,sizeof(int));
	+		m_adj(m,sizeof(int));
	 		pktstart = mtod(m, u_char *);
	 		len = m->m_pkthdr.len;
	 #if NBPFILTER > 0
	@@ -931,7 +1009,7 @@
	 		}
	 #endif /* NBPFILTER > 0 */
	 #ifdef INET
	-		if ((c = (*pktstart & 0xf0)) != (IPVERSION << 4)) {
	+		if ((af == AF_INET) && ((c = (*pktstart & 0xf0)) != (IPVERSION << 4))) {
	 			if (c & 0x80)
	 				c = TYPE_COMPRESSED_TCP;
	 			else if (c == TYPE_UNCOMPRESSED_TCP)
	@@ -997,24 +1075,43 @@
	 		sc->sc_if.if_ipackets++;
	 		getbinuptime(&sc->sc_lastpacket);

	+		queue = 0;
	+		switch (af) {
	+			case AF_INET:
	 #ifdef INET
	-		s = splnet();
	-		if (IF_QFULL(&ipintrq)) {
	-			IF_DROP(&ipintrq);
	+				queue = &ipintrq;
	+				isr = NETISR_IP;
	+#endif
	+				break;
	+			case AF_INET6:
	+#ifdef INET6
	+				queue = &ip6intrq;
	+				isr = NETISR_IPV6;
	+#endif
	+				break;
	+			default:
	+				panic("slinput impossible af");
	+				break;
	+		}
	+		if (queue == 0) {
	+			/* af not in this kernel! */
	+			sc->sc_if.if_ierrors ++;
	+			m_freem(m);
	+		} else if (IF_QFULL(queue)) {
	+			IF_DROP(queue);
	 			sc->sc_if.if_ierrors++;
	 			sc->sc_if.if_iqdrops++;
	 			m_freem(m);
	 		} else {
	-			IF_ENQUEUE(&ipintrq, m);
	-			schednetisr(NETISR_IP);
	+			IF_ENQUEUE(queue, m);
	+			schednetisr(isr);
	 		}
	 		splx(s);
	-#endif
	 	}
	 }

	 /*
	- * Process an ioctl request.
	+ * Process a (network interface) ioctl request.
	  */
	 static int
	 slioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
	@@ -1029,13 +1126,40 @@
	 	switch (cmd) {

	 	case SIOCSIFADDR:
	-		if (ifa->ifa_addr->sa_family == AF_INET)
	-			ifp->if_flags |= IFF_UP;
	-		else
	-			error = EAFNOSUPPORT;
	+		switch (ifa->ifa_addr->sa_family) {
	+#ifdef INET
	+			case AF_INET:
	+				ifp->if_flags |= IFF_UP;
	+				break;
	+#endif
	+#ifdef INET6
	+			case AF_INET6:
	+				ifp->if_flags |= IFF_UP;
	+				if (sc->sc_if.if_mtu < IPV6_MMTU)
	+					sc->sc_if.if_mtu = IPV6_MMTU;
	+				break;
	+#endif
	+			default:
	+				error = EAFNOSUPPORT;
	+				break;
	+		}
	 		break;

	 	case SIOCSIFDSTADDR:
	+		switch (ifa->ifa_addr->sa_family) {
	+#ifdef INET
	+			case AF_INET:
	+				break;
	+#endif
	+#ifdef INET6
	+			case AF_INET6:
	+				break;
	+#endif
	+			default:
	+				error = EAFNOSUPPORT;
	+				break;
	+		}
	+
	 		if (ifa->ifa_addr->sa_family != AF_INET)
	 			error = EAFNOSUPPORT;
	 		break;
	@@ -1045,6 +1169,20 @@
	 		    error = EINVAL;
	 		    break;
	 		}
	+#ifdef INET6
	+		if (ifr->ifr_mtu < IPV6_MMTU) {
	+			/* If we have any v6 address set, reject! */
	+			struct ifaddr *ifa2;
	+			for ( ifa2 = sc->sc_if.if_addrlist.tqh_first;
	+			      ifa2;
	+			      ifa2 = ifa2->ifa_list.tqe_next )
	+				switch (((struct sockaddr *)ifa2->ifa_addr)->sa_family) {
	+					case AF_INET6:
	+						error = EINVAL;
	+						goto done; /* break switch, for, switch */
	+				}
	+		}
	+#endif
	 		sc->sc_if.if_mtu = ifr->ifr_mtu;
	 		break;

	@@ -1059,12 +1197,14 @@
	 			break;
	 		}
	 		switch (ifr->ifr_addr.sa_family) {
	-
	 #ifdef INET
	 		case AF_INET:
	 			break;
	 #endif
	-
	+#ifdef INET6
	+		case AF_INET6:
	+			break;
	+#endif
	 		default:
	 			error = EAFNOSUPPORT;
	 			break;
	@@ -1100,6 +1240,9 @@
	 	default:
	 		error = EINVAL;
	 	}
	+#ifdef INET6
	+done:;
	+#endif
	 	splx(s);
	 	return error;
	 }

	--- base/share/man/man4/sl.4	Sun Jul  9 05:21:35 2006
	+++ live/share/man/man4/sl.4	Sun Oct 10 04:20:46 2010
	@@ -123,18 +123,24 @@
	 device appeared in
	 .Nx 1.0 .
	 .Sh BUGS
	+Standard
	 .Tn SLIP
	-can only transmit
	+can transmit only
	 .Tn IPv4
	-packets between preconfigured hosts on an asynchronous serial link.
	-It has no provision for address negotiation,
	-carriage of additional protocols (e.g.
	+packets between preconfigured hosts on an asynchronous serial link; the
	+.Nx
	+implementation has been enhanced to support
	+.Tn IPv6
	+as well.  It has no provision for address negotiation and is not
	+designed for synchronous serial links.  There is no support for other
	+protocols (e.g.
	 .Tn XNS ,
	 .Tn AppleTalk ,
	 .Tn DECNET ) ,
	-and is not designed for synchronous serial links.
	-This is why
	+though they would be relatively easy to add.  These are among the
	+reasons why
	 .Tn SLIP
	-has been superseded by the Point-to-Point Protocol
	+has for most applications been superseded by the Point-to-Point
	+Protocol
	 .Pq Tn PPP ,
	-which does all of those things, and much more.
	+which does all of those things and much more.

NetBSD Home
NetBSD PR Database Search

(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.