Index: Makefile
===================================================================
RCS file: /usr/cvs/src/sys/Makefile,v
retrieving revision 1.57
diff -u -p -r1.57 Makefile
--- Makefile	11 Dec 2005 12:16:03 -0000	1.57
+++ Makefile	25 May 2006 15:08:08 -0000
@@ -2,7 +2,7 @@
 
 SUBDIR=	altq arch compat crypto dev fs miscfs \
 	net net80211 netatalk netccitt netipsec netinet netinet6 \
-        netisdn netiso netkey netnatm netns netsmb \
+        netisdn netiso netkey netmpls netnatm netns netsmb \
 	nfs opencrypto sys ufs uvm
 
 .if (${MACHINE} != "evbppc")
Index: conf/files
===================================================================
RCS file: /usr/cvs/src/sys/conf/files,v
retrieving revision 1.775
diff -u -p -r1.775 files
--- conf/files	18 May 2006 09:05:51 -0000	1.775
+++ conf/files	25 May 2006 15:08:49 -0000
@@ -149,6 +149,7 @@ include "netiso/files.netiso"
 include "netnatm/files.netnatm"
 include "netns/files.netns"
 include "netsmb/files.netsmb"
+include "netmpls/files.netmpls"
 include "net/files.pf"
 
 defflag				IPX		# IPX network stack
Index: kern/uipc_mbuf.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/uipc_mbuf.c,v
retrieving revision 1.110
diff -u -p -r1.110 uipc_mbuf.c
--- kern/uipc_mbuf.c	15 Apr 2006 04:58:14 -0000	1.110
+++ kern/uipc_mbuf.c	25 May 2006 16:11:36 -0000
@@ -1,5 +1,34 @@
 /*	$NetBSD: uipc_mbuf.c,v 1.110 2006/04/15 04:58:14 christos Exp $	*/
 
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
 /*-
  * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -939,6 +968,9 @@ m_split0(struct mbuf *m0, int len0, int 
 			return (NULL);
 		MCLAIM(m, m0->m_owner);
 		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
+#ifdef MPLS
+		n->m_pkthdr.fecid = m0->m_pkthdr.fecid;
+#endif /* MPLS */
 		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
 		len_save = m0->m_pkthdr.len;
 		m0->m_pkthdr.len = len0;
@@ -1009,6 +1041,9 @@ m_devget(char *buf, int totlen, int off0
 		return (NULL);
 	m->m_pkthdr.rcvif = ifp;
 	m->m_pkthdr.len = totlen;
+#ifdef MPLS
+	m->m_pkthdr.fecid = 0;
+#endif	/* MPLS */
 	m->m_len = MHLEN;
 
 	while (totlen > 0) {
Index: net/if_atmsubr.c
===================================================================
RCS file: /usr/cvs/src/sys/net/if_atmsubr.c,v
retrieving revision 1.37
diff -u -p -r1.37 if_atmsubr.c
--- net/if_atmsubr.c	11 Dec 2005 23:05:24 -0000	1.37
+++ net/if_atmsubr.c	25 May 2006 16:12:37 -0000
@@ -1,6 +1,35 @@
 /*      $NetBSD: if_atmsubr.c,v 1.37 2005/12/11 23:05:24 thorpej Exp $       */
 
 /*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+/*
  *
  * Copyright (c) 1996 Charles D. Cranor and Washington University.
  * All rights reserved.
@@ -42,6 +71,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_atmsubr.c
 #include "opt_inet.h"
 #include "opt_gateway.h"
 #include "opt_natm.h"
+#include "opt_mpls.h"
 
 #include "bpfilter.h"
 
@@ -80,6 +110,11 @@ __KERNEL_RCSID(0, "$NetBSD: if_atmsubr.c
 #include <netnatm/natm.h>
 #endif
 
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif	/* MPLS */
+
 #define senderr(e) { error = (e); goto bad;}
 
 /*
@@ -181,6 +216,24 @@ atm_output(struct ifnet *ifp, struct mbu
 			break;
 #endif
 
+#ifdef MPLS
+		case AF_MPLS:
+			if (m->m_flags & (M_BCAST | M_MCAST))
+				etype = ETHERTYPE_MPLS_MCAST;
+			else
+				etype = ETHERTYPE_MPLS;
+#ifdef ATM_PVCEXT
+			if (ifp->if_flags & IFF_POINTOPOINT) {
+				/* pvc subinterface */
+				struct pvcsif *pvcsif = (struct pvcsif *)ifp;
+				atmdst = pvcsif->sif_aph;
+				break;
+			}
+#endif
+			senderr(EHOSTUNREACH);
+			break;
+#endif	/* MPLS */
+
 		case AF_UNSPEC:
 			/*
 			 * XXX: bpfwrite or output from a pvc shadow if.
@@ -301,7 +354,15 @@ atm_input(struct ifnet *ifp, struct atm_
 		  inq = &ip6intrq;
 		  break;
 #endif
-	  default:
+#ifdef MPLS
+	case ETHERTYPE_MPLS:
+	case ETHERTYPE_MPLS_MCAST:
+		/* this may be done with a NETISR as well */
+		mpls_shim_input(ifp, m);
+		return;
+#endif /* MPLS */
+
+	default:
 	      m_freem(m);
 	      return;
 	  }
Index: net/if_ethersubr.c
===================================================================
RCS file: /usr/cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.133
diff -u -p -r1.133 if_ethersubr.c
--- net/if_ethersubr.c	18 May 2006 09:05:51 -0000	1.133
+++ net/if_ethersubr.c	25 May 2006 18:32:10 -0000
@@ -1,6 +1,35 @@
 /*	$NetBSD: if_ethersubr.c,v 1.133 2006/05/18 09:05:51 liamjfoy Exp $	*/
 
 /*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+/*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  * All rights reserved.
  *
@@ -69,8 +98,10 @@ __KERNEL_RCSID(0, "$NetBSD: if_ethersubr
 #include "opt_llc.h"
 #include "opt_iso.h"
 #include "opt_ipx.h"
+#include "opt_mpls.h"
 #include "opt_mbuftrace.h"
 #include "opt_ns.h"
+#include "opt_mpls.h"
 #include "opt_gateway.h"
 #include "opt_pfil_hooks.h"
 #include "vlan.h"
@@ -189,6 +220,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 /* MPLS */
+
 static struct timeval bigpktppslim_last;
 static int bigpktppslim = 2;	/* XXX */
 static int bigpktpps_count;
@@ -486,6 +522,42 @@ ether_output(struct ifnet *ifp0, struct 
 #endif /* LLC_DEBUG */
 		} break;
 #endif /* LLC */
+#ifdef MPLS
+		case AF_MPLS:
+		{
+			struct sockaddr *sa;
+  
+			if (rt && rt->rt_ifa)
+				sa = (struct sockaddr *)rt->rt_ifa->ifa_dstaddr;
+			else
+				senderr(EHOSTUNREACH);
+
+			if (sa == NULL || sa->sa_len < 2)
+				senderr(EHOSTUNREACH);
+
+			switch (sa->sa_family) {
+			case AF_LINK:
+				if (satosdl(sa)->sdl_alen < sizeof(edst))
+					senderr(EHOSTUNREACH);
+				memcpy(edst, LLADDR(satosdl(sa)),
+				    sizeof(edst));
+				break;
+
+			case AF_INET:
+				if (!arpresolve(ifp, 0, m, sa, edst))
+					return 0;     /* if not yet resolved */
+				break;
+			default:
+				senderr(EHOSTUNREACH);
+			}
+
+			if (m->m_flags & (M_BCAST | M_MCAST))
+				etype = htons(ETHERTYPE_MPLS_MCAST);
+			else
+				etype = htons(ETHERTYPE_MPLS);
+		}
+		break;
+#endif /* MPLS */
 
 	case pseudo_AF_HDRCMPLT:
 		hdrcmplt = 1;
@@ -713,6 +785,9 @@ ether_input(struct ifnet *ifp, struct mb
 	/*
 	 * Determine if the packet is within its size limits.
 	 */
+#ifdef MPLS
+	if (etype != ETHERTYPE_MPLS && etype != ETHERTYPE_MPLS_MCAST)
+#endif
 	if (m->m_pkthdr.len >
 	    ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) {
 		if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count,
@@ -984,6 +1059,14 @@ ether_input(struct ifnet *ifp, struct mb
                 aarpinput(ifp, m); /* XXX */
                 return;
 #endif /* NETATALK */
+#ifdef MPLS
+	case ETHERTYPE_MPLS:
+	case ETHERTYPE_MPLS_MCAST:
+		/* this may be done with a NETISR as well */
+		mpls_shim_input(ifp, m);
+		return;
+#endif /* MPLS */
+
 	default:
 #if defined (ISO) || defined (LLC) || defined (NETATALK)
 		if (etype > ETHERMTU)
Index: net/route.h
===================================================================
RCS file: /usr/cvs/src/sys/net/route.h,v
retrieving revision 1.43
diff -u -p -r1.43 route.h
--- net/route.h	11 Dec 2005 12:24:52 -0000	1.43
+++ net/route.h	25 May 2006 16:13:06 -0000
@@ -1,6 +1,35 @@
 /*	$NetBSD: route.h,v 1.43 2005/12/11 12:24:52 christos Exp $	*/
 
 /*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+/*
  * Copyright (c) 1980, 1986, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -239,6 +268,7 @@ struct route_cb {
 	int	ipx_count;
 	int	ns_count;
 	int	iso_count;
+	int	mpls_count;
 	int	any_count;
 };
 
Index: net/rtsock.c
===================================================================
RCS file: /usr/cvs/src/sys/net/rtsock.c,v
retrieving revision 1.84
diff -u -p -r1.84 rtsock.c
--- net/rtsock.c	14 May 2006 21:19:33 -0000	1.84
+++ net/rtsock.c	25 May 2006 16:13:23 -0000
@@ -1,6 +1,35 @@
 /*	$NetBSD: rtsock.c,v 1.84 2006/05/14 21:19:33 elad Exp $	*/
 
 /*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+/*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  * All rights reserved.
  *
@@ -64,6 +93,7 @@
 __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.84 2006/05/14 21:19:33 elad Exp $");
 
 #include "opt_inet.h"
+#include "opt_mpls.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -80,6 +110,10 @@ __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1
 #include <net/route.h>
 #include <net/raw_cb.h>
 
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#endif /* MPLS */
+
 #include <machine/stdarg.h>
 
 DOMAIN_DEFINE(routedomain);	/* forward declare and add to link set */
@@ -140,6 +174,11 @@ rt_adjustcount(int af, int cnt)
 	case AF_ISO:
 		route_cb.iso_count += cnt;
 		return;
+#ifdef MPLS
+	case AF_MPLS:
+		route_cb.mpls_count += cnt;
+		return;
+#endif /* MPLS */
 	}
 }
 
Index: netinet/ip_input.c
===================================================================
RCS file: /usr/cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.226
diff -u -p -r1.226 ip_input.c
--- netinet/ip_input.c	8 May 2006 18:50:12 -0000	1.226
+++ netinet/ip_input.c	25 May 2006 15:35:05 -0000
@@ -104,6 +104,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v
 #include "opt_gateway.h"
 #include "opt_pfil_hooks.h"
 #include "opt_ipsec.h"
+#include "opt_mpls.h"
 #include "opt_mrouting.h"
 #include "opt_mbuftrace.h"
 #include "opt_inet_csum.h"
@@ -619,12 +620,17 @@ ip_input(struct mbuf *m)
 	/* ipflow (IP fast forwarding) is not compatible with IPsec. */
 	m->m_flags &= ~M_CANFASTFWD;
 #else
+#ifdef MPLS
+	/* ipflow (IP fast fowarding) is not compatible with MPLS. */
+	m->m_flags &= ~M_CANFASTFWD;
+#else
 	/*
 	 * Assume that we can create a fast-forward IP flow entry
 	 * based on this packet.
 	 */
 	m->m_flags |= M_CANFASTFWD;
 #endif
+#endif
 
 #ifdef PFIL_HOOKS
 	/*
Index: netinet/ip_output.c
===================================================================
RCS file: /usr/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.162
diff -u -p -r1.162 ip_output.c
--- netinet/ip_output.c	15 May 2006 00:05:17 -0000	1.162
+++ netinet/ip_output.c	25 May 2006 15:56:52 -0000
@@ -1,6 +1,35 @@
 /*	$NetBSD: ip_output.c,v 1.162 2006/05/15 00:05:17 christos Exp $	*/
 
 /*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+/*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  * All rights reserved.
  *
@@ -104,6 +133,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_output.c,
 #include "opt_inet.h"
 #include "opt_ipsec.h"
 #include "opt_mrouting.h"
+#include "opt_mpls.h"
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -143,6 +173,11 @@ __KERNEL_RCSID(0, "$NetBSD: ip_output.c,
 #include <netkey/key_debug.h>
 #endif /*IPSEC*/
 
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif /* MPLS */
+
 #ifdef FAST_IPSEC
 #include <netipsec/ipsec.h>
 #include <netipsec/key.h>
@@ -365,6 +400,13 @@ ip_output(struct mbuf *m0, ...)
 		ro->ro_rt->rt_use++;
 		if (ro->ro_rt->rt_flags & RTF_GATEWAY)
 			dst = satosin(ro->ro_rt->rt_gateway);
+#ifdef MPLS
+		/* set fec information by SMART FEC CF */
+		if (m->m_pkthdr.fecid == 0) {
+			if (dst && dst->sin_family == AF_MPLS)
+				m->m_pkthdr.fecid = satosmpls(dst)->smpls_label;
+		}
+#endif	/* MPLS */
 	}
 	if (IN_MULTICAST(ip->ip_dst.s_addr) ||
 	    (ip->ip_dst.s_addr == INADDR_BROADCAST)) {
@@ -494,7 +536,11 @@ ip_output(struct mbuf *m0, ...)
 	 * and verify user is allowed to send
 	 * such a packet.
 	 */
-	if (in_broadcast(dst->sin_addr, ifp)) {
+	if (
+#ifdef MPLS
+	    dst->sin_family == AF_INET &&
+#endif	/* MPLS */
+	    in_broadcast(dst->sin_addr, ifp)) {
 		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
 			error = EADDRNOTAVAIL;
 			goto bad;
@@ -892,16 +938,25 @@ spd_done:
 		/* clean ipsec history once it goes out of the node */
 		ipsec_delaux(m);
 #endif
-
-		if (__predict_true(
-		    (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) == 0 ||
-		    (ifp->if_capenable & IFCAP_TSOv4) != 0)) {
-			error =
-			    (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);
-		} else {
-			error =
-			    ip_tso_output(ifp, m, sintosa(dst), ro->ro_rt);
+#ifdef MPLS
+		if (m->m_pkthdr.fecid)
+			error = mpls_ip_output(ifp, m, sintosa(dst), ro->ro_rt);
+		else {
+#endif
+			if (__predict_true(
+			    (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) == 0 ||
+			    (ifp->if_capenable & IFCAP_TSOv4) != 0)) {
+				error =
+				    (*ifp->if_output)(ifp, m, sintosa(dst),
+					ro->ro_rt);
+			} else {
+				error =
+				    ip_tso_output(ifp, m, sintosa(dst),
+					ro->ro_rt);
+			}
+#ifdef MPLS
 		}
+#endif
 		goto done;
 	}
 
@@ -963,7 +1018,17 @@ spd_done:
 				    ro, flags, imo, so, mtu_p);
 			} else
 #endif /* IPSEC_NAT_T */
+
+#ifdef MPLS
+                        /* XXX ifp may change in MPLS routing. XXX */
+                        /* XXX queue length check in upperline maybe bad XXX */
+                        if (m->m_pkthdr.fecid)
+                                error = mpls_ip_output(ifp, m, sintosa(dst),
+                                    ro->ro_rt);
+                        else
+#endif /* MPLS */
 			{
+
 				KASSERT((m->m_pkthdr.csum_flags &
 				    (M_CSUM_UDPv4 | M_CSUM_TCPv4)) == 0);
 				error = (*ifp->if_output)(ifp, m, sintosa(dst),
@@ -1070,6 +1135,9 @@ ip_fragment(struct mbuf *m, struct ifnet
 		}
 		m->m_pkthdr.len = mhlen + len;
 		m->m_pkthdr.rcvif = (struct ifnet *)0;
+#ifdef MPLS
+		m->m_pkthdr.fecid = m0->m_pkthdr.fecid;
+#endif
 		mhip->ip_sum = 0;
 		if (sw_csum & M_CSUM_IPv4) {
 			mhip->ip_sum = in_cksum(m, mhlen);
Index: netinet6/ip6_forward.c
===================================================================
RCS file: /usr/cvs/src/sys/netinet6/ip6_forward.c,v
retrieving revision 1.47
diff -u -p -r1.47 ip6_forward.c
--- netinet6/ip6_forward.c	21 Jan 2006 00:15:36 -0000	1.47
+++ netinet6/ip6_forward.c	25 May 2006 15:45:50 -0000
@@ -34,6 +34,7 @@
 __KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.47 2006/01/21 00:15:36 rpaulo Exp $");
 
 #include "opt_ipsec.h"
+#include "opt_mpls.h"
 #include "opt_pfil_hooks.h"
 
 #include <sys/param.h>
@@ -69,6 +70,11 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_forward.
 #include <net/pfil.h>
 #endif
 
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif /* MPLS */
+
 #include <net/net_osdep.h>
 
 struct	route_in6 ip6_forward_rt;
@@ -386,6 +392,16 @@ ip6_forward(m, srcrt)
     skip_routing:;
 #endif /* IPSEC */
 
+#ifdef MPLS
+	/* set fec information by SMART FEC CF */
+	if (m->m_pkthdr.fecid == 0) {
+		if (rt && rt->rt_flags & RTF_GATEWAY && rt->rt_gateway
+		    && rt->rt_gateway->sa_family == AF_MPLS)
+			m->m_pkthdr.fecid =
+			    satosmpls(rt->rt_gateway)->smpls_label;
+	}
+#endif  /* MPLS */
+
 	/*
 	 * Source scope check: if a packet can't be delivered to its
 	 * destination for the reason that the destination is beyond the scope
@@ -591,6 +607,13 @@ ip6_forward(m, srcrt)
 	ip6 = mtod(m, struct ip6_hdr *);
 #endif /* PFIL_HOOKS */
 
+#ifdef MPLS
+	if (m->m_pkthdr.fecid)
+		error = mpls_ip6_output(rt->rt_ifp, m,
+					(struct sockaddr *)dst,
+					ip6_forward_rt.ro_rt);
+	else
+#endif  /* MPLS */
 	error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
 	if (error) {
 		in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
Index: netinet6/ip6_output.c
===================================================================
RCS file: /usr/cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.98
diff -u -p -r1.98 ip6_output.c
--- netinet6/ip6_output.c	14 May 2006 21:19:34 -0000	1.98
+++ netinet6/ip6_output.c	25 May 2006 15:50:20 -0000
@@ -68,6 +68,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_output.c
 #include "opt_inet6.h"
 #include "opt_ipsec.h"
 #include "opt_pfil_hooks.h"
+#include "opt_mpls.h"
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -102,6 +103,11 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_output.c
 #include <netkey/key.h>
 #endif /* IPSEC */
 
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif /* MPLS */
+
 #include <net/net_osdep.h>
 
 #ifdef PFIL_HOOKS
@@ -546,6 +552,14 @@ skip_ipsec2:;
 			ip6->ip6_hlim = ip6_defmcasthlim;
 	}
 
+#ifdef MPLS
+	/* set fec information by SMART FEC CF */
+	if (m->m_pkthdr.fecid == 0) {
+		if (dst && dst->sin6_family == AF_MPLS)
+			m->m_pkthdr.fecid = satosmpls(dst)->smpls_label;
+	}
+#endif /* MPLS */
+
 #ifdef IPSEC
 	if (needipsec && needipsectun) {
 		struct ipsec_output_state state;
@@ -915,16 +929,25 @@ skip_ipsec2:;
 		ipsec_delaux(m);
 #endif
 
-		sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
-		if ((sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
-			if (IN6_NEED_CHECKSUM(ifp,
-			    sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6))) {
-				in6_delayed_cksum(m);
+#ifdef MPLS
+		if (m->m_pkthdr.fecid)
+			error = mpls_ip6_output(ifp, m, sin6tosa(dst),
+				ro->ro_rt);
+		else
+#endif /* MPLS */
+		{
+			sw_csum = m->m_pkthdr.csum_flags 
+			  & ~ifp->if_csum_flags_tx;
+			if ((sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
+				if (IN6_NEED_CHECKSUM(ifp,
+				    sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6))) {
+					in6_delayed_cksum(m);
+				}
+				m->m_pkthdr.csum_flags &=
+				    ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
 			}
-			m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
+			error = nd6_output(ifp, origifp, m, dst, rt);
 		}
-
-		error = nd6_output(ifp, origifp, m, dst, rt);
 		goto done;
 	}
 
Index: netmpls/Makefile
===================================================================
RCS file: netmpls/Makefile
diff -N netmpls/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/Makefile	25 May 2006 16:14:53 -0000
@@ -0,0 +1,7 @@
+#	$NetBSD$
+
+INCSDIR= /usr/include/netmpls
+
+INCS=	mpls.h
+
+.include <bsd.kinc.mk>
Index: netmpls/files.netmpls
===================================================================
RCS file: netmpls/files.netmpls
diff -N netmpls/files.netmpls
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/files.netmpls	25 May 2006 15:10:32 -0000
@@ -0,0 +1,11 @@
+#	$NetBSD$
+
+defflag	opt_mpls.h			MPLS MPLS_DEBUG MPLS_MCAST
+
+file	netmpls/mpls.c                  mpls
+file	netmpls/mpls_ip.c               mpls & inet
+file	netmpls/mpls_ip6.c              mpls & inet6
+file	netmpls/mpls_lse.c              mpls
+file	netmpls/mpls_proto.c            mpls
+file	netmpls/mpls_raw.c              mpls
+file	netmpls/mpls_shim.c             mpls
Index: netmpls/mpls.c
===================================================================
RCS file: netmpls/mpls.c
diff -N netmpls/mpls.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls.c	25 May 2006 17:03:15 -0000
@@ -0,0 +1,348 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls.c,v 1.3 2002/08/31 19:20:47 zin Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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/param.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/protosw.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/systm.h>
+#include <sys/kauth.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/if_ether.h>
+#include <net/route.h>
+
+#include <netmpls/mpls.h>
+
+extern void mpls_purgeaddr __P((struct ifaddr *, struct ifnet *));
+extern int mpls_ifinit __P((struct ifnet *, struct mpls_ifaddr *,
+			    struct sockaddr_mpls *, int));
+extern void mpls_ifscrub __P((struct mpls_ifaddr *));
+
+struct mpls_ifaddrhead mpls_ifaddr;
+struct sockaddr_mpls mpls_scope_sockmask;
+
+void
+mpls_init()
+{
+	mpls_scope_sockmask.smpls_len = sizeof(struct sockaddr_mpls);
+	mpls_scope_sockmask.smpls_family = AF_MPLS;
+	mpls_scope_sockmask.smpls_label = htonl(MPLS_SCOPE_MASK);
+	TAILQ_INIT(&mpls_ifaddr);
+}
+
+void
+mpls_purgeaddr(struct ifaddr *ifa, struct ifnet *ifp)
+{
+	struct mpls_ifaddr *ia = (void *)ifa;
+
+	mpls_ifscrub(ia);
+	TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
+	IFAFREE(&ia->ia_ifa);
+	TAILQ_REMOVE(&mpls_ifaddr, ia, ia_list);
+	IFAFREE(&ia->ia_ifa);
+}
+
+void
+mpls_purgeif(struct ifnet *ifp)
+{
+	struct ifaddr *ifa, *nifa;
+
+	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
+		nifa = TAILQ_NEXT(ifa, ifa_list);
+		if (ifa->ifa_addr->sa_family != AF_MPLS)
+			continue;
+		mpls_purgeaddr(ifa, ifp);
+	}
+}
+
+/*
+ * Delete any existing route for an interface.
+ */
+void
+mpls_ifscrub(struct mpls_ifaddr *ia)
+{
+	if ((ia->ia_flags & IFA_ROUTE) == 0)
+		return;
+	rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
+	ia->ia_flags &= ~IFA_ROUTE;
+}
+
+/*
+ * Initialize an interface's MPLS address
+ * and routing table entry.
+ */
+int
+mpls_ifinit(struct ifnet *ifp, struct mpls_ifaddr *ia,
+	struct sockaddr_mpls *smpls, int scrub)
+{
+	struct sockaddr_mpls oldaddr;
+	int s = splnet(), flags = RTF_UP, error;
+
+	/*
+	 * Set up new addresses.
+	 */
+	ia->ia_addr = *smpls;
+
+	/*
+	 * Give the interface a chance to initialize
+	 * if this is its first address,
+	 * and to validate the address if necessary.
+	 */
+	if (ifp->if_ioctl &&
+	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
+		goto bad;
+
+	if (ifp->if_type == IFT_ETHER) {
+		/*
+		 * enable MTU extension on ether interface, if possible.
+		 *
+		 * XXX ToDo:
+		 * XXX now, when last vlan intarface is shutdowned,
+		 * XXX this extension is disabled by if_vlan.c.
+		 */
+		struct ethercom *ec = (struct ethercom *)ifp;
+
+		if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU)
+		    && !(ec->ec_capenable & ETHERCAP_VLAN_MTU)) {
+			ec->ec_capenable |= ETHERCAP_VLAN_MTU;
+			if (ifp->if_flags & IFF_UP) {
+				struct ifreq ifr;
+
+				ifr.ifr_flags = ifp->if_flags;
+				error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS,
+				    (caddr_t)&ifr);
+			}
+		}
+	}
+
+	splx(s);
+	if (scrub) {
+		ia->ia_ifa.ifa_addr = smplstosa(&oldaddr);
+		mpls_ifscrub(ia);
+		ia->ia_ifa.ifa_addr = smplstosa(&ia->ia_addr);
+	}
+
+        /*
+	 * Add route for the network.
+	 */
+	ia->ia_ifa.ifa_metric = ifp->if_metric;
+	error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags);
+	if (!error)
+		 ia->ia_flags |= IFA_ROUTE;
+
+	return (error);
+bad:
+	splx(s);
+	ia->ia_addr = oldaddr;
+
+	return error;
+}
+
+/*
+ * Generic MPLS control operations (ioctl's).
+ * Ifp is 0 if not an interface-specific ioctl.
+ */
+/* ARGSUSED */
+int
+mpls_control(struct socket *so, unsigned long cmd, caddr_t data,
+	struct ifnet *ifp, struct lwp *l)
+{
+	struct ifreq *ifr = (struct ifreq *)data;
+	struct mpls_ifaddr *ia = 0;
+	struct mpls_aliasreq *ifra = (struct mpls_aliasreq *)data;
+	struct sockaddr olddstaddr;
+	int hostIsNew, dstIsNew, error = 0;
+
+	/*
+	 * Check address family.
+	 */
+	switch (cmd) {
+
+	case SIOCAIFADDR:
+	case SIOCDIFADDR:
+	case SIOCSIFADDR:
+	case SIOCGIFALIAS:
+		if (ifr->ifr_addr.sa_len != sizeof(struct sockaddr_mpls)
+		    || ifr->ifr_addr.sa_family != AF_MPLS)
+			return (EADDRNOTAVAIL);
+		break;
+
+	case SIOCSIFDSTADDR:
+		if (ifr->ifr_addr.sa_len != sizeof(struct sockaddr_dl)
+		    || ifr->ifr_addr.sa_family != AF_LINK)
+			return (EADDRNOTAVAIL);
+		break;
+
+	case SIOCSIFNETMASK:
+	case SIOCGIFBRDADDR:
+	case SIOCSIFBRDADDR:
+		return(EOPNOTSUPP);
+	}
+
+	/*
+         * Find address for this interface, if it exists.
+         */
+	if (ifp)
+		for (ia = TAILQ_FIRST(&mpls_ifaddr); ia != NULL;
+		     ia = TAILQ_NEXT(ia, ia_list))
+			if (ia->ia_ifp == ifp)
+				break;
+
+	switch (cmd) {
+
+	case SIOCAIFADDR:
+	case SIOCDIFADDR:
+	case SIOCGIFALIAS:
+		for (ia = TAILQ_FIRST(&mpls_ifaddr); ia != NULL;
+		     ia = TAILQ_NEXT(ia, ia_list))
+			if (ia->ia_ifp == ifp &&
+			    ia->ia_addr.smpls_label == ifra->ifra_addr.smpls_label)
+				break;
+		if (cmd == SIOCDIFADDR && ia == 0)
+			return (EADDRNOTAVAIL);
+		/* FALLTHROUGH */
+	case SIOCSIFADDR:
+	case SIOCSIFDSTADDR:
+		if (ifp == 0)
+			panic("mpls_control");
+
+		if (cmd == SIOCGIFALIAS)
+			break;
+
+		if (kauth_cred_getuid(kauth_cred_get()))
+			return (EPERM);
+
+		if (ia == 0) {
+			MALLOC(ia, struct mpls_ifaddr *, sizeof(*ia),
+			       M_IFADDR, M_WAITOK);
+			if (ia == 0)
+				return (ENOBUFS);
+			bzero((caddr_t)ia, sizeof(*ia));
+			TAILQ_INSERT_TAIL(&mpls_ifaddr, ia, ia_list);
+			IFAREF(&ia->ia_ifa);
+			TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
+			    ifa_list);
+			IFAREF(&ia->ia_ifa);
+			ia->ia_ifa.ifa_refcnt++;	/* for 1.4X */
+			ia->ia_ifa.ifa_addr = smplstosa(&ia->ia_addr);
+			ia->ia_ifa.ifa_dstaddr = &ia->ia_dstaddr;
+			ia->ia_ifa.ifa_netmask = smplstosa(&mpls_scope_sockmask);
+			ia->ia_ifp = ifp;
+		}
+		break;
+
+	case SIOCGIFADDR:
+	case SIOCGIFNETMASK:
+	case SIOCGIFDSTADDR:
+		if (ia == 0)
+			return (EADDRNOTAVAIL);
+		break;
+	}
+
+	switch (cmd) {
+
+	case SIOCGIFADDR:
+		*satosmpls(&ifr->ifr_addr) = ia->ia_addr;
+		break;
+
+	case SIOCGIFDSTADDR:
+		ifr->ifr_dstaddr = ia->ia_dstaddr;
+		break;
+
+	case SIOCGIFNETMASK:
+		*satosmpls(&ifr->ifr_addr) = mpls_scope_sockmask;
+		break;
+
+	case SIOCSIFDSTADDR:
+		olddstaddr = ia->ia_dstaddr;
+		ia->ia_dstaddr = ifr->ifr_dstaddr;
+
+		if ((ifp->if_flags & IFF_POINTOPOINT) != 0)
+			if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
+				      (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
+				ia->ia_dstaddr = olddstaddr;
+			}
+		break;
+
+	case SIOCSIFADDR:
+		error = mpls_ifinit(ifp, ia, satosmpls(&ifr->ifr_addr), 1);
+		break;
+
+	case SIOCAIFADDR:
+		hostIsNew = 1;
+		dstIsNew = 0;
+		error = 0;
+		if (ia->ia_addr.smpls_family == AF_MPLS) {
+			if (ifra->ifra_addr.smpls_len == 0) {
+				ifra->ifra_addr = ia->ia_addr;
+				hostIsNew = 0;
+			} else if (ia->ia_addr.smpls_label == ifra->ifra_addr.smpls_label)
+				hostIsNew = 0;
+		}
+		if (ifra->ifra_dstaddr.sa_len) {
+			ia->ia_dstaddr = ifra->ifra_dstaddr;
+			dstIsNew = 1;
+		}
+		if (ifra->ifra_addr.smpls_family == AF_MPLS &&
+		    (hostIsNew || dstIsNew))
+			error = mpls_ifinit(ifp, ia, &ifra->ifra_addr, 0);
+		break;
+
+	case SIOCGIFALIAS:
+		ifra->ifra_mask = mpls_scope_sockmask;
+		if (ia->ia_dstaddr.sa_len)
+			ifra->ifra_dstaddr = ia->ia_dstaddr;
+		else
+			bzero(&ifra->ifra_dstaddr,
+			      sizeof(ifra->ifra_dstaddr));
+		break;
+
+	case SIOCDIFADDR:
+		mpls_purgeaddr(&ia->ia_ifa, ifp);
+		break;
+
+	default:
+		if (ifp == 0 || ifp->if_ioctl == 0)
+			return (EOPNOTSUPP);
+		error = (*ifp->if_ioctl)(ifp, cmd, data);
+		break;
+	}
+
+	return error;
+}
Index: netmpls/mpls.h
===================================================================
RCS file: netmpls/mpls.h
diff -N netmpls/mpls.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls.h	25 May 2006 17:13:12 -0000
@@ -0,0 +1,169 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls.h,v 1.3 2003/04/05 06:09:19 n-ogashi Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _NETMPLS_MPLS_H_
+#define _NETMPLS_MPLS_H_
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+
+/*
+ * Structure of a SHIM header.
+ */
+struct shim_hdr {
+	union {
+		u_int32_t shim_label;		/* 20bits of label */
+		struct {
+			u_int8_t shim_un1_pad1;
+			u_int8_t shim_un1_pad2;
+			u_int8_t shim_un1_exp;	/* 3bits of exp & BoS bit */
+			u_int8_t shim_un1_ttl;	/* 8bits of ttl */
+		} shim_un1;
+	} shim_ctlun;
+};
+
+#define shim_label	shim_ctlun.shim_label
+#define shim_exp	shim_ctlun.shim_un1.shim_un1_exp
+#define shim_ttl	shim_ctlun.shim_un1.shim_un1_ttl
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define SHIM_LABEL_MASK		0xfffff000	/* mpls label  (20bits) */
+#else /* LITTLE_ENDIAN */
+#define SHIM_LABEL_MASK		0x00f0ffff	/* mpls label  (20bits) */
+#endif
+#define SHIM_LABEL_OFFSET	12		/* mpls label  (20bits) */
+
+#define SHIM_EXP_MASK		0x0e		/* mpls exp     (3bits) */
+#define SHIM_EXP_OFFSET		1		/* mpls exp offset      */
+#define SHIM_BOS_MASK		0x01		/* mpls BoS flag (1bit) */
+
+#define MPLS_SHIM_LABEL(shimp)	(ntohl((shimp)->shim_label & SHIM_LABEL_MASK) \
+							>> SHIM_LABEL_OFFSET)
+#define MPLS_SHIM_EXP(shimp)	(((shimp)->shim_exp & SHIM_EXP_MASK) \
+							>> SHIM_EXP_OFFSET)
+#define MPLS_SHIM_BOS(shimp)	((shimp)->shim_exp & SHIM_BOS_MASK)
+#define MPLS_SHIM_TTL(shimp)	((shimp)->shim_ttl)
+
+/* Reserved lavel values (draft-ietf-mpls-label-encaps-07) */
+#define MPLS_LABEL_IPV4NULL	0               /* IPv4 Explicit NULL Label */
+#define MPLS_LABEL_RTALERT	1               /* Router Alert Label       */
+#define MPLS_LABEL_IPV6NULL	2               /* IPv6 Explicit NULL Label */
+#define MPLS_LABEL_IMPLNULL	3               /* Implicit NULL Label      */
+/*      MPLS_LABEL_RESERVED	4-15 */		/* Values 4-15 are reserved */
+#define MPLS_LABEL_RESERVED_MAX 15
+
+/*
+ * Socket address
+ */
+
+struct mpls_addr {
+	u_int32_t s_addr;
+} __attribute__((__packed__));
+
+struct sockaddr_mpls {
+	u_int8_t smpls_len;	/* length */
+	u_int8_t smpls_family;	/* AF_MPLS */
+	u_int8_t smpls_pad1[2];	/* padding */
+#if 0
+	u_int32_t smpls_label;	/* MPLS label scope(12) & label(20) */
+#else
+	struct mpls_addr smpls_addr;
+#endif /* if 0 */
+	u_int8_t smpls_exp;	/* exp value */
+#if MPLS_MCAST
+	u_int8_t smpls_mcexp;
+	u_int8_t smpls_pad2[2];
+	u_int32_t smpls_mclabel;
+#else
+	u_int8_t smpls_pad2[7];	/* padding */
+#endif
+} __attribute__((__packed__));
+
+#define smpls_label	smpls_addr.s_addr
+
+#define MPLS_SCOPE_MASK	0xfff00000	/* mpls label scope (12bits) */
+#define MPLS_LABEL_MASK	0x000fffff	/* mpls label       (20bits) */
+#define MPLS_SCOPE_OFFSET	20
+#define MPLS_EXP_MASK	0x07		/* mpls exp value   ( 3bits) */
+
+#define MPLS_FECID_SCOPE(fecid)	(((fecid) & MPLS_SCOPE_MASK) >> 20)
+#define MPLS_FECID_LABEL(fecid)	((fecid) & MPLS_LABEL_MASK)
+#define	MPLS_FECID_LABEL_MASK	0x000fffff
+#define MPLS_FECID_EXP_MASK	0x00700000
+
+#define MPLS_RTF_POP		0x4000
+#define MPLS_RTF_PUSH		0x8000
+
+#define AYAME_MPLS_SCOPE(addr)	((ntohl((addr).s_addr) & 0xfff00000) >> 20)
+#define AYAME_MPLS_LABEL(addr)	(ntohl((addr).s_addr) & 0x000fffff)
+#define AYAME_MPLS_ADDR_SAME(addr1,addr2)	((addr1).s_addr == (addr2).s_addr)
+#define AYAME_IS_MPLS_ADDR_UNSPEC(addr)		((addr).s_addr == 0)
+
+#define MPLS_INKERNEL_LOOP_MAX	16
+
+#define satosmpls(sa)		((struct sockaddr_mpls *)(sa))
+#define smplstosa(smpls)	((struct sockaddr *)(smpls))
+#define satosdl(sa)		((struct sockaddr_dl *)(sa))
+#define sdltosa(sdl)		((struct sockaddr *)(sdl))
+
+struct mpls_ifaddr {
+	struct  ifaddr ia_ifa;		/* protocol-independent info */
+#define ia_ifp		ia_ifa.ifa_ifp
+#define ia_flags	ia_ifa.ifa_flags
+	TAILQ_ENTRY(mpls_ifaddr) ia_list;	/* list of MPLS addresses */
+	struct sockaddr_mpls ia_addr;	/* interface address */
+	struct sockaddr ia_dstaddr;	/* peer dst address */
+};
+
+struct  mpls_aliasreq {
+	char ifra_name[IFNAMSIZ];		/* if name, e.g. "en0" */
+	struct sockaddr_mpls ifra_addr;
+	struct sockaddr ifra_dstaddr;
+	struct sockaddr_mpls ifra_mask;		/* not used */
+};
+
+
+#ifdef _KERNEL
+TAILQ_HEAD(mpls_ifaddrhead, mpls_ifaddr);	/* the actual queue head */
+extern struct mpls_ifaddrhead mpls_ifaddr;
+
+extern void	mpls_init(void);
+extern int	mpls_control(struct socket *, u_long, caddr_t,
+			     struct ifnet *, struct lwp *);
+extern void	mpls_purgeif(struct ifnet *);
+#endif /* _KERNEL */
+#endif /* _NETMPLS_MPLS_H_ */
Index: netmpls/mpls_ip.c
===================================================================
RCS file: netmpls/mpls_ip.c
diff -N netmpls/mpls_ip.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls_ip.c	25 May 2006 17:04:41 -0000
@@ -0,0 +1,178 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls_ip.c,v 1.2 2002/08/23 16:40:30 zin Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 "opt_mpls.h"
+#include "opt_inet.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+
+#include <net/if.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/if_llc.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+
+int
+mpls_ip_input(struct mbuf *m)
+{
+	int iphlen;
+	u_int8_t ttl;
+	struct ip *ip;
+	struct ifqueue *inq;
+	int s;
+
+	if (mpls_mapttl_ip) {
+		/* get ttl */
+		mpls_shim_peep(m, NULL, NULL, NULL, &ttl);
+
+		/* adjust shim header */
+		m_adj(m, sizeof(struct shim_hdr));
+
+		/* chatch up ip header */
+		if (m->m_len < sizeof (struct ip) &&
+		    (m = m_pullup(m, sizeof(struct ip))) == 0)
+			return ENOBUFS;
+		ip = mtod(m, struct ip *);
+		iphlen = ip->ip_hl << 2;
+		if (m->m_len < iphlen) {
+			if ((m = m_pullup(m, iphlen)) == 0)
+				return ENOBUFS;
+			ip = mtod(m, struct ip *);
+		}
+
+		ttl++;
+		if (ttl && ttl < ip->ip_ttl) {
+			/* check ipsum */
+			if (in_cksum(m, iphlen) != 0)
+				return EINVAL;
+
+			/* set IP ttl from MPLS ttl */
+			ip->ip_ttl = ttl;
+
+			/* reexam ipsum */
+			ip->ip_sum = 0;
+			ip->ip_sum = in_cksum(m, iphlen);
+		}
+	} else {
+		/* adjust shim header */
+		m_adj(m, sizeof(struct shim_hdr));
+	}
+
+	/* clear label */
+	m->m_pkthdr.fecid = 0;
+
+	schednetisr(NETISR_IP);
+	inq = &ipintrq;
+
+	s = splnet();
+	if (IF_QFULL(inq)) {
+		IF_DROP(inq);
+		m_freem(m);
+	} else
+		IF_ENQUEUE(inq, m);
+	splx(s);
+
+	return 0;
+}
+
+int
+mpls_ip_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+	struct rtentry *rt)
+{
+	struct sockaddr_mpls smpls;
+	struct ip *iphdr;
+	u_int32_t ipv4null = MPLS_LABEL_IPV4NULL;
+	u_int8_t ttl, bosf = 1;
+
+#if 0 /* It's too old */
+	printf("mpls_ip_output:"
+	    " catch a packet to forward (scope=%d,label=%d)\n",
+	    (m->m_pkthdr.fecid & MPLS_SCOPE_MASK) >> 20,
+	    m->m_pkthdr.fecid & MPLS_LABEL_MASK);
+#endif	/* MPLS_DEBUG */
+
+	if (mpls_mapttl_ip) {
+		/* catch-up ip hdr */
+		if (m->m_len < sizeof(struct ip))
+			if ((m = m_pullup(m, sizeof(struct ip))) == 0)
+				return(ENOBUFS);
+		iphdr = mtod(m, struct ip *);
+		/* map ip ttl to mpls ttl */
+		ttl = iphdr->ip_ttl;
+	} else
+		ttl = mpls_defttl;
+	if (ttl < 255)
+		ttl++;		/* XXX */
+	
+	bzero((caddr_t)&smpls, sizeof(smpls));
+	smpls.smpls_family = AF_MPLS;
+	smpls.smpls_len = sizeof(smpls);
+	smpls.smpls_label = m->m_pkthdr.fecid;
+	/* XXX E-LSP adhoc support XXX */
+	/* XXX where is scope? XXX */
+	/*
+	smpls.smpls_exp |=
+	    ((u_int8_t)((m->m_pkthdr.fecid & MPLS_FECID_EXP_MASK) >> 19))
+			& SHIM_EXP_MASK;
+	*/
+
+	if (mpls_push_expnull_ip) {
+		if ((m = mpls_shim_push(m, NULL, &ipv4null, &bosf, &ttl)) == 0)
+			return ENOBUFS;
+		bosf = 0;
+	}
+
+	/* Add bottom label by fecid */
+	if ((m = mpls_shim_push(m, &smpls, NULL, &bosf, &ttl)) == 0)
+		return ENOBUFS;
+
+	/* send to mpls_lse */
+	return mpls_lse(ifp, m, &smpls, bosf);
+}
Index: netmpls/mpls_ip6.c
===================================================================
RCS file: netmpls/mpls_ip6.c
diff -N netmpls/mpls_ip6.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls_ip6.c	25 May 2006 17:05:30 -0000
@@ -0,0 +1,159 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls_ip6.c,v 1.3 2002/08/23 16:40:30 zin Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 "opt_mpls.h"
+#include "opt_inet.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+
+#include <net/if.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/if_llc.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
+
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+
+int
+mpls_ip6_input(struct mbuf *m)
+{
+	u_int8_t ttl;
+	struct ip6_hdr *ip6hdr;
+	struct ifqueue *inq;
+	int s;
+
+	if (mpls_mapttl_ip6) {		/* XXX not supported yet XXX */
+		/* get ttl */
+		mpls_shim_peep(m, NULL, NULL, NULL, &ttl);
+
+		/* adjust shim header */
+		m_adj(m, sizeof(struct shim_hdr));
+
+		/* chatch up ip header */
+		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 *);
+
+		ttl++;
+		ip6hdr->ip6_hlim = ttl;
+	} else {
+		/* adjust shim header */
+		m_adj(m, sizeof(struct shim_hdr));
+	}
+
+	/* clear label */
+	m->m_pkthdr.fecid = 0;
+
+	schednetisr(NETISR_IPV6);
+	inq = &ip6intrq;
+
+	s = splnet();
+	if (IF_QFULL(inq)) {
+		IF_DROP(inq);
+		m_freem(m);
+	} else
+		IF_ENQUEUE(inq, m);
+	splx(s);
+	return(0);
+}
+
+int
+mpls_ip6_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+	struct rtentry *rt)
+{
+	struct sockaddr_mpls smpls;
+	struct ip6_hdr *ip6hdr;
+	u_int32_t ipv6null = MPLS_LABEL_IPV6NULL;
+	u_int8_t ttl, bosf = 1;
+
+#if 0 /* It's too old */
+	printf("mpls_ip6_output:"
+	    " catch a packet to forward (scope=%d,label=%d)\n",
+	    (m->m_pkthdr.fecid & MPLS_SCOPE_MASK) >> 20,
+	    m->m_pkthdr.fecid & MPLS_LABEL_MASK);
+#endif	/* MPLS_DEBUG */
+
+	if (mpls_mapttl_ip6) {
+		/* catch-up ip6 hdr */
+		if (m->m_len < sizeof(struct ip6_hdr))
+			if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0)
+				return(ENOBUFS);
+		ip6hdr = mtod(m, struct ip6_hdr *);
+		/* map ip ttl to mpls ttl */
+		ttl = ip6hdr->ip6_hlim;
+	} else
+		ttl = mpls_defttl;
+	if (ttl < 255)
+		ttl++;		/* XXX */
+	
+	bzero((caddr_t)&smpls, sizeof(smpls));
+	smpls.smpls_family = AF_MPLS;
+	smpls.smpls_len = sizeof(smpls);
+	smpls.smpls_label = m->m_pkthdr.fecid;
+	/* XXX E-LSP adhoc support XXX */
+	/* XXX where is scope? XXX */
+	/*
+	smpls.smpls_exp |=
+	    ((u_int8_t)((m->m_pkthdr.fecid & MPLS_FECID_EXP_MASK) >> 19))
+			& SHIM_EXP_MASK;
+	*/
+
+	if (mpls_push_expnull_ip6) {
+		if ((m = mpls_shim_push(m, NULL, &ipv6null, &bosf, &ttl)) == 0)
+			return ENOBUFS;
+		bosf = 0;
+	}
+
+	/* Add bottom label by fecid */
+	if ((m = mpls_shim_push(m, &smpls, NULL, &bosf, &ttl)) == 0)
+		return ENOBUFS;
+
+	/* send to mpls_lse */
+	return mpls_lse(ifp, m, &smpls, bosf);
+}
Index: netmpls/mpls_lse.c
===================================================================
RCS file: netmpls/mpls_lse.c
diff -N netmpls/mpls_lse.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls_lse.c	25 May 2006 17:13:41 -0000
@@ -0,0 +1,318 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls_lse.c,v 1.5 2003/05/17 09:30:32 n-ogashi Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 "opt_mpls.h"
+#include "opt_inet.h"
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+
+/*
+ * MPLS Label Switching Engine.
+ */
+
+/*
+ * Process a received MPLS packet;
+ * the packet is in the mbuf chain m from mpls_{ether,...}.
+ */
+int
+mpls_lse(struct ifnet *ifp, struct mbuf *m, struct sockaddr_mpls *dst,
+	uint8_t bosf)
+{
+	struct route mplsroute;
+	struct route *ro = &mplsroute;
+	struct sockaddr_mpls *rodst = satosmpls(&mplsroute.ro_dst);
+	struct rtentry *rt = NULL;
+	struct sockaddr_mpls *dstnew;
+	struct sockaddr_mpls smpls;	/* XXX adhoc XXX */
+	u_int8_t exp_bits;		/* XXX adhoc XXX */
+	int ink_loop, error = 0;
+
+	bzero((caddr_t)ro, sizeof(*ro));
+	bcopy((caddr_t)dst, (caddr_t)rodst, dst->smpls_len);
+
+	/* TTL decriment */
+	if ((m = mpls_shim_ttl_dec(m)) == NULL)
+		goto done;
+
+	for (ink_loop = 0; ink_loop < mpls_inkloop; ink_loop++) {
+
+#ifdef MPLS_DEBUG
+		printf("MPLS_DEBUG: %s(%d). [label = %08x]\n",
+		    __FILE__, __LINE__, ntohl(rodst->smpls_label));
+#endif	/* MPLS_DEBUG */
+
+		/*
+		 * OPERATIONS for Reserved Labels
+		 */
+		if (ntohl(rodst->smpls_label) <= MPLS_LABEL_RESERVED_MAX) {
+			switch (ntohl(rodst->smpls_label)) {
+#ifdef INET
+			case MPLS_LABEL_IPV4NULL:
+				if (bosf) {
+					error = mpls_ip_input(m);
+					goto done;
+				}
+#ifdef MPLS_DEBUG
+				printf("MPLS_DEBUG: %s(%d). [bosf = %d]\n",
+		    		    __FILE__, __LINE__, bosf);
+#endif	/* MPLS_DEBUG */
+				break;
+#endif	/* INET */
+#ifdef INET6
+			case MPLS_LABEL_IPV6NULL:
+				if (bosf) {
+					error = mpls_ip6_input(m);
+					goto done;
+				}
+				break;
+#endif	/* INET6 */
+			}
+
+			/* label is reserved, */
+			/* but operation is unsupported or invalid */
+			error = EINVAL;
+			printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__);
+			goto bad;
+		}
+
+		/*
+		 * route packet
+		 */
+		/* XXX */
+		exp_bits = rodst->smpls_exp;
+		rodst->smpls_exp = 0;
+
+		rtalloc(ro);
+		rt = ro->ro_rt;
+		bzero((caddr_t)ro, sizeof(*ro));
+
+		if (rt == 0) {
+			/* no entry for this label (silent discard) */
+			/* as the scope_id you use is not set interface, etc. */
+			/* error = EHOSTUNREACH; */
+			error = 0;
+#ifdef MPLS_DEBUG
+			printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__);
+#endif	/* MPLS_DEBUG */
+			goto bad;
+		}
+
+		/*
+		if ((mtu = rt->rt_rmx.rmx_mtu) == 0)
+			mtu = ifp->if_mtu;
+		*/
+
+
+		/*
+		 * label operations
+		 */
+		rt->rt_use++;
+		if (rt->rt_flags & RTF_GATEWAY)	/* XXX */
+			dstnew = satosmpls(rt->rt_gateway);
+		else {
+			/* XXX silent discard XXX */
+			/* error = EHOSTUNREACH;  */
+			error = 0;
+#ifdef MPLS_DEBUG
+			printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__);
+#endif	/* MPLS_DEBUG */
+			goto bad;
+		}
+
+#ifdef MPLS_MCAST
+		printf("MPLS_MCAST label=%d mclabel=%d\n",
+		       ntohl(dstnew->smpls_label) & 0x000fffff,
+		       ntohl(dstnew->smpls_mclabel));
+		/*
+		 * if gw_entry have next mplsmc entry, 
+		 * call mpls_lse again.
+		 */
+		if (dstnew->smpls_mclabel != 0) {
+			struct sockaddr_mpls smpmpls;
+			struct mbuf *nm;
+			memset(&smpmpls, 0, sizeof(smpmpls));
+			smpmpls.smpls_len = sizeof(smpmpls);
+			smpmpls.smpls_family = AF_MPLS;
+			smpmpls.smpls_label = dstnew->smpls_mclabel;
+#ifdef MPLS_DEBUG
+			printf("MPLS_MCAST label=%d mclabel=%d\n",
+			       ntohl(dstnew->smpls_label) & 0x000fffff,
+			       ntohl(dstnew->smpls_mclabel));
+#endif /* MPLS_DEBUG */
+			nm = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
+			if (nm != NULL) {
+#ifdef MPLS_DEBUG
+				printf("MPLS_MCAST dup\n");
+#endif /* MPLS_DEBUG */
+				mpls_lse(ifp, nm, &smpmpls, bosf);
+				m_freem(nm);
+			}
+		}
+#endif /* MPLS_MCAST */
+
+		if (dstnew->smpls_family != AF_MPLS) {
+			if (bosf) {
+				/* send to L3? */
+				switch (dstnew->smpls_family) {
+#ifdef INET
+				case AF_INET:
+					error = mpls_ip_input(m);
+					goto done;
+#endif	/* INET */
+#ifdef INET6
+				case AF_INET6:
+					error = mpls_ip6_input(m);
+					goto done;
+#endif	/* INET6 */
+				default:
+					error = EAFNOSUPPORT;
+#ifdef MPLS_DEBUG
+					printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__);
+#endif	/* MPLS_DEBUG */
+					goto bad;
+				}
+			} else {
+				/* XXX */
+				error = EINVAL;
+#ifdef MPLS_DEBUG
+				printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__);
+#endif	/* MPLS_DEBUG */
+				goto bad;
+			}
+		}
+
+		/* XXX */
+		smpls = *dstnew;
+		smpls.smpls_exp = exp_bits;
+		dstnew = &smpls;
+		/* XXX */
+
+		switch(rt->rt_flags & (MPLS_RTF_POP | MPLS_RTF_PUSH)) {
+
+		case MPLS_RTF_POP: 			/* Label Pop */
+
+			/* check bos flag */
+			if (bosf) {
+				/*
+				 * XXXXX No ExpNULL XXXXX
+				 *
+				 * I can't know which l3 I shuld send to!!
+				 * now, send to IPv4 stack (XXXXX)
+				 *
+				 * error = EINVAL;
+				 * goto bad;
+				 */
+
+				error = mpls_ip_input(m);
+				goto done;
+			}
+			/* label pop */
+			if ((m = mpls_shim_pop(m, rodst, NULL, &bosf, NULL)) == 0) {
+				error = ENOBUFS;
+				goto done;
+			}
+
+			break;
+
+		case MPLS_RTF_PUSH: 			/* Label Push */
+
+			if ((m = mpls_shim_push(m, dstnew, NULL, NULL, NULL)) == 0) {
+				error = ENOBUFS;
+				goto done;
+			}
+			bosf = 0;
+
+			break;
+
+		case (MPLS_RTF_POP | MPLS_RTF_PUSH):	/* Label Swap */
+		default: 
+
+			if ((m = mpls_shim_swap(m, dstnew, NULL)) == 0) {
+				error = ENOBUFS;
+				goto done;
+			}
+		}
+
+		ifp = rt->rt_ifp;
+		/* send to L2 : select outgoing i/f */
+		switch (ifp->if_type) {
+		case IFT_ETHER:
+		case IFT_ATM:		/* now only support scope 0 */
+		case IFT_GIF:		/* now only support scope 0 */
+			error = mpls_shim_output(ifp, m, dstnew, rt);
+			goto done;
+		case IFT_LOOP:
+			break;
+		default:
+			/* not supported yet: discard */
+#ifdef MPLS_DEBUG
+			printf("mpls_lse: interface type not supported yet!\n");
+#endif	/* MPLS_DEBUG */
+			error = EHOSTUNREACH;
+			goto bad;
+		}
+
+		if (rt) {
+			RTFREE(rt);
+			rt = 0;
+		}
+	}
+
+	/*
+	 * Discard broken packet
+	 */
+bad:
+#ifdef MPLS_DEBUG
+	printf("MPLS_DEBUG: %s(%d) [packet discard!!].\n", __FILE__, __LINE__);
+#endif	/* MPLS_DEBUG */
+	m_freem(m);
+
+done:
+	if (rt)
+		RTFREE(rt);
+
+	return error;
+}
Index: netmpls/mpls_proto.c
===================================================================
RCS file: netmpls/mpls_proto.c
diff -N netmpls/mpls_proto.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls_proto.c	25 May 2006 17:18:22 -0000
@@ -0,0 +1,77 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls_proto.c,v 1.1 2001/10/18 07:27:34 ayame Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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/param.h>
+#include <sys/socket.h>
+#include <sys/protosw.h>
+#include <sys/domain.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+
+/*
+ * MPLS protocol family:
+ */
+
+extern	struct domain mplsdomain;
+
+struct protosw mplssw[] = {
+{ 0,			&mplsdomain,		0,	0,
+  0,			0,			0,	0,
+  0,
+  mpls_init,		0,			0,	0,	NULL
+},
+{ SOCK_DGRAM,		&mplsdomain,		0,	PR_ATOMIC|PR_ADDR,
+  0,			0,			0,	0,
+  mpls_raw_usrreq,
+  0,			0,			0,	0,	NULL
+},
+/* raw wildcard */
+{ SOCK_RAW,		&mplsdomain,		0,	PR_ATOMIC|PR_ADDR,
+  0,			0,			0,	0,
+  mpls_raw_usrreq,
+  0,			0,			0,	0,	NULL
+},
+};
+
+struct domain mplsdomain = {
+	PF_MPLS, "mpls", /* mpls_init */ 0, 0, 0, 
+	mplssw,
+	&mplssw[sizeof(mplssw)/sizeof(mplssw[0])],
+	rn_inithead,
+	offsetof(struct sockaddr_mpls, smpls_label) << 3,
+	sizeof(struct sockaddr_mpls)
+};
Index: netmpls/mpls_raw.c
===================================================================
RCS file: netmpls/mpls_raw.c
diff -N netmpls/mpls_raw.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls_raw.c	25 May 2006 20:18:29 -0000
@@ -0,0 +1,185 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls_raw.c,v 1.2 2002/08/31 18:46:15 zin Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_mpls.h"
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/protosw.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+
+#define MPLS_RAW_SNDQ	8192
+#define MPLS_RAW_RCVQ	8192
+
+u_long mpls_raw_sendspace = MPLS_RAW_SNDQ;
+u_long mpls_raw_recvspace = MPLS_RAW_RCVQ;
+
+int mpls_defttl = 255;
+int mpls_inkloop = 16;
+int mpls_push_expnull_ip = 1;
+int mpls_push_expnull_ip6 = 0;
+int mpls_mapttl_ip = 1;
+int mpls_mapttl_ip6 = 0;
+
+int
+mpls_raw_usrreq(struct socket *so, int req, struct mbuf *m, 
+	struct mbuf *nam, struct mbuf *control, struct lwp *l)
+{
+	int s;
+	int error = 0;
+
+#ifdef MPLS_DEBUG
+	printf("mpls_raw_usrreq: called! (reqid=%d).\n", req);
+#endif	/* MPLS_DEBUG */
+
+	if (req == PRU_CONTROL)
+		return (mpls_control(so, (long)m, (caddr_t)nam,
+		    (struct ifnet *)control, l));
+
+	if (req == PRU_PURGEIF) {
+		mpls_purgeif((struct ifnet *)control);
+		return (0);
+	}
+
+	s = splsoftnet();
+
+	switch (req) {
+
+	case PRU_ATTACH:
+		if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
+			error = soreserve(so, mpls_raw_sendspace,
+			    mpls_raw_recvspace);
+			if (error)
+				break;
+		}
+		break;
+
+	case PRU_DETACH:
+	case PRU_BIND:
+	case PRU_LISTEN:
+	case PRU_CONNECT:
+	case PRU_CONNECT2:
+	case PRU_DISCONNECT:
+	case PRU_SHUTDOWN:
+	case PRU_RCVD:
+	case PRU_SEND:
+	case PRU_SENSE:
+	case PRU_RCVOOB:
+	case PRU_SENDOOB:
+	case PRU_SOCKADDR:
+	case PRU_PEERADDR:
+		error = EOPNOTSUPP;
+		break;
+
+	default:
+		panic("rip_usrreq");
+	}
+
+/* release: */
+	splx(s);
+	return (error);
+}
+
+/*
+ * Sysctl for MPLS variables.
+ */
+SYSCTL_SETUP(sysctl_net_mpls_setup, "sysctl net.mpls subtree setup")
+{
+
+        sysctl_createv(clog, 0, NULL, NULL,
+                       CTLFLAG_PERMANENT,
+                       CTLTYPE_NODE, "net", NULL,
+                       NULL, 0, NULL, 0,
+                       CTL_NET, CTL_EOL);
+        sysctl_createv(clog, 0, NULL, NULL,
+                       CTLFLAG_PERMANENT,
+                       CTLTYPE_NODE, "mpls", NULL,
+                       NULL, 0, NULL, 0,
+                       CTL_NET, PF_MPLS, CTL_EOL);
+
+        sysctl_createv(clog, 0, NULL, NULL,
+                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+                       CTLTYPE_INT, "ttl",
+                       SYSCTL_DESCR("Default TTL"),
+                       NULL, 0, &mpls_defttl, 0,
+                       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "maxloop_inkernel",
+		       SYSCTL_DESCR("Maximum inkernel loop"),
+		       NULL, 0, &mpls_maxinkloop, 0,
+		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
+#ifdef INET
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "pushexpnull_ip",
+		       SYSCTL_DESCR("Push ???"),
+		       NULL, 0, &mpls_push_expnull_ip, 0,
+		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "mapttl_ip",
+		       SYSCTL_DESCR("Map ???"),
+		       NULL, 0, &mpls_mapttl_ip, 0,
+		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
+#endif
+#ifdef INET6
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "pushexpnull_ip6",
+		       SYSCTL_DESCR("Push ???"),
+		       NULL, 0, &mpls_push_expnull_ip6, 0,
+		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "mapttl_ip6",
+		       SYSCTL_DESCR("Map ???"),
+		       NULL, 0, &mpls_mapttl_ip6, 0,
+		       CTL_NET, PF_MPLS, CTL_CREATE, CTL_EOL);
+#endif
+
+}
Index: netmpls/mpls_shim.c
===================================================================
RCS file: netmpls/mpls_shim.c
diff -N netmpls/mpls_shim.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls_shim.c	25 May 2006 17:10:33 -0000
@@ -0,0 +1,234 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls_shim.c,v 1.1 2001/10/18 07:27:34 ayame Exp	*/
+
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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/param.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+
+/*
+ * SHIM header exam.
+ */
+
+struct mbuf *
+mpls_shim_peep(struct mbuf *m, struct sockaddr_mpls *smplsp,
+	uint32_t *labelp, uint8_t *bosp, uint8_t *ttlp)
+{
+	struct shim_hdr *shim;
+	uint32_t label;
+
+	if (m->m_len < sizeof(struct shim_hdr))
+		if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0)
+			return(0);
+	shim = mtod(m, struct shim_hdr *);
+
+	/* set FECid to mbuf */
+	label = MPLS_SHIM_LABEL(shim);
+	if (label > MPLS_LABEL_RESERVED_MAX)
+		/* scope is always zero */
+		m->m_pkthdr.fecid = label;
+
+	/* set sockaddr_mpls structure, if need */
+	if (smplsp) {
+		bzero((caddr_t)smplsp, sizeof(*smplsp));
+		smplsp->smpls_family = AF_MPLS;
+		smplsp->smpls_len = sizeof(*smplsp);
+		smplsp->smpls_label = htonl(label);	/* scope is zero */
+		smplsp->smpls_exp = MPLS_SHIM_EXP(shim);
+	}
+
+	/* set each value, if need */
+	if (labelp)
+		*labelp = label;			/* scope is zero */
+	if (bosp)
+		*bosp = MPLS_SHIM_BOS(shim);
+	if (ttlp)
+		*ttlp = MPLS_SHIM_TTL(shim);
+
+	/* return mbuf */
+	return(m);
+}
+
+struct mbuf *
+mpls_shim_pop(struct mbuf *m, struct sockaddr_mpls *smplsp,
+	uint32_t *labelp, uint8_t *bosp, uint8_t *ttlp)
+{
+	/* shaves off top shim header from mbuf */
+	m_adj(m, sizeof(struct shim_hdr));
+
+	/* catch-up next shim_hdr */
+	if (m->m_len < sizeof(struct shim_hdr))
+		if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0)
+			return(0);
+
+	/* set each values, if need */
+	m = mpls_shim_peep(m, smplsp, labelp, bosp, ttlp);
+
+	/* return mbuf */
+	return(m);
+}
+
+struct mbuf *
+mpls_shim_swap(struct mbuf *m, struct sockaddr_mpls *smplsp,
+	uint32_t *labelp)
+{
+	struct shim_hdr *shim;
+
+	/* pullup shim_hdr */
+	if (m->m_len < sizeof(struct shim_hdr))
+		if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0)
+			return(0);
+        shim = mtod(m, struct shim_hdr *);
+
+	if (smplsp == NULL && labelp == NULL)
+		/* can't swap, because no dst label */
+		return(m);	/* XXX discard? XXX */
+
+	/* fecid swap */
+	if (labelp) {
+		m->m_pkthdr.fecid = *labelp;
+		/*
+		if (smplsp)
+			smplsp->smpls_label = htonl(*labelp);
+		*/
+	} else
+		m->m_pkthdr.fecid = ntohl(smplsp->smpls_label);
+
+	/* shim swap label */
+	shim->shim_label &= ~SHIM_LABEL_MASK;
+	shim->shim_label |=
+	    htonl((m->m_pkthdr.fecid & MPLS_LABEL_MASK) << SHIM_LABEL_OFFSET);
+	/* shim swap exp : XXX exp override */
+	if (smplsp) {
+		shim->shim_exp &= ~SHIM_EXP_MASK;	/* XXX exp override */
+		shim->shim_exp |=
+			smplsp->smpls_exp << SHIM_EXP_OFFSET & SHIM_EXP_MASK;
+	}
+
+	return(m);
+}
+
+struct mbuf *
+mpls_shim_push(struct mbuf *m, struct sockaddr_mpls *smplsp,
+	uint32_t *labelp, uint8_t *bosp, uint8_t *ttlp)
+{
+	struct shim_hdr *shim;
+
+        M_PREPEND(m, sizeof(struct shim_hdr), M_DONTWAIT);
+        if (m == 0)
+		return(0);
+
+        shim = mtod(m, struct shim_hdr *);
+	bzero((caddr_t)shim, sizeof(*shim));
+
+	if (bosp)
+		shim->shim_exp = *bosp & SHIM_BOS_MASK;
+	if (ttlp)
+		shim->shim_ttl = *ttlp;
+	else
+		shim->shim_ttl = 255;		/* XXX */
+	m = mpls_shim_swap(m, smplsp, labelp);
+
+	return m;
+}
+
+struct mbuf *
+mpls_shim_ttl_dec(struct mbuf *m)
+{
+	struct shim_hdr *shim;
+
+	/* pullup shim_hdr */
+	if (m->m_len < sizeof(struct shim_hdr))
+		if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0)
+			return 0;
+        shim = mtod(m, struct shim_hdr *);
+
+	if (shim->shim_ttl == 0) {
+		/* shim ttl exceed */
+		m_freem(m);
+		return 0;
+	}
+	shim->shim_ttl--;
+
+	return m;
+}
+
+/*
+ * MPLS shimed packet exam routine.
+ * the packet is in the mbuf chain m
+ */
+
+int
+mpls_shim_output(struct ifnet *ifp, struct mbuf *m,
+	struct sockaddr_mpls *smpls, struct rtentry *rt)
+{
+	int error;
+
+	/* XXX */
+	if (ifp->if_type)
+		m->m_pkthdr.fecid = 0;
+
+	/* no need to exp_exam for output */
+	error = (*ifp->if_output)(ifp, m, smplstosa(smpls), rt);
+
+	return error;
+}
+
+void
+mpls_shim_input(struct ifnet *ifp, struct mbuf *m)
+{
+	struct sockaddr_mpls smpls;
+	u_int8_t bosf;
+
+	if ((m = mpls_shim_peep(m, &smpls, NULL, &bosf, NULL)) == 0)
+		return;
+
+	/* set interface scope to m->m_pkthdr.fecid */
+	/* XXX now only support global(zero) scope */
+
+#ifdef MPLS_DEBUG
+	printf("mpls_ether_input:"
+	    " catch a packet to forward to LSE (scope=%d,label=%d)\n",
+	    (ntohl(smpls.smpls_label) & MPLS_SCOPE_MASK) >> 20,
+	    ntohl(smpls.smpls_label) & MPLS_LABEL_MASK);
+#endif	/* MPLS_DEBUG */
+
+	mpls_lse(ifp, m, &smpls, bosf);
+}
Index: netmpls/mpls_var.h
===================================================================
RCS file: netmpls/mpls_var.h
diff -N netmpls/mpls_var.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ netmpls/mpls_var.h	25 May 2006 19:48:03 -0000
@@ -0,0 +1,68 @@
+/*	$NetBSD$	*/
+/*	AYAME Id mpls_var.h,v 1.4 2002/08/31 19:20:47 zin Exp	*/
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+#ifdef _KERNEL
+extern int mpls_defttl;
+extern int mpls_inkloop;
+extern int mpls_push_expnull_ip;
+extern int mpls_push_expnull_ip6;
+extern int mpls_mapttl_ip;
+extern int mpls_mapttl_ip6;
+
+extern int mpls_lse(struct ifnet *, struct mbuf *,
+		    struct sockaddr_mpls *, u_int8_t);
+extern int mpls_canfwbympls(u_int32_t);
+extern struct mbuf *mpls_shim_peep(struct mbuf *, struct sockaddr_mpls *,
+					u_int32_t *, u_int8_t *, u_int8_t *);
+extern struct mbuf *mpls_shim_pop(struct mbuf *, struct sockaddr_mpls *,
+					u_int32_t *, u_int8_t *, u_int8_t *);
+extern struct mbuf *mpls_shim_swap(struct mbuf *, struct sockaddr_mpls *,
+					u_int32_t *);
+extern struct mbuf *mpls_shim_push(struct mbuf *, struct sockaddr_mpls *,
+					u_int32_t *, u_int8_t *, u_int8_t *);
+extern struct mbuf *mpls_shim_ttl_dec(struct mbuf *);
+
+extern int mpls_raw_usrreq(struct socket *, int, struct mbuf *,
+			struct mbuf *, struct mbuf *, struct lwp *);
+extern int mpls_shim_output(struct ifnet *, struct mbuf *,
+		 		   struct sockaddr_mpls *, struct rtentry *);
+extern void mpls_shim_input(struct ifnet *, struct mbuf *);
+/* #ifdef INET / temp comment-out */
+extern int mpls_ip_input(struct mbuf *);
+extern int mpls_ip_output(struct ifnet *, struct mbuf *,
+				struct sockaddr *, struct rtentry *);
+/* #endif	INET */
+/* #ifdef INET6 / temp comment-out */
+extern int mpls_ip6_input(struct mbuf *);
+extern int mpls_ip6_output(struct ifnet *, struct mbuf *,
+			   struct sockaddr *, struct rtentry *);
+/* #endif	INET6 */
+#endif /* _KERNEL */
Index: sys/mbuf.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.127
diff -u -p -r1.127 mbuf.h
--- sys/mbuf.h	16 Mar 2006 13:41:56 -0000	1.127
+++ sys/mbuf.h	25 May 2006 15:14:41 -0000
@@ -1,5 +1,34 @@
 /*	$NetBSD: mbuf.h,v 1.127 2006/03/16 13:41:56 yamt Exp $	*/
 
+/*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
 /*-
  * Copyright (c) 1996, 1997, 1999, 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -159,6 +188,9 @@ struct	pkthdr {
 	int	csum_flags;		/* checksum flags */
 	uint32_t csum_data;		/* checksum data */
 	u_int	segsz;			/* segment size */
+	uint32_t fecid;			/* explicit gw (pointer to rtentry) */
+					/*      used by sub-l3 (mpls, etc.) */
+
 };
 
 /*
@@ -474,6 +506,7 @@ MBUFLOCK(								\
 		(m)->m_pkthdr.rcvif = NULL;				\
 		(m)->m_pkthdr.csum_flags = 0;				\
 		(m)->m_pkthdr.csum_data = 0;				\
+		(m)->m_pkthdr.fecid = 0;				\
 		SLIST_INIT(&(m)->m_pkthdr.tags);			\
 	}								\
 )
Index: sys/socket.h
===================================================================
RCS file: /usr/cvs/src/sys/sys/socket.h,v
retrieving revision 1.79
diff -u -p -r1.79 socket.h
--- sys/socket.h	11 May 2006 15:49:44 -0000	1.79
+++ sys/socket.h	25 May 2006 16:15:02 -0000
@@ -1,6 +1,35 @@
 /*	$NetBSD: socket.h,v 1.79 2006/05/11 15:49:44 christos Exp $	*/
 
 /*
+ * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+/*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  * All rights reserved.
  *
@@ -195,8 +224,9 @@ struct	linger {
 #define	pseudo_AF_HDRCMPLT 30		/* Used by BPF to not rewrite hdrs
 					   in interface output routine */
 #endif
+#define	AF_MPLS		31		/* Multiprotocol Label Switching */
 
-#define	AF_MAX		31
+#define	AF_MAX		32
 
 /*
  * Structure used by kernel to store most
@@ -282,6 +312,7 @@ struct sockaddr_storage {
 #if defined(_NETBSD_SOURCE)
 #define PF_KEY 		pseudo_AF_KEY	/* like PF_ROUTE, only for key mgmt */
 #endif
+#define	PF_MPLS		AF_MPLS
 
 #define	PF_MAX		AF_MAX
 
@@ -359,6 +390,8 @@ struct sockcred {
 	{ "natm", CTLTYPE_NODE }, \
 	{ "arp", CTLTYPE_NODE }, \
 	{ "key", CTLTYPE_NODE }, \
+	{ 0, 0 }, \
+	{ "mpls", CTLTYPE_NODE }, \
 }
 
 struct kinfo_pcb {
