I've being working on a project that involves MPLS and OpenBSD, I
recently started coding and I would really love to get some
comments/advices about it.

This thread will contain code about the wire(4) pseudo device (RFC4448),
it will be used in the future by ldpd(8) or ifconfig(8) to configure
pseudowires (RFC4447). This device will allow us to develop VPLS support
in LDPd later (RFC4762).

Since I'm quite new to this expect rough edges.


NOTE: some files didn't exist, so I inlined then in the diff.
NOTE2: this is a really early development stage, this was not tested, it
just compiles.



? net/if_mpe.h
/*
 * Copyright (c) 2012 Rafael F. Zalamena <rzalam...@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

struct mpe_softc {
        struct ifnet            sc_if;          /* the interface */
        int                     sc_unit;
        struct shim_hdr         sc_shim;
        LIST_ENTRY(mpe_softc)   sc_list;
};

int              mpe_newlabel(struct ifnet *, int, struct shim_hdr *);

? net/if_wire.c
/*
 * Copyright (c) 2012 Rafael F. Zalamena <rzalam...@gmail.com>
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "bpfilter.h"
#include "vlan.h"

#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <machine/cpu.h>

#include <net/if.h>
#include <net/if_types.h>
#include <net/if_llc.h>
#include <net/route.h>
#include <net/netisr.h>

#ifdef INET
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/if_ether.h>
#include <netinet/ip_icmp.h>
#endif

#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#endif

#if NBPFILTER > 0
#include <net/bpf.h>
#endif

#include <netmpls/mpls.h>

#include <net/if_mpe.h>
#include <net/if_wire.h>

#ifdef WIRE_DEBUG
#define DPRINTF(fmt, args...)   printf("wire: " fmt, ## args)
#else
#define DPRINTF(fmt, args...)
#endif


void             wireattach(int);
int              wire_clone_create(struct if_clone *, int);
int              wire_clone_destroy(struct ifnet *);
int              wire_ioctl(struct ifnet *, u_long, caddr_t);
void             wire_init(struct wire_softc *);
void             wire_stop(struct wire_softc *);
int              wire_output(struct ifnet *, struct mbuf *,
                        struct sockaddr *, struct rtentry *);
void             wire_start(struct ifnet *);
struct mbuf     *wire_input(struct ether_header *, struct mbuf *);

LIST_HEAD(, wire_softc) wire_list;

struct if_clone wire_cloner =
    IF_CLONE_INITIALIZER("wire", wire_clone_create, wire_clone_destroy);

/* ARGSUSED */
void
wireattach(int n)
{
        LIST_INIT(&wire_list);
        if_clone_attach(&wire_cloner);
}

int
wire_clone_create(struct if_clone *ifc, int unit)
{
        struct wire_softc       *sc;
        struct ifnet            *ifp;
        int                      s;

        sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO);
        if (sc == NULL)
                return (ENOMEM);

        ifp = &sc->sc_if;
        snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
            ifc->ifc_name, unit);
        ifp->if_softc = sc;
        ifp->if_mtu = ETHERMTU;
        ifp->if_flags = IFF_POINTOPOINT;
        ifp->if_ioctl = wire_ioctl;
        ifp->if_output = wire_output;
        ifp->if_start = wire_start;
        ifp->if_type = IFT_MPLSTUNNEL;
        ifp->if_hdrlen = ETHER_HDR_LEN;
        IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
        IFQ_SET_READY(&ifp->if_snd);

        if_attach(ifp);
        if_alloc_sadl(ifp);

#if NBPFILTER > 0
        bpfattach(&sc->sc_if.if_bpf, ifp,
            DLT_EN10MB, ETHER_HDR_LEN);
#endif

        s = splnet();
        LIST_INSERT_HEAD(&wire_list, sc, sc_list);
        splx(s);

        return (0);
}

int
wire_clone_destroy(struct ifnet *ifp)
{
        struct wire_softc       *sc = ifp->if_softc;
        int                      s;

        wire_stop(sc);

        s = splnet();
        LIST_REMOVE(sc, sc_list);
        splx(s);

        if_detach(ifp);

        free(sc, M_DEVBUF);
        return (0);
}

int
wire_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
        struct ifwreq           *req = (struct ifwreq *) data;
        struct ifnet            *ifs, *ifm;
        struct ifreq            *ifreq = (struct ifreq *) data;
        struct wire_softc       *sc;
        int                      error = 0, s;
        struct shim_hdr          shim;
        struct ifreq             ifreq_aux;

        s = splnet();
        sc = (struct wire_softc *) &ifp->if_softc;
        switch (cmd) {
        case SIOCSETLABEL:
                if ((error = copyin(ifreq->ifr_data, &shim, sizeof(shim))))
                        break;
                if (shim.shim_label > MPLS_LABEL_MAX ||
                    shim.shim_label <= MPLS_LABEL_RESERVED_MAX) {
                        error = EINVAL;
                        break;
                }
                shim.shim_label = htonl(shim.shim_label << MPLS_LABEL_OFFSET);
                if (sc->sc_shim.shim_label == shim.shim_label)
                        break;

                if (sc->sc_shim.shim_label) {
                        /* remove old MPLS route */
                        mpe_newlabel(ifp, RTM_DELETE, &sc->sc_shim);
                }
                /* add new MPLS route */
                error = mpe_newlabel(ifp, RTM_ADD, &shim);
                if (error)
                        break;
                sc->sc_shim.shim_label = shim.shim_label;

                if ((error = copyin(ifreq->ifr_data, &shim, sizeof(shim))))
                        break;

                if ((shim.shim_label < MPLS_LABEL_RESERVED_MAX) ||
                    (shim.shim_label > MPLS_LABEL_MAX)) {
                        error = EINVAL;
                        break;
                }
                if (mpls_shim_label_exists(&shim)) {
                        error = EEXIST;
                        break;
                }

                if (sc->sc_shim.shim_label)
                        mpe_newlabel(ifp, RTM_DELETE, &sc->sc_shim);

                /* add new MPLS route */
                error = mpe_newlabel(ifp, RTM_ADD, &shim);
                sc->sc_shim.shim_label = shim.shim_label;
                break;

        case SIOCGETLABEL:
                shim.shim_label =
                    ((ntohl(sc->sc_shim.shim_label & MPLS_LABEL_MASK)) >>
                        MPLS_LABEL_OFFSET);
                error = copyout(&shim, ifreq->ifr_data, sizeof(shim));
                break;

        case SIOCWIREADD:
                if ((error = suser(curproc, 0)) != 0)
                        break;

                /* Get mpe output interface */
                ifm = ifunit(req->ifwr_mpename);
                if (ifm == NULL) {
                        error = ENOENT;
                        break;
                }
                if (ifm->if_type != IFT_MPLS) {
                        error = EINVAL;
                        break;
                }

                /* Get ethernet input interface */
                ifs = ifunit(req->ifwr_ifsname);
                if (ifs == NULL) {
                        error = ENOENT;
                        break;
                }
                if (ifs->if_type != IFT_ETHER) {
                        error = EINVAL;
                        break;
                }

                /* Set input interface to promiscuos mode */
                if ((ifs->if_flags & IFF_UP) == 0) {
                        /*
                         * Bring interface up long enough to set
                         * promiscuous flag, then shut it down again.
                         */
                        strlcpy(ifreq_aux.ifr_name, req->ifwr_ifsname,
                            IFNAMSIZ);
                        ifs->if_flags |= IFF_UP;
                        ifreq_aux.ifr_flags = ifs->if_flags;
                        error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
                            (caddr_t) &ifreq_aux);
                        if (error != 0)
                                break;

                        error = ifpromisc(ifs, 1);
                        if (error != 0)
                                break;

                        strlcpy(ifreq_aux.ifr_name, req->ifwr_ifsname,
                            IFNAMSIZ);
                        ifs->if_flags &= ~IFF_UP;
                        ifreq_aux.ifr_flags = ifs->if_flags;
                        error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
                            (caddr_t) &ifreq_aux);
                        if (error != 0) {
                                ifpromisc(ifs, 0);
                                break;
                        }
                } else {
                        error = ifpromisc(ifs, 1);
                        if (error != 0)
                                break;
                }

                sc->sc_ifmpe = ifm;
                sc->sc_ifs = ifs;
                ifs->if_wire = (caddr_t) sc;
                break;

        case SIOCWIREDEL:
                if ((error = suser(curproc, 0)) != 0)
                        break;

                ifs = ifunit(req->ifwr_ifsname);
                if (ifs == NULL) {
                        error = ENOENT;
                        break;
                }
                if (ifs->if_wire == NULL) {
                        error = ENXIO;
                        break;
                }
                wire_stop(sc);
                ifs->if_wire = NULL;
                sc->sc_ifs = NULL;
                sc->sc_ifmpe = NULL;
                break;

        case SIOCSIFFLAGS:
                if ((ifp->if_flags & IFF_UP))
                        wire_init(sc);
                else
                        wire_stop(sc);
                break;

        default:
                error = ENOTTY;
                break;
        }
        splx(s);
        return (error);
}

void
wire_ifdetach(struct ifnet *ifp)
{
        struct wire_softc       *sc;

        sc = (struct wire_softc *) ifp->if_wire;
        sc->sc_ifs = NULL;

        wire_stop(sc);
        ifpromisc(ifp, 0);
}

void
wire_init(struct wire_softc *sc)
{
        struct ifnet *ifp = &sc->sc_if;

        if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING)
                return;

        ifp->if_flags |= IFF_RUNNING;
}

void
wire_stop(struct wire_softc *sc)
{
        struct ifnet    *ifp = &sc->sc_if;

        if ((ifp->if_flags & IFF_RUNNING) == 0)
                return;

        ifp->if_flags &= ~IFF_RUNNING;
}

int
wire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
    struct rtentry *rt)
{
        struct ip       *ip;
        int              off;
        int              s;
        int              error = 0;
        u_int8_t         op = 0;
        struct shim_hdr  shim;

        m->m_pkthdr.rcvif = ifp;
        m->m_pkthdr.rdomain = 0;

        error = 0;
        switch (sa->sa_family) {
#ifdef INET
        case AF_INET:
                if (rt && rt->rt_flags & RTF_MPLS) {
                        shim.shim_label =
                            ((struct rt_mpls *) rt->rt_llinfo)->mpls_label;
                        shim.shim_label |= MPLS_BOS_MASK;
                        op = ((struct rt_mpls *) rt->rt_llinfo)->mpls_operation;
                }
                if (op != MPLS_OP_PUSH) {
                        m_freem(m);
                        error = ENETUNREACH;
                        goto out;
                }
                if (mpls_mapttl_ip) {
                        ip = mtod(m, struct ip *);
                        shim.shim_label |= htonl(ip->ip_ttl) & MPLS_TTL_MASK;
                } else
                        shim.shim_label |= htonl(mpls_defttl) & MPLS_TTL_MASK;

                off = sizeof(sa_family_t) + sizeof(in_addr_t);
                M_PREPEND(m, sizeof(shim) + off, M_DONTWAIT);
                if (m == NULL) {
                        error = ENOBUFS;
                        goto out;
                }
                *mtod(m, sa_family_t *) = AF_INET;
                m_copyback(m, sizeof(sa_family_t), sizeof(in_addr_t),
                    (caddr_t) &((satosin(sa)->sin_addr)), M_NOWAIT);
                break;
#endif
        default:
                m_freem(m);
                error = EPFNOSUPPORT;
                goto out;
        }

        m_copyback(m, off, sizeof(shim), (caddr_t) &shim, M_NOWAIT);

        s = splnet();
        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
        if (error) {
                /* mbuf is already freed */
                splx(s);
                goto out;
        }
        if_start(ifp);
        splx(s);

out:
        if (error)
                ifp->if_oerrors++;
        return (error);
}

void
wire_start(struct ifnet *ifp)
{
        struct mbuf             *m;
        struct sockaddr         *sa;
        int                      s;
        sa_family_t              af;
        struct rtentry          *rt;
        struct wire_softc       *sc;
        struct ifnet            *ifmpe;
        struct sockaddr_mpls     wiredst;

        for (;;) {
                s = splnet();
                IFQ_DEQUEUE(&ifp->if_snd, m);
                splx(s);

                if (m == NULL)
                        return;

                af = *mtod(m, sa_family_t *);
                m_adj(m, sizeof(af));
                switch (af) {
                case AF_INET:
                        sa = (struct sockaddr *)&wiredst;
                        bzero(sa, sizeof(struct sockaddr_in));
                        satosin(sa)->sin_family = af;
                        satosin(sa)->sin_len = sizeof(struct sockaddr_in);
                        bcopy(mtod(m, caddr_t), &satosin(sa)->sin_addr,
                            sizeof(in_addr_t));
                        m_adj(m, sizeof(in_addr_t));
                        break;

                default:
                        m_freem(m);
                        continue;
                }

                rt = rtalloc1(sa, RT_REPORT, 0);
                if (rt == NULL) {
                        /* no route give up */
                        m_freem(m);
                        continue;
                }

#if NBPFILTER > 0
                if (ifp->if_bpf) {
                        /* remove MPLS label before passing packet to bpf */
                        m->m_data += sizeof(struct shim_hdr);
                        m->m_len -= sizeof(struct shim_hdr);
                        m->m_pkthdr.len -= sizeof(struct shim_hdr);
                        bpf_mtap_af(ifp->if_bpf, af, m, BPF_DIRECTION_OUT);
                        m->m_data -= sizeof(struct shim_hdr);
                        m->m_len += sizeof(struct shim_hdr);
                        m->m_pkthdr.len += sizeof(struct shim_hdr);
                }
#endif
                sa->sa_family = AF_MPLS;

                sc = (struct wire_softc *) ifp->if_softc;
                ifmpe = sc->sc_ifmpe;
                if (ifmpe == NULL) {
                        m_freem(m);
                        continue;
                }
                ifmpe->if_output(ifmpe, m, sa, rt);
                RTFREE(rt);
        }
}

struct mbuf *
wire_input(struct ether_header *eh, struct mbuf *m)
{
        /* TODO  */
        return (NULL);
}

? net/if_wire.h
/*
 * Copyright (c) 2012 Rafael F. Zalamena <rzalam...@gmail.com>
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _NET_IF_WIRE_H_
#define _NET_IF_WIRE_H_

struct ifwreq {
        char                             ifwr_name[IFNAMSIZ];
        char                             ifwr_ifsname[IFNAMSIZ];
        char                             ifwr_mpename[IFNAMSIZ];
};

struct wire_softc {
        struct ifnet                     sc_if;         /* the interface */
        struct ifnet                    *sc_ifmpe;      /* Interfaces to 
exchange packets */
        struct ifnet                    *sc_ifs;
        struct shim_hdr                  sc_shim;

        LIST_ENTRY(wire_softc)           sc_list;       /* linked wire list */
};

void     wire_ifdetach(struct ifnet *);

#endif /* _NET_IF_WIRE_H_ */

Index: conf/GENERIC
===================================================================
RCS file: /backup/obsd_cvs//src/sys/conf/GENERIC,v
retrieving revision 1.189
diff -u -r1.189 GENERIC
--- conf/GENERIC        26 Jul 2012 15:52:28 -0000      1.189
+++ conf/GENERIC        22 Aug 2012 02:48:07 -0000
@@ -66,6 +66,7 @@
 option         MROUTING        # Multicast router
 #option                PIM             # Protocol Independent Multicast
 option         MPLS            # Multi-Protocol Label Switching
+option         WIRE_DEBUG      # Wire debugging messages
 
 #mpath0                at root         # SCSI Multipathing
 #scsibus*      at mpath?
@@ -93,6 +94,7 @@
 # clonable devices
 pseudo-device  bpfilter        # packet filter
 pseudo-device  bridge          # network bridging support
+pseudo-device  wire            # pseudowire support
 pseudo-device  carp            # CARP protocol support
 pseudo-device  gif             # IPv[46] over IPv[46] tunnel (RFC1933)
 pseudo-device  gre             # GRE encapsulation interface
Index: conf/files
===================================================================
RCS file: /backup/obsd_cvs//src/sys/conf/files,v
retrieving revision 1.537
diff -u -r1.537 files
--- conf/files  26 Apr 2012 01:22:31 -0000      1.537
+++ conf/files  22 Aug 2012 02:48:07 -0000
@@ -518,6 +518,7 @@
 pseudo-device bpfilter: ifnet
 pseudo-device enc: ifnet
 pseudo-device bridge: ifnet, ether
+pseudo-device wire: ifnet, ether
 pseudo-device vlan: ifnet, ether
 pseudo-device carp: ifnet, ether
 pseudo-device sppp: ifnet
@@ -758,6 +759,7 @@
 file net/if_bridge.c                   bridge                  needs-count
 file net/bridgestp.c                   bridge
 file net/if_vlan.c                     vlan                    needs-count
+file net/if_wire.c                     wire                    needs-count
 file net/pipex.c                       pipex
 file net/radix.c
 file net/radix_mpath.c                 !small_kernel
Index: net/if.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/net/if.c,v
retrieving revision 1.241
diff -u -r1.241 if.c
--- net/if.c    3 Jan 2012 23:41:51 -0000       1.241
+++ net/if.c    22 Aug 2012 02:48:08 -0000
@@ -124,6 +124,10 @@
 #include <net/if_bridge.h>
 #endif
 
+#if NWIRE > 0
+#include <net/if_wire.h>
+#endif
+
 #if NCARP > 0
 #include <netinet/ip_carp.h>
 #endif
@@ -533,6 +537,10 @@
        /* Remove the interface from any bridge it is part of.  */
        if (ifp->if_bridge)
                bridge_ifdetach(ifp);
+#endif
+#if NWIRE > 0
+       if (ifp->if_wire)
+               wire_ifdetach(ifp);
 #endif
 
 #if NCARP > 0
Index: net/if.h
===================================================================
RCS file: /backup/obsd_cvs//src/sys/net/if.h,v
retrieving revision 1.131
diff -u -r1.131 if.h
--- net/if.h    2 Dec 2011 03:15:31 -0000       1.131
+++ net/if.h    22 Aug 2012 02:48:08 -0000
@@ -251,6 +251,7 @@
        int     if_pcount;              /* number of promiscuous listeners */
        caddr_t if_bpf;                 /* packet filter structure */
        caddr_t if_bridge;              /* bridge structure */
+       caddr_t if_wire;                /* wire structure */
        caddr_t if_tp;                  /* used by trunk ports */
        caddr_t if_pf_kif;              /* pf interface abstraction */
        union {
Index: net/if_mpe.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/net/if_mpe.c,v
retrieving revision 1.27
diff -u -r1.27 if_mpe.c
--- net/if_mpe.c        14 Apr 2012 09:39:47 -0000      1.27
+++ net/if_mpe.c        22 Aug 2012 02:48:08 -0000
@@ -51,6 +51,8 @@
 
 #include <netmpls/mpls.h>
 
+#include <net/if_mpe.h>
+
 #ifdef MPLS_DEBUG
 #define DPRINTF(x)    do { if (mpedebug) printf x ; } while (0)
 #else
@@ -324,12 +326,9 @@
                shim.shim_label = htonl(shim.shim_label << MPLS_LABEL_OFFSET);
                if (ifm->sc_shim.shim_label == shim.shim_label)
                        break;
-               LIST_FOREACH(ifm, &mpeif_list, sc_list) {
-                       if (ifm != ifp->if_softc &&
-                           ifm->sc_shim.shim_label == shim.shim_label) {
-                               error = EEXIST;
-                               break;
-                       }
+               if (mpls_shim_label_exists(&shim)) {
+                       error = EEXIST;
+                       break;
                }
                if (error)
                        break;
Index: netmpls/mpls.h
===================================================================
RCS file: /backup/obsd_cvs//src/sys/netmpls/mpls.h,v
retrieving revision 1.25
diff -u -r1.25 mpls.h
--- netmpls/mpls.h      8 Sep 2010 08:00:56 -0000       1.25
+++ netmpls/mpls.h      22 Aug 2012 02:48:08 -0000
@@ -145,13 +145,6 @@
 
 #ifdef _KERNEL
 
-struct mpe_softc {
-       struct ifnet            sc_if;          /* the interface */
-       int                     sc_unit;
-       struct shim_hdr         sc_shim;
-       LIST_ENTRY(mpe_softc)   sc_list;
-};
-
 #define MPE_HDRLEN     sizeof(struct shim_hdr)
 #define MPE_MTU                1500
 #define MPE_MTU_MIN    256
@@ -175,6 +168,7 @@
 void   mpls_init(void);
 void   mplsintr(void);
 
+int             mpls_shim_label_exists(struct shim_hdr *);
 struct mbuf    *mpls_shim_pop(struct mbuf *);
 struct mbuf    *mpls_shim_swap(struct mbuf *, struct rt_mpls *);
 struct mbuf    *mpls_shim_push(struct mbuf *, struct rt_mpls *);
Index: netmpls/mpls_input.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/netmpls/mpls_input.c,v
retrieving revision 1.32
diff -u -r1.32 mpls_input.c
--- netmpls/mpls_input.c        6 Jul 2011 02:42:28 -0000       1.32
+++ netmpls/mpls_input.c        22 Aug 2012 02:48:08 -0000
@@ -282,6 +282,13 @@
                                goto done;
                        }
 #endif
+#if NWIRE > 0
+                       if (ifp->if_type == IFT_MPLSTUNNEL) {
+                               smpls = satosmpls(rt_key(rt));
+                               wire_input(m, rt->rt_ifp, smpls, ttl);
+                               goto done;
+                       }
+#endif
                        if (!rt->rt_gateway) {
                                m_freem(m);
                                goto done;
Index: netmpls/mpls_shim.c
===================================================================
RCS file: /backup/obsd_cvs//src/sys/netmpls/mpls_shim.c,v
retrieving revision 1.6
diff -u -r1.6 mpls_shim.c
--- netmpls/mpls_shim.c 28 Jan 2009 22:18:44 -0000      1.6
+++ netmpls/mpls_shim.c 22 Aug 2012 02:48:08 -0000
@@ -42,6 +42,30 @@
 
 #include <netmpls/mpls.h>
 
+#include <net/if_mpe.h>
+#include <net/if_wire.h>
+
+int
+mpls_shim_label_exists(struct shim_hdr *shim)
+{
+       extern LIST_HEAD(, mpe_softc)   mpeif_list;
+       extern LIST_HEAD(, wire_softc)  wire_list;
+
+       struct mpe_softc        *mpe_sc;
+       struct wire_softc       *wr_sc;
+
+       LIST_FOREACH(mpe_sc, &mpeif_list, sc_list) {
+               if (shim->shim_label == mpe_sc->sc_shim.shim_label)
+                       return (1);
+       }
+
+       LIST_FOREACH(wr_sc, &wire_list, sc_list) {
+               if (shim->shim_label == wr_sc->sc_shim.shim_label)
+                       return (1);
+       }
+       return (0);
+}
+
 struct mbuf *
 mpls_shim_pop(struct mbuf *m)
 {
Index: sys/sockio.h
===================================================================
RCS file: /backup/obsd_cvs//src/sys/sys/sockio.h,v
retrieving revision 1.49
diff -u -r1.49 sockio.h
--- sys/sockio.h        26 Nov 2011 23:38:18 -0000      1.49
+++ sys/sockio.h        22 Aug 2012 02:48:08 -0000
@@ -181,6 +181,9 @@
 #define SIOCSETKALIVE  _IOW('i', 163, struct ifkalivereq)
 #define SIOCGETKALIVE  _IOWR('i', 164, struct ifkalivereq)
 
+#define        SIOCWIREADD      _IOW('i', 165, struct ifwreq)  /* add wire ifs 
*/
+#define        SIOCWIREDEL      _IOW('i', 166, struct ifwreq)  /* del wire ifs 
*/
+
 #define        SIOCSVH         _IOWR('i', 245, struct ifreq)   /* set carp 
param */
 #define        SIOCGVH         _IOWR('i', 246, struct ifreq)   /* get carp 
param */

Reply via email to