1/* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 *
| 1/* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 *
|
29 * $FreeBSD: head/sys/netinet6/raw_ip6.c 98211 2002-06-14 08:35:21Z hsu $
| 29 * $FreeBSD: head/sys/netinet6/raw_ip6.c 105194 2002-10-16 01:54:46Z sam $
|
30 */ 31 32/* 33 * Copyright (c) 1982, 1986, 1988, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 65 */ 66 67#include "opt_ipsec.h" 68#include "opt_inet6.h" 69 70#include <sys/param.h> 71#include <sys/errno.h> 72#include <sys/lock.h> 73#include <sys/malloc.h> 74#include <sys/mbuf.h> 75#include <sys/proc.h> 76#include <sys/protosw.h> 77#include <sys/signalvar.h> 78#include <sys/socket.h> 79#include <sys/socketvar.h> 80#include <sys/sx.h> 81#include <sys/systm.h> 82 83#include <net/if.h> 84#include <net/if_types.h> 85#include <net/route.h> 86 87#include <netinet/in.h> 88#include <netinet/in_var.h> 89#include <netinet/in_systm.h> 90#include <netinet/icmp6.h> 91#include <netinet/in_pcb.h> 92#include <netinet/ip6.h> 93#include <netinet6/ip6protosw.h> 94#include <netinet6/ip6_mroute.h> 95#include <netinet6/in6_pcb.h> 96#include <netinet6/ip6_var.h> 97#include <netinet6/nd6.h> 98#include <netinet6/raw_ip6.h> 99#ifdef ENABLE_DEFAULT_SCOPE 100#include <netinet6/scope6_var.h> 101#endif 102 103#ifdef IPSEC 104#include <netinet6/ipsec.h> 105#include <netinet6/ipsec6.h> 106#endif /*IPSEC*/ 107 108#include <machine/stdarg.h> 109 110#define satosin6(sa) ((struct sockaddr_in6 *)(sa)) 111#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) 112 113/* 114 * Raw interface to IP6 protocol. 115 */ 116 117extern struct inpcbhead ripcb; 118extern struct inpcbinfo ripcbinfo; 119extern u_long rip_sendspace; 120extern u_long rip_recvspace; 121 122struct rip6stat rip6stat; 123 124/* 125 * Setup generic address and protocol structures 126 * for raw_input routine, then pass them along with 127 * mbuf chain. 128 */ 129int 130rip6_input(mp, offp, proto) 131 struct mbuf **mp; 132 int *offp, proto; 133{ 134 struct mbuf *m = *mp; 135 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 136 register struct inpcb *in6p; 137 struct inpcb *last = 0; 138 struct mbuf *opts = NULL; 139 struct sockaddr_in6 rip6src; 140 141 rip6stat.rip6s_ipackets++; 142 143 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { 144 /* XXX send icmp6 host/port unreach? */ 145 m_freem(m); 146 return IPPROTO_DONE; 147 } 148 149 init_sin6(&rip6src, m); /* general init */ 150 151 LIST_FOREACH(in6p, &ripcb, inp_list) { 152 if ((in6p->in6p_vflag & INP_IPV6) == 0) 153 continue; 154 if (in6p->in6p_ip6_nxt && 155 in6p->in6p_ip6_nxt != proto) 156 continue; 157 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 158 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 159 continue; 160 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 161 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 162 continue; 163 if (in6p->in6p_cksum != -1) { 164 rip6stat.rip6s_isum++; 165 if (in6_cksum(m, ip6->ip6_nxt, *offp, 166 m->m_pkthdr.len - *offp)) { 167 rip6stat.rip6s_badsum++; 168 continue; 169 } 170 } 171 if (last) { 172 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 173 174#ifdef IPSEC 175 /* 176 * Check AH/ESP integrity. 177 */ 178 if (n && ipsec6_in_reject_so(n, last->inp_socket)) { 179 m_freem(n); 180 ipsec6stat.in_polvio++; 181 /* do not inject data into pcb */ 182 } else 183#endif /*IPSEC*/ 184 if (n) { 185 if (last->in6p_flags & IN6P_CONTROLOPTS || 186 last->in6p_socket->so_options & SO_TIMESTAMP) 187 ip6_savecontrol(last, &opts, ip6, n); 188 /* strip intermediate headers */ 189 m_adj(n, *offp); 190 if (sbappendaddr(&last->in6p_socket->so_rcv, 191 (struct sockaddr *)&rip6src, 192 n, opts) == 0) { 193 m_freem(n); 194 if (opts) 195 m_freem(opts); 196 rip6stat.rip6s_fullsock++; 197 } else 198 sorwakeup(last->in6p_socket); 199 opts = NULL; 200 } 201 } 202 last = in6p; 203 } 204#ifdef IPSEC 205 /* 206 * Check AH/ESP integrity. 207 */ 208 if (last && ipsec6_in_reject_so(m, last->inp_socket)) { 209 m_freem(m); 210 ipsec6stat.in_polvio++; 211 ip6stat.ip6s_delivered--; 212 /* do not inject data into pcb */ 213 } else 214#endif /*IPSEC*/ 215 if (last) { 216 if (last->in6p_flags & IN6P_CONTROLOPTS || 217 last->in6p_socket->so_options & SO_TIMESTAMP) 218 ip6_savecontrol(last, &opts, ip6, m); 219 /* strip intermediate headers */ 220 m_adj(m, *offp); 221 if (sbappendaddr(&last->in6p_socket->so_rcv, 222 (struct sockaddr *)&rip6src, m, opts) == 0) { 223 m_freem(m); 224 if (opts) 225 m_freem(opts); 226 rip6stat.rip6s_fullsock++; 227 } else 228 sorwakeup(last->in6p_socket); 229 } else { 230 rip6stat.rip6s_nosock++; 231 if (m->m_flags & M_MCAST) 232 rip6stat.rip6s_nosockmcast++; 233 if (proto == IPPROTO_NONE) 234 m_freem(m); 235 else { 236 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 237 icmp6_error(m, ICMP6_PARAM_PROB, 238 ICMP6_PARAMPROB_NEXTHEADER, 239 prvnxtp - mtod(m, char *)); 240 } 241 ip6stat.ip6s_delivered--; 242 } 243 return IPPROTO_DONE; 244} 245 246void 247rip6_ctlinput(cmd, sa, d) 248 int cmd; 249 struct sockaddr *sa; 250 void *d; 251{ 252 struct ip6_hdr *ip6; 253 struct mbuf *m; 254 int off = 0; 255 struct ip6ctlparam *ip6cp = NULL; 256 const struct sockaddr_in6 *sa6_src = NULL; 257 struct inpcb *(*notify) __P((struct inpcb *, int)) = in6_rtchange; 258 259 if (sa->sa_family != AF_INET6 || 260 sa->sa_len != sizeof(struct sockaddr_in6)) 261 return; 262 263 if ((unsigned)cmd >= PRC_NCMDS) 264 return; 265 if (PRC_IS_REDIRECT(cmd)) 266 notify = in6_rtchange, d = NULL; 267 else if (cmd == PRC_HOSTDEAD) 268 d = NULL; 269 else if (inet6ctlerrmap[cmd] == 0) 270 return; 271 272 /* if the parameter is from icmp6, decode it. */ 273 if (d != NULL) { 274 ip6cp = (struct ip6ctlparam *)d; 275 m = ip6cp->ip6c_m; 276 ip6 = ip6cp->ip6c_ip6; 277 off = ip6cp->ip6c_off; 278 sa6_src = ip6cp->ip6c_src; 279 } else { 280 m = NULL; 281 ip6 = NULL; 282 sa6_src = &sa6_any; 283 } 284 285 (void) in6_pcbnotify(&ripcb, sa, 0, (const struct sockaddr *)sa6_src, 286 0, cmd, notify); 287} 288 289/* 290 * Generate IPv6 header and pass packet to ip6_output. 291 * Tack on options user may have setup with control call. 292 */ 293int 294#if __STDC__ 295rip6_output(struct mbuf *m, ...) 296#else 297rip6_output(m, va_alist) 298 struct mbuf *m; 299 va_dcl 300#endif 301{ 302 struct socket *so; 303 struct sockaddr_in6 *dstsock; 304 struct mbuf *control; 305 struct in6_addr *dst; 306 struct ip6_hdr *ip6; 307 struct inpcb *in6p; 308 u_int plen = m->m_pkthdr.len; 309 int error = 0; 310 struct ip6_pktopts opt, *optp = 0; 311 struct ifnet *oifp = NULL; 312 int type = 0, code = 0; /* for ICMPv6 output statistics only */ 313 int priv = 0; 314 va_list ap; 315 316 va_start(ap, m); 317 so = va_arg(ap, struct socket *); 318 dstsock = va_arg(ap, struct sockaddr_in6 *); 319 control = va_arg(ap, struct mbuf *); 320 va_end(ap); 321 322 in6p = sotoin6pcb(so); 323 324 priv = 0; 325 if (so->so_cred->cr_uid == 0) 326 priv = 1; 327 dst = &dstsock->sin6_addr; 328 if (control) { 329 if ((error = ip6_setpktoptions(control, &opt, priv, 0)) != 0) 330 goto bad; 331 optp = &opt; 332 } else 333 optp = in6p->in6p_outputopts; 334 335 /* 336 * For an ICMPv6 packet, we should know its type and code 337 * to update statistics. 338 */ 339 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 340 struct icmp6_hdr *icmp6; 341 if (m->m_len < sizeof(struct icmp6_hdr) && 342 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { 343 error = ENOBUFS; 344 goto bad; 345 } 346 icmp6 = mtod(m, struct icmp6_hdr *); 347 type = icmp6->icmp6_type; 348 code = icmp6->icmp6_code; 349 } 350 351 M_PREPEND(m, sizeof(*ip6), M_TRYWAIT); 352 ip6 = mtod(m, struct ip6_hdr *); 353 354 /* 355 * Next header might not be ICMP6 but use its pseudo header anyway. 356 */ 357 ip6->ip6_dst = *dst; 358 359 /* 360 * If the scope of the destination is link-local, embed the interface 361 * index in the address. 362 * 363 * XXX advanced-api value overrides sin6_scope_id 364 */ 365 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 366 struct in6_pktinfo *pi; 367 368 /* 369 * XXX Boundary check is assumed to be already done in 370 * ip6_setpktoptions(). 371 */ 372 if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) { 373 ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex); 374 oifp = ifnet_byindex(pi->ipi6_ifindex); 375 } else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && 376 in6p->in6p_moptions && 377 in6p->in6p_moptions->im6o_multicast_ifp) { 378 oifp = in6p->in6p_moptions->im6o_multicast_ifp; 379 ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index); 380 } else if (dstsock->sin6_scope_id) { 381 /* boundary check */ 382 if (dstsock->sin6_scope_id < 0 383 || if_index < dstsock->sin6_scope_id) { 384 error = ENXIO; /* XXX EINVAL? */ 385 goto bad; 386 } 387 ip6->ip6_dst.s6_addr16[1] 388 = htons(dstsock->sin6_scope_id & 0xffff);/*XXX*/ 389 } 390 } 391 392 /* 393 * Source address selection. 394 */ 395 { 396 struct in6_addr *in6a; 397 398 if ((in6a = in6_selectsrc(dstsock, optp, 399 in6p->in6p_moptions, 400 &in6p->in6p_route, 401 &in6p->in6p_laddr, 402 &error)) == 0) { 403 if (error == 0) 404 error = EADDRNOTAVAIL; 405 goto bad; 406 } 407 ip6->ip6_src = *in6a; 408 if (in6p->in6p_route.ro_rt) 409 oifp = ifnet_byindex(in6p->in6p_route.ro_rt->rt_ifp->if_index); 410 } 411 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | 412 (in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK); 413 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) | 414 (IPV6_VERSION & IPV6_VERSION_MASK); 415 /* ip6_plen will be filled in ip6_output, so not fill it here. */ 416 ip6->ip6_nxt = in6p->in6p_ip6_nxt; 417 ip6->ip6_hlim = in6_selecthlim(in6p, oifp); 418 419 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 || 420 in6p->in6p_cksum != -1) { 421 struct mbuf *n; 422 int off; 423 u_int16_t *p; 424 425 /* compute checksum */ 426 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) 427 off = offsetof(struct icmp6_hdr, icmp6_cksum); 428 else 429 off = in6p->in6p_cksum; 430 if (plen < off + 1) { 431 error = EINVAL; 432 goto bad; 433 } 434 off += sizeof(struct ip6_hdr); 435 436 n = m; 437 while (n && n->m_len <= off) { 438 off -= n->m_len; 439 n = n->m_next; 440 } 441 if (!n) 442 goto bad; 443 p = (u_int16_t *)(mtod(n, caddr_t) + off); 444 *p = 0; 445 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 446 } 447
| 30 */ 31 32/* 33 * Copyright (c) 1982, 1986, 1988, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 65 */ 66 67#include "opt_ipsec.h" 68#include "opt_inet6.h" 69 70#include <sys/param.h> 71#include <sys/errno.h> 72#include <sys/lock.h> 73#include <sys/malloc.h> 74#include <sys/mbuf.h> 75#include <sys/proc.h> 76#include <sys/protosw.h> 77#include <sys/signalvar.h> 78#include <sys/socket.h> 79#include <sys/socketvar.h> 80#include <sys/sx.h> 81#include <sys/systm.h> 82 83#include <net/if.h> 84#include <net/if_types.h> 85#include <net/route.h> 86 87#include <netinet/in.h> 88#include <netinet/in_var.h> 89#include <netinet/in_systm.h> 90#include <netinet/icmp6.h> 91#include <netinet/in_pcb.h> 92#include <netinet/ip6.h> 93#include <netinet6/ip6protosw.h> 94#include <netinet6/ip6_mroute.h> 95#include <netinet6/in6_pcb.h> 96#include <netinet6/ip6_var.h> 97#include <netinet6/nd6.h> 98#include <netinet6/raw_ip6.h> 99#ifdef ENABLE_DEFAULT_SCOPE 100#include <netinet6/scope6_var.h> 101#endif 102 103#ifdef IPSEC 104#include <netinet6/ipsec.h> 105#include <netinet6/ipsec6.h> 106#endif /*IPSEC*/ 107 108#include <machine/stdarg.h> 109 110#define satosin6(sa) ((struct sockaddr_in6 *)(sa)) 111#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) 112 113/* 114 * Raw interface to IP6 protocol. 115 */ 116 117extern struct inpcbhead ripcb; 118extern struct inpcbinfo ripcbinfo; 119extern u_long rip_sendspace; 120extern u_long rip_recvspace; 121 122struct rip6stat rip6stat; 123 124/* 125 * Setup generic address and protocol structures 126 * for raw_input routine, then pass them along with 127 * mbuf chain. 128 */ 129int 130rip6_input(mp, offp, proto) 131 struct mbuf **mp; 132 int *offp, proto; 133{ 134 struct mbuf *m = *mp; 135 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 136 register struct inpcb *in6p; 137 struct inpcb *last = 0; 138 struct mbuf *opts = NULL; 139 struct sockaddr_in6 rip6src; 140 141 rip6stat.rip6s_ipackets++; 142 143 if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { 144 /* XXX send icmp6 host/port unreach? */ 145 m_freem(m); 146 return IPPROTO_DONE; 147 } 148 149 init_sin6(&rip6src, m); /* general init */ 150 151 LIST_FOREACH(in6p, &ripcb, inp_list) { 152 if ((in6p->in6p_vflag & INP_IPV6) == 0) 153 continue; 154 if (in6p->in6p_ip6_nxt && 155 in6p->in6p_ip6_nxt != proto) 156 continue; 157 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 158 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 159 continue; 160 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 161 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 162 continue; 163 if (in6p->in6p_cksum != -1) { 164 rip6stat.rip6s_isum++; 165 if (in6_cksum(m, ip6->ip6_nxt, *offp, 166 m->m_pkthdr.len - *offp)) { 167 rip6stat.rip6s_badsum++; 168 continue; 169 } 170 } 171 if (last) { 172 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 173 174#ifdef IPSEC 175 /* 176 * Check AH/ESP integrity. 177 */ 178 if (n && ipsec6_in_reject_so(n, last->inp_socket)) { 179 m_freem(n); 180 ipsec6stat.in_polvio++; 181 /* do not inject data into pcb */ 182 } else 183#endif /*IPSEC*/ 184 if (n) { 185 if (last->in6p_flags & IN6P_CONTROLOPTS || 186 last->in6p_socket->so_options & SO_TIMESTAMP) 187 ip6_savecontrol(last, &opts, ip6, n); 188 /* strip intermediate headers */ 189 m_adj(n, *offp); 190 if (sbappendaddr(&last->in6p_socket->so_rcv, 191 (struct sockaddr *)&rip6src, 192 n, opts) == 0) { 193 m_freem(n); 194 if (opts) 195 m_freem(opts); 196 rip6stat.rip6s_fullsock++; 197 } else 198 sorwakeup(last->in6p_socket); 199 opts = NULL; 200 } 201 } 202 last = in6p; 203 } 204#ifdef IPSEC 205 /* 206 * Check AH/ESP integrity. 207 */ 208 if (last && ipsec6_in_reject_so(m, last->inp_socket)) { 209 m_freem(m); 210 ipsec6stat.in_polvio++; 211 ip6stat.ip6s_delivered--; 212 /* do not inject data into pcb */ 213 } else 214#endif /*IPSEC*/ 215 if (last) { 216 if (last->in6p_flags & IN6P_CONTROLOPTS || 217 last->in6p_socket->so_options & SO_TIMESTAMP) 218 ip6_savecontrol(last, &opts, ip6, m); 219 /* strip intermediate headers */ 220 m_adj(m, *offp); 221 if (sbappendaddr(&last->in6p_socket->so_rcv, 222 (struct sockaddr *)&rip6src, m, opts) == 0) { 223 m_freem(m); 224 if (opts) 225 m_freem(opts); 226 rip6stat.rip6s_fullsock++; 227 } else 228 sorwakeup(last->in6p_socket); 229 } else { 230 rip6stat.rip6s_nosock++; 231 if (m->m_flags & M_MCAST) 232 rip6stat.rip6s_nosockmcast++; 233 if (proto == IPPROTO_NONE) 234 m_freem(m); 235 else { 236 char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ 237 icmp6_error(m, ICMP6_PARAM_PROB, 238 ICMP6_PARAMPROB_NEXTHEADER, 239 prvnxtp - mtod(m, char *)); 240 } 241 ip6stat.ip6s_delivered--; 242 } 243 return IPPROTO_DONE; 244} 245 246void 247rip6_ctlinput(cmd, sa, d) 248 int cmd; 249 struct sockaddr *sa; 250 void *d; 251{ 252 struct ip6_hdr *ip6; 253 struct mbuf *m; 254 int off = 0; 255 struct ip6ctlparam *ip6cp = NULL; 256 const struct sockaddr_in6 *sa6_src = NULL; 257 struct inpcb *(*notify) __P((struct inpcb *, int)) = in6_rtchange; 258 259 if (sa->sa_family != AF_INET6 || 260 sa->sa_len != sizeof(struct sockaddr_in6)) 261 return; 262 263 if ((unsigned)cmd >= PRC_NCMDS) 264 return; 265 if (PRC_IS_REDIRECT(cmd)) 266 notify = in6_rtchange, d = NULL; 267 else if (cmd == PRC_HOSTDEAD) 268 d = NULL; 269 else if (inet6ctlerrmap[cmd] == 0) 270 return; 271 272 /* if the parameter is from icmp6, decode it. */ 273 if (d != NULL) { 274 ip6cp = (struct ip6ctlparam *)d; 275 m = ip6cp->ip6c_m; 276 ip6 = ip6cp->ip6c_ip6; 277 off = ip6cp->ip6c_off; 278 sa6_src = ip6cp->ip6c_src; 279 } else { 280 m = NULL; 281 ip6 = NULL; 282 sa6_src = &sa6_any; 283 } 284 285 (void) in6_pcbnotify(&ripcb, sa, 0, (const struct sockaddr *)sa6_src, 286 0, cmd, notify); 287} 288 289/* 290 * Generate IPv6 header and pass packet to ip6_output. 291 * Tack on options user may have setup with control call. 292 */ 293int 294#if __STDC__ 295rip6_output(struct mbuf *m, ...) 296#else 297rip6_output(m, va_alist) 298 struct mbuf *m; 299 va_dcl 300#endif 301{ 302 struct socket *so; 303 struct sockaddr_in6 *dstsock; 304 struct mbuf *control; 305 struct in6_addr *dst; 306 struct ip6_hdr *ip6; 307 struct inpcb *in6p; 308 u_int plen = m->m_pkthdr.len; 309 int error = 0; 310 struct ip6_pktopts opt, *optp = 0; 311 struct ifnet *oifp = NULL; 312 int type = 0, code = 0; /* for ICMPv6 output statistics only */ 313 int priv = 0; 314 va_list ap; 315 316 va_start(ap, m); 317 so = va_arg(ap, struct socket *); 318 dstsock = va_arg(ap, struct sockaddr_in6 *); 319 control = va_arg(ap, struct mbuf *); 320 va_end(ap); 321 322 in6p = sotoin6pcb(so); 323 324 priv = 0; 325 if (so->so_cred->cr_uid == 0) 326 priv = 1; 327 dst = &dstsock->sin6_addr; 328 if (control) { 329 if ((error = ip6_setpktoptions(control, &opt, priv, 0)) != 0) 330 goto bad; 331 optp = &opt; 332 } else 333 optp = in6p->in6p_outputopts; 334 335 /* 336 * For an ICMPv6 packet, we should know its type and code 337 * to update statistics. 338 */ 339 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 340 struct icmp6_hdr *icmp6; 341 if (m->m_len < sizeof(struct icmp6_hdr) && 342 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { 343 error = ENOBUFS; 344 goto bad; 345 } 346 icmp6 = mtod(m, struct icmp6_hdr *); 347 type = icmp6->icmp6_type; 348 code = icmp6->icmp6_code; 349 } 350 351 M_PREPEND(m, sizeof(*ip6), M_TRYWAIT); 352 ip6 = mtod(m, struct ip6_hdr *); 353 354 /* 355 * Next header might not be ICMP6 but use its pseudo header anyway. 356 */ 357 ip6->ip6_dst = *dst; 358 359 /* 360 * If the scope of the destination is link-local, embed the interface 361 * index in the address. 362 * 363 * XXX advanced-api value overrides sin6_scope_id 364 */ 365 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 366 struct in6_pktinfo *pi; 367 368 /* 369 * XXX Boundary check is assumed to be already done in 370 * ip6_setpktoptions(). 371 */ 372 if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) { 373 ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex); 374 oifp = ifnet_byindex(pi->ipi6_ifindex); 375 } else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && 376 in6p->in6p_moptions && 377 in6p->in6p_moptions->im6o_multicast_ifp) { 378 oifp = in6p->in6p_moptions->im6o_multicast_ifp; 379 ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index); 380 } else if (dstsock->sin6_scope_id) { 381 /* boundary check */ 382 if (dstsock->sin6_scope_id < 0 383 || if_index < dstsock->sin6_scope_id) { 384 error = ENXIO; /* XXX EINVAL? */ 385 goto bad; 386 } 387 ip6->ip6_dst.s6_addr16[1] 388 = htons(dstsock->sin6_scope_id & 0xffff);/*XXX*/ 389 } 390 } 391 392 /* 393 * Source address selection. 394 */ 395 { 396 struct in6_addr *in6a; 397 398 if ((in6a = in6_selectsrc(dstsock, optp, 399 in6p->in6p_moptions, 400 &in6p->in6p_route, 401 &in6p->in6p_laddr, 402 &error)) == 0) { 403 if (error == 0) 404 error = EADDRNOTAVAIL; 405 goto bad; 406 } 407 ip6->ip6_src = *in6a; 408 if (in6p->in6p_route.ro_rt) 409 oifp = ifnet_byindex(in6p->in6p_route.ro_rt->rt_ifp->if_index); 410 } 411 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | 412 (in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK); 413 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) | 414 (IPV6_VERSION & IPV6_VERSION_MASK); 415 /* ip6_plen will be filled in ip6_output, so not fill it here. */ 416 ip6->ip6_nxt = in6p->in6p_ip6_nxt; 417 ip6->ip6_hlim = in6_selecthlim(in6p, oifp); 418 419 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 || 420 in6p->in6p_cksum != -1) { 421 struct mbuf *n; 422 int off; 423 u_int16_t *p; 424 425 /* compute checksum */ 426 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) 427 off = offsetof(struct icmp6_hdr, icmp6_cksum); 428 else 429 off = in6p->in6p_cksum; 430 if (plen < off + 1) { 431 error = EINVAL; 432 goto bad; 433 } 434 off += sizeof(struct ip6_hdr); 435 436 n = m; 437 while (n && n->m_len <= off) { 438 off -= n->m_len; 439 n = n->m_next; 440 } 441 if (!n) 442 goto bad; 443 p = (u_int16_t *)(mtod(n, caddr_t) + off); 444 *p = 0; 445 *p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen); 446 } 447
|
448#ifdef IPSEC 449 if (ipsec_setsocket(m, so) != 0) { 450 error = ENOBUFS; 451 goto bad; 452 } 453#endif /*IPSEC*/ 454
| |
455 error = ip6_output(m, optp, &in6p->in6p_route, 0,
| 448 error = ip6_output(m, optp, &in6p->in6p_route, 0,
|
456 in6p->in6p_moptions, &oifp);
| 449 in6p->in6p_moptions, &oifp, in6p);
|
457 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 458 if (oifp) 459 icmp6_ifoutstat_inc(oifp, type, code); 460 icmp6stat.icp6s_outhist[type]++; 461 } else 462 rip6stat.rip6s_opackets++; 463 464 goto freectl; 465 466 bad: 467 if (m) 468 m_freem(m); 469 470 freectl: 471 if (optp == &opt && optp->ip6po_rthdr && optp->ip6po_route.ro_rt) 472 RTFREE(optp->ip6po_route.ro_rt); 473 if (control) { 474 if (optp == &opt) 475 ip6_clearpktopts(optp, 0, -1); 476 m_freem(control); 477 } 478 return(error); 479} 480 481/* 482 * Raw IPv6 socket option processing. 483 */ 484int 485rip6_ctloutput(so, sopt) 486 struct socket *so; 487 struct sockopt *sopt; 488{ 489 int error; 490 491 if (sopt->sopt_level == IPPROTO_ICMPV6) 492 /* 493 * XXX: is it better to call icmp6_ctloutput() directly 494 * from protosw? 495 */ 496 return(icmp6_ctloutput(so, sopt)); 497 else if (sopt->sopt_level != IPPROTO_IPV6) 498 return (EINVAL); 499 500 error = 0; 501 502 switch (sopt->sopt_dir) { 503 case SOPT_GET: 504 switch (sopt->sopt_name) { 505 case MRT6_INIT: 506 case MRT6_DONE: 507 case MRT6_ADD_MIF: 508 case MRT6_DEL_MIF: 509 case MRT6_ADD_MFC: 510 case MRT6_DEL_MFC: 511 case MRT6_PIM: 512 error = ip6_mrouter_get(so, sopt); 513 break; 514 default: 515 error = ip6_ctloutput(so, sopt); 516 break; 517 } 518 break; 519 520 case SOPT_SET: 521 switch (sopt->sopt_name) { 522 case MRT6_INIT: 523 case MRT6_DONE: 524 case MRT6_ADD_MIF: 525 case MRT6_DEL_MIF: 526 case MRT6_ADD_MFC: 527 case MRT6_DEL_MFC: 528 case MRT6_PIM: 529 error = ip6_mrouter_set(so, sopt); 530 break; 531 default: 532 error = ip6_ctloutput(so, sopt); 533 break; 534 } 535 break; 536 } 537 538 return (error); 539} 540 541static int 542rip6_attach(struct socket *so, int proto, struct thread *td) 543{ 544 struct inpcb *inp; 545 int error, s; 546 547 inp = sotoinpcb(so); 548 if (inp) 549 panic("rip6_attach"); 550 if (td && (error = suser(td)) != 0) 551 return error; 552 553 error = soreserve(so, rip_sendspace, rip_recvspace); 554 if (error) 555 return error; 556 s = splnet(); 557 error = in_pcballoc(so, &ripcbinfo, td); 558 splx(s); 559 if (error) 560 return error; 561 inp = (struct inpcb *)so->so_pcb; 562 inp->inp_vflag |= INP_IPV6; 563 inp->in6p_ip6_nxt = (long)proto; 564 inp->in6p_hops = -1; /* use kernel default */ 565 inp->in6p_cksum = -1; 566 MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *, 567 sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); 568 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 569 return 0; 570} 571 572static int 573rip6_detach(struct socket *so) 574{ 575 struct inpcb *inp; 576 577 inp = sotoinpcb(so); 578 if (inp == 0) 579 panic("rip6_detach"); 580 /* xxx: RSVP */ 581 if (so == ip6_mrouter) 582 ip6_mrouter_done(); 583 if (inp->in6p_icmp6filt) { 584 FREE(inp->in6p_icmp6filt, M_PCB); 585 inp->in6p_icmp6filt = NULL; 586 } 587 in6_pcbdetach(inp); 588 return 0; 589} 590 591static int 592rip6_abort(struct socket *so) 593{ 594 soisdisconnected(so); 595 return rip6_detach(so); 596} 597 598static int 599rip6_disconnect(struct socket *so) 600{ 601 struct inpcb *inp = sotoinpcb(so); 602 603 if ((so->so_state & SS_ISCONNECTED) == 0) 604 return ENOTCONN; 605 inp->in6p_faddr = in6addr_any; 606 return rip6_abort(so); 607} 608 609static int 610rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 611{ 612 struct inpcb *inp = sotoinpcb(so); 613 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 614 struct ifaddr *ia = NULL; 615 616 if (nam->sa_len != sizeof(*addr)) 617 return EINVAL; 618 619 if (TAILQ_EMPTY(&ifnet) || addr->sin6_family != AF_INET6) 620 return EADDRNOTAVAIL; 621#ifdef ENABLE_DEFAULT_SCOPE 622 if (addr->sin6_scope_id == 0) { /* not change if specified */ 623 addr->sin6_scope_id = scope6_addr2default(&addr->sin6_addr); 624 } 625#endif 626 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && 627 (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) 628 return EADDRNOTAVAIL; 629 if (ia && 630 ((struct in6_ifaddr *)ia)->ia6_flags & 631 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| 632 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { 633 return(EADDRNOTAVAIL); 634 } 635 inp->in6p_laddr = addr->sin6_addr; 636 return 0; 637} 638 639static int 640rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 641{ 642 struct inpcb *inp = sotoinpcb(so); 643 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 644 struct in6_addr *in6a = NULL; 645 int error = 0; 646#ifdef ENABLE_DEFAULT_SCOPE 647 struct sockaddr_in6 tmp; 648#endif 649 650 if (nam->sa_len != sizeof(*addr)) 651 return EINVAL; 652 if (TAILQ_EMPTY(&ifnet)) 653 return EADDRNOTAVAIL; 654 if (addr->sin6_family != AF_INET6) 655 return EAFNOSUPPORT; 656#ifdef ENABLE_DEFAULT_SCOPE 657 if (addr->sin6_scope_id == 0) { /* not change if specified */ 658 /* avoid overwrites */ 659 tmp = *addr; 660 addr = &tmp; 661 addr->sin6_scope_id = scope6_addr2default(&addr->sin6_addr); 662 } 663#endif 664 /* Source address selection. XXX: need pcblookup? */ 665 in6a = in6_selectsrc(addr, inp->in6p_outputopts, 666 inp->in6p_moptions, &inp->in6p_route, 667 &inp->in6p_laddr, &error); 668 if (in6a == NULL) 669 return (error ? error : EADDRNOTAVAIL); 670 inp->in6p_laddr = *in6a; 671 inp->in6p_faddr = addr->sin6_addr; 672 soisconnected(so); 673 return 0; 674} 675 676static int 677rip6_shutdown(struct socket *so) 678{ 679 socantsendmore(so); 680 return 0; 681} 682 683static int 684rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 685 struct mbuf *control, struct thread *td) 686{ 687 struct inpcb *inp = sotoinpcb(so); 688 struct sockaddr_in6 tmp; 689 struct sockaddr_in6 *dst; 690 691 /* always copy sockaddr to avoid overwrites */ 692 if (so->so_state & SS_ISCONNECTED) { 693 if (nam) { 694 m_freem(m); 695 return EISCONN; 696 } 697 /* XXX */ 698 bzero(&tmp, sizeof(tmp)); 699 tmp.sin6_family = AF_INET6; 700 tmp.sin6_len = sizeof(struct sockaddr_in6); 701 bcopy(&inp->in6p_faddr, &tmp.sin6_addr, 702 sizeof(struct in6_addr)); 703 dst = &tmp; 704 } else { 705 if (nam == NULL) { 706 m_freem(m); 707 return ENOTCONN; 708 } 709 tmp = *(struct sockaddr_in6 *)nam; 710 dst = &tmp; 711 } 712#ifdef ENABLE_DEFAULT_SCOPE 713 if (dst->sin6_scope_id == 0) { /* not change if specified */ 714 dst->sin6_scope_id = scope6_addr2default(&dst->sin6_addr); 715 } 716#endif 717 return rip6_output(m, so, dst, control); 718} 719 720struct pr_usrreqs rip6_usrreqs = { 721 rip6_abort, pru_accept_notsupp, rip6_attach, rip6_bind, rip6_connect, 722 pru_connect2_notsupp, in6_control, rip6_detach, rip6_disconnect, 723 pru_listen_notsupp, in6_setpeeraddr, pru_rcvd_notsupp, 724 pru_rcvoob_notsupp, rip6_send, pru_sense_null, rip6_shutdown, 725 in6_setsockaddr, sosend, soreceive, sopoll 726};
| 450 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { 451 if (oifp) 452 icmp6_ifoutstat_inc(oifp, type, code); 453 icmp6stat.icp6s_outhist[type]++; 454 } else 455 rip6stat.rip6s_opackets++; 456 457 goto freectl; 458 459 bad: 460 if (m) 461 m_freem(m); 462 463 freectl: 464 if (optp == &opt && optp->ip6po_rthdr && optp->ip6po_route.ro_rt) 465 RTFREE(optp->ip6po_route.ro_rt); 466 if (control) { 467 if (optp == &opt) 468 ip6_clearpktopts(optp, 0, -1); 469 m_freem(control); 470 } 471 return(error); 472} 473 474/* 475 * Raw IPv6 socket option processing. 476 */ 477int 478rip6_ctloutput(so, sopt) 479 struct socket *so; 480 struct sockopt *sopt; 481{ 482 int error; 483 484 if (sopt->sopt_level == IPPROTO_ICMPV6) 485 /* 486 * XXX: is it better to call icmp6_ctloutput() directly 487 * from protosw? 488 */ 489 return(icmp6_ctloutput(so, sopt)); 490 else if (sopt->sopt_level != IPPROTO_IPV6) 491 return (EINVAL); 492 493 error = 0; 494 495 switch (sopt->sopt_dir) { 496 case SOPT_GET: 497 switch (sopt->sopt_name) { 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 error = ip6_mrouter_get(so, sopt); 506 break; 507 default: 508 error = ip6_ctloutput(so, sopt); 509 break; 510 } 511 break; 512 513 case SOPT_SET: 514 switch (sopt->sopt_name) { 515 case MRT6_INIT: 516 case MRT6_DONE: 517 case MRT6_ADD_MIF: 518 case MRT6_DEL_MIF: 519 case MRT6_ADD_MFC: 520 case MRT6_DEL_MFC: 521 case MRT6_PIM: 522 error = ip6_mrouter_set(so, sopt); 523 break; 524 default: 525 error = ip6_ctloutput(so, sopt); 526 break; 527 } 528 break; 529 } 530 531 return (error); 532} 533 534static int 535rip6_attach(struct socket *so, int proto, struct thread *td) 536{ 537 struct inpcb *inp; 538 int error, s; 539 540 inp = sotoinpcb(so); 541 if (inp) 542 panic("rip6_attach"); 543 if (td && (error = suser(td)) != 0) 544 return error; 545 546 error = soreserve(so, rip_sendspace, rip_recvspace); 547 if (error) 548 return error; 549 s = splnet(); 550 error = in_pcballoc(so, &ripcbinfo, td); 551 splx(s); 552 if (error) 553 return error; 554 inp = (struct inpcb *)so->so_pcb; 555 inp->inp_vflag |= INP_IPV6; 556 inp->in6p_ip6_nxt = (long)proto; 557 inp->in6p_hops = -1; /* use kernel default */ 558 inp->in6p_cksum = -1; 559 MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *, 560 sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); 561 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 562 return 0; 563} 564 565static int 566rip6_detach(struct socket *so) 567{ 568 struct inpcb *inp; 569 570 inp = sotoinpcb(so); 571 if (inp == 0) 572 panic("rip6_detach"); 573 /* xxx: RSVP */ 574 if (so == ip6_mrouter) 575 ip6_mrouter_done(); 576 if (inp->in6p_icmp6filt) { 577 FREE(inp->in6p_icmp6filt, M_PCB); 578 inp->in6p_icmp6filt = NULL; 579 } 580 in6_pcbdetach(inp); 581 return 0; 582} 583 584static int 585rip6_abort(struct socket *so) 586{ 587 soisdisconnected(so); 588 return rip6_detach(so); 589} 590 591static int 592rip6_disconnect(struct socket *so) 593{ 594 struct inpcb *inp = sotoinpcb(so); 595 596 if ((so->so_state & SS_ISCONNECTED) == 0) 597 return ENOTCONN; 598 inp->in6p_faddr = in6addr_any; 599 return rip6_abort(so); 600} 601 602static int 603rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 604{ 605 struct inpcb *inp = sotoinpcb(so); 606 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 607 struct ifaddr *ia = NULL; 608 609 if (nam->sa_len != sizeof(*addr)) 610 return EINVAL; 611 612 if (TAILQ_EMPTY(&ifnet) || addr->sin6_family != AF_INET6) 613 return EADDRNOTAVAIL; 614#ifdef ENABLE_DEFAULT_SCOPE 615 if (addr->sin6_scope_id == 0) { /* not change if specified */ 616 addr->sin6_scope_id = scope6_addr2default(&addr->sin6_addr); 617 } 618#endif 619 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && 620 (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) 621 return EADDRNOTAVAIL; 622 if (ia && 623 ((struct in6_ifaddr *)ia)->ia6_flags & 624 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| 625 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { 626 return(EADDRNOTAVAIL); 627 } 628 inp->in6p_laddr = addr->sin6_addr; 629 return 0; 630} 631 632static int 633rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 634{ 635 struct inpcb *inp = sotoinpcb(so); 636 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; 637 struct in6_addr *in6a = NULL; 638 int error = 0; 639#ifdef ENABLE_DEFAULT_SCOPE 640 struct sockaddr_in6 tmp; 641#endif 642 643 if (nam->sa_len != sizeof(*addr)) 644 return EINVAL; 645 if (TAILQ_EMPTY(&ifnet)) 646 return EADDRNOTAVAIL; 647 if (addr->sin6_family != AF_INET6) 648 return EAFNOSUPPORT; 649#ifdef ENABLE_DEFAULT_SCOPE 650 if (addr->sin6_scope_id == 0) { /* not change if specified */ 651 /* avoid overwrites */ 652 tmp = *addr; 653 addr = &tmp; 654 addr->sin6_scope_id = scope6_addr2default(&addr->sin6_addr); 655 } 656#endif 657 /* Source address selection. XXX: need pcblookup? */ 658 in6a = in6_selectsrc(addr, inp->in6p_outputopts, 659 inp->in6p_moptions, &inp->in6p_route, 660 &inp->in6p_laddr, &error); 661 if (in6a == NULL) 662 return (error ? error : EADDRNOTAVAIL); 663 inp->in6p_laddr = *in6a; 664 inp->in6p_faddr = addr->sin6_addr; 665 soisconnected(so); 666 return 0; 667} 668 669static int 670rip6_shutdown(struct socket *so) 671{ 672 socantsendmore(so); 673 return 0; 674} 675 676static int 677rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 678 struct mbuf *control, struct thread *td) 679{ 680 struct inpcb *inp = sotoinpcb(so); 681 struct sockaddr_in6 tmp; 682 struct sockaddr_in6 *dst; 683 684 /* always copy sockaddr to avoid overwrites */ 685 if (so->so_state & SS_ISCONNECTED) { 686 if (nam) { 687 m_freem(m); 688 return EISCONN; 689 } 690 /* XXX */ 691 bzero(&tmp, sizeof(tmp)); 692 tmp.sin6_family = AF_INET6; 693 tmp.sin6_len = sizeof(struct sockaddr_in6); 694 bcopy(&inp->in6p_faddr, &tmp.sin6_addr, 695 sizeof(struct in6_addr)); 696 dst = &tmp; 697 } else { 698 if (nam == NULL) { 699 m_freem(m); 700 return ENOTCONN; 701 } 702 tmp = *(struct sockaddr_in6 *)nam; 703 dst = &tmp; 704 } 705#ifdef ENABLE_DEFAULT_SCOPE 706 if (dst->sin6_scope_id == 0) { /* not change if specified */ 707 dst->sin6_scope_id = scope6_addr2default(&dst->sin6_addr); 708 } 709#endif 710 return rip6_output(m, so, dst, control); 711} 712 713struct pr_usrreqs rip6_usrreqs = { 714 rip6_abort, pru_accept_notsupp, rip6_attach, rip6_bind, rip6_connect, 715 pru_connect2_notsupp, in6_control, rip6_detach, rip6_disconnect, 716 pru_listen_notsupp, in6_setpeeraddr, pru_rcvd_notsupp, 717 pru_rcvoob_notsupp, rip6_send, pru_sense_null, rip6_shutdown, 718 in6_setsockaddr, sosend, soreceive, sopoll 719};
|