Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet6/ip6_output.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet6/ip6_output.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.23 retrieving revision 1.23.2.7 diff -u -p -r1.23 -r1.23.2.7 --- src/sys/netinet6/ip6_output.c 2000/06/20 02:24:42 1.23 +++ src/sys/netinet6/ip6_output.c 2002/09/23 13:48:36 1.23.2.7 @@ -1,4 +1,4 @@ -/* $NetBSD: ip6_output.c,v 1.23 2000/06/20 02:24:42 itojun Exp $ */ +/* $NetBSD: ip6_output.c,v 1.23.2.7 2002/09/23 13:48:36 itojun Exp $ */ /* $KAME: ip6_output.c,v 1.109 2000/05/31 05:03:09 jinmei Exp $ */ /* @@ -92,6 +92,7 @@ #include #include #include +#include #ifdef IPSEC #include @@ -170,7 +171,7 @@ ip6_output(m0, opt, ro, flags, im6o, ifp /* for AH processing. stupid to have "socket" variable in IP layer... */ so = ipsec_getsocket(m); - ipsec_setsocket(m, NULL); + (void)ipsec_setsocket(m, NULL); ip6 = mtod(m, struct ip6_hdr *); #endif /* IPSEC */ @@ -770,11 +771,24 @@ skip_ipsec2:; * Larger scopes than link will be supported in the near * future. */ + origifp = NULL; if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])]; else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) origifp = ifindex2ifnet[ntohs(ip6->ip6_dst.s6_addr16[1])]; - else + /* + * XXX: origifp can be NULL even in those two cases above. + * For example, if we remove the (only) link-local address + * from the loopback interface, and try to send a link-local + * address without link-id information. Then the source + * address is ::1, and the destination address is the + * link-local address with its s6_addr16[1] being zero. + * What is worse, if the packet goes to the loopback interface + * by a default rejected route, the null pointer would be + * passed to looutput, and the kernel would hang. + * The following last resort would prevent such disaster. + */ + if (origifp == NULL) origifp = ifp; } else @@ -828,7 +842,8 @@ skip_ipsec2:; * Run through list of hooks for output packets. */ m1 = m; - pfh = pfil_hook_get(PFIL_OUT, &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); + pfh = pfil_hook_get(PFIL_OUT, + &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); for (; pfh; pfh = pfh->pfil_link.tqe_next) if (pfh->pfil_func) { rv = pfh->pfil_func(ip6, sizeof(*ip6), ifp, 1, &m1); @@ -874,6 +889,10 @@ skip_ipsec2:; } } #endif +#ifdef IPSEC + /* clean ipsec history once it goes out of the node */ + ipsec_delaux(m); +#endif #ifdef OLDIP6OUTPUT error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); @@ -1006,6 +1025,10 @@ sendorfree: } } #endif +#ifdef IPSEC + /* clean ipsec history once it goes out of the node */ + ipsec_delaux(m); +#endif #ifdef OLDIP6OUTPUT error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, @@ -1124,7 +1147,7 @@ ip6_insert_jumboopt(exthdrs, plen) mopt->m_len += JUMBOOPTLEN; } optbuf[0] = IP6OPT_PADN; - optbuf[1] = 1; + optbuf[1] = 0; /* * Adjust the header length according to the pad and @@ -1976,10 +1999,12 @@ ip6_setpktoptions(control, opt, priv) /* * Check if the requested source address is indeed a - * unicast address assigned to the node. + * unicast address assigned to the node, and can be + * used as the packet's source address. */ if (!IN6_IS_ADDR_UNSPECIFIED(&opt->ip6po_pktinfo->ipi6_addr)) { struct ifaddr *ia; + struct in6_ifaddr *ia6; struct sockaddr_in6 sin6; bzero(&sin6, sizeof(sin6)); @@ -1994,6 +2019,11 @@ ip6_setpktoptions(control, opt, priv) opt->ip6po_pktinfo->ipi6_ifindex))) { return(EADDRNOTAVAIL); } + ia6 = (struct in6_ifaddr *)ia; + if ((ia6->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) != 0) { + return(EADDRNOTAVAIL); + } + /* * Check if the requested source address is * indeed a unicast address assigned to the