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 */