Annotation of src/sys/netinet6/raw_ip6.c, Revision 1.23
1.23 ! itojun 1: /* $NetBSD: raw_ip6.c,v 1.22 2000/03/01 12:49:50 itojun Exp $ */
! 2: /* $KAME: raw_ip6.c,v 1.28 2000/05/28 23:25:07 itojun Exp $ */
1.3 thorpej 3:
1.2 itojun 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, 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. All advertising materials mentioning features or use of this software
46: * must display the following acknowledgement:
47: * This product includes software developed by the University of
48: * California, Berkeley and its contributors.
49: * 4. Neither the name of the University nor the names of its contributors
50: * may be used to endorse or promote products derived from this software
51: * without specific prior written permission.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63: * SUCH DAMAGE.
64: *
65: * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
66: */
1.6 thorpej 67:
68: #include "opt_ipsec.h"
1.2 itojun 69:
70: #include <sys/param.h>
71: #include <sys/malloc.h>
72: #include <sys/mbuf.h>
73: #include <sys/socket.h>
74: #include <sys/protosw.h>
75: #include <sys/socketvar.h>
76: #include <sys/errno.h>
77: #include <sys/systm.h>
78: #include <sys/proc.h>
79:
80: #include <net/if.h>
81: #include <net/route.h>
82: #include <net/if_types.h>
83:
84: #include <netinet/in.h>
85: #include <netinet/in_var.h>
1.19 itojun 86: #include <netinet/ip6.h>
1.2 itojun 87: #include <netinet6/ip6_var.h>
88: #include <netinet6/ip6_mroute.h>
1.19 itojun 89: #include <netinet/icmp6.h>
1.2 itojun 90: #include <netinet6/in6_pcb.h>
91: #include <netinet6/nd6.h>
1.20 itojun 92: #include <netinet6/ip6protosw.h>
1.2 itojun 93:
94: #ifdef IPSEC
95: #include <netinet6/ipsec.h>
96: #endif /*IPSEC*/
97:
98: #include <machine/stdarg.h>
99:
100: #include "faith.h"
101:
102: struct in6pcb rawin6pcb;
103: #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
104:
105: /*
106: * Raw interface to IP6 protocol.
107: */
108:
109: /*
110: * Initialize raw connection block queue.
111: */
112: void
113: rip6_init()
114: {
115: rawin6pcb.in6p_next = rawin6pcb.in6p_prev = &rawin6pcb;
116: }
117:
118: /*
119: * Setup generic address and protocol structures
120: * for raw_input routine, then pass them along with
121: * mbuf chain.
122: */
123: int
124: rip6_input(mp, offp, proto)
125: struct mbuf **mp;
126: int *offp, proto;
127: {
128: struct mbuf *m = *mp;
129: register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
130: register struct in6pcb *in6p;
131: struct in6pcb *last = NULL;
132: struct sockaddr_in6 rip6src;
133: struct mbuf *opts = NULL;
134:
135: #if defined(NFAITH) && 0 < NFAITH
136: if (m->m_pkthdr.rcvif) {
137: if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
138: /* send icmp6 host unreach? */
139: m_freem(m);
140: return IPPROTO_DONE;
141: }
142: }
143: #endif
1.14 itojun 144:
145: /* Be proactive about malicious use of IPv4 mapped address */
146: if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
147: IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
148: /* XXX stat */
149: m_freem(m);
150: return IPPROTO_DONE;
151: }
152:
1.2 itojun 153: bzero(&rip6src, sizeof(rip6src));
154: rip6src.sin6_len = sizeof(struct sockaddr_in6);
155: rip6src.sin6_family = AF_INET6;
156: rip6src.sin6_addr = ip6->ip6_src;
157: if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr))
158: rip6src.sin6_addr.s6_addr16[1] = 0;
159: if (m->m_pkthdr.rcvif) {
160: if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr))
161: rip6src.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
162: else
163: rip6src.sin6_scope_id = 0;
164: } else
165: rip6src.sin6_scope_id = 0;
166:
167: for (in6p = rawin6pcb.in6p_next;
168: in6p != &rawin6pcb; in6p = in6p->in6p_next) {
169: if (in6p->in6p_ip6.ip6_nxt &&
170: in6p->in6p_ip6.ip6_nxt != proto)
171: continue;
1.12 itojun 172: if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1.2 itojun 173: !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
174: continue;
1.12 itojun 175: if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
1.2 itojun 176: !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
177: continue;
178: if (in6p->in6p_cksum != -1
1.7 itojun 179: && in6_cksum(m, ip6->ip6_nxt, *offp, m->m_pkthdr.len - *offp))
180: {
1.2 itojun 181: /* XXX bark something */
182: continue;
183: }
184: if (last) {
185: struct mbuf *n;
186: if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
187: if (last->in6p_flags & IN6P_CONTROLOPTS)
188: ip6_savecontrol(last, &opts, ip6, n);
189: /* strip intermediate headers */
190: m_adj(n, *offp);
191: if (sbappendaddr(&last->in6p_socket->so_rcv,
192: (struct sockaddr *)&rip6src,
193: n, opts) == 0) {
194: /* should notify about lost packet */
195: m_freem(n);
196: if (opts)
197: m_freem(opts);
198: } else
199: sorwakeup(last->in6p_socket);
200: opts = NULL;
201: }
202: }
203: last = in6p;
204: }
205: if (last) {
206: if (last->in6p_flags & IN6P_CONTROLOPTS)
207: ip6_savecontrol(last, &opts, ip6, m);
208: /* strip intermediate headers */
209: m_adj(m, *offp);
210: if (sbappendaddr(&last->in6p_socket->so_rcv,
211: (struct sockaddr *)&rip6src, m, opts) == 0) {
212: m_freem(m);
213: if (opts)
214: m_freem(opts);
215: } else
216: sorwakeup(last->in6p_socket);
217: } else {
218: if (proto == IPPROTO_NONE)
219: m_freem(m);
220: else {
221: char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
222: icmp6_error(m, ICMP6_PARAM_PROB,
223: ICMP6_PARAMPROB_NEXTHEADER,
224: prvnxtp - mtod(m, char *));
225: }
226: ip6stat.ip6s_delivered--;
227: }
228: return IPPROTO_DONE;
229: }
230:
1.20 itojun 231: void
232: rip6_ctlinput(cmd, sa, d)
233: int cmd;
234: struct sockaddr *sa;
235: void *d;
236: {
237: struct sockaddr_in6 sa6;
238: register struct ip6_hdr *ip6;
239: struct mbuf *m;
240: int off;
1.21 itojun 241: void (*notify) __P((struct in6pcb *, int)) = in6_rtchange;
1.20 itojun 242:
243: if (sa->sa_family != AF_INET6 ||
244: sa->sa_len != sizeof(struct sockaddr_in6))
245: return;
246:
1.21 itojun 247: if ((unsigned)cmd >= PRC_NCMDS)
248: return;
249: if (PRC_IS_REDIRECT(cmd))
250: notify = in6_rtchange, d = NULL;
251: else if (cmd == PRC_HOSTDEAD)
252: d = NULL;
253: else if (inet6ctlerrmap[cmd] == 0)
1.20 itojun 254: return;
255:
256: /* if the parameter is from icmp6, decode it. */
257: if (d != NULL) {
258: struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
259: m = ip6cp->ip6c_m;
260: ip6 = ip6cp->ip6c_ip6;
261: off = ip6cp->ip6c_off;
262: } else {
263: m = NULL;
264: ip6 = NULL;
265: }
266:
267: /* translate addresses into internal form */
268: sa6 = *(struct sockaddr_in6 *)sa;
269: if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif)
270: sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
271:
272: if (ip6) {
273: /*
274: * XXX: We assume that when IPV6 is non NULL,
275: * M and OFF are valid.
276: */
277: struct in6_addr s;
278:
279: /* translate addresses into internal form */
280: memcpy(&s, &ip6->ip6_src, sizeof(s));
281: if (IN6_IS_ADDR_LINKLOCAL(&s))
282: s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
283:
284: (void) in6_pcbnotify(&rawin6pcb, (struct sockaddr *)&sa6,
1.21 itojun 285: 0, &s, 0, cmd, notify);
1.20 itojun 286: } else {
287: (void) in6_pcbnotify(&rawin6pcb, (struct sockaddr *)&sa6, 0,
1.21 itojun 288: &zeroin6_addr, 0, cmd, notify);
1.20 itojun 289: }
290: }
291:
1.2 itojun 292: /*
293: * Generate IPv6 header and pass packet to ip6_output.
294: * Tack on options user may have setup with control call.
295: */
296: int
297: #if __STDC__
298: rip6_output(struct mbuf *m, ...)
299: #else
300: rip6_output(m, va_alist)
301: struct mbuf *m;
302: va_dcl
303: #endif
304: {
305: struct socket *so;
306: struct sockaddr_in6 *dstsock;
307: struct mbuf *control;
308: struct in6_addr *dst;
309: struct ip6_hdr *ip6;
310: struct in6pcb *in6p;
311: u_int plen = m->m_pkthdr.len;
312: int error = 0;
313: struct ip6_pktopts opt, *optp = NULL;
314: struct ifnet *oifp = NULL;
1.12 itojun 315: int type, code; /* for ICMPv6 output statistics only */
1.20 itojun 316: int priv = 0;
1.2 itojun 317: va_list ap;
318:
319: va_start(ap, m);
320: so = va_arg(ap, struct socket *);
321: dstsock = va_arg(ap, struct sockaddr_in6 *);
322: control = va_arg(ap, struct mbuf *);
323: va_end(ap);
324:
325: in6p = sotoin6pcb(so);
326:
1.12 itojun 327: priv = 0;
328: {
329: struct proc *p = curproc; /* XXX */
330:
331: if (p && !suser(p->p_ucred, &p->p_acflag))
332: priv = 1;
333: }
1.2 itojun 334: dst = &dstsock->sin6_addr;
335: if (control) {
336: if ((error = ip6_setpktoptions(control, &opt, priv)) != 0)
337: goto bad;
338: optp = &opt;
339: } else
340: optp = in6p->in6p_outputopts;
341:
1.12 itojun 342: /*
343: * For an ICMPv6 packet, we should know its type and code
344: * to update statistics.
345: */
346: if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
347: struct icmp6_hdr *icmp6;
348: if (m->m_len < sizeof(struct icmp6_hdr) &&
349: (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
350: error = ENOBUFS;
351: goto bad;
352: }
353: icmp6 = mtod(m, struct icmp6_hdr *);
354: type = icmp6->icmp6_type;
355: code = icmp6->icmp6_code;
356: }
357:
1.2 itojun 358: M_PREPEND(m, sizeof(*ip6), M_WAIT);
359: ip6 = mtod(m, struct ip6_hdr *);
360:
361: /*
362: * Next header might not be ICMP6 but use its pseudo header anyway.
363: */
364: ip6->ip6_dst = *dst;
365:
366: /*
367: * If the scope of the destination is link-local, embed the interface
368: * index in the address.
369: *
370: * XXX advanced-api value overrides sin6_scope_id
371: */
1.12 itojun 372: if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst) ||
373: IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) {
1.2 itojun 374: struct in6_pktinfo *pi;
375:
376: /*
377: * XXX Boundary check is assumed to be already done in
1.12 itojun 378: * ip6_setpktoptions().
1.2 itojun 379: */
380: if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) {
381: ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex);
382: oifp = ifindex2ifnet[pi->ipi6_ifindex];
383: }
384: else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
385: in6p->in6p_moptions &&
386: in6p->in6p_moptions->im6o_multicast_ifp) {
1.12 itojun 387: oifp = in6p->in6p_moptions->im6o_multicast_ifp;
388: ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index);
1.2 itojun 389: } else if (dstsock->sin6_scope_id) {
390: /* boundary check */
391: if (dstsock->sin6_scope_id < 0
392: || if_index < dstsock->sin6_scope_id) {
393: error = ENXIO; /* XXX EINVAL? */
394: goto bad;
395: }
396: ip6->ip6_dst.s6_addr16[1]
397: = htons(dstsock->sin6_scope_id & 0xffff);/*XXX*/
398: }
399: }
400:
1.12 itojun 401: /*
402: * Source address selection.
403: */
404: {
1.2 itojun 405: struct in6_addr *in6a;
406:
407: if ((in6a = in6_selectsrc(dstsock, optp,
408: in6p->in6p_moptions,
409: &in6p->in6p_route,
1.12 itojun 410: &in6p->in6p_laddr,
1.2 itojun 411: &error)) == 0) {
412: if (error == 0)
413: error = EADDRNOTAVAIL;
414: goto bad;
415: }
416: ip6->ip6_src = *in6a;
417: if (in6p->in6p_route.ro_rt)
418: oifp = ifindex2ifnet[in6p->in6p_route.ro_rt->rt_ifp->if_index];
1.12 itojun 419: }
1.2 itojun 420:
421: ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
1.20 itojun 422: ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
423: ip6->ip6_vfc |= IPV6_VERSION;
1.2 itojun 424: #if 0 /* ip6_plen will be filled in ip6_output. */
425: ip6->ip6_plen = htons((u_short)plen);
426: #endif
427: ip6->ip6_nxt = in6p->in6p_ip6.ip6_nxt;
1.12 itojun 428: ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
1.2 itojun 429:
430: if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
431: in6p->in6p_cksum != -1) {
432: struct mbuf *n;
433: int off;
434: u_int16_t *p;
435:
436: #define offsetof(type, member) ((size_t)(&((type *)0)->member)) /* XXX */
437:
438: /* compute checksum */
439: if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
440: off = offsetof(struct icmp6_hdr, icmp6_cksum);
441: else
442: off = in6p->in6p_cksum;
443: if (plen < off + 1) {
444: error = EINVAL;
445: goto bad;
446: }
447: off += sizeof(struct ip6_hdr);
448:
449: n = m;
450: while (n && n->m_len <= off) {
451: off -= n->m_len;
452: n = n->m_next;
453: }
454: if (!n)
455: goto bad;
456: p = (u_int16_t *)(mtod(n, caddr_t) + off);
457: *p = 0;
458: *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
459: }
460:
1.12 itojun 461: error = ip6_output(m, optp, &in6p->in6p_route, 0, in6p->in6p_moptions,
462: &oifp);
463: if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
464: if (oifp)
465: icmp6_ifoutstat_inc(oifp, type, code);
466: icmp6stat.icp6s_outhist[type]++;
467: }
1.2 itojun 468:
469: goto freectl;
470:
471: bad:
472: if (m)
473: m_freem(m);
474:
475: freectl:
476: if (optp == &opt && optp->ip6po_rthdr && optp->ip6po_route.ro_rt)
477: RTFREE(optp->ip6po_route.ro_rt);
478: if (control)
479: m_freem(control);
480: return(error);
481: }
482:
483: /*
484: * Raw IPv6 socket option processing.
485: */
486: int
487: rip6_ctloutput(op, so, level, optname, m)
488: int op;
489: struct socket *so;
490: int level, optname;
491: struct mbuf **m;
492: {
493: int error = 0;
494:
495: switch(level) {
496: case IPPROTO_IPV6:
497: switch(optname) {
498: case MRT6_INIT:
499: case MRT6_DONE:
500: case MRT6_ADD_MIF:
501: case MRT6_DEL_MIF:
502: case MRT6_ADD_MFC:
503: case MRT6_DEL_MFC:
504: case MRT6_PIM:
505: if (op == PRCO_SETOPT) {
506: error = ip6_mrouter_set(optname, so, *m);
507: if (*m)
508: (void)m_free(*m);
509: } else if (op == PRCO_GETOPT) {
510: error = ip6_mrouter_get(optname, so, m);
511: } else
512: error = EINVAL;
513: return (error);
514: }
515: return (ip6_ctloutput(op, so, level, optname, m));
516: /* NOTREACHED */
517:
518: case IPPROTO_ICMPV6:
519: /*
520: * XXX: is it better to call icmp6_ctloutput() directly
521: * from protosw?
522: */
523: return(icmp6_ctloutput(op, so, level, optname, m));
524:
525: default:
526: if (op == PRCO_SETOPT && *m)
527: (void)m_free(*m);
528: return(EINVAL);
529: }
530: }
531:
532: extern u_long rip6_sendspace;
533: extern u_long rip6_recvspace;
534:
535: int
536: rip6_usrreq(so, req, m, nam, control, p)
537: register struct socket *so;
538: int req;
539: struct mbuf *m, *nam, *control;
540: struct proc *p;
541: {
542: register struct in6pcb *in6p = sotoin6pcb(so);
543: int s;
544: int error = 0;
545: /* extern struct socket *ip6_mrouter; */ /* xxx */
1.12 itojun 546: int priv;
547:
548: priv = 0;
549: if (p && !suser(p->p_ucred, &p->p_acflag))
550: priv++;
1.2 itojun 551:
552: if (req == PRU_CONTROL)
553: return (in6_control(so, (u_long)m, (caddr_t)nam,
554: (struct ifnet *)control, p));
1.17 thorpej 555:
1.18 thorpej 556: if (req == PRU_PURGEIF) {
557: in6_purgeif((struct ifnet *)control);
558: in6_pcbpurgeif(&rawin6pcb, (struct ifnet *)control);
1.17 thorpej 559: return (0);
560: }
1.2 itojun 561:
562: switch (req) {
563: case PRU_ATTACH:
564: if (in6p)
565: panic("rip6_attach");
1.12 itojun 566: if (!priv) {
1.2 itojun 567: error = EACCES;
568: break;
569: }
1.4 itojun 570: s = splsoftnet();
1.2 itojun 571: if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) ||
572: (error = in6_pcballoc(so, &rawin6pcb))) {
573: splx(s);
574: break;
575: }
576: splx(s);
577: in6p = sotoin6pcb(so);
1.5 itojun 578: in6p->in6p_ip6.ip6_nxt = (long)nam;
1.2 itojun 579: in6p->in6p_cksum = -1;
580: #ifdef IPSEC
1.16 itojun 581: error = ipsec_init_policy(so, &in6p->in6p_sp);
1.12 itojun 582: if (error != 0) {
1.11 itojun 583: in6_pcbdetach(in6p);
1.2 itojun 584: break;
1.11 itojun 585: }
1.2 itojun 586: #endif /*IPSEC*/
587:
588: MALLOC(in6p->in6p_icmp6filt, struct icmp6_filter *,
589: sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
1.12 itojun 590: if (in6p->in6p_icmp6filt == NULL) {
591: in6_pcbdetach(in6p);
592: error = ENOMEM;
593: break;
594: }
1.2 itojun 595: ICMP6_FILTER_SETPASSALL(in6p->in6p_icmp6filt);
596: break;
597:
598: case PRU_DISCONNECT:
599: if ((so->so_state & SS_ISCONNECTED) == 0) {
600: error = ENOTCONN;
601: break;
602: }
603: in6p->in6p_faddr = in6addr_any;
604: so->so_state &= ~SS_ISCONNECTED; /* XXX */
605: break;
606:
607: case PRU_ABORT:
608: soisdisconnected(so);
609: /* Fallthrough */
610: case PRU_DETACH:
611: if (in6p == 0)
612: panic("rip6_detach");
613: if (so == ip6_mrouter)
614: ip6_mrouter_done();
615: /* xxx: RSVP */
616: if (in6p->in6p_icmp6filt) {
617: FREE(in6p->in6p_icmp6filt, M_PCB);
618: in6p->in6p_icmp6filt = NULL;
619: }
620: in6_pcbdetach(in6p);
621: break;
622:
623: case PRU_BIND:
624: {
625: struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *);
626: struct ifaddr *ia = NULL;
627:
628: if (nam->m_len != sizeof(*addr)) {
629: error = EINVAL;
630: break;
631: }
1.23 ! itojun 632:
! 633: /*
! 634: * we don't support mapped address here, it would confuse
! 635: * users so reject it
! 636: */
! 637: if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
! 638: error = EADDRNOTAVAIL;
! 639: break;
! 640: }
! 641:
1.2 itojun 642: if ((ifnet.tqh_first == 0) ||
643: (addr->sin6_family != AF_INET6) ||
1.12 itojun 644: (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
1.2 itojun 645: (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0)) {
646: error = EADDRNOTAVAIL;
647: break;
648: }
649: if (ia &&
650: ((struct in6_ifaddr *)ia)->ia6_flags &
651: (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
652: IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
653: error = EADDRNOTAVAIL;
654: break;
655: }
656: in6p->in6p_laddr = addr->sin6_addr;
657: break;
658: }
659:
660: case PRU_CONNECT:
661: {
662: struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *);
663: struct in6_addr *in6a = NULL;
664:
665: if (nam->m_len != sizeof(*addr)) {
666: error = EINVAL;
667: break;
668: }
669: if (ifnet.tqh_first == 0) {
670: error = EADDRNOTAVAIL;
671: break;
672: }
673: if (addr->sin6_family != AF_INET6) {
674: error = EAFNOSUPPORT;
675: break;
676: }
677:
678: /* Source address selection. XXX: need pcblookup? */
1.12 itojun 679: in6a = in6_selectsrc(addr, in6p->in6p_outputopts,
680: in6p->in6p_moptions,
681: &in6p->in6p_route,
682: &in6p->in6p_laddr,
683: &error);
684: if (in6a == NULL) {
1.2 itojun 685: if (error == 0)
686: error = EADDRNOTAVAIL;
687: break;
688: }
689: in6p->in6p_laddr = *in6a;
690: in6p->in6p_faddr = addr->sin6_addr;
691: soisconnected(so);
692: break;
693: }
694:
695: case PRU_CONNECT2:
696: error = EOPNOTSUPP;
697: break;
698:
699: /*
700: * Mark the connection as being incapable of futther input.
701: */
702: case PRU_SHUTDOWN:
703: socantsendmore(so);
704: break;
705: /*
706: * Ship a packet out. The appropriate raw output
707: * routine handles any messaging necessary.
708: */
709: case PRU_SEND:
710: {
711: struct sockaddr_in6 tmp;
712: struct sockaddr_in6 *dst;
713:
714: if (so->so_state & SS_ISCONNECTED) {
715: if (nam) {
716: error = EISCONN;
717: break;
718: }
719: /* XXX */
720: bzero(&tmp, sizeof(tmp));
721: tmp.sin6_family = AF_INET6;
722: tmp.sin6_len = sizeof(struct sockaddr_in6);
723: bcopy(&in6p->in6p_faddr, &tmp.sin6_addr,
724: sizeof(struct in6_addr));
725: dst = &tmp;
726: } else {
727: if (nam == NULL) {
728: error = ENOTCONN;
729: break;
730: }
731: dst = mtod(nam, struct sockaddr_in6 *);
732: }
733: error = rip6_output(m, so, dst, control);
734: m = NULL;
735: break;
736: }
737:
738: case PRU_SENSE:
739: /*
740: * stat: don't bother with a blocksize
741: */
742: return(0);
743: /*
744: * Not supported.
745: */
746: case PRU_RCVOOB:
747: case PRU_RCVD:
748: case PRU_LISTEN:
749: case PRU_ACCEPT:
750: case PRU_SENDOOB:
751: error = EOPNOTSUPP;
752: break;
753:
754: case PRU_SOCKADDR:
755: in6_setsockaddr(in6p, nam);
756: break;
757:
758: case PRU_PEERADDR:
759: in6_setpeeraddr(in6p, nam);
760: break;
761:
762: default:
763: panic("rip6_usrreq");
764: }
765: if (m != NULL)
766: m_freem(m);
767: return(error);
768: }
CVSweb <webmaster@jp.NetBSD.org>