Line data Source code
1 : /* $OpenBSD: ip6_output.c,v 1.239 2018/08/28 15:15:02 mpi Exp $ */
2 : /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
3 :
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
12 : * notice, this list of conditions and the following disclaimer.
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : * 3. Neither the name of the project nor the names of its contributors
17 : * may be used to endorse or promote products derived from this software
18 : * without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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.
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
39 : * are met:
40 : * 1. Redistributions of source code must retain the above copyright
41 : * notice, this list of conditions and the following disclaimer.
42 : * 2. Redistributions in binary form must reproduce the above copyright
43 : * notice, this list of conditions and the following disclaimer in the
44 : * documentation and/or other materials provided with the distribution.
45 : * 3. Neither the name of the University nor the names of its contributors
46 : * may be used to endorse or promote products derived from this software
47 : * without specific prior written permission.
48 : *
49 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 : * SUCH DAMAGE.
60 : *
61 : * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
62 : */
63 :
64 : #include "pf.h"
65 :
66 : #include <sys/param.h>
67 : #include <sys/malloc.h>
68 : #include <sys/mbuf.h>
69 : #include <sys/errno.h>
70 : #include <sys/protosw.h>
71 : #include <sys/socket.h>
72 : #include <sys/socketvar.h>
73 : #include <sys/proc.h>
74 : #include <sys/systm.h>
75 :
76 : #include <net/if.h>
77 : #include <net/if_var.h>
78 : #include <net/if_enc.h>
79 : #include <net/route.h>
80 :
81 : #include <netinet/in.h>
82 : #include <netinet/ip.h>
83 : #include <netinet/in_pcb.h>
84 : #include <netinet/udp.h>
85 : #include <netinet/tcp.h>
86 :
87 : #include <netinet/ip_var.h>
88 : #include <netinet/tcp_timer.h>
89 : #include <netinet/tcp_var.h>
90 : #include <netinet/udp_var.h>
91 :
92 : #include <netinet6/in6_var.h>
93 : #include <netinet/ip6.h>
94 : #include <netinet/icmp6.h>
95 : #include <netinet6/ip6_var.h>
96 : #include <netinet6/nd6.h>
97 : #include <netinet6/ip6protosw.h>
98 :
99 : #include <crypto/idgen.h>
100 :
101 : #if NPF > 0
102 : #include <net/pfvar.h>
103 : #endif
104 :
105 : #ifdef IPSEC
106 : #include <netinet/ip_ipsp.h>
107 : #include <netinet/ip_ah.h>
108 : #include <netinet/ip_esp.h>
109 : #endif /* IPSEC */
110 :
111 : struct ip6_exthdrs {
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;
117 : };
118 :
119 : int ip6_pcbopt(int, u_char *, int, struct ip6_pktopts **, int, int);
120 : int ip6_getpcbopt(struct ip6_pktopts *, int, struct mbuf *);
121 : int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *, int, int, int);
122 : int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *, unsigned int);
123 : int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf *);
124 : int ip6_copyexthdr(struct mbuf **, caddr_t, int);
125 : int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,
126 : struct ip6_frag **);
127 : int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
128 : int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
129 : int ip6_getpmtu(struct rtentry *, struct ifnet *, u_long *);
130 : int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *);
131 : static __inline u_int16_t __attribute__((__unused__))
132 : in6_cksum_phdr(const struct in6_addr *, const struct in6_addr *,
133 : u_int32_t, u_int32_t);
134 : void in6_delayed_cksum(struct mbuf *, u_int8_t);
135 :
136 : /* Context for non-repeating IDs */
137 : struct idgen32_ctx ip6_id_ctx;
138 :
139 : /*
140 : * IP6 output. The packet in mbuf chain m contains a skeletal IP6
141 : * header (with pri, len, nxt, hlim, src, dst).
142 : * This function may modify ver and hlim only.
143 : * The mbuf chain containing the packet will be freed.
144 : * The mbuf opt, if present, will not be freed.
145 : *
146 : * type of "mtu": rt_mtu is u_long, ifnet.ifr_mtu is int, and
147 : * nd_ifinfo.linkmtu is u_int32_t. so we use u_long to hold largest one,
148 : * which is rt_mtu.
149 : */
150 : int
151 0 : ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro,
152 : int flags, struct ip6_moptions *im6o, struct inpcb *inp)
153 : {
154 : struct ip6_hdr *ip6;
155 : struct ifnet *ifp = NULL;
156 0 : struct mbuf *m = m0;
157 : int hlen, tlen;
158 0 : struct route_in6 ip6route;
159 : struct rtentry *rt = NULL;
160 0 : struct sockaddr_in6 *dst, dstsock;
161 0 : int error = 0;
162 0 : u_long mtu;
163 : int dontfrag;
164 : u_int16_t src_scope, dst_scope;
165 : u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
166 0 : struct ip6_exthdrs exthdrs;
167 0 : struct in6_addr finaldst;
168 : struct route_in6 *ro_pmtu = NULL;
169 : int hdrsplit = 0;
170 : u_int8_t sproto = 0;
171 : #ifdef IPSEC
172 : struct tdb *tdb = NULL;
173 : #endif /* IPSEC */
174 :
175 : #ifdef IPSEC
176 0 : if (inp && (inp->inp_flags & INP_IPV6) == 0)
177 0 : panic("ip6_output: IPv4 pcb is passed");
178 : #endif /* IPSEC */
179 :
180 0 : ip6 = mtod(m, struct ip6_hdr *);
181 0 : finaldst = ip6->ip6_dst;
182 :
183 : #define MAKE_EXTHDR(hp, mp) \
184 : do { \
185 : if (hp) { \
186 : struct ip6_ext *eh = (struct ip6_ext *)(hp); \
187 : error = ip6_copyexthdr((mp), (caddr_t)(hp), \
188 : ((eh)->ip6e_len + 1) << 3); \
189 : if (error) \
190 : goto freehdrs; \
191 : } \
192 : } while (0)
193 :
194 0 : bzero(&exthdrs, sizeof(exthdrs));
195 :
196 0 : if (opt) {
197 : /* Hop-by-Hop options header */
198 0 : MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
199 : /* Destination options header(1st part) */
200 0 : MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
201 : /* Routing header */
202 0 : MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
203 : /* Destination options header(2nd part) */
204 0 : MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
205 : }
206 :
207 : #ifdef IPSEC
208 0 : if (ipsec_in_use || inp) {
209 0 : tdb = ip6_output_ipsec_lookup(m, &error, inp);
210 0 : if (error != 0) {
211 : /*
212 : * -EINVAL is used to indicate that the packet should
213 : * be silently dropped, typically because we've asked
214 : * key management for an SA.
215 : */
216 0 : if (error == -EINVAL) /* Should silently drop packet */
217 0 : error = 0;
218 :
219 : goto freehdrs;
220 : }
221 : }
222 : #endif /* IPSEC */
223 :
224 : /*
225 : * Calculate the total length of the extension header chain.
226 : * Keep the length of the unfragmentable part for fragmentation.
227 : */
228 : optlen = 0;
229 0 : if (exthdrs.ip6e_hbh) optlen += exthdrs.ip6e_hbh->m_len;
230 0 : if (exthdrs.ip6e_dest1) optlen += exthdrs.ip6e_dest1->m_len;
231 0 : if (exthdrs.ip6e_rthdr) optlen += exthdrs.ip6e_rthdr->m_len;
232 0 : unfragpartlen = optlen + sizeof(struct ip6_hdr);
233 : /* NOTE: we don't add AH/ESP length here. do that later. */
234 0 : if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len;
235 :
236 : /*
237 : * If we need IPsec, or there is at least one extension header,
238 : * separate IP6 header from the payload.
239 : */
240 0 : if ((sproto || optlen) && !hdrsplit) {
241 0 : if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
242 0 : m = NULL;
243 0 : goto freehdrs;
244 : }
245 0 : m = exthdrs.ip6e_ip6;
246 : hdrsplit++;
247 0 : }
248 :
249 : /* adjust pointer */
250 0 : ip6 = mtod(m, struct ip6_hdr *);
251 :
252 : /* adjust mbuf packet header length */
253 0 : m->m_pkthdr.len += optlen;
254 0 : plen = m->m_pkthdr.len - sizeof(*ip6);
255 :
256 : /* If this is a jumbo payload, insert a jumbo payload option. */
257 0 : if (plen > IPV6_MAXPACKET) {
258 0 : if (!hdrsplit) {
259 0 : if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
260 0 : m = NULL;
261 0 : goto freehdrs;
262 : }
263 0 : m = exthdrs.ip6e_ip6;
264 0 : hdrsplit++;
265 0 : }
266 : /* adjust pointer */
267 0 : ip6 = mtod(m, struct ip6_hdr *);
268 0 : if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
269 : goto freehdrs;
270 0 : ip6->ip6_plen = 0;
271 0 : } else
272 0 : ip6->ip6_plen = htons(plen);
273 :
274 : /*
275 : * Concatenate headers and fill in next header fields.
276 : * Here we have, on "m"
277 : * IPv6 payload
278 : * and we insert headers accordingly. Finally, we should be getting:
279 : * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
280 : *
281 : * during the header composing process, "m" points to IPv6 header.
282 : * "mprev" points to an extension header prior to esp.
283 : */
284 : {
285 0 : u_char *nexthdrp = &ip6->ip6_nxt;
286 0 : struct mbuf *mprev = m;
287 :
288 : /*
289 : * we treat dest2 specially. this makes IPsec processing
290 : * much easier. the goal here is to make mprev point the
291 : * mbuf prior to dest2.
292 : *
293 : * result: IPv6 dest2 payload
294 : * m and mprev will point to IPv6 header.
295 : */
296 0 : if (exthdrs.ip6e_dest2) {
297 0 : if (!hdrsplit)
298 0 : panic("assumption failed: hdr not split");
299 0 : exthdrs.ip6e_dest2->m_next = m->m_next;
300 0 : m->m_next = exthdrs.ip6e_dest2;
301 0 : *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
302 0 : ip6->ip6_nxt = IPPROTO_DSTOPTS;
303 0 : }
304 :
305 : #define MAKE_CHAIN(m, mp, p, i)\
306 : do {\
307 : if (m) {\
308 : if (!hdrsplit) \
309 : panic("assumption failed: hdr not split"); \
310 : *mtod((m), u_char *) = *(p);\
311 : *(p) = (i);\
312 : p = mtod((m), u_char *);\
313 : (m)->m_next = (mp)->m_next;\
314 : (mp)->m_next = (m);\
315 : (mp) = (m);\
316 : }\
317 : } while (0)
318 : /*
319 : * result: IPv6 hbh dest1 rthdr dest2 payload
320 : * m will point to IPv6 header. mprev will point to the
321 : * extension header prior to dest2 (rthdr in the above case).
322 : */
323 0 : MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS);
324 0 : MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp,
325 : IPPROTO_DSTOPTS);
326 0 : MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
327 : IPPROTO_ROUTING);
328 : }
329 :
330 : /*
331 : * If there is a routing header, replace the destination address field
332 : * with the first hop of the routing header.
333 : */
334 0 : if (exthdrs.ip6e_rthdr) {
335 : struct ip6_rthdr *rh;
336 : struct ip6_rthdr0 *rh0;
337 : struct in6_addr *addr;
338 :
339 0 : rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
340 : struct ip6_rthdr *));
341 0 : switch (rh->ip6r_type) {
342 : case IPV6_RTHDR_TYPE_0:
343 0 : rh0 = (struct ip6_rthdr0 *)rh;
344 0 : addr = (struct in6_addr *)(rh0 + 1);
345 0 : ip6->ip6_dst = addr[0];
346 0 : bcopy(&addr[1], &addr[0],
347 0 : sizeof(struct in6_addr) * (rh0->ip6r0_segleft - 1));
348 0 : addr[rh0->ip6r0_segleft - 1] = finaldst;
349 : break;
350 : default: /* is it possible? */
351 0 : error = EINVAL;
352 0 : goto bad;
353 : }
354 0 : }
355 :
356 : /* Source address validation */
357 0 : if (!(flags & IPV6_UNSPECSRC) &&
358 0 : IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
359 : /*
360 : * XXX: we can probably assume validation in the caller, but
361 : * we explicitly check the address here for safety.
362 : */
363 0 : error = EOPNOTSUPP;
364 0 : ip6stat_inc(ip6s_badscope);
365 0 : goto bad;
366 : }
367 0 : if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
368 0 : error = EOPNOTSUPP;
369 0 : ip6stat_inc(ip6s_badscope);
370 0 : goto bad;
371 : }
372 :
373 0 : ip6stat_inc(ip6s_localout);
374 :
375 : /*
376 : * Route packet.
377 : */
378 : #if NPF > 0
379 : reroute:
380 : #endif
381 :
382 : /* initialize cached route */
383 0 : if (ro == NULL) {
384 : ro = &ip6route;
385 0 : bzero((caddr_t)ro, sizeof(*ro));
386 0 : }
387 : ro_pmtu = ro;
388 0 : if (opt && opt->ip6po_rthdr)
389 0 : ro = &opt->ip6po_route;
390 0 : dst = &ro->ro_dst;
391 :
392 : /*
393 : * if specified, try to fill in the traffic class field.
394 : * do not override if a non-zero value is already set.
395 : * we check the diffserv field and the ecn field separately.
396 : */
397 0 : if (opt && opt->ip6po_tclass >= 0) {
398 : int mask = 0;
399 :
400 0 : if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0)
401 0 : mask |= 0xfc;
402 0 : if ((ip6->ip6_flow & htonl(0x03 << 20)) == 0)
403 0 : mask |= 0x03;
404 0 : if (mask != 0)
405 0 : ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20);
406 0 : }
407 :
408 : /* fill in or override the hop limit field, if necessary. */
409 0 : if (opt && opt->ip6po_hlim != -1)
410 0 : ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
411 0 : else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
412 0 : if (im6o != NULL)
413 0 : ip6->ip6_hlim = im6o->im6o_hlim;
414 : else
415 0 : ip6->ip6_hlim = ip6_defmcasthlim;
416 : }
417 :
418 : #ifdef IPSEC
419 0 : if (tdb) {
420 : /*
421 : * XXX what should we do if ip6_hlim == 0 and the
422 : * packet gets tunneled?
423 : */
424 : /*
425 : * if we are source-routing, do not attempt to tunnel the
426 : * packet just because ip6_dst is different from what tdb has.
427 : * XXX
428 : */
429 0 : error = ip6_output_ipsec_send(tdb, m,
430 0 : exthdrs.ip6e_rthdr ? 1 : 0, 0);
431 0 : goto done;
432 : }
433 : #endif /* IPSEC */
434 :
435 0 : bzero(&dstsock, sizeof(dstsock));
436 0 : dstsock.sin6_family = AF_INET6;
437 0 : dstsock.sin6_addr = ip6->ip6_dst;
438 0 : dstsock.sin6_len = sizeof(dstsock);
439 0 : ro->ro_tableid = m->m_pkthdr.ph_rtableid;
440 :
441 0 : if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)) {
442 : struct in6_pktinfo *pi = NULL;
443 :
444 : /*
445 : * If the caller specify the outgoing interface
446 : * explicitly, use it.
447 : */
448 0 : if (opt != NULL && (pi = opt->ip6po_pktinfo) != NULL)
449 0 : ifp = if_get(pi->ipi6_ifindex);
450 :
451 0 : if (ifp == NULL && im6o != NULL)
452 0 : ifp = if_get(im6o->im6o_ifidx);
453 0 : }
454 :
455 0 : if (ifp == NULL) {
456 0 : rt = in6_selectroute(&dstsock, opt, ro, ro->ro_tableid);
457 0 : if (rt == NULL) {
458 0 : ip6stat_inc(ip6s_noroute);
459 0 : error = EHOSTUNREACH;
460 0 : goto bad;
461 : }
462 0 : if (ISSET(rt->rt_flags, RTF_LOCAL))
463 0 : ifp = if_get(rtable_loindex(m->m_pkthdr.ph_rtableid));
464 : else
465 0 : ifp = if_get(rt->rt_ifidx);
466 : /*
467 : * We aren't using rtisvalid() here because the UP/DOWN state
468 : * machine is broken with some Ethernet drivers like em(4).
469 : * As a result we might try to use an invalid cached route
470 : * entry while an interface is being detached.
471 : */
472 0 : if (ifp == NULL) {
473 0 : ip6stat_inc(ip6s_noroute);
474 0 : error = EHOSTUNREACH;
475 0 : goto bad;
476 : }
477 : } else {
478 0 : *dst = dstsock;
479 : }
480 :
481 0 : if (rt && (rt->rt_flags & RTF_GATEWAY) &&
482 0 : !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
483 0 : dst = satosin6(rt->rt_gateway);
484 :
485 0 : if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
486 : /* Unicast */
487 :
488 0 : m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
489 0 : } else {
490 : /* Multicast */
491 :
492 0 : m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
493 :
494 : /*
495 : * Confirm that the outgoing interface supports multicast.
496 : */
497 0 : if ((ifp->if_flags & IFF_MULTICAST) == 0) {
498 0 : ip6stat_inc(ip6s_noroute);
499 0 : error = ENETUNREACH;
500 0 : goto bad;
501 : }
502 :
503 0 : if ((im6o == NULL || im6o->im6o_loop) &&
504 0 : in6_hasmulti(&ip6->ip6_dst, ifp)) {
505 : /*
506 : * If we belong to the destination multicast group
507 : * on the outgoing interface, and the caller did not
508 : * forbid loopback, loop back a copy.
509 : * Can't defer TCP/UDP checksumming, do the
510 : * computation now.
511 : */
512 0 : in6_proto_cksum_out(m, NULL);
513 0 : ip6_mloopback(ifp, m, dst);
514 0 : }
515 : #ifdef MROUTING
516 : else {
517 : /*
518 : * If we are acting as a multicast router, perform
519 : * multicast forwarding as if the packet had just
520 : * arrived on the interface to which we are about
521 : * to send. The multicast forwarding function
522 : * recursively calls this function, using the
523 : * IPV6_FORWARDING flag to prevent infinite recursion.
524 : *
525 : * Multicasts that are looped back by ip6_mloopback(),
526 : * above, will be forwarded by the ip6_input() routine,
527 : * if necessary.
528 : */
529 0 : if (ip6_mforwarding && ip6_mrouter[ifp->if_rdomain] &&
530 0 : (flags & IPV6_FORWARDING) == 0) {
531 0 : if (ip6_mforward(ip6, ifp, m) != 0) {
532 0 : m_freem(m);
533 0 : goto done;
534 : }
535 : }
536 : }
537 : #endif
538 : /*
539 : * Multicasts with a hoplimit of zero may be looped back,
540 : * above, but must not be transmitted on a network.
541 : * Also, multicasts addressed to the loopback interface
542 : * are not sent -- the above call to ip6_mloopback() will
543 : * loop back a copy if this host actually belongs to the
544 : * destination group on the loopback interface.
545 : */
546 0 : if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) ||
547 0 : IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) {
548 0 : m_freem(m);
549 0 : goto done;
550 : }
551 : }
552 :
553 : /*
554 : * If this packet is going trough a loopback interface we wont
555 : * be able to restore its scope ID using the interface index.
556 : */
557 0 : if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) {
558 0 : if (ifp->if_flags & IFF_LOOPBACK)
559 0 : src_scope = ip6->ip6_src.s6_addr16[1];
560 0 : ip6->ip6_src.s6_addr16[1] = 0;
561 0 : }
562 0 : if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) {
563 0 : if (ifp->if_flags & IFF_LOOPBACK)
564 0 : dst_scope = ip6->ip6_dst.s6_addr16[1];
565 0 : ip6->ip6_dst.s6_addr16[1] = 0;
566 0 : }
567 :
568 : /* Determine path MTU. */
569 0 : if ((error = ip6_getpmtu(ro_pmtu->ro_rt, ifp, &mtu)) != 0)
570 : goto bad;
571 :
572 : /*
573 : * The caller of this function may specify to use the minimum MTU
574 : * in some cases.
575 : * An advanced API option (IPV6_USE_MIN_MTU) can also override MTU
576 : * setting. The logic is a bit complicated; by default, unicast
577 : * packets will follow path MTU while multicast packets will be sent at
578 : * the minimum MTU. If IP6PO_MINMTU_ALL is specified, all packets
579 : * including unicast ones will be sent at the minimum MTU. Multicast
580 : * packets will always be sent at the minimum MTU unless
581 : * IP6PO_MINMTU_DISABLE is explicitly specified.
582 : * See RFC 3542 for more details.
583 : */
584 0 : if (mtu > IPV6_MMTU) {
585 0 : if ((flags & IPV6_MINMTU))
586 0 : mtu = IPV6_MMTU;
587 0 : else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
588 0 : mtu = IPV6_MMTU;
589 0 : else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
590 0 : (opt == NULL ||
591 0 : opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) {
592 0 : mtu = IPV6_MMTU;
593 0 : }
594 : }
595 :
596 : /*
597 : * If the outgoing packet contains a hop-by-hop options header,
598 : * it must be examined and processed even by the source node.
599 : * (RFC 2460, section 4.)
600 : */
601 0 : if (exthdrs.ip6e_hbh) {
602 0 : struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *);
603 0 : u_int32_t dummy1; /* XXX unused */
604 0 : u_int32_t dummy2; /* XXX unused */
605 :
606 0 : m->m_pkthdr.ph_ifidx = ifp->if_index;
607 0 : if (ip6_process_hopopts(m, (u_int8_t *)(hbh + 1),
608 0 : ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh),
609 0 : &dummy1, &dummy2) < 0) {
610 : /* m was already freed at this point */
611 0 : error = EINVAL;/* better error? */
612 0 : goto done;
613 : }
614 0 : m->m_pkthdr.ph_ifidx = 0;
615 0 : }
616 :
617 : #if NPF > 0
618 0 : if (pf_test(AF_INET6, PF_OUT, ifp, &m) != PF_PASS) {
619 0 : error = EHOSTUNREACH;
620 0 : m_freem(m);
621 0 : goto done;
622 : }
623 0 : if (m == NULL)
624 : goto done;
625 0 : ip6 = mtod(m, struct ip6_hdr *);
626 0 : if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) ==
627 : (PF_TAG_REROUTE | PF_TAG_GENERATED)) {
628 : /* already rerun the route lookup, go on */
629 0 : m->m_pkthdr.pf.flags &= ~(PF_TAG_GENERATED | PF_TAG_REROUTE);
630 0 : } else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) {
631 : /* tag as generated to skip over pf_test on rerun */
632 0 : m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
633 0 : finaldst = ip6->ip6_dst;
634 : ro = NULL;
635 0 : if_put(ifp); /* drop reference since destination changed */
636 : ifp = NULL;
637 0 : goto reroute;
638 : }
639 : #endif
640 :
641 : /*
642 : * If the packet is not going on the wire it can be destinated
643 : * to any local address. In this case do not clear its scopes
644 : * to let ip6_input() find a matching local route.
645 : */
646 0 : if (ifp->if_flags & IFF_LOOPBACK) {
647 0 : if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
648 0 : ip6->ip6_src.s6_addr16[1] = src_scope;
649 0 : if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
650 0 : ip6->ip6_dst.s6_addr16[1] = dst_scope;
651 : }
652 :
653 0 : in6_proto_cksum_out(m, ifp);
654 :
655 : /*
656 : * Send the packet to the outgoing interface.
657 : * If necessary, do IPv6 fragmentation before sending.
658 : *
659 : * the logic here is rather complex:
660 : * 1: normal case (dontfrag == 0)
661 : * 1-a: send as is if tlen <= path mtu
662 : * 1-b: fragment if tlen > path mtu
663 : *
664 : * 2: if user asks us not to fragment (dontfrag == 1)
665 : * 2-a: send as is if tlen <= interface mtu
666 : * 2-b: error if tlen > interface mtu
667 : */
668 0 : tlen = m->m_pkthdr.len;
669 :
670 0 : if (ISSET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)) {
671 0 : CLR(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT);
672 : dontfrag = 1;
673 0 : } else if (opt && ISSET(opt->ip6po_flags, IP6PO_DONTFRAG))
674 0 : dontfrag = 1;
675 : else
676 : dontfrag = 0;
677 0 : if (dontfrag && tlen > ifp->if_mtu) { /* case 2-b */
678 0 : error = EMSGSIZE;
679 0 : goto bad;
680 : }
681 :
682 : /*
683 : * transmit packet without fragmentation
684 : */
685 0 : if (dontfrag || (tlen <= mtu)) { /* case 1-a and 2-a */
686 0 : error = ifp->if_output(ifp, m, sin6tosa(dst), ro->ro_rt);
687 0 : goto done;
688 : }
689 :
690 : /*
691 : * try to fragment the packet. case 1-b
692 : */
693 0 : if (mtu < IPV6_MMTU) {
694 : /* path MTU cannot be less than IPV6_MMTU */
695 0 : error = EMSGSIZE;
696 0 : goto bad;
697 0 : } else if (ip6->ip6_plen == 0) {
698 : /* jumbo payload cannot be fragmented */
699 0 : error = EMSGSIZE;
700 0 : goto bad;
701 : } else {
702 : u_char nextproto;
703 : #if 0
704 : struct ip6ctlparam ip6cp;
705 : u_int32_t mtu32;
706 : #endif
707 :
708 : /*
709 : * Too large for the destination or interface;
710 : * fragment if possible.
711 : * Must be able to put at least 8 bytes per fragment.
712 : */
713 : hlen = unfragpartlen;
714 0 : if (mtu > IPV6_MAXPACKET)
715 0 : mtu = IPV6_MAXPACKET;
716 :
717 : /*
718 : * Change the next header field of the last header in the
719 : * unfragmentable part.
720 : */
721 0 : if (exthdrs.ip6e_rthdr) {
722 0 : nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
723 0 : *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
724 0 : } else if (exthdrs.ip6e_dest1) {
725 0 : nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
726 0 : *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
727 0 : } else if (exthdrs.ip6e_hbh) {
728 0 : nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
729 0 : *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
730 0 : } else {
731 0 : nextproto = ip6->ip6_nxt;
732 0 : ip6->ip6_nxt = IPPROTO_FRAGMENT;
733 : }
734 :
735 0 : m0 = m;
736 0 : error = ip6_fragment(m0, hlen, nextproto, mtu);
737 0 : if (error)
738 0 : ip6stat_inc(ip6s_odropped);
739 : }
740 :
741 : /*
742 : * Remove leading garbages.
743 : */
744 0 : m = m0->m_nextpkt;
745 0 : m0->m_nextpkt = 0;
746 0 : m_freem(m0);
747 0 : for (m0 = m; m; m = m0) {
748 0 : m0 = m->m_nextpkt;
749 0 : m->m_nextpkt = 0;
750 0 : if (error == 0) {
751 0 : ip6stat_inc(ip6s_ofragments);
752 0 : error = ifp->if_output(ifp, m, sin6tosa(dst),
753 0 : ro->ro_rt);
754 0 : } else
755 0 : m_freem(m);
756 : }
757 :
758 0 : if (error == 0)
759 0 : ip6stat_inc(ip6s_fragmented);
760 :
761 : done:
762 0 : if_put(ifp);
763 0 : if (ro == &ip6route && ro->ro_rt) {
764 0 : rtfree(ro->ro_rt);
765 0 : } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
766 0 : rtfree(ro_pmtu->ro_rt);
767 0 : }
768 :
769 0 : return (error);
770 :
771 : freehdrs:
772 0 : m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */
773 0 : m_freem(exthdrs.ip6e_dest1);
774 0 : m_freem(exthdrs.ip6e_rthdr);
775 0 : m_freem(exthdrs.ip6e_dest2);
776 : /* FALLTHROUGH */
777 : bad:
778 0 : m_freem(m);
779 0 : goto done;
780 0 : }
781 :
782 : int
783 0 : ip6_fragment(struct mbuf *m0, int hlen, u_char nextproto, u_long mtu)
784 : {
785 : struct mbuf *m, **mnext, *m_frgpart;
786 : struct ip6_hdr *mhip6;
787 0 : struct ip6_frag *ip6f;
788 : u_int32_t id;
789 : int tlen, len, off;
790 : int error;
791 :
792 0 : id = htonl(ip6_randomid());
793 :
794 0 : mnext = &m0->m_nextpkt;
795 0 : *mnext = NULL;
796 :
797 0 : tlen = m0->m_pkthdr.len;
798 0 : len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
799 0 : if (len < 8)
800 0 : return (EMSGSIZE);
801 :
802 : /*
803 : * Loop through length of segment after first fragment,
804 : * make new header and copy data of each part and link onto
805 : * chain.
806 : */
807 0 : for (off = hlen; off < tlen; off += len) {
808 : struct mbuf *mlast;
809 :
810 0 : if ((m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL)
811 0 : return (ENOBUFS);
812 0 : *mnext = m;
813 0 : mnext = &m->m_nextpkt;
814 0 : if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0)
815 0 : return (error);
816 0 : m->m_data += max_linkhdr;
817 0 : mhip6 = mtod(m, struct ip6_hdr *);
818 0 : *mhip6 = *mtod(m0, struct ip6_hdr *);
819 0 : m->m_len = sizeof(*mhip6);
820 0 : if ((error = ip6_insertfraghdr(m0, m, hlen, &ip6f)) != 0)
821 0 : return (error);
822 0 : ip6f->ip6f_offlg = htons((u_int16_t)((off - hlen) & ~7));
823 0 : if (off + len >= tlen)
824 0 : len = tlen - off;
825 : else
826 0 : ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
827 0 : mhip6->ip6_plen = htons((u_int16_t)(len + hlen +
828 : sizeof(*ip6f) - sizeof(struct ip6_hdr)));
829 0 : if ((m_frgpart = m_copym(m0, off, len, M_DONTWAIT)) == NULL)
830 0 : return (ENOBUFS);
831 0 : for (mlast = m; mlast->m_next; mlast = mlast->m_next)
832 : ;
833 0 : mlast->m_next = m_frgpart;
834 0 : m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
835 0 : ip6f->ip6f_reserved = 0;
836 0 : ip6f->ip6f_ident = id;
837 0 : ip6f->ip6f_nxt = nextproto;
838 0 : }
839 :
840 0 : return (0);
841 0 : }
842 :
843 : int
844 0 : ip6_copyexthdr(struct mbuf **mp, caddr_t hdr, int hlen)
845 : {
846 : struct mbuf *m;
847 :
848 0 : if (hlen > MCLBYTES)
849 0 : return (ENOBUFS); /* XXX */
850 :
851 0 : MGET(m, M_DONTWAIT, MT_DATA);
852 0 : if (!m)
853 0 : return (ENOBUFS);
854 :
855 0 : if (hlen > MLEN) {
856 0 : MCLGET(m, M_DONTWAIT);
857 0 : if ((m->m_flags & M_EXT) == 0) {
858 0 : m_free(m);
859 0 : return (ENOBUFS);
860 : }
861 : }
862 0 : m->m_len = hlen;
863 0 : if (hdr)
864 0 : memcpy(mtod(m, caddr_t), hdr, hlen);
865 :
866 0 : *mp = m;
867 0 : return (0);
868 0 : }
869 :
870 : /*
871 : * Insert jumbo payload option.
872 : */
873 : int
874 0 : ip6_insert_jumboopt(struct ip6_exthdrs *exthdrs, u_int32_t plen)
875 : {
876 : struct mbuf *mopt;
877 : u_int8_t *optbuf;
878 : u_int32_t v;
879 :
880 : #define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */
881 :
882 : /*
883 : * If there is no hop-by-hop options header, allocate new one.
884 : * If there is one but it doesn't have enough space to store the
885 : * jumbo payload option, allocate a cluster to store the whole options.
886 : * Otherwise, use it to store the options.
887 : */
888 0 : if (exthdrs->ip6e_hbh == 0) {
889 0 : MGET(mopt, M_DONTWAIT, MT_DATA);
890 0 : if (mopt == NULL)
891 0 : return (ENOBUFS);
892 0 : mopt->m_len = JUMBOOPTLEN;
893 0 : optbuf = mtod(mopt, u_int8_t *);
894 0 : optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
895 0 : exthdrs->ip6e_hbh = mopt;
896 0 : } else {
897 : struct ip6_hbh *hbh;
898 :
899 : mopt = exthdrs->ip6e_hbh;
900 0 : if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) {
901 : /*
902 : * XXX assumption:
903 : * - exthdrs->ip6e_hbh is not referenced from places
904 : * other than exthdrs.
905 : * - exthdrs->ip6e_hbh is not an mbuf chain.
906 : */
907 0 : int oldoptlen = mopt->m_len;
908 : struct mbuf *n;
909 :
910 : /*
911 : * XXX: give up if the whole (new) hbh header does
912 : * not fit even in an mbuf cluster.
913 : */
914 0 : if (oldoptlen + JUMBOOPTLEN > MCLBYTES)
915 0 : return (ENOBUFS);
916 :
917 : /*
918 : * As a consequence, we must always prepare a cluster
919 : * at this point.
920 : */
921 0 : MGET(n, M_DONTWAIT, MT_DATA);
922 0 : if (n) {
923 0 : MCLGET(n, M_DONTWAIT);
924 0 : if ((n->m_flags & M_EXT) == 0) {
925 0 : m_freem(n);
926 : n = NULL;
927 0 : }
928 : }
929 0 : if (!n)
930 0 : return (ENOBUFS);
931 0 : n->m_len = oldoptlen + JUMBOOPTLEN;
932 0 : memcpy(mtod(n, caddr_t), mtod(mopt, caddr_t),
933 : oldoptlen);
934 0 : optbuf = mtod(n, u_int8_t *) + oldoptlen;
935 0 : m_freem(mopt);
936 0 : mopt = exthdrs->ip6e_hbh = n;
937 0 : } else {
938 0 : optbuf = mtod(mopt, u_int8_t *) + mopt->m_len;
939 0 : mopt->m_len += JUMBOOPTLEN;
940 : }
941 0 : optbuf[0] = IP6OPT_PADN;
942 0 : optbuf[1] = 0;
943 :
944 : /*
945 : * Adjust the header length according to the pad and
946 : * the jumbo payload option.
947 : */
948 0 : hbh = mtod(mopt, struct ip6_hbh *);
949 0 : hbh->ip6h_len += (JUMBOOPTLEN >> 3);
950 0 : }
951 :
952 : /* fill in the option. */
953 0 : optbuf[2] = IP6OPT_JUMBO;
954 0 : optbuf[3] = 4;
955 0 : v = (u_int32_t)htonl(plen + JUMBOOPTLEN);
956 0 : memcpy(&optbuf[4], &v, sizeof(u_int32_t));
957 :
958 : /* finally, adjust the packet header length */
959 0 : exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
960 :
961 0 : return (0);
962 : #undef JUMBOOPTLEN
963 0 : }
964 :
965 : /*
966 : * Insert fragment header and copy unfragmentable header portions.
967 : */
968 : int
969 0 : ip6_insertfraghdr(struct mbuf *m0, struct mbuf *m, int hlen,
970 : struct ip6_frag **frghdrp)
971 : {
972 : struct mbuf *n, *mlast;
973 :
974 0 : if (hlen > sizeof(struct ip6_hdr)) {
975 0 : n = m_copym(m0, sizeof(struct ip6_hdr),
976 0 : hlen - sizeof(struct ip6_hdr), M_DONTWAIT);
977 0 : if (n == NULL)
978 0 : return (ENOBUFS);
979 0 : m->m_next = n;
980 0 : } else
981 : n = m;
982 :
983 : /* Search for the last mbuf of unfragmentable part. */
984 0 : for (mlast = n; mlast->m_next; mlast = mlast->m_next)
985 : ;
986 :
987 0 : if ((mlast->m_flags & M_EXT) == 0 &&
988 0 : M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
989 : /* use the trailing space of the last mbuf for the fragment hdr */
990 0 : *frghdrp = (struct ip6_frag *)(mtod(mlast, caddr_t) +
991 0 : mlast->m_len);
992 0 : mlast->m_len += sizeof(struct ip6_frag);
993 0 : m->m_pkthdr.len += sizeof(struct ip6_frag);
994 0 : } else {
995 : /* allocate a new mbuf for the fragment header */
996 : struct mbuf *mfrg;
997 :
998 0 : MGET(mfrg, M_DONTWAIT, MT_DATA);
999 0 : if (mfrg == NULL)
1000 0 : return (ENOBUFS);
1001 0 : mfrg->m_len = sizeof(struct ip6_frag);
1002 0 : *frghdrp = mtod(mfrg, struct ip6_frag *);
1003 0 : mlast->m_next = mfrg;
1004 0 : }
1005 :
1006 0 : return (0);
1007 0 : }
1008 :
1009 : int
1010 0 : ip6_getpmtu(struct rtentry *rt, struct ifnet *ifp, u_long *mtup)
1011 : {
1012 : u_int32_t mtu = 0;
1013 : int error = 0;
1014 :
1015 0 : if (rt != NULL) {
1016 0 : mtu = rt->rt_mtu;
1017 0 : if (mtu == 0)
1018 0 : mtu = ifp->if_mtu;
1019 0 : else if (mtu < IPV6_MMTU) {
1020 : /* RFC8021 IPv6 Atomic Fragments Considered Harmful */
1021 : mtu = IPV6_MMTU;
1022 0 : } else if (mtu > ifp->if_mtu) {
1023 : /*
1024 : * The MTU on the route is larger than the MTU on
1025 : * the interface! This shouldn't happen, unless the
1026 : * MTU of the interface has been changed after the
1027 : * interface was brought up. Change the MTU in the
1028 : * route to match the interface MTU (as long as the
1029 : * field isn't locked).
1030 : */
1031 : mtu = ifp->if_mtu;
1032 0 : if (!(rt->rt_locks & RTV_MTU))
1033 0 : rt->rt_mtu = mtu;
1034 : }
1035 : } else {
1036 0 : mtu = ifp->if_mtu;
1037 : }
1038 :
1039 0 : *mtup = mtu;
1040 0 : return (error);
1041 : }
1042 :
1043 : /*
1044 : * IP6 socket option processing.
1045 : */
1046 : int
1047 0 : ip6_ctloutput(int op, struct socket *so, int level, int optname,
1048 : struct mbuf *m)
1049 : {
1050 : int privileged, optdatalen, uproto;
1051 : void *optdata;
1052 0 : struct inpcb *inp = sotoinpcb(so);
1053 0 : int error, optval;
1054 0 : struct proc *p = curproc; /* For IPsec and rdomain */
1055 : u_int rtid = 0;
1056 :
1057 0 : error = optval = 0;
1058 :
1059 0 : privileged = (inp->inp_socket->so_state & SS_PRIV);
1060 0 : uproto = (int)so->so_proto->pr_protocol;
1061 :
1062 0 : if (level != IPPROTO_IPV6)
1063 0 : return (EINVAL);
1064 :
1065 0 : switch (op) {
1066 : case PRCO_SETOPT:
1067 0 : switch (optname) {
1068 : /*
1069 : * Use of some Hop-by-Hop options or some
1070 : * Destination options, might require special
1071 : * privilege. That is, normal applications
1072 : * (without special privilege) might be forbidden
1073 : * from setting certain options in outgoing packets,
1074 : * and might never see certain options in received
1075 : * packets. [RFC 2292 Section 6]
1076 : * KAME specific note:
1077 : * KAME prevents non-privileged users from sending or
1078 : * receiving ANY hbh/dst options in order to avoid
1079 : * overhead of parsing options in the kernel.
1080 : */
1081 : case IPV6_RECVHOPOPTS:
1082 : case IPV6_RECVDSTOPTS:
1083 0 : if (!privileged) {
1084 : error = EPERM;
1085 0 : break;
1086 : }
1087 : /* FALLTHROUGH */
1088 : case IPV6_UNICAST_HOPS:
1089 : case IPV6_MINHOPCOUNT:
1090 : case IPV6_HOPLIMIT:
1091 :
1092 : case IPV6_RECVPKTINFO:
1093 : case IPV6_RECVHOPLIMIT:
1094 : case IPV6_RECVRTHDR:
1095 : case IPV6_RECVPATHMTU:
1096 : case IPV6_RECVTCLASS:
1097 : case IPV6_V6ONLY:
1098 : case IPV6_AUTOFLOWLABEL:
1099 : case IPV6_RECVDSTPORT:
1100 0 : if (m == NULL || m->m_len != sizeof(int)) {
1101 : error = EINVAL;
1102 0 : break;
1103 : }
1104 0 : optval = *mtod(m, int *);
1105 0 : switch (optname) {
1106 :
1107 : case IPV6_UNICAST_HOPS:
1108 0 : if (optval < -1 || optval >= 256)
1109 0 : error = EINVAL;
1110 : else {
1111 : /* -1 = kernel default */
1112 0 : inp->inp_hops = optval;
1113 : }
1114 : break;
1115 :
1116 : case IPV6_MINHOPCOUNT:
1117 0 : if (optval < 0 || optval > 255)
1118 0 : error = EINVAL;
1119 : else
1120 0 : inp->inp_ip6_minhlim = optval;
1121 : break;
1122 :
1123 : #define OPTSET(bit) \
1124 : do { \
1125 : if (optval) \
1126 : inp->inp_flags |= (bit); \
1127 : else \
1128 : inp->inp_flags &= ~(bit); \
1129 : } while (/*CONSTCOND*/ 0)
1130 : #define OPTBIT(bit) (inp->inp_flags & (bit) ? 1 : 0)
1131 :
1132 : case IPV6_RECVPKTINFO:
1133 0 : OPTSET(IN6P_PKTINFO);
1134 : break;
1135 :
1136 : case IPV6_HOPLIMIT:
1137 : {
1138 : struct ip6_pktopts **optp;
1139 :
1140 0 : optp = &inp->inp_outputopts6;
1141 0 : error = ip6_pcbopt(IPV6_HOPLIMIT,
1142 : (u_char *)&optval,
1143 : sizeof(optval),
1144 : optp,
1145 : privileged, uproto);
1146 : break;
1147 : }
1148 :
1149 : case IPV6_RECVHOPLIMIT:
1150 0 : OPTSET(IN6P_HOPLIMIT);
1151 : break;
1152 :
1153 : case IPV6_RECVHOPOPTS:
1154 0 : OPTSET(IN6P_HOPOPTS);
1155 : break;
1156 :
1157 : case IPV6_RECVDSTOPTS:
1158 0 : OPTSET(IN6P_DSTOPTS);
1159 : break;
1160 :
1161 : case IPV6_RECVRTHDR:
1162 0 : OPTSET(IN6P_RTHDR);
1163 : break;
1164 :
1165 : case IPV6_RECVPATHMTU:
1166 : /*
1167 : * We ignore this option for TCP
1168 : * sockets.
1169 : * (RFC3542 leaves this case
1170 : * unspecified.)
1171 : */
1172 0 : if (uproto != IPPROTO_TCP)
1173 0 : OPTSET(IN6P_MTU);
1174 : break;
1175 :
1176 : case IPV6_V6ONLY:
1177 : /*
1178 : * make setsockopt(IPV6_V6ONLY)
1179 : * available only prior to bind(2).
1180 : * see ipng mailing list, Jun 22 2001.
1181 : */
1182 0 : if (inp->inp_lport ||
1183 0 : !IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) {
1184 : error = EINVAL;
1185 0 : break;
1186 : }
1187 : /* No support for IPv4-mapped addresses. */
1188 0 : if (!optval)
1189 0 : error = EINVAL;
1190 : else
1191 : error = 0;
1192 : break;
1193 : case IPV6_RECVTCLASS:
1194 0 : OPTSET(IN6P_TCLASS);
1195 : break;
1196 : case IPV6_AUTOFLOWLABEL:
1197 0 : OPTSET(IN6P_AUTOFLOWLABEL);
1198 : break;
1199 :
1200 : case IPV6_RECVDSTPORT:
1201 0 : OPTSET(IN6P_RECVDSTPORT);
1202 : break;
1203 : }
1204 : break;
1205 :
1206 : case IPV6_TCLASS:
1207 : case IPV6_DONTFRAG:
1208 : case IPV6_USE_MIN_MTU:
1209 0 : if (m == NULL || m->m_len != sizeof(optval)) {
1210 : error = EINVAL;
1211 0 : break;
1212 : }
1213 0 : optval = *mtod(m, int *);
1214 : {
1215 : struct ip6_pktopts **optp;
1216 0 : optp = &inp->inp_outputopts6;
1217 0 : error = ip6_pcbopt(optname,
1218 : (u_char *)&optval,
1219 : sizeof(optval),
1220 : optp,
1221 : privileged, uproto);
1222 : break;
1223 : }
1224 :
1225 : case IPV6_PKTINFO:
1226 : case IPV6_HOPOPTS:
1227 : case IPV6_RTHDR:
1228 : case IPV6_DSTOPTS:
1229 : case IPV6_RTHDRDSTOPTS:
1230 : {
1231 : /* new advanced API (RFC3542) */
1232 : u_char *optbuf;
1233 : int optbuflen;
1234 : struct ip6_pktopts **optp;
1235 :
1236 0 : if (m && m->m_next) {
1237 : error = EINVAL; /* XXX */
1238 0 : break;
1239 : }
1240 0 : if (m) {
1241 0 : optbuf = mtod(m, u_char *);
1242 0 : optbuflen = m->m_len;
1243 0 : } else {
1244 : optbuf = NULL;
1245 : optbuflen = 0;
1246 : }
1247 0 : optp = &inp->inp_outputopts6;
1248 0 : error = ip6_pcbopt(optname,
1249 : optbuf, optbuflen,
1250 : optp, privileged, uproto);
1251 0 : break;
1252 : }
1253 : #undef OPTSET
1254 :
1255 : case IPV6_MULTICAST_IF:
1256 : case IPV6_MULTICAST_HOPS:
1257 : case IPV6_MULTICAST_LOOP:
1258 : case IPV6_JOIN_GROUP:
1259 : case IPV6_LEAVE_GROUP:
1260 0 : error = ip6_setmoptions(optname,
1261 0 : &inp->inp_moptions6,
1262 0 : m, inp->inp_rtableid);
1263 0 : break;
1264 :
1265 : case IPV6_PORTRANGE:
1266 0 : if (m == NULL || m->m_len != sizeof(int)) {
1267 : error = EINVAL;
1268 0 : break;
1269 : }
1270 0 : optval = *mtod(m, int *);
1271 :
1272 0 : switch (optval) {
1273 : case IPV6_PORTRANGE_DEFAULT:
1274 0 : inp->inp_flags &= ~(IN6P_LOWPORT);
1275 0 : inp->inp_flags &= ~(IN6P_HIGHPORT);
1276 0 : break;
1277 :
1278 : case IPV6_PORTRANGE_HIGH:
1279 0 : inp->inp_flags &= ~(IN6P_LOWPORT);
1280 0 : inp->inp_flags |= IN6P_HIGHPORT;
1281 0 : break;
1282 :
1283 : case IPV6_PORTRANGE_LOW:
1284 0 : inp->inp_flags &= ~(IN6P_HIGHPORT);
1285 0 : inp->inp_flags |= IN6P_LOWPORT;
1286 0 : break;
1287 :
1288 : default:
1289 : error = EINVAL;
1290 0 : break;
1291 : }
1292 : break;
1293 :
1294 : case IPSEC6_OUTSA:
1295 : error = EINVAL;
1296 0 : break;
1297 :
1298 : case IPV6_AUTH_LEVEL:
1299 : case IPV6_ESP_TRANS_LEVEL:
1300 : case IPV6_ESP_NETWORK_LEVEL:
1301 : case IPV6_IPCOMP_LEVEL:
1302 : #ifndef IPSEC
1303 : error = EINVAL;
1304 : #else
1305 0 : if (m == NULL || m->m_len != sizeof(int)) {
1306 : error = EINVAL;
1307 0 : break;
1308 : }
1309 0 : optval = *mtod(m, int *);
1310 :
1311 0 : if (optval < IPSEC_LEVEL_BYPASS ||
1312 0 : optval > IPSEC_LEVEL_UNIQUE) {
1313 : error = EINVAL;
1314 0 : break;
1315 : }
1316 :
1317 0 : switch (optname) {
1318 : case IPV6_AUTH_LEVEL:
1319 0 : if (optval < IPSEC_AUTH_LEVEL_DEFAULT &&
1320 0 : suser(p)) {
1321 : error = EACCES;
1322 0 : break;
1323 : }
1324 0 : inp->inp_seclevel[SL_AUTH] = optval;
1325 0 : break;
1326 :
1327 : case IPV6_ESP_TRANS_LEVEL:
1328 0 : if (optval < IPSEC_ESP_TRANS_LEVEL_DEFAULT &&
1329 0 : suser(p)) {
1330 : error = EACCES;
1331 0 : break;
1332 : }
1333 0 : inp->inp_seclevel[SL_ESP_TRANS] = optval;
1334 0 : break;
1335 :
1336 : case IPV6_ESP_NETWORK_LEVEL:
1337 0 : if (optval < IPSEC_ESP_NETWORK_LEVEL_DEFAULT &&
1338 0 : suser(p)) {
1339 : error = EACCES;
1340 0 : break;
1341 : }
1342 0 : inp->inp_seclevel[SL_ESP_NETWORK] = optval;
1343 0 : break;
1344 :
1345 : case IPV6_IPCOMP_LEVEL:
1346 0 : if (optval < IPSEC_IPCOMP_LEVEL_DEFAULT &&
1347 0 : suser(p)) {
1348 : error = EACCES;
1349 0 : break;
1350 : }
1351 0 : inp->inp_seclevel[SL_IPCOMP] = optval;
1352 0 : break;
1353 : }
1354 : #endif
1355 : break;
1356 : case SO_RTABLE:
1357 0 : if (m == NULL || m->m_len < sizeof(u_int)) {
1358 : error = EINVAL;
1359 0 : break;
1360 : }
1361 0 : rtid = *mtod(m, u_int *);
1362 0 : if (inp->inp_rtableid == rtid)
1363 : break;
1364 : /* needs privileges to switch when already set */
1365 0 : if (p->p_p->ps_rtableid != rtid &&
1366 0 : p->p_p->ps_rtableid != 0 &&
1367 0 : (error = suser(p)) != 0)
1368 : break;
1369 : /* table must exist */
1370 0 : if (!rtable_exists(rtid)) {
1371 : error = EINVAL;
1372 0 : break;
1373 : }
1374 0 : if (inp->inp_lport) {
1375 : error = EBUSY;
1376 0 : break;
1377 : }
1378 0 : inp->inp_rtableid = rtid;
1379 0 : in_pcbrehash(inp);
1380 0 : break;
1381 : case IPV6_PIPEX:
1382 0 : if (m != NULL && m->m_len == sizeof(int))
1383 0 : inp->inp_pipex = *mtod(m, int *);
1384 : else
1385 : error = EINVAL;
1386 : break;
1387 :
1388 : default:
1389 : error = ENOPROTOOPT;
1390 0 : break;
1391 : }
1392 : break;
1393 :
1394 : case PRCO_GETOPT:
1395 0 : switch (optname) {
1396 :
1397 : case IPV6_RECVHOPOPTS:
1398 : case IPV6_RECVDSTOPTS:
1399 : case IPV6_UNICAST_HOPS:
1400 : case IPV6_MINHOPCOUNT:
1401 : case IPV6_RECVPKTINFO:
1402 : case IPV6_RECVHOPLIMIT:
1403 : case IPV6_RECVRTHDR:
1404 : case IPV6_RECVPATHMTU:
1405 :
1406 : case IPV6_V6ONLY:
1407 : case IPV6_PORTRANGE:
1408 : case IPV6_RECVTCLASS:
1409 : case IPV6_AUTOFLOWLABEL:
1410 : case IPV6_RECVDSTPORT:
1411 0 : switch (optname) {
1412 :
1413 : case IPV6_RECVHOPOPTS:
1414 0 : optval = OPTBIT(IN6P_HOPOPTS);
1415 0 : break;
1416 :
1417 : case IPV6_RECVDSTOPTS:
1418 0 : optval = OPTBIT(IN6P_DSTOPTS);
1419 0 : break;
1420 :
1421 : case IPV6_UNICAST_HOPS:
1422 0 : optval = inp->inp_hops;
1423 0 : break;
1424 :
1425 : case IPV6_MINHOPCOUNT:
1426 0 : optval = inp->inp_ip6_minhlim;
1427 0 : break;
1428 :
1429 : case IPV6_RECVPKTINFO:
1430 0 : optval = OPTBIT(IN6P_PKTINFO);
1431 0 : break;
1432 :
1433 : case IPV6_RECVHOPLIMIT:
1434 0 : optval = OPTBIT(IN6P_HOPLIMIT);
1435 0 : break;
1436 :
1437 : case IPV6_RECVRTHDR:
1438 0 : optval = OPTBIT(IN6P_RTHDR);
1439 0 : break;
1440 :
1441 : case IPV6_RECVPATHMTU:
1442 0 : optval = OPTBIT(IN6P_MTU);
1443 0 : break;
1444 :
1445 : case IPV6_V6ONLY:
1446 0 : optval = 1;
1447 0 : break;
1448 :
1449 : case IPV6_PORTRANGE:
1450 : {
1451 : int flags;
1452 0 : flags = inp->inp_flags;
1453 0 : if (flags & IN6P_HIGHPORT)
1454 0 : optval = IPV6_PORTRANGE_HIGH;
1455 0 : else if (flags & IN6P_LOWPORT)
1456 0 : optval = IPV6_PORTRANGE_LOW;
1457 : else
1458 0 : optval = 0;
1459 : break;
1460 : }
1461 : case IPV6_RECVTCLASS:
1462 0 : optval = OPTBIT(IN6P_TCLASS);
1463 0 : break;
1464 :
1465 : case IPV6_AUTOFLOWLABEL:
1466 0 : optval = OPTBIT(IN6P_AUTOFLOWLABEL);
1467 0 : break;
1468 :
1469 : case IPV6_RECVDSTPORT:
1470 0 : optval = OPTBIT(IN6P_RECVDSTPORT);
1471 0 : break;
1472 : }
1473 0 : if (error)
1474 : break;
1475 0 : m->m_len = sizeof(int);
1476 0 : *mtod(m, int *) = optval;
1477 0 : break;
1478 :
1479 : case IPV6_PATHMTU:
1480 : {
1481 0 : u_long pmtu = 0;
1482 0 : struct ip6_mtuinfo mtuinfo;
1483 : struct ifnet *ifp;
1484 : struct rtentry *rt;
1485 :
1486 0 : if (!(so->so_state & SS_ISCONNECTED))
1487 0 : return (ENOTCONN);
1488 :
1489 0 : rt = in_pcbrtentry(inp);
1490 0 : if (!rtisvalid(rt))
1491 0 : return (EHOSTUNREACH);
1492 :
1493 0 : ifp = if_get(rt->rt_ifidx);
1494 0 : if (ifp == NULL)
1495 0 : return (EHOSTUNREACH);
1496 : /*
1497 : * XXX: we dot not consider the case of source
1498 : * routing, or optional information to specify
1499 : * the outgoing interface.
1500 : */
1501 0 : error = ip6_getpmtu(rt, ifp, &pmtu);
1502 0 : if_put(ifp);
1503 0 : if (error)
1504 0 : break;
1505 0 : if (pmtu > IPV6_MAXPACKET)
1506 0 : pmtu = IPV6_MAXPACKET;
1507 :
1508 0 : bzero(&mtuinfo, sizeof(mtuinfo));
1509 0 : mtuinfo.ip6m_mtu = (u_int32_t)pmtu;
1510 : optdata = (void *)&mtuinfo;
1511 : optdatalen = sizeof(mtuinfo);
1512 0 : if (optdatalen > MCLBYTES)
1513 0 : return (EMSGSIZE); /* XXX */
1514 0 : if (optdatalen > MLEN)
1515 0 : MCLGET(m, M_WAIT);
1516 0 : m->m_len = optdatalen;
1517 0 : bcopy(optdata, mtod(m, void *), optdatalen);
1518 0 : break;
1519 0 : }
1520 :
1521 : case IPV6_PKTINFO:
1522 : case IPV6_HOPOPTS:
1523 : case IPV6_RTHDR:
1524 : case IPV6_DSTOPTS:
1525 : case IPV6_RTHDRDSTOPTS:
1526 : case IPV6_TCLASS:
1527 : case IPV6_DONTFRAG:
1528 : case IPV6_USE_MIN_MTU:
1529 0 : error = ip6_getpcbopt(inp->inp_outputopts6,
1530 : optname, m);
1531 0 : break;
1532 :
1533 : case IPV6_MULTICAST_IF:
1534 : case IPV6_MULTICAST_HOPS:
1535 : case IPV6_MULTICAST_LOOP:
1536 : case IPV6_JOIN_GROUP:
1537 : case IPV6_LEAVE_GROUP:
1538 0 : error = ip6_getmoptions(optname,
1539 0 : inp->inp_moptions6, m);
1540 0 : break;
1541 :
1542 : case IPSEC6_OUTSA:
1543 : error = EINVAL;
1544 0 : break;
1545 :
1546 : case IPV6_AUTH_LEVEL:
1547 : case IPV6_ESP_TRANS_LEVEL:
1548 : case IPV6_ESP_NETWORK_LEVEL:
1549 : case IPV6_IPCOMP_LEVEL:
1550 : #ifndef IPSEC
1551 : m->m_len = sizeof(int);
1552 : *mtod(m, int *) = IPSEC_LEVEL_NONE;
1553 : #else
1554 0 : m->m_len = sizeof(int);
1555 0 : switch (optname) {
1556 : case IPV6_AUTH_LEVEL:
1557 0 : optval = inp->inp_seclevel[SL_AUTH];
1558 0 : break;
1559 :
1560 : case IPV6_ESP_TRANS_LEVEL:
1561 0 : optval =
1562 0 : inp->inp_seclevel[SL_ESP_TRANS];
1563 0 : break;
1564 :
1565 : case IPV6_ESP_NETWORK_LEVEL:
1566 0 : optval =
1567 0 : inp->inp_seclevel[SL_ESP_NETWORK];
1568 0 : break;
1569 :
1570 : case IPV6_IPCOMP_LEVEL:
1571 0 : optval = inp->inp_seclevel[SL_IPCOMP];
1572 0 : break;
1573 : }
1574 0 : *mtod(m, int *) = optval;
1575 : #endif
1576 0 : break;
1577 : case SO_RTABLE:
1578 0 : m->m_len = sizeof(u_int);
1579 0 : *mtod(m, u_int *) = optval;
1580 0 : break;
1581 : case IPV6_PIPEX:
1582 0 : m->m_len = sizeof(int);
1583 0 : *mtod(m, int *) = optval;
1584 0 : break;
1585 :
1586 : default:
1587 : error = ENOPROTOOPT;
1588 0 : break;
1589 : }
1590 : break;
1591 : }
1592 0 : return (error);
1593 0 : }
1594 :
1595 : int
1596 0 : ip6_raw_ctloutput(int op, struct socket *so, int level, int optname,
1597 : struct mbuf *m)
1598 : {
1599 : int error = 0, optval;
1600 : const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
1601 0 : struct inpcb *inp = sotoinpcb(so);
1602 :
1603 0 : if (level != IPPROTO_IPV6)
1604 0 : return (EINVAL);
1605 :
1606 0 : switch (optname) {
1607 : case IPV6_CHECKSUM:
1608 : /*
1609 : * For ICMPv6 sockets, no modification allowed for checksum
1610 : * offset, permit "no change" values to help existing apps.
1611 : *
1612 : * RFC3542 says: "An attempt to set IPV6_CHECKSUM
1613 : * for an ICMPv6 socket will fail."
1614 : * The current behavior does not meet RFC3542.
1615 : */
1616 0 : switch (op) {
1617 : case PRCO_SETOPT:
1618 0 : if (m == NULL || m->m_len != sizeof(int)) {
1619 : error = EINVAL;
1620 0 : break;
1621 : }
1622 0 : optval = *mtod(m, int *);
1623 0 : if ((optval % 2) != 0) {
1624 : /* the API assumes even offset values */
1625 : error = EINVAL;
1626 0 : } else if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
1627 0 : if (optval != icmp6off)
1628 0 : error = EINVAL;
1629 : } else
1630 0 : inp->inp_cksum6 = optval;
1631 : break;
1632 :
1633 : case PRCO_GETOPT:
1634 0 : if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
1635 0 : optval = icmp6off;
1636 : else
1637 0 : optval = inp->inp_cksum6;
1638 :
1639 0 : m->m_len = sizeof(int);
1640 0 : *mtod(m, int *) = optval;
1641 0 : break;
1642 :
1643 : default:
1644 : error = EINVAL;
1645 0 : break;
1646 : }
1647 : break;
1648 :
1649 : default:
1650 : error = ENOPROTOOPT;
1651 0 : break;
1652 : }
1653 :
1654 0 : return (error);
1655 0 : }
1656 :
1657 : /*
1658 : * initialize ip6_pktopts. beware that there are non-zero default values in
1659 : * the struct.
1660 : */
1661 : void
1662 0 : ip6_initpktopts(struct ip6_pktopts *opt)
1663 : {
1664 0 : bzero(opt, sizeof(*opt));
1665 0 : opt->ip6po_hlim = -1; /* -1 means default hop limit */
1666 0 : opt->ip6po_tclass = -1; /* -1 means default traffic class */
1667 0 : opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY;
1668 0 : }
1669 :
1670 : int
1671 0 : ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt,
1672 : int priv, int uproto)
1673 : {
1674 : struct ip6_pktopts *opt;
1675 :
1676 0 : if (*pktopt == NULL) {
1677 0 : *pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT,
1678 : M_WAITOK);
1679 0 : ip6_initpktopts(*pktopt);
1680 0 : }
1681 0 : opt = *pktopt;
1682 :
1683 0 : return (ip6_setpktopt(optname, buf, len, opt, priv, 1, uproto));
1684 : }
1685 :
1686 : int
1687 0 : ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct mbuf *m)
1688 : {
1689 : void *optdata = NULL;
1690 : int optdatalen = 0;
1691 : struct ip6_ext *ip6e;
1692 : int error = 0;
1693 0 : struct in6_pktinfo null_pktinfo;
1694 0 : int deftclass = 0, on;
1695 0 : int defminmtu = IP6PO_MINMTU_MCASTONLY;
1696 :
1697 0 : switch (optname) {
1698 : case IPV6_PKTINFO:
1699 0 : if (pktopt && pktopt->ip6po_pktinfo)
1700 0 : optdata = (void *)pktopt->ip6po_pktinfo;
1701 : else {
1702 : /* XXX: we don't have to do this every time... */
1703 0 : bzero(&null_pktinfo, sizeof(null_pktinfo));
1704 : optdata = (void *)&null_pktinfo;
1705 : }
1706 : optdatalen = sizeof(struct in6_pktinfo);
1707 0 : break;
1708 : case IPV6_TCLASS:
1709 0 : if (pktopt && pktopt->ip6po_tclass >= 0)
1710 0 : optdata = (void *)&pktopt->ip6po_tclass;
1711 : else
1712 : optdata = (void *)&deftclass;
1713 : optdatalen = sizeof(int);
1714 0 : break;
1715 : case IPV6_HOPOPTS:
1716 0 : if (pktopt && pktopt->ip6po_hbh) {
1717 0 : optdata = (void *)pktopt->ip6po_hbh;
1718 0 : ip6e = (struct ip6_ext *)pktopt->ip6po_hbh;
1719 0 : optdatalen = (ip6e->ip6e_len + 1) << 3;
1720 0 : }
1721 : break;
1722 : case IPV6_RTHDR:
1723 0 : if (pktopt && pktopt->ip6po_rthdr) {
1724 0 : optdata = (void *)pktopt->ip6po_rthdr;
1725 0 : ip6e = (struct ip6_ext *)pktopt->ip6po_rthdr;
1726 0 : optdatalen = (ip6e->ip6e_len + 1) << 3;
1727 0 : }
1728 : break;
1729 : case IPV6_RTHDRDSTOPTS:
1730 0 : if (pktopt && pktopt->ip6po_dest1) {
1731 0 : optdata = (void *)pktopt->ip6po_dest1;
1732 0 : ip6e = (struct ip6_ext *)pktopt->ip6po_dest1;
1733 0 : optdatalen = (ip6e->ip6e_len + 1) << 3;
1734 0 : }
1735 : break;
1736 : case IPV6_DSTOPTS:
1737 0 : if (pktopt && pktopt->ip6po_dest2) {
1738 0 : optdata = (void *)pktopt->ip6po_dest2;
1739 0 : ip6e = (struct ip6_ext *)pktopt->ip6po_dest2;
1740 0 : optdatalen = (ip6e->ip6e_len + 1) << 3;
1741 0 : }
1742 : break;
1743 : case IPV6_USE_MIN_MTU:
1744 0 : if (pktopt)
1745 0 : optdata = (void *)&pktopt->ip6po_minmtu;
1746 : else
1747 : optdata = (void *)&defminmtu;
1748 : optdatalen = sizeof(int);
1749 0 : break;
1750 : case IPV6_DONTFRAG:
1751 0 : if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG))
1752 0 : on = 1;
1753 : else
1754 0 : on = 0;
1755 : optdata = (void *)&on;
1756 : optdatalen = sizeof(on);
1757 0 : break;
1758 : default: /* should not happen */
1759 : #ifdef DIAGNOSTIC
1760 0 : panic("ip6_getpcbopt: unexpected option");
1761 : #endif
1762 : return (ENOPROTOOPT);
1763 : }
1764 :
1765 0 : if (optdatalen > MCLBYTES)
1766 0 : return (EMSGSIZE); /* XXX */
1767 0 : if (optdatalen > MLEN)
1768 0 : MCLGET(m, M_WAIT);
1769 0 : m->m_len = optdatalen;
1770 0 : if (optdatalen)
1771 0 : bcopy(optdata, mtod(m, void *), optdatalen);
1772 :
1773 0 : return (error);
1774 0 : }
1775 :
1776 : void
1777 0 : ip6_clearpktopts(struct ip6_pktopts *pktopt, int optname)
1778 : {
1779 0 : if (optname == -1 || optname == IPV6_PKTINFO) {
1780 0 : if (pktopt->ip6po_pktinfo)
1781 0 : free(pktopt->ip6po_pktinfo, M_IP6OPT, 0);
1782 0 : pktopt->ip6po_pktinfo = NULL;
1783 0 : }
1784 0 : if (optname == -1 || optname == IPV6_HOPLIMIT)
1785 0 : pktopt->ip6po_hlim = -1;
1786 0 : if (optname == -1 || optname == IPV6_TCLASS)
1787 0 : pktopt->ip6po_tclass = -1;
1788 0 : if (optname == -1 || optname == IPV6_HOPOPTS) {
1789 0 : if (pktopt->ip6po_hbh)
1790 0 : free(pktopt->ip6po_hbh, M_IP6OPT, 0);
1791 0 : pktopt->ip6po_hbh = NULL;
1792 0 : }
1793 0 : if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) {
1794 0 : if (pktopt->ip6po_dest1)
1795 0 : free(pktopt->ip6po_dest1, M_IP6OPT, 0);
1796 0 : pktopt->ip6po_dest1 = NULL;
1797 0 : }
1798 0 : if (optname == -1 || optname == IPV6_RTHDR) {
1799 0 : if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
1800 0 : free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT, 0);
1801 0 : pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
1802 0 : if (pktopt->ip6po_route.ro_rt) {
1803 0 : rtfree(pktopt->ip6po_route.ro_rt);
1804 0 : pktopt->ip6po_route.ro_rt = NULL;
1805 0 : }
1806 : }
1807 0 : if (optname == -1 || optname == IPV6_DSTOPTS) {
1808 0 : if (pktopt->ip6po_dest2)
1809 0 : free(pktopt->ip6po_dest2, M_IP6OPT, 0);
1810 0 : pktopt->ip6po_dest2 = NULL;
1811 0 : }
1812 0 : }
1813 :
1814 : #define PKTOPT_EXTHDRCPY(type) \
1815 : do {\
1816 : if (src->type) {\
1817 : size_t hlen = (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
1818 : dst->type = malloc(hlen, M_IP6OPT, M_NOWAIT);\
1819 : if (dst->type == NULL)\
1820 : goto bad;\
1821 : memcpy(dst->type, src->type, hlen);\
1822 : }\
1823 : } while (/*CONSTCOND*/ 0)
1824 :
1825 : int
1826 0 : copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src)
1827 : {
1828 0 : dst->ip6po_hlim = src->ip6po_hlim;
1829 0 : dst->ip6po_tclass = src->ip6po_tclass;
1830 0 : dst->ip6po_flags = src->ip6po_flags;
1831 0 : if (src->ip6po_pktinfo) {
1832 0 : dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo),
1833 : M_IP6OPT, M_NOWAIT);
1834 0 : if (dst->ip6po_pktinfo == NULL)
1835 : goto bad;
1836 0 : *dst->ip6po_pktinfo = *src->ip6po_pktinfo;
1837 0 : }
1838 0 : PKTOPT_EXTHDRCPY(ip6po_hbh);
1839 0 : PKTOPT_EXTHDRCPY(ip6po_dest1);
1840 0 : PKTOPT_EXTHDRCPY(ip6po_dest2);
1841 0 : PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */
1842 0 : return (0);
1843 :
1844 : bad:
1845 0 : ip6_clearpktopts(dst, -1);
1846 0 : return (ENOBUFS);
1847 0 : }
1848 : #undef PKTOPT_EXTHDRCPY
1849 :
1850 : void
1851 0 : ip6_freepcbopts(struct ip6_pktopts *pktopt)
1852 : {
1853 0 : if (pktopt == NULL)
1854 : return;
1855 :
1856 0 : ip6_clearpktopts(pktopt, -1);
1857 :
1858 0 : free(pktopt, M_IP6OPT, 0);
1859 0 : }
1860 :
1861 : /*
1862 : * Set the IP6 multicast options in response to user setsockopt().
1863 : */
1864 : int
1865 0 : ip6_setmoptions(int optname, struct ip6_moptions **im6op, struct mbuf *m,
1866 : unsigned int rtableid)
1867 : {
1868 0 : int error = 0;
1869 : u_int loop, ifindex;
1870 : struct ipv6_mreq *mreq;
1871 : struct ifnet *ifp;
1872 0 : struct ip6_moptions *im6o = *im6op;
1873 : struct in6_multi_mship *imm;
1874 0 : struct proc *p = curproc; /* XXX */
1875 :
1876 0 : if (im6o == NULL) {
1877 : /*
1878 : * No multicast option buffer attached to the pcb;
1879 : * allocate one and initialize to default values.
1880 : */
1881 0 : im6o = (struct ip6_moptions *)
1882 0 : malloc(sizeof(*im6o), M_IPMOPTS, M_WAITOK);
1883 :
1884 0 : if (im6o == NULL)
1885 0 : return (ENOBUFS);
1886 0 : *im6op = im6o;
1887 0 : im6o->im6o_ifidx = 0;
1888 0 : im6o->im6o_hlim = ip6_defmcasthlim;
1889 0 : im6o->im6o_loop = IPV6_DEFAULT_MULTICAST_LOOP;
1890 0 : LIST_INIT(&im6o->im6o_memberships);
1891 0 : }
1892 :
1893 0 : switch (optname) {
1894 :
1895 : case IPV6_MULTICAST_IF:
1896 : /*
1897 : * Select the interface for outgoing multicast packets.
1898 : */
1899 0 : if (m == NULL || m->m_len != sizeof(u_int)) {
1900 0 : error = EINVAL;
1901 0 : break;
1902 : }
1903 0 : memcpy(&ifindex, mtod(m, u_int *), sizeof(ifindex));
1904 0 : if (ifindex != 0) {
1905 0 : ifp = if_get(ifindex);
1906 0 : if (ifp == NULL) {
1907 0 : error = ENXIO; /* XXX EINVAL? */
1908 0 : break;
1909 : }
1910 0 : if ((ifp->if_flags & IFF_MULTICAST) == 0) {
1911 0 : error = EADDRNOTAVAIL;
1912 0 : if_put(ifp);
1913 0 : break;
1914 : }
1915 0 : if_put(ifp);
1916 0 : }
1917 0 : im6o->im6o_ifidx = ifindex;
1918 0 : break;
1919 :
1920 : case IPV6_MULTICAST_HOPS:
1921 : {
1922 : /*
1923 : * Set the IP6 hoplimit for outgoing multicast packets.
1924 : */
1925 : int optval;
1926 0 : if (m == NULL || m->m_len != sizeof(int)) {
1927 0 : error = EINVAL;
1928 0 : break;
1929 : }
1930 0 : memcpy(&optval, mtod(m, u_int *), sizeof(optval));
1931 0 : if (optval < -1 || optval >= 256)
1932 0 : error = EINVAL;
1933 0 : else if (optval == -1)
1934 0 : im6o->im6o_hlim = ip6_defmcasthlim;
1935 : else
1936 0 : im6o->im6o_hlim = optval;
1937 0 : break;
1938 : }
1939 :
1940 : case IPV6_MULTICAST_LOOP:
1941 : /*
1942 : * Set the loopback flag for outgoing multicast packets.
1943 : * Must be zero or one.
1944 : */
1945 0 : if (m == NULL || m->m_len != sizeof(u_int)) {
1946 0 : error = EINVAL;
1947 0 : break;
1948 : }
1949 0 : memcpy(&loop, mtod(m, u_int *), sizeof(loop));
1950 0 : if (loop > 1) {
1951 0 : error = EINVAL;
1952 0 : break;
1953 : }
1954 0 : im6o->im6o_loop = loop;
1955 0 : break;
1956 :
1957 : case IPV6_JOIN_GROUP:
1958 : /*
1959 : * Add a multicast group membership.
1960 : * Group must be a valid IP6 multicast address.
1961 : */
1962 0 : if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
1963 0 : error = EINVAL;
1964 0 : break;
1965 : }
1966 0 : mreq = mtod(m, struct ipv6_mreq *);
1967 0 : if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
1968 : /*
1969 : * We use the unspecified address to specify to accept
1970 : * all multicast addresses. Only super user is allowed
1971 : * to do this.
1972 : */
1973 0 : if (suser(p))
1974 : {
1975 0 : error = EACCES;
1976 0 : break;
1977 : }
1978 0 : } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
1979 0 : error = EINVAL;
1980 0 : break;
1981 : }
1982 :
1983 : /*
1984 : * If no interface was explicitly specified, choose an
1985 : * appropriate one according to the given multicast address.
1986 : */
1987 0 : if (mreq->ipv6mr_interface == 0) {
1988 : struct rtentry *rt;
1989 0 : struct sockaddr_in6 dst;
1990 :
1991 0 : memset(&dst, 0, sizeof(dst));
1992 0 : dst.sin6_len = sizeof(dst);
1993 0 : dst.sin6_family = AF_INET6;
1994 0 : dst.sin6_addr = mreq->ipv6mr_multiaddr;
1995 0 : rt = rtalloc(sin6tosa(&dst), RT_RESOLVE, rtableid);
1996 0 : if (rt == NULL) {
1997 0 : error = EADDRNOTAVAIL;
1998 0 : break;
1999 : }
2000 0 : ifp = if_get(rt->rt_ifidx);
2001 0 : rtfree(rt);
2002 0 : } else {
2003 : /*
2004 : * If the interface is specified, validate it.
2005 : */
2006 0 : ifp = if_get(mreq->ipv6mr_interface);
2007 0 : if (ifp == NULL) {
2008 0 : error = ENXIO; /* XXX EINVAL? */
2009 0 : break;
2010 : }
2011 : }
2012 :
2013 : /*
2014 : * See if we found an interface, and confirm that it
2015 : * supports multicast
2016 : */
2017 0 : if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
2018 0 : if_put(ifp);
2019 0 : error = EADDRNOTAVAIL;
2020 0 : break;
2021 : }
2022 : /*
2023 : * Put interface index into the multicast address,
2024 : * if the address has link/interface-local scope.
2025 : */
2026 0 : if (IN6_IS_SCOPE_EMBED(&mreq->ipv6mr_multiaddr)) {
2027 0 : mreq->ipv6mr_multiaddr.s6_addr16[1] =
2028 0 : htons(ifp->if_index);
2029 0 : }
2030 : /*
2031 : * See if the membership already exists.
2032 : */
2033 0 : LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain)
2034 0 : if (imm->i6mm_maddr->in6m_ifidx == ifp->if_index &&
2035 0 : IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
2036 : &mreq->ipv6mr_multiaddr))
2037 : break;
2038 0 : if (imm != NULL) {
2039 0 : if_put(ifp);
2040 0 : error = EADDRINUSE;
2041 0 : break;
2042 : }
2043 : /*
2044 : * Everything looks good; add a new record to the multicast
2045 : * address list for the given interface.
2046 : */
2047 0 : imm = in6_joingroup(ifp, &mreq->ipv6mr_multiaddr, &error);
2048 0 : if_put(ifp);
2049 0 : if (!imm)
2050 : break;
2051 0 : LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
2052 0 : break;
2053 :
2054 : case IPV6_LEAVE_GROUP:
2055 : /*
2056 : * Drop a multicast group membership.
2057 : * Group must be a valid IP6 multicast address.
2058 : */
2059 0 : if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
2060 0 : error = EINVAL;
2061 0 : break;
2062 : }
2063 0 : mreq = mtod(m, struct ipv6_mreq *);
2064 0 : if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
2065 0 : if (suser(p))
2066 : {
2067 0 : error = EACCES;
2068 0 : break;
2069 : }
2070 0 : } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
2071 0 : error = EINVAL;
2072 0 : break;
2073 : }
2074 :
2075 : /*
2076 : * Put interface index into the multicast address,
2077 : * if the address has link-local scope.
2078 : */
2079 0 : if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
2080 0 : mreq->ipv6mr_multiaddr.s6_addr16[1] =
2081 0 : htons(mreq->ipv6mr_interface);
2082 0 : }
2083 :
2084 : /*
2085 : * If an interface address was specified, get a pointer
2086 : * to its ifnet structure.
2087 : */
2088 0 : if (mreq->ipv6mr_interface == 0)
2089 0 : ifp = NULL;
2090 : else {
2091 0 : ifp = if_get(mreq->ipv6mr_interface);
2092 0 : if (ifp == NULL) {
2093 0 : error = ENXIO; /* XXX EINVAL? */
2094 0 : break;
2095 : }
2096 : }
2097 :
2098 : /*
2099 : * Find the membership in the membership list.
2100 : */
2101 0 : LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) {
2102 0 : if ((ifp == NULL ||
2103 0 : imm->i6mm_maddr->in6m_ifidx == ifp->if_index) &&
2104 0 : IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
2105 : &mreq->ipv6mr_multiaddr))
2106 : break;
2107 : }
2108 :
2109 0 : if_put(ifp);
2110 :
2111 0 : if (imm == NULL) {
2112 : /* Unable to resolve interface */
2113 0 : error = EADDRNOTAVAIL;
2114 0 : break;
2115 : }
2116 : /*
2117 : * Give up the multicast address record to which the
2118 : * membership points.
2119 : */
2120 0 : LIST_REMOVE(imm, i6mm_chain);
2121 0 : in6_leavegroup(imm);
2122 0 : break;
2123 :
2124 : default:
2125 0 : error = EOPNOTSUPP;
2126 0 : break;
2127 : }
2128 :
2129 : /*
2130 : * If all options have default values, no need to keep the option
2131 : * structure.
2132 : */
2133 0 : if (im6o->im6o_ifidx == 0 &&
2134 0 : im6o->im6o_hlim == ip6_defmcasthlim &&
2135 0 : im6o->im6o_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
2136 0 : LIST_EMPTY(&im6o->im6o_memberships)) {
2137 0 : free(*im6op, M_IPMOPTS, 0);
2138 0 : *im6op = NULL;
2139 0 : }
2140 :
2141 0 : return (error);
2142 0 : }
2143 :
2144 : /*
2145 : * Return the IP6 multicast options in response to user getsockopt().
2146 : */
2147 : int
2148 0 : ip6_getmoptions(int optname, struct ip6_moptions *im6o, struct mbuf *m)
2149 : {
2150 : u_int *hlim, *loop, *ifindex;
2151 :
2152 0 : switch (optname) {
2153 : case IPV6_MULTICAST_IF:
2154 0 : ifindex = mtod(m, u_int *);
2155 0 : m->m_len = sizeof(u_int);
2156 0 : if (im6o == NULL || im6o->im6o_ifidx == 0)
2157 0 : *ifindex = 0;
2158 : else
2159 0 : *ifindex = im6o->im6o_ifidx;
2160 0 : return (0);
2161 :
2162 : case IPV6_MULTICAST_HOPS:
2163 0 : hlim = mtod(m, u_int *);
2164 0 : m->m_len = sizeof(u_int);
2165 0 : if (im6o == NULL)
2166 0 : *hlim = ip6_defmcasthlim;
2167 : else
2168 0 : *hlim = im6o->im6o_hlim;
2169 0 : return (0);
2170 :
2171 : case IPV6_MULTICAST_LOOP:
2172 0 : loop = mtod(m, u_int *);
2173 0 : m->m_len = sizeof(u_int);
2174 0 : if (im6o == NULL)
2175 0 : *loop = ip6_defmcasthlim;
2176 : else
2177 0 : *loop = im6o->im6o_loop;
2178 0 : return (0);
2179 :
2180 : default:
2181 0 : return (EOPNOTSUPP);
2182 : }
2183 0 : }
2184 :
2185 : /*
2186 : * Discard the IP6 multicast options.
2187 : */
2188 : void
2189 0 : ip6_freemoptions(struct ip6_moptions *im6o)
2190 : {
2191 : struct in6_multi_mship *imm;
2192 :
2193 0 : if (im6o == NULL)
2194 0 : return;
2195 :
2196 0 : while (!LIST_EMPTY(&im6o->im6o_memberships)) {
2197 : imm = LIST_FIRST(&im6o->im6o_memberships);
2198 0 : LIST_REMOVE(imm, i6mm_chain);
2199 0 : in6_leavegroup(imm);
2200 : }
2201 0 : free(im6o, M_IPMOPTS, 0);
2202 0 : }
2203 :
2204 : /*
2205 : * Set IPv6 outgoing packet options based on advanced API.
2206 : */
2207 : int
2208 0 : ip6_setpktopts(struct mbuf *control, struct ip6_pktopts *opt,
2209 : struct ip6_pktopts *stickyopt, int priv, int uproto)
2210 : {
2211 : u_int clen;
2212 : struct cmsghdr *cm = 0;
2213 : caddr_t cmsgs;
2214 : int error;
2215 :
2216 0 : if (control == NULL || opt == NULL)
2217 0 : return (EINVAL);
2218 :
2219 0 : ip6_initpktopts(opt);
2220 0 : if (stickyopt) {
2221 : int error;
2222 :
2223 : /*
2224 : * If stickyopt is provided, make a local copy of the options
2225 : * for this particular packet, then override them by ancillary
2226 : * objects.
2227 : * XXX: copypktopts() does not copy the cached route to a next
2228 : * hop (if any). This is not very good in terms of efficiency,
2229 : * but we can allow this since this option should be rarely
2230 : * used.
2231 : */
2232 0 : if ((error = copypktopts(opt, stickyopt)) != 0)
2233 0 : return (error);
2234 0 : }
2235 :
2236 : /*
2237 : * XXX: Currently, we assume all the optional information is stored
2238 : * in a single mbuf.
2239 : */
2240 0 : if (control->m_next)
2241 0 : return (EINVAL);
2242 :
2243 0 : clen = control->m_len;
2244 0 : cmsgs = mtod(control, caddr_t);
2245 0 : do {
2246 0 : if (clen < CMSG_LEN(0))
2247 0 : return (EINVAL);
2248 0 : cm = (struct cmsghdr *)cmsgs;
2249 0 : if (cm->cmsg_len < CMSG_LEN(0) || cm->cmsg_len > clen ||
2250 0 : CMSG_ALIGN(cm->cmsg_len) > clen)
2251 0 : return (EINVAL);
2252 0 : if (cm->cmsg_level == IPPROTO_IPV6) {
2253 0 : error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm),
2254 0 : cm->cmsg_len - CMSG_LEN(0), opt, priv, 0, uproto);
2255 0 : if (error)
2256 0 : return (error);
2257 : }
2258 :
2259 0 : clen -= CMSG_ALIGN(cm->cmsg_len);
2260 0 : cmsgs += CMSG_ALIGN(cm->cmsg_len);
2261 0 : } while (clen);
2262 :
2263 0 : return (0);
2264 0 : }
2265 :
2266 : /*
2267 : * Set a particular packet option, as a sticky option or an ancillary data
2268 : * item. "len" can be 0 only when it's a sticky option.
2269 : */
2270 : int
2271 0 : ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt,
2272 : int priv, int sticky, int uproto)
2273 : {
2274 : int minmtupolicy;
2275 :
2276 0 : switch (optname) {
2277 : case IPV6_PKTINFO:
2278 : {
2279 : struct ifnet *ifp = NULL;
2280 : struct in6_pktinfo *pktinfo;
2281 :
2282 0 : if (len != sizeof(struct in6_pktinfo))
2283 0 : return (EINVAL);
2284 :
2285 0 : pktinfo = (struct in6_pktinfo *)buf;
2286 :
2287 : /*
2288 : * An application can clear any sticky IPV6_PKTINFO option by
2289 : * doing a "regular" setsockopt with ipi6_addr being
2290 : * in6addr_any and ipi6_ifindex being zero.
2291 : * [RFC 3542, Section 6]
2292 : */
2293 0 : if (opt->ip6po_pktinfo &&
2294 0 : pktinfo->ipi6_ifindex == 0 &&
2295 0 : IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
2296 0 : ip6_clearpktopts(opt, optname);
2297 0 : break;
2298 : }
2299 :
2300 0 : if (uproto == IPPROTO_TCP &&
2301 0 : sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
2302 0 : return (EINVAL);
2303 : }
2304 :
2305 0 : if (pktinfo->ipi6_ifindex) {
2306 0 : ifp = if_get(pktinfo->ipi6_ifindex);
2307 0 : if (ifp == NULL)
2308 0 : return (ENXIO);
2309 0 : if_put(ifp);
2310 0 : }
2311 :
2312 : /*
2313 : * We store the address anyway, and let in6_selectsrc()
2314 : * validate the specified address. This is because ipi6_addr
2315 : * may not have enough information about its scope zone, and
2316 : * we may need additional information (such as outgoing
2317 : * interface or the scope zone of a destination address) to
2318 : * disambiguate the scope.
2319 : * XXX: the delay of the validation may confuse the
2320 : * application when it is used as a sticky option.
2321 : */
2322 0 : if (opt->ip6po_pktinfo == NULL) {
2323 0 : opt->ip6po_pktinfo = malloc(sizeof(*pktinfo),
2324 : M_IP6OPT, M_NOWAIT);
2325 0 : if (opt->ip6po_pktinfo == NULL)
2326 0 : return (ENOBUFS);
2327 : }
2328 0 : bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
2329 0 : break;
2330 : }
2331 :
2332 : case IPV6_HOPLIMIT:
2333 : {
2334 : int *hlimp;
2335 :
2336 : /*
2337 : * RFC 3542 deprecated the usage of sticky IPV6_HOPLIMIT
2338 : * to simplify the ordering among hoplimit options.
2339 : */
2340 0 : if (sticky)
2341 0 : return (ENOPROTOOPT);
2342 :
2343 0 : if (len != sizeof(int))
2344 0 : return (EINVAL);
2345 0 : hlimp = (int *)buf;
2346 0 : if (*hlimp < -1 || *hlimp > 255)
2347 0 : return (EINVAL);
2348 :
2349 0 : opt->ip6po_hlim = *hlimp;
2350 0 : break;
2351 : }
2352 :
2353 : case IPV6_TCLASS:
2354 : {
2355 : int tclass;
2356 :
2357 0 : if (len != sizeof(int))
2358 0 : return (EINVAL);
2359 0 : tclass = *(int *)buf;
2360 0 : if (tclass < -1 || tclass > 255)
2361 0 : return (EINVAL);
2362 :
2363 0 : opt->ip6po_tclass = tclass;
2364 0 : break;
2365 : }
2366 : case IPV6_HOPOPTS:
2367 : {
2368 : struct ip6_hbh *hbh;
2369 : int hbhlen;
2370 :
2371 : /*
2372 : * XXX: We don't allow a non-privileged user to set ANY HbH
2373 : * options, since per-option restriction has too much
2374 : * overhead.
2375 : */
2376 0 : if (!priv)
2377 0 : return (EPERM);
2378 :
2379 0 : if (len == 0) {
2380 0 : ip6_clearpktopts(opt, IPV6_HOPOPTS);
2381 0 : break; /* just remove the option */
2382 : }
2383 :
2384 : /* message length validation */
2385 0 : if (len < sizeof(struct ip6_hbh))
2386 0 : return (EINVAL);
2387 0 : hbh = (struct ip6_hbh *)buf;
2388 0 : hbhlen = (hbh->ip6h_len + 1) << 3;
2389 0 : if (len != hbhlen)
2390 0 : return (EINVAL);
2391 :
2392 : /* turn off the previous option, then set the new option. */
2393 0 : ip6_clearpktopts(opt, IPV6_HOPOPTS);
2394 0 : opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_NOWAIT);
2395 0 : if (opt->ip6po_hbh == NULL)
2396 0 : return (ENOBUFS);
2397 0 : memcpy(opt->ip6po_hbh, hbh, hbhlen);
2398 :
2399 0 : break;
2400 : }
2401 :
2402 : case IPV6_DSTOPTS:
2403 : case IPV6_RTHDRDSTOPTS:
2404 : {
2405 : struct ip6_dest *dest, **newdest = NULL;
2406 : int destlen;
2407 :
2408 0 : if (!priv) /* XXX: see the comment for IPV6_HOPOPTS */
2409 0 : return (EPERM);
2410 :
2411 0 : if (len == 0) {
2412 0 : ip6_clearpktopts(opt, optname);
2413 0 : break; /* just remove the option */
2414 : }
2415 :
2416 : /* message length validation */
2417 0 : if (len < sizeof(struct ip6_dest))
2418 0 : return (EINVAL);
2419 0 : dest = (struct ip6_dest *)buf;
2420 0 : destlen = (dest->ip6d_len + 1) << 3;
2421 0 : if (len != destlen)
2422 0 : return (EINVAL);
2423 : /*
2424 : * Determine the position that the destination options header
2425 : * should be inserted; before or after the routing header.
2426 : */
2427 0 : switch (optname) {
2428 : case IPV6_RTHDRDSTOPTS:
2429 0 : newdest = &opt->ip6po_dest1;
2430 0 : break;
2431 : case IPV6_DSTOPTS:
2432 0 : newdest = &opt->ip6po_dest2;
2433 0 : break;
2434 : }
2435 :
2436 : /* turn off the previous option, then set the new option. */
2437 0 : ip6_clearpktopts(opt, optname);
2438 0 : *newdest = malloc(destlen, M_IP6OPT, M_NOWAIT);
2439 0 : if (*newdest == NULL)
2440 0 : return (ENOBUFS);
2441 0 : memcpy(*newdest, dest, destlen);
2442 :
2443 0 : break;
2444 : }
2445 :
2446 : case IPV6_RTHDR:
2447 : {
2448 : struct ip6_rthdr *rth;
2449 : int rthlen;
2450 :
2451 0 : if (len == 0) {
2452 0 : ip6_clearpktopts(opt, IPV6_RTHDR);
2453 0 : break; /* just remove the option */
2454 : }
2455 :
2456 : /* message length validation */
2457 0 : if (len < sizeof(struct ip6_rthdr))
2458 0 : return (EINVAL);
2459 0 : rth = (struct ip6_rthdr *)buf;
2460 0 : rthlen = (rth->ip6r_len + 1) << 3;
2461 0 : if (len != rthlen)
2462 0 : return (EINVAL);
2463 :
2464 0 : switch (rth->ip6r_type) {
2465 : case IPV6_RTHDR_TYPE_0:
2466 0 : if (rth->ip6r_len == 0) /* must contain one addr */
2467 0 : return (EINVAL);
2468 0 : if (rth->ip6r_len % 2) /* length must be even */
2469 0 : return (EINVAL);
2470 0 : if (rth->ip6r_len / 2 != rth->ip6r_segleft)
2471 0 : return (EINVAL);
2472 : break;
2473 : default:
2474 0 : return (EINVAL); /* not supported */
2475 : }
2476 : /* turn off the previous option */
2477 0 : ip6_clearpktopts(opt, IPV6_RTHDR);
2478 0 : opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_NOWAIT);
2479 0 : if (opt->ip6po_rthdr == NULL)
2480 0 : return (ENOBUFS);
2481 0 : memcpy(opt->ip6po_rthdr, rth, rthlen);
2482 0 : break;
2483 : }
2484 :
2485 : case IPV6_USE_MIN_MTU:
2486 0 : if (len != sizeof(int))
2487 0 : return (EINVAL);
2488 0 : minmtupolicy = *(int *)buf;
2489 0 : if (minmtupolicy != IP6PO_MINMTU_MCASTONLY &&
2490 0 : minmtupolicy != IP6PO_MINMTU_DISABLE &&
2491 0 : minmtupolicy != IP6PO_MINMTU_ALL) {
2492 0 : return (EINVAL);
2493 : }
2494 0 : opt->ip6po_minmtu = minmtupolicy;
2495 0 : break;
2496 :
2497 : case IPV6_DONTFRAG:
2498 0 : if (len != sizeof(int))
2499 0 : return (EINVAL);
2500 :
2501 0 : if (uproto == IPPROTO_TCP || *(int *)buf == 0) {
2502 : /*
2503 : * we ignore this option for TCP sockets.
2504 : * (RFC3542 leaves this case unspecified.)
2505 : */
2506 0 : opt->ip6po_flags &= ~IP6PO_DONTFRAG;
2507 0 : } else
2508 0 : opt->ip6po_flags |= IP6PO_DONTFRAG;
2509 : break;
2510 :
2511 : default:
2512 0 : return (ENOPROTOOPT);
2513 : } /* end of switch */
2514 :
2515 0 : return (0);
2516 0 : }
2517 :
2518 : /*
2519 : * Routine called from ip6_output() to loop back a copy of an IP6 multicast
2520 : * packet to the input queue of a specified interface.
2521 : */
2522 : void
2523 0 : ip6_mloopback(struct ifnet *ifp, struct mbuf *m, struct sockaddr_in6 *dst)
2524 : {
2525 : struct mbuf *copym;
2526 : struct ip6_hdr *ip6;
2527 :
2528 : /*
2529 : * Duplicate the packet.
2530 : */
2531 0 : copym = m_copym(m, 0, M_COPYALL, M_NOWAIT);
2532 0 : if (copym == NULL)
2533 0 : return;
2534 :
2535 : /*
2536 : * Make sure to deep-copy IPv6 header portion in case the data
2537 : * is in an mbuf cluster, so that we can safely override the IPv6
2538 : * header portion later.
2539 : */
2540 0 : if ((copym->m_flags & M_EXT) != 0 ||
2541 0 : copym->m_len < sizeof(struct ip6_hdr)) {
2542 0 : copym = m_pullup(copym, sizeof(struct ip6_hdr));
2543 0 : if (copym == NULL)
2544 0 : return;
2545 : }
2546 :
2547 : #ifdef DIAGNOSTIC
2548 0 : if (copym->m_len < sizeof(*ip6)) {
2549 0 : m_freem(copym);
2550 0 : return;
2551 : }
2552 : #endif
2553 :
2554 0 : ip6 = mtod(copym, struct ip6_hdr *);
2555 0 : if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
2556 0 : ip6->ip6_src.s6_addr16[1] = 0;
2557 0 : if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
2558 0 : ip6->ip6_dst.s6_addr16[1] = 0;
2559 :
2560 0 : if_input_local(ifp, copym, dst->sin6_family);
2561 0 : }
2562 :
2563 : /*
2564 : * Chop IPv6 header off from the payload.
2565 : */
2566 : int
2567 0 : ip6_splithdr(struct mbuf *m, struct ip6_exthdrs *exthdrs)
2568 : {
2569 : struct mbuf *mh;
2570 : struct ip6_hdr *ip6;
2571 :
2572 0 : ip6 = mtod(m, struct ip6_hdr *);
2573 0 : if (m->m_len > sizeof(*ip6)) {
2574 0 : MGETHDR(mh, M_DONTWAIT, MT_HEADER);
2575 0 : if (mh == NULL) {
2576 0 : m_freem(m);
2577 0 : return ENOBUFS;
2578 : }
2579 0 : M_MOVE_PKTHDR(mh, m);
2580 0 : MH_ALIGN(mh, sizeof(*ip6));
2581 0 : m->m_len -= sizeof(*ip6);
2582 0 : m->m_data += sizeof(*ip6);
2583 0 : mh->m_next = m;
2584 : m = mh;
2585 0 : m->m_len = sizeof(*ip6);
2586 0 : bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6));
2587 0 : }
2588 0 : exthdrs->ip6e_ip6 = m;
2589 0 : return 0;
2590 0 : }
2591 :
2592 : u_int32_t
2593 0 : ip6_randomid(void)
2594 : {
2595 0 : return idgen32(&ip6_id_ctx);
2596 : }
2597 :
2598 : void
2599 0 : ip6_randomid_init(void)
2600 : {
2601 0 : idgen32_init(&ip6_id_ctx);
2602 0 : }
2603 :
2604 : /*
2605 : * Compute significant parts of the IPv6 checksum pseudo-header
2606 : * for use in a delayed TCP/UDP checksum calculation.
2607 : */
2608 : static __inline u_int16_t __attribute__((__unused__))
2609 0 : in6_cksum_phdr(const struct in6_addr *src, const struct in6_addr *dst,
2610 : u_int32_t len, u_int32_t nxt)
2611 : {
2612 : u_int32_t sum = 0;
2613 : const u_int16_t *w;
2614 :
2615 0 : w = (const u_int16_t *) src;
2616 0 : sum += w[0];
2617 0 : if (!IN6_IS_SCOPE_EMBED(src))
2618 0 : sum += w[1];
2619 0 : sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
2620 0 : sum += w[6]; sum += w[7];
2621 :
2622 0 : w = (const u_int16_t *) dst;
2623 0 : sum += w[0];
2624 0 : if (!IN6_IS_SCOPE_EMBED(dst))
2625 0 : sum += w[1];
2626 0 : sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
2627 0 : sum += w[6]; sum += w[7];
2628 :
2629 0 : sum += (u_int16_t)(len >> 16) + (u_int16_t)(len /*& 0xffff*/);
2630 :
2631 0 : sum += (u_int16_t)(nxt >> 16) + (u_int16_t)(nxt /*& 0xffff*/);
2632 :
2633 0 : sum = (u_int16_t)(sum >> 16) + (u_int16_t)(sum /*& 0xffff*/);
2634 :
2635 0 : if (sum > 0xffff)
2636 0 : sum -= 0xffff;
2637 :
2638 0 : return (sum);
2639 : }
2640 :
2641 : /*
2642 : * Process a delayed payload checksum calculation.
2643 : */
2644 : void
2645 0 : in6_delayed_cksum(struct mbuf *m, u_int8_t nxt)
2646 : {
2647 0 : int nxtp, offset;
2648 0 : u_int16_t csum;
2649 :
2650 0 : offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxtp);
2651 0 : if (offset <= 0 || nxtp != nxt)
2652 : /* If the desired next protocol isn't found, punt. */
2653 0 : return;
2654 0 : csum = (u_int16_t)(in6_cksum(m, 0, offset, m->m_pkthdr.len - offset));
2655 :
2656 0 : switch (nxt) {
2657 : case IPPROTO_TCP:
2658 0 : offset += offsetof(struct tcphdr, th_sum);
2659 0 : break;
2660 :
2661 : case IPPROTO_UDP:
2662 0 : offset += offsetof(struct udphdr, uh_sum);
2663 0 : if (csum == 0)
2664 0 : csum = 0xffff;
2665 : break;
2666 :
2667 : case IPPROTO_ICMPV6:
2668 0 : offset += offsetof(struct icmp6_hdr, icmp6_cksum);
2669 0 : break;
2670 : }
2671 :
2672 0 : if ((offset + sizeof(u_int16_t)) > m->m_len)
2673 0 : m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
2674 : else
2675 0 : *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
2676 0 : }
2677 :
2678 : void
2679 0 : in6_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
2680 : {
2681 0 : struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
2682 :
2683 : /* some hw and in6_delayed_cksum need the pseudo header cksum */
2684 0 : if (m->m_pkthdr.csum_flags &
2685 : (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT|M_ICMP_CSUM_OUT)) {
2686 0 : int nxt, offset;
2687 0 : u_int16_t csum;
2688 :
2689 0 : offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
2690 0 : csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
2691 0 : htonl(m->m_pkthdr.len - offset), htonl(nxt));
2692 0 : if (nxt == IPPROTO_TCP)
2693 0 : offset += offsetof(struct tcphdr, th_sum);
2694 0 : else if (nxt == IPPROTO_UDP)
2695 0 : offset += offsetof(struct udphdr, uh_sum);
2696 0 : else if (nxt == IPPROTO_ICMPV6)
2697 0 : offset += offsetof(struct icmp6_hdr, icmp6_cksum);
2698 0 : if ((offset + sizeof(u_int16_t)) > m->m_len)
2699 0 : m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
2700 : else
2701 0 : *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
2702 0 : }
2703 :
2704 0 : if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
2705 0 : if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_TCPv6) ||
2706 0 : ip6->ip6_nxt != IPPROTO_TCP ||
2707 0 : ifp->if_bridgeport != NULL) {
2708 0 : tcpstat_inc(tcps_outswcsum);
2709 0 : in6_delayed_cksum(m, IPPROTO_TCP);
2710 0 : m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */
2711 0 : }
2712 0 : } else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
2713 0 : if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv6) ||
2714 0 : ip6->ip6_nxt != IPPROTO_UDP ||
2715 0 : ifp->if_bridgeport != NULL) {
2716 0 : udpstat_inc(udps_outswcsum);
2717 0 : in6_delayed_cksum(m, IPPROTO_UDP);
2718 0 : m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
2719 0 : }
2720 0 : } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) {
2721 0 : in6_delayed_cksum(m, IPPROTO_ICMPV6);
2722 0 : m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */
2723 0 : }
2724 0 : }
2725 :
2726 : #ifdef IPSEC
2727 : struct tdb *
2728 0 : ip6_output_ipsec_lookup(struct mbuf *m, int *error, struct inpcb *inp)
2729 : {
2730 : struct tdb *tdb;
2731 : struct m_tag *mtag;
2732 : struct tdb_ident *tdbi;
2733 :
2734 : /*
2735 : * Check if there was an outgoing SA bound to the flow
2736 : * from a transport protocol.
2737 : */
2738 :
2739 : /* Do we have any pending SAs to apply ? */
2740 0 : tdb = ipsp_spd_lookup(m, AF_INET6, sizeof(struct ip6_hdr),
2741 : error, IPSP_DIRECTION_OUT, NULL, inp, 0);
2742 :
2743 0 : if (tdb == NULL)
2744 0 : return NULL;
2745 : /* Loop detection */
2746 0 : for (mtag = m_tag_first(m); mtag != NULL; mtag = m_tag_next(m, mtag)) {
2747 0 : if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE)
2748 : continue;
2749 0 : tdbi = (struct tdb_ident *)(mtag + 1);
2750 0 : if (tdbi->spi == tdb->tdb_spi &&
2751 0 : tdbi->proto == tdb->tdb_sproto &&
2752 0 : tdbi->rdomain == tdb->tdb_rdomain &&
2753 0 : !memcmp(&tdbi->dst, &tdb->tdb_dst,
2754 : sizeof(union sockaddr_union))) {
2755 : /* no IPsec needed */
2756 0 : return NULL;
2757 : }
2758 : }
2759 0 : return tdb;
2760 0 : }
2761 :
2762 : int
2763 0 : ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, int tunalready, int fwd)
2764 : {
2765 : #if NPF > 0
2766 : struct ifnet *encif;
2767 : #endif
2768 : int error;
2769 :
2770 : #if NPF > 0
2771 0 : if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL ||
2772 0 : pf_test(AF_INET6, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) {
2773 0 : m_freem(m);
2774 0 : return EHOSTUNREACH;
2775 : }
2776 0 : if (m == NULL)
2777 0 : return 0;
2778 : /*
2779 : * PF_TAG_REROUTE handling or not...
2780 : * Packet is entering IPsec so the routing is
2781 : * already overruled by the IPsec policy.
2782 : * Until now the change was not reconsidered.
2783 : * What's the behaviour?
2784 : */
2785 0 : in6_proto_cksum_out(m, encif);
2786 : #endif
2787 0 : m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
2788 :
2789 : /* Callee frees mbuf */
2790 0 : error = ipsp_process_packet(m, tdb, AF_INET6, tunalready);
2791 0 : if (error) {
2792 0 : ipsecstat_inc(ipsec_odrops);
2793 0 : tdb->tdb_odrops++;
2794 0 : }
2795 0 : return error;
2796 0 : }
2797 : #endif /* IPSEC */
|