summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2010-09-08 08:00:57 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2010-09-08 08:00:57 +0000
commitaedb556b2f3c2c3d1954efd853f4037812d74383 (patch)
tree8ce6e085bdba38dfe3509306818ec911da231cc9
parentdec2856d44d47d5d78a57faed54c324ad2f292e2 (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.h5
-rw-r--r--sys/netmpls/mpls_output.c52
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);
+}