summaryrefslogtreecommitdiff
path: root/sys/netmpls
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netmpls')
-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);
+}