Deleted Added
full compact
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 ---