Index: distrib/sets/lists/base/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/base/mi,v
retrieving revision 1.847
diff -u -p -r1.847 mi
--- distrib/sets/lists/base/mi  5 Dec 2009 20:11:01 -0000       1.847
+++ distrib/sets/lists/base/mi  17 Dec 2009 11:14:51 -0000
@@ -778,6 +778,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
@@ -1117,6 +1118,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.1344
diff -u -p -r1.1344 mi
--- distrib/sets/lists/comp/mi  5 Dec 2009 22:43:34 -0000       1.1344
+++ distrib/sets/lists/comp/mi  17 Dec 2009 11:14:59 -0000
@@ -1617,6 +1617,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.213
diff -u -p -r1.213 mi
--- distrib/sets/lists/etc/mi   29 Sep 2009 23:56:26 -0000      1.213
+++ distrib/sets/lists/etc/mi   17 Dec 2009 11:14:59 -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.1175
diff -u -p -r1.1175 mi
--- distrib/sets/lists/man/mi   21 Nov 2009 03:24:30 -0000      1.1175
+++ distrib/sets/lists/man/mi   17 Dec 2009 11:15:02 -0000
@@ -2220,6 +2220,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
@@ -4663,6 +4664,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
@@ -7259,6 +7261,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/defaults/rc.conf
===================================================================
RCS file: /cvsroot/src/etc/defaults/rc.conf,v
retrieving revision 1.109
diff -u -p -r1.109 rc.conf
--- etc/defaults/rc.conf        1 Oct 2009 16:36:20 -0000       1.109
+++ etc/defaults/rc.conf        17 Dec 2009 11:15:03 -0000
@@ -254,6 +254,10 @@ mrouted=NO         mrouted_flags=""
route6d=NO             route6d_flags=""
rtsold=NO              rtsold_flags="-a"       # for ip6mode=autohost only

+# Label Distribution Protocol
+#
+ldpd=NO
+
# Daemons used to boot other hosts over a network.
#
rarpd=NO               rarpd_flags="-a"
Index: etc/mtree/NetBSD.dist.base
===================================================================
RCS file: /cvsroot/src/etc/mtree/NetBSD.dist.base,v
retrieving revision 1.8
diff -u -p -r1.8 NetBSD.dist.base
--- etc/mtree/NetBSD.dist.base  5 Dec 2009 20:11:02 -0000       1.8
+++ etc/mtree/NetBSD.dist.base  17 Dec 2009 11:15:04 -0000
@@ -147,6 +147,7 @@
./usr/include/netisdn
./usr/include/netiso
./usr/include/netkey
+./usr/include/netmpls
./usr/include/netnatm
./usr/include/netsmb
./usr/include/nfs
Index: etc/mtree/special
===================================================================
RCS file: /cvsroot/src/etc/mtree/special,v
retrieving revision 1.131
diff -u -p -r1.131 special
--- etc/mtree/special   29 Sep 2009 23:56:27 -0000      1.131
+++ etc/mtree/special   17 Dec 2009 11:15:04 -0000
@@ -222,6 +222,7 @@
./etc/rc.d/isdnd               type=file mode=0555
./etc/rc.d/kdc                 type=file mode=0555
./etc/rc.d/ldconfig            type=file mode=0555
+./etc/rc.d/ldpd                        type=file mode=0555
./etc/rc.d/local               type=file mode=0555
./etc/rc.d/lpd                 type=file mode=0555
./etc/rc.d/lvm                 type=file mode=0555
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   17 Dec 2009 11:15:04 -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: 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       17 Dec 2009 11:15:47 -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       17 Dec 2009 11:15:47 -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  17 Dec 2009 11:15:47 -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>

@@ -73,6 +74,11 @@ __RCSID("$NetBSD: route.c,v 1.119 2008/1
#include "keywords.h"
#include "extern.h"

+struct composed_mpls {
+       struct sockaddr_mpls smpls;
+       struct sockaddr_in sinet;
+} __packed__ ;
+
union sockunion {
       struct  sockaddr sa;
       struct  sockaddr_in sin;
@@ -83,13 +89,14 @@ union sockunion {
       struct  sockaddr_dl sdl;
#ifndef SMALL
       struct  sockaddr_iso siso;
+       struct  composed_mpls scmpls;
#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 +128,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 +582,24 @@ 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:
+               {
+               const struct sockaddr_in *sin = (const struct sockaddr_in *)
+                       (((const struct sockaddr_mpls *)sa) + 1);
+               union mpls_shim ms;
+
+               ms.s_addr =((const struct sockaddr_mpls*)sa)->smpls_addr.s_addr;
+               ms.s_addr = ntohl(ms.s_addr);
+
+               if (sa->sa_len <= sizeof(struct sockaddr_mpls))
+                   snprintf(line, sizeof(line), "%u",
+                       ms.shim.label);
+               else
+                   snprintf(line, sizeof(line), "%s:%d",
+                       inet_ntoa(sin->sin_addr),
+                       ms.shim.label);
+               break;
+               }
#endif /* SMALL */

       default:
@@ -819,6 +844,17 @@ newroute(int argc, char *const *argv)
                               af = AF_ISO;
                               aflen = sizeof(struct sockaddr_iso);
                               break;
+                       case K_MPLS:
+                               af = AF_MPLS;
+                               /* XXX: Not quite */
+                               aflen = sizeof(struct sockaddr_mpls);
+                               break;
+                       case K_TAG:
+                               if (!--argc)
+                                       usage(1+*argv);
+                               aflen = sizeof(struct sockaddr_mpls);
+                               (void)getaddr(RTA_MPLS, *++argv, 0, soup);
+                               break;
#endif /* SMALL */

                       case K_IFACE:
@@ -1104,7 +1140,7 @@ getaddr(int which, const char *s, struct
       struct hostent *hp;
       struct netent *np;
       u_int32_t val;
-       char *t;
+       char *t, scopy[25];
       int afamily;  /* local copy of af so we can change it */

       if (af == AF_UNSPEC) {
@@ -1134,6 +1170,10 @@ getaddr(int which, const char *s, struct
               su = &soup->so_ifa;
               su->sa.sa_family = af;
               break;
+       case RTA_MPLS:
+               su = &soup->so_mpls;
+               afamily = AF_MPLS;
+               break;
       default:
               su = NULL;
               usage("Internal Error");
@@ -1239,6 +1279,35 @@ badataddr:
               su->sat.sat_addr.s_node = val;
               rtm_addrs |= RTA_NETMASK;
               return(forcehost || su->sat.sat_addr.s_node != 0);
+       case AF_MPLS:
+               strlcpy(scopy, s, sizeof(scopy));
+               t = strchr (scopy, ':');
+               if (!t) {
+                       if (atoi(s) < 0 || atoi(s) >> 20)       /* ETOOMANYATOIS */
+                               errx(1, "bad tag: %s", s);
+                       su->scmpls.smpls.smpls_addr.s_addr = 0;
+                       su->scmpls.smpls.smpls_addr.shim.label = atoi(s);
+                       su->scmpls.smpls.smpls_addr.s_addr =
+                               htonl(su->scmpls.smpls.smpls_addr.s_addr);
+               } else {
+                       *t = '\0';
+                       t++;
+                       if (atoi(t) < 0 || atoi(t) >> 20)
+                               errx(1, "bad label: %s", t);
+                       su->scmpls.smpls.smpls_addr.s_addr = 0;
+                       su->scmpls.smpls.smpls_family = AF_MPLS;
+                       su->scmpls.smpls.smpls_len = sizeof(struct composed_mpls);
+                       su->scmpls.smpls.smpls_addr.shim.label = atoi(t);
+                       su->scmpls.smpls.smpls_addr.s_addr = htonl(su->scmpls.smpls.smpls_addr.s_addr);
+
+                       su->scmpls.sinet.sin_family = AF_INET;
+                       su->scmpls.sinet.sin_len = sizeof(struct sockaddr_in);
+                       if (inet_aton(scopy, &su->scmpls.sinet.sin_addr) == 0)
+                               errx(1, "bad address: %s", scopy);
+               }
+
+               /* We don't have netmasks for tags  */
+               return 1;
#endif

       case AF_LINK:
@@ -1462,6 +1531,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_MPLS, soup->so_mpls);
       rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
       if (verbose && ! shortoutput) {
               if (rtm_addrs)
@@ -1568,7 +1638,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\011MPLS";


#ifndef SMALL
@@ -1733,7 +1803,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 +1849,9 @@ print_getmsg(struct rt_msghdr *rtm, int
                               case RTA_IFA:
                                       ifa = sa;
                                       break;
+                               case RTA_MPLS:
+                                       mpls = sa;
+                                       break;
                               }
                               ADVANCE(cp, sa);
                       }
@@ -1806,6 +1879,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("   MPLS Tag: %s\n", name);
+       }
+
       if (ifa && ! shortoutput)
               (void)printf(" local addr: %s\n",
                   routename(ifa, NULL, RTF_HOST));
@@ -1980,6 +2064,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->scmpls.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.39
diff -u -p -r1.39 show.c
--- sbin/route/show.c   17 Mar 2009 00:53:42 -0000      1.39
+++ sbin/route/show.c   17 Dec 2009 11:15:47 -0000
@@ -43,11 +43,13 @@ __RCSID("$NetBSD: show.c,v 1.39 2009/03/
#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,26 @@ p_sockaddr(struct sockaddr *sa, struct s
#endif /* INET6 */

#ifndef SMALL
+       case AF_MPLS:
+               {
+               struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)sa;
+               struct sockaddr_in *sin = (struct sockaddr_in *)(smpls + 1);
+               union mpls_shim ms;
+
+               ms.s_addr = ntohl(smpls->smpls_addr.s_addr);
+
+               if (sa->sa_len <= sizeof(struct sockaddr_mpls) ||
+                   sin->sin_family != AF_INET)
+                       snprintf(workbuf, sizeof(workbuf), "%u",
+                       ms.shim.label);
+               else
+                   snprintf(workbuf, sizeof(workbuf), "%s:%u",
+                       inet_ntoa(sin->sin_addr),
+                       ms.shim.label);
+               cp = workbuf;
+               }
+               break;
+
#endif /* SMALL */

       default:
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        17 Dec 2009 11:15:51 -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.259
diff -u -p -r1.259 GENERIC
--- sys/arch/amd64/conf/GENERIC 5 Dec 2009 20:11:03 -0000       1.259
+++ sys/arch/amd64/conf/GENERIC 17 Dec 2009 11:15:51 -0000
@@ -175,6 +175,8 @@ options     INET6           # IPV6
#options       IPSEC_ESP       # IP security (encryption part; define w/IPSEC)
#options       IPSEC_NAT_T     # IPsec NAT traversal (NAT-T)
#options       IPSEC_DEBUG     # debug for IP security
+#options       MPLS            # MultiProtocol Label Switching
+#options       MPLS_DEBUG      # debug for MPLS
#options       MROUTING        # IP multicast routing
#options       PIM             # Protocol Independent Multicast
#options       ISO,TPIP        # OSI
Index: sys/arch/arc/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/GENERIC,v
retrieving revision 1.162
diff -u -p -r1.162 GENERIC
--- sys/arch/arc/conf/GENERIC   5 Dec 2009 20:11:03 -0000       1.162
+++ sys/arch/arc/conf/GENERIC   17 Dec 2009 11:15:52 -0000
@@ -136,6 +136,7 @@ options     INET6           # IPV6
#options       IPSEC_ESP       # IP security (encryption part; define w/IPSEC)
#options       IPSEC_NAT_T     # IPsec NAT traversal (NAT-T)
#options       IPSEC_DEBUG     # debug for IP security
+options                MPLS            # MultiProtocol Label Switching
#options       MROUTING        # IP multicast routing
#options       PIM             # Protocol Independent Multicast
#options       ISO,TPIP        # OSI networking
Index: sys/arch/evbmips/conf/MALTA
===================================================================
RCS file: /cvsroot/src/sys/arch/evbmips/conf/MALTA,v
retrieving revision 1.53
diff -u -p -r1.53 MALTA
--- sys/arch/evbmips/conf/MALTA 5 Dec 2009 20:11:11 -0000       1.53
+++ sys/arch/evbmips/conf/MALTA 17 Dec 2009 11:15:52 -0000
@@ -91,6 +91,7 @@ options       INET            # Internet protocols
#options       IPSEC_ESP       # IP security (encryption part; define w/IPSEC)
#options       IPSEC_NAT_T     # IPsec NAT traversal (NAT-T)
#options       IPSEC_DEBUG     # debug for IP security
+options                MPLS            # MultiProtocol Label Switching
#options       MROUTING        # packet forwarding of multicast packets
#options       PIM             # Protocol Independent Multicast
#options       ISO,TPIP        # OSI networking
Index: sys/arch/i386/conf/ALL
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/ALL,v
retrieving revision 1.222
diff -u -p -r1.222 ALL
--- sys/arch/i386/conf/ALL      5 Dec 2009 20:11:15 -0000       1.222
+++ sys/arch/i386/conf/ALL      17 Dec 2009 11:15:53 -0000
@@ -218,6 +218,7 @@ options     IPSEC           # IP security
options        IPSEC_ESP       # IP security (encryption part; define w/IPSEC)
options        IPSEC_NAT_T     # IPsec NAT traversal (NAT-T)
#options       IPSEC_DEBUG     # debug for IP security
+options                MPLS            # MultiProtocol Label Switching
options        MROUTING        # IP multicast routing
options        PIM             # Protocol Independent Multicast
options        ISO,TPIP        # OSI
Index: sys/arch/i386/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC,v
retrieving revision 1.954
diff -u -p -r1.954 GENERIC
--- sys/arch/i386/conf/GENERIC  5 Dec 2009 20:11:15 -0000       1.954
+++ sys/arch/i386/conf/GENERIC  17 Dec 2009 11:15:54 -0000
@@ -213,6 +213,7 @@ options     INET6           # IPV6
#options       IPSEC_ESP       # IP security (encryption part; define w/IPSEC)
#options       IPSEC_NAT_T     # IPsec NAT traversal (NAT-T)
#options       IPSEC_DEBUG     # debug for IP security
+#options       MPLS            # MultiProtocol Label Switching
#options       MROUTING        # IP multicast routing
#options       PIM             # Protocol Independent Multicast
#options       ISO,TPIP        # OSI
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.967
diff -u -p -r1.967 files
--- sys/conf/files      5 Dec 2009 20:11:17 -0000       1.967
+++ sys/conf/files      17 Dec 2009 11:15:57 -0000
@@ -187,6 +187,7 @@ include "netipsec/files.netipsec"
include "netiso/files.netiso"
include "netnatm/files.netnatm"
include "netsmb/files.netsmb"
+include "netmpls/files.netmpls"
include "net/files.pf"

obsolete defflag               CCITT           # obsolete
Index: sys/dev/ic/ug.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/ug.c,v
retrieving revision 1.11
diff -u -p -r1.11 ug.c
--- sys/dev/ic/ug.c     26 Mar 2008 16:09:37 -0000      1.11
+++ sys/dev/ic/ug.c     17 Dec 2009 11:15:58 -0000
@@ -542,6 +542,9 @@ ug2_attach(device_t dv)
               aprint_error_dev(dv, "unable to register with sysmon\n");
               sysmon_envsys_destroy(sc->sc_sme);
       }
+
+       if (!pmf_device_register(dv, NULL, NULL))
+               aprint_error_dev(dv, "Unable to register with PMF\n");
}

void
Index: sys/net/if_ethersubr.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_ethersubr.c,v
retrieving revision 1.175
diff -u -p -r1.175 if_ethersubr.c
--- sys/net/if_ethersubr.c      28 Nov 2009 09:20:37 -0000      1.175
+++ sys/net/if_ethersubr.c      17 Dec 2009 11:16:00 -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"
@@ -181,6 +182,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;
@@ -255,7 +261,12 @@ ether_output(struct ifnet *ifp0, struct
                       } else
                               senderr(EHOSTUNREACH);
               }
-               if ((rt->rt_flags & RTF_GATEWAY) && dst->sa_family != AF_NS) {
+               if ((rt->rt_flags & RTF_GATEWAY) && dst->sa_family != AF_NS
+#ifdef MPLS
+                   && dst->sa_family != AF_MPLS) {
+#else
+                   ) {
+#endif
                       if (rt->rt_gwroute == NULL)
                               goto lookup;
                       if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
@@ -428,6 +439,51 @@ ether_output(struct ifnet *ifp0, struct
               } break;
#endif /* ISO */

+#ifdef MPLS
+               case AF_MPLS:
+               {
+                       const struct sockaddr *wsa = dst;
+                       const struct sockaddr_mpls *bsa = (const struct sockaddr_mpls *)dst;
+                       size_t wlen = sizeof(struct sockaddr_mpls);
+
+                       for (; wlen < dst->sa_len; wlen += wsa->sa_len)
+                               wsa = (const struct sockaddr *)
+                                   ((const char *)wsa + wsa->sa_len);
+
+                       switch (wsa->sa_family) {
+                           case AF_INET:
+                               if (!arpresolve(ifp, 0, m, wsa, edst))
+                                       return 0;       /* Not yet resolved */
+                               break;
+                           default:
+                               senderr(EHOSTUNREACH);
+                       }
+
+                       etype = htons(ETHERTYPE_MPLS);
+
+                       if (bsa->smpls_addr.shim.label == MPLS_LABEL_IMPLNULL) {
+                               /*
+                                * We have to POP label. I don't use
+                                * IP queue and prefer this way
+                                * because IP routing may give us a
+                                * different result.
+                                */
+                               switch(wsa->sa_family) {
+                                   case AF_INET:
+                                       etype = htons(ETHERTYPE_IP);
+                                       break;
+                                   case AF_INET6:
+                                       etype = htons(ETHERTYPE_IPV6);
+                                       break;
+                                   default:
+                                       goto bad;
+                               }
+                               m_adj(m, sizeof(union mpls_shim)); /* XXX: adj until bos */
+                       }
+               }
+               break;
+#endif /* MPLS */
+
       case pseudo_AF_HDRCMPLT:
               hdrcmplt = 1;
               memcpy(esrc,
@@ -456,6 +512,21 @@ ether_output(struct ifnet *ifp0, struct
        */
       if (etype == 0)
               etype = htons(m->m_pkthdr.len);
+#ifdef MPLS
+       /* Prepend mpls shim */
+       if (rt0 && rt0->rt_mpls) {
+               switch(dst->sa_family) {
+                   case AF_INET:
+                       m = mpls_label_inet(m, rt0->rt_mpls);
+                       etype = htons(ETHERTYPE_MPLS);
+                       break;
+                   case AF_INET6:
+                       m = mpls_label_inet6(m, rt0->rt_mpls);
+                       etype = htons(ETHERTYPE_MPLS);
+                       break;
+               }
+       }
+#endif /* MPLS */
       /*
        * Add local net header.  If no space in first mbuf,
        * allocate another.
@@ -510,7 +581,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:
@@ -642,6 +712,9 @@ ether_input(struct ifnet *ifp, struct mb
       /*
        * Determine if the packet is within its size limits.
        */
+#ifdef MPLS
+       if (etype != ETHERTYPE_MPLS)
+#endif
       if (m->m_pkthdr.len >
           ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) {
               if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count,
@@ -907,6 +980,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 /* MPLS */
               default:
                       m_freem(m);
                       return;
Index: sys/net/if_gre.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_gre.c,v
retrieving revision 1.141
diff -u -p -r1.141 if_gre.c
--- sys/net/if_gre.c    2 Sep 2009 14:56:57 -0000       1.141
+++ sys/net/if_gre.c    17 Dec 2009 11:16:00 -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 "bpfilter.h"

#include <sys/param.h>
@@ -102,6 +103,11 @@ __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1
#include <netatalk/at_extern.h>
#endif

+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif
+
#if NBPFILTER > 0
#include <sys/time.h>
#include <net/bpf.h>
@@ -905,7 +911,16 @@ gre_input(struct gre_softc *sc, struct m
               isr = NETISR_IPV6;
               af = AF_INET6;
               break;
-#endif
+#endif /* INET6 */
+
+#ifdef MPLS
+       case ETHERTYPE_MPLS:
+       case ETHERTYPE_MPLS_MCAST:
+               ifq = &mplsintrq;
+               isr = NETISR_MPLS;
+               af = AF_MPLS;
+               break;
+#endif /* MPLS */
       default:           /* others not yet supported */
               GRE_DPRINTF(sc, "unhandled ethertype 0x%04x\n",
                   ntohs(gh->ptype));
@@ -974,6 +989,13 @@ gre_output(struct ifnet *ifp, struct mbu
               /* TBD Extract the IP ToS field and set the
                * encapsulating protocol's ToS to suit.
                */
+#ifdef MPLS
+               if (rt->rt_mpls != NULL) {
+                       etype = htons(ETHERTYPE_MPLS);
+                       m = mpls_label_inet(m, rt->rt_mpls);
+                       break;
+               }
+#endif
               etype = htons(ETHERTYPE_IP);
               break;
#endif
@@ -984,9 +1006,21 @@ gre_output(struct ifnet *ifp, struct mbu
#endif
#ifdef INET6
       case AF_INET6:
+#ifdef MPLS
+               if (rt->rt_mpls != NULL) {
+                       etype = htons(ETHERTYPE_MPLS);
+                       m = mpls_label_inet6(m, rt->rt_mpls);
+                       break;
+               }
+#endif
               etype = htons(ETHERTYPE_IPV6);
               break;
#endif
+#ifdef MPLS
+       case AF_MPLS:
+               etype = htons(ETHERTYPE_MPLS);
+               break;
+#endif
       default:
               IF_DROP(&ifp->if_snd);
               m_freem(m);
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    17 Dec 2009 11:16:00 -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) */
@@ -91,6 +92,10 @@
#ifdef NETATALK
#include <netatalk/at_extern.h>
#endif
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#include <netmpls/mpls_var.h>
+#endif

#endif /* !defined(_LOCORE) */
#endif /* defined(_KERNEL) */
@@ -112,6 +117,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   17 Dec 2009 11:16:00 -0000
@@ -45,5 +45,8 @@
#ifdef NATM
       DONETISR(NETISR_NATM,natmintr);
#endif
+#ifdef MPLS
+       DONETISR(NETISR_MPLS,mplsintr);
+#endif

#endif /* !_NET_NETISR_DISPATCH_H_ */
Index: sys/net/route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.121
diff -u -p -r1.121 route.c
--- sys/net/route.c     3 Nov 2009 00:30:11 -0000       1.121
+++ sys/net/route.c     17 Dec 2009 11:16:00 -0000
@@ -118,6 +118,8 @@ __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.
#include <netinet/in.h>
#include <netinet/in_var.h>

+#include <netmpls/mpls.h>
+
#ifdef RTFLUSH_DEBUG
#define        rtcache_debug() __predict_false(_rtcache_debug)
#else /* RTFLUSH_DEBUG */
@@ -373,6 +375,7 @@ rtalloc1(const struct sockaddr *dst, int
                                   rt->rt_ifp->if_dl->ifa_addr;
                               info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
                       }
+                       info.rti_info[RTAX_MPLS] = (struct sockaddr *)rt->rt_mpls;
                       rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0);
               } else
                       rt->rt_refcnt++;
@@ -495,6 +498,7 @@ rtredirect(const struct sockaddr *dst, c
                       info.rti_info[RTAX_NETMASK] = netmask;
                       info.rti_ifa = ifa;
                       info.rti_flags = flags;
+                       info.rti_info[RTAX_MPLS] = NULL;
                       rt = NULL;
                       error = rtrequest1(RTM_ADD, &info, &rt);
                       if (rt != NULL)
@@ -737,6 +741,7 @@ rtrequest1(int req, struct rt_addrinfo *
                       RTFREE(rt->rt_gwroute);
                       rt->rt_gwroute = NULL;
               }
+               rt_setmpls(rt, NULL);
               if (rt->rt_parent) {
                       rt->rt_parent->rt_refcnt--;
                       rt->rt_parent = NULL;
@@ -805,6 +810,7 @@ rtrequest1(int req, struct rt_addrinfo *
               rt_set_ifa(rt, ifa);
               RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
               rt->rt_ifp = ifa->ifa_ifp;
+               rt_setmpls(rt, info->rti_info[RTAX_MPLS]);
               if (req == RTM_RESOLVE) {
                       rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
                       rt->rt_parent = *ret_nrt;
@@ -1407,3 +1413,19 @@ rt_walktree(sa_family_t family, int (*f)

       return rn_walktree(rnh, rt_walktree_visitor, &rw);
}
+
+void
+rt_setmpls(struct rtentry *rt, const struct sockaddr *s)
+{
+       if (rt->rt_mpls != NULL) {
+               sockaddr_free((struct sockaddr *)rt->rt_mpls);
+               rt->rt_mpls = NULL;
+       }
+
+       if (s == NULL)
+               return;
+
+       rt->rt_mpls = (struct sockaddr_mpls*)sockaddr_dup(s, M_NOWAIT);
+
+       KASSERT(rt->rt_mpls != NULL);
+}
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     17 Dec 2009 11:16:01 -0000
@@ -124,6 +124,7 @@ struct rtentry {
       void *  rt_llinfo;              /* pointer to link level info cache */
       struct  nrt_metrics rt_rmx;     /* metrics used by rx'ing protocols */
       struct  rtentry *rt_gwroute;    /* implied entry for gatewayed routes */
+       struct  sockaddr_mpls *rt_mpls; /* MPLS tag */
       LIST_HEAD(, rttimer) rt_timer;  /* queue of timeouts for misc funcs */
       struct  rtentry *rt_parent;     /* parent of cloned route */
       struct sockaddr *_rt_key;
@@ -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_MPLS        0x100   /* MPLS */

/*
 * 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_MPLS       8       /* MPLS */
+#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;
};

@@ -349,6 +353,7 @@ void         rt_maskedcopy(const struct sockadd
void    rt_missmsg(int, struct rt_addrinfo *, int, int);
struct mbuf *rt_msg1(int, struct rt_addrinfo *, void *, int);
void    rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
+void    rt_setmpls(struct rtentry *, const struct sockaddr *);
int     rt_setgate(struct rtentry *, const struct sockaddr *);
void    rt_setmetrics(u_long, const struct rt_metrics *, struct nrt_metrics *);
int      rt_timer_add(struct rtentry *,
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvsroot/src/sys/net/rtsock.c,v
retrieving revision 1.127
diff -u -p -r1.127 rtsock.c
--- sys/net/rtsock.c    16 Sep 2009 15:23:04 -0000      1.127
+++ sys/net/rtsock.c    17 Dec 2009 11:16:01 -0000
@@ -64,6 +64,7 @@
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.127 2009/09/16 15:23:04 pooka Exp $");

#include "opt_inet.h"
+#include "opt_mpls.h"
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
#endif
@@ -87,6 +88,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
+
#if defined(COMPAT_14) || defined(COMPAT_50)
#include <compat/net/if.h>
#endif
@@ -128,12 +133,17 @@ 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;
+#ifdef MPLS
+       case AF_MPLS:
+               route_cb.mpls_count += cnt;
+               return;
+#endif /* MPLS */
+       case AF_NS:
+               route_cb.ns_count += cnt;
+               return;
       }
}

@@ -339,6 +349,9 @@ 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);
+#ifdef MPLS
+                       info.rti_info[RTAX_MPLS] = (struct sockaddr*)rt->rt_mpls;
+#endif
                       if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0)
                               ;
                       else if ((ifp = rt->rt_ifp) != NULL) {
@@ -403,6 +416,9 @@ route_output(struct mbuf *m, ...)
                       if (info.rti_info[RTAX_GATEWAY] &&
                           rt_setgate(rt, info.rti_info[RTAX_GATEWAY]))
                               senderr(EDQUOT);
+#ifdef MPLS
+                       rt_setmpls(rt, info.rti_info[RTAX_MPLS]);
+#endif
                       /* 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       17 Dec 2009 11:16:01 -0000
@@ -177,8 +177,6 @@ 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);
-
static void sysctl_netinet_icmp_setup(struct sysctllog **);

void
@@ -1251,7 +1249,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       17 Dec 2009 11:16:01 -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/netinet/ip_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_output.c,v
retrieving revision 1.205
diff -u -p -r1.205 ip_output.c
--- sys/netinet/ip_output.c     17 Jul 2009 22:02:54 -0000      1.205
+++ sys/netinet/ip_output.c     17 Dec 2009 11:16:02 -0000
@@ -97,6 +97,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>
@@ -778,6 +779,12 @@ spd_done:
       if (IN_NEED_CHECKSUM(ifp, M_CSUM_IPv4)) {
               m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
       }
+#ifdef MPLS
+       /* don't let interface compute cksum */
+       if (rt && rt->rt_mpls != NULL)
+               sw_csum = m->m_pkthdr.csum_flags;
+       else
+#endif
       sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
       /*
        * If small enough for mtu of path, or if using TCP segmentation
Index: sys/netinet/udp_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.179
diff -u -p -r1.179 udp_usrreq.c
--- sys/netinet/udp_usrreq.c    16 Sep 2009 15:23:05 -0000      1.179
+++ sys/netinet/udp_usrreq.c    17 Dec 2009 11:16:02 -0000
@@ -768,16 +768,24 @@ udp4_realinput(struct sockaddr_in *src,
                * Locate pcb(s) for datagram.
                */
               CIRCLEQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) {
+                       int i;
+#define        inmopts (inp->inp_moptions)
                       inp = (struct inpcb *)inph;
                       if (inp->inp_af != AF_INET)
                               continue;
-
-                       if (inp->inp_lport != *dport)
+                       if (inmopts == NULL)
                               continue;
-                       if (!in_nullhost(inp->inp_laddr)) {
-                               if (!in_hosteq(inp->inp_laddr, *dst4))
-                                       continue;
+                       for (i = 0; i < inmopts->imo_num_memberships; i++) {
+                               if (inmopts->imo_membership[i]->inm_ifp ==
+                                       m->m_pkthdr.rcvif &&
+                                   in_hosteq(*dst4,
+                                       inmopts->imo_membership[i]->inm_addr))
+                                           break;
                       }
+                       if (i == inmopts->imo_num_memberships)
+                               continue;
+                       if (inp->inp_lport != *dport)
+                               continue;
                       if (!in_nullhost(inp->inp_faddr)) {
                               if (!in_hosteq(inp->inp_faddr, *src4) ||
                                   inp->inp_fport != *sport)
Index: sys/netinet6/ip6_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.139
diff -u -p -r1.139 ip6_output.c
--- sys/netinet6/ip6_output.c   7 May 2009 21:51:47 -0000       1.139
+++ sys/netinet6/ip6_output.c   17 Dec 2009 11:16:03 -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>
@@ -969,6 +970,11 @@ skip_ipsec2:;
               ipsec_delaux(m);
#endif

+#ifdef MPLS
+               if (rt != NULL && rt->rt_mpls != NULL)
+                       sw_csum = m->m_pkthdr.csum_flags;
+               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,
Index: sys/sys/mbuf.h
===================================================================
RCS file: /cvsroot/src/sys/sys/mbuf.h,v
retrieving revision 1.144
diff -u -p -r1.144 mbuf.h
--- sys/sys/mbuf.h      24 Oct 2008 22:31:40 -0000      1.144
+++ sys/sys/mbuf.h      17 Dec 2009 11:16:03 -0000
@@ -890,6 +890,8 @@ struct      m_tag *m_tag_next(struct mbuf *,
                                                   * loop detection/recovery
                                                   */

+#define        PACKET_TAG_MPLS                         69 /* MPLS */
+
/*
 * Return the number of bytes in the mbuf chain, m.
 */
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    17 Dec 2009 11:16:03 -0000
@@ -210,8 +210,9 @@ struct      accept_filter_arg {
#endif
#define AF_BLUETOOTH   31              /* Bluetooth: HCI, SCO, L2CAP, RFCOMM */
#define        AF_IEEE80211    32              /* IEEE80211 */
+#define        AF_MPLS         33              /* MPLS */

-#define        AF_MAX          33
+#define        AF_MAX          34

/*
 * Structure used by kernel to store most
@@ -300,6 +301,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

@@ -377,6 +379,7 @@ struct sockcred {
       { "natm", CTLTYPE_NODE }, \
       { "arp", CTLTYPE_NODE }, \
       { "key", CTLTYPE_NODE }, \
+       { "mpls", CTLTYPE_NODE }, \
}

struct kinfo_pcb {
Index: usr.bin/netstat/Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/netstat/Makefile,v
retrieving revision 1.29
diff -u -p -r1.29 Makefile
--- usr.bin/netstat/Makefile    14 Sep 2009 10:36:50 -0000      1.29
+++ usr.bin/netstat/Makefile    17 Dec 2009 11:16:05 -0000
@@ -15,6 +15,7 @@ BINMODE=2555
LDADD= -lkvm
DPADD= ${LIBKVM}
CPPFLAGS+= -DIPSEC
+CPPFLAGS+= -DMPLS
CPPFLAGS+= -I${NETBSDSRCDIR}/sys/dist/pf

.if (${USE_INET6} != "no")
Index: usr.bin/netstat/main.c
===================================================================
RCS file: /cvsroot/src/usr.bin/netstat/main.c,v
retrieving revision 1.73
diff -u -p -r1.73 main.c
--- usr.bin/netstat/main.c      14 Sep 2009 10:36:51 -0000      1.73
+++ usr.bin/netstat/main.c      17 Dec 2009 11:16:05 -0000
@@ -462,6 +462,10 @@ main(argc, argv)
                               af = AF_ISO;
                       else if (strcmp(optarg, "atalk") == 0)
                               af = AF_APPLETALK;
+#ifdef MPLS
+                       else if (strcmp(optarg, "mpls") == 0)
+                               af = AF_MPLS;
+#endif
                       else
                               errx(1, "%s: unknown address family",
                                   optarg);
Index: usr.bin/netstat/netstat.h
===================================================================
RCS file: /cvsroot/src/usr.bin/netstat/netstat.h,v
retrieving revision 1.39
diff -u -p -r1.39 netstat.h
--- usr.bin/netstat/netstat.h   14 Sep 2009 10:36:51 -0000      1.39
+++ usr.bin/netstat/netstat.h   17 Dec 2009 11:16:05 -0000
@@ -142,6 +142,10 @@ const char *atalk_print2 __P((const stru
char   *ns_print __P((struct sockaddr *));
void   routepr __P((u_long));

+#ifdef MPLS
+char   *mpls_ntoa(const struct sockaddr *);
+#endif
+
void   nsprotopr __P((u_long, const char *));
void   spp_stats __P((u_long, const char *));
void   idp_stats __P((u_long, const char *));
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      17 Dec 2009 11:16:05 -0000
@@ -45,6 +45,9 @@
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
+#ifdef MPLS
+#include <netmpls/mpls.h>
+#endif

#include <err.h>
#include <errno.h>
@@ -288,6 +291,9 @@ pr_family(int paf)
       case AF_APPLETALK:
               afname = "AppleTalk";
               break;
+       case AF_MPLS:
+               afname = "MPLS";
+               break;
       default:
               afname = NULL;
               break;
@@ -419,6 +425,10 @@ routename(struct sockaddr *sa)

       case AF_LINK:
               return (link_print(sa));
+#ifdef MPLS
+       case AF_MPLS:
+               return mpls_ntoa(sa);
+#endif

#if 0 /* XXX-elad */
       case AF_UNSPEC:
@@ -637,6 +647,11 @@ netname(struct sockaddr *sa, struct sock
#endif
       case AF_LINK:
               return (link_print(sa));
+#ifdef MPLS
+       case AF_MPLS:
+               strlcpy(line, "Invalid MPLS Network", sizeof(line));
+               break;
+#endif
       default:
               snprintf(line, sizeof(line), "af %d: %s",
                   sa->sa_family, any_ntoa(sa));
@@ -665,6 +680,32 @@ any_ntoa(const struct sockaddr *sa)
       return (obuf);
}

+#ifdef MPLS
+char *
+mpls_ntoa(const struct sockaddr *sa)
+{
+       static char obuf[100];
+       const struct sockaddr_mpls *sm;
+       const struct sockaddr_in *si;
+       union mpls_shim ms;
+
+       sm = (const struct sockaddr_mpls*)sa;
+       ms.s_addr = ntohl(sm->smpls_addr.s_addr);
+
+       if (sm->smpls_len > sizeof(struct sockaddr_mpls)) {
+               si = (const struct sockaddr_in*)(sm + 1);
+               snprintf(obuf, sizeof(obuf), "%s:%d",
+                   inet_ntoa(si->sin_addr),
+                   ms.shim.label);
+       } else
+               snprintf(obuf, sizeof(obuf), "%u",
+                    ms.shim.label);
+
+       return obuf;
+}
+
+#endif
+
char *
link_print(struct sockaddr *sa)
{
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   17 Dec 2009 11:16:06 -0000
@@ -11,7 +11,7 @@ SUBDIR=       ac accton acpitools altq apm apm
       gpioctl grfconfig grfinfo gspa hdaudioctl hilinfo ifwatchd inetd \
       installboot \
       iopctl iostat ipwctl irdaattach isdn iteconfig iwictl\
-       kgmon lastlogin link lmcconfig lockstat lpr mailwrapper makefs \
+       kgmon lastlogin ldpd 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 \
Index: usr.sbin/postinstall/postinstall
===================================================================
RCS file: /cvsroot/src/usr.sbin/postinstall/postinstall,v
retrieving revision 1.106
diff -u -p -r1.106 postinstall
--- usr.sbin/postinstall/postinstall    13 Oct 2009 07:47:00 -0000      1.106
+++ usr.sbin/postinstall/postinstall    17 Dec 2009 11:16:08 -0000
@@ -1059,7 +1059,7 @@ do_rc()
               identd ifwatchd inetd ipfilter ipfs ipmon ipnat ipsec \
               irdaattach iscsi_target isdnd \
               kdc \
-               ldconfig local lpd lvm\
+               ldpd ldconfig local lpd lvm\
               mdnsd mixerctl mopd motd mountall mountcritlocal \
               mountcritremote mountd moused mrouted \
               named ndbootd network newsyslog nfsd nfslocking ntpd ntpdate \