Module Name: src Committed By: snj Date: Mon Feb 12 18:18:00 UTC 2018
Modified Files: src/sys/net [netbsd-8]: if_mpls.c src/sys/netmpls [netbsd-8]: mpls_ttl.c Log Message: Pull up following revision(s) (requested by maxv in ticket #546): sys/net/if_mpls.c: 1.31-1.33 sys/netmpls/mpls_ttl.c: 1.9-1.11 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: * Declare TRIM_LABEL as a function. * 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. -- Style in MPLS. -- Add XXX. To generate a diff of this commit: cvs rdiff -u -r1.29.8.1 -r1.29.8.2 src/sys/net/if_mpls.c cvs rdiff -u -r1.8 -r1.8.10.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.29.8.1 src/sys/net/if_mpls.c:1.29.8.2 --- src/sys/net/if_mpls.c:1.29.8.1 Sun Dec 10 10:10:25 2017 +++ src/sys/net/if_mpls.c Mon Feb 12 18:18:00 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_mpls.c,v 1.29.8.1 2017/12/10 10:10:25 snj Exp $ */ +/* $NetBSD: if_mpls.c,v 1.29.8.2 2018/02/12 18:18:00 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.29.8.1 2017/12/10 10:10:25 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_mpls.c,v 1.29.8.2 2018/02/12 18:18:00 snj Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -74,37 +74,27 @@ __KERNEL_RCSID(0, "$NetBSD: if_mpls.c,v #include "ioconf.h" -#define TRIM_LABEL do { \ - m_adj(m, sizeof(union mpls_shim)); \ - if (m->m_len < sizeof(union mpls_shim) && \ - (m = m_pullup(m, sizeof(union mpls_shim))) == NULL) \ - goto done; \ - dst.smpls_addr.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); \ - } while (/* CONSTCOND */ 0) - - static int mpls_clone_create(struct if_clone *, int); static int mpls_clone_destroy(struct ifnet *); static struct if_clone mpls_if_cloner = IF_CLONE_INITIALIZER("mpls", mpls_clone_create, mpls_clone_destroy); - static void mpls_input(struct ifnet *, struct mbuf *); static int mpls_output(struct ifnet *, struct mbuf *, const struct sockaddr *, - const struct rtentry *); + const struct rtentry *); static int mpls_ioctl(struct ifnet *, u_long, void *); static int mpls_send_frame(struct mbuf *, struct ifnet *, const struct rtentry *); 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 @@ -211,7 +201,6 @@ mpls_input(struct ifnet *ifp, struct mbu void mplsintr(void) { - struct mbuf *m; for (;;) { @@ -279,7 +268,7 @@ mpls_output(struct ifnet *ifp, struct mb psize += sizeof(mh); } - switch(dst->sa_family) { + switch (dst->sa_family) { #ifdef INET case AF_INET: m = mpls_label_inet(m, &mh, psize - sizeof(struct sockaddr_mpls)); @@ -304,7 +293,7 @@ mpls_output(struct ifnet *ifp, struct mb ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; - if ((rt1=rtalloc1(rt->rt_gateway, 1)) == NULL) { + if ((rt1 = rtalloc1(rt->rt_gateway, 1)) == NULL) { m_freem(m); return EHOSTUNREACH; } @@ -348,6 +337,20 @@ mpls_ioctl(struct ifnet *ifp, u_long cmd return error; } +static inline struct mbuf * +mpls_trim_label(struct mbuf *m, union mpls_shim *sh) +{ + m_adj(m, sizeof(union mpls_shim)); + + if (m->m_len < sizeof(union mpls_shim) && + (m = m_pullup(m, sizeof(union mpls_shim))) == NULL) + return NULL; + + sh->s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); + + return m; +} + /* * MPLS Label Switch Engine */ @@ -361,6 +364,12 @@ mpls_lse(struct mbuf *m) uint psize = sizeof(struct sockaddr_mpls); bool push_back_alert = false; + /* If we're not accepting MPLS frames, leave now. */ + if (!mpls_frame_accept) { + error = EINVAL; + goto done; + } + if (m->m_len < sizeof(union mpls_shim) && (m = m_pullup(m, sizeof(union mpls_shim))) == NULL) goto done; @@ -369,26 +378,31 @@ 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_frame_accept) - goto done; /* TTL decrement */ if ((m = mpls_ttl_dec(m)) == NULL) goto done; /* RFC 4182 */ - if (mpls_rfc4182 != 0) - while((dst.smpls_addr.shim.label == MPLS_LABEL_IPV4NULL || + if (mpls_rfc4182 != 0) { + while ((dst.smpls_addr.shim.label == MPLS_LABEL_IPV4NULL || dst.smpls_addr.shim.label == MPLS_LABEL_IPV6NULL) && - __predict_false(dst.smpls_addr.shim.bos == 0)) - TRIM_LABEL; + __predict_false(dst.smpls_addr.shim.bos == 0)) { + m = mpls_trim_label(m, &dst.smpls_addr); + if (m == NULL) { + goto done; + } + } + } /* RFC 3032 Section 2.1 Page 4 */ if (__predict_false(dst.smpls_addr.shim.label == MPLS_LABEL_RTALERT) && dst.smpls_addr.shim.bos == 0) { - TRIM_LABEL; + m = mpls_trim_label(m, &dst.smpls_addr); + if (m == NULL) { + goto done; + } push_back_alert = true; } @@ -398,15 +412,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 */ @@ -423,9 +439,9 @@ mpls_lse(struct mbuf *m) goto done; /* Get a route to dst */ - dst.smpls_addr.shim.ttl = - dst.smpls_addr.shim.bos = - dst.smpls_addr.shim.exp = 0; + dst.smpls_addr.shim.ttl = 0; + dst.smpls_addr.shim.bos = 0; + dst.smpls_addr.shim.exp = 0; dst.smpls_addr.s_addr = htonl(dst.smpls_addr.s_addr); if ((rt = rtalloc1((const struct sockaddr*)&dst, 1)) == NULL) goto done; @@ -460,8 +476,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); } @@ -471,8 +489,10 @@ mpls_lse(struct mbuf *m) tshim.s_addr = MPLS_LABEL_RTALERT; tshim.shim.bos = tshim.shim.exp = 0; tshim.shim.ttl = mpls_defttl; - if ((m = mpls_prepend_shim(m, &tshim)) == NULL) - return ENOBUFS; + if ((m = mpls_prepend_shim(m, &tshim)) == NULL) { + error = ENOBUFS; + goto done; + } } if ((rt->rt_flags & RTF_GATEWAY) == 0) { @@ -523,67 +543,73 @@ 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) { struct ip *iph; - union mpls_shim *ms; + union mpls_shim ms; int iphlen; if (mpls_mapttl_inet || mpls_mapprec_inet) { - /* get shim info */ - ms = mtod(m, union mpls_shim *); - ms->s_addr = ntohl(ms->s_addr); + ms.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); /* and get rid of it */ 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 */ if (mpls_mapttl_inet) - iph->ip_ttl = ms->shim.ttl; + iph->ip_ttl = ms.shim.ttl; /* set IP Precedence from MPLS Exp */ if (mpls_mapprec_inet) { iph->ip_tos = (iph->ip_tos << 3) >> 3; - iph->ip_tos |= ms->shim.exp << 5; + iph->ip_tos |= ms.shim.exp << 5; } /* 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 */ if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) { m_freem(m); - return ENOBUFS; + *error = ENOBUFS; + return NULL; } - return 0; + + *error = 0; + return m; } /* @@ -595,9 +621,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 */ @@ -614,13 +642,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; @@ -630,22 +656,28 @@ mpls_unlabel_inet6(struct mbuf *m) ms.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); 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; + if (m->m_len < sizeof(struct ip6_hdr) && + (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 queue. */ if (__predict_false(!pktq_enqueue(ip6_pktq, m, 0))) { m_freem(m); - return ENOBUFS; + *error = ENOBUFS; + return NULL; } - return 0; + + *error = 0; + return m; } static struct mbuf * @@ -654,9 +686,11 @@ 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) && + /* XXX Maybe just check m->m_pkthdr.len instead? */ + 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) @@ -671,14 +705,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.8 src/sys/netmpls/mpls_ttl.c:1.8.10.1 --- src/sys/netmpls/mpls_ttl.c:1.8 Fri Jun 10 13:31:44 2016 +++ src/sys/netmpls/mpls_ttl.c Mon Feb 12 18:18:00 2018 @@ -1,35 +1,6 @@ -/* $NetBSD: mpls_ttl.c,v 1.8 2016/06/10 13:31:44 ozaki-r Exp $ */ +/* $NetBSD: mpls_ttl.c,v 1.8.10.1 2018/02/12 18:18:00 snj Exp $ */ /* - * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/*- * Copyright (c) 2010 The NetBSD Foundation, Inc. * All rights reserved. * @@ -66,6 +37,35 @@ */ /* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -97,7 +97,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.8 2016/06/10 13:31:44 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.8.10.1 2018/02/12 18:18:00 snj Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -162,15 +162,19 @@ 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 *); /* - * References: RFC 4884 and RFC 4950 + * Send an ICMP Extended error message. References: RFC4884 and RFC4950. + * * This should be in sync with icmp_error() in sys/netinet/ip_icmp.c - * XXX: is called only for ICMP_TIMXCEED_INTRANS but code is too general + * XXX: is called only for ICMP_TIMXCEED_INTRANS but code is too general. + * + * XXX We're not setting the 'length' field of the Extended ICMP header. + * According to RFC4884, we are in 'non-compliant' mode. Moreover, we're + * not computing the checksum of the Extended ICMP header. */ - static void mpls_icmp_error(struct mbuf *n, int type, int code, n_long dest, int destmtu, union mpls_shim *shim) @@ -181,13 +185,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.cmn_hdr.checksum = 0; /* XXX */ - 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; @@ -200,6 +204,7 @@ mpls_icmp_error(struct mbuf *n, int type #endif if (type != ICMP_REDIRECT) ICMP_STATINC(ICMP_STAT_ERROR); + /* * Don't send error if the original packet was encrypted. * Don't send error if not the first fragment of message. @@ -217,6 +222,7 @@ mpls_icmp_error(struct mbuf *n, int type ICMP_STATINC(ICMP_STAT_OLDICMP); goto freeit; } + /* Don't send error in response to a multicast or broadcast packet */ if (n->m_flags & (M_BCAST|M_MCAST)) goto freeit; @@ -232,6 +238,7 @@ mpls_icmp_error(struct mbuf *n, int type * Now, formulate icmp message */ icmplen = min(ICMP_EXT_OFFSET, ntohs(oip->ip_len)); + /* * Defend against mbuf chains shorter than oip->ip_len - oiplen: */ @@ -252,7 +259,7 @@ mpls_icmp_error(struct mbuf *n, int type * icmp_sysctl will keep things below that limit. */ - KASSERT (packetlen <= MCLBYTES); + KASSERT(packetlen <= MCLBYTES); m = m_gethdr(M_DONTWAIT, MT_HEADER); if (m && (packetlen > MHLEN)) { @@ -264,6 +271,7 @@ mpls_icmp_error(struct mbuf *n, int type } if (m == NULL) goto freeit; + MCLAIM(m, n->m_owner); m->m_len = packetlen; if ((m->m_flags & M_EXT) == 0) @@ -304,7 +312,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"); @@ -327,10 +335,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; @@ -338,7 +345,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 *); @@ -349,9 +356,15 @@ 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 *); } + + /* + * RFC1122: packets with a multicast source address are + * not allowed. + * RFC1122: 127/8 must not appear on wire. + */ if (IN_MULTICAST(iph->ip_src.s_addr) || (ntohl(iph->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || (ntohl(iph->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || @@ -362,13 +375,12 @@ 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 */ struct mbuf * @@ -376,7 +388,7 @@ mpls_ttl_dec(struct mbuf *m) { union mpls_shim *mshim; #ifdef INET - union mpls_shim top_shim, bossh; + union mpls_shim top_shim, bos_shim; #endif if (__predict_false(m->m_len < sizeof(union mpls_shim) && @@ -394,25 +406,24 @@ 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; + bos_shim.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 (bos_shim.shim.bos == 0) { if (m->m_len < sizeof(union mpls_shim) && (m = m_pullup(m, sizeof(union mpls_shim))) == NULL) { m_freem(m); return NULL; } - bossh.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); + bos_shim.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