diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-09-08 08:00:57 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-09-08 08:00:57 +0000 |
commit | aedb556b2f3c2c3d1954efd853f4037812d74383 (patch) | |
tree | 8ce6e085bdba38dfe3509306818ec911da231cc9 | |
parent | dec2856d44d47d5d78a57faed54c324ad2f292e2 (diff) |
Map the TTL when building the initial MPLS stack from the encapsulated
packet. For IP and IPv6 the corresponding mapttl sysctl needs to be set.
This is needed to make traceroute work over MPLS.
OK michele@
-rw-r--r-- | sys/netmpls/mpls.h | 5 | ||||
-rw-r--r-- | sys/netmpls/mpls_output.c | 52 |
2 files changed, 53 insertions, 4 deletions
diff --git a/sys/netmpls/mpls.h b/sys/netmpls/mpls.h index 316d0f7ed86..64122e8679d 100644 --- a/sys/netmpls/mpls.h +++ b/sys/netmpls/mpls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls.h,v 1.24 2010/06/09 11:40:36 claudio Exp $ */ +/* $OpenBSD: mpls.h,v 1.25 2010/09/08 08:00:56 claudio Exp $ */ /* * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. @@ -168,6 +168,9 @@ extern int mpls_raw_usrreq(struct socket *, int, struct mbuf *, extern struct ifqueue mplsintrq; /* MPLS input queue */ extern int mplsqmaxlen; /* MPLS input queue length */ extern int mpls_defttl; +extern int mpls_mapttl_ip; +extern int mpls_mapttl_ip6; + void mpls_init(void); void mplsintr(void); diff --git a/sys/netmpls/mpls_output.c b/sys/netmpls/mpls_output.c index f2025764dfe..aa756b69835 100644 --- a/sys/netmpls/mpls_output.c +++ b/sys/netmpls/mpls_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls_output.c,v 1.11 2010/07/07 14:50:02 claudio Exp $ */ +/* $OpenBSD: mpls_output.c,v 1.12 2010/09/08 08:00:56 claudio Exp $ */ /* * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> @@ -33,13 +33,18 @@ #include <netinet/ip.h> #endif +#ifdef INET6 +#include <netinet/ip6.h> +#endif + extern int mpls_inkloop; #ifdef MPLS_DEBUG #define MPLS_LABEL_GET(l) ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET) #endif -void mpls_do_cksum(struct mbuf *); +void mpls_do_cksum(struct mbuf *); +u_int8_t mpls_getttl(struct mbuf *, sa_family_t); int mpls_output(struct ifnet *ifp0, struct mbuf *m, struct sockaddr *dst, @@ -52,6 +57,7 @@ mpls_output(struct ifnet *ifp0, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt = rt0; struct rt_mpls *rt_mpls; int i, error; + u_int8_t ttl; if (rt0 == NULL || (dst->sa_family != AF_INET && dst->sa_family != AF_INET6 && dst->sa_family != AF_MPLS)) { @@ -72,6 +78,8 @@ mpls_output(struct ifnet *ifp0, struct mbuf *m, struct sockaddr *dst, smpls->smpls_family = AF_MPLS; smpls->smpls_len = sizeof(*smpls); + ttl = mpls_getttl(m, dst->sa_family); + for (i = 0; i < mpls_inkloop; i++) { rt_mpls = (struct rt_mpls *)rt->rt_llinfo; if (rt_mpls == NULL || (rt->rt_flags & RTF_MPLS) == 0) { @@ -134,7 +142,7 @@ mpls_output(struct ifnet *ifp0, struct mbuf *m, struct sockaddr *dst, /* write back TTL */ shim->shim_label &= ~MPLS_TTL_MASK; - shim->shim_label |= htonl(mpls_defttl); + shim->shim_label |= htonl(ttl); #ifdef MPLS_DEBUG printf("MPLS: sending on %s outshim %x outlabel %d\n", @@ -181,3 +189,41 @@ mpls_do_cksum(struct mbuf *m) } #endif } + +u_int8_t +mpls_getttl(struct mbuf *m, sa_family_t af) +{ + struct shim_hdr *shim; + struct ip *ip; + struct ip6_hdr *ip6hdr; + u_int8_t ttl = mpls_defttl; + + /* If the AF is MPLS then inherit the TTL from the present label. */ + if (af == AF_MPLS) { + shim = mtod(m, struct shim_hdr *); + ttl = ntohl(shim->shim_label & MPLS_TTL_MASK); + return (ttl); + } + /* Else extract TTL from the encapsualted packet. */ + switch (*mtod(m, u_char *) >> 4) { + case IPVERSION: + if (!mpls_mapttl_ip) + break; + if (m->m_len < sizeof(*ip)) + break; /* impossible */ + ip = mtod(m, struct ip *); + ttl = ip->ip_ttl; + break; + case IPV6_VERSION >> 4: + if (!mpls_mapttl_ip6) + break; + if (m->m_len < sizeof(struct ip6_hdr)) + break; /* impossible */ + ip6hdr = mtod(m, struct ip6_hdr *); + ttl = ip6hdr->ip6_hlim; + break; + default: + break; + } + return (ttl); +} |