diff options
Diffstat (limited to 'sys/netinet6/raw_ipv6.c')
-rw-r--r-- | sys/netinet6/raw_ipv6.c | 445 |
1 files changed, 266 insertions, 179 deletions
diff --git a/sys/netinet6/raw_ipv6.c b/sys/netinet6/raw_ipv6.c index 72f995404a4..a32e501f699 100644 --- a/sys/netinet6/raw_ipv6.c +++ b/sys/netinet6/raw_ipv6.c @@ -42,7 +42,7 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. * SUCH DAMAGE. * * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 - * $Id: raw_ipv6.c,v 1.4 1999/04/28 09:28:16 art Exp $ + * $Id: raw_ipv6.c,v 1.5 1999/12/08 06:50:23 itojun Exp $ */ #include <sys/param.h> @@ -72,11 +72,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #include <netinet/ip.h> #include <netinet/in_pcb.h> -#include <netinet6/in6.h> #include <netinet6/in6_var.h> -#include <netinet6/ipv6.h> -#include <netinet6/ipv6_var.h> -#include <netinet6/icmpv6.h> +#include <netinet6/ip6.h> +#include <netinet6/ip6_var.h> +#include <netinet6/icmp6.h> #if __OpenBSD__ #undef IPSEC @@ -110,7 +109,7 @@ struct inpcbtable rawin6pcbtable; #else /* __NetBSD__ || __OpenBSD__ */ struct inpcb rawin6pcb; #endif /* __NetBSD__ || __OpenBSD__ */ -struct sockaddr_in6 ripv6src = { sizeof(struct sockaddr_in6), AF_INET6 }; +struct sockaddr_in6 rip6src = { sizeof(struct sockaddr_in6), AF_INET6 }; /* * Nominal space allocated to a raw ip socket. @@ -118,8 +117,13 @@ struct sockaddr_in6 ripv6src = { sizeof(struct sockaddr_in6), AF_INET6 }; #define RIPV6SNDQ 8192 #define RIPV6RCVQ 8192 -u_long ripv6_sendspace = RIPV6SNDQ; -u_long ripv6_recvspace = RIPV6RCVQ; +#if 0 +u_long rip6_sendspace = RIPV6SNDQ; +u_long rip6_recvspace = RIPV6RCVQ; +#else +extern u_long rip6_sendspace; +extern u_long rip6_recvspace; +#endif /* * External globals @@ -129,7 +133,9 @@ static struct inpcbhead ri6pcb; static struct inpcbinfo ri6pcbinfo; #endif /* __FreeBSD__ */ -extern struct ipv6stat ipv6stat; +#if 0 +extern struct ip6_hdrstat ipv6stat; +#endif #define RETURN_ERROR(x) { \ DPRINTF(EVENT, ("%s: returning %s\n", DEBUG_STATUS, #x)); \ @@ -145,7 +151,7 @@ extern struct ipv6stat ipv6stat; ----------------------------------------------------------------------*/ void -ripv6_init() +rip6_init() { #if __FreeBSD__ LIST_INIT(&ri6pcb); @@ -194,50 +200,50 @@ static int ipv6_findnexthdr(struct mbuf *m, size_t extra) do { switch(nexthdr) { case IPPROTO_IPV6: - hl = sizeof(struct ipv6); + hl = sizeof(struct ip6_hdr); if ((extra -= hl) < 0) return -1; - nexthdr = ((struct ipv6 *)p)->ipv6_nexthdr; + nexthdr = ((struct ip6_hdr *)p)->ip6_nxt; break; case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: - if (extra < sizeof(struct ipv6_opthdr)) + if (extra < sizeof(struct ip6_ext)) return -1; - hl = sizeof(struct ipv6_opthdr) + - (((struct ipv6_opthdr *)p)->oh_extlen << 3); + hl = sizeof(struct ip6_ext) + + (((struct ip6_ext *)p)->ip6e_len << 3); if ((extra -= hl) < 0) return -1; - nexthdr = ((struct ipv6_opthdr *)p)->oh_nexthdr; + nexthdr = ((struct ip6_ext *)p)->ip6e_nxt; break; case IPPROTO_ROUTING: - if (extra < sizeof(struct ipv6_srcroute0)) + if (extra < sizeof(struct ip6_rthdr0)) return -1; - hl = sizeof(struct ipv6_srcroute0) + - (((struct ipv6_srcroute0 *)p)->i6sr_len << 3); + hl = sizeof(struct ip6_rthdr0) + + (((struct ip6_rthdr0 *)p)->ip6r0_len << 3); if ((extra -= hl) < 0) return -1; - nexthdr = ((struct ipv6_srcroute0 *)p)->i6sr_nexthdr; + nexthdr = ((struct ip6_rthdr0 *)p)->ip6r0_nxt; break; #ifdef IPSEC case IPPROTO_AH: - if (extra < sizeof(struct ipv6_srcroute0)) + if (extra < sizeof(struct ip6_hdr_srcroute0)) return -1; - hl = sizeof(struct ipv6_srcroute0) + - ((struct ipv6_srcroute0 *)p)->i6sr_len << 3; + hl = sizeof(struct ip6_hdr_srcroute0) + + ((struct ip6_hdr_srcroute0 *)p)->i6sr_len << 3; if ((extra -= hl) < 0) return -1; - nexthdr = ((struct ipv6_srcroute0 *)p)->i6sr_nexthdr; + nexthdr = ((struct ip6_hdr_srcroute0 *)p)->i6sr_nexthdr; break; #endif /* IPSEC */ default: @@ -252,52 +258,54 @@ static int ipv6_findnexthdr(struct mbuf *m, size_t extra) /*---------------------------------------------------------------------- * If no HLP's are found for an IPv6 datagram, this routine is called. ----------------------------------------------------------------------*/ -void -#if __OpenBSD__ -ripv6_input(struct mbuf *m, ...) -#else /* __OpenBSD__ */ -ripv6_input(m,extra) - struct mbuf *m; - int extra; -#endif /* __OpenBSD__ */ +int +rip6_input(mp, offp, proto) + struct mbuf **mp; + int *offp, proto; { - register struct ipv6 *ipv6 = mtod(m, struct ipv6 *); /* Will have been + struct mbuf *m = *mp; + register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); /* Will have been pulled up by ipv6_input(). */ register struct inpcb *inp; - int nexthdr, icmpv6type; + int nexthdr, icmp6type; int foundone = 0; struct mbuf *m2 = NULL, *opts = NULL; struct sockaddr_in6 srcsa; #ifdef IPSEC struct sockaddr_in6 dstsa; #endif /* IPSEC */ -#if __OpenBSD__ - int extra; - va_list ap; + int extra = *offp; - va_start(ap, m); - extra = va_arg(ap, int); - va_end(ap); -#endif /* __OpenBSD__ */ - - DPRINTF(FINISHED, ("ripv6_input(m=%08x, extra=%d)\n", OSDEP_PCAST(m), extra)); + DPRINTF(FINISHED, ("rip6_input(m=%08x, extra=%d)\n", OSDEP_PCAST(m), extra)); DP(FINISHED, m->m_pkthdr.len, d); - DDO(FINISHED,printf("In ripv6_input(), header is:\n");dump_mchain(m)); - DPRINTF(EVENT, ("In ripv6_input()\n")); + DDO(FINISHED,printf("In rip6_input(), header is:\n");dump_mchain(m)); + DPRINTF(EVENT, ("In rip6_input()\n")); DPRINTF(EVENT, ("Header is: ")); +#if 0 DDO(GROSSEVENT, dump_ipv6(ipv6)); +#endif bzero(&srcsa, sizeof(struct sockaddr_in6)); srcsa.sin6_family = AF_INET6; srcsa.sin6_len = sizeof(struct sockaddr_in6); - srcsa.sin6_addr = ipv6->ipv6_src; + srcsa.sin6_addr = ip6->ip6_src; + + if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6_addr)) + srcsa.sin6_addr.s6_addr16[1] = 0; + if (m->m_pkthdr.rcvif) { + if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6_addr)) + srcsa.sin6_scope_id = m->m_pkthdr.rcvif->if_index; + else + srcsa.sin6_scope_id = 0; + } else + srcsa.sin6_scope_id = 0; #if IPSEC bzero(&dstsa, sizeof(struct sockaddr_in6)); dstsa.sin6_family = AF_INET6; dstsa.sin6_len = sizeof(struct sockaddr_in6); - dstsa.sin6_addr = ipv6->ipv6_dst; + dstsa.sin6_addr = ip6->ip6_dst; #endif /* IPSEC */ #if 0 @@ -305,28 +313,28 @@ ripv6_input(m,extra) if (m->m_len < extra)) { if (!(m = m_pullup2(m, extra))) return; - ipv6 = mtod(m, struct ipv6 *); + ip6 = mtod(m, struct ip6_hdr *); } #endif /* 0 */ if ((nexthdr = ipv6_findnexthdr(m, extra)) < 0) { - DPRINTF(ERROR, ("ripv6_input: ipv6_findnexthdr failed\n")); + DPRINTF(ERROR, ("rip6_input: ipv6_findnexthdr failed\n")); goto ret; } DP(FINISHED, nexthdr, d); if (nexthdr == IPPROTO_ICMPV6) { - if (m->m_len < extra + sizeof(struct icmpv6hdr)) { - if (!(m = m_pullup2(m, extra + sizeof(struct icmpv6hdr)))) { - DPRINTF(ERROR, ("ripv6_input: m_pullup2 failed\n")); + if (m->m_len < extra + sizeof(struct icmp6_hdr)) { + if (!(m = m_pullup2(m, extra + sizeof(struct icmp6_hdr)))) { + DPRINTF(ERROR, ("rip6_input: m_pullup2 failed\n")); goto ret; } - ipv6 = mtod(m, struct ipv6 *); + ip6 = mtod(m, struct ip6_hdr *); } - icmpv6type = ((struct icmpv6hdr *)(mtod(m, caddr_t) + extra))->icmpv6_type; + icmp6type = ((struct icmp6_hdr *)(mtod(m, caddr_t) + extra))->icmp6_type; } else - icmpv6type = -1; + icmp6type = -1; /* * Locate raw PCB for incoming datagram. @@ -337,21 +345,22 @@ ripv6_input(m,extra) #if __NetBSD__ || __OpenBSD__ for (inp = rawin6pcbtable.inpt_queue.cqh_first; inp != (struct inpcb *)&rawin6pcbtable.inpt_queue; - inp = inp->inp_queue.cqe_next) { + inp = inp->inp_queue.cqe_next) #else /* __NetBSD__ || __OpenBSD__ */ - for (inp = rawin6pcb.inp_next; inp != &rawin6pcb; inp = inp->inp_next) { + for (inp = rawin6pcb.inp_next; inp != &rawin6pcb; inp = inp->inp_next) #endif /* __NetBSD__ || __OpenBSD__ */ #endif /* __FreeBSD__ */ - if (inp->inp_ipv6.ipv6_nexthdr && inp->inp_ipv6.ipv6_nexthdr != nexthdr) + { + if (inp->inp_ipv6.ip6_nxt && inp->inp_ipv6.ip6_nxt != nexthdr) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) && - !IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, &ipv6->ipv6_dst)) + !IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, &ip6->ip6_dst)) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6) && - !IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, &ipv6->ipv6_src)) + !IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, &ip6->ip6_src)) continue; - if ((icmpv6type >= 0) && - ICMPV6_FILTER_WILLBLOCK(icmpv6type, &inp->inp_filter)) + if (inp->inp_icmp6filt && + ICMP6_FILTER_WILLBLOCK(icmp6type, inp->inp_icmp6filt)) continue; DPRINTF(IDL_EVENT, ("Found a raw pcb (>1)\n")); @@ -375,8 +384,8 @@ ripv6_input(m,extra) if ((m2 = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT))) { m_adj(m2, extra); DP(FINISHED, m2->m_pkthdr.len, d); - if (inp->inp_flags & INP_CONTROLOPTS) - opts = ipv6_headertocontrol(m, extra, inp->inp_flags); + if (inp->inp_flags & IN6P_CONTROLOPTS) + ip6_savecontrol(inp, &opts, ip6, m); else opts = NULL; if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&srcsa, m2, @@ -393,46 +402,54 @@ ripv6_input(m,extra) * We should send an ICMPv6 protocol unreachable here, * though original UCB 4.4-lite BSD's IPv4 does not do so. */ +#if 0 ipv6stat.ips_noproto++; ipv6stat.ips_delivered--; +#endif } ret: if (m) m_freem(m); - DPRINTF(FINISHED, ("ripv6_input\n")); + DPRINTF(FINISHED, ("rip6_input\n")); + return IPPROTO_DONE; } /*---------------------------------------------------------------------- - * Output function for raw IPv6. Called from ripv6_usrreq(), and + * Output function for raw IPv6. Called from rip6_usrreq(), and * ipv6_icmp_usrreq(). ----------------------------------------------------------------------*/ #if __OpenBSD__ -int ripv6_output(struct mbuf *m, ...) +int rip6_output(struct mbuf *m, ...) #else /* __OpenBSD__ */ int -ripv6_output(m, so, dst, control) +rip6_output(m, so, dst, control) struct mbuf *m; struct socket *so; struct in6_addr *dst; struct mbuf *control; #endif /* __OpenBSD__ */ { - register struct ipv6 *ipv6; + register struct ip6_hdr *ip6; register struct inpcb *inp; int flags; + int error = 0; +#if 0 struct ifnet *forceif = NULL; +#endif + struct ip6_pktopts opt, *optp = NULL; + struct ifnet *oifp = NULL; #if __OpenBSD__ va_list ap; struct socket *so; - struct in6_addr *dst; + struct sockaddr_in6 *dst; struct mbuf *control; va_start(ap, m); so = va_arg(ap, struct socket *); - dst = va_arg(ap, struct in6_addr *); + dst = va_arg(ap, struct sockaddr_in6 *); control = va_arg(ap, struct mbuf *); va_end(ap); #endif /* __OpenBSD__ */ @@ -440,6 +457,15 @@ ripv6_output(m, so, dst, control) inp = sotoinpcb(so); flags = (so->so_options & SO_DONTROUTE); + if (control) { + error = ip6_setpktoptions(control, &opt, so->so_state & SS_PRIV); + if (error != 0) + goto bad; + optp = &opt; + } else + optp = NULL; + +#if 0 if (inp->inp_flags & INP_HDRINCL) { flags |= IPV6_RAWOUTPUT; @@ -448,14 +474,25 @@ ripv6_output(m, so, dst, control) expects it to be contiguous. */ } else +#endif { - M_PREPEND(m, sizeof(struct ipv6), M_WAIT); - ipv6 = mtod(m, struct ipv6 *); - ipv6->ipv6_nexthdr = inp->inp_ipv6.ipv6_nexthdr; - ipv6->ipv6_hoplimit = MAXHOPLIMIT; - ipv6->ipv6_src = inp->inp_laddr6; - ipv6->ipv6_dst = *dst; - ipv6->ipv6_versfl = 0; /* Or possibly user flow label, in host order. */ + struct in6_addr *in6a; + + in6a = in6_selectsrc(dst, optp, inp->inp_moptions6, + &inp->inp_route6, &inp->inp_laddr6, &error); + if (in6a == NULL) { + if (error == 0) + error = EADDRNOTAVAIL; + goto bad; + } + + M_PREPEND(m, sizeof(struct ip6_hdr), M_WAIT); + ip6 = mtod(m, struct ip6_hdr *); + ip6->ip6_flow = 0; /* Or possibly user flow label, in host order. */ + ip6->ip6_vfc = IPV6_VERSION; + ip6->ip6_nxt = inp->inp_ipv6.ip6_nxt; + bcopy(in6a, &ip6->ip6_src, sizeof(*in6a)); + ip6->ip6_dst = dst->sin6_addr; /* * Question: How do I handle options? * @@ -463,22 +500,55 @@ ripv6_output(m, so, dst, control) */ } + /* + * If the scope of the destination is link-local, embed the interface + * index in the address. + * + * XXX advanced-api value overrides sin6_scope_id + */ + if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst) || + IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) { + struct in6_pktinfo *pi; + + /* + * XXX Boundary check is assumed to be already done in + * ip6_setpktoptions(). + */ + if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) { + ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex); + oifp = ifindex2ifnet[pi->ipi6_ifindex]; + } + else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && + inp->inp_moptions6 && + inp->inp_moptions6->im6o_multicast_ifp) { + oifp = inp->inp_moptions6->im6o_multicast_ifp; + ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index); + } else if (dst->sin6_scope_id) { + /* boundary check */ + if (dst->sin6_scope_id < 0 + || if_index < dst->sin6_scope_id) { + error = ENXIO; /* XXX EINVAL? */ + goto bad; + } + ip6->ip6_dst.s6_addr16[1] + = htons(dst->sin6_scope_id & 0xffff);/*XXX*/ + } + } + + ip6->ip6_hlim = in6_selecthlim(inp, oifp); + { - int payload = sizeof(struct ipv6); - int nexthdr = mtod(m, struct ipv6 *)->ipv6_nexthdr; + int payload = sizeof(struct ip6_hdr); + int nexthdr = mtod(m, struct ip6_hdr *)->ip6_nxt; +#if 0 int error; - - if (control) - if ((error = ipv6_controltoheader(&m, control, &forceif, &payload))) { - m_freem(m); - return error; - } +#endif if (inp->inp_csumoffset >= 0) { uint16_t *csum; if (!(m = m_pullup2(m, payload + inp->inp_csumoffset))) { - DPRINTF(IDL_ERROR, ("ripv6_output: m_pullup2(m, %d) failed\n", payload + inp->inp_csumoffset)); + DPRINTF(IDL_ERROR, ("rip6_output: m_pullup2(m, %d) failed\n", payload + inp->inp_csumoffset)); m_freem(m); return ENOBUFS; }; @@ -486,11 +556,16 @@ ripv6_output(m, so, dst, control) csum = (uint16_t *)(mtod(m, uint8_t *) + payload + inp->inp_csumoffset); *csum = 0; - *csum = in6_cksum(m, nexthdr, m->m_pkthdr.len - payload, payload); + *csum = in6_cksum(m, nexthdr, payload, m->m_pkthdr.len - payload); }; }; - return ipv6_output(m,&inp->inp_route6,flags,inp->inp_moptions6, forceif, so); + return ip6_output(m, optp, &inp->inp_route6, flags, inp->inp_moptions6, &oifp); + +bad: + if (m) + m_freem(m); + return error; } /*---------------------------------------------------------------------- @@ -498,7 +573,7 @@ ripv6_output(m, so, dst, control) ----------------------------------------------------------------------*/ #if __FreeBSD__ -int ripv6_ctloutput(struct socket *so, struct sockopt *sopt) +int rip6_ctloutput(struct socket *so, struct sockopt *sopt) { register struct inpcb *inp = sotoinpcb(so); int op; @@ -506,7 +581,7 @@ int ripv6_ctloutput(struct socket *so, struct sockopt *sopt) int optname; int optval; - DPRINTF(FINISHED, ("ripv6_ctloutput(so=%08x, sopt=%08x)\n", + DPRINTF(FINISHED, ("rip6_ctloutput(so=%08x, sopt=%08x)\n", OSDEP_PCAST(so), OSDEP_PCAST(sopt))); switch(sopt->sopt_dir) { @@ -524,7 +599,7 @@ int ripv6_ctloutput(struct socket *so, struct sockopt *sopt) optname = sopt->sopt_name; #else /* __FreeBSD__ */ int -ripv6_ctloutput (op, so, level, optname, m) +rip6_ctloutput (op, so, level, optname, m) int op; struct socket *so; int level, optname; @@ -532,7 +607,7 @@ ripv6_ctloutput (op, so, level, optname, m) { register struct inpcb *inp = sotoinpcb(so); - DPRINTF(FINISHED, ("ripv6_ctloutput(op=%x,so,level=%x,optname=%x,m)\n", op, level, optname)); + DPRINTF(FINISHED, ("rip6_ctloutput(op=%x,so,level=%x,optname=%x,m)\n", op, level, optname)); #endif /* __FreeBSD__ */ if ((level != IPPROTO_IP) && (level != IPPROTO_IPV6) && (level != IPPROTO_ICMPV6)) { @@ -572,34 +647,35 @@ ripv6_ctloutput (op, so, level, optname, m) return 0; }; break; - case ICMPV6_FILTER: + case ICMP6_FILTER: if (op == PRCO_SETOPT || op == PRCO_GETOPT) { #if __FreeBSD__ if (!sopt->sopt_val || (sopt->sopt_valsize != - sizeof(struct icmpv6_filter))) + sizeof(struct icmp6_filter))) RETURN_ERROR(EINVAL); if (op == PRCO_SETOPT) { - struct icmpv6_filter icmpv6_filter; - int error = sooptcopyin(sopt, &icmpv6_filter, - sizeof(struct icmpv6_filter), sizeof(struct icmpv6_filter)); + struct icmp6_filter icmp6_filter; + int error = sooptcopyin(sopt, &icmp6_filter, + sizeof(struct icmp6_filter), sizeof(struct icmp6_filter)); if (error) return error; - inp->inp_filter = icmpv6_filter; + bcopy(&icmp6_filter, inp->inp_icmp6filt, sizeof(icmp6_filter)); return 0; } else - return sooptcopyout(sopt, &inp->inp_filter, - sizeof(struct icmpv6_filter)); + return sooptcopyout(sopt, inp->inp_icmp6filt, + sizeof(struct icmp6_filter)); #else /* __FreeBSD__ */ - if (!m || !*m || (*m)->m_len != sizeof(struct icmpv6_filter)) + if (!m || !*m || (*m)->m_len != sizeof(struct icmp6_filter)) RETURN_ERROR(EINVAL); if (op == PRCO_SETOPT) { - inp->inp_filter = *mtod(*m, struct icmpv6_filter *); + bcopy(mtod(*m, struct icmp6_filter *), inp->inp_icmp6filt, + sizeof(struct icmp6_filter)); m_freem(*m); } else { - (*m)->m_len = sizeof(struct icmpv6_filter); - *mtod(*m, struct icmpv6_filter *) = inp->inp_filter; + (*m)->m_len = sizeof(struct icmp6_filter); + *mtod(*m, struct icmp6_filter *) = *inp->inp_icmp6filt; }; return 0; #endif /* __FreeBSD__ */ @@ -683,9 +759,9 @@ ripv6_ctloutput (op, so, level, optname, m) }; } #if __FreeBSD__ - return ipv6_ctloutput(so, sopt); + return ip6_ctloutput(so, sopt); #else /* __FreeBSD__ */ - return ipv6_ctloutput(op, so, level, optname, m); + return ip6_ctloutput(op, so, level, optname, m); #endif /* __FreeBSD__ */ } @@ -698,17 +774,17 @@ ripv6_ctloutput (op, so, level, optname, m) #endif /* __GNUC__ && __GNUC__ >= 2 && __OPTIMIZE__ && !__FreeBSD__ */ #if __NetBSD__ || __FreeBSD__ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_attach(struct socket *so, int proto, struct proc *p) #else /* __NetBSD__ || __FreeBSD__ */ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto) +MAYBESTATIC MAYBEINLINE int rip6_usrreq_attach(struct socket *so, int proto) #endif /* __NetBSD__ || __FreeBSD__ */ { register struct inpcb *inp = sotoinpcb(so); register int error = 0; if (inp) - panic("ripv6_attach - Already got PCB"); + panic("rip6_attach - Already got PCB"); #if __NetBSD__ || __FreeBSD__ if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) @@ -719,7 +795,7 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto) error = EACCES; return error; } - if ((error = soreserve(so, ripv6_sendspace, ripv6_recvspace)) || + if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) || #if __FreeBSD__ (error = in_pcballoc(so, &ri6pcbinfo, p))) @@ -735,48 +811,55 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto) inp = sotoinpcb(so); #ifdef __alpha__ - inp->inp_ipv6.ipv6_nexthdr = (u_long)proto; /*nam; Nam contains protocol + inp->inp_ipv6.ip6_nxt = (u_long)proto; /*nam; Nam contains protocol type, apparently. */ #else - inp->inp_ipv6.ipv6_nexthdr = (int)proto; /*nam; Nam contains protocol + inp->inp_ipv6.ip6_nxt = (int)proto; /*nam; Nam contains protocol type, apparently. */ #endif - if (inp->inp_ipv6.ipv6_nexthdr == IPPROTO_ICMPV6) + if (inp->inp_ipv6.ip6_nxt == IPPROTO_ICMPV6) inp->inp_csumoffset = 2; + inp->inp_icmp6filt = (struct icmp6_filter *) + malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); + ICMP6_FILTER_SETPASSALL(inp->inp_icmp6filt); return error; } -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_detach(struct socket *so) +MAYBESTATIC MAYBEINLINE int rip6_usrreq_detach(struct socket *so) { register struct inpcb *inp = sotoinpcb(so); if (inp == 0) - panic("ripv6_detach"); + panic("rip6_detach"); #ifdef MROUTING /* More MROUTING stuff. */ #endif + if (inp->inp_icmp6filt) { + free(inp->inp_icmp6filt, M_PCB); + inp->inp_icmp6filt = NULL; + } in_pcbdetach(inp); return 0; } -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_abort(struct socket *so) +MAYBESTATIC MAYBEINLINE int rip6_usrreq_abort(struct socket *so) { soisdisconnected(so); - return ripv6_usrreq_detach(so); + return rip6_usrreq_detach(so); } -static MAYBEINLINE int ripv6_usrreq_disconnect(struct socket *so) +static MAYBEINLINE int rip6_usrreq_disconnect(struct socket *so) { if ((so->so_state & SS_ISCONNECTED) == 0) return ENOTCONN; - return ripv6_usrreq_abort(so); + return rip6_usrreq_abort(so); } #if __NetBSD__ || __FreeBSD__ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_bind(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_bind(struct socket *so, struct sockaddr *nam, struct proc *p) #else /* __NetBSD__ || __FreeBSD__ */ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_bind(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_bind(struct socket *so, struct sockaddr *nam) #endif /* __NetBSD__ || __FreeBSD__ */ { @@ -800,27 +883,30 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_bind(struct socket *so, } #if __NetBSD__ || __FreeBSD__ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_connect(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_connect(struct socket *so, struct sockaddr *nam, struct proc *p) #else /* __NetBSD__ || __FreeBSD__ */ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_connect(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_connect(struct socket *so, struct sockaddr *nam) #endif /* __NetBSD__ || __FreeBSD__ */ { register struct inpcb *inp = sotoinpcb(so); register struct sockaddr_in6 *addr = (struct sockaddr_in6 *) nam; + int error; + struct in6_addr *in6a; if (addr->sin6_family != AF_INET6) return EAFNOSUPPORT; -#if __NetBSD__ || __FreeBSD__ || __OpenBSD__ - if (ifnet.tqh_first == 0) { -#else /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ - if (ifnet == 0) { -#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ - return EADDRNOTAVAIL; /* This is a weird way to say there - are no interfaces, no? */ - } + in6a = in6_selectsrc(addr, inp->inp_outputopts6, + inp->inp_moptions6, &inp->inp_route6, &inp->inp_laddr6, + &error); + if (in6a == NULL) { + if (error == 0) + error = EADDRNOTAVAIL; + return error; + } + inp->inp_laddr6 = *in6a; inp->inp_faddr6 = addr->sin6_addr; /* Will structure assignment work with this compiler? */ @@ -828,28 +914,31 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_connect(struct socket *so, return 0; } -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_shutdown(struct socket *so) +MAYBESTATIC MAYBEINLINE int rip6_usrreq_shutdown(struct socket *so) { socantsendmore(so); return 0; } +static int rip6_usrreq_send __P((struct socket *so, int flags, struct mbuf *m, + struct sockaddr *addr, struct mbuf *control)); + #if __NetBSD__ || __FreeBSD__ /* * Note that flags and p are not used, but required by protosw in * FreeBSD. */ -int ripv6_usrreq_send(struct socket *so, int flags, struct mbuf *m, +static int rip6_usrreq_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct proc *p) #else /* __NetBSD__ || __FreeBSD__ */ -int ripv6_usrreq_send(struct socket *so, int flags, struct mbuf *m, +static int rip6_usrreq_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control) #endif /* __NetBSD__ || __FreeBSD__ */ { register struct inpcb *inp = sotoinpcb(so); register int error = 0; - struct in6_addr *dst; + struct sockaddr_in6 *dst, tmp; if (inp == 0) { m_freem(m); @@ -865,26 +954,30 @@ int ripv6_usrreq_send(struct socket *so, int flags, struct mbuf *m, if (addr) return EISCONN; - dst = &(inp->inp_faddr6); + bzero(&tmp, sizeof(tmp)); + tmp.sin6_family = AF_INET6; + tmp.sin6_len = sizeof(tmp); + tmp.sin6_addr = inp->inp_faddr6; + dst = &tmp; } else { if (addr == NULL) return ENOTCONN; - dst = &((struct sockaddr_in6 *)addr)->sin6_addr; + dst = (struct sockaddr_in6 *)addr; } - error = ripv6_output(m,so,dst,control); + error = rip6_output(m,so,dst,control); /* m = NULL; */ return error; } #if __NetBSD__ || __FreeBSD__ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_control(struct socket *so, u_long cmd, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct proc *p) #else /* __NetBSD__ || __FreeBSD__ */ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_control(struct socket *so, int cmd, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_control(struct socket *so, int cmd, caddr_t data, struct ifnet *ifp) #endif /* __NetBSD__ || __FreeBSD__ */ { @@ -897,7 +990,7 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_control(struct socket *so, int cmd, #endif /* __NetBSD__ || __FreeBSD__ */ } -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sense(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_sense(struct socket *so, struct stat *sb) { /* services stat(2) call. */ @@ -905,10 +998,10 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sense(struct socket *so, } #if __FreeBSD__ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sockaddr(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_sockaddr(struct socket *so, struct sockaddr **nam) #else /* __FreeBSD__ */ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sockaddr(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_sockaddr(struct socket *so, struct mbuf *nam) #endif /* __FreeBSD__ */ { @@ -917,10 +1010,10 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sockaddr(struct socket *so, } #if __FreeBSD__ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_peeraddr(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_peeraddr(struct socket *so, struct sockaddr **nam) #else /* __FreeBSD__ */ -MAYBESTATIC MAYBEINLINE int ripv6_usrreq_peeraddr(struct socket *so, +MAYBESTATIC MAYBEINLINE int rip6_usrreq_peeraddr(struct socket *so, struct mbuf *nam) #endif /* __FreeBSD__ */ { @@ -929,13 +1022,13 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_peeraddr(struct socket *so, } #if __FreeBSD__ -struct pr_usrreqs ripv6_usrreqs = { - ripv6_usrreq_abort, pru_accept_notsupp, ripv6_usrreq_attach, - ripv6_usrreq_bind, ripv6_usrreq_connect, pru_connect2_notsupp, - ripv6_usrreq_control, ripv6_usrreq_detach, ripv6_usrreq_detach, - pru_listen_notsupp, ripv6_usrreq_peeraddr, pru_rcvd_notsupp, - pru_rcvoob_notsupp, ripv6_usrreq_send, ripv6_usrreq_sense, - ripv6_usrreq_shutdown, ripv6_usrreq_sockaddr, sosend, soreceive, sopoll +struct pr_usrreqs rip6_usrreqs = { + rip6_usrreq_abort, pru_accept_notsupp, rip6_usrreq_attach, + rip6_usrreq_bind, rip6_usrreq_connect, pru_connect2_notsupp, + rip6_usrreq_control, rip6_usrreq_detach, rip6_usrreq_detach, + pru_listen_notsupp, rip6_usrreq_peeraddr, pru_rcvd_notsupp, + pru_rcvoob_notsupp, rip6_usrreq_send, rip6_usrreq_sense, + rip6_usrreq_shutdown, rip6_usrreq_sockaddr, sosend, soreceive, sopoll }; #endif /* __FreeBSD__ */ @@ -944,21 +1037,15 @@ struct pr_usrreqs ripv6_usrreqs = { ----------------------------------------------------------------------*/ #if !__FreeBSD__ int -#if __NetBSD__ -ripv6_usrreq(so, req, m, nam, control, p) -#else /* __NetBSD__ */ -ripv6_usrreq(so, req, m, nam, control) -#endif /* __NetBSD__ */ +rip6_usrreq(so, req, m, nam, control, p) struct socket *so; int req; struct mbuf *m, *nam, *control; -#if __NetBSD__ struct proc *p; -#endif /* __NetBSD__ */ { register int error = 0; - DPRINTF(IDL_EVENT, ("ripv6_usrreq(so, req, m, nam, control)\n")); + DPRINTF(IDL_EVENT, ("rip6_usrreq(so, req, m, nam, control)\n")); #ifdef MROUTING /* @@ -974,23 +1061,23 @@ ripv6_usrreq(so, req, m, nam, control) { case PRU_ATTACH: #if __NetBSD__ - error = ripv6_usrreq_attach(so, 0, p); /* XXX */ + error = rip6_usrreq_attach(so, (long)nam, p); #else /* __NetBSD__ */ - error = ripv6_usrreq_attach(so, 0); /* XXX */ + error = rip6_usrreq_attach(so, (long)nam); #endif /* __NetBSD__ */ break; case PRU_DISCONNECT: - error = ripv6_usrreq_disconnect(so); + error = rip6_usrreq_disconnect(so); break; /* NOT */ /* FALLTHROUGH */ case PRU_ABORT: - error = ripv6_usrreq_abort(so); + error = rip6_usrreq_abort(so); break; /* NOT */ /* FALLTHROUGH */ case PRU_DETACH: - error = ripv6_usrreq_detach(so); + error = rip6_usrreq_detach(so); break; case PRU_BIND: if (nam->m_len != sizeof(struct sockaddr_in6)) @@ -999,9 +1086,9 @@ ripv6_usrreq(so, req, m, nam, control) * Be strict regarding sockaddr_in6 fields. */ #if __NetBSD__ - error = ripv6_usrreq_bind(so, mtod(nam, struct sockaddr *), p); + error = rip6_usrreq_bind(so, mtod(nam, struct sockaddr *), p); #else /* __NetBSD__ */ - error = ripv6_usrreq_bind(so, mtod(nam, struct sockaddr *)); + error = rip6_usrreq_bind(so, mtod(nam, struct sockaddr *)); #endif /* __NetBSD__ */ break; case PRU_CONNECT: @@ -1011,13 +1098,13 @@ ripv6_usrreq(so, req, m, nam, control) if (nam->m_len != sizeof(struct sockaddr_in6)) return EINVAL; #if __NetBSD__ - error = ripv6_usrreq_connect(so, mtod(nam, struct sockaddr *), p); + error = rip6_usrreq_connect(so, mtod(nam, struct sockaddr *), p); #else /* __NetBSD__ */ - error = ripv6_usrreq_connect(so, mtod(nam, struct sockaddr *)); + error = rip6_usrreq_connect(so, mtod(nam, struct sockaddr *)); #endif /* __NetBSD__ */ break; case PRU_SHUTDOWN: - error = ripv6_usrreq_shutdown(so); + error = rip6_usrreq_shutdown(so); break; case PRU_SEND: /* @@ -1026,22 +1113,22 @@ ripv6_usrreq(so, req, m, nam, control) if (nam->m_len != sizeof(struct sockaddr_in6)) return EINVAL; #if __NetBSD__ - error = ripv6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control, p); + error = rip6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control, p); #else /* __NetBSD__ */ - error = ripv6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control); + error = rip6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control); #endif /* __NetBSD__ */ m = NULL; break; case PRU_CONTROL: #if __NetBSD__ - return ripv6_usrreq_control(so, (u_long)m, (caddr_t) nam, + return rip6_usrreq_control(so, (u_long)m, (caddr_t) nam, (struct ifnet *) control, p); #else /* __NetBSD__ */ - return ripv6_usrreq_control(so, (int)m, (caddr_t) nam, + return rip6_usrreq_control(so, (int)m, (caddr_t) nam, (struct ifnet *) control); #endif /* __NetBSD__ */ case PRU_SENSE: - return ripv6_usrreq_sense(so, NULL); /* XXX */ + return rip6_usrreq_sense(so, NULL); /* XXX */ case PRU_CONNECT2: case PRU_RCVOOB: case PRU_LISTEN: @@ -1051,13 +1138,13 @@ ripv6_usrreq(so, req, m, nam, control) error = EOPNOTSUPP; break; case PRU_SOCKADDR: - error = ripv6_usrreq_sockaddr(so, nam); + error = rip6_usrreq_sockaddr(so, nam); break; case PRU_PEERADDR: - error = ripv6_usrreq_peeraddr(so, nam); + error = rip6_usrreq_peeraddr(so, nam); break; default: - panic ("ripv6_usrreq - unknown req\n"); + panic ("rip6_usrreq - unknown req\n"); } if (m != NULL) m_freem(m); |