raw_ip6.c (180990) | raw_ip6.c (181803) |
---|---|
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 --- 46 unchanged lines hidden (view full) --- 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 60 */ 61 62#include <sys/cdefs.h> | 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 --- 46 unchanged lines hidden (view full) --- 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 60 */ 61 62#include <sys/cdefs.h> |
63__FBSDID("$FreeBSD: head/sys/netinet6/raw_ip6.c 180990 2008-07-30 09:26:27Z rwatson $"); | 63__FBSDID("$FreeBSD: head/sys/netinet6/raw_ip6.c 181803 2008-08-17 23:27:27Z bz $"); |
64 65#include "opt_ipsec.h" 66#include "opt_inet6.h" 67 68#include <sys/param.h> 69#include <sys/errno.h> 70#include <sys/lock.h> 71#include <sys/malloc.h> 72#include <sys/mbuf.h> 73#include <sys/priv.h> 74#include <sys/proc.h> 75#include <sys/protosw.h> 76#include <sys/signalvar.h> 77#include <sys/socket.h> 78#include <sys/socketvar.h> 79#include <sys/sx.h> 80#include <sys/syslog.h> | 64 65#include "opt_ipsec.h" 66#include "opt_inet6.h" 67 68#include <sys/param.h> 69#include <sys/errno.h> 70#include <sys/lock.h> 71#include <sys/malloc.h> 72#include <sys/mbuf.h> 73#include <sys/priv.h> 74#include <sys/proc.h> 75#include <sys/protosw.h> 76#include <sys/signalvar.h> 77#include <sys/socket.h> 78#include <sys/socketvar.h> 79#include <sys/sx.h> 80#include <sys/syslog.h> |
81#include <sys/vimage.h> |
|
81 82#include <net/if.h> 83#include <net/if_types.h> 84#include <net/route.h> 85 86#include <netinet/in.h> 87#include <netinet/in_var.h> 88#include <netinet/in_systm.h> --- 48 unchanged lines hidden (view full) --- 137{ 138 struct mbuf *m = *mp; 139 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 140 register struct inpcb *in6p; 141 struct inpcb *last = 0; 142 struct mbuf *opts = NULL; 143 struct sockaddr_in6 fromsa; 144 | 82 83#include <net/if.h> 84#include <net/if_types.h> 85#include <net/route.h> 86 87#include <netinet/in.h> 88#include <netinet/in_var.h> 89#include <netinet/in_systm.h> --- 48 unchanged lines hidden (view full) --- 138{ 139 struct mbuf *m = *mp; 140 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 141 register struct inpcb *in6p; 142 struct inpcb *last = 0; 143 struct mbuf *opts = NULL; 144 struct sockaddr_in6 fromsa; 145 |
145 rip6stat.rip6s_ipackets++; | 146 V_rip6stat.rip6s_ipackets++; |
146 147 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { 148 /* XXX Send icmp6 host/port unreach? */ 149 m_freem(m); 150 return (IPPROTO_DONE); 151 } 152 153 init_sin6(&fromsa, m); /* general init */ 154 | 147 148 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { 149 /* XXX Send icmp6 host/port unreach? */ 150 m_freem(m); 151 return (IPPROTO_DONE); 152 } 153 154 init_sin6(&fromsa, m); /* general init */ 155 |
155 INP_INFO_RLOCK(&ripcbinfo); 156 LIST_FOREACH(in6p, &ripcb, inp_list) { | 156 INP_INFO_RLOCK(&V_ripcbinfo); 157 LIST_FOREACH(in6p, &V_ripcb, inp_list) { |
157 if ((in6p->in6p_vflag & INP_IPV6) == 0) 158 continue; 159 if (in6p->in6p_ip6_nxt && 160 in6p->in6p_ip6_nxt != proto) 161 continue; 162 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 163 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 164 continue; 165 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 166 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 167 continue; 168 INP_RLOCK(in6p); 169 if (in6p->in6p_cksum != -1) { | 158 if ((in6p->in6p_vflag & INP_IPV6) == 0) 159 continue; 160 if (in6p->in6p_ip6_nxt && 161 in6p->in6p_ip6_nxt != proto) 162 continue; 163 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 164 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 165 continue; 166 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 167 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 168 continue; 169 INP_RLOCK(in6p); 170 if (in6p->in6p_cksum != -1) { |
170 rip6stat.rip6s_isum++; | 171 V_rip6stat.rip6s_isum++; |
171 if (in6_cksum(m, proto, *offp, 172 m->m_pkthdr.len - *offp)) { 173 INP_RUNLOCK(in6p); | 172 if (in6_cksum(m, proto, *offp, 173 m->m_pkthdr.len - *offp)) { 174 INP_RUNLOCK(in6p); |
174 rip6stat.rip6s_badsum++; | 175 V_rip6stat.rip6s_badsum++; |
175 continue; 176 } 177 } 178 if (last) { 179 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 180 181#ifdef IPSEC 182 /* 183 * Check AH/ESP integrity. 184 */ 185 if (n && ipsec6_in_reject(n, last)) { 186 m_freem(n); | 176 continue; 177 } 178 } 179 if (last) { 180 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 181 182#ifdef IPSEC 183 /* 184 * Check AH/ESP integrity. 185 */ 186 if (n && ipsec6_in_reject(n, last)) { 187 m_freem(n); |
187 ipsec6stat.in_polvio++; | 188 V_ipsec6stat.in_polvio++; |
188 /* Do not inject data into pcb. */ 189 } else 190#endif /* IPSEC */ 191 if (n) { 192 if (last->in6p_flags & IN6P_CONTROLOPTS || 193 last->in6p_socket->so_options & SO_TIMESTAMP) 194 ip6_savecontrol(last, n, &opts); 195 /* strip intermediate headers */ 196 m_adj(n, *offp); 197 if (sbappendaddr(&last->in6p_socket->so_rcv, 198 (struct sockaddr *)&fromsa, 199 n, opts) == 0) { 200 m_freem(n); 201 if (opts) 202 m_freem(opts); | 189 /* Do not inject data into pcb. */ 190 } else 191#endif /* IPSEC */ 192 if (n) { 193 if (last->in6p_flags & IN6P_CONTROLOPTS || 194 last->in6p_socket->so_options & SO_TIMESTAMP) 195 ip6_savecontrol(last, n, &opts); 196 /* strip intermediate headers */ 197 m_adj(n, *offp); 198 if (sbappendaddr(&last->in6p_socket->so_rcv, 199 (struct sockaddr *)&fromsa, 200 n, opts) == 0) { 201 m_freem(n); 202 if (opts) 203 m_freem(opts); |
203 rip6stat.rip6s_fullsock++; | 204 V_rip6stat.rip6s_fullsock++; |
204 } else 205 sorwakeup(last->in6p_socket); 206 opts = NULL; 207 } 208 INP_RUNLOCK(last); 209 } 210 last = in6p; 211 } | 205 } else 206 sorwakeup(last->in6p_socket); 207 opts = NULL; 208 } 209 INP_RUNLOCK(last); 210 } 211 last = in6p; 212 } |
212 INP_INFO_RUNLOCK(&ripcbinfo); | 213 INP_INFO_RUNLOCK(&V_ripcbinfo); |
213#ifdef IPSEC 214 /* 215 * Check AH/ESP integrity. 216 */ 217 if (last && ipsec6_in_reject(m, last)) { 218 m_freem(m); | 214#ifdef IPSEC 215 /* 216 * Check AH/ESP integrity. 217 */ 218 if (last && ipsec6_in_reject(m, last)) { 219 m_freem(m); |
219 ipsec6stat.in_polvio++; 220 ip6stat.ip6s_delivered--; | 220 V_ipsec6stat.in_polvio++; 221 V_ip6stat.ip6s_delivered--; |
221 /* Do not inject data into pcb. */ 222 INP_RUNLOCK(last); 223 } else 224#endif /* IPSEC */ 225 if (last) { 226 if (last->in6p_flags & IN6P_CONTROLOPTS || 227 last->in6p_socket->so_options & SO_TIMESTAMP) 228 ip6_savecontrol(last, m, &opts); 229 /* Strip intermediate headers. */ 230 m_adj(m, *offp); 231 if (sbappendaddr(&last->in6p_socket->so_rcv, 232 (struct sockaddr *)&fromsa, m, opts) == 0) { 233 m_freem(m); 234 if (opts) 235 m_freem(opts); | 222 /* Do not inject data into pcb. */ 223 INP_RUNLOCK(last); 224 } else 225#endif /* IPSEC */ 226 if (last) { 227 if (last->in6p_flags & IN6P_CONTROLOPTS || 228 last->in6p_socket->so_options & SO_TIMESTAMP) 229 ip6_savecontrol(last, m, &opts); 230 /* Strip intermediate headers. */ 231 m_adj(m, *offp); 232 if (sbappendaddr(&last->in6p_socket->so_rcv, 233 (struct sockaddr *)&fromsa, m, opts) == 0) { 234 m_freem(m); 235 if (opts) 236 m_freem(opts); |
236 rip6stat.rip6s_fullsock++; | 237 V_rip6stat.rip6s_fullsock++; |
237 } else 238 sorwakeup(last->in6p_socket); 239 INP_RUNLOCK(last); 240 } else { | 238 } else 239 sorwakeup(last->in6p_socket); 240 INP_RUNLOCK(last); 241 } else { |
241 rip6stat.rip6s_nosock++; | 242 V_rip6stat.rip6s_nosock++; |
242 if (m->m_flags & M_MCAST) | 243 if (m->m_flags & M_MCAST) |
243 rip6stat.rip6s_nosockmcast++; | 244 V_rip6stat.rip6s_nosockmcast++; |
244 if (proto == IPPROTO_NONE) 245 m_freem(m); 246 else { 247 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 248 icmp6_error(m, ICMP6_PARAM_PROB, 249 ICMP6_PARAMPROB_NEXTHEADER, 250 prvnxtp - mtod(m, char *)); 251 } | 245 if (proto == IPPROTO_NONE) 246 m_freem(m); 247 else { 248 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 249 icmp6_error(m, ICMP6_PARAM_PROB, 250 ICMP6_PARAMPROB_NEXTHEADER, 251 prvnxtp - mtod(m, char *)); 252 } |
252 ip6stat.ip6s_delivered--; | 253 V_ip6stat.ip6s_delivered--; |
253 } 254 return (IPPROTO_DONE); 255} 256 257void 258rip6_ctlinput(int cmd, struct sockaddr *sa, void *d) 259{ 260 struct ip6_hdr *ip6; --- 29 unchanged lines hidden (view full) --- 290 sa6_src = ip6cp->ip6c_src; 291 } else { 292 m = NULL; 293 ip6 = NULL; 294 cmdarg = NULL; 295 sa6_src = &sa6_any; 296 } 297 | 254 } 255 return (IPPROTO_DONE); 256} 257 258void 259rip6_ctlinput(int cmd, struct sockaddr *sa, void *d) 260{ 261 struct ip6_hdr *ip6; --- 29 unchanged lines hidden (view full) --- 291 sa6_src = ip6cp->ip6c_src; 292 } else { 293 m = NULL; 294 ip6 = NULL; 295 cmdarg = NULL; 296 sa6_src = &sa6_any; 297 } 298 |
298 (void) in6_pcbnotify(&ripcbinfo, sa, 0, | 299 (void) in6_pcbnotify(&V_ripcbinfo, sa, 0, |
299 (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); 300} 301 302/* 303 * Generate IPv6 header and pass packet to ip6_output. Tack on options user 304 * may have setup with control call. 305 */ 306int --- 41 unchanged lines hidden (view full) --- 348 optp = in6p->in6p_outputopts; 349 350 /* 351 * Check and convert scope zone ID into internal form. 352 * 353 * XXX: we may still need to determine the zone later. 354 */ 355 if (!(so->so_state & SS_ISCONNECTED)) { | 300 (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); 301} 302 303/* 304 * Generate IPv6 header and pass packet to ip6_output. Tack on options user 305 * may have setup with control call. 306 */ 307int --- 41 unchanged lines hidden (view full) --- 349 optp = in6p->in6p_outputopts; 350 351 /* 352 * Check and convert scope zone ID into internal form. 353 * 354 * XXX: we may still need to determine the zone later. 355 */ 356 if (!(so->so_state & SS_ISCONNECTED)) { |
356 if (dstsock->sin6_scope_id == 0 && !ip6_use_defzone) | 357 if (dstsock->sin6_scope_id == 0 && !V_ip6_use_defzone) |
357 scope_ambiguous = 1; | 358 scope_ambiguous = 1; |
358 if ((error = sa6_embedscope(dstsock, ip6_use_defzone)) != 0) | 359 if ((error = sa6_embedscope(dstsock, V_ip6_use_defzone)) != 0) |
359 goto bad; 360 } 361 362 /* 363 * For an ICMPv6 packet, we should know its type and code to update 364 * statistics. 365 */ 366 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { --- 83 unchanged lines hidden (view full) --- 450 *p = 0; 451 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 452 } 453 454 error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p); 455 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 456 if (oifp) 457 icmp6_ifoutstat_inc(oifp, type, code); | 360 goto bad; 361 } 362 363 /* 364 * For an ICMPv6 packet, we should know its type and code to update 365 * statistics. 366 */ 367 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { --- 83 unchanged lines hidden (view full) --- 451 *p = 0; 452 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 453 } 454 455 error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p); 456 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 457 if (oifp) 458 icmp6_ifoutstat_inc(oifp, type, code); |
458 icmp6stat.icp6s_outhist[type]++; | 459 V_icmp6stat.icp6s_outhist[type]++; |
459 } else | 460 } else |
460 rip6stat.rip6s_opackets++; | 461 V_rip6stat.rip6s_opackets++; |
461 462 goto freectl; 463 464 bad: 465 if (m) 466 m_freem(m); 467 468 freectl: --- 86 unchanged lines hidden (view full) --- 555 return (error); 556 error = soreserve(so, rip_sendspace, rip_recvspace); 557 if (error) 558 return (error); 559 MALLOC(filter, struct icmp6_filter *, 560 sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); 561 if (filter == NULL) 562 return (ENOMEM); | 462 463 goto freectl; 464 465 bad: 466 if (m) 467 m_freem(m); 468 469 freectl: --- 86 unchanged lines hidden (view full) --- 556 return (error); 557 error = soreserve(so, rip_sendspace, rip_recvspace); 558 if (error) 559 return (error); 560 MALLOC(filter, struct icmp6_filter *, 561 sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); 562 if (filter == NULL) 563 return (ENOMEM); |
563 INP_INFO_WLOCK(&ripcbinfo); 564 error = in_pcballoc(so, &ripcbinfo); | 564 INP_INFO_WLOCK(&V_ripcbinfo); 565 error = in_pcballoc(so, &V_ripcbinfo); |
565 if (error) { | 566 if (error) { |
566 INP_INFO_WUNLOCK(&ripcbinfo); | 567 INP_INFO_WUNLOCK(&V_ripcbinfo); |
567 FREE(filter, M_PCB); 568 return (error); 569 } 570 inp = (struct inpcb *)so->so_pcb; | 568 FREE(filter, M_PCB); 569 return (error); 570 } 571 inp = (struct inpcb *)so->so_pcb; |
571 INP_INFO_WUNLOCK(&ripcbinfo); | 572 INP_INFO_WUNLOCK(&V_ripcbinfo); |
572 inp->inp_vflag |= INP_IPV6; 573 inp->in6p_ip6_nxt = (long)proto; 574 inp->in6p_hops = -1; /* use kernel default */ 575 inp->in6p_cksum = -1; 576 inp->in6p_icmp6filt = filter; 577 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 578 INP_WUNLOCK(inp); 579 return (0); --- 5 unchanged lines hidden (view full) --- 585 struct inpcb *inp; 586 587 inp = sotoinpcb(so); 588 KASSERT(inp != NULL, ("rip6_detach: inp == NULL")); 589 590 if (so == ip6_mrouter && ip6_mrouter_done) 591 ip6_mrouter_done(); 592 /* xxx: RSVP */ | 573 inp->inp_vflag |= INP_IPV6; 574 inp->in6p_ip6_nxt = (long)proto; 575 inp->in6p_hops = -1; /* use kernel default */ 576 inp->in6p_cksum = -1; 577 inp->in6p_icmp6filt = filter; 578 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 579 INP_WUNLOCK(inp); 580 return (0); --- 5 unchanged lines hidden (view full) --- 586 struct inpcb *inp; 587 588 inp = sotoinpcb(so); 589 KASSERT(inp != NULL, ("rip6_detach: inp == NULL")); 590 591 if (so == ip6_mrouter && ip6_mrouter_done) 592 ip6_mrouter_done(); 593 /* xxx: RSVP */ |
593 INP_INFO_WLOCK(&ripcbinfo); | 594 INP_INFO_WLOCK(&V_ripcbinfo); |
594 INP_WLOCK(inp); 595 FREE(inp->in6p_icmp6filt, M_PCB); 596 in6_pcbdetach(inp); 597 in6_pcbfree(inp); | 595 INP_WLOCK(inp); 596 FREE(inp->in6p_icmp6filt, M_PCB); 597 in6_pcbdetach(inp); 598 in6_pcbfree(inp); |
598 INP_INFO_WUNLOCK(&ripcbinfo); | 599 INP_INFO_WUNLOCK(&V_ripcbinfo); |
599} 600 601/* XXXRW: This can't ever be called. */ 602static void 603rip6_abort(struct socket *so) 604{ 605 struct inpcb *inp; 606 --- 37 unchanged lines hidden (view full) --- 644 struct ifaddr *ia = NULL; 645 int error = 0; 646 647 inp = sotoinpcb(so); 648 KASSERT(inp != NULL, ("rip6_bind: inp == NULL")); 649 650 if (nam->sa_len != sizeof(*addr)) 651 return (EINVAL); | 600} 601 602/* XXXRW: This can't ever be called. */ 603static void 604rip6_abort(struct socket *so) 605{ 606 struct inpcb *inp; 607 --- 37 unchanged lines hidden (view full) --- 645 struct ifaddr *ia = NULL; 646 int error = 0; 647 648 inp = sotoinpcb(so); 649 KASSERT(inp != NULL, ("rip6_bind: inp == NULL")); 650 651 if (nam->sa_len != sizeof(*addr)) 652 return (EINVAL); |
652 if (TAILQ_EMPTY(&ifnet) || addr->sin6_family != AF_INET6) | 653 if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6) |
653 return (EADDRNOTAVAIL); | 654 return (EADDRNOTAVAIL); |
654 if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0) | 655 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0) |
655 return (error); 656 657 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && 658 (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) 659 return (EADDRNOTAVAIL); 660 if (ia && 661 ((struct in6_ifaddr *)ia)->ia6_flags & 662 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| 663 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { 664 return (EADDRNOTAVAIL); 665 } | 656 return (error); 657 658 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && 659 (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) 660 return (EADDRNOTAVAIL); 661 if (ia && 662 ((struct in6_ifaddr *)ia)->ia6_flags & 663 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| 664 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { 665 return (EADDRNOTAVAIL); 666 } |
666 INP_INFO_WLOCK(&ripcbinfo); | 667 INP_INFO_WLOCK(&V_ripcbinfo); |
667 INP_WLOCK(inp); 668 inp->in6p_laddr = addr->sin6_addr; 669 INP_WUNLOCK(inp); | 668 INP_WLOCK(inp); 669 inp->in6p_laddr = addr->sin6_addr; 670 INP_WUNLOCK(inp); |
670 INP_INFO_WUNLOCK(&ripcbinfo); | 671 INP_INFO_WUNLOCK(&V_ripcbinfo); |
671 return (0); 672} 673 674static int 675rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 676{ 677 struct inpcb *inp; 678 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 679 struct in6_addr *in6a = NULL; 680 struct ifnet *ifp = NULL; 681 int error = 0, scope_ambiguous = 0; 682 683 inp = sotoinpcb(so); 684 KASSERT(inp != NULL, ("rip6_connect: inp == NULL")); 685 686 if (nam->sa_len != sizeof(*addr)) 687 return (EINVAL); | 672 return (0); 673} 674 675static int 676rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 677{ 678 struct inpcb *inp; 679 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 680 struct in6_addr *in6a = NULL; 681 struct ifnet *ifp = NULL; 682 int error = 0, scope_ambiguous = 0; 683 684 inp = sotoinpcb(so); 685 KASSERT(inp != NULL, ("rip6_connect: inp == NULL")); 686 687 if (nam->sa_len != sizeof(*addr)) 688 return (EINVAL); |
688 if (TAILQ_EMPTY(&ifnet)) | 689 if (TAILQ_EMPTY(&V_ifnet)) |
689 return (EADDRNOTAVAIL); 690 if (addr->sin6_family != AF_INET6) 691 return (EAFNOSUPPORT); 692 693 /* 694 * Application should provide a proper zone ID or the use of default 695 * zone IDs should be enabled. Unfortunately, some applications do 696 * not behave as it should, so we need a workaround. Even if an 697 * appropriate ID is not determined, we'll see if we can determine 698 * the outgoing interface. If we can, determine the zone ID based on 699 * the interface below. 700 */ | 690 return (EADDRNOTAVAIL); 691 if (addr->sin6_family != AF_INET6) 692 return (EAFNOSUPPORT); 693 694 /* 695 * Application should provide a proper zone ID or the use of default 696 * zone IDs should be enabled. Unfortunately, some applications do 697 * not behave as it should, so we need a workaround. Even if an 698 * appropriate ID is not determined, we'll see if we can determine 699 * the outgoing interface. If we can, determine the zone ID based on 700 * the interface below. 701 */ |
701 if (addr->sin6_scope_id == 0 && !ip6_use_defzone) | 702 if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone) |
702 scope_ambiguous = 1; | 703 scope_ambiguous = 1; |
703 if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0) | 704 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0) |
704 return (error); 705 | 705 return (error); 706 |
706 INP_INFO_WLOCK(&ripcbinfo); | 707 INP_INFO_WLOCK(&V_ripcbinfo); |
707 INP_WLOCK(inp); 708 /* Source address selection. XXX: need pcblookup? */ 709 in6a = in6_selectsrc(addr, inp->in6p_outputopts, 710 inp, NULL, so->so_cred, 711 &ifp, &error); 712 if (in6a == NULL) { 713 INP_WUNLOCK(inp); | 708 INP_WLOCK(inp); 709 /* Source address selection. XXX: need pcblookup? */ 710 in6a = in6_selectsrc(addr, inp->in6p_outputopts, 711 inp, NULL, so->so_cred, 712 &ifp, &error); 713 if (in6a == NULL) { 714 INP_WUNLOCK(inp); |
714 INP_INFO_WUNLOCK(&ripcbinfo); | 715 INP_INFO_WUNLOCK(&V_ripcbinfo); |
715 return (error ? error : EADDRNOTAVAIL); 716 } 717 718 /* XXX: see above */ 719 if (ifp && scope_ambiguous && 720 (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) { 721 INP_WUNLOCK(inp); | 716 return (error ? error : EADDRNOTAVAIL); 717 } 718 719 /* XXX: see above */ 720 if (ifp && scope_ambiguous && 721 (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) { 722 INP_WUNLOCK(inp); |
722 INP_INFO_WUNLOCK(&ripcbinfo); | 723 INP_INFO_WUNLOCK(&V_ripcbinfo); |
723 return (error); 724 } 725 inp->in6p_faddr = addr->sin6_addr; 726 inp->in6p_laddr = *in6a; 727 soisconnected(so); 728 INP_WUNLOCK(inp); | 724 return (error); 725 } 726 inp->in6p_faddr = addr->sin6_addr; 727 inp->in6p_laddr = *in6a; 728 soisconnected(so); 729 INP_WUNLOCK(inp); |
729 INP_INFO_WUNLOCK(&ripcbinfo); | 730 INP_INFO_WUNLOCK(&V_ripcbinfo); |
730 return (0); 731} 732 733static int 734rip6_shutdown(struct socket *so) 735{ 736 struct inpcb *inp; 737 --- 81 unchanged lines hidden --- | 731 return (0); 732} 733 734static int 735rip6_shutdown(struct socket *so) 736{ 737 struct inpcb *inp; 738 --- 81 unchanged lines hidden --- |