diff options
Diffstat (limited to 'sys/netmpls')
-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); +} |