summaryrefslogtreecommitdiff
path: root/sys/netmpls/mpls_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netmpls/mpls_input.c')
-rw-r--r--sys/netmpls/mpls_input.c116
1 files changed, 76 insertions, 40 deletions
diff --git a/sys/netmpls/mpls_input.c b/sys/netmpls/mpls_input.c
index bdab232a85b..9b0231a6922 100644
--- a/sys/netmpls/mpls_input.c
+++ b/sys/netmpls/mpls_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpls_input.c,v 1.26 2010/06/02 15:41:07 claudio Exp $ */
+/* $OpenBSD: mpls_input.c,v 1.27 2010/06/09 11:40:36 claudio Exp $ */
/*
* Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org>
@@ -56,6 +56,9 @@ extern int mpls_inkloop;
extern int mpls_mapttl_ip;
extern int mpls_mapttl_ip6;
+int mpls_ip_adjttl(struct mbuf *, u_int8_t);
+int mpls_ip6_adjttl(struct mbuf *, u_int8_t);
+
void
mpls_init(void)
{
@@ -93,7 +96,7 @@ mpls_input(struct mbuf *m)
struct rtentry *rt = NULL;
struct rt_mpls *rt_mpls;
u_int8_t ttl;
- int i, hasbos;
+ int i, s, hasbos;
if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
m_freem(m);
@@ -117,7 +120,7 @@ mpls_input(struct mbuf *m)
ifp->if_xname, MPLS_LABEL_GET(shim->shim_label),
MPLS_TTL_GET(shim->shim_label),
MPLS_BOS_ISSET(shim->shim_label));
-#endif /* MPLS_DEBUG */
+#endif
/* check and decrement TTL */
ttl = ntohl(shim->shim_label & MPLS_TTL_MASK);
@@ -159,13 +162,23 @@ mpls_input(struct mbuf *m)
* to be at the beginning of the stack.
*/
if (hasbos) {
- mpls_ip_input(m, ttl);
+ if (mpls_ip_adjttl(m, ttl))
+ goto done;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ipintrq, m);
+ schednetisr(NETISR_IP);
+ splx(s);
goto done;
} else
continue;
case MPLS_LABEL_IPV6NULL:
if (hasbos) {
- mpls_ip6_input(m, ttl);
+ if (mpls_ip6_adjttl(m, ttl))
+ goto done;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ip6intrq, m);
+ schednetisr(NETISR_IPV6);
+ splx(s);
goto done;
} else
continue;
@@ -208,20 +221,26 @@ mpls_input(struct mbuf *m)
break;
if (!rt->rt_gateway) {
-#ifdef MPLS_DEBUG
- printf("MPLS_DEBUG: no layer 3 informations "
- "attached\n");
-#endif
m_freem(m);
goto done;
}
switch(rt->rt_gateway->sa_family) {
case AF_INET:
- mpls_ip_input(m, ttl);
+ if (mpls_ip_adjttl(m, ttl))
+ break;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ipintrq, m);
+ schednetisr(NETISR_IP);
+ splx(s);
break;
case AF_INET6:
- mpls_ip6_input(m, ttl);
+ if (mpls_ip6_adjttl(m, ttl))
+ break;
+ s = splnet();
+ IF_INPUT_ENQUEUE(&ip6intrq, m);
+ schednetisr(NETISR_IPV6);
+ splx(s);
break;
default:
m_freem(m);
@@ -229,19 +248,45 @@ mpls_input(struct mbuf *m)
goto done;
case MPLS_OP_POP:
m = mpls_shim_pop(m);
- if (hasbos) {
+ if (!hasbos)
+ /* redo lookup with next label */
+ break;
+
+ ifp = rt->rt_ifp;
#if NMPE > 0
- if (rt->rt_ifp->if_type == IFT_MPLS) {
- smpls = satosmpls(rt_key(rt));
- mpe_input(m, rt->rt_ifp, smpls, ttl);
- goto done;
- }
+ if (ifp->if_type == IFT_MPLS) {
+ smpls = satosmpls(rt_key(rt));
+ mpe_input(m, rt->rt_ifp, smpls, ttl);
+ goto done;
+ }
#endif
- /* last label but we have no clue so drop */
+ if (!rt->rt_gateway) {
m_freem(m);
goto done;
}
- break;
+
+ switch(rt->rt_gateway->sa_family) {
+ case AF_INET:
+ if (mpls_ip_adjttl(m, ttl))
+ goto done;
+ break;
+ case AF_INET6:
+ if (mpls_ip6_adjttl(m, ttl))
+ goto done;
+ break;
+ default:
+ m_freem(m);
+ goto done;
+ }
+
+ /* Output iface is not MPLS-enabled */
+ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
+ m_freem(m);
+ goto done;
+ }
+
+ (*ifp->if_ll_output)(ifp, m, rt->rt_gateway, rt);
+ goto done;
case MPLS_OP_PUSH:
m = mpls_shim_push(m, rt_mpls);
break;
@@ -293,27 +338,27 @@ done:
RTFREE(rt);
}
-void
-mpls_ip_input(struct mbuf *m, u_int8_t ttl)
+int
+mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl)
{
struct ip *ip;
- int s, hlen;
+ int hlen;
if (mpls_mapttl_ip) {
if (m->m_len < sizeof (struct ip) &&
(m = m_pullup(m, sizeof(struct ip))) == NULL)
- return;
+ return -1;
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
if (m->m_len < hlen) {
if ((m = m_pullup(m, hlen)) == NULL)
- return;
+ return -1;
ip = mtod(m, struct ip *);
}
-
+ /* make sure we have a valid header */
if (in_cksum(m, hlen) != 0) {
m_free(m);
- return;
+ return -1;
}
/* set IP ttl from MPLS ttl */
@@ -323,32 +368,23 @@ mpls_ip_input(struct mbuf *m, u_int8_t ttl)
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m, hlen);
}
-
- s = splnet();
- IF_INPUT_ENQUEUE(&ipintrq, m);
- schednetisr(NETISR_IP);
- splx(s);
+ return 0;
}
-void
-mpls_ip6_input(struct mbuf *m, u_int8_t ttl)
+int
+mpls_ip6_adjttl(struct mbuf *m, u_int8_t ttl)
{
struct ip6_hdr *ip6hdr;
- int s;
if (mpls_mapttl_ip6) {
if (m->m_len < sizeof (struct ip6_hdr) &&
(m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL)
- return;
+ return -1;
ip6hdr = mtod(m, struct ip6_hdr *);
/* set IPv6 ttl from MPLS ttl */
ip6hdr->ip6_hlim = ttl;
}
-
- s = splnet();
- IF_INPUT_ENQUEUE(&ip6intrq, m);
- schednetisr(NETISR_IPV6);
- splx(s);
+ return 0;
}