? doi
? mpls1.patch
? mpls2.diff
? other2.tar
? sysnetmpls.tar
? unu
? sys/netmpls
? sys/arch/amd64/compile/GENERIC
? sys/arch/i386/conf/KEMOBILE
? sys/arch/i386/conf/KEMOBMON
? usr.sbin/ldpd
Index: distrib/sets/lists/base/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/base/mi,v
retrieving revision 1.862
diff -u -p -r1.862 mi
--- distrib/sets/lists/base/mi	17 Apr 2010 15:55:52 -0000	1.862
+++ distrib/sets/lists/base/mi	6 May 2010 11:25:56 -0000
@@ -790,6 +790,7 @@
 ./usr/include/netisdn				base-c-usr
 ./usr/include/netiso				base-c-usr
 ./usr/include/netkey				base-c-usr
+./usr/include/netmpls				base-c-usr
 ./usr/include/netnatm				base-c-usr
 ./usr/include/netns				base-obsolete		obsolete
 ./usr/include/netsmb				base-c-usr
@@ -1129,6 +1130,7 @@
 ./usr/sbin/ktutil				base-krb5-bin		kerberos
 ./usr/sbin/kvm_mkdb				base-obsolete		obsolete
 ./usr/sbin/lastlogin				base-sysutil-bin
+./usr/sbin/ldpd					base-router-bin
 ./usr/sbin/link					base-sysutil-bin
 ./usr/sbin/linkfarm				base-obsolete		obsolete
 ./usr/sbin/lmcconfig				base-netutil-bin
Index: distrib/sets/lists/comp/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v
retrieving revision 1.1436
diff -u -p -r1.1436 mi
--- distrib/sets/lists/comp/mi	25 Apr 2010 00:54:44 -0000	1.1436
+++ distrib/sets/lists/comp/mi	6 May 2010 11:26:10 -0000
@@ -1453,6 +1453,7 @@
 ./usr/include/net/if_ieee80211.h		comp-obsolete		obsolete
 ./usr/include/net/if_llc.h			comp-c-include
 ./usr/include/net/if_media.h			comp-c-include
+./usr/include/net/if_mpls.h			comp-c-include
 ./usr/include/net/if_pflog.h			comp-c-include
 ./usr/include/net/if_ppp.h			comp-c-include
 ./usr/include/net/if_pppoe.h			comp-c-include
@@ -1631,6 +1632,7 @@
 ./usr/include/netiso/tp_user.h			comp-c-include
 ./usr/include/netiso/tp_var.h			comp-c-include
 ./usr/include/netiso/tuba_table.h		comp-obsolete		obsolete
+./usr/include/netmpls/mpls.h			comp-c-include
 ./usr/include/netkey/key.h			comp-c-include
 ./usr/include/netkey/key_debug.h		comp-c-include
 ./usr/include/netkey/key_var.h			comp-c-include
Index: distrib/sets/lists/etc/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/etc/mi,v
retrieving revision 1.216
diff -u -p -r1.216 mi
--- distrib/sets/lists/etc/mi	5 Feb 2010 09:44:23 -0000	1.216
+++ distrib/sets/lists/etc/mi	6 May 2010 11:26:11 -0000
@@ -212,6 +212,7 @@
 ./etc/rc.d/kdc					etc-krb5-rc
 ./etc/rc.d/kerberos				etc-obsolete		obsolete
 ./etc/rc.d/ldconfig				etc-sys-rc
+./etc/rc.d/ldpd					etc-net-rc
 ./etc/rc.d/lkm1					etc-obsolete		obsolete
 ./etc/rc.d/lkm2					etc-obsolete		obsolete
 ./etc/rc.d/lkm3					etc-obsolete		obsolete
Index: distrib/sets/lists/man/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/man/mi,v
retrieving revision 1.1205
diff -u -p -r1.1205 mi
--- distrib/sets/lists/man/mi	25 Apr 2010 00:54:45 -0000	1.1205
+++ distrib/sets/lists/man/mi	6 May 2010 11:26:18 -0000
@@ -2245,6 +2245,7 @@
 ./usr/share/man/cat8/lastlogin.0		man-sysutil-catman	.cat
 ./usr/share/man/cat8/ldconfig.0			man-sysutil-catman	.cat
 ./usr/share/man/cat8/lfs_cleanerd.0		man-sysutil-catman	.cat
+./usr/share/man/cat8/ldpd.0			man-router-catman	.cat
 ./usr/share/man/cat8/link.0			man-sysutil-catman	.cat
 ./usr/share/man/cat8/lmcconfig.0		man-sysutil-catman	.cat
 ./usr/share/man/cat8/lmcctl.0			man-obsolete		obsolete
@@ -4714,6 +4715,7 @@
 ./usr/share/man/html8/ktutil.html		man-krb5-htmlman	kerberos,html
 ./usr/share/man/html8/lastlogin.html		man-sysutil-htmlman	html
 ./usr/share/man/html8/ldconfig.html		man-sysutil-htmlman	html
+./usr/share/man/html8/ldpd.html			man-netutil-htmlman	html
 ./usr/share/man/html8/lfs_cleanerd.html		man-sysutil-htmlman	html
 ./usr/share/man/html8/link.html			man-sysutil-htmlman	html
 ./usr/share/man/html8/lmcconfig.html		man-sysutil-htmlman	html
@@ -7336,6 +7338,7 @@
 ./usr/share/man/man8/kvm_mkdb.8			man-obsolete		obsolete
 ./usr/share/man/man8/lastlogin.8		man-sysutil-man		.man
 ./usr/share/man/man8/ldconfig.8			man-sysutil-man		.man
+./usr/share/man/man8/ldpd.8			man-router-man		.man
 ./usr/share/man/man8/lfs_cleanerd.8		man-sysutil-man		.man
 ./usr/share/man/man8/link.8			man-sysutil-man		.man
 ./usr/share/man/man8/lmcconfig.8		man-sysutil-man		.man
Index: etc/rc.d/Makefile
===================================================================
RCS file: /cvsroot/src/etc/rc.d/Makefile,v
retrieving revision 1.80
diff -u -p -r1.80 Makefile
--- etc/rc.d/Makefile	29 Sep 2009 23:56:27 -0000	1.80
+++ etc/rc.d/Makefile	6 May 2010 11:26:20 -0000
@@ -25,7 +25,7 @@ CONFIGFILES=\
 		identd ifwatchd inetd ipfilter ipfs ipmon ipnat ipsec \
 		irdaattach iscsi_target isdnd \
 		kdc \
-		ldconfig local lpd lvm \
+		ldconfig ldpd local lpd lvm \
 		mdnsd mixerctl mopd motd mountall mountcritlocal \
 		mountcritremote mountd moused mrouted \
 		named ndbootd network newsyslog nfsd nfslocking ntpd ntpdate \
Index: etc/rc.d/ldpd
===================================================================
RCS file: etc/rc.d/ldpd
diff -N etc/rc.d/ldpd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ etc/rc.d/ldpd	6 May 2010 11:26:20 -0000
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# $NetBSD$
+#
+
+#
+# PROVIDE: ldpd
+# REQUIRE: network
+
+$_rc_subr_loaded . /etc/rc.subr
+
+name="ldpd"
+rcvar=$name
+command="/usr/sbin/${name}"
+
+load_rc_config $name
+run_rc_command "$1"
Index: sbin/route/keywords.c
===================================================================
RCS file: /cvsroot/src/sbin/route/keywords.c,v
retrieving revision 1.6
diff -u -p -r1.6 keywords.c
--- sbin/route/keywords.c	6 Aug 2006 17:44:56 -0000	1.6
+++ sbin/route/keywords.c	6 May 2010 11:26:48 -0000
@@ -36,6 +36,7 @@ struct keytab keywords[] = {
 	{"lockrest", K_LOCKREST},
 	{"mask", K_MASK},
 	{"monitor", K_MONITOR},
+	{"mpls", K_MPLS},
 	{"mtu", K_MTU},
 	{"net", K_NET},
 	{"netmask", K_NETMASK},
@@ -53,6 +54,7 @@ struct keytab keywords[] = {
 	{"show", K_SHOW},
 	{"ssthresh", K_SSTHRESH},
 	{"static", K_STATIC},
+	{"tag", K_TAG},
 	{"x25", K_X25},
 	{"xns", K_XNS},
 	{"xresolve", K_XRESOLVE},
Index: sbin/route/keywords.h
===================================================================
RCS file: /cvsroot/src/sbin/route/keywords.h,v
retrieving revision 1.9
diff -u -p -r1.9 keywords.h
--- sbin/route/keywords.h	6 Aug 2006 17:44:56 -0000	1.9
+++ sbin/route/keywords.h	6 May 2010 11:26:48 -0000
@@ -59,3 +59,5 @@ extern struct keytab {
 #define	K_FLUSHALL	49
 #define	K_NOCLONED	50
 #define	K_NOCLONING	51
+#define	K_MPLS		52
+#define	K_TAG		53
Index: sbin/route/route.c
===================================================================
RCS file: /cvsroot/src/sbin/route/route.c,v
retrieving revision 1.119
diff -u -p -r1.119 route.c
--- sbin/route/route.c	28 Dec 2008 20:12:31 -0000	1.119
+++ sbin/route/route.c	6 May 2010 11:26:48 -0000
@@ -57,6 +57,7 @@ __RCSID("$NetBSD: route.c,v 1.119 2008/1
 #include <netinet/in.h>
 #include <netatalk/at.h>
 #include <netiso/iso.h>
+#include <netmpls/mpls.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 
@@ -83,13 +84,14 @@ union sockunion {
 	struct	sockaddr_dl sdl;
 #ifndef SMALL
 	struct	sockaddr_iso siso;
+	struct	sockaddr_mpls smpls;
 #endif /* SMALL */
 };
 
 typedef union sockunion *sup;
 
 struct sou {
-	union sockunion so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
+	union sockunion so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, so_mpls;
 };
 
 static char *any_ntoa(const struct sockaddr *);
@@ -121,7 +123,7 @@ static void sockaddr(const char *, struc
 int	pid, rtm_addrs;
 int	sock;
 int	forcehost, forcenet, doflush, nflag, af, qflag, tflag, Sflag;
-int	iflag, verbose, aflen = sizeof(struct sockaddr_in);
+int	iflag, verbose, aflen = sizeof(struct sockaddr_in), rtag;
 int	locking, lockrest, debugonly, shortoutput;
 struct	rt_metrics rt_metrics;
 u_int32_t  rtm_inits;
@@ -575,6 +577,16 @@ routename(const struct sockaddr *sa, str
 		    ((const struct sockaddr_at *)sa)->sat_addr.s_net,
 		    ((const struct sockaddr_at *)sa)->sat_addr.s_node);
 		break;
+	case AF_MPLS:
+		{
+		union mpls_shim ms;
+
+		ms.s_addr =((const struct sockaddr_mpls*)sa)->smpls_addr.s_addr;
+		ms.s_addr = ntohl(ms.s_addr);
+
+		snprintf(line, sizeof(line), "%u", ms.shim.label);
+		break;
+		}
 #endif /* SMALL */
 
 	default:
@@ -819,6 +831,16 @@ newroute(int argc, char *const *argv)
 				af = AF_ISO;
 				aflen = sizeof(struct sockaddr_iso);
 				break;
+			case K_MPLS:
+				af = AF_MPLS;
+				aflen = sizeof(struct sockaddr_mpls);
+				break;
+			case K_TAG:
+				if (!--argc)
+					usage(1+*argv);
+				aflen = sizeof(struct sockaddr_mpls);
+				(void)getaddr(RTA_TAG, *++argv, 0, soup);
+				break;
 #endif /* SMALL */
 
 			case K_IFACE:
@@ -1134,6 +1156,10 @@ getaddr(int which, const char *s, struct
 		su = &soup->so_ifa;
 		su->sa.sa_family = af;
 		break;
+	case RTA_TAG:
+		su = &soup->so_mpls;
+		afamily = AF_MPLS;
+		break;
 	default:
 		su = NULL;
 		usage("Internal Error");
@@ -1239,6 +1265,16 @@ badataddr:
 		su->sat.sat_addr.s_node = val;
 		rtm_addrs |= RTA_NETMASK;
 		return(forcehost || su->sat.sat_addr.s_node != 0);
+	case AF_MPLS:
+		if (atoi(s) < 0 || atoi(s) >> 20)	/* ETOOMANYATOIS */
+			errx(1, "bad tag: %s", s);
+		su->smpls.smpls_addr.s_addr = 0;
+		su->smpls.smpls_addr.shim.label = atoi(s);
+		su->smpls.smpls_addr.s_addr =
+			htonl(su->smpls.smpls_addr.s_addr);
+
+		/* We don't have netmasks for tags  */
+		return 1;
 #endif
 
 	case AF_LINK:
@@ -1462,6 +1498,7 @@ rtmsg(int cmd, int flags, struct sou *so
 	NEXTADDR(RTA_GENMASK, soup->so_genmask);
 	NEXTADDR(RTA_IFP, soup->so_ifp);
 	NEXTADDR(RTA_IFA, soup->so_ifa);
+	NEXTADDR(RTA_TAG, soup->so_mpls);
 	rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
 	if (verbose && ! shortoutput) {
 		if (rtm_addrs)
@@ -1568,7 +1605,7 @@ const char routeflags[] =
 const char ifnetflags[] =
 "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST";
 const char addrnames[] =
-"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
+"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011TAG";
 
 
 #ifndef SMALL
@@ -1733,7 +1770,7 @@ print_rtmsg(struct rt_msghdr *rtm, int m
 static int
 print_getmsg(struct rt_msghdr *rtm, int msglen, struct sou *soup)
 {
-	struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL;
+	struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL, *mpls = NULL;
 	struct sockaddr_dl *ifp = NULL;
 	struct sockaddr *sa;
 	char *cp;
@@ -1779,6 +1816,9 @@ print_getmsg(struct rt_msghdr *rtm, int 
 				case RTA_IFA:
 					ifa = sa;
 					break;
+				case RTA_TAG:
+					mpls = sa;
+					break;
 				}
 				ADVANCE(cp, sa);
 			}
@@ -1806,6 +1846,17 @@ print_getmsg(struct rt_msghdr *rtm, int 
 		} else
 			(void)printf("    gateway: %s\n", name);
 	}
+	if (mpls) {
+		const char *name;
+		name = routename(mpls, NULL, RTF_HOST);
+		if(shortoutput) {
+			if (*name == '\0')
+				return 1;
+			printf("%s\n", name);
+		} else
+			printf("        Tag: %s\n", name);
+	}
+		
 	if (ifa && ! shortoutput)
 		(void)printf(" local addr: %s\n",
 		    routename(ifa, NULL, RTF_HOST));
@@ -1980,6 +2031,14 @@ sodump(sup su, const char *which)
 		(void)printf("%s: iso %s; ",
 		    which, iso_ntoa(&su->siso.siso_addr));
 		break;
+	case AF_MPLS:
+		{
+		union mpls_shim ms;
+		ms.s_addr = ntohl(su->smpls.smpls_addr.s_addr);
+		printf("%s: mpls %u; ",
+		    which, ms.shim.label);
+		}
+		break;
 #endif /* SMALL */
 	default:
 		(void)printf("%s: (%d) %s; ",
Index: sbin/route/show.c
===================================================================
RCS file: /cvsroot/src/sbin/route/show.c,v
retrieving revision 1.40
diff -u -p -r1.40 show.c
--- sbin/route/show.c	26 Jan 2010 21:27:54 -0000	1.40
+++ sbin/route/show.c	6 May 2010 11:26:48 -0000
@@ -43,11 +43,13 @@ __RCSID("$NetBSD: show.c,v 1.40 2010/01/
 #include <sys/socket.h>
 #include <sys/mbuf.h>
 
+#include <arpa/inet.h>
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
 #include <net/route.h>
 #include <netinet/in.h>
+#include <netmpls/mpls.h>
 
 #include <sys/sysctl.h>
 
@@ -138,6 +140,10 @@ parse_show_opts(int argc, char * const *
 			af = AF_ISO;
 			afname = argv[argc - 1] + 1;
 			break;
+		case K_MPLS:
+			af = AF_MPLS;
+			afname = argv[argc - 1] + 1;
+			break;
 #endif /* SMALL */
 		case K_LINK:
 			if (nolink)
@@ -319,6 +325,9 @@ pr_family(int af)
 	case AF_ISO:
 		afname = "ISO";
 		break;
+	case AF_MPLS:
+		afname = "MPLS";
+		break;
 #endif /* SMALL */
 	case AF_APPLETALK:
 		afname = "AppleTalk";
@@ -363,6 +372,18 @@ p_sockaddr(struct sockaddr *sa, struct s
 #endif /* INET6 */
 
 #ifndef SMALL
+	case AF_MPLS:
+		{
+		struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)sa;
+		union mpls_shim ms;
+
+		ms.s_addr = ntohl(smpls->smpls_addr.s_addr);
+
+		snprintf(workbuf, sizeof(workbuf), "%u",
+			ms.shim.label);
+		cp = workbuf;
+		}
+		break;
 	case AF_APPLETALK:
 		if (getnameinfo(sa, sa->sa_len, workbuf, sizeof(workbuf),
 		    NULL, 0, NI_NUMERICHOST) != 0)
Index: sys/Makefile
===================================================================
RCS file: /cvsroot/src/sys/Makefile,v
retrieving revision 1.75
diff -u -p -r1.75 Makefile
--- sys/Makefile	30 Dec 2008 22:18:11 -0000	1.75
+++ sys/Makefile	6 May 2010 11:26:49 -0000
@@ -2,7 +2,7 @@
 
 SUBDIR=	altq arch compat dev fs miscfs \
 	net net80211 netatalk netbt netipsec netinet netinet6 \
-        netisdn netiso netkey netnatm netsmb \
+        netisdn netiso netkey netmpls netnatm netsmb \
 	nfs opencrypto sys ufs uvm
 
 # interrupt implementation depends on the kernel within the port
Index: sys/arch/amd64/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.277
diff -u -p -r1.277 GENERIC
--- sys/arch/amd64/conf/GENERIC	16 Apr 2010 13:48:28 -0000	1.277
+++ sys/arch/amd64/conf/GENERIC	6 May 2010 11:26:50 -0000
@@ -1114,6 +1114,7 @@ pseudo-device	tap			# virtual Ethernet
 pseudo-device	gre			# generic L3 over IP tunnel
 pseudo-device	gif			# IPv[46] over IPv[46] tunnel (RFC1933)
 #pseudo-device	faith			# IPv[46] tcp relay translation i/f
+pseudo-device	mpls			# MultiProtocol Label Switching
 pseudo-device	stf			# 6to4 IPv6 over IPv4 encapsulation
 pseudo-device	vlan			# IEEE 802.1q encapsulation
 pseudo-device	bridge			# simple inter-network bridging
Index: sys/arch/i386/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC,v
retrieving revision 1.980
diff -u -p -r1.980 GENERIC
--- sys/arch/i386/conf/GENERIC	16 Apr 2010 13:48:32 -0000	1.980
+++ sys/arch/i386/conf/GENERIC	6 May 2010 11:26:52 -0000
@@ -119,12 +119,12 @@ options 	SYSCTL_INCLUDE_DESCR	# Include 
 options 	BUFQ_PRIOCSCAN
 
 # Diagnostic/debugging support options
-#options 	DIAGNOSTIC	# expensive kernel consistency checks
-#options 	DEBUG		# expensive debugging checks/support
-#options 	LOCKDEBUG	# expensive locking checks/support
-#options 	KMEMSTATS	# kernel memory statistics (vmstat -m)
+options 	DIAGNOSTIC	# expensive kernel consistency checks
+options 	DEBUG		# expensive debugging checks/support
+options 	LOCKDEBUG	# expensive locking checks/support
+options 	KMEMSTATS	# kernel memory statistics (vmstat -m)
 options 	DDB		# in-kernel debugger
-#options 	DDB_ONPANIC=1	# see also sysctl(8): `ddb.onpanic'
+options 	DDB_ONPANIC=1	# see also sysctl(8): `ddb.onpanic'
 options 	DDB_HISTORY_SIZE=512	# enable history editing in DDB
 #options 	DDB_VERBOSE_HELP
 #options 	KGDB		# remote debugger
@@ -1528,6 +1528,7 @@ pseudo-device	tun			# network tunneling 
 pseudo-device	gre			# generic L3 over IP tunnel
 pseudo-device	gif			# IPv[46] over IPv[46] tunnel (RFC 1933)
 #pseudo-device	faith			# IPv[46] TCP relay translation i/f
+pseudo-device	mpls			# Multi Protocol Label Switching
 pseudo-device	stf			# 6to4 IPv6 over IPv4 encapsulation
 pseudo-device	vlan			# IEEE 802.1q encapsulation
 pseudo-device	bridge			# simple inter-network bridging
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.988
diff -u -p -r1.988 files
--- sys/conf/files	16 Apr 2010 13:44:49 -0000	1.988
+++ sys/conf/files	6 May 2010 11:26:55 -0000
@@ -1273,6 +1273,7 @@ defpseudo strip:	ifnet
 defpseudo gre:		ifnet
 defpseudo gif:		ifnet
 defpseudo faith:	ifnet
+defpseudo mpls:		ifnet
 defpseudo srt:		ifnet
 defpseudo stf:		ifnet
 defpseudodev tap:	ifnet, ether, arp
@@ -1611,6 +1612,9 @@ file	net/if_hippisubr.c		hippi			needs-f
 file	net/if_ieee1394subr.c		ieee1394
 file	net/if_loop.c			loop			needs-flag
 file	net/if_media.c
+file	net/if_mpls.c			mpls			needs-flag
+file	netmpls/mpls_proto.c		mpls
+file	netmpls/mpls_ttl.c		mpls
 file	net/if_ppp.c			ppp			needs-flag
 file	net/if_srt.c			srt
 file	net/if_stf.c			stf & inet & inet6	needs-flag
Index: sys/net/Makefile
===================================================================
RCS file: /cvsroot/src/sys/net/Makefile,v
retrieving revision 1.27
diff -u -p -r1.27 Makefile
--- sys/net/Makefile	30 May 2009 09:04:35 -0000	1.27
+++ sys/net/Makefile	6 May 2010 11:26:57 -0000
@@ -4,7 +4,7 @@ INCSDIR= /usr/include/net
 
 INCS=	bpf.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \
 	if_atm.h if_bridgevar.h if_dl.h if_ether.h if_etherip.h if_fddi.h if_gif.h \
-	if_gre.h if_hippi.h if_ieee1394.h if_llc.h if_media.h \
+	if_gre.h if_hippi.h if_ieee1394.h if_llc.h if_media.h if_mpls.h \
 	if_pflog.h if_ppp.h if_pppoe.h if_sppp.h if_srt.h if_stf.h \
 	if_tap.h if_token.h if_tun.h if_types.h if_vlanvar.h net_stats.h \
 	netisr.h pfil.h pfkeyv2.h pfvar.h ppp-comp.h ppp_defs.h radix.h \
Index: sys/net/if_ethersubr.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_ethersubr.c,v
retrieving revision 1.177
diff -u -p -r1.177 if_ethersubr.c
--- sys/net/if_ethersubr.c	5 Apr 2010 07:22:23 -0000	1.177
+++ sys/net/if_ethersubr.c	6 May 2010 11:26:58 -0000
@@ -68,6 +68,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_ethersubr
 #include "opt_iso.h"
 #include "opt_ipx.h"
 #include "opt_mbuftrace.h"
+#include "opt_mpls.h"
 #include "opt_gateway.h"
 #include "opt_pfil_hooks.h"
 #include "opt_pppoe.h"
@@ -178,6 +179,11 @@ extern u_char	at_org_code[3];
 extern u_char	aarp_org_code[3];
 #endif /* NETATALK */
 
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif
+
 static struct timeval bigpktppslim_last;
 static int bigpktppslim = 2;	/* XXX */
 static int bigpktpps_count;
@@ -289,6 +295,14 @@ ether_output(struct ifnet *ifp0, struct 
 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
 			mcopy = m_copy(m, 0, (int)M_COPYALL);
 		etype = htons(ETHERTYPE_IP);
+#ifdef MPLS
+		if (rt0 != NULL && rt_gettag(rt0) != NULL) {
+			union mpls_shim msh;
+			msh.s_addr = MPLS_GETSADDR(rt0);
+			if (msh.shim.label != MPLS_LABEL_IMPLNULL)
+				etype = htons(ETHERTYPE_MPLS);
+		}
+#endif
 		break;
 
 	case AF_ARP:
@@ -507,7 +521,6 @@ ether_output(struct ifnet *ifp0, struct 
 	if (ALTQ_IS_ENABLED(&ifp->if_snd))
 		altq_etherclassify(&ifp->if_snd, m, &pktattr);
 #endif
-
 	return ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr));
 
 bad:
@@ -639,7 +652,7 @@ ether_input(struct ifnet *ifp, struct mb
 	/*
 	 * Determine if the packet is within its size limits.
 	 */
-	if (m->m_pkthdr.len >
+	if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len >
 	    ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) {
 		if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count,
 			    bigpktppslim)) {
@@ -904,6 +917,12 @@ ether_input(struct ifnet *ifp, struct mb
 			aarpinput(ifp, m); /* XXX */
 			return;
 #endif /* NETATALK */
+#ifdef MPLS
+		case ETHERTYPE_MPLS:
+			schednetisr(NETISR_MPLS);
+			inq = &mplsintrq;
+			break;
+#endif
 		default:
 			m_freem(m);
 			return;
Index: sys/net/if_gre.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_gre.c,v
retrieving revision 1.143
diff -u -p -r1.143 if_gre.c
--- sys/net/if_gre.c	5 Apr 2010 07:22:23 -0000	1.143
+++ sys/net/if_gre.c	6 May 2010 11:26:58 -0000
@@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1
 #include "opt_atalk.h"
 #include "opt_gre.h"
 #include "opt_inet.h"
+#include "opt_mpls.h"
 
 #include <sys/param.h>
 #include <sys/file.h>
@@ -95,6 +96,11 @@ __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1
 #include <netinet6/in6_var.h>
 #endif
 
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif
+
 #ifdef NETATALK
 #include <netatalk/at.h>
 #include <netatalk/at_var.h>
@@ -899,6 +905,13 @@ gre_input(struct gre_softc *sc, struct m
 		af = AF_INET6;
 		break;
 #endif
+#ifdef MPLS
+	case ETHERTYPE_MPLS:
+		ifq = &mplsintrq;
+		isr = NETISR_MPLS;
+		af = AF_MPLS;
+		break;
+#endif
 	default:	   /* others not yet supported */
 		GRE_DPRINTF(sc, "unhandled ethertype 0x%04x\n",
 		    ntohs(gh->ptype));
@@ -962,6 +975,14 @@ gre_output(struct ifnet *ifp, struct mbu
 		 * encapsulating protocol's ToS to suit.
 		 */
 		etype = htons(ETHERTYPE_IP);
+#ifdef MPLS
+		if (rt != NULL && rt_gettag(rt) != NULL) {
+			union mpls_shim msh;
+			msh.s_addr = MPLS_GETSADDR(rt);
+			if (msh.shim.label != MPLS_LABEL_IMPLNULL)
+				etype = htons(ETHERTYPE_MPLS);
+		}
+#endif
 		break;
 #endif
 #ifdef NETATALK
Index: sys/net/if_mpls.c
===================================================================
RCS file: sys/net/if_mpls.c
diff -N sys/net/if_mpls.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/net/if_mpls.c	6 May 2010 11:26:58 -0000
@@ -0,0 +1,599 @@
+/*	$NetBSD$ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Mihai Chelaru <kefren@NetBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include "opt_inet.h"
+#include "opt_mpls.h"
+
+#include <sys/param.h>
+
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/sysctl.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
+#endif
+
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+
+#include "if_mpls.h"
+
+void mplsattach(int);
+
+static int mpls_clone_create(struct if_clone *, int);
+static int mpls_clone_destroy(struct ifnet *);
+
+static struct if_clone mpls_if_cloner =
+	IF_CLONE_INITIALIZER("mpls", mpls_clone_create, mpls_clone_destroy);
+
+
+static void mpls_input(struct ifnet *, struct mbuf *);
+static int mpls_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
+	struct rtentry *);
+static int mpls_ioctl(struct ifnet *, u_long, void *);
+static int mpls_send_frame(struct mbuf *, struct ifnet *, struct rtentry *);
+static int mpls_lse(struct mbuf *);
+
+#ifdef INET
+static int mpls_unlabel_inet(struct mbuf *);
+static struct mbuf *mpls_label_inet(struct mbuf *, union mpls_shim *);
+#endif
+
+#ifdef INET6
+static int mpls_unlabel_inet6(struct mbuf *);
+static struct mbuf *mpls_label_inet6(struct mbuf *, union mpls_shim *);
+#endif
+
+static struct mbuf *mpls_prepend_shim(struct mbuf *, union mpls_shim *);
+
+extern int mpls_defttl, mpls_mapttl_inet, mpls_mapttl_inet6, mpls_icmp_respond,
+	mpls_forwarding, mpls_accept, mpls_mapprec_inet, mpls_mapclass_inet6;
+
+/* ARGSUSED */
+void
+mplsattach(int count)
+{
+	if_clone_attach(&mpls_if_cloner);
+}
+
+static int
+mpls_clone_create(struct if_clone *ifc, int unit)
+{
+	struct mpls_softc *sc;
+
+	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+
+	if_initname(&sc->sc_if, ifc->ifc_name, unit);
+	sc->sc_if.if_softc = sc;
+	sc->sc_if.if_type = IFT_MPLS;
+	sc->sc_if.if_addrlen = 0;
+	sc->sc_if.if_hdrlen = sizeof(union mpls_shim);
+	sc->sc_if.if_dlt = DLT_NULL;
+	sc->sc_if.if_mtu = 1500;
+	sc->sc_if.if_flags = 0;
+	sc->sc_if.if_input = mpls_input;
+	sc->sc_if.if_output = mpls_output;
+	sc->sc_if.if_ioctl = mpls_ioctl;
+
+	if_attach(&sc->sc_if);
+	if_alloc_sadl(&sc->sc_if);
+	bpf_attach(&sc->sc_if, DLT_NULL, sizeof(uint32_t));
+	return 0;
+}
+
+static int
+mpls_clone_destroy(struct ifnet *ifp)
+{
+	int s;
+
+	bpf_detach(ifp);
+
+	s = splnet();
+	if_detach(ifp);
+	splx(s);
+
+	free(ifp->if_softc, M_DEVBUF);
+	return 0;
+}
+
+static void
+mpls_input(struct ifnet *ifp, struct mbuf *m)
+{
+#if 0
+	/*
+	 * TODO - kefren
+	 * I'd love to unshim the packet, guess family
+	 * and pass it to bpf
+	 */
+	bpf_mtap_af(ifp, AF_MPLS, m);
+#endif
+
+	mpls_lse(m);
+}
+
+void
+mplsintr(void)
+{
+	struct mbuf *m;
+	int s;
+
+	while (!IF_IS_EMPTY(&mplsintrq)) {
+		s = splnet();
+		IF_DEQUEUE(&mplsintrq, m);
+		splx(s);
+
+		if (!m)
+			return;
+
+		if (((m->m_flags & M_PKTHDR) == 0) ||
+		    (m->m_pkthdr.rcvif == 0))
+			panic("mplsintr(): no pkthdr or rcvif");
+
+#ifdef MBUFTRACE
+		m_claimm(m, &mpls_owner);
+#endif
+		mpls_input(m->m_pkthdr.rcvif, m);
+	}
+}
+
+/*
+ * prepend shim and deliver
+ */
+static int
+mpls_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct rtentry *rt)
+{
+	union mpls_shim mh;
+	struct rtentry *rt1;
+	int err;
+
+	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
+		m_freem(m);
+		return ENETDOWN;
+	}
+
+	if (rt_gettag(rt) == NULL) {
+		m_freem(m);
+		return EINVAL;
+	}
+
+	bpf_mtap_af(ifp, dst->sa_family, m);
+
+	mh.s_addr=MPLS_GETSADDR(rt);
+	mh.shim.bos=1;
+	mh.shim.exp=0;
+	mh.shim.ttl=mpls_defttl;
+
+	switch(dst->sa_family) {
+#ifdef INET
+	case AF_INET:
+		m = mpls_label_inet(m, &mh);
+		break;
+#endif
+#ifdef INET6
+	case AF_INET6:
+		m = mpls_label_inet6(m, &mh);
+		break;
+#endif
+	default:
+		m = mpls_prepend_shim(m, &mh);
+		break;
+	}
+
+	if (m == NULL) {
+		IF_DROP(&ifp->if_snd);
+		ifp->if_oerrors++;
+		return ENOBUFS;
+	}
+
+	ifp->if_opackets++;
+	ifp->if_obytes += m->m_pkthdr.len;
+
+	if ((rt1=rtalloc1(rt->rt_gateway, 1)) == NULL) {
+		m_freem(m);
+		return EHOSTUNREACH;
+	}
+
+	err = mpls_send_frame(m, rt1->rt_ifp, rt);
+	RTFREE(rt1);
+	return err;
+}
+
+static int
+mpls_ioctl(struct ifnet *ifp, u_long cmd, void *data)
+{
+	int error = 0, s = splnet();
+	struct ifreq *ifr = data;
+
+	switch(cmd) {
+	case SIOCINITIFADDR:
+		ifp->if_flags |= IFF_UP | IFF_RUNNING;
+		break;
+	case SIOCSIFMTU:
+		if (ifr != NULL && ifr->ifr_mtu < 576) {
+			error = EINVAL;
+			break;
+		}
+		/* FALLTHROUGH */
+	case SIOCGIFMTU:
+		if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
+			error = 0;
+		break;
+	case SIOCSIFFLAGS:
+		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
+			break;
+		if (ifp->if_flags & IFF_UP)
+			ifp->if_flags |= IFF_RUNNING;
+		break;
+	default:
+		error = ifioctl_common(ifp, cmd, data);
+		break;
+	}
+	splx(s);
+	return error;
+}
+
+/*
+ * MPLS Label Switch Engine
+ */
+static int
+mpls_lse(struct mbuf *m)
+{
+	struct sockaddr_mpls dst;
+	union mpls_shim tshim, *htag;
+	struct rtentry *rt = NULL;
+	int error = ENOBUFS;
+
+	if (m->m_len < sizeof(union mpls_shim) &&
+	    (m = m_pullup(m, sizeof(union mpls_shim))) == NULL)
+		goto done;
+
+	dst.smpls_len = sizeof(struct sockaddr_mpls);
+	dst.smpls_family = AF_MPLS;
+	dst.smpls_addr.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr);
+
+	/* Check if we're accepting MPLS Frames */
+	error = EINVAL;
+	if (!mpls_accept)
+		goto done;
+
+	/* TTL decrement */
+	if ((m = mpls_ttl_dec(m)) == NULL)
+		goto done;
+
+	if (dst.smpls_addr.shim.label <= MPLS_LABEL_RESMAX) {
+		/* Don't swap reserved labels */
+		switch (dst.smpls_addr.shim.label) {
+#ifdef INET
+		case MPLS_LABEL_IPV4NULL:
+			/* Pop shim and push mbuf to IP stack */
+			if (dst.smpls_addr.shim.bos)
+				error = mpls_unlabel_inet(m);
+			break;
+#endif
+#ifdef INET6
+		case MPLS_LABEL_IPV6NULL:
+			/* Pop shim and push mbuf to IPv6 stack */
+			if (dst.smpls_addr.shim.bos)
+				error = mpls_unlabel_inet6(m);
+			break;
+#endif
+		case MPLS_LABEL_RTALERT:	/* Yeah, I'm all alerted */
+		case MPLS_LABEL_IMPLNULL:	/* This is logical only */
+		default:			/* Rest are not allowed */
+			break;
+		}
+		goto done;
+	}
+
+	/* Check if we should do MPLS forwarding */
+	error = EHOSTUNREACH;
+	if (!mpls_forwarding)
+		goto done;
+
+	/* Get a route to dst */
+	dst.smpls_addr.shim.ttl =
+	    dst.smpls_addr.shim.bos =
+	    dst.smpls_addr.shim.exp = 0;
+	dst.smpls_addr.s_addr = htonl(dst.smpls_addr.s_addr);
+	if ((rt = rtalloc1((const struct sockaddr*)&dst, 1)) == NULL)
+		goto done;
+
+	/* MPLS packet with no tagged route ? */
+	if ((rt->rt_flags & RTF_GATEWAY) == 0 ||
+	     rt_gettag(rt) == NULL)
+		goto done;
+
+	tshim.s_addr = MPLS_GETSADDR(rt);
+
+	/* Swap labels */
+	if ((m->m_len < sizeof(union mpls_shim)) &&
+	    (m = m_pullup(m, sizeof(union mpls_shim))) == 0) {
+		error = ENOBUFS;
+		goto done;
+	}
+
+	/* Replace only the label */
+	htag = mtod(m, union mpls_shim *);
+	htag->s_addr = ntohl(htag->s_addr);
+	htag->shim.label = tshim.shim.label;
+	htag->s_addr = htonl(htag->s_addr);
+
+	error = mpls_send_frame(m, rt->rt_ifp, rt);
+
+done:
+	if (error != 0 && m != NULL)
+		m_freem(m);
+	if (rt != NULL)
+		RTFREE(rt);
+
+	return error;
+}
+
+static int
+mpls_send_frame(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt)
+{
+	union mpls_shim msh;
+
+	if ((rt->rt_flags & RTF_GATEWAY) == 0)
+		return EHOSTUNREACH;
+
+	rt->rt_use++;
+
+	msh.s_addr = MPLS_GETSADDR(rt);
+	if (msh.shim.label == MPLS_LABEL_IMPLNULL) {
+		m_adj(m, sizeof(union mpls_shim));
+		m->m_pkthdr.csum_flags = 0;
+	}
+
+	switch(ifp->if_type) {
+	/* only these two are supported for now */
+	case IFT_ETHER:
+	case IFT_TUNNEL:
+		return (*ifp->if_output)(ifp, m, rt->rt_gateway, rt);
+	case IFT_LOOP:
+		break;
+	default:
+		return ENETUNREACH;
+	}
+	return 0;
+}
+
+
+
+#ifdef INET
+static int
+mpls_unlabel_inet(struct mbuf *m)
+{
+	int s, iphlen;
+	struct ip *iph;
+	union mpls_shim *ms;
+	struct ifqueue *inq;
+
+	if (mpls_mapttl_inet || mpls_mapprec_inet) {
+
+		/* get shim info */
+		ms = mtod(m, union mpls_shim *);
+		ms->s_addr = ntohl(ms->s_addr);
+
+		/* and get rid of it */
+		m_adj(m, sizeof(union mpls_shim));
+
+		/* get ip header */
+		if (m->m_len < sizeof (struct ip) &&
+		    (m = m_pullup(m, sizeof(struct ip))) == NULL)
+			return ENOBUFS;
+		iph = mtod(m, struct ip *);
+		iphlen = iph->ip_hl << 2;
+
+		/* get it all */
+		if (m->m_len < iphlen) {
+			if ((m = m_pullup(m, iphlen)) == NULL)
+				return ENOBUFS;
+			iph = mtod(m, struct ip *);
+		}
+
+		/* check ipsum */
+		if (in_cksum(m, iphlen) != 0) {
+			m_freem(m);
+			return EINVAL;
+		}
+
+		/* set IP ttl from MPLS ttl */
+		if (mpls_mapttl_inet)
+			iph->ip_ttl = ms->shim.ttl;
+
+		/* set IP Precedence from MPLS Exp */
+		if (mpls_mapprec_inet) {
+			iph->ip_tos = (iph->ip_tos << 3) >> 3;
+			iph->ip_tos |= ms->shim.exp << 5;
+		}
+
+		/* reset ipsum because we modified TTL and TOS */
+		iph->ip_sum = 0;
+		iph->ip_sum = in_cksum(m, iphlen);
+	} else
+		m_adj(m, sizeof(union mpls_shim));
+
+	/* Put it on IP queue */
+	inq = &ipintrq;
+	s = splnet();
+	if (IF_QFULL(inq)) {
+		IF_DROP(inq);
+		splx(s);
+		m_freem(m);
+		return ENOBUFS;
+	}
+	IF_ENQUEUE(inq, m);
+	splx(s);
+	schednetisr(NETISR_IP);
+
+	return 0;
+}
+
+/*
+ * Prepend MPLS label
+ */
+static struct mbuf *
+mpls_label_inet(struct mbuf *m, union mpls_shim *ms)
+{
+	struct ip *iphdr;
+
+	if (mpls_mapttl_inet || mpls_mapprec_inet) {
+		if ((m->m_len < sizeof(struct ip)) &&
+		    (m = m_pullup(m, sizeof(struct ip))) == 0)
+			return NULL;
+		iphdr = mtod(m, struct ip *);
+
+		/* Map TTL */
+		if (mpls_mapttl_inet)
+			ms->shim.ttl = iphdr->ip_ttl;
+
+		/* Copy IP precedence to EXP */
+		if (mpls_mapprec_inet)
+			ms->shim.exp = ((u_int8_t)iphdr->ip_tos) >> 5;
+	}
+
+	if ((m = mpls_prepend_shim(m, ms)) == NULL)
+		return NULL;
+
+	return m;
+}
+
+#endif	/* INET */
+
+#ifdef INET6
+
+static int
+mpls_unlabel_inet6(struct mbuf *m)
+{
+	struct ip6_hdr *ip6hdr;
+	union mpls_shim ms;
+	struct ifqueue *inq;
+	int s;
+
+	/* TODO: mapclass */
+	if (mpls_mapttl_inet6) {
+		ms.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr);
+		m_adj(m, sizeof(union mpls_shim));
+
+		if (m->m_len < sizeof (struct ip6_hdr) &&
+		    (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0)
+			return ENOBUFS;
+		ip6hdr = mtod(m, struct ip6_hdr *);
+
+		/* Because we just decremented this in mpls_lse */
+		ip6hdr->ip6_hlim = ms.shim.ttl + 1;
+	} else
+		m_adj(m, sizeof(union mpls_shim));
+
+	/* Put it back on IPv6 stack */
+	schednetisr(NETISR_IPV6);
+	inq = &ip6intrq;
+	s = splnet();
+	if (IF_QFULL(inq)) {
+		IF_DROP(inq);
+		splx(s);
+		m_freem(m);
+		return ENOBUFS;
+	}
+
+	IF_ENQUEUE(inq, m);
+	splx(s);
+
+	return 0;
+}
+
+static struct mbuf *
+mpls_label_inet6(struct mbuf *m, union mpls_shim *ms)
+{
+	struct ip6_hdr *ip6h;
+
+	if (mpls_mapttl_inet6 || mpls_mapclass_inet6) {
+		if (m->m_len < sizeof(struct ip6_hdr) &&
+		    (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0)
+			return NULL;
+		ip6h = mtod(m, struct ip6_hdr *);
+
+		if (mpls_mapttl_inet6)
+			ms->shim.ttl = ip6h->ip6_hlim;
+
+		if (mpls_mapclass_inet6)
+			ms->shim.exp = ip6h->ip6_vfc << 1 >> 5;
+	}
+
+	if ((m = mpls_prepend_shim(m, ms)) == NULL)
+		return NULL;
+
+	return m;
+}
+
+#endif	/* INET6 */
+
+static struct mbuf *
+mpls_prepend_shim(struct mbuf *m, union mpls_shim *ms) 
+{
+	union mpls_shim *shim; 
+ 
+	M_PREPEND(m, sizeof(*ms), M_DONTWAIT);
+	if (m == NULL)
+		return NULL;
+
+	if (m->m_len < sizeof(union mpls_shim) &&
+	    (m = m_pullup(m, sizeof(union mpls_shim))) == 0)
+		return NULL;
+
+	shim = mtod(m, union mpls_shim *);
+
+	memcpy(shim, ms, sizeof(*shim));
+	shim->s_addr = htonl(shim->s_addr);
+
+	return m;
+}
Index: sys/net/if_mpls.h
===================================================================
RCS file: sys/net/if_mpls.h
diff -N sys/net/if_mpls.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/net/if_mpls.h	6 May 2010 11:26:58 -0000
@@ -0,0 +1,41 @@
+/*	$NetBSD$ */
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Mihai Chelaru <kefren@NetBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NET_IF_MPLS_H_
+#define _NET_IF_MPLS_H_
+
+
+struct mpls_softc {
+	struct ifnet	sc_if;
+};
+
+
+#endif	/* _NET_IF_MPLS_H_ */
Index: sys/net/netisr.h
===================================================================
RCS file: /cvsroot/src/sys/net/netisr.h,v
retrieving revision 1.39
diff -u -p -r1.39 netisr.h
--- sys/net/netisr.h	12 Nov 2008 12:36:28 -0000	1.39
+++ sys/net/netisr.h	6 May 2010 11:26:58 -0000
@@ -52,6 +52,7 @@
 #include "opt_inet.h"
 #include "opt_atalk.h"
 #include "opt_iso.h"
+#include "opt_mpls.h"
 #include "opt_natm.h"
 #include "arp.h"
 #endif /* defined(_KERNEL_OPT) */
@@ -85,6 +86,9 @@
 #include <netiso/iso.h>
 #include <netiso/clnp.h>
 #endif
+#ifdef MPLS
+#include <netmpls/mpls_var.h>
+#endif
 #ifdef NATM
 #include <netnatm/natm.h>
 #endif
@@ -112,6 +116,7 @@
 #define	NETISR_ISDN	26		/* same as AF_E164 */
 #define	NETISR_NATM	27		/* same as AF_NATM */
 #define	NETISR_ARP	28		/* same as AF_ARP */
+#define NETISR_MPLS	33		/* same as AF_MPLS */
 #define	NETISR_MAX	AF_MAX
 
 #if !defined(_LOCORE) && defined(_KERNEL)
Index: sys/net/netisr_dispatch.h
===================================================================
RCS file: /cvsroot/src/sys/net/netisr_dispatch.h,v
retrieving revision 1.14
diff -u -p -r1.14 netisr_dispatch.h
--- sys/net/netisr_dispatch.h	14 Jul 2007 21:02:42 -0000	1.14
+++ sys/net/netisr_dispatch.h	6 May 2010 11:26:58 -0000
@@ -42,6 +42,9 @@
 #ifdef ISO
 	DONETISR(NETISR_ISO,clnlintr);
 #endif
+#ifdef MPLS
+	DONETISR(NETISR_MPLS,mplsintr);
+#endif
 #ifdef NATM
 	DONETISR(NETISR_NATM,natmintr);
 #endif
Index: sys/net/route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.122
diff -u -p -r1.122 route.c
--- sys/net/route.c	2 May 2010 19:17:56 -0000	1.122
+++ sys/net/route.c	6 May 2010 11:26:58 -0000
@@ -804,6 +804,8 @@ rtrequest1(int req, struct rt_addrinfo *
 			RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
 		}
 		rt_set_ifa(rt, ifa);
+		if (info->rti_info[RTAX_TAG] != NULL)
+			rt_settag(rt, info->rti_info[RTAX_TAG]);
 		RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
 		if (info->rti_info[RTAX_IFP] != NULL &&
 		    (ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP])) != NULL &&
@@ -1413,3 +1415,20 @@ rt_walktree(sa_family_t family, int (*f)
 
 	return rn_walktree(rnh, rt_walktree_visitor, &rw);
 }
+
+const struct sockaddr *
+rt_settag(struct rtentry *rt, const struct sockaddr *tag)
+{
+	if (rt->rt_tag != tag) {
+		if (rt->rt_tag != NULL)
+			sockaddr_free(rt->rt_tag);
+		rt->rt_tag = sockaddr_dup(tag, M_NOWAIT);
+	}
+	return rt->rt_tag; 
+}
+
+struct sockaddr *
+rt_gettag(struct rtentry *rt)
+{
+	return rt->rt_tag;
+}
Index: sys/net/route.h
===================================================================
RCS file: /cvsroot/src/sys/net/route.h,v
retrieving revision 1.74
diff -u -p -r1.74 route.h
--- sys/net/route.h	3 Nov 2009 00:30:31 -0000	1.74
+++ sys/net/route.h	6 May 2010 11:26:58 -0000
@@ -126,7 +126,8 @@ struct rtentry {
 	struct	rtentry *rt_gwroute;	/* implied entry for gatewayed routes */
 	LIST_HEAD(, rttimer) rt_timer;  /* queue of timeouts for misc funcs */
 	struct	rtentry *rt_parent;	/* parent of cloned route */
-	struct sockaddr *_rt_key;
+	struct	sockaddr *_rt_key;
+	struct	sockaddr *rt_tag;	/* route tagging info */
 };
 
 static inline const struct sockaddr *
@@ -243,6 +244,7 @@ struct rt_msghdr {
 #define RTA_IFA		0x20	/* interface addr sockaddr present */
 #define RTA_AUTHOR	0x40	/* sockaddr for author of redirect */
 #define RTA_BRD		0x80	/* for NEWADDR, broadcast or p-p dest addr */
+#define RTA_TAG		0x100	/* route tag */
 
 /*
  * Index offsets for sockaddr array for alternate internal encoding.
@@ -255,7 +257,8 @@ struct rt_msghdr {
 #define RTAX_IFA	5	/* interface addr sockaddr present */
 #define RTAX_AUTHOR	6	/* sockaddr for author of redirect */
 #define RTAX_BRD	7	/* for NEWADDR, broadcast or p-p dest addr */
-#define RTAX_MAX	8	/* size of array to allocate */
+#define RTAX_TAG	8	/* route tag */
+#define RTAX_MAX	9	/* size of array to allocate */
 
 #define RT_ROUNDUP(a) \
 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
@@ -276,6 +279,7 @@ struct route_cb {
 	int	ipx_count;
 	int	ns_count;
 	int	iso_count;
+	int	mpls_count;
 	int	any_count;
 };
 
@@ -383,6 +387,9 @@ int	 rtrequest1(int, struct rt_addrinfo 
 struct ifaddr	*rt_get_ifa(struct rtentry *);
 void	rt_replace_ifa(struct rtentry *, struct ifaddr *);
 
+const struct sockaddr *rt_settag(struct rtentry *, const struct sockaddr *);
+struct sockaddr *rt_gettag(struct rtentry *);
+
 static inline void
 rt_destroy(struct rtentry *rt)
 {
@@ -390,7 +397,9 @@ rt_destroy(struct rtentry *rt)
 		sockaddr_free(rt->_rt_key);
 	if (rt->rt_gateway != NULL)
 		sockaddr_free(rt->rt_gateway);
-	rt->_rt_key = rt->rt_gateway = NULL;
+	if (rt_gettag(rt) != NULL)
+		sockaddr_free(rt_gettag(rt));
+	rt->_rt_key = rt->rt_gateway = rt->rt_tag = NULL;
 }
 
 static inline const struct sockaddr *
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvsroot/src/sys/net/rtsock.c,v
retrieving revision 1.128
diff -u -p -r1.128 rtsock.c
--- sys/net/rtsock.c	2 May 2010 19:17:56 -0000	1.128
+++ sys/net/rtsock.c	6 May 2010 11:26:59 -0000
@@ -64,6 +64,7 @@
 __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.128 2010/05/02 19:17:56 kefren Exp $");
 
 #include "opt_inet.h"
+#include "opt_mpls.h"
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
 #endif
@@ -87,6 +88,8 @@ __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1
 #include <net/route.h>
 #include <net/raw_cb.h>
 
+#include <netmpls/mpls.h>
+
 #if defined(COMPAT_14) || defined(COMPAT_50)
 #include <compat/net/if.h>
 #endif
@@ -128,12 +131,15 @@ rt_adjustcount(int af, int cnt)
 	case AF_IPX:
 		route_cb.ipx_count += cnt;
 		return;
-	case AF_NS:
-		route_cb.ns_count += cnt;
-		return;
 	case AF_ISO:
 		route_cb.iso_count += cnt;
 		return;
+	case AF_MPLS:
+		route_cb.mpls_count += cnt;
+		return;
+	case AF_NS:
+		route_cb.ns_count += cnt;
+		return;
 	}
 }
 
@@ -339,6 +345,7 @@ route_output(struct mbuf *m, ...)
 			info.rti_info[RTAX_DST] = rt_getkey(rt);
 			info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
 			info.rti_info[RTAX_NETMASK] = rt_mask(rt);
+			info.rti_info[RTAX_TAG] = (struct sockaddr*)rt_gettag(rt);
 			if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0)
 				;
 			else if ((ifp = rt->rt_ifp) != NULL) {
@@ -403,6 +410,8 @@ route_output(struct mbuf *m, ...)
 			if (info.rti_info[RTAX_GATEWAY] &&
 			    rt_setgate(rt, info.rti_info[RTAX_GATEWAY]))
 				senderr(EDQUOT);
+			if (info.rti_info[RTAX_TAG])
+				rt_settag(rt, info.rti_info[RTAX_TAG]);
 			/* new gateway could require new ifaddr, ifp;
 			   flags may also be different; ifp may be specified
 			   by ll sockaddr when protocol address is ambiguous */
Index: sys/netinet/ip_icmp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.122
diff -u -p -r1.122 ip_icmp.c
--- sys/netinet/ip_icmp.c	7 Dec 2009 18:47:24 -0000	1.122
+++ sys/netinet/ip_icmp.c	6 May 2010 11:26:59 -0000
@@ -177,7 +177,7 @@ static struct rttimer_queue *icmp_redire
 static void icmp_mtudisc_timeout(struct rtentry *, struct rttimer *);
 static void icmp_redirect_timeout(struct rtentry *, struct rttimer *);
 
-static int icmp_ratelimit(const struct in_addr *, const int, const int);
+int icmp_ratelimit(const struct in_addr *, const int, const int);
 
 static void sysctl_netinet_icmp_setup(struct sysctllog **);
 
@@ -1251,7 +1251,7 @@ icmp_redirect_timeout(struct rtentry *rt
  *
  * XXX per-destination/type check necessary?
  */
-static int
+int
 icmp_ratelimit(const struct in_addr *dst, const int type,
     const int code)
 {
Index: sys/netinet/ip_icmp.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_icmp.h,v
retrieving revision 1.25
diff -u -p -r1.25 ip_icmp.h
--- sys/netinet/ip_icmp.h	8 Sep 2008 23:36:55 -0000	1.25
+++ sys/netinet/ip_icmp.h	6 May 2010 11:26:59 -0000
@@ -184,6 +184,7 @@ void	icmp_send(struct mbuf *, struct mbu
 int	icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 
 void	icmp_mtudisc_callback_register(void (*)(struct in_addr));
+int	icmp_ratelimit(const struct in_addr *, const int, const int);
 #endif
 
 
Index: sys/rump/net/lib/libnet/opt/opt_mpls.h
===================================================================
RCS file: sys/rump/net/lib/libnet/opt/opt_mpls.h
diff -N sys/rump/net/lib/libnet/opt/opt_mpls.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/rump/net/lib/libnet/opt/opt_mpls.h	6 May 2010 11:26:59 -0000
@@ -0,0 +1,3 @@
+/* $NetBSD:$ */
+
+/* XXX: dummy */
Index: sys/sys/socket.h
===================================================================
RCS file: /cvsroot/src/sys/sys/socket.h,v
retrieving revision 1.97
diff -u -p -r1.97 socket.h
--- sys/sys/socket.h	5 Dec 2009 20:11:18 -0000	1.97
+++ sys/sys/socket.h	6 May 2010 11:27:00 -0000
@@ -210,8 +210,8 @@ struct	accept_filter_arg {
 #endif
 #define AF_BLUETOOTH	31		/* Bluetooth: HCI, SCO, L2CAP, RFCOMM */
 #define	AF_IEEE80211	32		/* IEEE80211 */
-
-#define	AF_MAX		33
+#define	AF_MPLS		33		/* MultiProtocol Label Switching */
+#define	AF_MAX		34
 
 /*
  * Structure used by kernel to store most
@@ -300,6 +300,7 @@ struct sockaddr_storage {
 #define PF_KEY 		pseudo_AF_KEY	/* like PF_ROUTE, only for key mgmt */
 #endif
 #define PF_BLUETOOTH	AF_BLUETOOTH
+#define	PF_MPLS		AF_MPLS
 
 #define	PF_MAX		AF_MAX
 
Index: usr.bin/netstat/show.c
===================================================================
RCS file: /cvsroot/src/usr.bin/netstat/show.c,v
retrieving revision 1.8
diff -u -p -r1.8 show.c
--- usr.bin/netstat/show.c	13 Sep 2009 02:53:17 -0000	1.8
+++ usr.bin/netstat/show.c	6 May 2010 11:27:01 -0000
@@ -44,6 +44,7 @@
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
+#include <netmpls/mpls.h>
 #include <arpa/inet.h>
 
 #include <err.h>
@@ -59,6 +60,7 @@
 
 char	*any_ntoa(const struct sockaddr *);
 char	*link_print(struct sockaddr *);
+char	*mpls_ntoa(const struct sockaddr *); 
 
 #define ROUNDUP(a) \
 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
@@ -288,6 +290,9 @@ pr_family(int paf)
 	case AF_APPLETALK:
 		afname = "AppleTalk";
 		break;
+	case AF_MPLS:
+		afname = "MPLS";
+		break;
 	default:
 		afname = NULL;
 		break;
@@ -420,6 +425,9 @@ routename(struct sockaddr *sa)
 	case AF_LINK:
 		return (link_print(sa));
 
+	case AF_MPLS:
+		return mpls_ntoa(sa);
+
 #if 0 /* XXX-elad */
 	case AF_UNSPEC:
 		if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) {
@@ -684,3 +692,19 @@ link_print(struct sockaddr *sa)
 		return (link_ntoa(sdl));
 	}
 }
+
+char *
+mpls_ntoa(const struct sockaddr *sa)
+{
+	static char obuf[100];
+	const struct sockaddr_mpls *sm;
+	union mpls_shim ms;
+
+	sm = (const struct sockaddr_mpls*)sa;
+	ms.s_addr = ntohl(sm->smpls_addr.s_addr);
+
+	snprintf(obuf, sizeof(obuf), "%u",
+	     ms.shim.label);
+
+	return obuf;
+}
Index: usr.sbin/Makefile
===================================================================
RCS file: /cvsroot/src/usr.sbin/Makefile,v
retrieving revision 1.243
diff -u -p -r1.243 Makefile
--- usr.sbin/Makefile	11 Oct 2009 08:57:54 -0000	1.243
+++ usr.sbin/Makefile	6 May 2010 11:27:01 -0000
@@ -14,7 +14,7 @@ SUBDIR=	ac accton acpitools altq apm apm
 	kgmon lastlogin link lmcconfig lockstat lpr mailwrapper makefs \
 	map-mbone mdconfig memswitch mlxctl mmcformat mopd mountd moused \
 	mrinfo mrouted mscdlabel mtrace \
-	mtree ndbootd ndiscvt netgroup_mkdb nfsd ntp ofctl paxctl pcictl \
+	mtree ndbootd ndiscvt netgroup_mkdb nfsd ntp ldpd ofctl paxctl pcictl \
 	pppd psrset pstat pwd_mkdb postinstall powerd puffs quot quotacheck \
 	quotaon rarpd rbootd rdate \
 	repquota rmt rpc.bootparamd rpc.lockd rpc.pcnfsd \
