diff options
-rw-r--r-- | sys/netmpls/mpls.c | 111 | ||||
-rw-r--r-- | sys/netmpls/mpls.h | 296 | ||||
-rw-r--r-- | sys/netmpls/mpls_input.c | 337 | ||||
-rw-r--r-- | sys/netmpls/mpls_lse.c | 333 | ||||
-rw-r--r-- | sys/netmpls/mpls_proto.c | 155 | ||||
-rw-r--r-- | sys/netmpls/mpls_raw.c | 301 | ||||
-rw-r--r-- | sys/netmpls/mpls_shim.c | 247 | ||||
-rw-r--r-- | sys/netmpls/mpls_var.h | 65 |
8 files changed, 1845 insertions, 0 deletions
diff --git a/sys/netmpls/mpls.c b/sys/netmpls/mpls.c new file mode 100644 index 00000000000..ac683aa135e --- /dev/null +++ b/sys/netmpls/mpls.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * + * $Id: mpls.c,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/systm.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +extern void mpls_purgeaddr(struct ifaddr *, struct ifnet *); +extern int mpls_ifinit(struct ifnet *, struct mpls_ifaddr *, + struct sockaddr_mpls *, int); +extern void mpls_ifscrub(struct mpls_ifaddr *); + +struct mpls_ifaddrhead mpls_ifaddr; +struct sockaddr_mpls mpls_scope_sockmask; + +void +mpls_init() +{ + mplsintrq.ifq_maxlen = 50; +} + +void +mpls_purgeaddr(struct ifaddr *ifa, struct ifnet *ifp) +{ +} + +void +mpls_purgeif(struct ifnet *ifp) +{ +} + +/* + * Delete any existing route for an interface. + */ +void +mpls_ifscrub(struct mpls_ifaddr *ia) +{ +} + +/* + * Initialize an interface's MPLS address + * and routing table entry. + */ +int +mpls_ifinit(struct ifnet *ifp, struct mpls_ifaddr *ia, + struct sockaddr_mpls *smpls, int scrub) +{ +#ifdef MPLS_DEBUG + panic("mpls_ifinit\n"); +#endif + return (EAFNOSUPPORT); +} + +/* + * Generic MPLS control operations (ioctl's). + * Ifp is 0 if not an interface-specific ioctl. + */ +/* ARGSUSED */ +int +mpls_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) +{ + return (EOPNOTSUPP); +} diff --git a/sys/netmpls/mpls.h b/sys/netmpls/mpls.h new file mode 100644 index 00000000000..969795208f2 --- /dev/null +++ b/sys/netmpls/mpls.h @@ -0,0 +1,296 @@ +/* $OpenBSD: mpls.h,v 1.1 2008/04/23 11:00:35 norby Exp $ */ + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETMPLS_MPLS_H_ +#define _NETMPLS_MPLS_H_ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/queue.h> + +#include <net/if.h> +#include <net/if_dl.h> + +/* + * Structure of a SHIM header. + */ +struct shim_hdr { + u_int32_t shim_label; /* 20 bit label, 4 bit exp & BoS, 8 bit TTL */ +}; + +/* + * By byte-swapping the constants, we avoid ever having to byte-swap IP + * addresses inside the kernel. Unfortunately, user-level programs rely + * on these macros not doing byte-swapping. + */ + +#ifdef _KERNEL +#define __MADDR(x) ((u_int32_t)htonl((u_int32_t)(x))) +#else +#define __MADDR(x) ((u_int32_t)(x)) +#endif + +#define MPLS_LABEL_MASK __MADDR(0xfffff000U) +#define MPLS_LABEL_OFFSET 12 +#define MPLS_EXP_MASK __MADDR(0x00000e00U) +#define MPLS_EXP_OFFSET 9 +#define MPLS_BOS_MASK __MADDR(0x00000100U) +#define MPLS_BOS_OFFSET 8 +#define MPLS_TTL_MASK __MADDR(0x000000ffU) + +#define MPLS_BOS_ISSET(l) (((l) & MPLS_BOS_MASK) == MPLS_BOS_MASK) + +/* Reserved lavel values (RFC3032) */ +#define MPLS_LABEL_IPV4NULL 0 /* IPv4 Explicit NULL Label */ +#define MPLS_LABEL_RTALERT 1 /* Router Alert Label */ +#define MPLS_LABEL_IPV6NULL 2 /* IPv6 Explicit NULL Label */ +#define MPLS_LABEL_IMPLNULL 3 /* Implicit NULL Label */ +/* MPLS_LABEL_RESERVED 4-15 */ /* Values 4-15 are reserved */ +#define MPLS_LABEL_RESERVED_MAX 15 + +/* + * Socket address + */ + +struct sockaddr_mpls { + u_int8_t smpls_len; /* length */ + u_int8_t smpls_family; /* AF_MPLS */ + u_int8_t smpls_operation; + u_int8_t smpls_out_exp; /* outgoing exp value */ + u_int32_t smpls_out_label; /* outgoing MPLS label */ + u_int16_t smpls_out_ifindex; + u_int16_t smpls_in_ifindex; + u_int32_t smpls_in_label; /* MPLS label 20 bits*/ +#if MPLS_MCAST + u_int8_t smpls_mcexp; + u_int8_t smpls_pad2[2]; + u_int32_t smpls_mclabel; +#endif +}; + +#define MPLS_OP_POP 1 +#define MPLS_OP_PUSH 2 +#define MPLS_OP_SWAP 3 + +#define MPLS_INKERNEL_LOOP_MAX 16 + +#define satosmpls(sa) ((struct sockaddr_mpls *)(sa)) +#define smplstosa(smpls) ((struct sockaddr *)(smpls)) +#define satosdl(sa) ((struct sockaddr_dl *)(sa)) +#define sdltosa(sdl) ((struct sockaddr *)(sdl)) + +/* + * Names for MPLS sysctl objects + */ +#define MPLSCTL_ENABLE 1 +#define MPLSCTL_DEFTTL 2 +#define MPLSCTL_IFQUEUE 3 +#define MPLSCTL_MAXINKLOOP 4 +#define MPLSCTL_MAXID 5 + +#define MPLSCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ + { "ttl", CTLTYPE_INT }, \ + { "ifq", CTLTYPE_NODE },\ + { "maxloop_inkernel", CTLTYPE_INT }, \ +} + +#define MPLSCTL_VARS { \ + 0, \ + &mpls_enable, \ + &mpls_defttl, \ + 0, \ + &mpls_inkloop, \ +} + +#endif +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL + * 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. + */ + +/* + * + * $Id: mpls.h,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#ifndef _NETMPLS_MPLS_H_ +#define _NETMPLS_MPLS_H_ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/queue.h> + +#include <net/if.h> +#include <net/if_dl.h> + +/* + * Structure of a SHIM header. + */ +struct shim_hdr { + u_int32_t shim_label; /* 20bit label, 4bit exp & BOS, 8bit ttl */ +}; + +/* + * By byte-swapping the constants, we avoid ever having to byte-swap IP + * addresses inside the kernel. Unfortunately, user-level programs rely + * on these macros not doing byte-swapping. + */ +#define SHIM_LABEL_MASK 0xfffff000U +#define SHIM_LABEL_OFFSET 12 +#define SHIM_EXP_MASK 0x00000e00U +#define SHIM_EXP_OFFSET 9 +#define SHIM_BOS_MASK 0x00000100U +#define SHIM_BOS_OFFSET 8 +#define SHIM_TTL_MASK 0x000000ffU + +#define MPLS_SHIM_LABEL_GET(l) (((l) & SHIM_LABEL_MASK) >> SHIM_LABEL_OFFSET) +#define MPLS_SHIM_EXP_GET(l) (((l) & SHIM_EXP_MASK) >> SHIM_EXP_OFFSET) +#define MPLS_SHIM_BOS_ISSET(l) (((l) & SHIM_BOS_MASK) == SHIM_BOS_MASK) +#define MPLS_SHIM_TTL_GET(l) ((l) & SHIM_TTL_MASK) +#define MPLS_SHIM_TTL_SET(l, t) (((l) & ~SHIM_TTL_MASK) | ((t) & SHIM_TTL_MASK)) + +/* Reserved lavel values (rfc3032) */ +#define MPLS_LABEL_IPV4NULL 0 /* IPv4 Explicit NULL Label */ +#define MPLS_LABEL_RTALERT 1 /* Router Alert Label */ +#define MPLS_LABEL_IPV6NULL 2 /* IPv6 Explicit NULL Label */ +#define MPLS_LABEL_IMPLNULL 3 /* Implicit NULL Label */ +/* MPLS_LABEL_RESERVED 4-15 */ /* Values 4-15 are reserved */ +#define MPLS_LABEL_RESERVED_MAX 15 + +/* + * Socket address + */ + +struct sockaddr_mpls { + u_int8_t smpls_len; /* length */ + u_int8_t smpls_family; /* AF_MPLS */ + u_int8_t smpls_operation; + u_int8_t smpls_out_exp; /* outgoing exp value */ + u_int32_t smpls_out_label; /* outgoing MPLS label */ + u_int16_t smpls_out_ifindex; + u_int16_t smpls_in_ifindex; + u_int32_t smpls_in_label; /* MPLS label 20 bits*/ +#if MPLS_MCAST + u_int8_t smpls_mcexp; + u_int8_t smpls_pad2[2]; + u_int32_t smpls_mclabel; +#endif +}; + +#define MPLS_EXP_MASK 0x07 /* mpls exp value ( 3bits) */ + +#define MPLS_OP_POP 1 +#define MPLS_OP_PUSH 2 +#define MPLS_OP_SWAP 3 + +#define MPLS_INKERNEL_LOOP_MAX 16 + +#define satosmpls(sa) ((struct sockaddr_mpls *)(sa)) +#define smplstosa(smpls) ((struct sockaddr *)(smpls)) +#define satosdl(sa) ((struct sockaddr_dl *)(sa)) +#define sdltosa(sdl) ((struct sockaddr *)(sdl)) + +struct mpls_ifaddr { + struct ifaddr ia_ifa; /* protocol-independent info */ +#define ia_ifp ia_ifa.ifa_ifp +#define ia_flags ia_ifa.ifa_flags + TAILQ_ENTRY(mpls_ifaddr) ia_list; /* list of MPLS addresses */ + struct sockaddr_mpls ia_addr; /* interface address */ + struct sockaddr ia_dstaddr; /* peer dst address */ +}; + +struct mpls_aliasreq { + char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + struct sockaddr_mpls ifra_addr; + struct sockaddr ifra_dstaddr; + struct sockaddr_mpls ifra_mask; /* not used */ +}; + + +/* + * Names for IP sysctl objects + */ +#define MPLSCTL_DEFTTL 1 +#define MPLSCTL_MAXINKLOOP 2 +#define MPLSCTL_PUSHEXPNULL_IP 3 +#define MPLSCTL_PUSHEXPNULL_IP6 4 +#define MPLSCTL_MAPTTL_IP 5 +#define MPLSCTL_MAPTTL_IP6 6 +#define MPLSCTL_MAXID 7 + +#define MPLSCTL_NAMES { \ + { 0, 0 }, \ + { "ttl", CTLTYPE_INT }, \ + { "maxloop_inkernel", CTLTYPE_INT }, \ + { "pushexpnull_ip", CTLTYPE_INT }, \ + { "pushexpnull_ip6", CTLTYPE_INT }, \ + { "mapttl_ip", CTLTYPE_INT }, \ + { "mapttl_ip6", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL +TAILQ_HEAD(mpls_ifaddrhead, mpls_ifaddr); /* the actual queue head */ +extern struct mpls_ifaddrhead mpls_ifaddr; + +extern void mpls_init(void); +extern int mpls_control(struct socket *, u_long, caddr_t, struct ifnet *); +extern void mpls_purgeif(struct ifnet *); +#endif /* _KERNEL */ +#endif /* _NETMPLS_MPLS_H_ */ diff --git a/sys/netmpls/mpls_input.c b/sys/netmpls/mpls_input.c new file mode 100644 index 00000000000..2e5681b3848 --- /dev/null +++ b/sys/netmpls/mpls_input.c @@ -0,0 +1,337 @@ +/* $OpenBSD: mpls_input.c,v 1.1 2008/04/23 11:00:35 norby Exp $ */ + +/* + * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> + * + * 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. + */ + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +struct ifqueue mplsintrq; +int mplsqmaxlen = IFQ_MAXLEN; +extern int mpls_inkloop; + +void mpls_input(struct mbuf *); + +#ifdef MPLS_DEBUG +#define MPLS_LABEL_GET(l) ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET) +#define MPLS_TTL_GET(l) (ntohl((l) & MPLS_TTL_MASK)) +#endif + +void +mpls_init(void) +{ + mplsintrq.ifq_maxlen = mplsqmaxlen; +} + +void +mplsintr(void) +{ + struct mbuf *m; + int s; + + while (mplsintrq.ifq_head) { + /* Get next datagram of input queue */ + s = splnet(); + IF_DEQUEUE(&mplsintrq, m); + splx(s); + if (m == NULL) + return; +#ifdef DIAGNOSTIC + if ((m->m_flags & M_PKTHDR) == 0) + panic("ipintr no HDR"); +#endif + mpls_input(m); + } +} + +void +mpls_input(struct mbuf *m) +{ + struct route ro; + struct ifnet *ifp = m->m_pkthdr.rcvif; + struct sockaddr_mpls *smpls; + struct shim_hdr *shim; + struct rtentry *rt = NULL; + u_int32_t ttl; + int i; + + if (m->m_len < sizeof(*shim)) + if ((m = m_pullup(m, sizeof(*shim))) == NULL) + return; + + shim = mtod(m, struct shim_hdr *); + +#ifdef MPLS_DEBUG + printf("mpls_input: iface %s label=%d, ttl=%d BoS %d\n", + ifp->if_xname, MPLS_LABEL_GET(shim->shim_label), + MPLS_TTL_GET(shim->shim_label), + MPLS_BOS_ISSET(shim->shim_label)); +#endif /* MPLS_DEBUG */ + + /* check and decrement TTL */ + ttl = ntohl(shim->shim_label & MPLS_TTL_MASK); + if (ttl <= 1) { + /* TTL exceeded */ + /* + * XXX if possible hand packet up to network layer so that an + * ICMP TTL exceeded can be sent back. + */ + m_freem(m); + return; + } + ttl = htonl(ttl - 1); + + for (i = 0; i < mpls_inkloop; i++) { + /* XXX maybe this should be done later */ + if (MPLS_BOS_ISSET(shim->shim_label)) { + /* no LER until now */ + m_freem(m); + goto done; + } + + bzero(&ro, sizeof(ro)); + smpls = satosmpls(&ro.ro_dst); + smpls->smpls_family = AF_MPLS; + smpls->smpls_len = sizeof(*smpls); + smpls->smpls_in_ifindex = ifp->if_index; + smpls->smpls_in_label = shim->shim_label & MPLS_LABEL_MASK; + +printf("smpls af %d len %d in_label %d in_ifindex %d\n", smpls->smpls_family, + smpls->smpls_len, smpls->smpls_in_label, smpls->smpls_in_ifindex); + + rtalloc(&ro); /* XXX switch to rtalloc1() */ + rt = ro.ro_rt; + + if (rt == NULL) { + /* no entry for this label */ +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: label not found\n"); +#endif + m_freem(m); + goto done; + } + + rt->rt_use++; + smpls = satosmpls(rt_key(rt)); +printf("route af %d len %d in_label %d in_ifindex %d\n", smpls->smpls_family, + smpls->smpls_len, MPLS_LABEL_GET(smpls->smpls_in_label), + smpls->smpls_in_ifindex); +printf("\top %d out_label %d out_ifindex %d\n", smpls->smpls_operation, + MPLS_LABEL_GET(smpls->smpls_out_label), smpls->smpls_out_ifindex); + + switch (smpls->smpls_operation) { + case MPLS_OP_POP: + m = mpls_shim_pop(m); + break; + case MPLS_OP_PUSH: + m = mpls_shim_push(m, smpls); + break; + case MPLS_OP_SWAP: + m = mpls_shim_swap(m, smpls); + break; + default: + break; + } + + break; + /* not yet done with packet */ + if (rt) { + RTFREE(rt); + rt = NULL; + } + } + + /* write back TTL */ + shim->shim_label = (shim->shim_label & ~MPLS_TTL_MASK) | ttl; + +printf("MPLS: sending on %s outlabel %x dst af %d in %d out %d\n", + ifp->if_xname, ntohl(shim->shim_label), smpls->smpls_family, + MPLS_LABEL_GET(smpls->smpls_in_label), + MPLS_LABEL_GET(smpls->smpls_out_label)); + + (*ifp->if_output)(ifp, m, smplstosa(smpls), rt); +done: + if (rt) + RTFREE(rt); +} +/* $OpenBSD: mpls_input.c,v 1.1 2008/04/23 11:00:35 norby Exp $ */ +/* + * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> + * + * 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. + */ + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +struct ifqueue mplsintrq; + +void mpls_input(struct mbuf *); + +void +mplsintr(void) +{ + struct mbuf *m; + int s; + + while (mplsintrq.ifq_head) { + /* Get next datagram of input queue */ + s = splnet(); + IF_DEQUEUE(&mplsintrq, m); + splx(s); + if (m == NULL) + return; +#ifdef DIAGNOSTIC + if ((m->m_flags & M_PKTHDR) == 0) + panic("ipintr no HDR"); +#endif + mpls_input(m); + } +} + +void +mpls_input(struct mbuf *m) +{ + struct route ro; + struct ifnet *ifp = m->m_pkthdr.rcvif; + struct sockaddr_mpls *smpls; + struct shim_hdr *shim; + struct rtentry *rt = NULL; + u_int32_t label, ttl; + int i, error; + + printf("mpls_input: !! \n"); + + if (m->m_len < sizeof(label)) + if ((m = m_pullup(m, sizeof(label))) == NULL) + return; + + shim = mtod(m, struct shim_hdr *); + /* swap label to host byte order. */ + label = ntohl(shim->shim_label); + +#ifdef MPLS_DEBUG + printf("mpls_input: iface %s label=%d, ttl=%d BoS %d\n", + ifp->if_xname, MPLS_SHIM_LABEL_GET(label), + MPLS_SHIM_TTL_GET(label), MPLS_SHIM_BOS_ISSET(label)); +#endif /* MPLS_DEBUG */ + + /* check and decrement TTL */ + ttl = MPLS_SHIM_TTL_GET(label); + if (ttl <= 1) { + /* ttl exceeded */ + /* + * XXX if possible hand packet up to network layer so that an + * ICMP TTL exceeded can be sent back. + */ + m_freem(m); + return; + } + ttl--; + + for (i = 0; i < MPLS_INKERNEL_LOOP_MAX; i++) { + /* XXX maybe this should be done later */ + if (MPLS_SHIM_BOS_ISSET(label)) { + /* no LER until now */ + error = EHOSTUNREACH; + goto done; + } + + bzero(&ro, sizeof(ro)); + smpls = satosmpls(&ro.ro_dst); + smpls->smpls_family = AF_MPLS; + smpls->smpls_len = sizeof(*smpls); + smpls->smpls_in_ifindex = ifp->if_index; + smpls->smpls_in_label = MPLS_SHIM_LABEL_GET(label); + + rtalloc(&ro); /* XXX switch to rtalloc1() */ + rt = ro.ro_rt; + + if (rt == NULL) { + /* no entry for this label */ + error = EHOSTUNREACH; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: label not found\n"); +#endif + goto done; + } + + rt->rt_use++; + smpls = satosmpls(rt_key(rt)); + + switch (smpls->smpls_operation) { + case MPLS_OP_POP: + printf("mpls_input: POP\n"); + /* mpls_shim_pop() */ + break; + case MPLS_OP_PUSH: + printf("mpls_input: PUSH\n"); + /* mpls_shim_push() */ + break; + case MPLS_OP_SWAP: + printf("mpls_input: SWAP\n"); + /* mpls_shim_swap() */ + break; + default: + break; + } + + /* not yet done with packet */ + /* reget current label */ + shim = mtod(m, struct shim_hdr *); + label = ntohl(shim->shim_label); + + if (rt) { + RTFREE(rt); + rt = NULL; + } + } + + /* write back modified label */ + shim->shim_label = htonl(MPLS_SHIM_TTL_SET(label, ttl)); + + error = (*ifp->if_output)(ifp, m, smplstosa(&smpls), rt); +done: + if (error) + m_freem(m); + if (rt) + RTFREE(rt); +} diff --git a/sys/netmpls/mpls_lse.c b/sys/netmpls/mpls_lse.c new file mode 100644 index 00000000000..92ec6386d37 --- /dev/null +++ b/sys/netmpls/mpls_lse.c @@ -0,0 +1,333 @@ +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * + * $Id: mpls_lse.c,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/systm.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +/* + * MPLS Label Switching Engine. + */ + +/* + * Process a received MPLS packet; + * the packet is in the mbuf chain m from mpls_{ether,...}. + */ +int +mpls_lse(struct ifnet *ifp, struct mbuf *m, struct sockaddr_mpls *dst, + u_int8_t bosf) +{ + struct route mplsroute; + struct route *ro = &mplsroute; + struct sockaddr_mpls *rodst = satosmpls(&mplsroute.ro_dst); /* Actual labeland stuff */ + struct rtentry *rt = NULL; + struct sockaddr_mpls *dstnew; + struct sockaddr_mpls smpls; /* XXX adhoc XXX */ + u_int8_t exp_bits; /* XXX adhoc XXX */ + int ink_loop, error = 0, bad = 0; + + bzero((caddr_t)ro, sizeof(*ro)); + bcopy((caddr_t)dst, (caddr_t)rodst, dst->smpls_len); + +/* XXX: Kefren: I don't understand this inkloop so I've replaced it with asingle + loop for easy break */ + for (ink_loop = 0; ink_loop < mpls_inkloop; ink_loop++) { +/* for (ink_loop = 0; ink_loop < 1; ink_loop++) { */ + +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d). [label=%d]\n", + __FILE__, __LINE__, ntohl(rodst->smpls_in_label)); +#endif /* MPLS_DEBUG */ + + /* + * OPERATIONS for Reserved Labels + */ + if (ntohl(rodst->smpls_in_label) <= MPLS_LABEL_RESERVED_MAX) { + printf("MPLS_DEBUG: %s(%d). [bosf = %d label = %s]\n", + __FILE__, __LINE__, bosf, + ntohl(rodst->smpls_in_label)); + switch (ntohl(rodst->smpls_in_label)) { +#ifdef INET + case MPLS_LABEL_IPV4NULL: +#if 0 /* claudio@ */ + if (bosf) { + error = mpls_ip_input(m); + goto done; + } +#endif +#ifdef MPLS_DEBUG +#endif /* MPLS_DEBUG */ + break; +#endif /* INET */ +#ifdef INET6 + case MPLS_LABEL_IPV6NULL: +#if 0 /* claudio@ */ + if (bosf) { + error = mpls_ip6_input(m); + goto done; + } +#endif + break; +#endif /* INET6 */ + } + + /* label is reserved, */ + /* but operation is unsupported or invalid */ + error = EINVAL; + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); + bad = 1; + break; + } /* MPLS RESERVED label */ + + /* + * switch packet + * + * XXX: no really, this is fun. AYAME sucks so much. */ + exp_bits = rodst->smpls_out_exp; + rodst->smpls_out_exp = 0; + + rtalloc(ro); + rt = ro->ro_rt; + bzero((caddr_t)ro, sizeof(*ro)); + + if (rt == 0) { + /* no entry for this label (silent discard) */ + /* as the scope_id you use is not set interface, etc. */ + /* error = EHOSTUNREACH; */ + error = 0; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + break; + } + + /* + if ((mtu = rt->rt_rmx.rmx_mtu) == 0) + mtu = ifp->if_mtu; + */ + + + /* + * label operations + */ + rt->rt_use++; + if (rt->rt_flags & RTF_GATEWAY) /* XXX */ + dstnew = satosmpls(rt->rt_gateway); + else { + /* XXX silent discard XXX */ + /* error = EHOSTUNREACH; */ + error = 0; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + break; + } + +#ifdef MPLS_MCAST + printf("MPLS_MCAST label=%d mclabel=%d\n", + ntohl(dstnew->smpls_in_label) & 0x000fffff, + ntohl(dstnew->smpls_mclabel)); + /* + * if gw_entry have next mplsmc entry, + * call mpls_lse again. + */ + if (dstnew->smpls_mclabel != 0) { + struct sockaddr_mpls smpmpls; + struct mbuf *nm; + memset(&smpmpls, 0, sizeof(smpmpls)); + smpmpls.smpls_len = sizeof(smpmpls); + smpmpls.smpls_family = AF_MPLS; + smpmpls.smpls_in_label = dstnew->smpls_mclabel; +#ifdef MPLS_DEBUG + printf("MPLS_MCAST label=%d mclabel=%d\n", + ntohl(dstnew->smpls_in_label) & 0x000fffff, + ntohl(dstnew->smpls_mclabel)); +#endif /* MPLS_DEBUG */ + nm = m_copym(m, 0, M_COPYALL, M_DONTWAIT); + if (nm != NULL) { +#ifdef MPLS_DEBUG + printf("MPLS_MCAST dup\n"); +#endif /* MPLS_DEBUG */ + mpls_lse(ifp, nm, &smpmpls, bosf); + m_freem(nm); + } + } +#endif /* MPLS_MCAST */ + + if (dstnew->smpls_family != AF_MPLS) { + if (bosf) { + /* send to L3? */ + switch (dstnew->smpls_family) { +#if 0 /* claudio@ */ +#ifdef INET + case AF_INET: + error = mpls_ip_input(m); + goto done; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + error = mpls_ip6_input(m); + goto done; +#endif /* INET6 */ +#endif + default: + error = EAFNOSUPPORT; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + } + break; + } else { + /* XXX */ + error = EINVAL; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + break; + } + } + + /* XXX */ + smpls = *dstnew; + smpls.smpls_out_exp = exp_bits; + dstnew = &smpls; + /* XXX Kefren */ +/* dstnew->smpls_exp = exp_bits;*/ + + switch(dstnew->smpls_operation) { + + case MPLS_OP_POP: /* Label Pop */ + + /* check bos flag */ +#if 0 /* claudio@ */ + if (bosf) { + /* + * XXXXX No ExpNULL XXXXX + * + * I can't know which l3 I shuld send to!! + * now, send to IPv4 stack (XXXXX) + * We have to 'look' into the packet + * and clasify it + * + * error = EINVAL; + * goto bad; + */ + + error = mpls_ip_input(m); + goto done; + } +#endif + /* label pop */ + if ((m = mpls_shim_pop(m, rodst, NULL, &bosf, NULL)) == 0) { + error = ENOBUFS; + goto done; + } + + break; + + case MPLS_OP_PUSH: /* Label Push */ + + if ((m = mpls_shim_push(m, dstnew, NULL, NULL, NULL)) == 0) { + error = ENOBUFS; + goto done; + } + bosf = 0; + + break; + + case MPLS_OP_SWAP: /* Label Swap */ + default: + + if ((m = mpls_shim_swap(m, dstnew, NULL)) == 0) { + error = ENOBUFS; + goto done; + } + } + + ifp = rt->rt_ifp; + /* send to L2 : select outgoing i/f */ + switch (ifp->if_type) { + case IFT_ETHER: + case IFT_ATM: /* now only support scope 0 */ + case IFT_GIF: /* now only support scope 0 */ + error = (*ifp->if_output)(ifp, m, smplstosa(dstnew), rt); + goto done; + case IFT_LOOP: + break; + default: + /* not supported yet: discard */ +#ifdef MPLS_DEBUG + printf("mpls_lse: interface type not supported yet!\n"); +#endif /* MPLS_DEBUG */ + error = EHOSTUNREACH; + bad=1; + } + if (bad) break; + if (rt) { + RTFREE(rt); + rt = 0; + } + } /* The big inkloop for */ + + /* + * Discard broken packet + */ +if (bad) { +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d) [packet discard!!].\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + m_freem(m); +} + +done: + if (rt) + RTFREE(rt); + return(error); +} diff --git a/sys/netmpls/mpls_proto.c b/sys/netmpls/mpls_proto.c new file mode 100644 index 00000000000..3984208fdd3 --- /dev/null +++ b/sys/netmpls/mpls_proto.c @@ -0,0 +1,155 @@ +/* $OpenBSD: mpls_proto.c,v 1.1 2008/04/23 11:00:35 norby Exp $ */ + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/mbuf.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +/* + * MPLS protocol family: + */ + +extern struct domain mplsdomain; + +struct protosw mplssw[] = { +{ 0, &mplsdomain, 0, 0, + 0, 0, 0, 0, + 0, + mpls_init, 0, 0, 0, mpls_sysctl +}, +{ SOCK_DGRAM, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, + 0, 0, 0, 0, + mpls_raw_usrreq, + 0, 0, 0, 0, mpls_sysctl, +}, +/* raw wildcard */ +{ SOCK_RAW, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, + 0, 0, 0, 0, + mpls_raw_usrreq, + 0, 0, 0, 0, mpls_sysctl, +}, +}; + +struct domain mplsdomain = { + AF_MPLS, "mpls", mpls_init, 0, 0, + mplssw, + &mplssw[sizeof(mplssw)/sizeof(mplssw[0])], 0, + rn_inithead, + offsetof(struct sockaddr_mpls, smpls_in_ifindex) << 3, + sizeof(struct sockaddr_mpls) +}; +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * + * $Id: mpls_proto.c,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/mbuf.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +/* + * MPLS protocol family: + */ + +extern struct domain mplsdomain; + +struct protosw mplssw[] = { +{ 0, &mplsdomain, 0, 0, + 0, 0, 0, 0, + 0, + mpls_init, 0, 0, 0, mpls_sysctl +}, +{ SOCK_DGRAM, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, + 0, 0, 0, 0, + mpls_raw_usrreq, + 0, 0, 0, 0, mpls_sysctl, +}, +/* raw wildcard */ +{ SOCK_RAW, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, + 0, 0, 0, 0, + mpls_raw_usrreq, + 0, 0, 0, 0, mpls_sysctl, +}, +}; + +struct domain mplsdomain = { + AF_MPLS, "mpls", /*mpls_init */ 0 , 0, 0, + mplssw, + &mplssw[sizeof(mplssw)/sizeof(mplssw[0])], 0, + rn_inithead, + offsetof(struct sockaddr_mpls, smpls_in_ifindex) << 3, + sizeof(struct sockaddr_mpls) +}; diff --git a/sys/netmpls/mpls_raw.c b/sys/netmpls/mpls_raw.c new file mode 100644 index 00000000000..b084f879dcc --- /dev/null +++ b/sys/netmpls/mpls_raw.c @@ -0,0 +1,301 @@ +/* $OpenBSD: mpls_raw.c,v 1.1 2008/04/23 11:00:35 norby Exp $ */ + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/systm.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +#define MPLS_RAW_SNDQ 8192 +#define MPLS_RAW_RCVQ 8192 + +u_long mpls_raw_sendspace = MPLS_RAW_SNDQ; +u_long mpls_raw_recvspace = MPLS_RAW_RCVQ; + +int mpls_enable = 0; +int mpls_defttl = 255; +int mpls_inkloop = 16; +int mpls_push_expnull_ip = 0; +int mpls_push_expnull_ip6 = 0; +int mpls_mapttl_ip = 1; +int mpls_mapttl_ip6 = 0; + +int *mplsctl_vars[MPLSCTL_MAXID] = MPLSCTL_VARS; + +int mpls_control(struct socket *, u_long, caddr_t, struct ifnet *); + +/* + * Generic MPLS control operations (ioctl's). + * Ifp is 0 if not an interface-specific ioctl. + */ +/* ARGSUSED */ +int +mpls_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) +{ + return (EOPNOTSUPP); +} + +int +mpls_raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + int error = 0; + +#ifdef MPLS_DEBUG + printf("mpls_raw_usrreq: called! (reqid=%d).\n", req); +#endif /* MPLS_DEBUG */ + + if (req == PRU_CONTROL) + return (mpls_control(so, (u_long)m, (caddr_t)nam, + (struct ifnet *)control)); + + switch (req) { + case PRU_ATTACH: + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = soreserve(so, mpls_raw_sendspace, + mpls_raw_recvspace); + if (error) + break; + } + break; + + case PRU_DETACH: + case PRU_BIND: + case PRU_LISTEN: + case PRU_CONNECT: + case PRU_CONNECT2: + case PRU_DISCONNECT: + case PRU_SHUTDOWN: + case PRU_RCVD: + case PRU_SEND: + case PRU_SENSE: + case PRU_RCVOOB: + case PRU_SENDOOB: + case PRU_SOCKADDR: + case PRU_PEERADDR: + error = EOPNOTSUPP; + break; + + default: + panic("rip_usrreq"); + } + + return (error); +} + +int +mpls_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) +{ + if (name[0] >= MPLSCTL_MAXID) + return EOPNOTSUPP; + + /* Almost all sysctl names at this level are terminal. */ + if (namelen != 1 && name[0] != MPLSCTL_IFQUEUE) + return (ENOTDIR); + + switch (name[0]) { + case MPLSCTL_IFQUEUE: + return (sysctl_ifq(name + 1, namelen - 1, + oldp, oldlenp, newp, newlen, &mplsintrq)); + default: + return sysctl_int_arr(mplsctl_vars, name, namelen, + oldp, oldlenp, newp, newlen); + } +} +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * + * $Id: mpls_raw.c,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/systm.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +#define MPLS_RAW_SNDQ 8192 +#define MPLS_RAW_RCVQ 8192 + +u_long mpls_raw_sendspace = MPLS_RAW_SNDQ; +u_long mpls_raw_recvspace = MPLS_RAW_RCVQ; + +int mpls_defttl = 255; +int mpls_inkloop = 16; +int mpls_push_expnull_ip = 0; +int mpls_push_expnull_ip6 = 0; +int mpls_mapttl_ip = 1; +int mpls_mapttl_ip6 = 0; + +#define MPLSCTL_VARS { \ + 0, \ + &mpls_defttl, \ + &mpls_inkloop, \ + &mpls_push_expnull_ip, \ + &mpls_push_expnull_ip6, \ + &mpls_mapttl_ip, \ + &mpls_mapttl_ip6, \ +} + +int +mpls_raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + int s; + int error = 0; + +#ifdef MPLS_DEBUG + printf("mpls_raw_usrreq: called! (reqid=%d).\n", req); +#endif /* MPLS_DEBUG */ + + if (req == PRU_CONTROL) + return (mpls_control(so, (long)m, (caddr_t)nam, + (struct ifnet *)control)); +/* XXX norby + if (req == PRU_PURGEIF) { + mpls_purgeif((struct ifnet *)control); + return (0); + } +*/ + s = splsoftnet(); + + switch (req) { + + case PRU_ATTACH: + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = soreserve(so, mpls_raw_sendspace, mpls_raw_recvspace); + if (error) + break; + } + break; + + case PRU_DETACH: + case PRU_BIND: + case PRU_LISTEN: + case PRU_CONNECT: + case PRU_CONNECT2: + case PRU_DISCONNECT: + case PRU_SHUTDOWN: + case PRU_RCVD: + case PRU_SEND: + case PRU_SENSE: + case PRU_RCVOOB: + case PRU_SENDOOB: + case PRU_SOCKADDR: + case PRU_PEERADDR: + error = EOPNOTSUPP; + break; + + default: + panic("rip_usrreq"); + } + +/* release: */ + splx(s); + return (error); +} + +static int *mpls_sysvars[] = MPLSCTL_VARS; + +int +mpls_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) +{ + if (name[0] >= MPLSCTL_MAXID) + return EOPNOTSUPP; + if (!mpls_sysvars[name[0]]) + return EOPNOTSUPP; + +#ifdef MPLS_DEBUG + printf("mpls_sysctl\n"); +#endif /* MPLS_DEBUG */ + + switch (name[0]) { + default: + return sysctl_int(oldp, oldlenp, newp, newlen, + mpls_sysvars[name[0]]); + } +} + diff --git a/sys/netmpls/mpls_shim.c b/sys/netmpls/mpls_shim.c new file mode 100644 index 00000000000..57df3b4f1ce --- /dev/null +++ b/sys/netmpls/mpls_shim.c @@ -0,0 +1,247 @@ +/* $OpenBSD: mpls_shim.c,v 1.1 2008/04/23 11:00:35 norby Exp $ */ + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <sys/systm.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +struct mbuf * +mpls_shim_pop(struct mbuf *m) +{ + /* shaves off top shim header from mbuf */ + m_adj(m, sizeof(struct shim_hdr)); + + /* catch-up next shim_hdr */ + if (m->m_len < sizeof(struct shim_hdr)) + if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0) + return (NULL); + + /* return mbuf */ + return (m); +} + +struct mbuf * +mpls_shim_swap(struct mbuf *m, struct sockaddr_mpls *smplsp) +{ + struct shim_hdr *shim; + + /* pullup shim_hdr */ + if (m->m_len < sizeof(struct shim_hdr)) + if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0) + return (NULL); + shim = mtod(m, struct shim_hdr *); + + /* swap label */ + shim->shim_label &= ~MPLS_LABEL_MASK; + shim->shim_label |= smplsp->smpls_out_label & MPLS_LABEL_MASK; + + /* swap exp : XXX exp override */ + { + u_int32_t t; + + shim->shim_label &= ~MPLS_EXP_MASK; + t = smplsp->smpls_out_exp << MPLS_EXP_OFFSET; + shim->shim_label |= htonl(t) & MPLS_EXP_MASK; + } + shim->shim_label = htonl(shim->shim_label); + + return (m); +} + +struct mbuf * +mpls_shim_push(struct mbuf *m, struct sockaddr_mpls *smplsp) +{ + struct shim_hdr *shim; + + M_PREPEND(m, sizeof(struct shim_hdr), M_DONTWAIT); + if (m == 0) + return (NULL); + + shim = mtod(m, struct shim_hdr *); + bzero((caddr_t)shim, sizeof(*shim)); + + return (mpls_shim_swap(m, smplsp)); +} +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * + * $Id: mpls_shim.c,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <sys/systm.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +struct mbuf * +mpls_shim_pop(struct mbuf *m, struct sockaddr_mpls *smplsp, u_int32_t *labelp, + u_int8_t *bosp, u_int8_t *ttlp) +{ + u_int32_t label; + + /* shaves off top shim header from mbuf */ + m_adj(m, sizeof(struct shim_hdr)); + + /* catch-up next shim_hdr */ + if (m->m_len < sizeof(struct shim_hdr)) + if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0) + return(0); + + label = ntohl(*mtod(m, u_int32_t *)); + + /* set each values, if need */ + if (bosp) + *bosp = MPLS_SHIM_BOS_ISSET(label); + if (ttlp) + *ttlp = MPLS_SHIM_TTL_GET(label); + if (labelp) + *labelp = MPLS_SHIM_LABEL_GET(label); + if (smplsp) { + bzero(smplsp, sizeof(*smplsp)); + smplsp->smpls_family = AF_MPLS; + smplsp->smpls_len = sizeof(*smplsp); + smplsp->smpls_in_label = MPLS_SHIM_LABEL_GET(label); + } + + /* return mbuf */ + return(m); +} + +struct mbuf * +mpls_shim_swap(struct mbuf *m, struct sockaddr_mpls *smplsp, u_int32_t *labelp) +{ + struct shim_hdr *shim; + u_int32_t label; + + /* pullup shim_hdr */ + if (m->m_len < sizeof(struct shim_hdr)) /* XXX isn't this + already checked by mpls_shim_peep ? */ + if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0) + return(0); + shim = mtod(m, struct shim_hdr *); + shim->shim_label = ntohl(shim->shim_label); + + if (smplsp == NULL && labelp == NULL) + /* can't swap, because no dst label */ + return(m); /* XXX discard? XXX */ + + if (labelp) { + label = *labelp; + /* + if (smplsp) + smplsp->smpls_in_label = htonl(*labelp); + */ + } else + label = ntohl(smplsp->smpls_in_label); + + /* shim swap label */ + shim->shim_label &= ~SHIM_LABEL_MASK; + shim->shim_label |= MPLS_SHIM_LABEL_GET(label) << SHIM_LABEL_OFFSET; + + /* shim swap exp : XXX exp override */ + if (smplsp) { + shim->shim_label &= ~SHIM_EXP_MASK; + shim->shim_label |= + smplsp->smpls_out_exp << SHIM_EXP_OFFSET & SHIM_EXP_MASK; + } + shim->shim_label = htonl(shim->shim_label); + + return(m); +} + +struct mbuf * +mpls_shim_push(struct mbuf *m, struct sockaddr_mpls *smplsp, u_int32_t *labelp, + u_int8_t *bosp, u_int8_t *ttlp) +{ + struct shim_hdr *shim; + + M_PREPEND(m, sizeof(struct shim_hdr), M_DONTWAIT); + if (m == 0) + return(0); + + shim = mtod(m, struct shim_hdr *); + bzero((caddr_t)shim, sizeof(*shim)); + + if (bosp && *bosp) + shim->shim_label |= SHIM_BOS_MASK; + if (ttlp) + shim->shim_label |= *ttlp & SHIM_TTL_MASK; + else + shim->shim_label |= 255; /* XXX */ + m = mpls_shim_swap(m, smplsp, labelp); + + return m; +} diff --git a/sys/netmpls/mpls_var.h b/sys/netmpls/mpls_var.h new file mode 100644 index 00000000000..4d1e2e62437 --- /dev/null +++ b/sys/netmpls/mpls_var.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * + * $Id: mpls_var.h,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#ifdef _KERNEL +extern int mpls_defttl; +extern int mpls_inkloop; +extern int mpls_push_expnull_ip; +extern int mpls_push_expnull_ip6; +extern int mpls_mapttl_ip; +extern int mpls_mapttl_ip6; + +extern int mpls_lse(struct ifnet *, struct mbuf *, + struct sockaddr_mpls *, u_int8_t); +extern int mpls_canfwbympls(u_int32_t); +extern struct mbuf *mpls_shim_peep(struct mbuf *, struct sockaddr_mpls *, + u_int32_t *, u_int8_t *, u_int8_t *); +extern struct mbuf *mpls_shim_pop(struct mbuf *, struct sockaddr_mpls *, + u_int32_t *, u_int8_t *, u_int8_t *); +extern struct mbuf *mpls_shim_swap(struct mbuf *, struct sockaddr_mpls *, + u_int32_t *); +extern struct mbuf *mpls_shim_push(struct mbuf *, struct sockaddr_mpls *, + u_int32_t *, u_int8_t *, u_int8_t *); + +extern int mpls_raw_usrreq(struct socket *, int, struct mbuf *, + struct mbuf *, struct mbuf *); + +extern int mpls_sysctl(int *, u_int, void *, size_t *, void *, size_t); + + + +extern struct ifqueue mplsintrq; /* MPLS input queue */ + +void mplsintr(void); +#endif /* _KERNEL */ |