Deleted Added
full compact
raw_ip6.c (190964) raw_ip6.c (191672)
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
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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.
28 */
29
30/*-
31 * Copyright (c) 1982, 1986, 1988, 1993
32 * The Regents of the University of California.
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
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
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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.
28 */
29
30/*-
31 * Copyright (c) 1982, 1986, 1988, 1993
32 * The Regents of the University of California.
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
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 190964 2009-04-12 13:22:33Z rwatson $");
63__FBSDID("$FreeBSD: head/sys/netinet6/raw_ip6.c 191672 2009-04-29 19:19:13Z bms $");
64
65#include "opt_ipsec.h"
66#include "opt_inet6.h"
67#include "opt_route.h"
68
69#include <sys/param.h>
70#include <sys/errno.h>
71#include <sys/jail.h>
72#include <sys/lock.h>
73#include <sys/malloc.h>
74#include <sys/mbuf.h>
75#include <sys/priv.h>
76#include <sys/proc.h>
77#include <sys/protosw.h>
78#include <sys/signalvar.h>
79#include <sys/socket.h>
80#include <sys/socketvar.h>
81#include <sys/sx.h>
82#include <sys/syslog.h>
83#include <sys/vimage.h>
84
85#include <net/if.h>
86#include <net/if_types.h>
87#include <net/route.h>
88#include <net/vnet.h>
89
90#include <netinet/in.h>
91#include <netinet/in_var.h>
92#include <netinet/in_systm.h>
93#include <netinet/in_pcb.h>
94#include <netinet/vinet.h>
95
96#include <netinet/icmp6.h>
97#include <netinet/ip6.h>
98#include <netinet6/ip6protosw.h>
99#include <netinet6/ip6_mroute.h>
100#include <netinet6/in6_pcb.h>
101#include <netinet6/ip6_var.h>
102#include <netinet6/nd6.h>
103#include <netinet6/raw_ip6.h>
104#include <netinet6/scope6_var.h>
105#include <netinet6/vinet6.h>
106
107#ifdef IPSEC
108#include <netipsec/ipsec.h>
109#include <netipsec/ipsec6.h>
110#endif /* IPSEC */
111
112#include <machine/stdarg.h>
113
114#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
115#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
116
117/*
118 * Raw interface to IP6 protocol.
119 */
120
121#ifdef VIMAGE_GLOBALS
122extern struct inpcbhead ripcb;
123extern struct inpcbinfo ripcbinfo;
124struct rip6stat rip6stat;
125#endif
126
127extern u_long rip_sendspace;
128extern u_long rip_recvspace;
129
130/*
64
65#include "opt_ipsec.h"
66#include "opt_inet6.h"
67#include "opt_route.h"
68
69#include <sys/param.h>
70#include <sys/errno.h>
71#include <sys/jail.h>
72#include <sys/lock.h>
73#include <sys/malloc.h>
74#include <sys/mbuf.h>
75#include <sys/priv.h>
76#include <sys/proc.h>
77#include <sys/protosw.h>
78#include <sys/signalvar.h>
79#include <sys/socket.h>
80#include <sys/socketvar.h>
81#include <sys/sx.h>
82#include <sys/syslog.h>
83#include <sys/vimage.h>
84
85#include <net/if.h>
86#include <net/if_types.h>
87#include <net/route.h>
88#include <net/vnet.h>
89
90#include <netinet/in.h>
91#include <netinet/in_var.h>
92#include <netinet/in_systm.h>
93#include <netinet/in_pcb.h>
94#include <netinet/vinet.h>
95
96#include <netinet/icmp6.h>
97#include <netinet/ip6.h>
98#include <netinet6/ip6protosw.h>
99#include <netinet6/ip6_mroute.h>
100#include <netinet6/in6_pcb.h>
101#include <netinet6/ip6_var.h>
102#include <netinet6/nd6.h>
103#include <netinet6/raw_ip6.h>
104#include <netinet6/scope6_var.h>
105#include <netinet6/vinet6.h>
106
107#ifdef IPSEC
108#include <netipsec/ipsec.h>
109#include <netipsec/ipsec6.h>
110#endif /* IPSEC */
111
112#include <machine/stdarg.h>
113
114#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
115#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
116
117/*
118 * Raw interface to IP6 protocol.
119 */
120
121#ifdef VIMAGE_GLOBALS
122extern struct inpcbhead ripcb;
123extern struct inpcbinfo ripcbinfo;
124struct rip6stat rip6stat;
125#endif
126
127extern u_long rip_sendspace;
128extern u_long rip_recvspace;
129
130/*
131 * Hooks for multicast forwarding.
131 * Hooks for multicast routing. They all default to NULL, so leave them not
132 * initialized and rely on BSS being set to 0.
132 */
133 */
133struct socket *ip6_mrouter = NULL;
134
135/*
136 * The socket used to communicate with the multicast routing daemon.
137 */
138#ifdef VIMAGE_GLOBALS
139struct socket *ip6_mrouter;
140#endif
141
142/*
143 * The various mrouter functions.
144 */
134int (*ip6_mrouter_set)(struct socket *, struct sockopt *);
135int (*ip6_mrouter_get)(struct socket *, struct sockopt *);
136int (*ip6_mrouter_done)(void);
137int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *);
138int (*mrt6_ioctl)(int, caddr_t);
139
140/*
141 * Setup generic address and protocol structures for raw_input routine, then
142 * pass them along with mbuf chain.
143 */
144int
145rip6_input(struct mbuf **mp, int *offp, int proto)
146{
147 INIT_VNET_INET(curvnet);
148 INIT_VNET_INET6(curvnet);
149#ifdef IPSEC
150 INIT_VNET_IPSEC(curvnet);
151#endif
145int (*ip6_mrouter_set)(struct socket *, struct sockopt *);
146int (*ip6_mrouter_get)(struct socket *, struct sockopt *);
147int (*ip6_mrouter_done)(void);
148int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *);
149int (*mrt6_ioctl)(int, caddr_t);
150
151/*
152 * Setup generic address and protocol structures for raw_input routine, then
153 * pass them along with mbuf chain.
154 */
155int
156rip6_input(struct mbuf **mp, int *offp, int proto)
157{
158 INIT_VNET_INET(curvnet);
159 INIT_VNET_INET6(curvnet);
160#ifdef IPSEC
161 INIT_VNET_IPSEC(curvnet);
162#endif
163 struct ifnet *ifp;
152 struct mbuf *m = *mp;
153 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
154 register struct inpcb *in6p;
155 struct inpcb *last = 0;
156 struct mbuf *opts = NULL;
157 struct sockaddr_in6 fromsa;
158
159 V_rip6stat.rip6s_ipackets++;
160
161 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
162 /* XXX Send icmp6 host/port unreach? */
163 m_freem(m);
164 return (IPPROTO_DONE);
165 }
166
167 init_sin6(&fromsa, m); /* general init */
168
164 struct mbuf *m = *mp;
165 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
166 register struct inpcb *in6p;
167 struct inpcb *last = 0;
168 struct mbuf *opts = NULL;
169 struct sockaddr_in6 fromsa;
170
171 V_rip6stat.rip6s_ipackets++;
172
173 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
174 /* XXX Send icmp6 host/port unreach? */
175 m_freem(m);
176 return (IPPROTO_DONE);
177 }
178
179 init_sin6(&fromsa, m); /* general init */
180
181 ifp = m->m_pkthdr.rcvif;
182
169 INP_INFO_RLOCK(&V_ripcbinfo);
170 LIST_FOREACH(in6p, &V_ripcb, inp_list) {
171 /* XXX inp locking */
172 if ((in6p->inp_vflag & INP_IPV6) == 0)
173 continue;
174 if (in6p->inp_ip_p &&
175 in6p->inp_ip_p != proto)
176 continue;
177 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
178 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
179 continue;
180 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
181 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
182 continue;
183 INP_INFO_RLOCK(&V_ripcbinfo);
184 LIST_FOREACH(in6p, &V_ripcb, inp_list) {
185 /* XXX inp locking */
186 if ((in6p->inp_vflag & INP_IPV6) == 0)
187 continue;
188 if (in6p->inp_ip_p &&
189 in6p->inp_ip_p != proto)
190 continue;
191 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
192 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
193 continue;
194 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
195 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
196 continue;
183 if (prison_check_ip6(in6p->inp_cred, &ip6->ip6_dst) != 0)
184 continue;
185 INP_RLOCK(in6p);
197 if (jailed(in6p->inp_cred)) {
198 /*
199 * Allow raw socket in jail to receive multicast;
200 * assume process had PRIV_NETINET_RAW at attach,
201 * and fall through into normal filter path if so.
202 */
203 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
204 prison_check_ip6(in6p->inp_cred,
205 &ip6->ip6_dst) != 0)
206 continue;
207 }
186 if (in6p->in6p_cksum != -1) {
187 V_rip6stat.rip6s_isum++;
188 if (in6_cksum(m, proto, *offp,
189 m->m_pkthdr.len - *offp)) {
190 INP_RUNLOCK(in6p);
191 V_rip6stat.rip6s_badsum++;
192 continue;
193 }
194 }
208 if (in6p->in6p_cksum != -1) {
209 V_rip6stat.rip6s_isum++;
210 if (in6_cksum(m, proto, *offp,
211 m->m_pkthdr.len - *offp)) {
212 INP_RUNLOCK(in6p);
213 V_rip6stat.rip6s_badsum++;
214 continue;
215 }
216 }
217 INP_RLOCK(in6p);
218 /*
219 * If this raw socket has multicast state, and we
220 * have received a multicast, check if this socket
221 * should receive it, as multicast filtering is now
222 * the responsibility of the transport layer.
223 */
224 if (in6p->in6p_moptions &&
225 IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
226 struct sockaddr_in6 mcaddr;
227 int blocked;
228
229 bzero(&mcaddr, sizeof(struct sockaddr_in6));
230 mcaddr.sin6_len = sizeof(struct sockaddr_in6);
231 mcaddr.sin6_family = AF_INET6;
232 mcaddr.sin6_addr = ip6->ip6_dst;
233
234 blocked = im6o_mc_filter(in6p->in6p_moptions, ifp,
235 (struct sockaddr *)&mcaddr,
236 (struct sockaddr *)&fromsa);
237 if (blocked != MCAST_PASS) {
238 IP6STAT_INC(ip6s_notmember);
239 continue;
240 }
241 }
195 if (last != NULL) {
196 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
197
198#ifdef IPSEC
199 /*
200 * Check AH/ESP integrity.
201 */
202 if (n && ipsec6_in_reject(n, last)) {
203 m_freem(n);
204 V_ipsec6stat.in_polvio++;
205 /* Do not inject data into pcb. */
206 } else
207#endif /* IPSEC */
208 if (n) {
209 if (last->inp_flags & INP_CONTROLOPTS ||
210 last->inp_socket->so_options & SO_TIMESTAMP)
211 ip6_savecontrol(last, n, &opts);
212 /* strip intermediate headers */
213 m_adj(n, *offp);
214 if (sbappendaddr(&last->inp_socket->so_rcv,
215 (struct sockaddr *)&fromsa,
216 n, opts) == 0) {
217 m_freem(n);
218 if (opts)
219 m_freem(opts);
220 V_rip6stat.rip6s_fullsock++;
221 } else
222 sorwakeup(last->inp_socket);
223 opts = NULL;
224 }
225 INP_RUNLOCK(last);
226 }
227 last = in6p;
228 }
229 INP_INFO_RUNLOCK(&V_ripcbinfo);
230#ifdef IPSEC
231 /*
232 * Check AH/ESP integrity.
233 */
234 if ((last != NULL) && ipsec6_in_reject(m, last)) {
235 m_freem(m);
236 V_ipsec6stat.in_polvio++;
237 V_ip6stat.ip6s_delivered--;
238 /* Do not inject data into pcb. */
239 INP_RUNLOCK(last);
240 } else
241#endif /* IPSEC */
242 if (last != NULL) {
243 if (last->inp_flags & INP_CONTROLOPTS ||
244 last->inp_socket->so_options & SO_TIMESTAMP)
245 ip6_savecontrol(last, m, &opts);
246 /* Strip intermediate headers. */
247 m_adj(m, *offp);
248 if (sbappendaddr(&last->inp_socket->so_rcv,
249 (struct sockaddr *)&fromsa, m, opts) == 0) {
250 m_freem(m);
251 if (opts)
252 m_freem(opts);
253 V_rip6stat.rip6s_fullsock++;
254 } else
255 sorwakeup(last->inp_socket);
256 INP_RUNLOCK(last);
257 } else {
258 V_rip6stat.rip6s_nosock++;
259 if (m->m_flags & M_MCAST)
260 V_rip6stat.rip6s_nosockmcast++;
261 if (proto == IPPROTO_NONE)
262 m_freem(m);
263 else {
264 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
265 icmp6_error(m, ICMP6_PARAM_PROB,
266 ICMP6_PARAMPROB_NEXTHEADER,
267 prvnxtp - mtod(m, char *));
268 }
269 V_ip6stat.ip6s_delivered--;
270 }
271 return (IPPROTO_DONE);
272}
273
274void
275rip6_ctlinput(int cmd, struct sockaddr *sa, void *d)
276{
277 INIT_VNET_INET(curvnet);
278 struct ip6_hdr *ip6;
279 struct mbuf *m;
280 int off = 0;
281 struct ip6ctlparam *ip6cp = NULL;
282 const struct sockaddr_in6 *sa6_src = NULL;
283 void *cmdarg;
284 struct inpcb *(*notify)(struct inpcb *, int) = in6_rtchange;
285
286 if (sa->sa_family != AF_INET6 ||
287 sa->sa_len != sizeof(struct sockaddr_in6))
288 return;
289
290 if ((unsigned)cmd >= PRC_NCMDS)
291 return;
292 if (PRC_IS_REDIRECT(cmd))
293 notify = in6_rtchange, d = NULL;
294 else if (cmd == PRC_HOSTDEAD)
295 d = NULL;
296 else if (inet6ctlerrmap[cmd] == 0)
297 return;
298
299 /*
300 * If the parameter is from icmp6, decode it.
301 */
302 if (d != NULL) {
303 ip6cp = (struct ip6ctlparam *)d;
304 m = ip6cp->ip6c_m;
305 ip6 = ip6cp->ip6c_ip6;
306 off = ip6cp->ip6c_off;
307 cmdarg = ip6cp->ip6c_cmdarg;
308 sa6_src = ip6cp->ip6c_src;
309 } else {
310 m = NULL;
311 ip6 = NULL;
312 cmdarg = NULL;
313 sa6_src = &sa6_any;
314 }
315
316 (void) in6_pcbnotify(&V_ripcbinfo, sa, 0,
317 (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify);
318}
319
320/*
321 * Generate IPv6 header and pass packet to ip6_output. Tack on options user
322 * may have setup with control call.
323 */
324int
325#if __STDC__
326rip6_output(struct mbuf *m, ...)
327#else
328rip6_output(m, va_alist)
329 struct mbuf *m;
330 va_dcl
331#endif
332{
333 INIT_VNET_INET6(curvnet);
334 struct mbuf *control;
335 struct socket *so;
336 struct sockaddr_in6 *dstsock;
337 struct in6_addr *dst;
338 struct ip6_hdr *ip6;
339 struct inpcb *in6p;
340 u_int plen = m->m_pkthdr.len;
341 int error = 0;
342 struct ip6_pktopts opt, *optp;
343 struct ifnet *oifp = NULL;
344 int type = 0, code = 0; /* for ICMPv6 output statistics only */
345 int scope_ambiguous = 0;
346 struct in6_addr *in6a;
347 va_list ap;
348
349 va_start(ap, m);
350 so = va_arg(ap, struct socket *);
351 dstsock = va_arg(ap, struct sockaddr_in6 *);
352 control = va_arg(ap, struct mbuf *);
353 va_end(ap);
354
355 in6p = sotoinpcb(so);
356 INP_WLOCK(in6p);
357
358 dst = &dstsock->sin6_addr;
359 if (control != NULL) {
360 if ((error = ip6_setpktopts(control, &opt,
361 in6p->in6p_outputopts, so->so_cred,
362 so->so_proto->pr_protocol)) != 0) {
363 goto bad;
364 }
365 optp = &opt;
366 } else
367 optp = in6p->in6p_outputopts;
368
369 /*
370 * Check and convert scope zone ID into internal form.
371 *
372 * XXX: we may still need to determine the zone later.
373 */
374 if (!(so->so_state & SS_ISCONNECTED)) {
375 if (dstsock->sin6_scope_id == 0 && !V_ip6_use_defzone)
376 scope_ambiguous = 1;
377 if ((error = sa6_embedscope(dstsock, V_ip6_use_defzone)) != 0)
378 goto bad;
379 }
380
381 /*
382 * For an ICMPv6 packet, we should know its type and code to update
383 * statistics.
384 */
385 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
386 struct icmp6_hdr *icmp6;
387 if (m->m_len < sizeof(struct icmp6_hdr) &&
388 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
389 error = ENOBUFS;
390 goto bad;
391 }
392 icmp6 = mtod(m, struct icmp6_hdr *);
393 type = icmp6->icmp6_type;
394 code = icmp6->icmp6_code;
395 }
396
397 M_PREPEND(m, sizeof(*ip6), M_DONTWAIT);
398 if (m == NULL) {
399 error = ENOBUFS;
400 goto bad;
401 }
402 ip6 = mtod(m, struct ip6_hdr *);
403
404 /*
405 * Source address selection.
406 */
407 if ((in6a = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
408 &oifp, &error)) == NULL) {
409 if (error == 0)
410 error = EADDRNOTAVAIL;
411 goto bad;
412 }
413 error = prison_get_ip6(in6p->inp_cred, in6a);
414 if (error != 0)
415 goto bad;
416 ip6->ip6_src = *in6a;
417
418 if (oifp && scope_ambiguous) {
419 /*
420 * Application should provide a proper zone ID or the use of
421 * default zone IDs should be enabled. Unfortunately, some
422 * applications do not behave as it should, so we need a
423 * workaround. Even if an appropriate ID is not determined
424 * (when it's required), if we can determine the outgoing
425 * interface. determine the zone ID based on the interface.
426 */
427 error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
428 if (error != 0)
429 goto bad;
430 }
431 ip6->ip6_dst = dstsock->sin6_addr;
432
433 /*
434 * Fill in the rest of the IPv6 header fields.
435 */
436 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
437 (in6p->inp_flow & IPV6_FLOWINFO_MASK);
438 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
439 (IPV6_VERSION & IPV6_VERSION_MASK);
440
441 /*
442 * ip6_plen will be filled in ip6_output, so not fill it here.
443 */
444 ip6->ip6_nxt = in6p->inp_ip_p;
445 ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
446
447 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
448 in6p->in6p_cksum != -1) {
449 struct mbuf *n;
450 int off;
451 u_int16_t *p;
452
453 /* Compute checksum. */
454 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
455 off = offsetof(struct icmp6_hdr, icmp6_cksum);
456 else
457 off = in6p->in6p_cksum;
458 if (plen < off + 1) {
459 error = EINVAL;
460 goto bad;
461 }
462 off += sizeof(struct ip6_hdr);
463
464 n = m;
465 while (n && n->m_len <= off) {
466 off -= n->m_len;
467 n = n->m_next;
468 }
469 if (!n)
470 goto bad;
471 p = (u_int16_t *)(mtod(n, caddr_t) + off);
472 *p = 0;
473 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
474 }
475
476 error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p);
477 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
478 if (oifp)
479 icmp6_ifoutstat_inc(oifp, type, code);
480 ICMP6STAT_INC(icp6s_outhist[type]);
481 } else
482 V_rip6stat.rip6s_opackets++;
483
484 goto freectl;
485
486 bad:
487 if (m)
488 m_freem(m);
489
490 freectl:
491 if (control != NULL) {
492 ip6_clearpktopts(&opt, -1);
493 m_freem(control);
494 }
495 INP_WUNLOCK(in6p);
496 return (error);
497}
498
499/*
500 * Raw IPv6 socket option processing.
501 */
502int
503rip6_ctloutput(struct socket *so, struct sockopt *sopt)
504{
505 int error;
506
507 if (sopt->sopt_level == IPPROTO_ICMPV6)
508 /*
509 * XXX: is it better to call icmp6_ctloutput() directly
510 * from protosw?
511 */
512 return (icmp6_ctloutput(so, sopt));
513 else if (sopt->sopt_level != IPPROTO_IPV6)
514 return (EINVAL);
515
516 error = 0;
517
518 switch (sopt->sopt_dir) {
519 case SOPT_GET:
520 switch (sopt->sopt_name) {
521 case MRT6_INIT:
522 case MRT6_DONE:
523 case MRT6_ADD_MIF:
524 case MRT6_DEL_MIF:
525 case MRT6_ADD_MFC:
526 case MRT6_DEL_MFC:
527 case MRT6_PIM:
528 error = ip6_mrouter_get ? ip6_mrouter_get(so, sopt) :
529 EOPNOTSUPP;
530 break;
531 case IPV6_CHECKSUM:
532 error = ip6_raw_ctloutput(so, sopt);
533 break;
534 default:
535 error = ip6_ctloutput(so, sopt);
536 break;
537 }
538 break;
539
540 case SOPT_SET:
541 switch (sopt->sopt_name) {
542 case MRT6_INIT:
543 case MRT6_DONE:
544 case MRT6_ADD_MIF:
545 case MRT6_DEL_MIF:
546 case MRT6_ADD_MFC:
547 case MRT6_DEL_MFC:
548 case MRT6_PIM:
549 error = ip6_mrouter_set ? ip6_mrouter_set(so, sopt) :
550 EOPNOTSUPP;
551 break;
552 case IPV6_CHECKSUM:
553 error = ip6_raw_ctloutput(so, sopt);
554 break;
555 default:
556 error = ip6_ctloutput(so, sopt);
557 break;
558 }
559 break;
560 }
561
562 return (error);
563}
564
565static int
566rip6_attach(struct socket *so, int proto, struct thread *td)
567{
568 INIT_VNET_INET(so->so_vnet);
569 struct inpcb *inp;
570 struct icmp6_filter *filter;
571 int error;
572
573 inp = sotoinpcb(so);
574 KASSERT(inp == NULL, ("rip6_attach: inp != NULL"));
575
576 error = priv_check(td, PRIV_NETINET_RAW);
577 if (error)
578 return (error);
579 error = soreserve(so, rip_sendspace, rip_recvspace);
580 if (error)
581 return (error);
582 filter = malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
583 if (filter == NULL)
584 return (ENOMEM);
585 INP_INFO_WLOCK(&V_ripcbinfo);
586 error = in_pcballoc(so, &V_ripcbinfo);
587 if (error) {
588 INP_INFO_WUNLOCK(&V_ripcbinfo);
589 free(filter, M_PCB);
590 return (error);
591 }
592 inp = (struct inpcb *)so->so_pcb;
593 INP_INFO_WUNLOCK(&V_ripcbinfo);
594 inp->inp_vflag |= INP_IPV6;
595 inp->inp_ip_p = (long)proto;
596 inp->in6p_hops = -1; /* use kernel default */
597 inp->in6p_cksum = -1;
598 inp->in6p_icmp6filt = filter;
599 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
600 INP_WUNLOCK(inp);
601 return (0);
602}
603
604static void
605rip6_detach(struct socket *so)
606{
242 if (last != NULL) {
243 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
244
245#ifdef IPSEC
246 /*
247 * Check AH/ESP integrity.
248 */
249 if (n && ipsec6_in_reject(n, last)) {
250 m_freem(n);
251 V_ipsec6stat.in_polvio++;
252 /* Do not inject data into pcb. */
253 } else
254#endif /* IPSEC */
255 if (n) {
256 if (last->inp_flags & INP_CONTROLOPTS ||
257 last->inp_socket->so_options & SO_TIMESTAMP)
258 ip6_savecontrol(last, n, &opts);
259 /* strip intermediate headers */
260 m_adj(n, *offp);
261 if (sbappendaddr(&last->inp_socket->so_rcv,
262 (struct sockaddr *)&fromsa,
263 n, opts) == 0) {
264 m_freem(n);
265 if (opts)
266 m_freem(opts);
267 V_rip6stat.rip6s_fullsock++;
268 } else
269 sorwakeup(last->inp_socket);
270 opts = NULL;
271 }
272 INP_RUNLOCK(last);
273 }
274 last = in6p;
275 }
276 INP_INFO_RUNLOCK(&V_ripcbinfo);
277#ifdef IPSEC
278 /*
279 * Check AH/ESP integrity.
280 */
281 if ((last != NULL) && ipsec6_in_reject(m, last)) {
282 m_freem(m);
283 V_ipsec6stat.in_polvio++;
284 V_ip6stat.ip6s_delivered--;
285 /* Do not inject data into pcb. */
286 INP_RUNLOCK(last);
287 } else
288#endif /* IPSEC */
289 if (last != NULL) {
290 if (last->inp_flags & INP_CONTROLOPTS ||
291 last->inp_socket->so_options & SO_TIMESTAMP)
292 ip6_savecontrol(last, m, &opts);
293 /* Strip intermediate headers. */
294 m_adj(m, *offp);
295 if (sbappendaddr(&last->inp_socket->so_rcv,
296 (struct sockaddr *)&fromsa, m, opts) == 0) {
297 m_freem(m);
298 if (opts)
299 m_freem(opts);
300 V_rip6stat.rip6s_fullsock++;
301 } else
302 sorwakeup(last->inp_socket);
303 INP_RUNLOCK(last);
304 } else {
305 V_rip6stat.rip6s_nosock++;
306 if (m->m_flags & M_MCAST)
307 V_rip6stat.rip6s_nosockmcast++;
308 if (proto == IPPROTO_NONE)
309 m_freem(m);
310 else {
311 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
312 icmp6_error(m, ICMP6_PARAM_PROB,
313 ICMP6_PARAMPROB_NEXTHEADER,
314 prvnxtp - mtod(m, char *));
315 }
316 V_ip6stat.ip6s_delivered--;
317 }
318 return (IPPROTO_DONE);
319}
320
321void
322rip6_ctlinput(int cmd, struct sockaddr *sa, void *d)
323{
324 INIT_VNET_INET(curvnet);
325 struct ip6_hdr *ip6;
326 struct mbuf *m;
327 int off = 0;
328 struct ip6ctlparam *ip6cp = NULL;
329 const struct sockaddr_in6 *sa6_src = NULL;
330 void *cmdarg;
331 struct inpcb *(*notify)(struct inpcb *, int) = in6_rtchange;
332
333 if (sa->sa_family != AF_INET6 ||
334 sa->sa_len != sizeof(struct sockaddr_in6))
335 return;
336
337 if ((unsigned)cmd >= PRC_NCMDS)
338 return;
339 if (PRC_IS_REDIRECT(cmd))
340 notify = in6_rtchange, d = NULL;
341 else if (cmd == PRC_HOSTDEAD)
342 d = NULL;
343 else if (inet6ctlerrmap[cmd] == 0)
344 return;
345
346 /*
347 * If the parameter is from icmp6, decode it.
348 */
349 if (d != NULL) {
350 ip6cp = (struct ip6ctlparam *)d;
351 m = ip6cp->ip6c_m;
352 ip6 = ip6cp->ip6c_ip6;
353 off = ip6cp->ip6c_off;
354 cmdarg = ip6cp->ip6c_cmdarg;
355 sa6_src = ip6cp->ip6c_src;
356 } else {
357 m = NULL;
358 ip6 = NULL;
359 cmdarg = NULL;
360 sa6_src = &sa6_any;
361 }
362
363 (void) in6_pcbnotify(&V_ripcbinfo, sa, 0,
364 (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify);
365}
366
367/*
368 * Generate IPv6 header and pass packet to ip6_output. Tack on options user
369 * may have setup with control call.
370 */
371int
372#if __STDC__
373rip6_output(struct mbuf *m, ...)
374#else
375rip6_output(m, va_alist)
376 struct mbuf *m;
377 va_dcl
378#endif
379{
380 INIT_VNET_INET6(curvnet);
381 struct mbuf *control;
382 struct socket *so;
383 struct sockaddr_in6 *dstsock;
384 struct in6_addr *dst;
385 struct ip6_hdr *ip6;
386 struct inpcb *in6p;
387 u_int plen = m->m_pkthdr.len;
388 int error = 0;
389 struct ip6_pktopts opt, *optp;
390 struct ifnet *oifp = NULL;
391 int type = 0, code = 0; /* for ICMPv6 output statistics only */
392 int scope_ambiguous = 0;
393 struct in6_addr *in6a;
394 va_list ap;
395
396 va_start(ap, m);
397 so = va_arg(ap, struct socket *);
398 dstsock = va_arg(ap, struct sockaddr_in6 *);
399 control = va_arg(ap, struct mbuf *);
400 va_end(ap);
401
402 in6p = sotoinpcb(so);
403 INP_WLOCK(in6p);
404
405 dst = &dstsock->sin6_addr;
406 if (control != NULL) {
407 if ((error = ip6_setpktopts(control, &opt,
408 in6p->in6p_outputopts, so->so_cred,
409 so->so_proto->pr_protocol)) != 0) {
410 goto bad;
411 }
412 optp = &opt;
413 } else
414 optp = in6p->in6p_outputopts;
415
416 /*
417 * Check and convert scope zone ID into internal form.
418 *
419 * XXX: we may still need to determine the zone later.
420 */
421 if (!(so->so_state & SS_ISCONNECTED)) {
422 if (dstsock->sin6_scope_id == 0 && !V_ip6_use_defzone)
423 scope_ambiguous = 1;
424 if ((error = sa6_embedscope(dstsock, V_ip6_use_defzone)) != 0)
425 goto bad;
426 }
427
428 /*
429 * For an ICMPv6 packet, we should know its type and code to update
430 * statistics.
431 */
432 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
433 struct icmp6_hdr *icmp6;
434 if (m->m_len < sizeof(struct icmp6_hdr) &&
435 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
436 error = ENOBUFS;
437 goto bad;
438 }
439 icmp6 = mtod(m, struct icmp6_hdr *);
440 type = icmp6->icmp6_type;
441 code = icmp6->icmp6_code;
442 }
443
444 M_PREPEND(m, sizeof(*ip6), M_DONTWAIT);
445 if (m == NULL) {
446 error = ENOBUFS;
447 goto bad;
448 }
449 ip6 = mtod(m, struct ip6_hdr *);
450
451 /*
452 * Source address selection.
453 */
454 if ((in6a = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
455 &oifp, &error)) == NULL) {
456 if (error == 0)
457 error = EADDRNOTAVAIL;
458 goto bad;
459 }
460 error = prison_get_ip6(in6p->inp_cred, in6a);
461 if (error != 0)
462 goto bad;
463 ip6->ip6_src = *in6a;
464
465 if (oifp && scope_ambiguous) {
466 /*
467 * Application should provide a proper zone ID or the use of
468 * default zone IDs should be enabled. Unfortunately, some
469 * applications do not behave as it should, so we need a
470 * workaround. Even if an appropriate ID is not determined
471 * (when it's required), if we can determine the outgoing
472 * interface. determine the zone ID based on the interface.
473 */
474 error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
475 if (error != 0)
476 goto bad;
477 }
478 ip6->ip6_dst = dstsock->sin6_addr;
479
480 /*
481 * Fill in the rest of the IPv6 header fields.
482 */
483 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
484 (in6p->inp_flow & IPV6_FLOWINFO_MASK);
485 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
486 (IPV6_VERSION & IPV6_VERSION_MASK);
487
488 /*
489 * ip6_plen will be filled in ip6_output, so not fill it here.
490 */
491 ip6->ip6_nxt = in6p->inp_ip_p;
492 ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
493
494 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
495 in6p->in6p_cksum != -1) {
496 struct mbuf *n;
497 int off;
498 u_int16_t *p;
499
500 /* Compute checksum. */
501 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
502 off = offsetof(struct icmp6_hdr, icmp6_cksum);
503 else
504 off = in6p->in6p_cksum;
505 if (plen < off + 1) {
506 error = EINVAL;
507 goto bad;
508 }
509 off += sizeof(struct ip6_hdr);
510
511 n = m;
512 while (n && n->m_len <= off) {
513 off -= n->m_len;
514 n = n->m_next;
515 }
516 if (!n)
517 goto bad;
518 p = (u_int16_t *)(mtod(n, caddr_t) + off);
519 *p = 0;
520 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
521 }
522
523 error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p);
524 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
525 if (oifp)
526 icmp6_ifoutstat_inc(oifp, type, code);
527 ICMP6STAT_INC(icp6s_outhist[type]);
528 } else
529 V_rip6stat.rip6s_opackets++;
530
531 goto freectl;
532
533 bad:
534 if (m)
535 m_freem(m);
536
537 freectl:
538 if (control != NULL) {
539 ip6_clearpktopts(&opt, -1);
540 m_freem(control);
541 }
542 INP_WUNLOCK(in6p);
543 return (error);
544}
545
546/*
547 * Raw IPv6 socket option processing.
548 */
549int
550rip6_ctloutput(struct socket *so, struct sockopt *sopt)
551{
552 int error;
553
554 if (sopt->sopt_level == IPPROTO_ICMPV6)
555 /*
556 * XXX: is it better to call icmp6_ctloutput() directly
557 * from protosw?
558 */
559 return (icmp6_ctloutput(so, sopt));
560 else if (sopt->sopt_level != IPPROTO_IPV6)
561 return (EINVAL);
562
563 error = 0;
564
565 switch (sopt->sopt_dir) {
566 case SOPT_GET:
567 switch (sopt->sopt_name) {
568 case MRT6_INIT:
569 case MRT6_DONE:
570 case MRT6_ADD_MIF:
571 case MRT6_DEL_MIF:
572 case MRT6_ADD_MFC:
573 case MRT6_DEL_MFC:
574 case MRT6_PIM:
575 error = ip6_mrouter_get ? ip6_mrouter_get(so, sopt) :
576 EOPNOTSUPP;
577 break;
578 case IPV6_CHECKSUM:
579 error = ip6_raw_ctloutput(so, sopt);
580 break;
581 default:
582 error = ip6_ctloutput(so, sopt);
583 break;
584 }
585 break;
586
587 case SOPT_SET:
588 switch (sopt->sopt_name) {
589 case MRT6_INIT:
590 case MRT6_DONE:
591 case MRT6_ADD_MIF:
592 case MRT6_DEL_MIF:
593 case MRT6_ADD_MFC:
594 case MRT6_DEL_MFC:
595 case MRT6_PIM:
596 error = ip6_mrouter_set ? ip6_mrouter_set(so, sopt) :
597 EOPNOTSUPP;
598 break;
599 case IPV6_CHECKSUM:
600 error = ip6_raw_ctloutput(so, sopt);
601 break;
602 default:
603 error = ip6_ctloutput(so, sopt);
604 break;
605 }
606 break;
607 }
608
609 return (error);
610}
611
612static int
613rip6_attach(struct socket *so, int proto, struct thread *td)
614{
615 INIT_VNET_INET(so->so_vnet);
616 struct inpcb *inp;
617 struct icmp6_filter *filter;
618 int error;
619
620 inp = sotoinpcb(so);
621 KASSERT(inp == NULL, ("rip6_attach: inp != NULL"));
622
623 error = priv_check(td, PRIV_NETINET_RAW);
624 if (error)
625 return (error);
626 error = soreserve(so, rip_sendspace, rip_recvspace);
627 if (error)
628 return (error);
629 filter = malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
630 if (filter == NULL)
631 return (ENOMEM);
632 INP_INFO_WLOCK(&V_ripcbinfo);
633 error = in_pcballoc(so, &V_ripcbinfo);
634 if (error) {
635 INP_INFO_WUNLOCK(&V_ripcbinfo);
636 free(filter, M_PCB);
637 return (error);
638 }
639 inp = (struct inpcb *)so->so_pcb;
640 INP_INFO_WUNLOCK(&V_ripcbinfo);
641 inp->inp_vflag |= INP_IPV6;
642 inp->inp_ip_p = (long)proto;
643 inp->in6p_hops = -1; /* use kernel default */
644 inp->in6p_cksum = -1;
645 inp->in6p_icmp6filt = filter;
646 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
647 INP_WUNLOCK(inp);
648 return (0);
649}
650
651static void
652rip6_detach(struct socket *so)
653{
607 INIT_VNET_INET(so->so_vnet);
654 INIT_VNET_INET6(so->so_vnet);
608 struct inpcb *inp;
609
610 inp = sotoinpcb(so);
611 KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
612
655 struct inpcb *inp;
656
657 inp = sotoinpcb(so);
658 KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
659
613 if (so == ip6_mrouter && ip6_mrouter_done)
660 if (so == V_ip6_mrouter && ip6_mrouter_done)
614 ip6_mrouter_done();
615 /* xxx: RSVP */
616 INP_INFO_WLOCK(&V_ripcbinfo);
617 INP_WLOCK(inp);
618 free(inp->in6p_icmp6filt, M_PCB);
619 in_pcbdetach(inp);
620 in_pcbfree(inp);
621 INP_INFO_WUNLOCK(&V_ripcbinfo);
622}
623
624/* XXXRW: This can't ever be called. */
625static void
626rip6_abort(struct socket *so)
627{
628 struct inpcb *inp;
629
630 inp = sotoinpcb(so);
631 KASSERT(inp != NULL, ("rip6_abort: inp == NULL"));
632
633 soisdisconnected(so);
634}
635
636static void
637rip6_close(struct socket *so)
638{
639 struct inpcb *inp;
640
641 inp = sotoinpcb(so);
642 KASSERT(inp != NULL, ("rip6_close: inp == NULL"));
643
644 soisdisconnected(so);
645}
646
647static int
648rip6_disconnect(struct socket *so)
649{
650 struct inpcb *inp;
651
652 inp = sotoinpcb(so);
653 KASSERT(inp != NULL, ("rip6_disconnect: inp == NULL"));
654
655 if ((so->so_state & SS_ISCONNECTED) == 0)
656 return (ENOTCONN);
657 inp->in6p_faddr = in6addr_any;
658 rip6_abort(so);
659 return (0);
660}
661
662static int
663rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
664{
665 INIT_VNET_NET(so->so_vnet);
666 INIT_VNET_INET(so->so_vnet);
667 INIT_VNET_INET6(so->so_vnet);
668 struct inpcb *inp;
669 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
670 struct ifaddr *ia = NULL;
671 int error = 0;
672
673 inp = sotoinpcb(so);
674 KASSERT(inp != NULL, ("rip6_bind: inp == NULL"));
675
676 if (nam->sa_len != sizeof(*addr))
677 return (EINVAL);
678 if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0)
679 return (error);
680 if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6)
681 return (EADDRNOTAVAIL);
682 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
683 return (error);
684
685 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
686 (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0)
687 return (EADDRNOTAVAIL);
688 if (ia &&
689 ((struct in6_ifaddr *)ia)->ia6_flags &
690 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
691 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
692 return (EADDRNOTAVAIL);
693 }
694 INP_INFO_WLOCK(&V_ripcbinfo);
695 INP_WLOCK(inp);
696 inp->in6p_laddr = addr->sin6_addr;
697 INP_WUNLOCK(inp);
698 INP_INFO_WUNLOCK(&V_ripcbinfo);
699 return (0);
700}
701
702static int
703rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
704{
705 INIT_VNET_NET(so->so_vnet);
706 INIT_VNET_INET(so->so_vnet);
707 INIT_VNET_INET6(so->so_vnet);
708 struct inpcb *inp;
709 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
710 struct in6_addr *in6a = NULL;
711 struct ifnet *ifp = NULL;
712 int error = 0, scope_ambiguous = 0;
713
714 inp = sotoinpcb(so);
715 KASSERT(inp != NULL, ("rip6_connect: inp == NULL"));
716
717 if (nam->sa_len != sizeof(*addr))
718 return (EINVAL);
719 if (TAILQ_EMPTY(&V_ifnet))
720 return (EADDRNOTAVAIL);
721 if (addr->sin6_family != AF_INET6)
722 return (EAFNOSUPPORT);
723
724 /*
725 * Application should provide a proper zone ID or the use of default
726 * zone IDs should be enabled. Unfortunately, some applications do
727 * not behave as it should, so we need a workaround. Even if an
728 * appropriate ID is not determined, we'll see if we can determine
729 * the outgoing interface. If we can, determine the zone ID based on
730 * the interface below.
731 */
732 if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone)
733 scope_ambiguous = 1;
734 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
735 return (error);
736
737 INP_INFO_WLOCK(&V_ripcbinfo);
738 INP_WLOCK(inp);
739 /* Source address selection. XXX: need pcblookup? */
740 in6a = in6_selectsrc(addr, inp->in6p_outputopts,
741 inp, NULL, so->so_cred,
742 &ifp, &error);
743 if (in6a == NULL) {
744 INP_WUNLOCK(inp);
745 INP_INFO_WUNLOCK(&V_ripcbinfo);
746 return (error ? error : EADDRNOTAVAIL);
747 }
748
749 /* XXX: see above */
750 if (ifp && scope_ambiguous &&
751 (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
752 INP_WUNLOCK(inp);
753 INP_INFO_WUNLOCK(&V_ripcbinfo);
754 return (error);
755 }
756 inp->in6p_faddr = addr->sin6_addr;
757 inp->in6p_laddr = *in6a;
758 soisconnected(so);
759 INP_WUNLOCK(inp);
760 INP_INFO_WUNLOCK(&V_ripcbinfo);
761 return (0);
762}
763
764static int
765rip6_shutdown(struct socket *so)
766{
767 struct inpcb *inp;
768
769 inp = sotoinpcb(so);
770 KASSERT(inp != NULL, ("rip6_shutdown: inp == NULL"));
771
772 INP_WLOCK(inp);
773 socantsendmore(so);
774 INP_WUNLOCK(inp);
775 return (0);
776}
777
778static int
779rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
780 struct mbuf *control, struct thread *td)
781{
782 struct inpcb *inp;
783 struct sockaddr_in6 tmp;
784 struct sockaddr_in6 *dst;
785 int ret;
786
787 inp = sotoinpcb(so);
788 KASSERT(inp != NULL, ("rip6_send: inp == NULL"));
789
790 /* Always copy sockaddr to avoid overwrites. */
791 /* Unlocked read. */
792 if (so->so_state & SS_ISCONNECTED) {
793 if (nam) {
794 m_freem(m);
795 return (EISCONN);
796 }
797 /* XXX */
798 bzero(&tmp, sizeof(tmp));
799 tmp.sin6_family = AF_INET6;
800 tmp.sin6_len = sizeof(struct sockaddr_in6);
801 INP_RLOCK(inp);
802 bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
803 sizeof(struct in6_addr));
804 INP_RUNLOCK(inp);
805 dst = &tmp;
806 } else {
807 if (nam == NULL) {
808 m_freem(m);
809 return (ENOTCONN);
810 }
811 if (nam->sa_len != sizeof(struct sockaddr_in6)) {
812 m_freem(m);
813 return (EINVAL);
814 }
815 tmp = *(struct sockaddr_in6 *)nam;
816 dst = &tmp;
817
818 if (dst->sin6_family == AF_UNSPEC) {
819 /*
820 * XXX: we allow this case for backward
821 * compatibility to buggy applications that
822 * rely on old (and wrong) kernel behavior.
823 */
824 log(LOG_INFO, "rip6 SEND: address family is "
825 "unspec. Assume AF_INET6\n");
826 dst->sin6_family = AF_INET6;
827 } else if (dst->sin6_family != AF_INET6) {
828 m_freem(m);
829 return(EAFNOSUPPORT);
830 }
831 }
832 ret = rip6_output(m, so, dst, control);
833 return (ret);
834}
835
836struct pr_usrreqs rip6_usrreqs = {
837 .pru_abort = rip6_abort,
838 .pru_attach = rip6_attach,
839 .pru_bind = rip6_bind,
840 .pru_connect = rip6_connect,
841 .pru_control = in6_control,
842 .pru_detach = rip6_detach,
843 .pru_disconnect = rip6_disconnect,
844 .pru_peeraddr = in6_getpeeraddr,
845 .pru_send = rip6_send,
846 .pru_shutdown = rip6_shutdown,
847 .pru_sockaddr = in6_getsockaddr,
848 .pru_close = rip6_close,
849};
661 ip6_mrouter_done();
662 /* xxx: RSVP */
663 INP_INFO_WLOCK(&V_ripcbinfo);
664 INP_WLOCK(inp);
665 free(inp->in6p_icmp6filt, M_PCB);
666 in_pcbdetach(inp);
667 in_pcbfree(inp);
668 INP_INFO_WUNLOCK(&V_ripcbinfo);
669}
670
671/* XXXRW: This can't ever be called. */
672static void
673rip6_abort(struct socket *so)
674{
675 struct inpcb *inp;
676
677 inp = sotoinpcb(so);
678 KASSERT(inp != NULL, ("rip6_abort: inp == NULL"));
679
680 soisdisconnected(so);
681}
682
683static void
684rip6_close(struct socket *so)
685{
686 struct inpcb *inp;
687
688 inp = sotoinpcb(so);
689 KASSERT(inp != NULL, ("rip6_close: inp == NULL"));
690
691 soisdisconnected(so);
692}
693
694static int
695rip6_disconnect(struct socket *so)
696{
697 struct inpcb *inp;
698
699 inp = sotoinpcb(so);
700 KASSERT(inp != NULL, ("rip6_disconnect: inp == NULL"));
701
702 if ((so->so_state & SS_ISCONNECTED) == 0)
703 return (ENOTCONN);
704 inp->in6p_faddr = in6addr_any;
705 rip6_abort(so);
706 return (0);
707}
708
709static int
710rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
711{
712 INIT_VNET_NET(so->so_vnet);
713 INIT_VNET_INET(so->so_vnet);
714 INIT_VNET_INET6(so->so_vnet);
715 struct inpcb *inp;
716 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
717 struct ifaddr *ia = NULL;
718 int error = 0;
719
720 inp = sotoinpcb(so);
721 KASSERT(inp != NULL, ("rip6_bind: inp == NULL"));
722
723 if (nam->sa_len != sizeof(*addr))
724 return (EINVAL);
725 if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0)
726 return (error);
727 if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6)
728 return (EADDRNOTAVAIL);
729 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
730 return (error);
731
732 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
733 (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0)
734 return (EADDRNOTAVAIL);
735 if (ia &&
736 ((struct in6_ifaddr *)ia)->ia6_flags &
737 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
738 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
739 return (EADDRNOTAVAIL);
740 }
741 INP_INFO_WLOCK(&V_ripcbinfo);
742 INP_WLOCK(inp);
743 inp->in6p_laddr = addr->sin6_addr;
744 INP_WUNLOCK(inp);
745 INP_INFO_WUNLOCK(&V_ripcbinfo);
746 return (0);
747}
748
749static int
750rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
751{
752 INIT_VNET_NET(so->so_vnet);
753 INIT_VNET_INET(so->so_vnet);
754 INIT_VNET_INET6(so->so_vnet);
755 struct inpcb *inp;
756 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
757 struct in6_addr *in6a = NULL;
758 struct ifnet *ifp = NULL;
759 int error = 0, scope_ambiguous = 0;
760
761 inp = sotoinpcb(so);
762 KASSERT(inp != NULL, ("rip6_connect: inp == NULL"));
763
764 if (nam->sa_len != sizeof(*addr))
765 return (EINVAL);
766 if (TAILQ_EMPTY(&V_ifnet))
767 return (EADDRNOTAVAIL);
768 if (addr->sin6_family != AF_INET6)
769 return (EAFNOSUPPORT);
770
771 /*
772 * Application should provide a proper zone ID or the use of default
773 * zone IDs should be enabled. Unfortunately, some applications do
774 * not behave as it should, so we need a workaround. Even if an
775 * appropriate ID is not determined, we'll see if we can determine
776 * the outgoing interface. If we can, determine the zone ID based on
777 * the interface below.
778 */
779 if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone)
780 scope_ambiguous = 1;
781 if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
782 return (error);
783
784 INP_INFO_WLOCK(&V_ripcbinfo);
785 INP_WLOCK(inp);
786 /* Source address selection. XXX: need pcblookup? */
787 in6a = in6_selectsrc(addr, inp->in6p_outputopts,
788 inp, NULL, so->so_cred,
789 &ifp, &error);
790 if (in6a == NULL) {
791 INP_WUNLOCK(inp);
792 INP_INFO_WUNLOCK(&V_ripcbinfo);
793 return (error ? error : EADDRNOTAVAIL);
794 }
795
796 /* XXX: see above */
797 if (ifp && scope_ambiguous &&
798 (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
799 INP_WUNLOCK(inp);
800 INP_INFO_WUNLOCK(&V_ripcbinfo);
801 return (error);
802 }
803 inp->in6p_faddr = addr->sin6_addr;
804 inp->in6p_laddr = *in6a;
805 soisconnected(so);
806 INP_WUNLOCK(inp);
807 INP_INFO_WUNLOCK(&V_ripcbinfo);
808 return (0);
809}
810
811static int
812rip6_shutdown(struct socket *so)
813{
814 struct inpcb *inp;
815
816 inp = sotoinpcb(so);
817 KASSERT(inp != NULL, ("rip6_shutdown: inp == NULL"));
818
819 INP_WLOCK(inp);
820 socantsendmore(so);
821 INP_WUNLOCK(inp);
822 return (0);
823}
824
825static int
826rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
827 struct mbuf *control, struct thread *td)
828{
829 struct inpcb *inp;
830 struct sockaddr_in6 tmp;
831 struct sockaddr_in6 *dst;
832 int ret;
833
834 inp = sotoinpcb(so);
835 KASSERT(inp != NULL, ("rip6_send: inp == NULL"));
836
837 /* Always copy sockaddr to avoid overwrites. */
838 /* Unlocked read. */
839 if (so->so_state & SS_ISCONNECTED) {
840 if (nam) {
841 m_freem(m);
842 return (EISCONN);
843 }
844 /* XXX */
845 bzero(&tmp, sizeof(tmp));
846 tmp.sin6_family = AF_INET6;
847 tmp.sin6_len = sizeof(struct sockaddr_in6);
848 INP_RLOCK(inp);
849 bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
850 sizeof(struct in6_addr));
851 INP_RUNLOCK(inp);
852 dst = &tmp;
853 } else {
854 if (nam == NULL) {
855 m_freem(m);
856 return (ENOTCONN);
857 }
858 if (nam->sa_len != sizeof(struct sockaddr_in6)) {
859 m_freem(m);
860 return (EINVAL);
861 }
862 tmp = *(struct sockaddr_in6 *)nam;
863 dst = &tmp;
864
865 if (dst->sin6_family == AF_UNSPEC) {
866 /*
867 * XXX: we allow this case for backward
868 * compatibility to buggy applications that
869 * rely on old (and wrong) kernel behavior.
870 */
871 log(LOG_INFO, "rip6 SEND: address family is "
872 "unspec. Assume AF_INET6\n");
873 dst->sin6_family = AF_INET6;
874 } else if (dst->sin6_family != AF_INET6) {
875 m_freem(m);
876 return(EAFNOSUPPORT);
877 }
878 }
879 ret = rip6_output(m, so, dst, control);
880 return (ret);
881}
882
883struct pr_usrreqs rip6_usrreqs = {
884 .pru_abort = rip6_abort,
885 .pru_attach = rip6_attach,
886 .pru_bind = rip6_bind,
887 .pru_connect = rip6_connect,
888 .pru_control = in6_control,
889 .pru_detach = rip6_detach,
890 .pru_disconnect = rip6_disconnect,
891 .pru_peeraddr = in6_getpeeraddr,
892 .pru_send = rip6_send,
893 .pru_shutdown = rip6_shutdown,
894 .pru_sockaddr = in6_getsockaddr,
895 .pru_close = rip6_close,
896};