ip6_output.c (60889) | ip6_output.c (62587) |
---|---|
1/* $FreeBSD: head/sys/netinet6/ip6_output.c 62587 2000-07-04 16:35:15Z itojun $ */ 2/* $KAME: ip6_output.c,v 1.115 2000/07/03 13:23:28 itojun Exp $ */ 3 |
|
1/* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. | 4/* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. |
28 * 29 * $FreeBSD: head/sys/netinet6/ip6_output.c 60889 2000-05-24 21:16:56Z archie $ | |
30 */ 31 32/* 33 * Copyright (c) 1982, 1986, 1988, 1990, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions --- 21 unchanged lines hidden (view full) --- 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 65 */ 66 | 31 */ 32 33/* 34 * Copyright (c) 1982, 1986, 1988, 1990, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions --- 21 unchanged lines hidden (view full) --- 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 66 */ 67 |
67#include "opt_ipsec.h" | |
68#include "opt_ip6fw.h" | 68#include "opt_ip6fw.h" |
69#include "opt_inet.h" 70#include "opt_inet6.h" 71#include "opt_ipsec.h" |
|
69 70#include <sys/param.h> 71#include <sys/malloc.h> 72#include <sys/mbuf.h> 73#include <sys/errno.h> 74#include <sys/protosw.h> 75#include <sys/socket.h> 76#include <sys/socketvar.h> 77#include <sys/systm.h> 78#include <sys/kernel.h> 79#include <sys/proc.h> 80 81#include <net/if.h> 82#include <net/route.h> 83 84#include <netinet/in.h> 85#include <netinet/in_var.h> | 72 73#include <sys/param.h> 74#include <sys/malloc.h> 75#include <sys/mbuf.h> 76#include <sys/errno.h> 77#include <sys/protosw.h> 78#include <sys/socket.h> 79#include <sys/socketvar.h> 80#include <sys/systm.h> 81#include <sys/kernel.h> 82#include <sys/proc.h> 83 84#include <net/if.h> 85#include <net/route.h> 86 87#include <netinet/in.h> 88#include <netinet/in_var.h> |
86#include <netinet6/ip6.h> 87#include <netinet6/icmp6.h> 88#include <netinet/in_pcb.h> | 89#include 90#include |
89#include <netinet6/ip6_var.h> | 91#include <netinet6/ip6_var.h> |
92#include <netinet/in_pcb.h> |
|
90#include <netinet6/nd6.h> 91 92#ifdef IPSEC 93#include <netinet6/ipsec.h> | 93#include <netinet6/nd6.h> 94 95#ifdef IPSEC 96#include <netinet6/ipsec.h> |
97#ifdef INET6 |
|
94#include <netinet6/ipsec6.h> | 98#include <netinet6/ipsec6.h> |
95#include <netkey/key.h> 96#ifdef IPSEC_DEBUG 97#include <netkey/key_debug.h> 98#else 99#define KEYDEBUG(lev,arg) | |
100#endif | 99#endif |
100#include <netkey/key.h> |
|
101#endif /* IPSEC */ 102 | 101#endif /* IPSEC */ 102 |
103#include "loop.h" 104 | |
105#include <net/net_osdep.h> 106 107#ifdef IPV6FIREWALL 108#include <netinet6/ip6_fw.h> 109#endif 110 111static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options"); 112 113struct ip6_exthdrs { | 103#include <net/net_osdep.h> 104 105#ifdef IPV6FIREWALL 106#include <netinet6/ip6_fw.h> 107#endif 108 109static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options"); 110 111struct ip6_exthdrs { |
114 struct mbuf *ip6e_ip6; 115 struct mbuf *ip6e_hbh; 116 struct mbuf *ip6e_dest1; 117 struct mbuf *ip6e_rthdr; 118 struct mbuf *ip6e_dest2; | 112 struct mbuf *ip6e_ip6; 113 struct mbuf *ip6e_hbh; 114 struct mbuf *ip6e_dest1; 115 struct mbuf *ip6e_rthdr; 116 struct mbuf *ip6e_dest2; |
119}; 120 | 117}; 118 |
121static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *, | 119static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *, |
122 struct socket *, struct sockopt *sopt)); | 120 struct socket *, struct sockopt *sopt)); |
123static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *)); 124static int ip6_getmoptions __P((int, struct ip6_moptions *, struct mbuf **)); 125static int ip6_copyexthdr __P((struct mbuf **, caddr_t, int)); 126static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int, | 121static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *)); 122static int ip6_getmoptions __P((int, struct ip6_moptions *, struct mbuf **)); 123static int ip6_copyexthdr __P((struct mbuf **, caddr_t, int)); 124static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int, |
127 struct ip6_frag **)); | 125 struct ip6_frag **)); |
128static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t)); 129static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *)); | 126static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t)); 127static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *)); |
130 131/* 132 * IP6 output. The packet in mbuf chain m contains a skeletal IP6 133 * header (with pri, len, nxt, hlim, src, dst). 134 * This function may modify ver and hlim only. 135 * The mbuf chain containing the packet will be freed. 136 * The mbuf opt, if present, will not be freed. 137 */ 138int 139ip6_output(m0, opt, ro, flags, im6o, ifpp) 140 struct mbuf *m0; 141 struct ip6_pktopts *opt; 142 struct route_in6 *ro; 143 int flags; 144 struct ip6_moptions *im6o; 145 struct ifnet **ifpp; /* XXX: just for statistics */ 146{ 147 struct ip6_hdr *ip6, *mhip6; | 128 129/* 130 * IP6 output. The packet in mbuf chain m contains a skeletal IP6 131 * header (with pri, len, nxt, hlim, src, dst). 132 * This function may modify ver and hlim only. 133 * The mbuf chain containing the packet will be freed. 134 * The mbuf opt, if present, will not be freed. 135 */ 136int 137ip6_output(m0, opt, ro, flags, im6o, ifpp) 138 struct mbuf *m0; 139 struct ip6_pktopts *opt; 140 struct route_in6 *ro; 141 int flags; 142 struct ip6_moptions *im6o; 143 struct ifnet **ifpp; /* XXX: just for statistics */ 144{ 145 struct ip6_hdr *ip6, *mhip6; |
148 struct ifnet *ifp; | 146 struct ifnet *ifp, *origifp; |
149 struct mbuf *m = m0; 150 int hlen, tlen, len, off; 151 struct route_in6 ip6route; 152 struct sockaddr_in6 *dst; 153 int error = 0; 154 struct in6_ifaddr *ia; 155 u_long mtu; 156 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0; 157 struct ip6_exthdrs exthdrs; 158 struct in6_addr finaldst; 159 struct route_in6 *ro_pmtu = NULL; 160 int hdrsplit = 0; 161 int needipsec = 0; 162#ifdef IPSEC 163 int needipsectun = 0; 164 struct socket *so; 165 struct secpolicy *sp = NULL; 166 167 /* for AH processing. stupid to have "socket" variable in IP layer... */ | 147 struct mbuf *m = m0; 148 int hlen, tlen, len, off; 149 struct route_in6 ip6route; 150 struct sockaddr_in6 *dst; 151 int error = 0; 152 struct in6_ifaddr *ia; 153 u_long mtu; 154 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0; 155 struct ip6_exthdrs exthdrs; 156 struct in6_addr finaldst; 157 struct route_in6 *ro_pmtu = NULL; 158 int hdrsplit = 0; 159 int needipsec = 0; 160#ifdef IPSEC 161 int needipsectun = 0; 162 struct socket *so; 163 struct secpolicy *sp = NULL; 164 165 /* for AH processing. stupid to have "socket" variable in IP layer... */ |
168 if ((flags & IPV6_SOCKINMRCVIF) != 0) { 169 so = (struct socket *)m->m_pkthdr.rcvif; 170 m->m_pkthdr.rcvif = NULL; 171 } else 172 so = NULL; | 166 so = ipsec_getsocket(m); 167 ipsec_setsocket(m, NULL); |
173 ip6 = mtod(m, struct ip6_hdr *); 174#endif /* IPSEC */ 175 | 168 ip6 = mtod(m, struct ip6_hdr *); 169#endif /* IPSEC */ 170 |
176#define MAKE_EXTHDR(hp,mp) \ 177 { \ | 171#define MAKE_EXTHDR(hp, mp) \ 172 do { \ |
178 if (hp) { \ 179 struct ip6_ext *eh = (struct ip6_ext *)(hp); \ 180 error = ip6_copyexthdr((mp), (caddr_t)(hp), \ 181 ((eh)->ip6e_len + 1) << 3); \ 182 if (error) \ 183 goto freehdrs; \ 184 } \ | 173 if (hp) { \ 174 struct ip6_ext *eh = (struct ip6_ext *)(hp); \ 175 error = ip6_copyexthdr((mp), (caddr_t)(hp), \ 176 ((eh)->ip6e_len + 1) << 3); \ 177 if (error) \ 178 goto freehdrs; \ 179 } \ |
185 } 186 | 180 } while (0) 181 |
187 bzero(&exthdrs, sizeof(exthdrs)); | 182 bzero(&exthdrs, sizeof(exthdrs)); |
183 |
|
188 if (opt) { 189 /* Hop-by-Hop options header */ 190 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh); 191 /* Destination options header(1st part) */ 192 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1); 193 /* Routing header */ 194 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr); 195 /* Destination options header(2nd part) */ --- 4 unchanged lines hidden (view full) --- 200 /* get a security policy for this packet */ 201 if (so == NULL) 202 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error); 203 else 204 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); 205 206 if (sp == NULL) { 207 ipsec6stat.out_inval++; | 184 if (opt) { 185 /* Hop-by-Hop options header */ 186 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh); 187 /* Destination options header(1st part) */ 188 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1); 189 /* Routing header */ 190 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr); 191 /* Destination options header(2nd part) */ --- 4 unchanged lines hidden (view full) --- 196 /* get a security policy for this packet */ 197 if (so == NULL) 198 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error); 199 else 200 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); 201 202 if (sp == NULL) { 203 ipsec6stat.out_inval++; |
208 goto bad; | 204 goto freehdrs; |
209 } 210 211 error = 0; 212 213 /* check policy */ 214 switch (sp->policy) { 215 case IPSEC_POLICY_DISCARD: 216 /* 217 * This packet is just discarded. 218 */ 219 ipsec6stat.out_polvio++; | 205 } 206 207 error = 0; 208 209 /* check policy */ 210 switch (sp->policy) { 211 case IPSEC_POLICY_DISCARD: 212 /* 213 * This packet is just discarded. 214 */ 215 ipsec6stat.out_polvio++; |
220 goto bad; | 216 goto freehdrs; |
221 222 case IPSEC_POLICY_BYPASS: 223 case IPSEC_POLICY_NONE: 224 /* no need to do IPsec. */ 225 needipsec = 0; 226 break; 227 228 case IPSEC_POLICY_IPSEC: 229 if (sp->req == NULL) { | 217 218 case IPSEC_POLICY_BYPASS: 219 case IPSEC_POLICY_NONE: 220 /* no need to do IPsec. */ 221 needipsec = 0; 222 break; 223 224 case IPSEC_POLICY_IPSEC: 225 if (sp->req == NULL) { |
230 /* XXX should be panic ? */ 231 printf("ip6_output: No IPsec request specified.\n"); 232 error = EINVAL; 233 goto bad; | 226 /* acquire a policy */ 227 error = key_spdacquire(sp); 228 goto freehdrs; |
234 } 235 needipsec = 1; 236 break; 237 238 case IPSEC_POLICY_ENTRUST: 239 default: 240 printf("ip6_output: Invalid policy found. %d\n", sp->policy); 241 } --- 74 unchanged lines hidden (view full) --- 316 if (!hdrsplit) 317 panic("assumption failed: hdr not split"); 318 exthdrs.ip6e_dest2->m_next = m->m_next; 319 m->m_next = exthdrs.ip6e_dest2; 320 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt; 321 ip6->ip6_nxt = IPPROTO_DSTOPTS; 322 } 323 | 229 } 230 needipsec = 1; 231 break; 232 233 case IPSEC_POLICY_ENTRUST: 234 default: 235 printf("ip6_output: Invalid policy found. %d\n", sp->policy); 236 } --- 74 unchanged lines hidden (view full) --- 311 if (!hdrsplit) 312 panic("assumption failed: hdr not split"); 313 exthdrs.ip6e_dest2->m_next = m->m_next; 314 m->m_next = exthdrs.ip6e_dest2; 315 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt; 316 ip6->ip6_nxt = IPPROTO_DSTOPTS; 317 } 318 |
324#define MAKE_CHAIN(m,mp,p,i)\ 325 {\ | 319#define MAKE_CHAIN(m, mp, p, i)\ 320 do {\ |
326 if (m) {\ 327 if (!hdrsplit) \ 328 panic("assumption failed: hdr not split"); \ 329 *mtod((m), u_char *) = *(p);\ 330 *(p) = (i);\ 331 p = mtod((m), u_char *);\ 332 (m)->m_next = (mp)->m_next;\ 333 (mp)->m_next = (m);\ 334 (mp) = (m);\ 335 }\ | 321 if (m) {\ 322 if (!hdrsplit) \ 323 panic("assumption failed: hdr not split"); \ 324 *mtod((m), u_char *) = *(p);\ 325 *(p) = (i);\ 326 p = mtod((m), u_char *);\ 327 (m)->m_next = (mp)->m_next;\ 328 (mp)->m_next = (m);\ 329 (mp) = (m);\ 330 }\ |
336 } | 331 } while (0) |
337 /* 338 * result: IPv6 hbh dest1 rthdr dest2 payload 339 * m will point to IPv6 header. mprev will point to the 340 * extension header prior to dest2 (rthdr in the above case). 341 */ 342 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, 343 nexthdrp, IPPROTO_HOPOPTS); 344 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, --- 120 unchanged lines hidden (view full) --- 465 RTFREE(ro->ro_rt); 466 ro->ro_rt = (struct rtentry *)0; 467 } 468 if (ro->ro_rt == 0) { 469 bzero(dst, sizeof(*dst)); 470 dst->sin6_family = AF_INET6; 471 dst->sin6_len = sizeof(struct sockaddr_in6); 472 dst->sin6_addr = ip6->ip6_dst; | 332 /* 333 * result: IPv6 hbh dest1 rthdr dest2 payload 334 * m will point to IPv6 header. mprev will point to the 335 * extension header prior to dest2 (rthdr in the above case). 336 */ 337 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, 338 nexthdrp, IPPROTO_HOPOPTS); 339 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, --- 120 unchanged lines hidden (view full) --- 460 RTFREE(ro->ro_rt); 461 ro->ro_rt = (struct rtentry *)0; 462 } 463 if (ro->ro_rt == 0) { 464 bzero(dst, sizeof(*dst)); 465 dst->sin6_family = AF_INET6; 466 dst->sin6_len = sizeof(struct sockaddr_in6); 467 dst->sin6_addr = ip6->ip6_dst; |
468#ifdef SCOPEDROUTING 469 /* XXX: sin6_scope_id should already be fixed at this point */ 470 if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr)) 471 dst->sin6_scope_id = ntohs(dst->sin6_addr.s6_addr16[1]); 472#endif |
|
473 } 474#ifdef IPSEC 475 if (needipsec && needipsectun) { 476 struct ipsec_output_state state; 477 478 /* 479 * All the extension headers will become inaccessible 480 * (since they can be encrypted). --- 34 unchanged lines hidden (view full) --- 515 error = 0; 516 break; 517 } 518 goto bad; 519 } 520 521 exthdrs.ip6e_ip6 = m; 522 } | 473 } 474#ifdef IPSEC 475 if (needipsec && needipsectun) { 476 struct ipsec_output_state state; 477 478 /* 479 * All the extension headers will become inaccessible 480 * (since they can be encrypted). --- 34 unchanged lines hidden (view full) --- 515 error = 0; 516 break; 517 } 518 goto bad; 519 } 520 521 exthdrs.ip6e_ip6 = m; 522 } |
523#endif /*IPESC*/ | 523#endif /*IPSEC*/ |
524 525 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 526 /* Unicast */ 527 528#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) 529#define sin6tosa(sin6) ((struct sockaddr *)(sin6)) 530 /* xxx 531 * interface selection comes here 532 * if an interface is specified from an upper layer, 533 * ifp must point it. 534 */ | 524 525 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 526 /* Unicast */ 527 528#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) 529#define sin6tosa(sin6) ((struct sockaddr *)(sin6)) 530 /* xxx 531 * interface selection comes here 532 * if an interface is specified from an upper layer, 533 * ifp must point it. 534 */ |
535 if (ro->ro_rt == 0) | 535 if (ro->ro_rt == 0) { 536 /* 537 * non-bsdi always clone routes, if parent is 538 * PRF_CLONING. 539 */ |
536 rtalloc((struct route *)ro); | 540 rtalloc((struct route *)ro); |
541 } |
|
537 if (ro->ro_rt == 0) { 538 ip6stat.ip6s_noroute++; 539 error = EHOSTUNREACH; 540 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */ 541 goto bad; 542 } 543 ia = ifatoia6(ro->ro_rt->rt_ifa); 544 ifp = ro->ro_rt->rt_ifp; 545 ro->ro_rt->rt_use++; 546 if (ro->ro_rt->rt_flags & RTF_GATEWAY) 547 dst = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway; 548 m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */ 549 550 in6_ifstat_inc(ifp, ifs6_out_request); 551 552 /* | 542 if (ro->ro_rt == 0) { 543 ip6stat.ip6s_noroute++; 544 error = EHOSTUNREACH; 545 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */ 546 goto bad; 547 } 548 ia = ifatoia6(ro->ro_rt->rt_ifa); 549 ifp = ro->ro_rt->rt_ifp; 550 ro->ro_rt->rt_use++; 551 if (ro->ro_rt->rt_flags & RTF_GATEWAY) 552 dst = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway; 553 m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */ 554 555 in6_ifstat_inc(ifp, ifs6_out_request); 556 557 /* |
553 * Check if there is the outgoing interface conflicts with 554 * the interface specified by ifi6_ifindex(if specified). | 558 * Check if the outgoing interface conflicts with 559 * the interface specified by ifi6_ifindex (if specified). |
555 * Note that loopback interface is always okay. | 560 * Note that loopback interface is always okay. |
556 * (this happens when we are sending packet toward my 557 * interface) | 561 * (this may happen when we are sending a packet to one of 562 * our own addresses.) |
558 */ 559 if (opt && opt->ip6po_pktinfo 560 && opt->ip6po_pktinfo->ipi6_ifindex) { 561 if (!(ifp->if_flags & IFF_LOOPBACK) 562 && ifp->if_index != opt->ip6po_pktinfo->ipi6_ifindex) { 563 ip6stat.ip6s_noroute++; 564 in6_ifstat_inc(ifp, ifs6_out_discard); 565 error = EHOSTUNREACH; --- 105 unchanged lines hidden (view full) --- 671 * recursively calls this function, using the 672 * IPV6_FORWARDING flag to prevent infinite recursion. 673 * 674 * Multicasts that are looped back by ip6_mloopback(), 675 * above, will be forwarded by the ip6_input() routine, 676 * if necessary. 677 */ 678 if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) { | 563 */ 564 if (opt && opt->ip6po_pktinfo 565 && opt->ip6po_pktinfo->ipi6_ifindex) { 566 if (!(ifp->if_flags & IFF_LOOPBACK) 567 && ifp->if_index != opt->ip6po_pktinfo->ipi6_ifindex) { 568 ip6stat.ip6s_noroute++; 569 in6_ifstat_inc(ifp, ifs6_out_discard); 570 error = EHOSTUNREACH; --- 105 unchanged lines hidden (view full) --- 676 * recursively calls this function, using the 677 * IPV6_FORWARDING flag to prevent infinite recursion. 678 * 679 * Multicasts that are looped back by ip6_mloopback(), 680 * above, will be forwarded by the ip6_input() routine, 681 * if necessary. 682 */ 683 if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) { |
679 if (ip6_mforward(ip6, ifp, m) != NULL) { | 684 if (ip6_mforward(ip6, ifp, m) != 0) { |
680 m_freem(m); 681 goto done; 682 } 683 } 684 } 685 /* 686 * Multicasts with a hoplimit of zero may be looped back, 687 * above, but must not be transmitted on a network. --- 53 unchanged lines hidden (view full) --- 741 mtu = ifmtu; 742 if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0) 743 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */ 744 } 745 } else { 746 mtu = nd_ifinfo[ifp->if_index].linkmtu; 747 } 748 | 685 m_freem(m); 686 goto done; 687 } 688 } 689 } 690 /* 691 * Multicasts with a hoplimit of zero may be looped back, 692 * above, but must not be transmitted on a network. --- 53 unchanged lines hidden (view full) --- 746 mtu = ifmtu; 747 if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0) 748 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */ 749 } 750 } else { 751 mtu = nd_ifinfo[ifp->if_index].linkmtu; 752 } 753 |
749 /* 750 * Fake link-local scope-class addresses 751 */ 752 if ((ifp->if_flags & IFF_LOOPBACK) == 0) { | 754 /* Fake scoped addresses */ 755 if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 756 /* 757 * If source or destination address is a scoped address, and 758 * the packet is going to be sent to a loopback interface, 759 * we should keep the original interface. 760 */ 761 762 /* 763 * XXX: this is a very experimental and temporary solution. 764 * We eventually have sockaddr_in6 and use the sin6_scope_id 765 * field of the structure here. 766 * We rely on the consistency between two scope zone ids 767 * of source add destination, which should already be assured 768 * Larger scopes than link will be supported in the near 769 * future. 770 */ |
753 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) | 771 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) |
772 origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])]; 773 else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 774 origifp = ifindex2ifnet[ntohs(ip6->ip6_dst.s6_addr16[1])]; 775 else 776 origifp = ifp; 777 } 778 else 779 origifp = ifp; 780#ifndef FAKE_LOOPBACK_IF 781 if ((ifp->if_flags & IFF_LOOPBACK) == 0) 782#else 783 if (1) 784#endif 785 { 786 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) |
|
754 ip6->ip6_src.s6_addr16[1] = 0; 755 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 756 ip6->ip6_dst.s6_addr16[1] = 0; 757 } 758 759#ifdef IPV6FIREWALL 760 /* 761 * Check with the firewall... 762 */ 763 if (ip6_fw_chk_ptr) { 764 u_short port = 0; | 787 ip6->ip6_src.s6_addr16[1] = 0; 788 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 789 ip6->ip6_dst.s6_addr16[1] = 0; 790 } 791 792#ifdef IPV6FIREWALL 793 /* 794 * Check with the firewall... 795 */ 796 if (ip6_fw_chk_ptr) { 797 u_short port = 0; |
798 m->m_pkthdr.rcvif = NULL; /*XXX*/ |
|
765 /* If ipfw says divert, we have to just drop packet */ 766 if ((*ip6_fw_chk_ptr)(&ip6, ifp, &port, &m)) { 767 m_freem(m); 768 goto done; 769 } 770 if (!m) { 771 error = EACCES; 772 goto done; --- 49 unchanged lines hidden (view full) --- 822 * larger than the link's MTU. 823 * XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet... 824 */ 825 826 || ifp->if_flags & IFF_FRAGMENTABLE 827#endif 828 ) 829 { | 799 /* If ipfw says divert, we have to just drop packet */ 800 if ((*ip6_fw_chk_ptr)(&ip6, ifp, &port, &m)) { 801 m_freem(m); 802 goto done; 803 } 804 if (!m) { 805 error = EACCES; 806 goto done; --- 49 unchanged lines hidden (view full) --- 856 * larger than the link's MTU. 857 * XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet... 858 */ 859 860 || ifp->if_flags & IFF_FRAGMENTABLE 861#endif 862 ) 863 { |
830#if defined(__NetBSD__) && defined(IFA_STATS) 831 if (IFA_STATS) { 832 struct in6_ifaddr *ia6; 833 ip6 = mtod(m, struct ip6_hdr *); 834 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src); 835 if (ia6) { 836 ia->ia_ifa.ifa_data.ifad_outbytes += 837 m->m_pkthdr.len; 838 } 839 } 840#endif 841 error = nd6_output(ifp, m, dst, ro->ro_rt); | 864 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); |
842 goto done; 843 } else if (mtu < IPV6_MMTU) { 844 /* 845 * note that path MTU is never less than IPV6_MMTU 846 * (see icmp6_input). 847 */ 848 error = EMSGSIZE; 849 in6_ifstat_inc(ifp, ifs6_out_fragfail); --- 99 unchanged lines hidden (view full) --- 949sendorfree: 950 m = m0->m_nextpkt; 951 m0->m_nextpkt = 0; 952 m_freem(m0); 953 for (m0 = m; m; m = m0) { 954 m0 = m->m_nextpkt; 955 m->m_nextpkt = 0; 956 if (error == 0) { | 865 goto done; 866 } else if (mtu < IPV6_MMTU) { 867 /* 868 * note that path MTU is never less than IPV6_MMTU 869 * (see icmp6_input). 870 */ 871 error = EMSGSIZE; 872 in6_ifstat_inc(ifp, ifs6_out_fragfail); --- 99 unchanged lines hidden (view full) --- 972sendorfree: 973 m = m0->m_nextpkt; 974 m0->m_nextpkt = 0; 975 m_freem(m0); 976 for (m0 = m; m; m = m0) { 977 m0 = m->m_nextpkt; 978 m->m_nextpkt = 0; 979 if (error == 0) { |
957#if defined(__NetBSD__) && defined(IFA_STATS) 958 if (IFA_STATS) { 959 struct in6_ifaddr *ia6; 960 ip6 = mtod(m, struct ip6_hdr *); 961 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src); 962 if (ia6) { 963 ia->ia_ifa.ifa_data.ifad_outbytes += 964 m->m_pkthdr.len; 965 } 966 } 967#endif 968 error = nd6_output(ifp, m, dst, ro->ro_rt); | 980 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); |
969 } else 970 m_freem(m); 971 } 972 973 if (error == 0) 974 ip6stat.ip6s_fragmented++; 975 976done: --- 142 unchanged lines hidden (view full) --- 1119 } else 1120 n = m; 1121 1122 /* Search for the last mbuf of unfragmentable part. */ 1123 for (mlast = n; mlast->m_next; mlast = mlast->m_next) 1124 ; 1125 1126 if ((mlast->m_flags & M_EXT) == 0 && | 981 } else 982 m_freem(m); 983 } 984 985 if (error == 0) 986 ip6stat.ip6s_fragmented++; 987 988done: --- 142 unchanged lines hidden (view full) --- 1131 } else 1132 n = m; 1133 1134 /* Search for the last mbuf of unfragmentable part. */ 1135 for (mlast = n; mlast->m_next; mlast = mlast->m_next) 1136 ; 1137 1138 if ((mlast->m_flags & M_EXT) == 0 && |
1127 M_TRAILINGSPACE(mlast) < sizeof(struct ip6_frag)) { | 1139 M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) { |
1128 /* use the trailing space of the last mbuf for the fragment hdr */ 1129 *frghdrp = 1130 (struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len); 1131 mlast->m_len += sizeof(struct ip6_frag); 1132 m->m_pkthdr.len += sizeof(struct ip6_frag); 1133 } else { 1134 /* allocate a new mbuf for the fragment header */ 1135 struct mbuf *mfrg; --- 57 unchanged lines hidden (view full) --- 1193 case IPV6_HOPOPTS: 1194 case IPV6_DSTOPTS: 1195 if (!privileged) { 1196 error = EPERM; 1197 break; 1198 } 1199 /* fall through */ 1200 case IPV6_UNICAST_HOPS: | 1140 /* use the trailing space of the last mbuf for the fragment hdr */ 1141 *frghdrp = 1142 (struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len); 1143 mlast->m_len += sizeof(struct ip6_frag); 1144 m->m_pkthdr.len += sizeof(struct ip6_frag); 1145 } else { 1146 /* allocate a new mbuf for the fragment header */ 1147 struct mbuf *mfrg; --- 57 unchanged lines hidden (view full) --- 1205 case IPV6_HOPOPTS: 1206 case IPV6_DSTOPTS: 1207 if (!privileged) { 1208 error = EPERM; 1209 break; 1210 } 1211 /* fall through */ 1212 case IPV6_UNICAST_HOPS: |
1201 case IPV6_RECVOPTS: 1202 case IPV6_RECVRETOPTS: 1203 case IPV6_RECVDSTADDR: | |
1204 case IPV6_PKTINFO: 1205 case IPV6_HOPLIMIT: 1206 case IPV6_RTHDR: 1207 case IPV6_CHECKSUM: 1208 case IPV6_FAITH: 1209 case IPV6_BINDV6ONLY: 1210 if (optlen != sizeof(int)) 1211 error = EINVAL; --- 16 unchanged lines hidden (view full) --- 1228 } 1229 break; 1230#define OPTSET(bit) \ 1231 if (optval) \ 1232 in6p->in6p_flags |= bit; \ 1233 else \ 1234 in6p->in6p_flags &= ~bit; 1235 | 1213 case IPV6_PKTINFO: 1214 case IPV6_HOPLIMIT: 1215 case IPV6_RTHDR: 1216 case IPV6_CHECKSUM: 1217 case IPV6_FAITH: 1218 case IPV6_BINDV6ONLY: 1219 if (optlen != sizeof(int)) 1220 error = EINVAL; --- 16 unchanged lines hidden (view full) --- 1237 } 1238 break; 1239#define OPTSET(bit) \ 1240 if (optval) \ 1241 in6p->in6p_flags |= bit; \ 1242 else \ 1243 in6p->in6p_flags &= ~bit; 1244 |
1236 case IPV6_RECVOPTS: 1237 OPTSET(IN6P_RECVOPTS); 1238 break; 1239 1240 case IPV6_RECVRETOPTS: 1241 OPTSET(IN6P_RECVRETOPTS); 1242 break; 1243 1244 case IPV6_RECVDSTADDR: 1245 OPTSET(IN6P_RECVDSTADDR); 1246 break; 1247 | |
1248 case IPV6_PKTINFO: 1249 OPTSET(IN6P_PKTINFO); 1250 break; 1251 1252 case IPV6_HOPLIMIT: 1253 OPTSET(IN6P_HOPLIMIT); 1254 break; 1255 --- 47 unchanged lines hidden (view full) --- 1303 m->m_len, m->m_len); 1304 error = ip6_setmoptions(sopt->sopt_name, 1305 &in6p->in6p_moptions, 1306 m); 1307 (void)m_free(m); 1308 } 1309 break; 1310 | 1245 case IPV6_PKTINFO: 1246 OPTSET(IN6P_PKTINFO); 1247 break; 1248 1249 case IPV6_HOPLIMIT: 1250 OPTSET(IN6P_HOPLIMIT); 1251 break; 1252 --- 47 unchanged lines hidden (view full) --- 1300 m->m_len, m->m_len); 1301 error = ip6_setmoptions(sopt->sopt_name, 1302 &in6p->in6p_moptions, 1303 m); 1304 (void)m_free(m); 1305 } 1306 break; 1307 |
1311 case IPV6_PORTRANGE: 1312 error = sooptcopyin(sopt, &optval, sizeof optval, 1313 sizeof optval); 1314 if (error) 1315 break; | 1308 case IPV6_PORTRANGE: 1309 error = sooptcopyin(sopt, &optval, 1310 sizeof optval, sizeof optval); 1311 if (error) 1312 break; |
1316 | 1313 |
1317 switch (optval) { 1318 case IPV6_PORTRANGE_DEFAULT: 1319 in6p->in6p_flags &= ~(IN6P_LOWPORT); 1320 in6p->in6p_flags &= ~(IN6P_HIGHPORT); 1321 break; | 1314 switch (optval) { 1315 case IPV6_PORTRANGE_DEFAULT: 1316 in6p->in6p_flags &= ~(IN6P_LOWPORT); 1317 in6p->in6p_flags &= ~(IN6P_HIGHPORT); 1318 break; |
1322 | 1319 |
1323 case IPV6_PORTRANGE_HIGH: 1324 in6p->in6p_flags &= ~(IN6P_LOWPORT); 1325 in6p->in6p_flags |= IN6P_HIGHPORT; 1326 break; | 1320 case IPV6_PORTRANGE_HIGH: 1321 in6p->in6p_flags &= ~(IN6P_LOWPORT); 1322 in6p->in6p_flags |= IN6P_HIGHPORT; 1323 break; |
1327 | 1324 |
1328 case IPV6_PORTRANGE_LOW: 1329 in6p->in6p_flags &= ~(IN6P_HIGHPORT); 1330 in6p->in6p_flags |= IN6P_LOWPORT; 1331 break; | 1325 case IPV6_PORTRANGE_LOW: 1326 in6p->in6p_flags &= ~(IN6P_HIGHPORT); 1327 in6p->in6p_flags |= IN6P_LOWPORT; 1328 break; |
1332 | 1329 |
1333 default: 1334 error = EINVAL; | 1330 default: 1331 error = EINVAL; 1332 break; 1333 } |
1335 break; | 1334 break; |
1336 } 1337 break; | |
1338 1339#ifdef IPSEC 1340 case IPV6_IPSEC_POLICY: 1341 { 1342 caddr_t req = NULL; | 1335 1336#ifdef IPSEC 1337 case IPV6_IPSEC_POLICY: 1338 { 1339 caddr_t req = NULL; |
1340 size_t len = 0; |
|
1343 struct mbuf *m; 1344 | 1341 struct mbuf *m; 1342 |
1345 if ((error = soopt_getm(sopt, &m)) 1346 != 0) /* XXX */ | 1343 if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */ |
1347 break; | 1344 break; |
1348 if ((error = soopt_mcopyin(sopt, m)) 1349 != 0) /* XXX */ | 1345 if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */ |
1350 break; | 1346 break; |
1351 if (m != 0) | 1347 if (m) { |
1352 req = mtod(m, caddr_t); | 1348 req = mtod(m, caddr_t); |
1349 len = m->m_len; 1350 } |
|
1353 error = ipsec6_set_policy(in6p, optname, req, | 1351 error = ipsec6_set_policy(in6p, optname, req, |
1354 privileged); | 1352 len, privileged); |
1355 m_freem(m); 1356 } 1357 break; 1358#endif /* IPSEC */ 1359 1360#ifdef IPV6FIREWALL 1361 case IPV6_FW_ADD: 1362 case IPV6_FW_DEL: --- 21 unchanged lines hidden (view full) --- 1384 error = ENOPROTOOPT; 1385 break; 1386 } 1387 break; 1388 1389 case SOPT_GET: 1390 switch (optname) { 1391 | 1353 m_freem(m); 1354 } 1355 break; 1356#endif /* IPSEC */ 1357 1358#ifdef IPV6FIREWALL 1359 case IPV6_FW_ADD: 1360 case IPV6_FW_DEL: --- 21 unchanged lines hidden (view full) --- 1382 error = ENOPROTOOPT; 1383 break; 1384 } 1385 break; 1386 1387 case SOPT_GET: 1388 switch (optname) { 1389 |
1392 case IPV6_OPTIONS: 1393 case IPV6_RETOPTS: 1394 error = ENOPROTOOPT; 1395 break; 1396 | |
1397 case IPV6_PKTOPTIONS: 1398 if (in6p->in6p_options) { 1399 error = soopt_mcopyout(sopt, 1400 in6p->in6p_options); 1401 } else 1402 sopt->sopt_valsize = 0; 1403 break; 1404 1405 case IPV6_HOPOPTS: 1406 case IPV6_DSTOPTS: 1407 if (!privileged) { 1408 error = EPERM; 1409 break; 1410 } 1411 /* fall through */ 1412 case IPV6_UNICAST_HOPS: | 1390 case IPV6_PKTOPTIONS: 1391 if (in6p->in6p_options) { 1392 error = soopt_mcopyout(sopt, 1393 in6p->in6p_options); 1394 } else 1395 sopt->sopt_valsize = 0; 1396 break; 1397 1398 case IPV6_HOPOPTS: 1399 case IPV6_DSTOPTS: 1400 if (!privileged) { 1401 error = EPERM; 1402 break; 1403 } 1404 /* fall through */ 1405 case IPV6_UNICAST_HOPS: |
1413 case IPV6_RECVOPTS: 1414 case IPV6_RECVRETOPTS: 1415 case IPV6_RECVDSTADDR: | |
1416 case IPV6_PKTINFO: 1417 case IPV6_HOPLIMIT: 1418 case IPV6_RTHDR: 1419 case IPV6_CHECKSUM: 1420 case IPV6_FAITH: 1421 case IPV6_BINDV6ONLY: 1422 case IPV6_PORTRANGE: 1423 switch (optname) { 1424 1425 case IPV6_UNICAST_HOPS: 1426 optval = in6p->in6p_hops; 1427 break; 1428 1429#define OPTBIT(bit) (in6p->in6p_flags & bit ? 1 : 0) 1430 | 1406 case IPV6_PKTINFO: 1407 case IPV6_HOPLIMIT: 1408 case IPV6_RTHDR: 1409 case IPV6_CHECKSUM: 1410 case IPV6_FAITH: 1411 case IPV6_BINDV6ONLY: 1412 case IPV6_PORTRANGE: 1413 switch (optname) { 1414 1415 case IPV6_UNICAST_HOPS: 1416 optval = in6p->in6p_hops; 1417 break; 1418 1419#define OPTBIT(bit) (in6p->in6p_flags & bit ? 1 : 0) 1420 |
1431 case IPV6_RECVOPTS: 1432 optval = OPTBIT(IN6P_RECVOPTS); 1433 break; 1434 1435 case IPV6_RECVRETOPTS: 1436 optval = OPTBIT(IN6P_RECVRETOPTS); 1437 break; 1438 1439 case IPV6_RECVDSTADDR: 1440 optval = OPTBIT(IN6P_RECVDSTADDR); 1441 break; 1442 | |
1443 case IPV6_PKTINFO: 1444 optval = OPTBIT(IN6P_PKTINFO); 1445 break; 1446 1447 case IPV6_HOPLIMIT: 1448 optval = OPTBIT(IN6P_HOPLIMIT); 1449 break; 1450 --- 53 unchanged lines hidden (view full) --- 1504 mtod(m, char *), m->m_len); 1505 m_freem(m); 1506 } 1507 break; 1508 1509#ifdef IPSEC 1510 case IPV6_IPSEC_POLICY: 1511 { | 1421 case IPV6_PKTINFO: 1422 optval = OPTBIT(IN6P_PKTINFO); 1423 break; 1424 1425 case IPV6_HOPLIMIT: 1426 optval = OPTBIT(IN6P_HOPLIMIT); 1427 break; 1428 --- 53 unchanged lines hidden (view full) --- 1482 mtod(m, char *), m->m_len); 1483 m_freem(m); 1484 } 1485 break; 1486 1487#ifdef IPSEC 1488 case IPV6_IPSEC_POLICY: 1489 { |
1512 1513 struct mbuf *m = NULL; | |
1514 caddr_t req = NULL; | 1490 caddr_t req = NULL; |
1491 size_t len = 0; 1492 struct mbuf *m = NULL; 1493 struct mbuf **mp = &m; |
|
1515 | 1494 |
1516 if (m != 0) | 1495 error = soopt_getm(sopt, &m); /* XXX */ 1496 if (error != NULL) 1497 break; 1498 error = soopt_mcopyin(sopt, m); /* XXX */ 1499 if (error != NULL) 1500 break; 1501 if (m) { |
1517 req = mtod(m, caddr_t); | 1502 req = mtod(m, caddr_t); |
1518 error = ipsec6_get_policy(in6p, req, &m); | 1503 len = m->m_len; 1504 } 1505 error = ipsec6_get_policy(in6p, req, len, mp); |
1519 if (error == 0) 1520 error = soopt_mcopyout(sopt, m); /*XXX*/ | 1506 if (error == 0) 1507 error = soopt_mcopyout(sopt, m); /*XXX*/ |
1521 if (error == 0) 1522 m_freem(m); | 1508 m_freem(m); |
1523 break; 1524 } 1525#endif /* IPSEC */ 1526 1527#ifdef IPV6FIREWALL 1528 case IPV6_FW_GET: 1529 { 1530 struct mbuf *m; --- 174 unchanged lines hidden (view full) --- 1705 } 1706 mreq = mtod(m, struct ipv6_mreq *); 1707 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) { 1708 /* 1709 * We use the unspecified address to specify to accept 1710 * all multicast addresses. Only super user is allowed 1711 * to do this. 1712 */ | 1509 break; 1510 } 1511#endif /* IPSEC */ 1512 1513#ifdef IPV6FIREWALL 1514 case IPV6_FW_GET: 1515 { 1516 struct mbuf *m; --- 174 unchanged lines hidden (view full) --- 1691 } 1692 mreq = mtod(m, struct ipv6_mreq *); 1693 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) { 1694 /* 1695 * We use the unspecified address to specify to accept 1696 * all multicast addresses. Only super user is allowed 1697 * to do this. 1698 */ |
1713 if (suser(p)) { | 1699 if (suser(p)) 1700 { |
1714 error = EACCES; 1715 break; 1716 } 1717 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) { 1718 error = EINVAL; 1719 break; 1720 } 1721 --- 51 unchanged lines hidden (view full) --- 1773 */ 1774 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) { 1775 mreq->ipv6mr_multiaddr.s6_addr16[1] 1776 = htons(mreq->ipv6mr_interface); 1777 } 1778 /* 1779 * See if the membership already exists. 1780 */ | 1701 error = EACCES; 1702 break; 1703 } 1704 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) { 1705 error = EINVAL; 1706 break; 1707 } 1708 --- 51 unchanged lines hidden (view full) --- 1760 */ 1761 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) { 1762 mreq->ipv6mr_multiaddr.s6_addr16[1] 1763 = htons(mreq->ipv6mr_interface); 1764 } 1765 /* 1766 * See if the membership already exists. 1767 */ |
1781 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) | 1768 for (imm = im6o->im6o_memberships.lh_first; 1769 imm != NULL; imm = imm->i6mm_chain.le_next) |
1782 if (imm->i6mm_maddr->in6m_ifp == ifp && 1783 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, 1784 &mreq->ipv6mr_multiaddr)) 1785 break; 1786 if (imm != NULL) { 1787 error = EADDRINUSE; 1788 break; 1789 } --- 49 unchanged lines hidden (view full) --- 1839 */ 1840 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) { 1841 mreq->ipv6mr_multiaddr.s6_addr16[1] 1842 = htons(mreq->ipv6mr_interface); 1843 } 1844 /* 1845 * Find the membership in the membership list. 1846 */ | 1770 if (imm->i6mm_maddr->in6m_ifp == ifp && 1771 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, 1772 &mreq->ipv6mr_multiaddr)) 1773 break; 1774 if (imm != NULL) { 1775 error = EADDRINUSE; 1776 break; 1777 } --- 49 unchanged lines hidden (view full) --- 1827 */ 1828 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) { 1829 mreq->ipv6mr_multiaddr.s6_addr16[1] 1830 = htons(mreq->ipv6mr_interface); 1831 } 1832 /* 1833 * Find the membership in the membership list. 1834 */ |
1847 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) { | 1835 for (imm = im6o->im6o_memberships.lh_first; 1836 imm != NULL; imm = imm->i6mm_chain.le_next) { |
1848 if ((ifp == NULL || 1849 imm->i6mm_maddr->in6m_ifp == ifp) && 1850 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, 1851 &mreq->ipv6mr_multiaddr)) 1852 break; 1853 } 1854 if (imm == NULL) { 1855 /* Unable to resolve interface */ --- 15 unchanged lines hidden (view full) --- 1871 } 1872 1873 /* 1874 * If all options have default values, no need to keep the mbuf. 1875 */ 1876 if (im6o->im6o_multicast_ifp == NULL && 1877 im6o->im6o_multicast_hlim == ip6_defmcasthlim && 1878 im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP && | 1837 if ((ifp == NULL || 1838 imm->i6mm_maddr->in6m_ifp == ifp) && 1839 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr, 1840 &mreq->ipv6mr_multiaddr)) 1841 break; 1842 } 1843 if (imm == NULL) { 1844 /* Unable to resolve interface */ --- 15 unchanged lines hidden (view full) --- 1860 } 1861 1862 /* 1863 * If all options have default values, no need to keep the mbuf. 1864 */ 1865 if (im6o->im6o_multicast_ifp == NULL && 1866 im6o->im6o_multicast_hlim == ip6_defmcasthlim && 1867 im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP && |
1879 LIST_EMPTY(&im6o->im6o_memberships)) { | 1868 im6o->im6o_memberships.lh_first == NULL) { |
1880 free(*im6op, M_IPMOPTS); 1881 *im6op = NULL; 1882 } 1883 1884 return(error); 1885} 1886 1887/* --- 50 unchanged lines hidden (view full) --- 1938ip6_freemoptions(im6o) 1939 register struct ip6_moptions *im6o; 1940{ 1941 struct in6_multi_mship *imm; 1942 1943 if (im6o == NULL) 1944 return; 1945 | 1869 free(*im6op, M_IPMOPTS); 1870 *im6op = NULL; 1871 } 1872 1873 return(error); 1874} 1875 1876/* --- 50 unchanged lines hidden (view full) --- 1927ip6_freemoptions(im6o) 1928 register struct ip6_moptions *im6o; 1929{ 1930 struct in6_multi_mship *imm; 1931 1932 if (im6o == NULL) 1933 return; 1934 |
1946 while ((imm = LIST_FIRST(&im6o->im6o_memberships)) != NULL) { | 1935 while ((imm = im6o->im6o_memberships.lh_first) != NULL) { |
1947 LIST_REMOVE(imm, i6mm_chain); 1948 if (imm->i6mm_maddr) 1949 in6_delmulti(imm->i6mm_maddr); 1950 free(imm, M_IPMADDR); 1951 } 1952 free(im6o, M_IPMOPTS); 1953} 1954 --- 16 unchanged lines hidden (view full) --- 1971 1972 /* 1973 * XXX: Currently, we assume all the optional information is stored 1974 * in a single mbuf. 1975 */ 1976 if (control->m_next) 1977 return(EINVAL); 1978 | 1936 LIST_REMOVE(imm, i6mm_chain); 1937 if (imm->i6mm_maddr) 1938 in6_delmulti(imm->i6mm_maddr); 1939 free(imm, M_IPMADDR); 1940 } 1941 free(im6o, M_IPMOPTS); 1942} 1943 --- 16 unchanged lines hidden (view full) --- 1960 1961 /* 1962 * XXX: Currently, we assume all the optional information is stored 1963 * in a single mbuf. 1964 */ 1965 if (control->m_next) 1966 return(EINVAL); 1967 |
1979 opt->ip6po_m = control; 1980 | |
1981 for (; control->m_len; control->m_data += ALIGN(cm->cmsg_len), 1982 control->m_len -= ALIGN(cm->cmsg_len)) { 1983 cm = mtod(control, struct cmsghdr *); 1984 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len) 1985 return(EINVAL); 1986 if (cm->cmsg_level != IPPROTO_IPV6) 1987 continue; 1988 --- 126 unchanged lines hidden (view full) --- 2115 * pointer that might NOT be &loif -- easier than replicating that code here. 2116 */ 2117void 2118ip6_mloopback(ifp, m, dst) 2119 struct ifnet *ifp; 2120 register struct mbuf *m; 2121 register struct sockaddr_in6 *dst; 2122{ | 1968 for (; control->m_len; control->m_data += ALIGN(cm->cmsg_len), 1969 control->m_len -= ALIGN(cm->cmsg_len)) { 1970 cm = mtod(control, struct cmsghdr *); 1971 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len) 1972 return(EINVAL); 1973 if (cm->cmsg_level != IPPROTO_IPV6) 1974 continue; 1975 --- 126 unchanged lines hidden (view full) --- 2102 * pointer that might NOT be &loif -- easier than replicating that code here. 2103 */ 2104void 2105ip6_mloopback(ifp, m, dst) 2106 struct ifnet *ifp; 2107 register struct mbuf *m; 2108 register struct sockaddr_in6 *dst; 2109{ |
2123 struct mbuf *copym; | 2110 struct mbuf *copym; 2111 struct ip6_hdr *ip6; |
2124 2125 copym = m_copy(m, 0, M_COPYALL); | 2112 2113 copym = m_copy(m, 0, M_COPYALL); |
2126 if (copym != NULL) { 2127 (void)if_simloop(ifp, copym, dst->sin6_family, 0); | 2114 if (copym == NULL) 2115 return; 2116 2117 /* 2118 * Make sure to deep-copy IPv6 header portion in case the data 2119 * is in an mbuf cluster, so that we can safely override the IPv6 2120 * header portion later. 2121 */ 2122 if ((copym->m_flags & M_EXT) != 0 || 2123 copym->m_len < sizeof(struct ip6_hdr)) { 2124 copym = m_pullup(copym, sizeof(struct ip6_hdr)); 2125 if (copym == NULL) 2126 return; |
2128 } | 2127 } |
2128 2129#ifdef DIAGNOSTIC 2130 if (copym->m_len < sizeof(*ip6)) { 2131 m_freem(copym); 2132 return; 2133 } 2134#endif 2135 2136#ifndef FAKE_LOOPBACK_IF 2137 if ((ifp->if_flags & IFF_LOOPBACK) == 0) 2138#else 2139 if (1) 2140#endif 2141 { 2142 ip6 = mtod(copym, struct ip6_hdr *); 2143 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 2144 ip6->ip6_src.s6_addr16[1] = 0; 2145 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 2146 ip6->ip6_dst.s6_addr16[1] = 0; 2147 } 2148 2149 (void)if_simloop(ifp, copym, dst->sin6_family, NULL); |
|
2129} 2130 2131/* 2132 * Chop IPv6 header off from the payload. 2133 */ 2134static int 2135ip6_splithdr(m, exthdrs) 2136 struct mbuf *m; --- 50 unchanged lines hidden --- | 2150} 2151 2152/* 2153 * Chop IPv6 header off from the payload. 2154 */ 2155static int 2156ip6_splithdr(m, exthdrs) 2157 struct mbuf *m; --- 50 unchanged lines hidden --- |