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