Module Name: src Committed By: snj Date: Tue Mar 13 17:42:39 UTC 2018
Modified Files: src/sys/net [netbsd-6-1]: if_mpls.c src/sys/netmpls [netbsd-6-1]: mpls_ttl.c Log Message: Pull up following revision(s) (requested by uwe in ticket #1534): sys/net/if_mpls.c: 1.31-1.33 via patch sys/netmpls/mpls_ttl.c: 1.9 via patch Style, and fix several bugs: - ip4_check(), mpls_unlabel_inet() and mpls_unlabel_inet6() perform pullups, so we need to pass the updated pointers back - in mpls_lse() the route is not always freed Looks a little better now. -- Kick MPLS packets earlier. -- Several changes: * In mpls_unlabel_inet, copy the label locally. It's not incorrect to keep a pointer on the mbuf, but it's bug-friendly. * In mpls_label_inetX, fix the length check. Meanwhile add an XXX: we just want to make sure that m_copydata won't fail, but if we were guaranteed that m has M_PKTHDR set, we could simply check the length against m->m_pkthdr.len. To generate a diff of this commit: cvs rdiff -u -r1.8.22.1 -r1.8.22.2 src/sys/net/if_mpls.c cvs rdiff -u -r1.3 -r1.3.32.1 src/sys/netmpls/mpls_ttl.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if_mpls.c diff -u src/sys/net/if_mpls.c:1.8.22.1 src/sys/net/if_mpls.c:1.8.22.2 --- src/sys/net/if_mpls.c:1.8.22.1 Tue Jul 30 03:06:42 2013 +++ src/sys/net/if_mpls.c Tue Mar 13 17:42:39 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_mpls.c,v 1.8.22.1 2013/07/30 03:06:42 msaitoh Exp $ */ +/* $NetBSD: if_mpls.c,v 1.8.22.2 2018/03/13 17:42:39 snj Exp $ */ /* * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_mpls.c,v 1.8.22.1 2013/07/30 03:06:42 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_mpls.c,v 1.8.22.2 2018/03/13 17:42:39 snj Exp $"); #include "opt_inet.h" #include "opt_mpls.h" @@ -83,12 +83,12 @@ static int mpls_send_frame(struct mbuf * static int mpls_lse(struct mbuf *); #ifdef INET -static int mpls_unlabel_inet(struct mbuf *); +static struct mbuf *mpls_unlabel_inet(struct mbuf *, int *error); static struct mbuf *mpls_label_inet(struct mbuf *, union mpls_shim *, uint); #endif #ifdef INET6 -static int mpls_unlabel_inet6(struct mbuf *); +static struct mbuf *mpls_unlabel_inet6(struct mbuf *, int *error); static struct mbuf *mpls_label_inet6(struct mbuf *, union mpls_shim *, uint); #endif @@ -308,6 +308,12 @@ mpls_lse(struct mbuf *m) int error = ENOBUFS; uint psize = sizeof(struct sockaddr_mpls); + /* If we're not accepting MPLS frames, leave now. */ + if (!mpls_accept) { + error = EINVAL; + goto done; + } + if (m->m_len < sizeof(union mpls_shim) && (m = m_pullup(m, sizeof(union mpls_shim))) == NULL) goto done; @@ -316,10 +322,7 @@ mpls_lse(struct mbuf *m) dst.smpls_family = AF_MPLS; dst.smpls_addr.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); - /* Check if we're accepting MPLS Frames */ error = EINVAL; - if (!mpls_accept) - goto done; /* TTL decrement */ if ((m = mpls_ttl_dec(m)) == NULL) @@ -331,15 +334,17 @@ mpls_lse(struct mbuf *m) #ifdef INET case MPLS_LABEL_IPV4NULL: /* Pop shim and push mbuf to IP stack */ - if (dst.smpls_addr.shim.bos) - error = mpls_unlabel_inet(m); + if (dst.smpls_addr.shim.bos) { + m = mpls_unlabel_inet(m, &error); + } break; #endif #ifdef INET6 case MPLS_LABEL_IPV6NULL: /* Pop shim and push mbuf to IPv6 stack */ - if (dst.smpls_addr.shim.bos) - error = mpls_unlabel_inet6(m); + if (dst.smpls_addr.shim.bos) { + m = mpls_unlabel_inet6(m, &error); + } break; #endif case MPLS_LABEL_RTALERT: /* Yeah, I'm all alerted */ @@ -393,8 +398,10 @@ mpls_lse(struct mbuf *m) tshim.shim.bos = tshim.shim.exp = 0; tshim.shim.ttl = mpls_defttl; if (tshim.shim.label != MPLS_LABEL_IMPLNULL && - ((m = mpls_prepend_shim(m, &tshim)) == NULL)) - return ENOBUFS; + ((m = mpls_prepend_shim(m, &tshim)) == NULL)) { + error = ENOBUFS; + goto done; + } psize += sizeof(tshim); } @@ -439,11 +446,9 @@ mpls_send_frame(struct mbuf *m, struct i return 0; } - - #ifdef INET -static int -mpls_unlabel_inet(struct mbuf *m) +static struct mbuf * +mpls_unlabel_inet(struct mbuf *m, int *error) { int s, iphlen; struct ip *iph; @@ -451,7 +456,6 @@ mpls_unlabel_inet(struct mbuf *m) struct ifqueue *inq; if (mpls_mapttl_inet || mpls_mapprec_inet) { - /* get shim info */ ms = mtod(m, union mpls_shim *); ms->s_addr = ntohl(ms->s_addr); @@ -460,23 +464,29 @@ mpls_unlabel_inet(struct mbuf *m) m_adj(m, sizeof(union mpls_shim)); /* get ip header */ - if (m->m_len < sizeof (struct ip) && - (m = m_pullup(m, sizeof(struct ip))) == NULL) - return ENOBUFS; + if (m->m_len < sizeof(struct ip) && + (m = m_pullup(m, sizeof(struct ip))) == NULL) { + *error = ENOBUFS; + return NULL; + } + iph = mtod(m, struct ip *); iphlen = iph->ip_hl << 2; /* get it all */ if (m->m_len < iphlen) { - if ((m = m_pullup(m, iphlen)) == NULL) - return ENOBUFS; + if ((m = m_pullup(m, iphlen)) == NULL) { + *error = ENOBUFS; + return NULL; + } iph = mtod(m, struct ip *); } /* check ipsum */ if (in_cksum(m, iphlen) != 0) { m_freem(m); - return EINVAL; + *error = EINVAL; + return NULL; } /* set IP ttl from MPLS ttl */ @@ -492,8 +502,9 @@ mpls_unlabel_inet(struct mbuf *m) /* reset ipsum because we modified TTL and TOS */ iph->ip_sum = 0; iph->ip_sum = in_cksum(m, iphlen); - } else + } else { m_adj(m, sizeof(union mpls_shim)); + } /* Put it on IP queue */ inq = &ipintrq; @@ -502,13 +513,15 @@ mpls_unlabel_inet(struct mbuf *m) IF_DROP(inq); splx(s); m_freem(m); - return ENOBUFS; + *error = ENOBUFS; + return NULL; } IF_ENQUEUE(inq, m); splx(s); schednetisr(NETISR_IP); - return 0; + *error = 0; + return m; } /* @@ -520,9 +533,11 @@ mpls_label_inet(struct mbuf *m, union mp struct ip iphdr; if (mpls_mapttl_inet || mpls_mapprec_inet) { - if ((m->m_len < sizeof(struct ip)) && + /* XXX Maybe just check m->m_pkthdr.len instead? */ + if ((m->m_len < offset + sizeof(struct ip)) && (m = m_pullup(m, offset + sizeof(struct ip))) == 0) - return NULL; /* XXX */ + return NULL; + m_copydata(m, offset, sizeof(struct ip), &iphdr); /* Map TTL */ @@ -539,13 +554,11 @@ mpls_label_inet(struct mbuf *m, union mp return m; } - #endif /* INET */ #ifdef INET6 - -static int -mpls_unlabel_inet6(struct mbuf *m) +static struct mbuf * +mpls_unlabel_inet6(struct mbuf *m, int *error) { struct ip6_hdr *ip6hdr; union mpls_shim ms; @@ -558,14 +571,17 @@ mpls_unlabel_inet6(struct mbuf *m) m_adj(m, sizeof(union mpls_shim)); if (m->m_len < sizeof (struct ip6_hdr) && - (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) - return ENOBUFS; + (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) { + *error = ENOBUFS; + return NULL; + } ip6hdr = mtod(m, struct ip6_hdr *); /* Because we just decremented this in mpls_lse */ ip6hdr->ip6_hlim = ms.shim.ttl + 1; - } else + } else { m_adj(m, sizeof(union mpls_shim)); + } /* Put it back on IPv6 stack */ schednetisr(NETISR_IPV6); @@ -575,13 +591,15 @@ mpls_unlabel_inet6(struct mbuf *m) IF_DROP(inq); splx(s); m_freem(m); - return ENOBUFS; + *error = ENOBUFS; + return NULL; } IF_ENQUEUE(inq, m); splx(s); - return 0; + *error = 0; + return m; } static struct mbuf * @@ -590,9 +608,10 @@ mpls_label_inet6(struct mbuf *m, union m struct ip6_hdr ip6h; if (mpls_mapttl_inet6 || mpls_mapclass_inet6) { - if (m->m_len < sizeof(struct ip6_hdr) && + if ((m->m_len < offset + sizeof(struct ip6_hdr)) && (m = m_pullup(m, offset + sizeof(struct ip6_hdr))) == 0) return NULL; + m_copydata(m, offset, sizeof(struct ip6_hdr), &ip6h); if (mpls_mapttl_inet6) @@ -607,14 +626,13 @@ mpls_label_inet6(struct mbuf *m, union m return m; } - #endif /* INET6 */ static struct mbuf * -mpls_prepend_shim(struct mbuf *m, union mpls_shim *ms) +mpls_prepend_shim(struct mbuf *m, union mpls_shim *ms) { union mpls_shim *shim; - + M_PREPEND(m, sizeof(*ms), M_DONTWAIT); if (m == NULL) return NULL; Index: src/sys/netmpls/mpls_ttl.c diff -u src/sys/netmpls/mpls_ttl.c:1.3 src/sys/netmpls/mpls_ttl.c:1.3.32.1 --- src/sys/netmpls/mpls_ttl.c:1.3 Mon Jul 5 09:54:26 2010 +++ src/sys/netmpls/mpls_ttl.c Tue Mar 13 17:42:39 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: mpls_ttl.c,v 1.3 2010/07/05 09:54:26 kefren Exp $ */ +/* $NetBSD: mpls_ttl.c,v 1.3.32.1 2018/03/13 17:42:39 snj Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -29,7 +29,7 @@ * SUCH DAMAGE. */ -/*- +/* * Copyright (c) 2010 The NetBSD Foundation, Inc. * All rights reserved. * @@ -97,7 +97,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.3 2010/07/05 09:54:26 kefren Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.3.32.1 2018/03/13 17:42:39 snj Exp $"); #include "opt_inet.h" #include "opt_mpls.h" @@ -136,21 +136,21 @@ extern int icmpreturndatabytes; struct icmp_ext_cmn_hdr { #if BYTE_ORDER == BIG_ENDIAN - unsigned char version:4; - unsigned char reserved1:4; + unsigned char version:4; + unsigned char reserved1:4; #else - unsigned char reserved1:4; - unsigned char version:4; + unsigned char reserved1:4; + unsigned char version:4; #endif - unsigned char reserved2; - unsigned short checksum; + unsigned char reserved2; + unsigned short checksum; }; struct icmp_ext_obj_hdr { u_short length; - u_char class_num; + u_char class_num; #define MPLS_STACK_ENTRY_CLASS 1 - u_char c_type; + u_char c_type; #define MPLS_STACK_ENTRY_C_TYPE 1 }; @@ -161,8 +161,8 @@ struct mpls_extension { } __packed; static void mpls_icmp_error(struct mbuf *, int, int, n_long, int, - union mpls_shim *); -static bool ip4_check(struct mbuf *); + union mpls_shim *); +static struct mbuf *ip4_check(struct mbuf *); /* * Reference: http://tools.ietf.org/html/rfc4950 @@ -179,13 +179,13 @@ mpls_icmp_error(struct mbuf *n, int type struct mbuf *m; unsigned icmplen, mblen, packetlen; struct mpls_extension mpls_icmp_ext; - + memset(&mpls_icmp_ext, 0, sizeof(mpls_icmp_ext)); mpls_icmp_ext.cmn_hdr.version = ICMP_EXT_VERSION; mpls_icmp_ext.cmn_hdr.checksum = 0; - mpls_icmp_ext.obj_hdr.length = htons(sizeof(union mpls_shim) + - sizeof(struct icmp_ext_obj_hdr)); + mpls_icmp_ext.obj_hdr.length = htons(sizeof(union mpls_shim) + + sizeof(struct icmp_ext_obj_hdr)); mpls_icmp_ext.obj_hdr.class_num = MPLS_STACK_ENTRY_CLASS; mpls_icmp_ext.obj_hdr.c_type = MPLS_STACK_ENTRY_C_TYPE; @@ -302,7 +302,7 @@ mpls_icmp_error(struct mbuf *n, int type /* * Now, copy old ip header (without options) * in front of icmp message. - */ + */ if ((m->m_flags & M_EXT) == 0 && m->m_data - sizeof(struct ip) < m->m_pktdat) panic("icmp len"); @@ -325,10 +325,9 @@ mpls_icmp_error(struct mbuf *n, int type freeit: m_freem(n); - } -static bool +static struct mbuf * ip4_check(struct mbuf *m) { struct ip *iph; @@ -336,7 +335,7 @@ ip4_check(struct mbuf *m) if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == NULL) - return false; + return NULL; iph = mtod(m, struct ip *); @@ -347,7 +346,7 @@ ip4_check(struct mbuf *m) goto freeit; if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == NULL) - return false; + return NULL; iph = mtod(m, struct ip *); } if (IN_MULTICAST(iph->ip_src.s_addr) || @@ -360,11 +359,11 @@ ip4_check(struct mbuf *m) if (len < hlen || m->m_pkthdr.len < len) goto freeit; - return true; + return m; + freeit: m_freem(m); - return false; - + return NULL; } #endif /* INET */ @@ -392,15 +391,14 @@ mpls_ttl_dec(struct mbuf *m) #ifdef INET /* - * shim ttl exceeded - * send back ICMP type 11 code 0 + * Shim ttl exceeded. Send back ICMP type 11 code 0. */ bossh.s_addr = mshim->s_addr; top_shim.s_addr = htonl(mshim->s_addr); m_adj(m, sizeof(union mpls_shim)); /* Goto BOS */ - while(bossh.shim.bos == 0) { + while (bossh.shim.bos == 0) { if (m->m_len < sizeof(union mpls_shim) && (m = m_pullup(m, sizeof(union mpls_shim))) == NULL) { m_freem(m); @@ -409,8 +407,8 @@ mpls_ttl_dec(struct mbuf *m) bossh.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); m_adj(m, sizeof(union mpls_shim)); } - - if (ip4_check(m) == true) + + if ((m = ip4_check(m)) != NULL) mpls_icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, 0, &top_shim); #else