Module Name: src Committed By: kefren Date: Mon Jul 5 09:54:26 UTC 2010
Modified Files: src/sys/netmpls: mpls_ttl.c Log Message: do some rudimentary checks on ip4 header before passing packet to mpls_icmp_error To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 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/netmpls/mpls_ttl.c diff -u src/sys/netmpls/mpls_ttl.c:1.2 src/sys/netmpls/mpls_ttl.c:1.3 --- src/sys/netmpls/mpls_ttl.c:1.2 Fri Jul 2 12:25:54 2010 +++ src/sys/netmpls/mpls_ttl.c Mon Jul 5 09:54:26 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: mpls_ttl.c,v 1.2 2010/07/02 12:25:54 kefren Exp $ */ +/* $NetBSD: mpls_ttl.c,v 1.3 2010/07/05 09:54:26 kefren Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -97,7 +97,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.2 2010/07/02 12:25:54 kefren Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.3 2010/07/05 09:54:26 kefren Exp $"); #include "opt_inet.h" #include "opt_mpls.h" @@ -160,10 +160,12 @@ union mpls_shim ms; } __packed; -static void mpls_icmp_error(struct mbuf*, int, int, n_long, int, union mpls_shim *); +static void mpls_icmp_error(struct mbuf *, int, int, n_long, int, + union mpls_shim *); +static bool ip4_check(struct mbuf *); /* - * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt + * Reference: http://tools.ietf.org/html/rfc4950 * This should be in sync with icmp_error() in sys/netinet/ip_icmp.c */ @@ -326,6 +328,45 @@ } +static bool +ip4_check(struct mbuf *m) +{ + struct ip *iph; + int hlen, len; + + if (m->m_len < sizeof(struct ip) && + (m = m_pullup(m, sizeof(struct ip))) == NULL) + return false; + + iph = mtod(m, struct ip *); + + if (iph->ip_v != IPVERSION) + goto freeit; + hlen = iph->ip_hl << 2; + if (hlen < sizeof(struct ip)) + goto freeit; + if (hlen > m->m_len) { + if ((m = m_pullup(m, hlen)) == NULL) + return false; + iph = mtod(m, struct ip *); + } + 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 || + in_cksum(m, hlen) != 0) + goto freeit; + + len = ntohs(iph->ip_len); + if (len < hlen || m->m_pkthdr.len < len) + goto freeit; + + return true; +freeit: + m_freem(m); + return false; + +} + #endif /* INET */ struct mbuf * @@ -368,9 +409,10 @@ bossh.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); m_adj(m, sizeof(union mpls_shim)); } - - mpls_icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, - 0, 0, &top_shim); + + if (ip4_check(m) == true) + mpls_icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, + 0, 0, &top_shim); #else m_freem(m); #endif