version 1.31, 2001/03/04 16:49:17 |
version 1.31.2.10, 2002/06/24 22:11:54 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
/* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ |
/* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */ |
|
|
/* |
/* |
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
|
|
* @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 |
* @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 |
*/ |
*/ |
|
|
|
#include <sys/cdefs.h> |
|
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#include "opt_ipsec.h" |
#include "opt_ipsec.h" |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
|
|
#include <sys/socketvar.h> |
#include <sys/socketvar.h> |
#include <sys/errno.h> |
#include <sys/errno.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
|
#include <sys/lwp.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
|
|
#include <net/if.h> |
#include <net/if.h> |
|
|
#ifdef ENABLE_DEFAULT_SCOPE |
#ifdef ENABLE_DEFAULT_SCOPE |
#include <netinet6/scope6_var.h> |
#include <netinet6/scope6_var.h> |
#endif |
#endif |
|
#include <netinet6/raw_ip6.h> |
|
|
#ifdef IPSEC |
#ifdef IPSEC |
#include <netinet6/ipsec.h> |
#include <netinet6/ipsec.h> |
#endif /*IPSEC*/ |
#endif /* IPSEC */ |
|
|
#include <machine/stdarg.h> |
#include <machine/stdarg.h> |
|
|
#include "faith.h" |
#include "faith.h" |
|
#if defined(NFAITH) && 0 < NFAITH |
|
#include <net/if_faith.h> |
|
#endif |
|
|
struct in6pcb rawin6pcb; |
struct in6pcb rawin6pcb; |
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) |
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) |
Line 109 struct in6pcb rawin6pcb; |
|
Line 117 struct in6pcb rawin6pcb; |
|
* Raw interface to IP6 protocol. |
* Raw interface to IP6 protocol. |
*/ |
*/ |
|
|
|
struct rip6stat rip6stat; |
|
|
/* |
/* |
* Initialize raw connection block queue. |
* Initialize raw connection block queue. |
*/ |
*/ |
void |
void |
rip6_init() |
rip6_init() |
{ |
{ |
|
|
rawin6pcb.in6p_next = rawin6pcb.in6p_prev = &rawin6pcb; |
rawin6pcb.in6p_next = rawin6pcb.in6p_prev = &rawin6pcb; |
} |
} |
|
|
Line 135 rip6_input(mp, offp, proto) |
|
Line 146 rip6_input(mp, offp, proto) |
|
struct sockaddr_in6 rip6src; |
struct sockaddr_in6 rip6src; |
struct mbuf *opts = NULL; |
struct mbuf *opts = NULL; |
|
|
|
rip6stat.rip6s_ipackets++; |
|
|
#if defined(NFAITH) && 0 < NFAITH |
#if defined(NFAITH) && 0 < NFAITH |
if (m->m_pkthdr.rcvif) { |
if (faithprefix(&ip6->ip6_dst)) { |
if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { |
/* send icmp6 host unreach? */ |
/* send icmp6 host unreach? */ |
m_freem(m); |
m_freem(m); |
return IPPROTO_DONE; |
return IPPROTO_DONE; |
|
} |
|
} |
} |
#endif |
#endif |
|
|
Line 156 rip6_input(mp, offp, proto) |
|
Line 167 rip6_input(mp, offp, proto) |
|
bzero(&rip6src, sizeof(rip6src)); |
bzero(&rip6src, sizeof(rip6src)); |
rip6src.sin6_len = sizeof(struct sockaddr_in6); |
rip6src.sin6_len = sizeof(struct sockaddr_in6); |
rip6src.sin6_family = AF_INET6; |
rip6src.sin6_family = AF_INET6; |
#if 0 /*XXX inbound flowlabel */ |
#if 0 /* XXX inbound flowlabel */ |
rip6src.sin6_flowinfo = ip6->ip6_flow & IPV6_FLOWINFO_MASK; |
rip6src.sin6_flowinfo = ip6->ip6_flow & IPV6_FLOWINFO_MASK; |
#endif |
#endif |
/* KAME hack: recover scopeid */ |
/* KAME hack: recover scopeid */ |
Line 169 rip6_input(mp, offp, proto) |
|
Line 180 rip6_input(mp, offp, proto) |
|
in6p->in6p_ip6.ip6_nxt != proto) |
in6p->in6p_ip6.ip6_nxt != proto) |
continue; |
continue; |
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && |
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && |
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) |
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) |
continue; |
continue; |
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && |
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && |
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) |
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) |
continue; |
|
if (in6p->in6p_cksum != -1 |
|
&& in6_cksum(m, ip6->ip6_nxt, *offp, m->m_pkthdr.len - *offp)) |
|
{ |
|
/* XXX bark something */ |
|
continue; |
continue; |
|
if (in6p->in6p_cksum != -1) { |
|
rip6stat.rip6s_isum++; |
|
if (in6_cksum(m, ip6->ip6_nxt, *offp, |
|
m->m_pkthdr.len - *offp)) { |
|
rip6stat.rip6s_badsum++; |
|
continue; |
|
} |
} |
} |
if (last) { |
if (last) { |
struct mbuf *n; |
struct mbuf *n; |
Line 191 rip6_input(mp, offp, proto) |
|
Line 204 rip6_input(mp, offp, proto) |
|
ipsec6stat.in_polvio++; |
ipsec6stat.in_polvio++; |
/* do not inject data into pcb */ |
/* do not inject data into pcb */ |
} else |
} else |
#endif /*IPSEC*/ |
#endif /* IPSEC */ |
if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { |
if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { |
if (last->in6p_flags & IN6P_CONTROLOPTS) |
if (last->in6p_flags & IN6P_CONTROLOPTS) |
ip6_savecontrol(last, &opts, ip6, n); |
ip6_savecontrol(last, &opts, ip6, n); |
/* strip intermediate headers */ |
/* strip intermediate headers */ |
m_adj(n, *offp); |
m_adj(n, *offp); |
if (sbappendaddr(&last->in6p_socket->so_rcv, |
if (sbappendaddr(&last->in6p_socket->so_rcv, |
(struct sockaddr *)&rip6src, |
(struct sockaddr *)&rip6src, n, opts) == 0) { |
n, opts) == 0) { |
|
/* should notify about lost packet */ |
/* should notify about lost packet */ |
m_freem(n); |
m_freem(n); |
if (opts) |
if (opts) |
m_freem(opts); |
m_freem(opts); |
|
rip6stat.rip6s_fullsock++; |
} else |
} else |
sorwakeup(last->in6p_socket); |
sorwakeup(last->in6p_socket); |
opts = NULL; |
opts = NULL; |
Line 221 rip6_input(mp, offp, proto) |
|
Line 234 rip6_input(mp, offp, proto) |
|
ip6stat.ip6s_delivered--; |
ip6stat.ip6s_delivered--; |
/* do not inject data into pcb */ |
/* do not inject data into pcb */ |
} else |
} else |
#endif /*IPSEC*/ |
#endif /* IPSEC */ |
if (last) { |
if (last) { |
if (last->in6p_flags & IN6P_CONTROLOPTS) |
if (last->in6p_flags & IN6P_CONTROLOPTS) |
ip6_savecontrol(last, &opts, ip6, m); |
ip6_savecontrol(last, &opts, ip6, m); |
/* strip intermediate headers */ |
/* strip intermediate headers */ |
m_adj(m, *offp); |
m_adj(m, *offp); |
if (sbappendaddr(&last->in6p_socket->so_rcv, |
if (sbappendaddr(&last->in6p_socket->so_rcv, |
(struct sockaddr *)&rip6src, m, opts) == 0) { |
(struct sockaddr *)&rip6src, m, opts) == 0) { |
m_freem(m); |
m_freem(m); |
if (opts) |
if (opts) |
m_freem(opts); |
m_freem(opts); |
|
rip6stat.rip6s_fullsock++; |
} else |
} else |
sorwakeup(last->in6p_socket); |
sorwakeup(last->in6p_socket); |
} else { |
} else { |
|
rip6stat.rip6s_nosock++; |
|
if (m->m_flags & M_MCAST) |
|
rip6stat.rip6s_nosockmcast++; |
if (proto == IPPROTO_NONE) |
if (proto == IPPROTO_NONE) |
m_freem(m); |
m_freem(m); |
else { |
else { |
char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ |
char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ |
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_protounknown); |
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_protounknown); |
icmp6_error(m, ICMP6_PARAM_PROB, |
icmp6_error(m, ICMP6_PARAM_PROB, |
ICMP6_PARAMPROB_NEXTHEADER, |
ICMP6_PARAMPROB_NEXTHEADER, |
prvnxtp - mtod(m, char *)); |
prvnxtp - mtod(m, char *)); |
} |
} |
ip6stat.ip6s_delivered--; |
ip6stat.ip6s_delivered--; |
} |
} |
Line 309 rip6_ctlinput(cmd, sa, d) |
|
Line 326 rip6_ctlinput(cmd, sa, d) |
|
* from icmp6_notify_error() |
* from icmp6_notify_error() |
*/ |
*/ |
in6p = NULL; |
in6p = NULL; |
in6p = in6_pcblookup_connect(&rawin6pcb, |
in6p = in6_pcblookup_connect(&rawin6pcb, &sa6->sin6_addr, 0, |
&sa6->sin6_addr, 0, |
|
(struct in6_addr *)&sa6_src->sin6_addr, 0, 0); |
(struct in6_addr *)&sa6_src->sin6_addr, 0, 0); |
#if 0 |
#if 0 |
if (!in6p) { |
if (!in6p) { |
Line 333 rip6_ctlinput(cmd, sa, d) |
|
Line 349 rip6_ctlinput(cmd, sa, d) |
|
/* |
/* |
* Depending on the value of "valid" and routing table |
* Depending on the value of "valid" and routing table |
* size (mtudisc_{hi,lo}wat), we will: |
* size (mtudisc_{hi,lo}wat), we will: |
* - recalcurate the new MTU and create the |
* - recalculate the new MTU and create the |
* corresponding routing entry, or |
* corresponding routing entry, or |
* - ignore the MTU change notification. |
* - ignore the MTU change notification. |
*/ |
*/ |
Line 442 rip6_output(m, va_alist) |
|
Line 458 rip6_output(m, va_alist) |
|
{ |
{ |
struct in6_addr *in6a; |
struct in6_addr *in6a; |
|
|
if ((in6a = in6_selectsrc(dstsock, optp, |
if ((in6a = in6_selectsrc(dstsock, optp, in6p->in6p_moptions, |
in6p->in6p_moptions, |
&in6p->in6p_route, &in6p->in6p_laddr, &error)) == 0) { |
&in6p->in6p_route, |
|
&in6p->in6p_laddr, |
|
&error)) == 0) { |
|
if (error == 0) |
if (error == 0) |
error = EADDRNOTAVAIL; |
error = EADDRNOTAVAIL; |
goto bad; |
goto bad; |
Line 472 rip6_output(m, va_alist) |
|
Line 485 rip6_output(m, va_alist) |
|
int off; |
int off; |
u_int16_t sum; |
u_int16_t sum; |
|
|
#define offsetof(type, member) ((size_t)(&((type *)0)->member)) /* XXX */ |
|
|
|
/* compute checksum */ |
/* compute checksum */ |
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) |
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) |
off = offsetof(struct icmp6_hdr, icmp6_cksum); |
off = offsetof(struct icmp6_hdr, icmp6_cksum); |
Line 496 rip6_output(m, va_alist) |
|
Line 507 rip6_output(m, va_alist) |
|
error = ENOBUFS; |
error = ENOBUFS; |
goto bad; |
goto bad; |
} |
} |
#endif /*IPSEC*/ |
#endif /* IPSEC */ |
|
|
flags = 0; |
flags = 0; |
#ifdef IPV6_MINMTU |
#ifdef IN6P_MINMTU |
if (in6p->in6p_flags & IN6P_MINMTU) |
if (in6p->in6p_flags & IN6P_MINMTU) |
flags |= IPV6_MINMTU; |
flags |= IPV6_MINMTU; |
#endif |
#endif |
|
|
error = ip6_output(m, optp, &in6p->in6p_route, flags, |
error = ip6_output(m, optp, &in6p->in6p_route, flags, |
in6p->in6p_moptions, &oifp); |
in6p->in6p_moptions, &oifp); |
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { |
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { |
if (oifp) |
if (oifp) |
icmp6_ifoutstat_inc(oifp, type, code); |
icmp6_ifoutstat_inc(oifp, type, code); |
icmp6stat.icp6s_outhist[type]++; |
icmp6stat.icp6s_outhist[type]++; |
} |
} else |
|
rip6stat.rip6s_opackets++; |
|
|
goto freectl; |
goto freectl; |
|
|
Line 530 rip6_output(m, va_alist) |
|
Line 542 rip6_output(m, va_alist) |
|
* Raw IPv6 socket option processing. |
* Raw IPv6 socket option processing. |
*/ |
*/ |
int |
int |
rip6_ctloutput(op, so, level, optname, m) |
rip6_ctloutput(op, so, level, optname, mp) |
int op; |
int op; |
struct socket *so; |
struct socket *so; |
int level, optname; |
int level, optname; |
struct mbuf **m; |
struct mbuf **mp; |
{ |
{ |
int error = 0; |
int error = 0; |
|
|
Line 549 rip6_ctloutput(op, so, level, optname, m |
|
Line 561 rip6_ctloutput(op, so, level, optname, m |
|
case MRT6_DEL_MFC: |
case MRT6_DEL_MFC: |
case MRT6_PIM: |
case MRT6_PIM: |
if (op == PRCO_SETOPT) { |
if (op == PRCO_SETOPT) { |
error = ip6_mrouter_set(optname, so, *m); |
error = ip6_mrouter_set(optname, so, *mp); |
if (*m) |
if (*mp) |
(void)m_free(*m); |
(void)m_free(*mp); |
} else if (op == PRCO_GETOPT) { |
} else if (op == PRCO_GETOPT) |
error = ip6_mrouter_get(optname, so, m); |
error = ip6_mrouter_get(optname, so, mp); |
} else |
else |
error = EINVAL; |
error = EINVAL; |
return (error); |
return (error); |
|
case IPV6_CHECKSUM: |
|
return (ip6_raw_ctloutput(op, so, level, optname, mp)); |
|
default: |
|
return (ip6_ctloutput(op, so, level, optname, mp)); |
} |
} |
return (ip6_ctloutput(op, so, level, optname, m)); |
|
/* NOTREACHED */ |
|
|
|
case IPPROTO_ICMPV6: |
case IPPROTO_ICMPV6: |
/* |
/* |
* XXX: is it better to call icmp6_ctloutput() directly |
* XXX: is it better to call icmp6_ctloutput() directly |
* from protosw? |
* from protosw? |
*/ |
*/ |
return(icmp6_ctloutput(op, so, level, optname, m)); |
return (icmp6_ctloutput(op, so, level, optname, mp)); |
|
|
default: |
default: |
if (op == PRCO_SETOPT && *m) |
if (op == PRCO_SETOPT && *mp) |
(void)m_free(*m); |
m_free(*mp); |
return(EINVAL); |
return EINVAL; |
} |
} |
} |
} |
|
|
Line 597 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 611 rip6_usrreq(so, req, m, nam, control, p) |
|
|
|
if (req == PRU_CONTROL) |
if (req == PRU_CONTROL) |
return (in6_control(so, (u_long)m, (caddr_t)nam, |
return (in6_control(so, (u_long)m, (caddr_t)nam, |
(struct ifnet *)control, p)); |
(struct ifnet *)control, p)); |
|
|
if (req == PRU_PURGEIF) { |
if (req == PRU_PURGEIF) { |
|
in6_pcbpurgeif0(&rawin6pcb, (struct ifnet *)control); |
in6_purgeif((struct ifnet *)control); |
in6_purgeif((struct ifnet *)control); |
in6_pcbpurgeif(&rawin6pcb, (struct ifnet *)control); |
in6_pcbpurgeif(&rawin6pcb, (struct ifnet *)control); |
return (0); |
return (0); |
Line 627 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 642 rip6_usrreq(so, req, m, nam, control, p) |
|
in6p = sotoin6pcb(so); |
in6p = sotoin6pcb(so); |
in6p->in6p_ip6.ip6_nxt = (long)nam; |
in6p->in6p_ip6.ip6_nxt = (long)nam; |
in6p->in6p_cksum = -1; |
in6p->in6p_cksum = -1; |
#ifdef IPSEC |
|
error = ipsec_init_policy(so, &in6p->in6p_sp); |
|
if (error != 0) { |
|
in6_pcbdetach(in6p); |
|
break; |
|
} |
|
#endif /*IPSEC*/ |
|
|
|
MALLOC(in6p->in6p_icmp6filt, struct icmp6_filter *, |
MALLOC(in6p->in6p_icmp6filt, struct icmp6_filter *, |
sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); |
sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); |
if (in6p->in6p_icmp6filt == NULL) { |
if (in6p->in6p_icmp6filt == NULL) { |
in6_pcbdetach(in6p); |
in6_pcbdetach(in6p); |
error = ENOMEM; |
error = ENOMEM; |
Line 686 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 694 rip6_usrreq(so, req, m, nam, control, p) |
|
#ifdef ENABLE_DEFAULT_SCOPE |
#ifdef ENABLE_DEFAULT_SCOPE |
if (addr->sin6_scope_id == 0) /* not change if specified */ |
if (addr->sin6_scope_id == 0) /* not change if specified */ |
addr->sin6_scope_id = |
addr->sin6_scope_id = |
scope6_addr2default(&addr->sin6_addr); |
scope6_addr2default(&addr->sin6_addr); |
|
#endif |
|
/* KAME hack: embed scopeid */ |
|
if (in6_embedscope(&addr->sin6_addr, addr, in6p, NULL) != 0) |
|
return EINVAL; |
|
#ifndef SCOPEDROUTING |
|
addr->sin6_scope_id = 0; /* for ifa_ifwithaddr */ |
#endif |
#endif |
|
|
/* |
/* |
* we don't support mapped address here, it would confuse |
* we don't support mapped address here, it would confuse |
* users so reject it |
* users so reject it |
Line 696 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 711 rip6_usrreq(so, req, m, nam, control, p) |
|
error = EADDRNOTAVAIL; |
error = EADDRNOTAVAIL; |
break; |
break; |
} |
} |
/* |
|
* Currently, ifa_ifwithaddr tends to fail for a link-local |
|
* address, since it implicitly expects that the link ID |
|
* for the address is embedded in the sin6_addr part. |
|
* For now, we'd rather keep this "as is". We'll eventually fix |
|
* this in a more natural way. |
|
*/ |
|
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && |
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) && |
(ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) { |
(ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0) { |
error = EADDRNOTAVAIL; |
error = EADDRNOTAVAIL; |
break; |
break; |
} |
} |
if (ia && |
if (ia && ((struct in6_ifaddr *)ia)->ia6_flags & |
((struct in6_ifaddr *)ia)->ia6_flags & |
|
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| |
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY| |
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { |
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) { |
error = EADDRNOTAVAIL; |
error = EADDRNOTAVAIL; |
Line 718 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 725 rip6_usrreq(so, req, m, nam, control, p) |
|
in6p->in6p_laddr = addr->sin6_addr; |
in6p->in6p_laddr = addr->sin6_addr; |
break; |
break; |
} |
} |
|
|
case PRU_CONNECT: |
case PRU_CONNECT: |
{ |
{ |
struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *); |
struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *); |
struct in6_addr *in6a = NULL; |
struct in6_addr *in6a = NULL; |
#ifdef ENABLE_DEFAULT_SCOPE |
#ifdef ENABLE_DEFAULT_SCOPE |
Line 747 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 754 rip6_usrreq(so, req, m, nam, control, p) |
|
sin6 = *addr; |
sin6 = *addr; |
addr = &sin6; |
addr = &sin6; |
addr->sin6_scope_id = |
addr->sin6_scope_id = |
scope6_addr2default(&addr->sin6_addr); |
scope6_addr2default(&addr->sin6_addr); |
} |
} |
#endif |
#endif |
|
|
/* Source address selection. XXX: need pcblookup? */ |
/* Source address selection. XXX: need pcblookup? */ |
in6a = in6_selectsrc(addr, in6p->in6p_outputopts, |
in6a = in6_selectsrc(addr, in6p->in6p_outputopts, |
in6p->in6p_moptions, |
in6p->in6p_moptions, &in6p->in6p_route, |
&in6p->in6p_route, |
&in6p->in6p_laddr, &error); |
&in6p->in6p_laddr, |
|
&error); |
|
if (in6a == NULL) { |
if (in6a == NULL) { |
if (error == 0) |
if (error == 0) |
error = EADDRNOTAVAIL; |
error = EADDRNOTAVAIL; |
Line 766 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 771 rip6_usrreq(so, req, m, nam, control, p) |
|
in6p->in6p_faddr = addr->sin6_addr; |
in6p->in6p_faddr = addr->sin6_addr; |
soisconnected(so); |
soisconnected(so); |
break; |
break; |
} |
} |
|
|
case PRU_CONNECT2: |
case PRU_CONNECT2: |
error = EOPNOTSUPP; |
error = EOPNOTSUPP; |
Line 783 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 788 rip6_usrreq(so, req, m, nam, control, p) |
|
* routine handles any messaging necessary. |
* routine handles any messaging necessary. |
*/ |
*/ |
case PRU_SEND: |
case PRU_SEND: |
{ |
{ |
struct sockaddr_in6 tmp; |
struct sockaddr_in6 tmp; |
struct sockaddr_in6 *dst; |
struct sockaddr_in6 *dst; |
|
|
Line 798 rip6_usrreq(so, req, m, nam, control, p) |
|
Line 803 rip6_usrreq(so, req, m, nam, control, p) |
|
tmp.sin6_family = AF_INET6; |
tmp.sin6_family = AF_INET6; |
tmp.sin6_len = sizeof(struct sockaddr_in6); |
tmp.sin6_len = sizeof(struct sockaddr_in6); |
bcopy(&in6p->in6p_faddr, &tmp.sin6_addr, |
bcopy(&in6p->in6p_faddr, &tmp.sin6_addr, |
sizeof(struct in6_addr)); |
sizeof(struct in6_addr)); |
dst = &tmp; |
dst = &tmp; |
} else { |
} else { |
if (nam == NULL) { |
if (nam == NULL) { |
error = ENOTCONN; |
error = ENOTCONN; |
break; |
break; |
} |
} |
|
if (nam->m_len != sizeof(tmp)) { |
|
error = EINVAL; |
|
break; |
|
} |
|
|
tmp = *mtod(nam, struct sockaddr_in6 *); |
tmp = *mtod(nam, struct sockaddr_in6 *); |
dst = &tmp; |
dst = &tmp; |
|
|
|
if (dst->sin6_family != AF_INET6) { |
|
error = EAFNOSUPPORT; |
|
break; |
|
} |
} |
} |
#ifdef ENABLE_DEFAULT_SCOPE |
#ifdef ENABLE_DEFAULT_SCOPE |
if (dst->sin6_scope_id == 0) { |
if (dst->sin6_scope_id == 0) { |
dst->sin6_scope_id = |
dst->sin6_scope_id = |
scope6_addr2default(&dst->sin6_addr); |
scope6_addr2default(&dst->sin6_addr); |
} |
} |
#endif |
#endif |
error = rip6_output(m, so, dst, control); |
error = rip6_output(m, so, dst, control); |
m = NULL; |
m = NULL; |
break; |
break; |
} |
} |
|
|
case PRU_SENSE: |
case PRU_SENSE: |
/* |
/* |