From 149aafe6ad34a17275d25da4f8c8d04fcb60bce9 Mon Sep 17 00:00:00 2001 From: itojun Date: Mon, 15 Oct 2001 11:12:44 +0000 Subject: [PATCH] sync with kame. net.inet6.icmp6.nodeinfo is now a bitmap (2^0 = ping6 -w, 2^1 = ping6 -a). give up local if there's mbuf alloc failures. cope with ".." in hostname. sync comments/whitespaces. --- sys/netinet6/esp_rijndael.c | 4 +- sys/netinet6/icmp6.c | 160 +++++++++++++++++++++++++----------- 2 files changed, 116 insertions(+), 48 deletions(-) diff --git a/sys/netinet6/esp_rijndael.c b/sys/netinet6/esp_rijndael.c index a9e2934f8d78..762fbeff1822 100644 --- a/sys/netinet6/esp_rijndael.c +++ b/sys/netinet6/esp_rijndael.c @@ -1,4 +1,4 @@ -/* $NetBSD: esp_rijndael.c,v 1.5 2001/06/18 11:23:00 wiz Exp $ */ +/* $NetBSD: esp_rijndael.c,v 1.6 2001/10/15 11:12:44 itojun Exp $ */ /* $KAME: esp_rijndael.c,v 1.4 2001/03/02 05:53:05 itojun Exp $ */ /* @@ -48,7 +48,7 @@ #include -/* as rijndael uses asymmetric scheduled keys, we need to do it twice. */ +/* as rijndael uses assymetric scheduled keys, we need to do it twice. */ int esp_rijndael_schedlen(algo) const struct esp_algorithm *algo; diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 09f6123c48d4..d75a6cbd518a 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -1,4 +1,4 @@ -/* $NetBSD: icmp6.c,v 1.66 2001/06/22 13:01:49 itojun Exp $ */ +/* $NetBSD: icmp6.c,v 1.67 2001/10/15 11:12:44 itojun Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* @@ -288,9 +288,15 @@ icmp6_error(m, type, code, param) oip6 = mtod(m, struct ip6_hdr *); /* - * Multicast destination check. For unrecognized option errors, - * this check has already done in ip6_unknown_opt(), so we can - * check only for other errors. + * If the destination address of the erroneous packet is a multicast + * address, or the packet was sent using link-layer multicast, + * we should basically suppress sending an error (RFC 2463, Section + * 2.4). + * We have two exceptions (the item e.2 in that section): + * - the Pakcet Too Big message can be sent for path MTU discovery. + * - the Parameter Problem Message that can be allowed an icmp6 error + * in the option type field. This check has been done in + * ip6_unknown_opt(), so we can just check the type and code. */ if ((m->m_flags & (M_BCAST|M_MCAST) || IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) && @@ -299,7 +305,10 @@ icmp6_error(m, type, code, param) code != ICMP6_PARAMPROB_OPTION))) goto freeit; - /* Source address check. XXX: the case of anycast source? */ + /* + * RFC 2463, 2.4 (e.5): source address check. + * XXX: the case of anycast source? + */ if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) || IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) goto freeit; @@ -336,7 +345,18 @@ icmp6_error(m, type, code, param) } else { /* ICMPv6 informational - send the error */ } - } else { + } +#if 0 /* controversial */ + else if (off >= 0 && nxt == IPPROTO_ESP) { + /* + * It could be ICMPv6 error inside ESP. Take a safer side, + * don't respond. + */ + icmp6stat.icp6s_canterror++; + goto freeit; + } +#endif + else { /* non-ICMPv6 - send the error */ } @@ -388,7 +408,7 @@ icmp6_error(m, type, code, param) m->m_pkthdr.rcvif = NULL; icmp6stat.icp6s_outhist[type]++; - icmp6_reflect(m, sizeof(struct ip6_hdr)); /*header order: IPv6 - ICMPv6*/ + icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */ return; @@ -416,7 +436,7 @@ icmp6_input(mp, offp, proto) #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE); - /* m might change if M_LOOP. So, call mtod after this */ + /* m might change if M_LOOP. So, call mtod after this */ #endif /* @@ -476,7 +496,6 @@ icmp6_input(mp, offp, proto) icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error); switch (icmp6->icmp6_type) { - case ICMP6_DST_UNREACH: icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach); switch (code) { @@ -497,7 +516,7 @@ icmp6_input(mp, offp, proto) #else case ICMP6_DST_UNREACH_BEYONDSCOPE: /* I mean "source address was incorrect." */ - code = PRC_PARAMPROB; + code = PRC_UNREACH_NET; break; #endif case ICMP6_DST_UNREACH_NOPORT: @@ -527,8 +546,10 @@ icmp6_input(mp, offp, proto) icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); switch (code) { case ICMP6_TIME_EXCEED_TRANSIT: + code = PRC_TIMXCEED_INTRANS; + break; case ICMP6_TIME_EXCEED_REASSEMBLY: - code += PRC_TIMXCEED_INTRANS; + code = PRC_TIMXCEED_REASS; break; default: goto badcode; @@ -556,17 +577,29 @@ icmp6_input(mp, offp, proto) icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo); if (code != 0) goto badcode; - if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { - /* Give up remote */ - break; + /* + * Copy mbuf to send to two data paths: userland socket(s), + * and to the querier (echo reply). + * m: a copy for socket, n: a copy for querier + */ + if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { + /* Give up local */ + n = m; + m = NULL; + goto deliverecho; } - if ((n->m_flags & M_EXT) != 0 - || n->m_len < off + sizeof(struct icmp6_hdr)) { + /* + * If the first mbuf is shared, or the first mbuf is too short, + * copy the first part of the data into a fresh mbuf. + * Otherwise, we will wrongly overwrite both copies. + */ + if ((n->m_flags & M_EXT) != 0 || + n->m_len < off + sizeof(struct icmp6_hdr)) { struct mbuf *n0 = n; const int maxlen = sizeof(*nip6) + sizeof(*nicmp6); /* - * Prepare an internal mbuf. m_pullup() doesn't + * Prepare an internal mbuf. m_pullup() doesn't * always copy the length we specified. */ if (maxlen >= MCLBYTES) { @@ -583,9 +616,11 @@ icmp6_input(mp, offp, proto) } } if (n == NULL) { - /* Give up remote */ + /* Give up local */ m_freem(n0); - break; + n = m; + m = NULL; + goto deliverecho; } M_COPY_PKTHDR(n, n0); /* @@ -596,17 +631,19 @@ icmp6_input(mp, offp, proto) nicmp6 = (struct icmp6_hdr *)(nip6 + 1); bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); noff = sizeof(struct ip6_hdr); - n->m_pkthdr.len = n->m_len = - noff + sizeof(struct icmp6_hdr); + n->m_len = noff + sizeof(struct icmp6_hdr); /* - * Adjust mbuf. ip6_plen will be adjusted in + * Adjust mbuf. ip6_plen will be adjusted in * ip6_output(). + * n->m_pkthdr.len == n0->m_pkthdr.len at this point. */ + n->m_pkthdr.len += noff + sizeof(struct icmp6_hdr); + n->m_pkthdr.len -= (off + sizeof(struct icmp6_hdr)); m_adj(n0, off + sizeof(struct icmp6_hdr)); - n->m_pkthdr.len += n0->m_pkthdr.len; n->m_next = n0; n0->m_flags &= ~M_PKTHDR; } else { + deliverecho: nip6 = mtod(n, struct ip6_hdr *); nicmp6 = (struct icmp6_hdr *)((caddr_t)nip6 + off); noff = off; @@ -618,6 +655,8 @@ icmp6_input(mp, offp, proto) icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++; icmp6_reflect(n, noff); } + if (!m) + goto freeit; break; case ICMP6_ECHO_REPLY: @@ -652,7 +691,7 @@ icmp6_input(mp, offp, proto) case MLD6_MTRACE_RESP: case MLD6_MTRACE: - /* XXX: these two are experimental. not officially defind. */ + /* XXX: these two are experimental. not officially defind. */ /* XXX: per-interface statistics? */ break; /* just pass it to applications */ @@ -675,7 +714,7 @@ icmp6_input(mp, offp, proto) IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo), IPPROTO_DONE); #endif - n = m_copy(m, 0, M_COPYALL); + n = m_copym(m, 0, M_COPYALL, M_DONTWAIT); if (n) n = ni6_input(n, off); /* XXX meaningless if n == NULL */ @@ -684,6 +723,9 @@ icmp6_input(mp, offp, proto) u_char *p; int maxlen, maxhlen; + if ((icmp6_nodeinfo & 5) != 5) + break; + if (code != 0) goto badcode; maxlen = sizeof(*nip6) + sizeof(*nicmp6) + 4; @@ -703,6 +745,7 @@ icmp6_input(mp, offp, proto) /* Give up remote */ break; } + n->m_pkthdr.rcvif = NULL; n->m_len = 0; maxhlen = M_TRAILINGSPACE(n) - maxlen; if (maxhlen > hostnamelen) @@ -716,7 +759,7 @@ icmp6_input(mp, offp, proto) bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); p = (u_char *)(nicmp6 + 1); bzero(p, 4); - bcopy(hostname, p + 4, maxhlen); /*meaningless TTL*/ + bcopy(hostname, p + 4, maxhlen); /* meaningless TTL */ noff = sizeof(struct ip6_hdr); M_COPY_PKTHDR(n, m); /* just for recvif */ n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + @@ -909,7 +952,7 @@ icmp6_notify_error(m, off, icmp6len, code) struct ip6_rthdr0 *rth0; int rthlen; - while (1) { /* XXX: should avoid inf. loop explicitly? */ + while (1) { /* XXX: should avoid infinite loop explicitly? */ struct ip6_ext *eh; switch (nxt) { @@ -1023,7 +1066,7 @@ icmp6_notify_error(m, off, icmp6len, code) default: /* * This case includes ESP and the No Next - * Header. In such cases going to the notify + * Header. In such cases going to the notify * label does not have any meaning * (i.e. ctlfunc will be NULL), but we go * anyway since we might have to update @@ -1171,8 +1214,9 @@ icmp6_mtudisc_update(ip6cp, validated) rt->rt_rmx.rmx_mtu = mtu; } } - if (rt) + if (rt) { /* XXX: need braces to avoid conflict with else in RTFREE. */ RTFREE(rt); + } /* * Notify protocols that the MTU for this destination @@ -1255,7 +1299,7 @@ ni6_input(m, off) /* 07 draft */ if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0) break; - /*FALLTHROUGH*/ + /* FALLTHROUGH */ case NI_QTYPE_FQDN: case NI_QTYPE_NODEADDR: switch (ni6->ni_code) { @@ -1353,6 +1397,18 @@ ni6_input(m, off) break; } + /* refuse based on configuration. XXX ICMP6_NI_REFUSED? */ + switch (qtype) { + case NI_QTYPE_FQDN: + if ((icmp6_nodeinfo & 1) == 0) + goto bad; + break; + case NI_QTYPE_NODEADDR: + if ((icmp6_nodeinfo & 2) == 0) + goto bad; + break; + } + /* guess reply length */ switch (qtype) { case NI_QTYPE_NOOP: @@ -1373,7 +1429,7 @@ ni6_input(m, off) default: /* * XXX: We must return a reply with the ICMP6 code - * `unknown Qtype' in this case. However we regard the case + * `unknown Qtype' in this case. However we regard the case * as an FQDN query for backward compatibility. * Older versions set a random value to this field, * so it rarely varies in the defined qtypes. @@ -1547,8 +1603,12 @@ ni6_nametodns(name, namelen, old) /* result does not fit into mbuf */ if (cp + i + 1 >= ep) goto fail; - /* DNS label length restriction, RFC1035 page 8 */ - if (i >= 64) + /* + * DNS label length restriction, RFC1035 page 8. + * "i == 0" case is included here to avoid returning + * 0-length label on "foo..bar". + */ + if (i <= 0 || i >= 64) goto fail; *cp++ = i; bcopy(p, cp, i); @@ -1567,7 +1627,7 @@ ni6_nametodns(name, namelen, old) } panic("should not reach here"); - /*NOTREACHED*/ + /* NOTREACHED */ fail: if (m) @@ -1719,7 +1779,7 @@ ni6_addrs(ni6, m, ifpp, subj) /* * check if anycast is okay. - * XXX: just experimental. not in the spec. + * XXX: just experimental. not in the spec. */ if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 && (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) @@ -1805,7 +1865,7 @@ ni6_store_addrs(ni6, nni6, ifp0, resid) /* * check if anycast is okay. - * XXX: just experimental. not in the spec. + * XXX: just experimental. not in the spec. */ if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 && (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) @@ -1837,16 +1897,21 @@ ni6_store_addrs(ni6, nni6, ifp0, resid) * Note that we currently do not support stateful * address configuration by DHCPv6, so the former * case can't happen. + * + * TTL must be 2^31 > TTL >= 0. */ if (ifa6->ia6_lifetime.ia6t_expire == 0) ltime = ND6_INFINITE_LIFETIME; else { if (ifa6->ia6_lifetime.ia6t_expire > time_second) - ltime = htonl(ifa6->ia6_lifetime.ia6t_expire - time_second); + ltime = ifa6->ia6_lifetime.ia6t_expire - time_second; else ltime = 0; } + if (ltime > 0x7fffffff) + ltime = 0x7fffffff; + ltime = htonl(ltime); bcopy(<ime, cp, sizeof(u_int32_t)); cp += sizeof(u_int32_t); @@ -2055,7 +2120,9 @@ icmp6_reflect(m, off) sa6_src.sin6_len = sizeof(sa6_src); sa6_src.sin6_addr = ip6->ip6_dst; in6_recoverscope(&sa6_src, &ip6->ip6_dst, m->m_pkthdr.rcvif); - in6_embedscope(&ip6->ip6_dst, &sa6_src, NULL, NULL); + in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL, NULL); + ip6->ip6_dst = sa6_src.sin6_addr; + bzero(&sa6_dst, sizeof(sa6_dst)); sa6_dst.sin6_family = AF_INET6; sa6_dst.sin6_len = sizeof(sa6_dst); @@ -2064,7 +2131,7 @@ icmp6_reflect(m, off) in6_embedscope(&t, &sa6_dst, NULL, NULL); /* - * If the incoming packet was addressed directly to us(i.e. unicast), + * If the incoming packet was addressed directly to us (i.e. unicast), * use dst as the src for the reply. * The IN6_IFF_NOTREADY case would be VERY rare, but is possible * (for example) when we encounter an error while forwarding procedure @@ -2079,7 +2146,7 @@ icmp6_reflect(m, off) if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) { /* * This is the case if the dst is our link-local address - * and the sender is also ourseleves. + * and the sender is also ourselves. */ src = &t; } @@ -2090,13 +2157,14 @@ icmp6_reflect(m, off) /* * This case matches to multicasts, our anycast, or unicasts - * that we do not own. Select a source address based on the + * that we do not own. Select a source address based on the * source address of the erroneous packet. */ bzero(&ro, sizeof(ro)); src = in6_selectsrc(&sa6_src, NULL, NULL, &ro, NULL, &e); - if (ro.ro_rt) + if (ro.ro_rt) { /* XXX: see comments in icmp6_mtudisc_update */ RTFREE(ro.ro_rt); /* XXX: we could use this */ + } if (src == NULL) { nd6log((LOG_DEBUG, "icmp6_reflect: source can't be determined: " @@ -2123,7 +2191,7 @@ icmp6_reflect(m, off) sizeof(struct ip6_hdr), plen); /* - * xxx option handling + * XXX option handling */ m->m_flags &= ~(M_BCAST|M_MCAST); @@ -2322,7 +2390,7 @@ icmp6_redirect_input(m, off) nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); - if (!is_onlink) { /* better router case. perform rtredirect. */ + if (!is_onlink) { /* better router case. perform rtredirect. */ /* perform rtredirect */ struct sockaddr_in6 sdst; struct sockaddr_in6 sgw; @@ -2533,7 +2601,7 @@ icmp6_redirect_output(m0, rt) if (!rt_router) goto nolladdropt; len = sizeof(*nd_opt) + ifp->if_addrlen; - len = (len + 7) & ~7; /*round by 8*/ + len = (len + 7) & ~7; /* round by 8 */ /* safety check */ if (len + (p - (u_char *)ip6) > maxlen) goto nolladdropt; @@ -2771,7 +2839,7 @@ icmp6_ratelimit(dst, type, code) { int ret; - ret = 0; /*okay to send*/ + ret = 0; /* okay to send */ /* PPS limit */ if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,