mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-10-14 07:15:58 +08:00
Move rtems/freebsd to freebsd and contrib to freebsd/contrib
This commit is contained in:
125
freebsd/netinet6/dest6.c
Normal file
125
freebsd/netinet6/dest6.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: dest6.c,v 1.59 2003/07/11 13:21:16 t-momose Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_inet.h>
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/domain.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/errno.h>
|
||||
#include <rtems/freebsd/sys/time.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet/icmp6.h>
|
||||
|
||||
/*
|
||||
* Destination options header processing.
|
||||
*/
|
||||
int
|
||||
dest6_input(struct mbuf **mp, int *offp, int proto)
|
||||
{
|
||||
struct mbuf *m = *mp;
|
||||
int off = *offp, dstoptlen, optlen;
|
||||
struct ip6_dest *dstopts;
|
||||
u_int8_t *opt;
|
||||
|
||||
/* validation of the length of the header */
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off, sizeof(*dstopts), IPPROTO_DONE);
|
||||
dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
|
||||
#else
|
||||
IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, sizeof(*dstopts));
|
||||
if (dstopts == NULL)
|
||||
return IPPROTO_DONE;
|
||||
#endif
|
||||
dstoptlen = (dstopts->ip6d_len + 1) << 3;
|
||||
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off, dstoptlen, IPPROTO_DONE);
|
||||
dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
|
||||
#else
|
||||
IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, dstoptlen);
|
||||
if (dstopts == NULL)
|
||||
return IPPROTO_DONE;
|
||||
#endif
|
||||
off += dstoptlen;
|
||||
dstoptlen -= sizeof(struct ip6_dest);
|
||||
opt = (u_int8_t *)dstopts + sizeof(struct ip6_dest);
|
||||
|
||||
/* search header for all options. */
|
||||
for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) {
|
||||
if (*opt != IP6OPT_PAD1 &&
|
||||
(dstoptlen < IP6OPT_MINLEN || *(opt + 1) + 2 > dstoptlen)) {
|
||||
V_ip6stat.ip6s_toosmall++;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
switch (*opt) {
|
||||
case IP6OPT_PAD1:
|
||||
optlen = 1;
|
||||
break;
|
||||
case IP6OPT_PADN:
|
||||
optlen = *(opt + 1) + 2;
|
||||
break;
|
||||
default: /* unknown option */
|
||||
optlen = ip6_unknown_opt(opt, m,
|
||||
opt - mtod(m, u_int8_t *));
|
||||
if (optlen == -1)
|
||||
return (IPPROTO_DONE);
|
||||
optlen += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*offp = off;
|
||||
return (dstopts->ip6d_nxt);
|
||||
|
||||
bad:
|
||||
m_freem(m);
|
||||
return (IPPROTO_DONE);
|
||||
}
|
781
freebsd/netinet6/frag6.c
Normal file
781
freebsd/netinet6/frag6.c
Normal file
@@ -0,0 +1,781 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: frag6.c,v 1.33 2002/01/07 11:34:48 kjc Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/domain.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/errno.h>
|
||||
#include <rtems/freebsd/sys/time.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/syslog.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
#include <rtems/freebsd/net/vnet.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet/icmp6.h>
|
||||
#include <rtems/freebsd/netinet/in_systm.h> /* for ECN definitions */
|
||||
#include <rtems/freebsd/netinet/ip.h> /* for ECN definitions */
|
||||
|
||||
#include <rtems/freebsd/security/mac/mac_framework.h>
|
||||
|
||||
/*
|
||||
* Define it to get a correct behavior on per-interface statistics.
|
||||
* You will need to perform an extra routing table lookup, per fragment,
|
||||
* to do it. This may, or may not be, a performance hit.
|
||||
*/
|
||||
#define IN6_IFSTAT_STRICT
|
||||
|
||||
static void frag6_enq(struct ip6asfrag *, struct ip6asfrag *);
|
||||
static void frag6_deq(struct ip6asfrag *);
|
||||
static void frag6_insque(struct ip6q *, struct ip6q *);
|
||||
static void frag6_remque(struct ip6q *);
|
||||
static void frag6_freef(struct ip6q *);
|
||||
|
||||
static struct mtx ip6qlock;
|
||||
/*
|
||||
* These fields all protected by ip6qlock.
|
||||
*/
|
||||
static VNET_DEFINE(u_int, frag6_nfragpackets);
|
||||
static VNET_DEFINE(u_int, frag6_nfrags);
|
||||
static VNET_DEFINE(struct ip6q, ip6q); /* ip6 reassemble queue */
|
||||
|
||||
#define V_frag6_nfragpackets VNET(frag6_nfragpackets)
|
||||
#define V_frag6_nfrags VNET(frag6_nfrags)
|
||||
#define V_ip6q VNET(ip6q)
|
||||
|
||||
#define IP6Q_LOCK_INIT() mtx_init(&ip6qlock, "ip6qlock", NULL, MTX_DEF);
|
||||
#define IP6Q_LOCK() mtx_lock(&ip6qlock)
|
||||
#define IP6Q_TRYLOCK() mtx_trylock(&ip6qlock)
|
||||
#define IP6Q_LOCK_ASSERT() mtx_assert(&ip6qlock, MA_OWNED)
|
||||
#define IP6Q_UNLOCK() mtx_unlock(&ip6qlock)
|
||||
|
||||
static MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header");
|
||||
|
||||
/*
|
||||
* Initialise reassembly queue and fragment identifier.
|
||||
*/
|
||||
static void
|
||||
frag6_change(void *tag)
|
||||
{
|
||||
|
||||
V_ip6_maxfragpackets = nmbclusters / 4;
|
||||
V_ip6_maxfrags = nmbclusters / 4;
|
||||
}
|
||||
|
||||
void
|
||||
frag6_init(void)
|
||||
{
|
||||
|
||||
V_ip6_maxfragpackets = nmbclusters / 4;
|
||||
V_ip6_maxfrags = nmbclusters / 4;
|
||||
V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q;
|
||||
|
||||
if (!IS_DEFAULT_VNET(curvnet))
|
||||
return;
|
||||
|
||||
EVENTHANDLER_REGISTER(nmbclusters_change,
|
||||
frag6_change, NULL, EVENTHANDLER_PRI_ANY);
|
||||
|
||||
IP6Q_LOCK_INIT();
|
||||
}
|
||||
|
||||
/*
|
||||
* In RFC2460, fragment and reassembly rule do not agree with each other,
|
||||
* in terms of next header field handling in fragment header.
|
||||
* While the sender will use the same value for all of the fragmented packets,
|
||||
* receiver is suggested not to check the consistency.
|
||||
*
|
||||
* fragment rule (p20):
|
||||
* (2) A Fragment header containing:
|
||||
* The Next Header value that identifies the first header of
|
||||
* the Fragmentable Part of the original packet.
|
||||
* -> next header field is same for all fragments
|
||||
*
|
||||
* reassembly rule (p21):
|
||||
* The Next Header field of the last header of the Unfragmentable
|
||||
* Part is obtained from the Next Header field of the first
|
||||
* fragment's Fragment header.
|
||||
* -> should grab it from the first fragment only
|
||||
*
|
||||
* The following note also contradicts with fragment rule - noone is going to
|
||||
* send different fragment with different next header field.
|
||||
*
|
||||
* additional note (p22):
|
||||
* The Next Header values in the Fragment headers of different
|
||||
* fragments of the same original packet may differ. Only the value
|
||||
* from the Offset zero fragment packet is used for reassembly.
|
||||
* -> should grab it from the first fragment only
|
||||
*
|
||||
* There is no explicit reason given in the RFC. Historical reason maybe?
|
||||
*/
|
||||
/*
|
||||
* Fragment input
|
||||
*/
|
||||
int
|
||||
frag6_input(struct mbuf **mp, int *offp, int proto)
|
||||
{
|
||||
struct mbuf *m = *mp, *t;
|
||||
struct ip6_hdr *ip6;
|
||||
struct ip6_frag *ip6f;
|
||||
struct ip6q *q6;
|
||||
struct ip6asfrag *af6, *ip6af, *af6dwn;
|
||||
#ifdef IN6_IFSTAT_STRICT
|
||||
struct in6_ifaddr *ia;
|
||||
#endif
|
||||
int offset = *offp, nxt, i, next;
|
||||
int first_frag = 0;
|
||||
int fragoff, frgpartlen; /* must be larger than u_int16_t */
|
||||
struct ifnet *dstifp;
|
||||
u_int8_t ecn, ecn0;
|
||||
#if 0
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
#endif
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), IPPROTO_DONE);
|
||||
ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset);
|
||||
#else
|
||||
IP6_EXTHDR_GET(ip6f, struct ip6_frag *, m, offset, sizeof(*ip6f));
|
||||
if (ip6f == NULL)
|
||||
return (IPPROTO_DONE);
|
||||
#endif
|
||||
|
||||
dstifp = NULL;
|
||||
#ifdef IN6_IFSTAT_STRICT
|
||||
/* find the destination interface of the packet. */
|
||||
if ((ia = ip6_getdstifaddr(m)) != NULL) {
|
||||
dstifp = ia->ia_ifp;
|
||||
ifa_free(&ia->ia_ifa);
|
||||
}
|
||||
#else
|
||||
/* we are violating the spec, this is not the destination interface */
|
||||
if ((m->m_flags & M_PKTHDR) != 0)
|
||||
dstifp = m->m_pkthdr.rcvif;
|
||||
#endif
|
||||
|
||||
/* jumbo payload can't contain a fragment header */
|
||||
if (ip6->ip6_plen == 0) {
|
||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset);
|
||||
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether fragment packet's fragment length is
|
||||
* multiple of 8 octets.
|
||||
* sizeof(struct ip6_frag) == 8
|
||||
* sizeof(struct ip6_hdr) = 40
|
||||
*/
|
||||
if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) &&
|
||||
(((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) {
|
||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||
offsetof(struct ip6_hdr, ip6_plen));
|
||||
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
V_ip6stat.ip6s_fragments++;
|
||||
in6_ifstat_inc(dstifp, ifs6_reass_reqd);
|
||||
|
||||
/* offset now points to data portion */
|
||||
offset += sizeof(struct ip6_frag);
|
||||
|
||||
IP6Q_LOCK();
|
||||
|
||||
/*
|
||||
* Enforce upper bound on number of fragments.
|
||||
* If maxfrag is 0, never accept fragments.
|
||||
* If maxfrag is -1, accept all fragments without limitation.
|
||||
*/
|
||||
if (V_ip6_maxfrags < 0)
|
||||
;
|
||||
else if (V_frag6_nfrags >= (u_int)V_ip6_maxfrags)
|
||||
goto dropfrag;
|
||||
|
||||
for (q6 = V_ip6q.ip6q_next; q6 != &V_ip6q; q6 = q6->ip6q_next)
|
||||
if (ip6f->ip6f_ident == q6->ip6q_ident &&
|
||||
IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) &&
|
||||
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst)
|
||||
#ifdef MAC
|
||||
&& mac_ip6q_match(m, q6)
|
||||
#endif
|
||||
)
|
||||
break;
|
||||
|
||||
if (q6 == &V_ip6q) {
|
||||
/*
|
||||
* the first fragment to arrive, create a reassembly queue.
|
||||
*/
|
||||
first_frag = 1;
|
||||
|
||||
/*
|
||||
* Enforce upper bound on number of fragmented packets
|
||||
* for which we attempt reassembly;
|
||||
* If maxfragpackets is 0, never accept fragments.
|
||||
* If maxfragpackets is -1, accept all fragments without
|
||||
* limitation.
|
||||
*/
|
||||
if (V_ip6_maxfragpackets < 0)
|
||||
;
|
||||
else if (V_frag6_nfragpackets >= (u_int)V_ip6_maxfragpackets)
|
||||
goto dropfrag;
|
||||
V_frag6_nfragpackets++;
|
||||
q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE,
|
||||
M_NOWAIT);
|
||||
if (q6 == NULL)
|
||||
goto dropfrag;
|
||||
bzero(q6, sizeof(*q6));
|
||||
#ifdef MAC
|
||||
if (mac_ip6q_init(q6, M_NOWAIT) != 0) {
|
||||
free(q6, M_FTABLE);
|
||||
goto dropfrag;
|
||||
}
|
||||
mac_ip6q_create(m, q6);
|
||||
#endif
|
||||
frag6_insque(q6, &V_ip6q);
|
||||
|
||||
/* ip6q_nxt will be filled afterwards, from 1st fragment */
|
||||
q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6;
|
||||
#ifdef notyet
|
||||
q6->ip6q_nxtp = (u_char *)nxtp;
|
||||
#endif
|
||||
q6->ip6q_ident = ip6f->ip6f_ident;
|
||||
q6->ip6q_ttl = IPV6_FRAGTTL;
|
||||
q6->ip6q_src = ip6->ip6_src;
|
||||
q6->ip6q_dst = ip6->ip6_dst;
|
||||
q6->ip6q_ecn =
|
||||
(ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK;
|
||||
q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */
|
||||
|
||||
q6->ip6q_nfrag = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's the 1st fragment, record the length of the
|
||||
* unfragmentable part and the next header of the fragment header.
|
||||
*/
|
||||
fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
|
||||
if (fragoff == 0) {
|
||||
q6->ip6q_unfrglen = offset - sizeof(struct ip6_hdr) -
|
||||
sizeof(struct ip6_frag);
|
||||
q6->ip6q_nxt = ip6f->ip6f_nxt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the reassembled packet would not exceed 65535 bytes
|
||||
* in size.
|
||||
* If it would exceed, discard the fragment and return an ICMP error.
|
||||
*/
|
||||
frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset;
|
||||
if (q6->ip6q_unfrglen >= 0) {
|
||||
/* The 1st fragment has already arrived. */
|
||||
if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
|
||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||
offset - sizeof(struct ip6_frag) +
|
||||
offsetof(struct ip6_frag, ip6f_offlg));
|
||||
IP6Q_UNLOCK();
|
||||
return (IPPROTO_DONE);
|
||||
}
|
||||
} else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
|
||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||
offset - sizeof(struct ip6_frag) +
|
||||
offsetof(struct ip6_frag, ip6f_offlg));
|
||||
IP6Q_UNLOCK();
|
||||
return (IPPROTO_DONE);
|
||||
}
|
||||
/*
|
||||
* If it's the first fragment, do the above check for each
|
||||
* fragment already stored in the reassembly queue.
|
||||
*/
|
||||
if (fragoff == 0) {
|
||||
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
|
||||
af6 = af6dwn) {
|
||||
af6dwn = af6->ip6af_down;
|
||||
|
||||
if (q6->ip6q_unfrglen + af6->ip6af_off + af6->ip6af_frglen >
|
||||
IPV6_MAXPACKET) {
|
||||
struct mbuf *merr = IP6_REASS_MBUF(af6);
|
||||
struct ip6_hdr *ip6err;
|
||||
int erroff = af6->ip6af_offset;
|
||||
|
||||
/* dequeue the fragment. */
|
||||
frag6_deq(af6);
|
||||
free(af6, M_FTABLE);
|
||||
|
||||
/* adjust pointer. */
|
||||
ip6err = mtod(merr, struct ip6_hdr *);
|
||||
|
||||
/*
|
||||
* Restore source and destination addresses
|
||||
* in the erroneous IPv6 header.
|
||||
*/
|
||||
ip6err->ip6_src = q6->ip6q_src;
|
||||
ip6err->ip6_dst = q6->ip6q_dst;
|
||||
|
||||
icmp6_error(merr, ICMP6_PARAM_PROB,
|
||||
ICMP6_PARAMPROB_HEADER,
|
||||
erroff - sizeof(struct ip6_frag) +
|
||||
offsetof(struct ip6_frag, ip6f_offlg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip6af = (struct ip6asfrag *)malloc(sizeof(struct ip6asfrag), M_FTABLE,
|
||||
M_NOWAIT);
|
||||
if (ip6af == NULL)
|
||||
goto dropfrag;
|
||||
bzero(ip6af, sizeof(*ip6af));
|
||||
ip6af->ip6af_mff = ip6f->ip6f_offlg & IP6F_MORE_FRAG;
|
||||
ip6af->ip6af_off = fragoff;
|
||||
ip6af->ip6af_frglen = frgpartlen;
|
||||
ip6af->ip6af_offset = offset;
|
||||
IP6_REASS_MBUF(ip6af) = m;
|
||||
|
||||
if (first_frag) {
|
||||
af6 = (struct ip6asfrag *)q6;
|
||||
goto insert;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle ECN by comparing this segment with the first one;
|
||||
* if CE is set, do not lose CE.
|
||||
* drop if CE and not-ECT are mixed for the same packet.
|
||||
*/
|
||||
ecn = (ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK;
|
||||
ecn0 = q6->ip6q_ecn;
|
||||
if (ecn == IPTOS_ECN_CE) {
|
||||
if (ecn0 == IPTOS_ECN_NOTECT) {
|
||||
free(ip6af, M_FTABLE);
|
||||
goto dropfrag;
|
||||
}
|
||||
if (ecn0 != IPTOS_ECN_CE)
|
||||
q6->ip6q_ecn = IPTOS_ECN_CE;
|
||||
}
|
||||
if (ecn == IPTOS_ECN_NOTECT && ecn0 != IPTOS_ECN_NOTECT) {
|
||||
free(ip6af, M_FTABLE);
|
||||
goto dropfrag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a segment which begins after this one does.
|
||||
*/
|
||||
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
|
||||
af6 = af6->ip6af_down)
|
||||
if (af6->ip6af_off > ip6af->ip6af_off)
|
||||
break;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* If there is a preceding segment, it may provide some of
|
||||
* our data already. If so, drop the data from the incoming
|
||||
* segment. If it provides all of our data, drop us.
|
||||
*/
|
||||
if (af6->ip6af_up != (struct ip6asfrag *)q6) {
|
||||
i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
|
||||
- ip6af->ip6af_off;
|
||||
if (i > 0) {
|
||||
if (i >= ip6af->ip6af_frglen)
|
||||
goto dropfrag;
|
||||
m_adj(IP6_REASS_MBUF(ip6af), i);
|
||||
ip6af->ip6af_off += i;
|
||||
ip6af->ip6af_frglen -= i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* While we overlap succeeding segments trim them or,
|
||||
* if they are completely covered, dequeue them.
|
||||
*/
|
||||
while (af6 != (struct ip6asfrag *)q6 &&
|
||||
ip6af->ip6af_off + ip6af->ip6af_frglen > af6->ip6af_off) {
|
||||
i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
|
||||
if (i < af6->ip6af_frglen) {
|
||||
af6->ip6af_frglen -= i;
|
||||
af6->ip6af_off += i;
|
||||
m_adj(IP6_REASS_MBUF(af6), i);
|
||||
break;
|
||||
}
|
||||
af6 = af6->ip6af_down;
|
||||
m_freem(IP6_REASS_MBUF(af6->ip6af_up));
|
||||
frag6_deq(af6->ip6af_up);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* If the incoming framgent overlaps some existing fragments in
|
||||
* the reassembly queue, drop it, since it is dangerous to override
|
||||
* existing fragments from a security point of view.
|
||||
* We don't know which fragment is the bad guy - here we trust
|
||||
* fragment that came in earlier, with no real reason.
|
||||
*
|
||||
* Note: due to changes after disabling this part, mbuf passed to
|
||||
* m_adj() below now does not meet the requirement.
|
||||
*/
|
||||
if (af6->ip6af_up != (struct ip6asfrag *)q6) {
|
||||
i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
|
||||
- ip6af->ip6af_off;
|
||||
if (i > 0) {
|
||||
#if 0 /* suppress the noisy log */
|
||||
log(LOG_ERR, "%d bytes of a fragment from %s "
|
||||
"overlaps the previous fragment\n",
|
||||
i, ip6_sprintf(ip6buf, &q6->ip6q_src));
|
||||
#endif
|
||||
free(ip6af, M_FTABLE);
|
||||
goto dropfrag;
|
||||
}
|
||||
}
|
||||
if (af6 != (struct ip6asfrag *)q6) {
|
||||
i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
|
||||
if (i > 0) {
|
||||
#if 0 /* suppress the noisy log */
|
||||
log(LOG_ERR, "%d bytes of a fragment from %s "
|
||||
"overlaps the succeeding fragment",
|
||||
i, ip6_sprintf(ip6buf, &q6->ip6q_src));
|
||||
#endif
|
||||
free(ip6af, M_FTABLE);
|
||||
goto dropfrag;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
insert:
|
||||
#ifdef MAC
|
||||
if (!first_frag)
|
||||
mac_ip6q_update(m, q6);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Stick new segment in its place;
|
||||
* check for complete reassembly.
|
||||
* Move to front of packet queue, as we are
|
||||
* the most recently active fragmented packet.
|
||||
*/
|
||||
frag6_enq(ip6af, af6->ip6af_up);
|
||||
V_frag6_nfrags++;
|
||||
q6->ip6q_nfrag++;
|
||||
#if 0 /* xxx */
|
||||
if (q6 != V_ip6q.ip6q_next) {
|
||||
frag6_remque(q6);
|
||||
frag6_insque(q6, &V_ip6q);
|
||||
}
|
||||
#endif
|
||||
next = 0;
|
||||
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
|
||||
af6 = af6->ip6af_down) {
|
||||
if (af6->ip6af_off != next) {
|
||||
IP6Q_UNLOCK();
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
next += af6->ip6af_frglen;
|
||||
}
|
||||
if (af6->ip6af_up->ip6af_mff) {
|
||||
IP6Q_UNLOCK();
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reassembly is complete; concatenate fragments.
|
||||
*/
|
||||
ip6af = q6->ip6q_down;
|
||||
t = m = IP6_REASS_MBUF(ip6af);
|
||||
af6 = ip6af->ip6af_down;
|
||||
frag6_deq(ip6af);
|
||||
while (af6 != (struct ip6asfrag *)q6) {
|
||||
af6dwn = af6->ip6af_down;
|
||||
frag6_deq(af6);
|
||||
while (t->m_next)
|
||||
t = t->m_next;
|
||||
t->m_next = IP6_REASS_MBUF(af6);
|
||||
m_adj(t->m_next, af6->ip6af_offset);
|
||||
free(af6, M_FTABLE);
|
||||
af6 = af6dwn;
|
||||
}
|
||||
|
||||
/* adjust offset to point where the original next header starts */
|
||||
offset = ip6af->ip6af_offset - sizeof(struct ip6_frag);
|
||||
free(ip6af, M_FTABLE);
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ip6->ip6_plen = htons((u_short)next + offset - sizeof(struct ip6_hdr));
|
||||
if (q6->ip6q_ecn == IPTOS_ECN_CE)
|
||||
ip6->ip6_flow |= htonl(IPTOS_ECN_CE << 20);
|
||||
nxt = q6->ip6q_nxt;
|
||||
#ifdef notyet
|
||||
*q6->ip6q_nxtp = (u_char)(nxt & 0xff);
|
||||
#endif
|
||||
|
||||
/* Delete frag6 header */
|
||||
if (m->m_len >= offset + sizeof(struct ip6_frag)) {
|
||||
/* This is the only possible case with !PULLDOWN_TEST */
|
||||
ovbcopy((caddr_t)ip6, (caddr_t)ip6 + sizeof(struct ip6_frag),
|
||||
offset);
|
||||
m->m_data += sizeof(struct ip6_frag);
|
||||
m->m_len -= sizeof(struct ip6_frag);
|
||||
} else {
|
||||
/* this comes with no copy if the boundary is on cluster */
|
||||
if ((t = m_split(m, offset, M_DONTWAIT)) == NULL) {
|
||||
frag6_remque(q6);
|
||||
V_frag6_nfrags -= q6->ip6q_nfrag;
|
||||
#ifdef MAC
|
||||
mac_ip6q_destroy(q6);
|
||||
#endif
|
||||
free(q6, M_FTABLE);
|
||||
V_frag6_nfragpackets--;
|
||||
goto dropfrag;
|
||||
}
|
||||
m_adj(t, sizeof(struct ip6_frag));
|
||||
m_cat(m, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store NXT to the original.
|
||||
*/
|
||||
{
|
||||
char *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */
|
||||
*prvnxtp = nxt;
|
||||
}
|
||||
|
||||
frag6_remque(q6);
|
||||
V_frag6_nfrags -= q6->ip6q_nfrag;
|
||||
#ifdef MAC
|
||||
mac_ip6q_reassemble(q6, m);
|
||||
mac_ip6q_destroy(q6);
|
||||
#endif
|
||||
free(q6, M_FTABLE);
|
||||
V_frag6_nfragpackets--;
|
||||
|
||||
if (m->m_flags & M_PKTHDR) { /* Isn't it always true? */
|
||||
int plen = 0;
|
||||
for (t = m; t; t = t->m_next)
|
||||
plen += t->m_len;
|
||||
m->m_pkthdr.len = plen;
|
||||
}
|
||||
|
||||
V_ip6stat.ip6s_reassembled++;
|
||||
in6_ifstat_inc(dstifp, ifs6_reass_ok);
|
||||
|
||||
/*
|
||||
* Tell launch routine the next header
|
||||
*/
|
||||
|
||||
*mp = m;
|
||||
*offp = offset;
|
||||
|
||||
IP6Q_UNLOCK();
|
||||
return nxt;
|
||||
|
||||
dropfrag:
|
||||
IP6Q_UNLOCK();
|
||||
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
||||
V_ip6stat.ip6s_fragdropped++;
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a fragment reassembly header and all
|
||||
* associated datagrams.
|
||||
*/
|
||||
void
|
||||
frag6_freef(struct ip6q *q6)
|
||||
{
|
||||
struct ip6asfrag *af6, *down6;
|
||||
|
||||
IP6Q_LOCK_ASSERT();
|
||||
|
||||
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
|
||||
af6 = down6) {
|
||||
struct mbuf *m = IP6_REASS_MBUF(af6);
|
||||
|
||||
down6 = af6->ip6af_down;
|
||||
frag6_deq(af6);
|
||||
|
||||
/*
|
||||
* Return ICMP time exceeded error for the 1st fragment.
|
||||
* Just free other fragments.
|
||||
*/
|
||||
if (af6->ip6af_off == 0) {
|
||||
struct ip6_hdr *ip6;
|
||||
|
||||
/* adjust pointer */
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
||||
/* restore source and destination addresses */
|
||||
ip6->ip6_src = q6->ip6q_src;
|
||||
ip6->ip6_dst = q6->ip6q_dst;
|
||||
|
||||
icmp6_error(m, ICMP6_TIME_EXCEEDED,
|
||||
ICMP6_TIME_EXCEED_REASSEMBLY, 0);
|
||||
} else
|
||||
m_freem(m);
|
||||
free(af6, M_FTABLE);
|
||||
}
|
||||
frag6_remque(q6);
|
||||
V_frag6_nfrags -= q6->ip6q_nfrag;
|
||||
#ifdef MAC
|
||||
mac_ip6q_destroy(q6);
|
||||
#endif
|
||||
free(q6, M_FTABLE);
|
||||
V_frag6_nfragpackets--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put an ip fragment on a reassembly chain.
|
||||
* Like insque, but pointers in middle of structure.
|
||||
*/
|
||||
void
|
||||
frag6_enq(struct ip6asfrag *af6, struct ip6asfrag *up6)
|
||||
{
|
||||
|
||||
IP6Q_LOCK_ASSERT();
|
||||
|
||||
af6->ip6af_up = up6;
|
||||
af6->ip6af_down = up6->ip6af_down;
|
||||
up6->ip6af_down->ip6af_up = af6;
|
||||
up6->ip6af_down = af6;
|
||||
}
|
||||
|
||||
/*
|
||||
* To frag6_enq as remque is to insque.
|
||||
*/
|
||||
void
|
||||
frag6_deq(struct ip6asfrag *af6)
|
||||
{
|
||||
|
||||
IP6Q_LOCK_ASSERT();
|
||||
|
||||
af6->ip6af_up->ip6af_down = af6->ip6af_down;
|
||||
af6->ip6af_down->ip6af_up = af6->ip6af_up;
|
||||
}
|
||||
|
||||
void
|
||||
frag6_insque(struct ip6q *new, struct ip6q *old)
|
||||
{
|
||||
|
||||
IP6Q_LOCK_ASSERT();
|
||||
|
||||
new->ip6q_prev = old;
|
||||
new->ip6q_next = old->ip6q_next;
|
||||
old->ip6q_next->ip6q_prev= new;
|
||||
old->ip6q_next = new;
|
||||
}
|
||||
|
||||
void
|
||||
frag6_remque(struct ip6q *p6)
|
||||
{
|
||||
|
||||
IP6Q_LOCK_ASSERT();
|
||||
|
||||
p6->ip6q_prev->ip6q_next = p6->ip6q_next;
|
||||
p6->ip6q_next->ip6q_prev = p6->ip6q_prev;
|
||||
}
|
||||
|
||||
/*
|
||||
* IPv6 reassembling timer processing;
|
||||
* if a timer expires on a reassembly
|
||||
* queue, discard it.
|
||||
*/
|
||||
void
|
||||
frag6_slowtimo(void)
|
||||
{
|
||||
VNET_ITERATOR_DECL(vnet_iter);
|
||||
struct ip6q *q6;
|
||||
|
||||
VNET_LIST_RLOCK_NOSLEEP();
|
||||
IP6Q_LOCK();
|
||||
VNET_FOREACH(vnet_iter) {
|
||||
CURVNET_SET(vnet_iter);
|
||||
q6 = V_ip6q.ip6q_next;
|
||||
if (q6)
|
||||
while (q6 != &V_ip6q) {
|
||||
--q6->ip6q_ttl;
|
||||
q6 = q6->ip6q_next;
|
||||
if (q6->ip6q_prev->ip6q_ttl == 0) {
|
||||
V_ip6stat.ip6s_fragtimeout++;
|
||||
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
|
||||
frag6_freef(q6->ip6q_prev);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we are over the maximum number of fragments
|
||||
* (due to the limit being lowered), drain off
|
||||
* enough to get down to the new limit.
|
||||
*/
|
||||
while (V_frag6_nfragpackets > (u_int)V_ip6_maxfragpackets &&
|
||||
V_ip6q.ip6q_prev) {
|
||||
V_ip6stat.ip6s_fragoverflow++;
|
||||
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
|
||||
frag6_freef(V_ip6q.ip6q_prev);
|
||||
}
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
IP6Q_UNLOCK();
|
||||
VNET_LIST_RUNLOCK_NOSLEEP();
|
||||
}
|
||||
|
||||
/*
|
||||
* Drain off all datagram fragments.
|
||||
*/
|
||||
void
|
||||
frag6_drain(void)
|
||||
{
|
||||
VNET_ITERATOR_DECL(vnet_iter);
|
||||
|
||||
VNET_LIST_RLOCK_NOSLEEP();
|
||||
if (IP6Q_TRYLOCK() == 0) {
|
||||
VNET_LIST_RUNLOCK_NOSLEEP();
|
||||
return;
|
||||
}
|
||||
VNET_FOREACH(vnet_iter) {
|
||||
CURVNET_SET(vnet_iter);
|
||||
while (V_ip6q.ip6q_next != &V_ip6q) {
|
||||
V_ip6stat.ip6s_fragdropped++;
|
||||
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
|
||||
frag6_freef(V_ip6q.ip6q_next);
|
||||
}
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
IP6Q_UNLOCK();
|
||||
VNET_LIST_RUNLOCK_NOSLEEP();
|
||||
}
|
2857
freebsd/netinet6/icmp6.c
Normal file
2857
freebsd/netinet6/icmp6.c
Normal file
File diff suppressed because it is too large
Load Diff
4
freebsd/netinet6/icmp6.h
Normal file
4
freebsd/netinet6/icmp6.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $KAME: icmp6.h,v 1.17 2000/06/11 17:23:40 jinmei Exp $ */
|
||||
|
||||
#error "netinet6/icmp6.h is obsolete. use netinet/icmp6.h"
|
2671
freebsd/netinet6/in6.c
Normal file
2671
freebsd/netinet6/in6.c
Normal file
File diff suppressed because it is too large
Load Diff
708
freebsd/netinet6/in6.h
Normal file
708
freebsd/netinet6/in6.h
Normal file
@@ -0,0 +1,708 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6.h,v 1.89 2001/05/27 13:28:35 itojun Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)in.h 8.3 (Berkeley) 1/3/94
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __KAME_NETINET_IN_HH_INCLUDED_
|
||||
#error "do not include netinet6/in6.h directly, include netinet/in.h. see RFC2553"
|
||||
#endif
|
||||
|
||||
#ifndef _NETINET6_IN6_HH_
|
||||
#define _NETINET6_IN6_HH_
|
||||
|
||||
/*
|
||||
* Identification of the network protocol stack
|
||||
* for *BSD-current/release: http://www.kame.net/dev/cvsweb.cgi/kame/COVERAGE
|
||||
* has the table of implementation/integration differences.
|
||||
*/
|
||||
#define __KAME__
|
||||
#define __KAME_VERSION "FreeBSD"
|
||||
|
||||
/*
|
||||
* IPv6 port allocation rules should mirror the IPv4 rules and are controlled
|
||||
* by the the net.inet.ip.portrange sysctl tree. The following defines exist
|
||||
* for compatibility with userland applications that need them.
|
||||
*/
|
||||
#if __BSD_VISIBLE
|
||||
#define IPV6PORT_RESERVED 1024
|
||||
#define IPV6PORT_ANONMIN 49152
|
||||
#define IPV6PORT_ANONMAX 65535
|
||||
#define IPV6PORT_RESERVEDMIN 600
|
||||
#define IPV6PORT_RESERVEDMAX (IPV6PORT_RESERVED-1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IPv6 address
|
||||
*/
|
||||
struct in6_addr {
|
||||
union {
|
||||
uint8_t __u6_addr8[16];
|
||||
uint16_t __u6_addr16[8];
|
||||
uint32_t __u6_addr32[4];
|
||||
} __u6_addr; /* 128-bit IP6 address */
|
||||
};
|
||||
|
||||
#define s6_addr __u6_addr.__u6_addr8
|
||||
#ifdef _KERNEL /* XXX nonstandard */
|
||||
#define s6_addr8 __u6_addr.__u6_addr8
|
||||
#define s6_addr16 __u6_addr.__u6_addr16
|
||||
#define s6_addr32 __u6_addr.__u6_addr32
|
||||
#endif
|
||||
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
|
||||
/*
|
||||
* XXX missing POSIX.1-2001 macro IPPROTO_IPV6.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Socket address for IPv6
|
||||
*/
|
||||
#if __BSD_VISIBLE
|
||||
#define SIN6_LEN
|
||||
#endif
|
||||
|
||||
struct sockaddr_in6 {
|
||||
uint8_t sin6_len; /* length of this struct */
|
||||
sa_family_t sin6_family; /* AF_INET6 */
|
||||
in_port_t sin6_port; /* Transport layer port # */
|
||||
uint32_t sin6_flowinfo; /* IP6 flow information */
|
||||
struct in6_addr sin6_addr; /* IP6 address */
|
||||
uint32_t sin6_scope_id; /* scope zone index */
|
||||
};
|
||||
|
||||
/*
|
||||
* Local definition for masks
|
||||
*/
|
||||
#ifdef _KERNEL /* XXX nonstandard */
|
||||
#define IN6MASK0 {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}}
|
||||
#define IN6MASK32 {{{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
|
||||
#define IN6MASK64 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
|
||||
#define IN6MASK96 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}
|
||||
#define IN6MASK128 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern const struct sockaddr_in6 sa6_any;
|
||||
|
||||
extern const struct in6_addr in6mask0;
|
||||
extern const struct in6_addr in6mask32;
|
||||
extern const struct in6_addr in6mask64;
|
||||
extern const struct in6_addr in6mask96;
|
||||
extern const struct in6_addr in6mask128;
|
||||
#endif /* _KERNEL */
|
||||
|
||||
/*
|
||||
* Macros started with IPV6_ADDR is KAME local
|
||||
*/
|
||||
#ifdef _KERNEL /* XXX nonstandard */
|
||||
#if _BYTE_ORDER == _BIG_ENDIAN
|
||||
#define IPV6_ADDR_INT32_ONE 1
|
||||
#define IPV6_ADDR_INT32_TWO 2
|
||||
#define IPV6_ADDR_INT32_MNL 0xff010000
|
||||
#define IPV6_ADDR_INT32_MLL 0xff020000
|
||||
#define IPV6_ADDR_INT32_SMP 0x0000ffff
|
||||
#define IPV6_ADDR_INT16_ULL 0xfe80
|
||||
#define IPV6_ADDR_INT16_USL 0xfec0
|
||||
#define IPV6_ADDR_INT16_MLL 0xff02
|
||||
#elif _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
#define IPV6_ADDR_INT32_ONE 0x01000000
|
||||
#define IPV6_ADDR_INT32_TWO 0x02000000
|
||||
#define IPV6_ADDR_INT32_MNL 0x000001ff
|
||||
#define IPV6_ADDR_INT32_MLL 0x000002ff
|
||||
#define IPV6_ADDR_INT32_SMP 0xffff0000
|
||||
#define IPV6_ADDR_INT16_ULL 0x80fe
|
||||
#define IPV6_ADDR_INT16_USL 0xc0fe
|
||||
#define IPV6_ADDR_INT16_MLL 0x02ff
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Definition of some useful macros to handle IP6 addresses
|
||||
*/
|
||||
#if __BSD_VISIBLE
|
||||
#define IN6ADDR_ANY_INIT \
|
||||
{{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
|
||||
#define IN6ADDR_LOOPBACK_INIT \
|
||||
{{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
|
||||
#define IN6ADDR_NODELOCAL_ALLNODES_INIT \
|
||||
{{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
|
||||
#define IN6ADDR_INTFACELOCAL_ALLNODES_INIT \
|
||||
{{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
|
||||
#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \
|
||||
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
|
||||
#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
|
||||
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
|
||||
#define IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT \
|
||||
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16 }}}
|
||||
#endif
|
||||
|
||||
extern const struct in6_addr in6addr_any;
|
||||
extern const struct in6_addr in6addr_loopback;
|
||||
#if __BSD_VISIBLE
|
||||
extern const struct in6_addr in6addr_nodelocal_allnodes;
|
||||
extern const struct in6_addr in6addr_linklocal_allnodes;
|
||||
extern const struct in6_addr in6addr_linklocal_allrouters;
|
||||
extern const struct in6_addr in6addr_linklocal_allv2routers;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Equality
|
||||
* NOTE: Some of kernel programming environment (for example, openbsd/sparc)
|
||||
* does not supply memcmp(). For userland memcmp() is preferred as it is
|
||||
* in ANSI standard.
|
||||
*/
|
||||
#ifdef _KERNEL
|
||||
#define IN6_ARE_ADDR_EQUAL(a, b) \
|
||||
(bcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
|
||||
#else
|
||||
#if __BSD_VISIBLE
|
||||
#define IN6_ARE_ADDR_EQUAL(a, b) \
|
||||
(memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unspecified
|
||||
*/
|
||||
#define IN6_IS_ADDR_UNSPECIFIED(a) \
|
||||
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) == 0))
|
||||
|
||||
/*
|
||||
* Loopback
|
||||
*/
|
||||
#define IN6_IS_ADDR_LOOPBACK(a) \
|
||||
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) == ntohl(1)))
|
||||
|
||||
/*
|
||||
* IPv4 compatible
|
||||
*/
|
||||
#define IN6_IS_ADDR_V4COMPAT(a) \
|
||||
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) != 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) != ntohl(1)))
|
||||
|
||||
/*
|
||||
* Mapped
|
||||
*/
|
||||
#define IN6_IS_ADDR_V4MAPPED(a) \
|
||||
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
|
||||
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff)))
|
||||
|
||||
/*
|
||||
* KAME Scope Values
|
||||
*/
|
||||
|
||||
#ifdef _KERNEL /* XXX nonstandard */
|
||||
#define IPV6_ADDR_SCOPE_NODELOCAL 0x01
|
||||
#define IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
|
||||
#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02
|
||||
#define IPV6_ADDR_SCOPE_SITELOCAL 0x05
|
||||
#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
|
||||
#define IPV6_ADDR_SCOPE_GLOBAL 0x0e
|
||||
#else
|
||||
#define __IPV6_ADDR_SCOPE_NODELOCAL 0x01
|
||||
#define __IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
|
||||
#define __IPV6_ADDR_SCOPE_LINKLOCAL 0x02
|
||||
#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05
|
||||
#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
|
||||
#define __IPV6_ADDR_SCOPE_GLOBAL 0x0e
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unicast Scope
|
||||
* Note that we must check topmost 10 bits only, not 16 bits (see RFC2373).
|
||||
*/
|
||||
#define IN6_IS_ADDR_LINKLOCAL(a) \
|
||||
(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
|
||||
#define IN6_IS_ADDR_SITELOCAL(a) \
|
||||
(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
|
||||
|
||||
/*
|
||||
* Multicast
|
||||
*/
|
||||
#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
|
||||
|
||||
#ifdef _KERNEL /* XXX nonstandard */
|
||||
#define IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
|
||||
#else
|
||||
#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Multicast Scope
|
||||
*/
|
||||
#ifdef _KERNEL /* refers nonstandard items */
|
||||
#define IN6_IS_ADDR_MC_NODELOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL))
|
||||
#define IN6_IS_ADDR_MC_INTFACELOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_INTFACELOCAL))
|
||||
#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL))
|
||||
#define IN6_IS_ADDR_MC_SITELOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_SITELOCAL))
|
||||
#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_ORGLOCAL))
|
||||
#define IN6_IS_ADDR_MC_GLOBAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL))
|
||||
#else
|
||||
#define IN6_IS_ADDR_MC_NODELOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL))
|
||||
#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL))
|
||||
#define IN6_IS_ADDR_MC_SITELOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL))
|
||||
#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL))
|
||||
#define IN6_IS_ADDR_MC_GLOBAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL))
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL /* nonstandard */
|
||||
/*
|
||||
* KAME Scope
|
||||
*/
|
||||
#define IN6_IS_SCOPE_LINKLOCAL(a) \
|
||||
((IN6_IS_ADDR_LINKLOCAL(a)) || \
|
||||
(IN6_IS_ADDR_MC_LINKLOCAL(a)))
|
||||
#define IN6_IS_SCOPE_EMBED(a) \
|
||||
((IN6_IS_ADDR_LINKLOCAL(a)) || \
|
||||
(IN6_IS_ADDR_MC_LINKLOCAL(a)) || \
|
||||
(IN6_IS_ADDR_MC_INTFACELOCAL(a)))
|
||||
|
||||
#define IFA6_IS_DEPRECATED(a) \
|
||||
((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
|
||||
(u_int32_t)((time_second - (a)->ia6_updatetime)) > \
|
||||
(a)->ia6_lifetime.ia6t_pltime)
|
||||
#define IFA6_IS_INVALID(a) \
|
||||
((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \
|
||||
(u_int32_t)((time_second - (a)->ia6_updatetime)) > \
|
||||
(a)->ia6_lifetime.ia6t_vltime)
|
||||
#endif /* _KERNEL */
|
||||
|
||||
/*
|
||||
* IP6 route structure
|
||||
*/
|
||||
#if __BSD_VISIBLE
|
||||
struct route_in6 {
|
||||
struct rtentry *ro_rt;
|
||||
struct llentry *ro_lle;
|
||||
struct sockaddr_in6 ro_dst;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Options for use with [gs]etsockopt at the IPV6 level.
|
||||
* First word of comment is data type; bool is stored in int.
|
||||
*/
|
||||
/* no hdrincl */
|
||||
#if 0 /* the followings are relic in IPv4 and hence are disabled */
|
||||
#define IPV6_OPTIONS 1 /* buf/ip6_opts; set/get IP6 options */
|
||||
#define IPV6_RECVOPTS 5 /* bool; receive all IP6 opts w/dgram */
|
||||
#define IPV6_RECVRETOPTS 6 /* bool; receive IP6 opts for response */
|
||||
#define IPV6_RECVDSTADDR 7 /* bool; receive IP6 dst addr w/dgram */
|
||||
#define IPV6_RETOPTS 8 /* ip6_opts; set/get IP6 options */
|
||||
#endif
|
||||
#define IPV6_SOCKOPT_RESERVED1 3 /* reserved for future use */
|
||||
#define IPV6_UNICAST_HOPS 4 /* int; IP6 hops */
|
||||
#define IPV6_MULTICAST_IF 9 /* u_int; set/get IP6 multicast i/f */
|
||||
#define IPV6_MULTICAST_HOPS 10 /* int; set/get IP6 multicast hops */
|
||||
#define IPV6_MULTICAST_LOOP 11 /* u_int; set/get IP6 multicast loopback */
|
||||
#define IPV6_JOIN_GROUP 12 /* ip6_mreq; join a group membership */
|
||||
#define IPV6_LEAVE_GROUP 13 /* ip6_mreq; leave a group membership */
|
||||
#define IPV6_PORTRANGE 14 /* int; range to choose for unspec port */
|
||||
#define ICMP6_FILTER 18 /* icmp6_filter; icmp6 filter */
|
||||
/* RFC2292 options */
|
||||
#ifdef _KERNEL
|
||||
#define IPV6_2292PKTINFO 19 /* bool; send/recv if, src/dst addr */
|
||||
#define IPV6_2292HOPLIMIT 20 /* bool; hop limit */
|
||||
#define IPV6_2292NEXTHOP 21 /* bool; next hop addr */
|
||||
#define IPV6_2292HOPOPTS 22 /* bool; hop-by-hop option */
|
||||
#define IPV6_2292DSTOPTS 23 /* bool; destinaion option */
|
||||
#define IPV6_2292RTHDR 24 /* bool; routing header */
|
||||
#define IPV6_2292PKTOPTIONS 25 /* buf/cmsghdr; set/get IPv6 options */
|
||||
#endif
|
||||
|
||||
#define IPV6_CHECKSUM 26 /* int; checksum offset for raw socket */
|
||||
#define IPV6_V6ONLY 27 /* bool; make AF_INET6 sockets v6 only */
|
||||
#ifndef _KERNEL
|
||||
#define IPV6_BINDV6ONLY IPV6_V6ONLY
|
||||
#endif
|
||||
|
||||
#if 1 /* IPSEC */
|
||||
#define IPV6_IPSEC_POLICY 28 /* struct; get/set security policy */
|
||||
#endif /* IPSEC */
|
||||
|
||||
#define IPV6_FAITH 29 /* bool; accept FAITH'ed connections */
|
||||
|
||||
#if 1 /* IPV6FIREWALL */
|
||||
#define IPV6_FW_ADD 30 /* add a firewall rule to chain */
|
||||
#define IPV6_FW_DEL 31 /* delete a firewall rule from chain */
|
||||
#define IPV6_FW_FLUSH 32 /* flush firewall rule chain */
|
||||
#define IPV6_FW_ZERO 33 /* clear single/all firewall counter(s) */
|
||||
#define IPV6_FW_GET 34 /* get entire firewall rule chain */
|
||||
#endif
|
||||
|
||||
/* new socket options introduced in RFC3542 */
|
||||
#define IPV6_RTHDRDSTOPTS 35 /* ip6_dest; send dst option before rthdr */
|
||||
|
||||
#define IPV6_RECVPKTINFO 36 /* bool; recv if, dst addr */
|
||||
#define IPV6_RECVHOPLIMIT 37 /* bool; recv hop limit */
|
||||
#define IPV6_RECVRTHDR 38 /* bool; recv routing header */
|
||||
#define IPV6_RECVHOPOPTS 39 /* bool; recv hop-by-hop option */
|
||||
#define IPV6_RECVDSTOPTS 40 /* bool; recv dst option after rthdr */
|
||||
#ifdef _KERNEL
|
||||
#define IPV6_RECVRTHDRDSTOPTS 41 /* bool; recv dst option before rthdr */
|
||||
#endif
|
||||
|
||||
#define IPV6_USE_MIN_MTU 42 /* bool; send packets at the minimum MTU */
|
||||
#define IPV6_RECVPATHMTU 43 /* bool; notify an according MTU */
|
||||
|
||||
#define IPV6_PATHMTU 44 /* mtuinfo; get the current path MTU (sopt),
|
||||
4 bytes int; MTU notification (cmsg) */
|
||||
#if 0 /*obsoleted during 2292bis -> 3542*/
|
||||
#define IPV6_REACHCONF 45 /* no data; ND reachability confirm
|
||||
(cmsg only/not in of RFC3542) */
|
||||
#endif
|
||||
|
||||
/* more new socket options introduced in RFC3542 */
|
||||
#define IPV6_PKTINFO 46 /* in6_pktinfo; send if, src addr */
|
||||
#define IPV6_HOPLIMIT 47 /* int; send hop limit */
|
||||
#define IPV6_NEXTHOP 48 /* sockaddr; next hop addr */
|
||||
#define IPV6_HOPOPTS 49 /* ip6_hbh; send hop-by-hop option */
|
||||
#define IPV6_DSTOPTS 50 /* ip6_dest; send dst option befor rthdr */
|
||||
#define IPV6_RTHDR 51 /* ip6_rthdr; send routing header */
|
||||
#if 0
|
||||
#define IPV6_PKTOPTIONS 52 /* buf/cmsghdr; set/get IPv6 options */
|
||||
/* obsoleted by RFC3542 */
|
||||
#endif
|
||||
|
||||
#define IPV6_RECVTCLASS 57 /* bool; recv traffic class values */
|
||||
|
||||
#define IPV6_AUTOFLOWLABEL 59 /* bool; attach flowlabel automagically */
|
||||
|
||||
#define IPV6_TCLASS 61 /* int; send traffic class value */
|
||||
#define IPV6_DONTFRAG 62 /* bool; disable IPv6 fragmentation */
|
||||
|
||||
#define IPV6_PREFER_TEMPADDR 63 /* int; prefer temporary addresses as
|
||||
* the source address.
|
||||
*/
|
||||
|
||||
#define IPV6_BINDANY 64 /* bool: allow bind to any address */
|
||||
|
||||
/*
|
||||
* The following option is private; do not use it from user applications.
|
||||
* It is deliberately defined to the same value as IP_MSFILTER.
|
||||
*/
|
||||
#define IPV6_MSFILTER 74 /* struct __msfilterreq;
|
||||
* set/get multicast source filter list.
|
||||
*/
|
||||
|
||||
/* to define items, should talk with KAME guys first, for *BSD compatibility */
|
||||
|
||||
#define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor. XXX old spec */
|
||||
#define IPV6_RTHDR_STRICT 1 /* this hop must be a neighbor. XXX old spec */
|
||||
#define IPV6_RTHDR_TYPE_0 0 /* IPv6 routing header type 0 */
|
||||
|
||||
/*
|
||||
* Defaults and limits for options
|
||||
*/
|
||||
#define IPV6_DEFAULT_MULTICAST_HOPS 1 /* normally limit m'casts to 1 hop */
|
||||
#define IPV6_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
|
||||
|
||||
/*
|
||||
* The im6o_membership vector for each socket is now dynamically allocated at
|
||||
* run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
|
||||
* according to a power-of-two increment.
|
||||
*/
|
||||
#define IPV6_MIN_MEMBERSHIPS 31
|
||||
#define IPV6_MAX_MEMBERSHIPS 4095
|
||||
|
||||
/*
|
||||
* Default resource limits for IPv6 multicast source filtering.
|
||||
* These may be modified by sysctl.
|
||||
*/
|
||||
#define IPV6_MAX_GROUP_SRC_FILTER 512 /* sources per group */
|
||||
#define IPV6_MAX_SOCK_SRC_FILTER 128 /* sources per socket/group */
|
||||
|
||||
/*
|
||||
* Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP.
|
||||
*/
|
||||
struct ipv6_mreq {
|
||||
struct in6_addr ipv6mr_multiaddr;
|
||||
unsigned int ipv6mr_interface;
|
||||
};
|
||||
|
||||
/*
|
||||
* IPV6_PKTINFO: Packet information(RFC2292 sec 5)
|
||||
*/
|
||||
struct in6_pktinfo {
|
||||
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
|
||||
unsigned int ipi6_ifindex; /* send/recv interface index */
|
||||
};
|
||||
|
||||
/*
|
||||
* Control structure for IPV6_RECVPATHMTU socket option.
|
||||
*/
|
||||
struct ip6_mtuinfo {
|
||||
struct sockaddr_in6 ip6m_addr; /* or sockaddr_storage? */
|
||||
uint32_t ip6m_mtu;
|
||||
};
|
||||
|
||||
/*
|
||||
* Argument for IPV6_PORTRANGE:
|
||||
* - which range to search when port is unspecified at bind() or connect()
|
||||
*/
|
||||
#define IPV6_PORTRANGE_DEFAULT 0 /* default range */
|
||||
#define IPV6_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */
|
||||
#define IPV6_PORTRANGE_LOW 2 /* "low" - vouchsafe security */
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
/*
|
||||
* Definitions for inet6 sysctl operations.
|
||||
*
|
||||
* Third level is protocol number.
|
||||
* Fourth level is desired variable within that protocol.
|
||||
*/
|
||||
#define IPV6PROTO_MAXID (IPPROTO_PIM + 1) /* don't list to IPV6PROTO_MAX */
|
||||
|
||||
/*
|
||||
* Names for IP sysctl objects
|
||||
*/
|
||||
#define IPV6CTL_FORWARDING 1 /* act as router */
|
||||
#define IPV6CTL_SENDREDIRECTS 2 /* may send redirects when forwarding*/
|
||||
#define IPV6CTL_DEFHLIM 3 /* default Hop-Limit */
|
||||
#ifdef notyet
|
||||
#define IPV6CTL_DEFMTU 4 /* default MTU */
|
||||
#endif
|
||||
#define IPV6CTL_FORWSRCRT 5 /* forward source-routed dgrams */
|
||||
#define IPV6CTL_STATS 6 /* stats */
|
||||
#define IPV6CTL_MRTSTATS 7 /* multicast forwarding stats */
|
||||
#define IPV6CTL_MRTPROTO 8 /* multicast routing protocol */
|
||||
#define IPV6CTL_MAXFRAGPACKETS 9 /* max packets reassembly queue */
|
||||
#define IPV6CTL_SOURCECHECK 10 /* verify source route and intf */
|
||||
#define IPV6CTL_SOURCECHECK_LOGINT 11 /* minimume logging interval */
|
||||
#define IPV6CTL_ACCEPT_RTADV 12
|
||||
#define IPV6CTL_KEEPFAITH 13
|
||||
#define IPV6CTL_LOG_INTERVAL 14
|
||||
#define IPV6CTL_HDRNESTLIMIT 15
|
||||
#define IPV6CTL_DAD_COUNT 16
|
||||
#define IPV6CTL_AUTO_FLOWLABEL 17
|
||||
#define IPV6CTL_DEFMCASTHLIM 18
|
||||
#define IPV6CTL_GIF_HLIM 19 /* default HLIM for gif encap packet */
|
||||
#define IPV6CTL_KAME_VERSION 20
|
||||
#define IPV6CTL_USE_DEPRECATED 21 /* use deprecated addr (RFC2462 5.5.4) */
|
||||
#define IPV6CTL_RR_PRUNE 22 /* walk timer for router renumbering */
|
||||
#if 0 /* obsolete */
|
||||
#define IPV6CTL_MAPPED_ADDR 23
|
||||
#endif
|
||||
#define IPV6CTL_V6ONLY 24
|
||||
#define IPV6CTL_RTEXPIRE 25 /* cloned route expiration time */
|
||||
#define IPV6CTL_RTMINEXPIRE 26 /* min value for expiration time */
|
||||
#define IPV6CTL_RTMAXCACHE 27 /* trigger level for dynamic expire */
|
||||
|
||||
#define IPV6CTL_USETEMPADDR 32 /* use temporary addresses (RFC3041) */
|
||||
#define IPV6CTL_TEMPPLTIME 33 /* preferred lifetime for tmpaddrs */
|
||||
#define IPV6CTL_TEMPVLTIME 34 /* valid lifetime for tmpaddrs */
|
||||
#define IPV6CTL_AUTO_LINKLOCAL 35 /* automatic link-local addr assign */
|
||||
#define IPV6CTL_RIP6STATS 36 /* raw_ip6 stats */
|
||||
#define IPV6CTL_PREFER_TEMPADDR 37 /* prefer temporary addr as src */
|
||||
#define IPV6CTL_ADDRCTLPOLICY 38 /* get/set address selection policy */
|
||||
#define IPV6CTL_USE_DEFAULTZONE 39 /* use default scope zone */
|
||||
|
||||
#define IPV6CTL_MAXFRAGS 41 /* max fragments */
|
||||
#if 0
|
||||
#define IPV6CTL_IFQ 42 /* ip6intrq node */
|
||||
#define IPV6CTL_ISATAPRTR 43 /* isatap router */
|
||||
#endif
|
||||
#define IPV6CTL_MCAST_PMTU 44 /* enable pMTU discovery for multicast? */
|
||||
|
||||
/* New entries should be added here from current IPV6CTL_MAXID value. */
|
||||
/* to define items, should talk with KAME guys first, for *BSD compatibility */
|
||||
#define IPV6CTL_STEALTH 45
|
||||
|
||||
#define ICMPV6CTL_ND6_ONLINKNSRFC4861 47
|
||||
#define IPV6CTL_MAXID 48
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
/*
|
||||
* Redefinition of mbuf flags
|
||||
*/
|
||||
#define M_AUTHIPHDR M_PROTO2
|
||||
#define M_DECRYPTED M_PROTO3
|
||||
#define M_LOOP M_PROTO4
|
||||
#define M_AUTHIPDGM M_PROTO5
|
||||
#define M_RTALERT_MLD M_PROTO6
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct cmsghdr;
|
||||
|
||||
int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
|
||||
int in6_localaddr __P((struct in6_addr *));
|
||||
int in6_addrscope __P((struct in6_addr *));
|
||||
struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *));
|
||||
extern void in6_if_up __P((struct ifnet *));
|
||||
struct sockaddr;
|
||||
extern u_char ip6_protox[];
|
||||
|
||||
void in6_sin6_2_sin __P((struct sockaddr_in *sin,
|
||||
struct sockaddr_in6 *sin6));
|
||||
void in6_sin_2_v4mapsin6 __P((struct sockaddr_in *sin,
|
||||
struct sockaddr_in6 *sin6));
|
||||
void in6_sin6_2_sin_in_sock __P((struct sockaddr *nam));
|
||||
void in6_sin_2_v4mapsin6_in_sock __P((struct sockaddr **nam));
|
||||
extern void addrsel_policy_init __P((void));
|
||||
|
||||
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
|
||||
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
|
||||
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
|
||||
|
||||
extern int (*faithprefix_p)(struct in6_addr *);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#ifndef _SIZE_T_DECLARED
|
||||
typedef __size_t size_t;
|
||||
#define _SIZE_T_DECLARED
|
||||
#endif
|
||||
|
||||
#ifndef _SOCKLEN_T_DECLARED
|
||||
typedef __socklen_t socklen_t;
|
||||
#define _SOCKLEN_T_DECLARED
|
||||
#endif
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
|
||||
__BEGIN_DECLS
|
||||
struct cmsghdr;
|
||||
|
||||
extern int inet6_option_space __P((int));
|
||||
extern int inet6_option_init __P((void *, struct cmsghdr **, int));
|
||||
extern int inet6_option_append __P((struct cmsghdr *, const uint8_t *,
|
||||
int, int));
|
||||
extern uint8_t *inet6_option_alloc __P((struct cmsghdr *, int, int, int));
|
||||
extern int inet6_option_next __P((const struct cmsghdr *, uint8_t **));
|
||||
extern int inet6_option_find __P((const struct cmsghdr *, uint8_t **, int));
|
||||
|
||||
extern size_t inet6_rthdr_space __P((int, int));
|
||||
extern struct cmsghdr *inet6_rthdr_init __P((void *, int));
|
||||
extern int inet6_rthdr_add __P((struct cmsghdr *, const struct in6_addr *,
|
||||
unsigned int));
|
||||
extern int inet6_rthdr_lasthop __P((struct cmsghdr *, unsigned int));
|
||||
#if 0 /* not implemented yet */
|
||||
extern int inet6_rthdr_reverse __P((const struct cmsghdr *, struct cmsghdr *));
|
||||
#endif
|
||||
extern int inet6_rthdr_segments __P((const struct cmsghdr *));
|
||||
extern struct in6_addr *inet6_rthdr_getaddr __P((struct cmsghdr *, int));
|
||||
extern int inet6_rthdr_getflags __P((const struct cmsghdr *, int));
|
||||
|
||||
extern int inet6_opt_init __P((void *, socklen_t));
|
||||
extern int inet6_opt_append __P((void *, socklen_t, int, uint8_t, socklen_t,
|
||||
uint8_t, void **));
|
||||
extern int inet6_opt_finish __P((void *, socklen_t, int));
|
||||
extern int inet6_opt_set_val __P((void *, int, void *, socklen_t));
|
||||
|
||||
extern int inet6_opt_next __P((void *, socklen_t, int, uint8_t *, socklen_t *,
|
||||
void **));
|
||||
extern int inet6_opt_find __P((void *, socklen_t, int, uint8_t, socklen_t *,
|
||||
void **));
|
||||
extern int inet6_opt_get_val __P((void *, int, void *, socklen_t));
|
||||
extern socklen_t inet6_rth_space __P((int, int));
|
||||
extern void *inet6_rth_init __P((void *, socklen_t, int, int));
|
||||
extern int inet6_rth_add __P((void *, const struct in6_addr *));
|
||||
extern int inet6_rth_reverse __P((const void *, void *));
|
||||
extern int inet6_rth_segments __P((const void *));
|
||||
extern struct in6_addr *inet6_rth_getaddr __P((const void *, int));
|
||||
__END_DECLS
|
||||
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
#endif /* !_NETINET6_IN6_HH_ */
|
303
freebsd/netinet6/in6_cksum.c
Normal file
303
freebsd/netinet6/in6_cksum.c
Normal file
@@ -0,0 +1,303 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_cksum.c,v 1.10 2000/12/03 00:53:59 itojun Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1988, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/scope6_var.h>
|
||||
|
||||
/*
|
||||
* Checksum routine for Internet Protocol family headers (Portable Version).
|
||||
*
|
||||
* This routine is very heavily used in the network
|
||||
* code and should be modified for each CPU to be as fast as possible.
|
||||
*/
|
||||
|
||||
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
|
||||
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
|
||||
|
||||
/*
|
||||
* m MUST contain a continuous IP6 header.
|
||||
* off is an offset where TCP/UDP/ICMP6 header starts.
|
||||
* len is a total length of a transport segment.
|
||||
* (e.g. TCP header + TCP payload)
|
||||
*/
|
||||
int
|
||||
in6_cksum(struct mbuf *m, u_int8_t nxt, u_int32_t off, u_int32_t len)
|
||||
{
|
||||
u_int16_t *w;
|
||||
int sum = 0;
|
||||
int mlen = 0;
|
||||
int byte_swapped = 0;
|
||||
struct ip6_hdr *ip6;
|
||||
struct in6_addr in6;
|
||||
union {
|
||||
u_int16_t phs[4];
|
||||
struct {
|
||||
u_int32_t ph_len;
|
||||
u_int8_t ph_zero[3];
|
||||
u_int8_t ph_nxt;
|
||||
} __packed ph;
|
||||
} uph;
|
||||
union {
|
||||
u_int8_t c[2];
|
||||
u_int16_t s;
|
||||
} s_util;
|
||||
union {
|
||||
u_int16_t s[2];
|
||||
u_int32_t l;
|
||||
} l_util;
|
||||
|
||||
/* sanity check */
|
||||
if (m->m_pkthdr.len < off + len) {
|
||||
panic("in6_cksum: mbuf len (%d) < off+len (%d+%d)",
|
||||
m->m_pkthdr.len, off, len);
|
||||
}
|
||||
|
||||
bzero(&uph, sizeof(uph));
|
||||
|
||||
/*
|
||||
* First create IP6 pseudo header and calculate a summary.
|
||||
*/
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
uph.ph.ph_len = htonl(len);
|
||||
uph.ph.ph_nxt = nxt;
|
||||
|
||||
/*
|
||||
* IPv6 source address.
|
||||
* XXX: we'd like to avoid copying the address, but we can't due to
|
||||
* the possibly embedded scope zone ID.
|
||||
*/
|
||||
in6 = ip6->ip6_src;
|
||||
in6_clearscope(&in6);
|
||||
w = (u_int16_t *)&in6;
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
|
||||
|
||||
/* IPv6 destination address */
|
||||
in6 = ip6->ip6_dst;
|
||||
in6_clearscope(&in6);
|
||||
w = (u_int16_t *)&in6;
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
|
||||
|
||||
/* Payload length and upper layer identifier */
|
||||
sum += uph.phs[0]; sum += uph.phs[1];
|
||||
sum += uph.phs[2]; sum += uph.phs[3];
|
||||
|
||||
/*
|
||||
* Secondly calculate a summary of the first mbuf excluding offset.
|
||||
*/
|
||||
while (off > 0) {
|
||||
if (m->m_len <= off)
|
||||
off -= m->m_len;
|
||||
else
|
||||
break;
|
||||
m = m->m_next;
|
||||
}
|
||||
w = (u_int16_t *)(mtod(m, u_char *) + off);
|
||||
mlen = m->m_len - off;
|
||||
if (len < mlen)
|
||||
mlen = len;
|
||||
len -= mlen;
|
||||
/*
|
||||
* Force to even boundary.
|
||||
*/
|
||||
if ((1 & (long) w) && (mlen > 0)) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
s_util.c[0] = *(u_char *)w;
|
||||
w = (u_int16_t *)((char *)w + 1);
|
||||
mlen--;
|
||||
byte_swapped = 1;
|
||||
}
|
||||
/*
|
||||
* Unroll the loop to make overhead from
|
||||
* branches &c small.
|
||||
*/
|
||||
while ((mlen -= 32) >= 0) {
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
|
||||
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
|
||||
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
|
||||
w += 16;
|
||||
}
|
||||
mlen += 32;
|
||||
while ((mlen -= 8) >= 0) {
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
w += 4;
|
||||
}
|
||||
mlen += 8;
|
||||
if (mlen == 0 && byte_swapped == 0)
|
||||
goto next;
|
||||
REDUCE;
|
||||
while ((mlen -= 2) >= 0) {
|
||||
sum += *w++;
|
||||
}
|
||||
if (byte_swapped) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
byte_swapped = 0;
|
||||
if (mlen == -1) {
|
||||
s_util.c[1] = *(char *)w;
|
||||
sum += s_util.s;
|
||||
mlen = 0;
|
||||
} else
|
||||
mlen = -1;
|
||||
} else if (mlen == -1)
|
||||
s_util.c[0] = *(char *)w;
|
||||
next:
|
||||
m = m->m_next;
|
||||
|
||||
/*
|
||||
* Lastly calculate a summary of the rest of mbufs.
|
||||
*/
|
||||
|
||||
for (;m && len; m = m->m_next) {
|
||||
if (m->m_len == 0)
|
||||
continue;
|
||||
w = mtod(m, u_int16_t *);
|
||||
if (mlen == -1) {
|
||||
/*
|
||||
* The first byte of this mbuf is the continuation
|
||||
* of a word spanning between this mbuf and the
|
||||
* last mbuf.
|
||||
*
|
||||
* s_util.c[0] is already saved when scanning previous
|
||||
* mbuf.
|
||||
*/
|
||||
s_util.c[1] = *(char *)w;
|
||||
sum += s_util.s;
|
||||
w = (u_int16_t *)((char *)w + 1);
|
||||
mlen = m->m_len - 1;
|
||||
len--;
|
||||
} else
|
||||
mlen = m->m_len;
|
||||
if (len < mlen)
|
||||
mlen = len;
|
||||
len -= mlen;
|
||||
/*
|
||||
* Force to even boundary.
|
||||
*/
|
||||
if ((1 & (long) w) && (mlen > 0)) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
s_util.c[0] = *(u_char *)w;
|
||||
w = (u_int16_t *)((char *)w + 1);
|
||||
mlen--;
|
||||
byte_swapped = 1;
|
||||
}
|
||||
/*
|
||||
* Unroll the loop to make overhead from
|
||||
* branches &c small.
|
||||
*/
|
||||
while ((mlen -= 32) >= 0) {
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
|
||||
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
|
||||
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
|
||||
w += 16;
|
||||
}
|
||||
mlen += 32;
|
||||
while ((mlen -= 8) >= 0) {
|
||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||
w += 4;
|
||||
}
|
||||
mlen += 8;
|
||||
if (mlen == 0 && byte_swapped == 0)
|
||||
continue;
|
||||
REDUCE;
|
||||
while ((mlen -= 2) >= 0) {
|
||||
sum += *w++;
|
||||
}
|
||||
if (byte_swapped) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
byte_swapped = 0;
|
||||
if (mlen == -1) {
|
||||
s_util.c[1] = *(char *)w;
|
||||
sum += s_util.s;
|
||||
mlen = 0;
|
||||
} else
|
||||
mlen = -1;
|
||||
} else if (mlen == -1)
|
||||
s_util.c[0] = *(char *)w;
|
||||
}
|
||||
if (len)
|
||||
panic("in6_cksum: out of data");
|
||||
if (mlen == -1) {
|
||||
/* The last mbuf has odd # of bytes. Follow the
|
||||
standard (the odd byte may be shifted left by 8 bits
|
||||
or not as determined by endian-ness of the machine) */
|
||||
s_util.c[1] = 0;
|
||||
sum += s_util.s;
|
||||
}
|
||||
REDUCE;
|
||||
return (~sum & 0xffff);
|
||||
}
|
466
freebsd/netinet6/in6_gif.c
Normal file
466
freebsd/netinet6/in6_gif.c
Normal file
@@ -0,0 +1,466 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_gif.c,v 1.49 2001/05/14 14:02:17 itojun Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_inet.h>
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/sockio.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/errno.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/queue.h>
|
||||
#include <rtems/freebsd/sys/syslog.h>
|
||||
#include <rtems/freebsd/sys/sysctl.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_systm.h>
|
||||
#ifdef INET
|
||||
#include <rtems/freebsd/netinet/ip.h>
|
||||
#endif
|
||||
#include <rtems/freebsd/netinet/ip_encap.h>
|
||||
#ifdef INET6
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/in6_gif.h>
|
||||
#include <rtems/freebsd/netinet6/in6_var.h>
|
||||
#endif
|
||||
#include <rtems/freebsd/netinet6/ip6protosw.h>
|
||||
#include <rtems/freebsd/netinet/ip_ecn.h>
|
||||
#ifdef INET6
|
||||
#include <rtems/freebsd/netinet6/ip6_ecn.h>
|
||||
#endif
|
||||
|
||||
#include <rtems/freebsd/net/if_gif.h>
|
||||
|
||||
VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
|
||||
#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
|
||||
|
||||
SYSCTL_DECL(_net_inet6_ip6);
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_gif_hlim), 0, "");
|
||||
|
||||
static int gif_validate6(const struct ip6_hdr *, struct gif_softc *,
|
||||
struct ifnet *);
|
||||
|
||||
extern struct domain inet6domain;
|
||||
struct ip6protosw in6_gif_protosw = {
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = 0, /* IPPROTO_IPV[46] */
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = in6_gif_input,
|
||||
.pr_output = rip6_output,
|
||||
.pr_ctloutput = rip6_ctloutput,
|
||||
.pr_usrreqs = &rip6_usrreqs
|
||||
};
|
||||
|
||||
int
|
||||
in6_gif_output(struct ifnet *ifp,
|
||||
int family, /* family of the packet to be encapsulate */
|
||||
struct mbuf *m)
|
||||
{
|
||||
struct gif_softc *sc = ifp->if_softc;
|
||||
struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;
|
||||
struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc;
|
||||
struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst;
|
||||
struct ip6_hdr *ip6;
|
||||
struct etherip_header eiphdr;
|
||||
int error, len, proto;
|
||||
u_int8_t itos, otos;
|
||||
|
||||
GIF_LOCK_ASSERT(sc);
|
||||
|
||||
if (sin6_src == NULL || sin6_dst == NULL ||
|
||||
sin6_src->sin6_family != AF_INET6 ||
|
||||
sin6_dst->sin6_family != AF_INET6) {
|
||||
m_freem(m);
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
switch (family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
{
|
||||
struct ip *ip;
|
||||
|
||||
proto = IPPROTO_IPV4;
|
||||
if (m->m_len < sizeof(*ip)) {
|
||||
m = m_pullup(m, sizeof(*ip));
|
||||
if (!m)
|
||||
return ENOBUFS;
|
||||
}
|
||||
ip = mtod(m, struct ip *);
|
||||
itos = ip->ip_tos;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct ip6_hdr *ip6;
|
||||
proto = IPPROTO_IPV6;
|
||||
if (m->m_len < sizeof(*ip6)) {
|
||||
m = m_pullup(m, sizeof(*ip6));
|
||||
if (!m)
|
||||
return ENOBUFS;
|
||||
}
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case AF_LINK:
|
||||
proto = IPPROTO_ETHERIP;
|
||||
|
||||
/*
|
||||
* GIF_SEND_REVETHIP (disabled by default) intentionally
|
||||
* sends an EtherIP packet with revered version field in
|
||||
* the header. This is a knob for backward compatibility
|
||||
* with FreeBSD 7.2R or prior.
|
||||
*/
|
||||
if ((sc->gif_options & GIF_SEND_REVETHIP)) {
|
||||
eiphdr.eip_ver = 0;
|
||||
eiphdr.eip_resvl = ETHERIP_VERSION;
|
||||
eiphdr.eip_resvh = 0;
|
||||
} else {
|
||||
eiphdr.eip_ver = ETHERIP_VERSION;
|
||||
eiphdr.eip_resvl = 0;
|
||||
eiphdr.eip_resvh = 0;
|
||||
}
|
||||
/* prepend Ethernet-in-IP header */
|
||||
M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
|
||||
if (m && m->m_len < sizeof(struct etherip_header))
|
||||
m = m_pullup(m, sizeof(struct etherip_header));
|
||||
if (m == NULL)
|
||||
return ENOBUFS;
|
||||
bcopy(&eiphdr, mtod(m, struct etherip_header *),
|
||||
sizeof(struct etherip_header));
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("in6_gif_output: warning: unknown family %d passed\n",
|
||||
family);
|
||||
#endif
|
||||
m_freem(m);
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
/* prepend new IP header */
|
||||
len = sizeof(struct ip6_hdr);
|
||||
#ifndef __NO_STRICT_ALIGNMENT
|
||||
if (family == AF_LINK)
|
||||
len += ETHERIP_ALIGN;
|
||||
#endif
|
||||
M_PREPEND(m, len, M_DONTWAIT);
|
||||
if (m != NULL && m->m_len < len)
|
||||
m = m_pullup(m, len);
|
||||
if (m == NULL) {
|
||||
printf("ENOBUFS in in6_gif_output %d\n", __LINE__);
|
||||
return ENOBUFS;
|
||||
}
|
||||
#ifndef __NO_STRICT_ALIGNMENT
|
||||
if (family == AF_LINK) {
|
||||
len = mtod(m, vm_offset_t) & 3;
|
||||
KASSERT(len == 0 || len == ETHERIP_ALIGN,
|
||||
("in6_gif_output: unexpected misalignment"));
|
||||
m->m_data += len;
|
||||
m->m_len -= ETHERIP_ALIGN;
|
||||
}
|
||||
#endif
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ip6->ip6_flow = 0;
|
||||
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
|
||||
ip6->ip6_vfc |= IPV6_VERSION;
|
||||
ip6->ip6_plen = htons((u_short)m->m_pkthdr.len);
|
||||
ip6->ip6_nxt = proto;
|
||||
ip6->ip6_hlim = V_ip6_gif_hlim;
|
||||
ip6->ip6_src = sin6_src->sin6_addr;
|
||||
/* bidirectional configured tunnel mode */
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
|
||||
ip6->ip6_dst = sin6_dst->sin6_addr;
|
||||
else {
|
||||
m_freem(m);
|
||||
return ENETUNREACH;
|
||||
}
|
||||
ip_ecn_ingress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED : ECN_NOCARE,
|
||||
&otos, &itos);
|
||||
ip6->ip6_flow &= ~htonl(0xff << 20);
|
||||
ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
|
||||
|
||||
if (dst->sin6_family != sin6_dst->sin6_family ||
|
||||
!IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) {
|
||||
/* cache route doesn't match */
|
||||
bzero(dst, sizeof(*dst));
|
||||
dst->sin6_family = sin6_dst->sin6_family;
|
||||
dst->sin6_len = sizeof(struct sockaddr_in6);
|
||||
dst->sin6_addr = sin6_dst->sin6_addr;
|
||||
if (sc->gif_ro6.ro_rt) {
|
||||
RTFREE(sc->gif_ro6.ro_rt);
|
||||
sc->gif_ro6.ro_rt = NULL;
|
||||
}
|
||||
#if 0
|
||||
GIF2IFP(sc)->if_mtu = GIF_MTU;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sc->gif_ro6.ro_rt == NULL) {
|
||||
rtalloc((struct route *)&sc->gif_ro6);
|
||||
if (sc->gif_ro6.ro_rt == NULL) {
|
||||
m_freem(m);
|
||||
return ENETUNREACH;
|
||||
}
|
||||
|
||||
/* if it constitutes infinite encapsulation, punt. */
|
||||
if (sc->gif_ro.ro_rt->rt_ifp == ifp) {
|
||||
m_freem(m);
|
||||
return ENETUNREACH; /*XXX*/
|
||||
}
|
||||
#if 0
|
||||
ifp->if_mtu = sc->gif_ro6.ro_rt->rt_ifp->if_mtu
|
||||
- sizeof(struct ip6_hdr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef IPV6_MINMTU
|
||||
/*
|
||||
* force fragmentation to minimum MTU, to avoid path MTU discovery.
|
||||
* it is too painful to ask for resend of inner packet, to achieve
|
||||
* path MTU discovery for encapsulated packets.
|
||||
*/
|
||||
error = ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL, NULL);
|
||||
#else
|
||||
error = ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL, NULL);
|
||||
#endif
|
||||
|
||||
if (!(GIF2IFP(sc)->if_flags & IFF_LINK0) &&
|
||||
sc->gif_ro6.ro_rt != NULL) {
|
||||
RTFREE(sc->gif_ro6.ro_rt);
|
||||
sc->gif_ro6.ro_rt = NULL;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
in6_gif_input(struct mbuf **mp, int *offp, int proto)
|
||||
{
|
||||
struct mbuf *m = *mp;
|
||||
struct ifnet *gifp = NULL;
|
||||
struct gif_softc *sc;
|
||||
struct ip6_hdr *ip6;
|
||||
int af = 0;
|
||||
u_int32_t otos;
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
||||
sc = (struct gif_softc *)encap_getarg(m);
|
||||
if (sc == NULL) {
|
||||
m_freem(m);
|
||||
V_ip6stat.ip6s_nogif++;
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
gifp = GIF2IFP(sc);
|
||||
if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
|
||||
m_freem(m);
|
||||
V_ip6stat.ip6s_nogif++;
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
otos = ip6->ip6_flow;
|
||||
m_adj(m, *offp);
|
||||
|
||||
switch (proto) {
|
||||
#ifdef INET
|
||||
case IPPROTO_IPV4:
|
||||
{
|
||||
struct ip *ip;
|
||||
u_int8_t otos8;
|
||||
af = AF_INET;
|
||||
otos8 = (ntohl(otos) >> 20) & 0xff;
|
||||
if (m->m_len < sizeof(*ip)) {
|
||||
m = m_pullup(m, sizeof(*ip));
|
||||
if (!m)
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
ip = mtod(m, struct ip *);
|
||||
if (ip_ecn_egress((gifp->if_flags & IFF_LINK1) ?
|
||||
ECN_ALLOWED : ECN_NOCARE,
|
||||
&otos8, &ip->ip_tos) == 0) {
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case IPPROTO_IPV6:
|
||||
{
|
||||
struct ip6_hdr *ip6;
|
||||
af = AF_INET6;
|
||||
if (m->m_len < sizeof(*ip6)) {
|
||||
m = m_pullup(m, sizeof(*ip6));
|
||||
if (!m)
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
if (ip6_ecn_egress((gifp->if_flags & IFF_LINK1) ?
|
||||
ECN_ALLOWED : ECN_NOCARE,
|
||||
&otos, &ip6->ip6_flow) == 0) {
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case IPPROTO_ETHERIP:
|
||||
af = AF_LINK;
|
||||
break;
|
||||
|
||||
default:
|
||||
V_ip6stat.ip6s_nogif++;
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
gif_input(m, af, gifp);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* validate outer address.
|
||||
*/
|
||||
static int
|
||||
gif_validate6(const struct ip6_hdr *ip6, struct gif_softc *sc,
|
||||
struct ifnet *ifp)
|
||||
{
|
||||
struct sockaddr_in6 *src, *dst;
|
||||
|
||||
src = (struct sockaddr_in6 *)sc->gif_psrc;
|
||||
dst = (struct sockaddr_in6 *)sc->gif_pdst;
|
||||
|
||||
/*
|
||||
* Check for address match. Note that the check is for an incoming
|
||||
* packet. We should compare the *source* address in our configuration
|
||||
* and the *destination* address of the packet, and vice versa.
|
||||
*/
|
||||
if (!IN6_ARE_ADDR_EQUAL(&src->sin6_addr, &ip6->ip6_dst) ||
|
||||
!IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_src))
|
||||
return 0;
|
||||
|
||||
/* martian filters on outer source - done in ip6_input */
|
||||
|
||||
/* ingress filters on outer source */
|
||||
if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0 && ifp) {
|
||||
struct sockaddr_in6 sin6;
|
||||
struct rtentry *rt;
|
||||
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_addr = ip6->ip6_src;
|
||||
sin6.sin6_scope_id = 0; /* XXX */
|
||||
|
||||
rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
|
||||
if (!rt || rt->rt_ifp != ifp) {
|
||||
#if 0
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
log(LOG_WARNING, "%s: packet from %s dropped "
|
||||
"due to ingress filter\n", if_name(GIF2IFP(sc)),
|
||||
ip6_sprintf(ip6buf, &sin6.sin6_addr));
|
||||
#endif
|
||||
if (rt)
|
||||
RTFREE_LOCKED(rt);
|
||||
return 0;
|
||||
}
|
||||
RTFREE_LOCKED(rt);
|
||||
}
|
||||
|
||||
return 128 * 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* we know that we are in IFF_UP, outer address available, and outer family
|
||||
* matched the physical addr family. see gif_encapcheck().
|
||||
* sanity check for arg should have been done in the caller.
|
||||
*/
|
||||
int
|
||||
gif_encapcheck6(const struct mbuf *m, int off, int proto, void *arg)
|
||||
{
|
||||
struct ip6_hdr ip6;
|
||||
struct gif_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
|
||||
/* sanity check done in caller */
|
||||
sc = (struct gif_softc *)arg;
|
||||
|
||||
/* LINTED const cast */
|
||||
m_copydata(m, 0, sizeof(ip6), (caddr_t)&ip6);
|
||||
ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL;
|
||||
|
||||
return gif_validate6(&ip6, sc, ifp);
|
||||
}
|
||||
|
||||
int
|
||||
in6_gif_attach(struct gif_softc *sc)
|
||||
{
|
||||
sc->encap_cookie6 = encap_attach_func(AF_INET6, -1, gif_encapcheck,
|
||||
(void *)&in6_gif_protosw, sc);
|
||||
if (sc->encap_cookie6 == NULL)
|
||||
return EEXIST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
in6_gif_detach(struct gif_softc *sc)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = encap_detach(sc->encap_cookie6);
|
||||
if (error == 0)
|
||||
sc->encap_cookie6 = NULL;
|
||||
return error;
|
||||
}
|
45
freebsd/netinet6/in6_gif.h
Normal file
45
freebsd/netinet6/in6_gif.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_gif.h,v 1.5 2000/04/14 08:36:03 itojun Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IN6_GIF_HH_
|
||||
#define _NETINET6_IN6_GIF_HH_
|
||||
|
||||
#define GIF_HLIM 30
|
||||
|
||||
struct gif_softc;
|
||||
int in6_gif_input __P((struct mbuf **, int *, int));
|
||||
int in6_gif_output __P((struct ifnet *, int, struct mbuf *));
|
||||
int gif_encapcheck6 __P((const struct mbuf *, int, int, void *));
|
||||
int in6_gif_attach __P((struct gif_softc *));
|
||||
int in6_gif_detach __P((struct gif_softc *));
|
||||
|
||||
#endif /* _NETINET6_IN6_GIF_HH_ */
|
971
freebsd/netinet6/in6_ifattach.c
Normal file
971
freebsd/netinet6/in6_ifattach.c
Normal file
@@ -0,0 +1,971 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/sockio.h>
|
||||
#include <rtems/freebsd/sys/jail.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/proc.h>
|
||||
#include <rtems/freebsd/sys/syslog.h>
|
||||
#include <rtems/freebsd/sys/md5.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/if_dl.h>
|
||||
#include <rtems/freebsd/net/if_types.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
#include <rtems/freebsd/net/vnet.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/if_ether.h>
|
||||
#include <rtems/freebsd/netinet/in_pcb.h>
|
||||
#include <rtems/freebsd/netinet/ip_var.h>
|
||||
#include <rtems/freebsd/netinet/udp.h>
|
||||
#include <rtems/freebsd/netinet/udp_var.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/in6_var.h>
|
||||
#include <rtems/freebsd/netinet6/in6_pcb.h>
|
||||
#include <rtems/freebsd/netinet6/in6_ifattach.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/nd6.h>
|
||||
#include <rtems/freebsd/netinet6/mld6_var.h>
|
||||
#include <rtems/freebsd/netinet6/scope6_var.h>
|
||||
|
||||
VNET_DEFINE(unsigned long, in6_maxmtu) = 0;
|
||||
|
||||
#ifdef IP6_AUTO_LINKLOCAL
|
||||
VNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL;
|
||||
#else
|
||||
VNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */
|
||||
#endif
|
||||
|
||||
VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch);
|
||||
#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
|
||||
|
||||
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
|
||||
#define V_ripcbinfo VNET(ripcbinfo)
|
||||
|
||||
static int get_rand_ifid(struct ifnet *, struct in6_addr *);
|
||||
static int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
|
||||
static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
|
||||
static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
|
||||
static int in6_ifattach_loopback(struct ifnet *);
|
||||
static void in6_purgemaddrs(struct ifnet *);
|
||||
|
||||
#define EUI64_GBIT 0x01
|
||||
#define EUI64_UBIT 0x02
|
||||
#define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
|
||||
#define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT)
|
||||
#define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6))
|
||||
#define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT)
|
||||
#define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6))
|
||||
|
||||
#define IFID_LOCAL(in6) (!EUI64_LOCAL(in6))
|
||||
#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
|
||||
|
||||
/*
|
||||
* Generate a last-resort interface identifier, when the machine has no
|
||||
* IEEE802/EUI64 address sources.
|
||||
* The goal here is to get an interface identifier that is
|
||||
* (1) random enough and (2) does not change across reboot.
|
||||
* We currently use MD5(hostname) for it.
|
||||
*
|
||||
* in6 - upper 64bits are preserved
|
||||
*/
|
||||
static int
|
||||
get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
|
||||
{
|
||||
MD5_CTX ctxt;
|
||||
struct prison *pr;
|
||||
u_int8_t digest[16];
|
||||
int hostnamelen;
|
||||
|
||||
pr = curthread->td_ucred->cr_prison;
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
hostnamelen = strlen(pr->pr_hostname);
|
||||
#if 0
|
||||
/* we need at least several letters as seed for ifid */
|
||||
if (hostnamelen < 3) {
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* generate 8 bytes of pseudo-random value. */
|
||||
bzero(&ctxt, sizeof(ctxt));
|
||||
MD5Init(&ctxt);
|
||||
MD5Update(&ctxt, pr->pr_hostname, hostnamelen);
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
MD5Final(digest, &ctxt);
|
||||
|
||||
/* assumes sizeof(digest) > sizeof(ifid) */
|
||||
bcopy(digest, &in6->s6_addr[8], 8);
|
||||
|
||||
/* make sure to set "u" bit to local, and "g" bit to individual. */
|
||||
in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
|
||||
in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
|
||||
|
||||
/* convert EUI64 into IPv6 interface identifier */
|
||||
EUI64_TO_IFID(in6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
|
||||
{
|
||||
MD5_CTX ctxt;
|
||||
u_int8_t seed[16], digest[16], nullbuf[8];
|
||||
u_int32_t val32;
|
||||
|
||||
/* If there's no history, start with a random seed. */
|
||||
bzero(nullbuf, sizeof(nullbuf));
|
||||
if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
val32 = arc4random();
|
||||
bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
|
||||
}
|
||||
} else
|
||||
bcopy(seed0, seed, 8);
|
||||
|
||||
/* copy the right-most 64-bits of the given address */
|
||||
/* XXX assumption on the size of IFID */
|
||||
bcopy(seed1, &seed[8], 8);
|
||||
|
||||
if (0) { /* for debugging purposes only */
|
||||
int i;
|
||||
|
||||
printf("generate_tmp_ifid: new randomized ID from: ");
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%02x", seed[i]);
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
/* generate 16 bytes of pseudo-random value. */
|
||||
bzero(&ctxt, sizeof(ctxt));
|
||||
MD5Init(&ctxt);
|
||||
MD5Update(&ctxt, seed, sizeof(seed));
|
||||
MD5Final(digest, &ctxt);
|
||||
|
||||
/*
|
||||
* RFC 3041 3.2.1. (3)
|
||||
* Take the left-most 64-bits of the MD5 digest and set bit 6 (the
|
||||
* left-most bit is numbered 0) to zero.
|
||||
*/
|
||||
bcopy(digest, ret, 8);
|
||||
ret[0] &= ~EUI64_UBIT;
|
||||
|
||||
/*
|
||||
* XXX: we'd like to ensure that the generated value is not zero
|
||||
* for simplicity. If the caclculated digest happens to be zero,
|
||||
* use a random non-zero value as the last resort.
|
||||
*/
|
||||
if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
|
||||
nd6log((LOG_INFO,
|
||||
"generate_tmp_ifid: computed MD5 value is zero.\n"));
|
||||
|
||||
val32 = arc4random();
|
||||
val32 = 1 + (val32 % (0xffffffff - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3041 3.2.1. (4)
|
||||
* Take the rightmost 64-bits of the MD5 digest and save them in
|
||||
* stable storage as the history value to be used in the next
|
||||
* iteration of the algorithm.
|
||||
*/
|
||||
bcopy(&digest[8], seed0, 8);
|
||||
|
||||
if (0) { /* for debugging purposes only */
|
||||
int i;
|
||||
|
||||
printf("to: ");
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%02x", digest[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get interface identifier for the specified interface.
|
||||
* XXX assumes single sockaddr_dl (AF_LINK address) per an interface
|
||||
*
|
||||
* in6 - upper 64bits are preserved
|
||||
*/
|
||||
int
|
||||
in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr_dl *sdl;
|
||||
u_int8_t *addr;
|
||||
size_t addrlen;
|
||||
static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
static u_int8_t allone[8] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
IF_ADDR_LOCK(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
|
||||
if (sdl == NULL)
|
||||
continue;
|
||||
if (sdl->sdl_alen == 0)
|
||||
continue;
|
||||
|
||||
goto found;
|
||||
}
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
|
||||
return -1;
|
||||
|
||||
found:
|
||||
IF_ADDR_LOCK_ASSERT(ifp);
|
||||
addr = LLADDR(sdl);
|
||||
addrlen = sdl->sdl_alen;
|
||||
|
||||
/* get EUI64 */
|
||||
switch (ifp->if_type) {
|
||||
case IFT_ETHER:
|
||||
case IFT_FDDI:
|
||||
case IFT_ISO88025:
|
||||
case IFT_ATM:
|
||||
case IFT_IEEE1394:
|
||||
#ifdef IFT_IEEE80211
|
||||
case IFT_IEEE80211:
|
||||
#endif
|
||||
/* IEEE802/EUI64 cases - what others? */
|
||||
/* IEEE1394 uses 16byte length address starting with EUI64 */
|
||||
if (addrlen > 8)
|
||||
addrlen = 8;
|
||||
|
||||
/* look at IEEE802/EUI64 only */
|
||||
if (addrlen != 8 && addrlen != 6) {
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for invalid MAC address - on bsdi, we see it a lot
|
||||
* since wildboar configures all-zero MAC on pccard before
|
||||
* card insertion.
|
||||
*/
|
||||
if (bcmp(addr, allzero, addrlen) == 0) {
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
if (bcmp(addr, allone, addrlen) == 0) {
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make EUI64 address */
|
||||
if (addrlen == 8)
|
||||
bcopy(addr, &in6->s6_addr[8], 8);
|
||||
else if (addrlen == 6) {
|
||||
in6->s6_addr[8] = addr[0];
|
||||
in6->s6_addr[9] = addr[1];
|
||||
in6->s6_addr[10] = addr[2];
|
||||
in6->s6_addr[11] = 0xff;
|
||||
in6->s6_addr[12] = 0xfe;
|
||||
in6->s6_addr[13] = addr[3];
|
||||
in6->s6_addr[14] = addr[4];
|
||||
in6->s6_addr[15] = addr[5];
|
||||
}
|
||||
break;
|
||||
|
||||
case IFT_ARCNET:
|
||||
if (addrlen != 1) {
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
if (!addr[0]) {
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero(&in6->s6_addr[8], 8);
|
||||
in6->s6_addr[15] = addr[0];
|
||||
|
||||
/*
|
||||
* due to insufficient bitwidth, we mark it local.
|
||||
*/
|
||||
in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
|
||||
in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
|
||||
break;
|
||||
|
||||
case IFT_GIF:
|
||||
#ifdef IFT_STF
|
||||
case IFT_STF:
|
||||
#endif
|
||||
/*
|
||||
* RFC2893 says: "SHOULD use IPv4 address as ifid source".
|
||||
* however, IPv4 address is not very suitable as unique
|
||||
* identifier source (can be renumbered).
|
||||
* we don't do this.
|
||||
*/
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* sanity check: g bit must not indicate "group" */
|
||||
if (EUI64_GROUP(in6)) {
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* convert EUI64 into IPv6 interface identifier */
|
||||
EUI64_TO_IFID(in6);
|
||||
|
||||
/*
|
||||
* sanity check: ifid must not be all zero, avoid conflict with
|
||||
* subnet router anycast
|
||||
*/
|
||||
if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
|
||||
bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get interface identifier for the specified interface. If it is not
|
||||
* available on ifp0, borrow interface identifier from other information
|
||||
* sources.
|
||||
*
|
||||
* altifp - secondary EUI64 source
|
||||
*/
|
||||
static int
|
||||
get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
|
||||
struct in6_addr *in6)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
/* first, try to get it from the interface itself */
|
||||
if (in6_get_hw_ifid(ifp0, in6) == 0) {
|
||||
nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
|
||||
if_name(ifp0)));
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* try secondary EUI64 source. this basically is for ATM PVC */
|
||||
if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
|
||||
nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
|
||||
if_name(ifp0), if_name(altifp)));
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* next, try to get it from some other hardware interface */
|
||||
IFNET_RLOCK_NOSLEEP();
|
||||
for (ifp = V_ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
|
||||
if (ifp == ifp0)
|
||||
continue;
|
||||
if (in6_get_hw_ifid(ifp, in6) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* to borrow ifid from other interface, ifid needs to be
|
||||
* globally unique
|
||||
*/
|
||||
if (IFID_UNIVERSAL(in6)) {
|
||||
nd6log((LOG_DEBUG,
|
||||
"%s: borrow interface identifier from %s\n",
|
||||
if_name(ifp0), if_name(ifp)));
|
||||
IFNET_RUNLOCK_NOSLEEP();
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
IFNET_RUNLOCK_NOSLEEP();
|
||||
|
||||
/* last resort: get from random number source */
|
||||
if (get_rand_ifid(ifp, in6) == 0) {
|
||||
nd6log((LOG_DEBUG,
|
||||
"%s: interface identifier generated by random number\n",
|
||||
if_name(ifp0)));
|
||||
goto success;
|
||||
}
|
||||
|
||||
printf("%s: failed to get interface identifier\n", if_name(ifp0));
|
||||
return -1;
|
||||
|
||||
success:
|
||||
nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
|
||||
in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
|
||||
in6->s6_addr[14], in6->s6_addr[15]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* altifp - secondary EUI64 source
|
||||
*/
|
||||
static int
|
||||
in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
struct in6_aliasreq ifra;
|
||||
struct nd_prefixctl pr0;
|
||||
int i, error;
|
||||
|
||||
/*
|
||||
* configure link-local address.
|
||||
*/
|
||||
bzero(&ifra, sizeof(ifra));
|
||||
|
||||
/*
|
||||
* in6_update_ifa() does not use ifra_name, but we accurately set it
|
||||
* for safety.
|
||||
*/
|
||||
strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
|
||||
|
||||
ifra.ifra_addr.sin6_family = AF_INET6;
|
||||
ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
|
||||
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
|
||||
} else {
|
||||
if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
|
||||
nd6log((LOG_ERR,
|
||||
"%s: no ifid available\n", if_name(ifp)));
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
|
||||
return (-1);
|
||||
|
||||
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_prefixmask.sin6_family = AF_INET6;
|
||||
ifra.ifra_prefixmask.sin6_addr = in6mask64;
|
||||
/* link-local addresses should NEVER expire. */
|
||||
ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
|
||||
ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
|
||||
|
||||
/*
|
||||
* Now call in6_update_ifa() to do a bunch of procedures to configure
|
||||
* a link-local address. We can set the 3rd argument to NULL, because
|
||||
* we know there's no other link-local address on the interface
|
||||
* and therefore we are adding one (instead of updating one).
|
||||
*/
|
||||
if ((error = in6_update_ifa(ifp, &ifra, NULL,
|
||||
IN6_IFAUPDATE_DADDELAY)) != 0) {
|
||||
/*
|
||||
* XXX: When the interface does not support IPv6, this call
|
||||
* would fail in the SIOCSIFADDR ioctl. I believe the
|
||||
* notification is rather confusing in this case, so just
|
||||
* suppress it. (jinmei@kame.net 20010130)
|
||||
*/
|
||||
if (error != EAFNOSUPPORT)
|
||||
nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
|
||||
"configure a link-local address on %s "
|
||||
"(errno=%d)\n",
|
||||
if_name(ifp), error));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
|
||||
#ifdef DIAGNOSTIC
|
||||
if (!ia) {
|
||||
panic("ia == NULL in in6_ifattach_linklocal");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
ifa_free(&ia->ia_ifa);
|
||||
|
||||
/*
|
||||
* Make the link-local prefix (fe80::%link/64) as on-link.
|
||||
* Since we'd like to manage prefixes separately from addresses,
|
||||
* we make an ND6 prefix structure for the link-local prefix,
|
||||
* and add it to the prefix list as a never-expire prefix.
|
||||
* XXX: this change might affect some existing code base...
|
||||
*/
|
||||
bzero(&pr0, sizeof(pr0));
|
||||
pr0.ndpr_ifp = ifp;
|
||||
/* this should be 64 at this moment. */
|
||||
pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
|
||||
pr0.ndpr_prefix = ifra.ifra_addr;
|
||||
/* apply the mask for safety. (nd6_prelist_add will apply it again) */
|
||||
for (i = 0; i < 4; i++) {
|
||||
pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
|
||||
in6mask64.s6_addr32[i];
|
||||
}
|
||||
/*
|
||||
* Initialize parameters. The link-local prefix must always be
|
||||
* on-link, and its lifetimes never expire.
|
||||
*/
|
||||
pr0.ndpr_raf_onlink = 1;
|
||||
pr0.ndpr_raf_auto = 1; /* probably meaningless */
|
||||
pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
|
||||
pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
|
||||
/*
|
||||
* Since there is no other link-local addresses, nd6_prefix_lookup()
|
||||
* probably returns NULL. However, we cannot always expect the result.
|
||||
* For example, if we first remove the (only) existing link-local
|
||||
* address, and then reconfigure another one, the prefix is still
|
||||
* valid with referring to the old link-local address.
|
||||
*/
|
||||
if (nd6_prefix_lookup(&pr0) == NULL) {
|
||||
if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ifp - must be IFT_LOOP
|
||||
*/
|
||||
static int
|
||||
in6_ifattach_loopback(struct ifnet *ifp)
|
||||
{
|
||||
struct in6_aliasreq ifra;
|
||||
int error;
|
||||
|
||||
bzero(&ifra, sizeof(ifra));
|
||||
|
||||
/*
|
||||
* in6_update_ifa() does not use ifra_name, but we accurately set it
|
||||
* for safety.
|
||||
*/
|
||||
strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
|
||||
|
||||
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_prefixmask.sin6_family = AF_INET6;
|
||||
ifra.ifra_prefixmask.sin6_addr = in6mask128;
|
||||
|
||||
/*
|
||||
* Always initialize ia_dstaddr (= broadcast address) to loopback
|
||||
* address. Follows IPv4 practice - see in_ifinit().
|
||||
*/
|
||||
ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_dstaddr.sin6_family = AF_INET6;
|
||||
ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
|
||||
|
||||
ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_addr.sin6_family = AF_INET6;
|
||||
ifra.ifra_addr.sin6_addr = in6addr_loopback;
|
||||
|
||||
/* the loopback address should NEVER expire. */
|
||||
ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
|
||||
ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
|
||||
|
||||
/* we don't need to perform DAD on loopback interfaces. */
|
||||
ifra.ifra_flags |= IN6_IFF_NODAD;
|
||||
|
||||
/* skip registration to the prefix list. XXX should be temporary. */
|
||||
ifra.ifra_flags |= IN6_IFF_NOPFX;
|
||||
|
||||
/*
|
||||
* We are sure that this is a newly assigned address, so we can set
|
||||
* NULL to the 3rd arg.
|
||||
*/
|
||||
if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
|
||||
nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
|
||||
"the loopback address on %s (errno=%d)\n",
|
||||
if_name(ifp), error));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* compute NI group address, based on the current hostname setting.
|
||||
* see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
|
||||
*
|
||||
* when ifp == NULL, the caller is responsible for filling scopeid.
|
||||
*/
|
||||
int
|
||||
in6_nigroup(struct ifnet *ifp, const char *name, int namelen,
|
||||
struct in6_addr *in6)
|
||||
{
|
||||
struct prison *pr;
|
||||
const char *p;
|
||||
u_char *q;
|
||||
MD5_CTX ctxt;
|
||||
u_int8_t digest[16];
|
||||
char l;
|
||||
char n[64]; /* a single label must not exceed 63 chars */
|
||||
|
||||
/*
|
||||
* If no name is given and namelen is -1,
|
||||
* we try to do the hostname lookup ourselves.
|
||||
*/
|
||||
if (!name && namelen == -1) {
|
||||
pr = curthread->td_ucred->cr_prison;
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
name = pr->pr_hostname;
|
||||
namelen = strlen(name);
|
||||
} else
|
||||
pr = NULL;
|
||||
if (!name || !namelen) {
|
||||
if (pr != NULL)
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = name;
|
||||
while (p && *p && *p != '.' && p - name < namelen)
|
||||
p++;
|
||||
if (p == name || p - name > sizeof(n) - 1) {
|
||||
if (pr != NULL)
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
return -1; /* label too long */
|
||||
}
|
||||
l = p - name;
|
||||
strncpy(n, name, l);
|
||||
if (pr != NULL)
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
n[(int)l] = '\0';
|
||||
for (q = n; *q; q++) {
|
||||
if ('A' <= *q && *q <= 'Z')
|
||||
*q = *q - 'A' + 'a';
|
||||
}
|
||||
|
||||
/* generate 8 bytes of pseudo-random value. */
|
||||
bzero(&ctxt, sizeof(ctxt));
|
||||
MD5Init(&ctxt);
|
||||
MD5Update(&ctxt, &l, sizeof(l));
|
||||
MD5Update(&ctxt, n, l);
|
||||
MD5Final(digest, &ctxt);
|
||||
|
||||
bzero(in6, sizeof(*in6));
|
||||
in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
|
||||
in6->s6_addr8[11] = 2;
|
||||
bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
|
||||
if (in6_setscope(in6, ifp, NULL))
|
||||
return (-1); /* XXX: should not fail */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX multiple loopback interface needs more care. for instance,
|
||||
* nodelocal address needs to be configured onto only one of them.
|
||||
* XXX multiple link-local address case
|
||||
*
|
||||
* altifp - secondary EUI64 source
|
||||
*/
|
||||
void
|
||||
in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
struct in6_addr in6;
|
||||
|
||||
/* some of the interfaces are inherently not IPv6 capable */
|
||||
switch (ifp->if_type) {
|
||||
case IFT_PFLOG:
|
||||
case IFT_PFSYNC:
|
||||
case IFT_CARP:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* quirks based on interface type
|
||||
*/
|
||||
switch (ifp->if_type) {
|
||||
#ifdef IFT_STF
|
||||
case IFT_STF:
|
||||
/*
|
||||
* 6to4 interface is a very special kind of beast.
|
||||
* no multicast, no linklocal. RFC2529 specifies how to make
|
||||
* linklocals for 6to4 interface, but there's no use and
|
||||
* it is rather harmful to have one.
|
||||
*/
|
||||
goto statinit;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* usually, we require multicast capability to the interface
|
||||
*/
|
||||
if ((ifp->if_flags & IFF_MULTICAST) == 0) {
|
||||
nd6log((LOG_INFO, "in6_ifattach: "
|
||||
"%s is not multicast capable, IPv6 not enabled\n",
|
||||
if_name(ifp)));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* assign loopback address for loopback interface.
|
||||
* XXX multiple loopback interface case.
|
||||
*/
|
||||
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
|
||||
struct ifaddr *ifa;
|
||||
|
||||
in6 = in6addr_loopback;
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &in6);
|
||||
if (ifa == NULL) {
|
||||
if (in6_ifattach_loopback(ifp) != 0)
|
||||
return;
|
||||
} else
|
||||
ifa_free(ifa);
|
||||
}
|
||||
|
||||
/*
|
||||
* assign a link-local address, if there's none.
|
||||
*/
|
||||
if (V_ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) {
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0);
|
||||
if (ia == NULL) {
|
||||
if (in6_ifattach_linklocal(ifp, altifp) == 0) {
|
||||
/* linklocal address assigned */
|
||||
} else {
|
||||
/* failed to assign linklocal address. bark? */
|
||||
}
|
||||
} else
|
||||
ifa_free(&ia->ia_ifa);
|
||||
}
|
||||
|
||||
#ifdef IFT_STF /* XXX */
|
||||
statinit:
|
||||
#endif
|
||||
|
||||
/* update dynamically. */
|
||||
if (V_in6_maxmtu < ifp->if_mtu)
|
||||
V_in6_maxmtu = ifp->if_mtu;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: in6_ifdetach() does not support loopback if at this moment.
|
||||
* We don't need this function in bsdi, because interfaces are never removed
|
||||
* from the ifnet list in bsdi.
|
||||
*/
|
||||
void
|
||||
in6_ifdetach(struct ifnet *ifp)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
struct ifaddr *ifa, *next;
|
||||
struct radix_node_head *rnh;
|
||||
struct rtentry *rt;
|
||||
short rtflags;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct in6_multi_mship *imm;
|
||||
|
||||
/* remove neighbor management table */
|
||||
nd6_purge(ifp);
|
||||
|
||||
/* nuke any of IPv6 addresses we have */
|
||||
TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
in6_purgeaddr(ifa);
|
||||
}
|
||||
|
||||
/* undo everything done by in6_ifattach(), just in case */
|
||||
TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6
|
||||
|| !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
|
||||
/*
|
||||
* leave from multicast groups we have joined for the interface
|
||||
*/
|
||||
while ((imm = ia->ia6_memberships.lh_first) != NULL) {
|
||||
LIST_REMOVE(imm, i6mm_chain);
|
||||
in6_leavegroup(imm);
|
||||
}
|
||||
|
||||
/* remove from the routing table */
|
||||
if ((ia->ia_flags & IFA_ROUTE) &&
|
||||
(rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
|
||||
rtflags = rt->rt_flags;
|
||||
RTFREE_LOCKED(rt);
|
||||
rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
|
||||
(struct sockaddr *)&ia->ia_addr,
|
||||
(struct sockaddr *)&ia->ia_prefixmask,
|
||||
rtflags, (struct rtentry **)0);
|
||||
}
|
||||
|
||||
/* remove from the linked list */
|
||||
IF_ADDR_LOCK(ifp);
|
||||
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
ifa_free(ifa); /* if_addrhead */
|
||||
|
||||
IN6_IFADDR_WLOCK();
|
||||
TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link);
|
||||
IN6_IFADDR_WUNLOCK();
|
||||
ifa_free(ifa);
|
||||
}
|
||||
|
||||
in6_pcbpurgeif0(&V_udbinfo, ifp);
|
||||
in6_pcbpurgeif0(&V_ripcbinfo, ifp);
|
||||
/* leave from all multicast groups joined */
|
||||
in6_purgemaddrs(ifp);
|
||||
|
||||
/*
|
||||
* remove neighbor management table. we call it twice just to make
|
||||
* sure we nuke everything. maybe we need just one call.
|
||||
* XXX: since the first call did not release addresses, some prefixes
|
||||
* might remain. We should call nd6_purge() again to release the
|
||||
* prefixes after removing all addresses above.
|
||||
* (Or can we just delay calling nd6_purge until at this point?)
|
||||
*/
|
||||
nd6_purge(ifp);
|
||||
|
||||
/* remove route to link-local allnodes multicast (ff02::1) */
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_addr = in6addr_linklocal_allnodes;
|
||||
if (in6_setscope(&sin6.sin6_addr, ifp, NULL))
|
||||
/* XXX: should not fail */
|
||||
return;
|
||||
/* XXX grab lock first to avoid LOR */
|
||||
rnh = rt_tables_get_rnh(0, AF_INET6);
|
||||
if (rnh != NULL) {
|
||||
RADIX_NODE_HEAD_LOCK(rnh);
|
||||
rt = rtalloc1((struct sockaddr *)&sin6, 0, RTF_RNH_LOCKED);
|
||||
if (rt) {
|
||||
if (rt->rt_ifp == ifp)
|
||||
rtexpunge(rt);
|
||||
RTFREE_LOCKED(rt);
|
||||
}
|
||||
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
in6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
|
||||
const u_int8_t *baseid, int generate)
|
||||
{
|
||||
u_int8_t nullbuf[8];
|
||||
struct nd_ifinfo *ndi = ND_IFINFO(ifp);
|
||||
|
||||
bzero(nullbuf, sizeof(nullbuf));
|
||||
if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
|
||||
/* we've never created a random ID. Create a new one. */
|
||||
generate = 1;
|
||||
}
|
||||
|
||||
if (generate) {
|
||||
bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
|
||||
|
||||
/* generate_tmp_ifid will update seedn and buf */
|
||||
(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
|
||||
ndi->randomid);
|
||||
}
|
||||
bcopy(ndi->randomid, retbuf, 8);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
in6_tmpaddrtimer(void *arg)
|
||||
{
|
||||
CURVNET_SET((struct vnet *) arg);
|
||||
struct nd_ifinfo *ndi;
|
||||
u_int8_t nullbuf[8];
|
||||
struct ifnet *ifp;
|
||||
|
||||
callout_reset(&V_in6_tmpaddrtimer_ch,
|
||||
(V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
|
||||
V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet);
|
||||
|
||||
bzero(nullbuf, sizeof(nullbuf));
|
||||
for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
|
||||
ifp = TAILQ_NEXT(ifp, if_list)) {
|
||||
ndi = ND_IFINFO(ifp);
|
||||
if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
|
||||
/*
|
||||
* We've been generating a random ID on this interface.
|
||||
* Create a new one.
|
||||
*/
|
||||
(void)generate_tmp_ifid(ndi->randomseed0,
|
||||
ndi->randomseed1, ndi->randomid);
|
||||
}
|
||||
}
|
||||
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
static void
|
||||
in6_purgemaddrs(struct ifnet *ifp)
|
||||
{
|
||||
LIST_HEAD(,in6_multi) purgeinms;
|
||||
struct in6_multi *inm, *tinm;
|
||||
struct ifmultiaddr *ifma;
|
||||
|
||||
LIST_INIT(&purgeinms);
|
||||
IN6_MULTI_LOCK();
|
||||
|
||||
/*
|
||||
* Extract list of in6_multi associated with the detaching ifp
|
||||
* which the PF_INET6 layer is about to release.
|
||||
* We need to do this as IF_ADDR_LOCK() may be re-acquired
|
||||
* by code further down.
|
||||
*/
|
||||
IF_ADDR_LOCK(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_INET6 ||
|
||||
ifma->ifma_protospec == NULL)
|
||||
continue;
|
||||
inm = (struct in6_multi *)ifma->ifma_protospec;
|
||||
LIST_INSERT_HEAD(&purgeinms, inm, in6m_entry);
|
||||
}
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
|
||||
LIST_FOREACH_SAFE(inm, &purgeinms, in6m_entry, tinm) {
|
||||
LIST_REMOVE(inm, in6m_entry);
|
||||
in6m_release_locked(inm);
|
||||
}
|
||||
mld_ifdetach(ifp);
|
||||
|
||||
IN6_MULTI_UNLOCK();
|
||||
}
|
45
freebsd/netinet6/in6_ifattach.h
Normal file
45
freebsd/netinet6/in6_ifattach.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_ifattach.h,v 1.14 2001/02/08 12:48:39 jinmei Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IN6_IFATTACH_HH_
|
||||
#define _NETINET6_IN6_IFATTACH_HH_
|
||||
|
||||
#ifdef _KERNEL
|
||||
void in6_ifattach __P((struct ifnet *, struct ifnet *));
|
||||
void in6_ifdetach __P((struct ifnet *));
|
||||
int in6_get_tmpifid __P((struct ifnet *, u_int8_t *, const u_int8_t *, int));
|
||||
void in6_tmpaddrtimer __P((void *));
|
||||
int in6_get_hw_ifid __P((struct ifnet *, struct in6_addr *));
|
||||
int in6_nigroup __P((struct ifnet *, const char *, int, struct in6_addr *));
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET6_IN6_IFATTACH_HH_ */
|
2840
freebsd/netinet6/in6_mcast.c
Normal file
2840
freebsd/netinet6/in6_mcast.c
Normal file
File diff suppressed because it is too large
Load Diff
936
freebsd/netinet6/in6_pcb.c
Normal file
936
freebsd/netinet6/in6_pcb.c
Normal file
@@ -0,0 +1,936 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_inet.h>
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
#include <rtems/freebsd/local/opt_ipsec.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/domain.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/socketvar.h>
|
||||
#include <rtems/freebsd/sys/sockio.h>
|
||||
#include <rtems/freebsd/sys/errno.h>
|
||||
#include <rtems/freebsd/sys/time.h>
|
||||
#include <rtems/freebsd/sys/priv.h>
|
||||
#include <rtems/freebsd/sys/proc.h>
|
||||
#include <rtems/freebsd/sys/jail.h>
|
||||
|
||||
#include <rtems/freebsd/vm/uma.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/if_types.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/in_systm.h>
|
||||
#include <rtems/freebsd/netinet/tcp_var.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet/ip_var.h>
|
||||
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/nd6.h>
|
||||
#include <rtems/freebsd/netinet/in_pcb.h>
|
||||
#include <rtems/freebsd/netinet6/in6_pcb.h>
|
||||
#include <rtems/freebsd/netinet6/scope6_var.h>
|
||||
|
||||
#include <rtems/freebsd/security/mac/mac_framework.h>
|
||||
|
||||
struct in6_addr zeroin6_addr;
|
||||
|
||||
int
|
||||
in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
|
||||
struct ucred *cred)
|
||||
{
|
||||
struct socket *so = inp->inp_socket;
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
|
||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
|
||||
u_short lport = 0;
|
||||
int error, wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
|
||||
|
||||
INP_INFO_WLOCK_ASSERT(pcbinfo);
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
|
||||
if (TAILQ_EMPTY(&V_in6_ifaddrhead)) /* XXX broken! */
|
||||
return (EADDRNOTAVAIL);
|
||||
if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
|
||||
return (EINVAL);
|
||||
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
|
||||
wild = INPLOOKUP_WILDCARD;
|
||||
if (nam == NULL) {
|
||||
if ((error = prison_local_ip6(cred, &inp->in6p_laddr,
|
||||
((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
|
||||
return (error);
|
||||
} else {
|
||||
sin6 = (struct sockaddr_in6 *)nam;
|
||||
if (nam->sa_len != sizeof(*sin6))
|
||||
return (EINVAL);
|
||||
/*
|
||||
* family check.
|
||||
*/
|
||||
if (nam->sa_family != AF_INET6)
|
||||
return (EAFNOSUPPORT);
|
||||
|
||||
if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0)
|
||||
return(error);
|
||||
|
||||
if ((error = prison_local_ip6(cred, &sin6->sin6_addr,
|
||||
((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
|
||||
return (error);
|
||||
|
||||
lport = sin6->sin6_port;
|
||||
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
|
||||
/*
|
||||
* Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
|
||||
* allow compepte duplication of binding if
|
||||
* SO_REUSEPORT is set, or if SO_REUSEADDR is set
|
||||
* and a multicast address is bound on both
|
||||
* new and duplicated sockets.
|
||||
*/
|
||||
if (so->so_options & SO_REUSEADDR)
|
||||
reuseport = SO_REUSEADDR|SO_REUSEPORT;
|
||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
struct ifaddr *ifa;
|
||||
|
||||
sin6->sin6_port = 0; /* yech... */
|
||||
if ((ifa = ifa_ifwithaddr((struct sockaddr *)sin6)) ==
|
||||
NULL &&
|
||||
(inp->inp_flags & INP_BINDANY) == 0) {
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: bind to an anycast address might accidentally
|
||||
* cause sending a packet with anycast source address.
|
||||
* We should allow to bind to a deprecated address, since
|
||||
* the application dares to use it.
|
||||
*/
|
||||
if (ifa != NULL &&
|
||||
((struct in6_ifaddr *)ifa)->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
|
||||
ifa_free(ifa);
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
if (ifa != NULL)
|
||||
ifa_free(ifa);
|
||||
}
|
||||
if (lport) {
|
||||
struct inpcb *t;
|
||||
|
||||
/* GROSS */
|
||||
if (ntohs(lport) <= V_ipport_reservedhigh &&
|
||||
ntohs(lport) >= V_ipport_reservedlow &&
|
||||
priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
|
||||
0))
|
||||
return (EACCES);
|
||||
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
|
||||
priv_check_cred(inp->inp_cred,
|
||||
PRIV_NETINET_REUSEPORT, 0) != 0) {
|
||||
t = in6_pcblookup_local(pcbinfo,
|
||||
&sin6->sin6_addr, lport,
|
||||
INPLOOKUP_WILDCARD, cred);
|
||||
if (t &&
|
||||
((t->inp_flags & INP_TIMEWAIT) == 0) &&
|
||||
(so->so_type != SOCK_STREAM ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
|
||||
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
|
||||
!IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
|
||||
(t->inp_socket->so_options & SO_REUSEPORT)
|
||||
== 0) && (inp->inp_cred->cr_uid !=
|
||||
t->inp_cred->cr_uid))
|
||||
return (EADDRINUSE);
|
||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
in6_sin6_2_sin(&sin, sin6);
|
||||
t = in_pcblookup_local(pcbinfo,
|
||||
sin.sin_addr, lport,
|
||||
INPLOOKUP_WILDCARD, cred);
|
||||
if (t &&
|
||||
((t->inp_flags &
|
||||
INP_TIMEWAIT) == 0) &&
|
||||
(so->so_type != SOCK_STREAM ||
|
||||
ntohl(t->inp_faddr.s_addr) ==
|
||||
INADDR_ANY) &&
|
||||
(inp->inp_cred->cr_uid !=
|
||||
t->inp_cred->cr_uid))
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
}
|
||||
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
|
||||
lport, wild, cred);
|
||||
if (t && (reuseport & ((t->inp_flags & INP_TIMEWAIT) ?
|
||||
intotw(t)->tw_so_options :
|
||||
t->inp_socket->so_options)) == 0)
|
||||
return (EADDRINUSE);
|
||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
in6_sin6_2_sin(&sin, sin6);
|
||||
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
|
||||
lport, wild, cred);
|
||||
if (t && t->inp_flags & INP_TIMEWAIT) {
|
||||
if ((reuseport &
|
||||
intotw(t)->tw_so_options) == 0 &&
|
||||
(ntohl(t->inp_laddr.s_addr) !=
|
||||
INADDR_ANY || ((inp->inp_vflag &
|
||||
INP_IPV6PROTO) ==
|
||||
(t->inp_vflag & INP_IPV6PROTO))))
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
else if (t &&
|
||||
(reuseport & t->inp_socket->so_options)
|
||||
== 0 && (ntohl(t->inp_laddr.s_addr) !=
|
||||
INADDR_ANY || INP_SOCKAF(so) ==
|
||||
INP_SOCKAF(t->inp_socket)))
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
}
|
||||
inp->in6p_laddr = sin6->sin6_addr;
|
||||
}
|
||||
if (lport == 0) {
|
||||
if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0)
|
||||
return (error);
|
||||
} else {
|
||||
inp->inp_lport = lport;
|
||||
if (in_pcbinshash(inp) != 0) {
|
||||
inp->in6p_laddr = in6addr_any;
|
||||
inp->inp_lport = 0;
|
||||
return (EAGAIN);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform old in6_pcbconnect() into an inner subroutine for new
|
||||
* in6_pcbconnect(): Do some validity-checking on the remote
|
||||
* address (in mbuf 'nam') and then determine local host address
|
||||
* (i.e., which interface) to use to access that remote host.
|
||||
*
|
||||
* This preserves definition of in6_pcbconnect(), while supporting a
|
||||
* slightly different version for T/TCP. (This is more than
|
||||
* a bit of a kludge, but cleaning up the internal interfaces would
|
||||
* have forced minor changes in every protocol).
|
||||
*/
|
||||
int
|
||||
in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
|
||||
struct in6_addr *plocal_addr6)
|
||||
{
|
||||
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
|
||||
int error = 0;
|
||||
struct ifnet *ifp = NULL;
|
||||
int scope_ambiguous = 0;
|
||||
struct in6_addr in6a;
|
||||
|
||||
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
|
||||
if (nam->sa_len != sizeof (*sin6))
|
||||
return (EINVAL);
|
||||
if (sin6->sin6_family != AF_INET6)
|
||||
return (EAFNOSUPPORT);
|
||||
if (sin6->sin6_port == 0)
|
||||
return (EADDRNOTAVAIL);
|
||||
|
||||
if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone)
|
||||
scope_ambiguous = 1;
|
||||
if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0)
|
||||
return(error);
|
||||
|
||||
if (!TAILQ_EMPTY(&V_in6_ifaddrhead)) {
|
||||
/*
|
||||
* If the destination address is UNSPECIFIED addr,
|
||||
* use the loopback addr, e.g ::1.
|
||||
*/
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
|
||||
sin6->sin6_addr = in6addr_loopback;
|
||||
}
|
||||
if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
|
||||
return (error);
|
||||
|
||||
error = in6_selectsrc(sin6, inp->in6p_outputopts,
|
||||
inp, NULL, inp->inp_cred, &ifp, &in6a);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (ifp && scope_ambiguous &&
|
||||
(error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {
|
||||
return(error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not update this earlier, in case we return with an error.
|
||||
*
|
||||
* XXX: this in6_selectsrc result might replace the bound local
|
||||
* address with the address specified by setsockopt(IPV6_PKTINFO).
|
||||
* Is it the intended behavior?
|
||||
*/
|
||||
*plocal_addr6 = in6a;
|
||||
|
||||
/*
|
||||
* Don't do pcblookup call here; return interface in
|
||||
* plocal_addr6
|
||||
* and exit to caller, that will do the lookup.
|
||||
*/
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Outer subroutine:
|
||||
* Connect from a socket to a specified address.
|
||||
* Both address and port must be specified in argument sin.
|
||||
* If don't have a local address for this socket yet,
|
||||
* then pick one.
|
||||
*/
|
||||
int
|
||||
in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
|
||||
struct ucred *cred)
|
||||
{
|
||||
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
|
||||
struct in6_addr addr6;
|
||||
int error;
|
||||
|
||||
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
|
||||
/*
|
||||
* Call inner routine, to assign local interface address.
|
||||
* in6_pcbladdr() may automatically fill in sin6_scope_id.
|
||||
*/
|
||||
if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
|
||||
return (error);
|
||||
|
||||
if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
|
||||
sin6->sin6_port,
|
||||
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
|
||||
? &addr6 : &inp->in6p_laddr,
|
||||
inp->inp_lport, 0, NULL) != NULL) {
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
|
||||
if (inp->inp_lport == 0) {
|
||||
error = in6_pcbbind(inp, (struct sockaddr *)0, cred);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
inp->in6p_laddr = addr6;
|
||||
}
|
||||
inp->in6p_faddr = sin6->sin6_addr;
|
||||
inp->inp_fport = sin6->sin6_port;
|
||||
/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
|
||||
inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
|
||||
if (inp->inp_flags & IN6P_AUTOFLOWLABEL)
|
||||
inp->inp_flow |=
|
||||
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
|
||||
|
||||
in_pcbrehash(inp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
in6_pcbdisconnect(struct inpcb *inp)
|
||||
{
|
||||
|
||||
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
|
||||
bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
|
||||
inp->inp_fport = 0;
|
||||
/* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
|
||||
inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
|
||||
in_pcbrehash(inp);
|
||||
}
|
||||
|
||||
struct sockaddr *
|
||||
in6_sockaddr(in_port_t port, struct in6_addr *addr_p)
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = malloc(sizeof *sin6, M_SONAME, M_WAITOK);
|
||||
bzero(sin6, sizeof *sin6);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_len = sizeof(*sin6);
|
||||
sin6->sin6_port = port;
|
||||
sin6->sin6_addr = *addr_p;
|
||||
(void)sa6_recoverscope(sin6); /* XXX: should catch errors */
|
||||
|
||||
return (struct sockaddr *)sin6;
|
||||
}
|
||||
|
||||
struct sockaddr *
|
||||
in6_v4mapsin6_sockaddr(in_port_t port, struct in_addr *addr_p)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 *sin6_p;
|
||||
|
||||
bzero(&sin, sizeof sin);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_port = port;
|
||||
sin.sin_addr = *addr_p;
|
||||
|
||||
sin6_p = malloc(sizeof *sin6_p, M_SONAME,
|
||||
M_WAITOK);
|
||||
in6_sin_2_v4mapsin6(&sin, sin6_p);
|
||||
|
||||
return (struct sockaddr *)sin6_p;
|
||||
}
|
||||
|
||||
int
|
||||
in6_getsockaddr(struct socket *so, struct sockaddr **nam)
|
||||
{
|
||||
register struct inpcb *inp;
|
||||
struct in6_addr addr;
|
||||
in_port_t port;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("in6_getsockaddr: inp == NULL"));
|
||||
|
||||
INP_RLOCK(inp);
|
||||
port = inp->inp_lport;
|
||||
addr = inp->in6p_laddr;
|
||||
INP_RUNLOCK(inp);
|
||||
|
||||
*nam = in6_sockaddr(port, &addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
in6_getpeeraddr(struct socket *so, struct sockaddr **nam)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
struct in6_addr addr;
|
||||
in_port_t port;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("in6_getpeeraddr: inp == NULL"));
|
||||
|
||||
INP_RLOCK(inp);
|
||||
port = inp->inp_fport;
|
||||
addr = inp->in6p_faddr;
|
||||
INP_RUNLOCK(inp);
|
||||
|
||||
*nam = in6_sockaddr(port, &addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int error;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("in6_mapped_sockaddr: inp == NULL"));
|
||||
|
||||
if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) {
|
||||
error = in_getsockaddr(so, nam);
|
||||
if (error == 0)
|
||||
in6_sin_2_v4mapsin6_in_sock(nam);
|
||||
} else {
|
||||
/* scope issues will be handled in in6_getsockaddr(). */
|
||||
error = in6_getsockaddr(so, nam);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int error;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("in6_mapped_peeraddr: inp == NULL"));
|
||||
|
||||
if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) {
|
||||
error = in_getpeeraddr(so, nam);
|
||||
if (error == 0)
|
||||
in6_sin_2_v4mapsin6_in_sock(nam);
|
||||
} else
|
||||
/* scope issues will be handled in in6_getpeeraddr(). */
|
||||
error = in6_getpeeraddr(so, nam);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass some notification to all connections of a protocol
|
||||
* associated with address dst. The local address and/or port numbers
|
||||
* may be specified to limit the search. The "usual action" will be
|
||||
* taken, depending on the ctlinput cmd. The caller must filter any
|
||||
* cmds that are uninteresting (e.g., no error in the map).
|
||||
* Call the protocol specific routine (if any) to report
|
||||
* any errors for each matching socket.
|
||||
*/
|
||||
void
|
||||
in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
|
||||
u_int fport_arg, const struct sockaddr *src, u_int lport_arg,
|
||||
int cmd, void *cmdarg,
|
||||
struct inpcb *(*notify)(struct inpcb *, int))
|
||||
{
|
||||
struct inpcb *inp, *inp_temp;
|
||||
struct sockaddr_in6 sa6_src, *sa6_dst;
|
||||
u_short fport = fport_arg, lport = lport_arg;
|
||||
u_int32_t flowinfo;
|
||||
int errno;
|
||||
|
||||
if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6)
|
||||
return;
|
||||
|
||||
sa6_dst = (struct sockaddr_in6 *)dst;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
|
||||
return;
|
||||
|
||||
/*
|
||||
* note that src can be NULL when we get notify by local fragmentation.
|
||||
*/
|
||||
sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src;
|
||||
flowinfo = sa6_src.sin6_flowinfo;
|
||||
|
||||
/*
|
||||
* Redirects go to all references to the destination,
|
||||
* and use in6_rtchange to invalidate the route cache.
|
||||
* Dead host indications: also use in6_rtchange to invalidate
|
||||
* the cache, and deliver the error to all the sockets.
|
||||
* Otherwise, if we have knowledge of the local port and address,
|
||||
* deliver only to that socket.
|
||||
*/
|
||||
if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
|
||||
fport = 0;
|
||||
lport = 0;
|
||||
bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
|
||||
|
||||
if (cmd != PRC_HOSTDEAD)
|
||||
notify = in6_rtchange;
|
||||
}
|
||||
errno = inet6ctlerrmap[cmd];
|
||||
INP_INFO_WLOCK(pcbinfo);
|
||||
LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
|
||||
INP_WLOCK(inp);
|
||||
if ((inp->inp_vflag & INP_IPV6) == 0) {
|
||||
INP_WUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the error designates a new path MTU for a destination
|
||||
* and the application (associated with this socket) wanted to
|
||||
* know the value, notify. Note that we notify for all
|
||||
* disconnected sockets if the corresponding application
|
||||
* wanted. This is because some UDP applications keep sending
|
||||
* sockets disconnected.
|
||||
* XXX: should we avoid to notify the value to TCP sockets?
|
||||
*/
|
||||
if (cmd == PRC_MSGSIZE && (inp->inp_flags & IN6P_MTU) != 0 &&
|
||||
(IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
|
||||
IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &sa6_dst->sin6_addr))) {
|
||||
ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst,
|
||||
(u_int32_t *)cmdarg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect if we should notify the error. If no source and
|
||||
* destination ports are specifed, but non-zero flowinfo and
|
||||
* local address match, notify the error. This is the case
|
||||
* when the error is delivered with an encrypted buffer
|
||||
* by ESP. Otherwise, just compare addresses and ports
|
||||
* as usual.
|
||||
*/
|
||||
if (lport == 0 && fport == 0 && flowinfo &&
|
||||
inp->inp_socket != NULL &&
|
||||
flowinfo == (inp->inp_flow & IPV6_FLOWLABEL_MASK) &&
|
||||
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
|
||||
goto do_notify;
|
||||
else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
|
||||
&sa6_dst->sin6_addr) ||
|
||||
inp->inp_socket == 0 ||
|
||||
(lport && inp->inp_lport != lport) ||
|
||||
(!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
|
||||
!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
|
||||
&sa6_src.sin6_addr)) ||
|
||||
(fport && inp->inp_fport != fport)) {
|
||||
INP_WUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
|
||||
do_notify:
|
||||
if (notify) {
|
||||
if ((*notify)(inp, errno))
|
||||
INP_WUNLOCK(inp);
|
||||
} else
|
||||
INP_WUNLOCK(inp);
|
||||
}
|
||||
INP_INFO_WUNLOCK(pcbinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a PCB based on the local address and port.
|
||||
*/
|
||||
struct inpcb *
|
||||
in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
|
||||
u_short lport, int wild_okay, struct ucred *cred)
|
||||
{
|
||||
register struct inpcb *inp;
|
||||
int matchwild = 3, wildcard;
|
||||
|
||||
INP_INFO_WLOCK_ASSERT(pcbinfo);
|
||||
|
||||
if (!wild_okay) {
|
||||
struct inpcbhead *head;
|
||||
/*
|
||||
* Look for an unconnected (wildcard foreign addr) PCB that
|
||||
* matches the local address and port we're looking for.
|
||||
*/
|
||||
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
|
||||
0, pcbinfo->ipi_hashmask)];
|
||||
LIST_FOREACH(inp, head, inp_hash) {
|
||||
/* XXX inp locking */
|
||||
if ((inp->inp_vflag & INP_IPV6) == 0)
|
||||
continue;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
|
||||
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
|
||||
inp->inp_lport == lport) {
|
||||
/* Found. */
|
||||
if (cred == NULL ||
|
||||
prison_equal_ip6(cred->cr_prison,
|
||||
inp->inp_cred->cr_prison))
|
||||
return (inp);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Not found.
|
||||
*/
|
||||
return (NULL);
|
||||
} else {
|
||||
struct inpcbporthead *porthash;
|
||||
struct inpcbport *phd;
|
||||
struct inpcb *match = NULL;
|
||||
/*
|
||||
* Best fit PCB lookup.
|
||||
*
|
||||
* First see if this local port is in use by looking on the
|
||||
* port hash list.
|
||||
*/
|
||||
porthash = &pcbinfo->ipi_porthashbase[INP_PCBPORTHASH(lport,
|
||||
pcbinfo->ipi_porthashmask)];
|
||||
LIST_FOREACH(phd, porthash, phd_hash) {
|
||||
if (phd->phd_port == lport)
|
||||
break;
|
||||
}
|
||||
if (phd != NULL) {
|
||||
/*
|
||||
* Port is in use by one or more PCBs. Look for best
|
||||
* fit.
|
||||
*/
|
||||
LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
|
||||
wildcard = 0;
|
||||
if (cred != NULL &&
|
||||
!prison_equal_ip6(cred->cr_prison,
|
||||
inp->inp_cred->cr_prison))
|
||||
continue;
|
||||
/* XXX inp locking */
|
||||
if ((inp->inp_vflag & INP_IPV6) == 0)
|
||||
continue;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
|
||||
wildcard++;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(
|
||||
&inp->in6p_laddr)) {
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(laddr))
|
||||
wildcard++;
|
||||
else if (!IN6_ARE_ADDR_EQUAL(
|
||||
&inp->in6p_laddr, laddr))
|
||||
continue;
|
||||
} else {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
|
||||
wildcard++;
|
||||
}
|
||||
if (wildcard < matchwild) {
|
||||
match = inp;
|
||||
matchwild = wildcard;
|
||||
if (matchwild == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (match);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
|
||||
{
|
||||
struct inpcb *in6p;
|
||||
struct ip6_moptions *im6o;
|
||||
int i, gap;
|
||||
|
||||
INP_INFO_RLOCK(pcbinfo);
|
||||
LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
|
||||
INP_WLOCK(in6p);
|
||||
im6o = in6p->in6p_moptions;
|
||||
if ((in6p->inp_vflag & INP_IPV6) && im6o != NULL) {
|
||||
/*
|
||||
* Unselect the outgoing ifp for multicast if it
|
||||
* is being detached.
|
||||
*/
|
||||
if (im6o->im6o_multicast_ifp == ifp)
|
||||
im6o->im6o_multicast_ifp = NULL;
|
||||
/*
|
||||
* Drop multicast group membership if we joined
|
||||
* through the interface being detached.
|
||||
*/
|
||||
gap = 0;
|
||||
for (i = 0; i < im6o->im6o_num_memberships; i++) {
|
||||
if (im6o->im6o_membership[i]->in6m_ifp ==
|
||||
ifp) {
|
||||
in6_mc_leave(im6o->im6o_membership[i],
|
||||
NULL);
|
||||
gap++;
|
||||
} else if (gap != 0) {
|
||||
im6o->im6o_membership[i - gap] =
|
||||
im6o->im6o_membership[i];
|
||||
}
|
||||
}
|
||||
im6o->im6o_num_memberships -= gap;
|
||||
}
|
||||
INP_WUNLOCK(in6p);
|
||||
}
|
||||
INP_INFO_RUNLOCK(pcbinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for alternatives when higher level complains
|
||||
* about service problems. For now, invalidate cached
|
||||
* routing information. If the route was created dynamically
|
||||
* (by a redirect), time to try a default gateway again.
|
||||
*/
|
||||
void
|
||||
in6_losing(struct inpcb *in6p)
|
||||
{
|
||||
|
||||
/*
|
||||
* We don't store route pointers in the routing table anymore
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* After a routing change, flush old routing
|
||||
* and allocate a (hopefully) better one.
|
||||
*/
|
||||
struct inpcb *
|
||||
in6_rtchange(struct inpcb *inp, int errno)
|
||||
{
|
||||
/*
|
||||
* We don't store route pointers in the routing table anymore
|
||||
*/
|
||||
return inp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup PCB in hash list.
|
||||
*/
|
||||
struct inpcb *
|
||||
in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
|
||||
u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, int wildcard,
|
||||
struct ifnet *ifp)
|
||||
{
|
||||
struct inpcbhead *head;
|
||||
struct inpcb *inp, *tmpinp;
|
||||
u_short fport = fport_arg, lport = lport_arg;
|
||||
int faith;
|
||||
|
||||
INP_INFO_LOCK_ASSERT(pcbinfo);
|
||||
|
||||
if (faithprefix_p != NULL)
|
||||
faith = (*faithprefix_p)(laddr);
|
||||
else
|
||||
faith = 0;
|
||||
|
||||
/*
|
||||
* First look for an exact match.
|
||||
*/
|
||||
tmpinp = NULL;
|
||||
head = &pcbinfo->ipi_hashbase[
|
||||
INP_PCBHASH(faddr->s6_addr32[3] /* XXX */, lport, fport,
|
||||
pcbinfo->ipi_hashmask)];
|
||||
LIST_FOREACH(inp, head, inp_hash) {
|
||||
/* XXX inp locking */
|
||||
if ((inp->inp_vflag & INP_IPV6) == 0)
|
||||
continue;
|
||||
if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
|
||||
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
|
||||
inp->inp_fport == fport &&
|
||||
inp->inp_lport == lport) {
|
||||
/*
|
||||
* XXX We should be able to directly return
|
||||
* the inp here, without any checks.
|
||||
* Well unless both bound with SO_REUSEPORT?
|
||||
*/
|
||||
if (prison_flag(inp->inp_cred, PR_IP6))
|
||||
return (inp);
|
||||
if (tmpinp == NULL)
|
||||
tmpinp = inp;
|
||||
}
|
||||
}
|
||||
if (tmpinp != NULL)
|
||||
return (tmpinp);
|
||||
|
||||
/*
|
||||
* Then look for a wildcard match, if requested.
|
||||
*/
|
||||
if (wildcard == INPLOOKUP_WILDCARD) {
|
||||
struct inpcb *local_wild = NULL, *local_exact = NULL;
|
||||
struct inpcb *jail_wild = NULL;
|
||||
int injail;
|
||||
|
||||
/*
|
||||
* Order of socket selection - we always prefer jails.
|
||||
* 1. jailed, non-wild.
|
||||
* 2. jailed, wild.
|
||||
* 3. non-jailed, non-wild.
|
||||
* 4. non-jailed, wild.
|
||||
*/
|
||||
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
|
||||
0, pcbinfo->ipi_hashmask)];
|
||||
LIST_FOREACH(inp, head, inp_hash) {
|
||||
/* XXX inp locking */
|
||||
if ((inp->inp_vflag & INP_IPV6) == 0)
|
||||
continue;
|
||||
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
|
||||
inp->inp_lport != lport) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* XXX inp locking */
|
||||
if (faith && (inp->inp_flags & INP_FAITH) == 0)
|
||||
continue;
|
||||
|
||||
injail = prison_flag(inp->inp_cred, PR_IP6);
|
||||
if (injail) {
|
||||
if (prison_check_ip6(inp->inp_cred,
|
||||
laddr) != 0)
|
||||
continue;
|
||||
} else {
|
||||
if (local_exact != NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr)) {
|
||||
if (injail)
|
||||
return (inp);
|
||||
else
|
||||
local_exact = inp;
|
||||
} else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
|
||||
if (injail)
|
||||
jail_wild = inp;
|
||||
else
|
||||
local_wild = inp;
|
||||
}
|
||||
} /* LIST_FOREACH */
|
||||
|
||||
if (jail_wild != NULL)
|
||||
return (jail_wild);
|
||||
if (local_exact != NULL)
|
||||
return (local_exact);
|
||||
if (local_wild != NULL)
|
||||
return (local_wild);
|
||||
} /* if (wildcard == INPLOOKUP_WILDCARD) */
|
||||
|
||||
/*
|
||||
* Not found.
|
||||
*/
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
|
||||
{
|
||||
struct ip6_hdr *ip;
|
||||
|
||||
ip = mtod(m, struct ip6_hdr *);
|
||||
bzero(sin6, sizeof(*sin6));
|
||||
sin6->sin6_len = sizeof(*sin6);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_addr = ip->ip6_src;
|
||||
|
||||
(void)sa6_recoverscope(sin6); /* XXX: should catch errors... */
|
||||
|
||||
return;
|
||||
}
|
109
freebsd/netinet6/in6_pcb.h
Normal file
109
freebsd/netinet6/in6_pcb.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_pcb.h,v 1.13 2001/02/06 09:16:53 itojun Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)in_pcb.h 8.1 (Berkeley) 6/10/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IN6_PCB_HH_
|
||||
#define _NETINET6_IN6_PCB_HH_
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
|
||||
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
|
||||
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
|
||||
|
||||
void in6_pcbpurgeif0 __P((struct inpcbinfo *, struct ifnet *));
|
||||
void in6_losing __P((struct inpcb *));
|
||||
int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct ucred *));
|
||||
int in6_pcbconnect __P((struct inpcb *, struct sockaddr *, struct ucred *));
|
||||
void in6_pcbdisconnect __P((struct inpcb *));
|
||||
int in6_pcbladdr(struct inpcb *, struct sockaddr *, struct in6_addr *);
|
||||
struct inpcb *
|
||||
in6_pcblookup_local __P((struct inpcbinfo *,
|
||||
struct in6_addr *, u_short, int,
|
||||
struct ucred *));
|
||||
struct inpcb *
|
||||
in6_pcblookup_hash __P((struct inpcbinfo *,
|
||||
struct in6_addr *, u_int, struct in6_addr *,
|
||||
u_int, int, struct ifnet *));
|
||||
void in6_pcbnotify __P((struct inpcbinfo *, struct sockaddr *,
|
||||
u_int, const struct sockaddr *, u_int, int, void *,
|
||||
struct inpcb *(*)(struct inpcb *, int)));
|
||||
#ifndef __rtems__
|
||||
struct inpcb *
|
||||
in6_rtchange __P((struct inpcb *, int));
|
||||
#else
|
||||
struct inpcb *
|
||||
in6_rtchange(struct inpcb *inp, int errno);
|
||||
#endif
|
||||
struct sockaddr *
|
||||
in6_sockaddr __P((in_port_t port, struct in6_addr *addr_p));
|
||||
struct sockaddr *
|
||||
in6_v4mapsin6_sockaddr __P((in_port_t port, struct in_addr *addr_p));
|
||||
int in6_getpeeraddr __P((struct socket *so, struct sockaddr **nam));
|
||||
int in6_getsockaddr __P((struct socket *so, struct sockaddr **nam));
|
||||
int in6_mapped_sockaddr __P((struct socket *so, struct sockaddr **nam));
|
||||
int in6_mapped_peeraddr __P((struct socket *so, struct sockaddr **nam));
|
||||
int in6_selecthlim __P((struct in6pcb *, struct ifnet *));
|
||||
int in6_pcbsetport __P((struct in6_addr *, struct inpcb *, struct ucred *));
|
||||
void init_sin6 __P((struct sockaddr_in6 *sin6, struct mbuf *m));
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_NETINET6_IN6_PCB_HH_ */
|
597
freebsd/netinet6/in6_proto.c
Normal file
597
freebsd/netinet6/in6_proto.c
Normal file
@@ -0,0 +1,597 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_proto.c,v 1.91 2001/05/27 13:28:35 itojun Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)in_proto.c 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_inet.h>
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
#include <rtems/freebsd/local/opt_ipsec.h>
|
||||
#include <rtems/freebsd/local/opt_ipstealth.h>
|
||||
#include <rtems/freebsd/local/opt_sctp.h>
|
||||
#include <rtems/freebsd/local/opt_mpath.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/socketvar.h>
|
||||
#include <rtems/freebsd/sys/proc.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/jail.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/domain.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/sysctl.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/radix.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
#ifdef RADIX_MPATH
|
||||
#include <rtems/freebsd/net/radix_mpath.h>
|
||||
#endif
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_systm.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/ip_encap.h>
|
||||
#include <rtems/freebsd/netinet/ip.h>
|
||||
#include <rtems/freebsd/netinet/ip_var.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet/icmp6.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/tcp.h>
|
||||
#include <rtems/freebsd/netinet/tcp_timer.h>
|
||||
#include <rtems/freebsd/netinet/tcp_var.h>
|
||||
#include <rtems/freebsd/netinet/udp.h>
|
||||
#include <rtems/freebsd/netinet/udp_var.h>
|
||||
#include <rtems/freebsd/netinet6/tcp6_var.h>
|
||||
#include <rtems/freebsd/netinet6/raw_ip6.h>
|
||||
#include <rtems/freebsd/netinet6/udp6_var.h>
|
||||
#include <rtems/freebsd/netinet6/pim6_var.h>
|
||||
#include <rtems/freebsd/netinet6/nd6.h>
|
||||
|
||||
#ifdef SCTP
|
||||
#include <rtems/freebsd/netinet/in_pcb.h>
|
||||
#include <rtems/freebsd/netinet/sctp_pcb.h>
|
||||
#include <rtems/freebsd/netinet/sctp.h>
|
||||
#include <rtems/freebsd/netinet/sctp_var.h>
|
||||
#include <rtems/freebsd/netinet6/sctp6_var.h>
|
||||
#endif /* SCTP */
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <rtems/freebsd/netipsec/ipsec.h>
|
||||
#include <rtems/freebsd/netipsec/ipsec6.h>
|
||||
#endif /* IPSEC */
|
||||
|
||||
#include <rtems/freebsd/netinet6/ip6protosw.h>
|
||||
|
||||
/*
|
||||
* TCP/IP protocol family: IP6, ICMP6, UDP, TCP.
|
||||
*/
|
||||
|
||||
extern struct domain inet6domain;
|
||||
static struct pr_usrreqs nousrreqs;
|
||||
|
||||
#define PR_LISTEN 0
|
||||
#define PR_ABRTACPTDIS 0
|
||||
|
||||
/* Spacer for loadable protocols. */
|
||||
#define IP6PROTOSPACER \
|
||||
{ \
|
||||
.pr_domain = &inet6domain, \
|
||||
.pr_protocol = PROTO_SPACER, \
|
||||
.pr_usrreqs = &nousrreqs \
|
||||
}
|
||||
|
||||
struct ip6protosw inet6sw[] = {
|
||||
{
|
||||
.pr_type = 0,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_IPV6,
|
||||
.pr_init = ip6_init,
|
||||
#ifdef VIMAGE
|
||||
.pr_destroy = ip6_destroy,
|
||||
#endif
|
||||
.pr_slowtimo = frag6_slowtimo,
|
||||
.pr_drain = frag6_drain,
|
||||
.pr_usrreqs = &nousrreqs,
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_DGRAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_UDP,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = udp6_input,
|
||||
.pr_ctlinput = udp6_ctlinput,
|
||||
.pr_ctloutput = ip6_ctloutput,
|
||||
.pr_usrreqs = &udp6_usrreqs,
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_STREAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_TCP,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN,
|
||||
.pr_input = tcp6_input,
|
||||
.pr_ctlinput = tcp6_ctlinput,
|
||||
.pr_ctloutput = tcp_ctloutput,
|
||||
#ifndef INET /* don't call initialization and timeout routines twice */
|
||||
.pr_init = tcp_init,
|
||||
.pr_slowtimo = tcp_slowtimo,
|
||||
#endif
|
||||
.pr_drain = tcp_drain,
|
||||
.pr_usrreqs = &tcp6_usrreqs,
|
||||
},
|
||||
#ifdef SCTP
|
||||
{
|
||||
.pr_type = SOCK_DGRAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_SCTP,
|
||||
.pr_flags = PR_WANTRCVD,
|
||||
.pr_input = sctp6_input,
|
||||
.pr_ctlinput = sctp6_ctlinput,
|
||||
.pr_ctloutput = sctp_ctloutput,
|
||||
.pr_drain = sctp_drain,
|
||||
.pr_usrreqs = &sctp6_usrreqs
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_SEQPACKET,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_SCTP,
|
||||
.pr_flags = PR_WANTRCVD,
|
||||
.pr_input = sctp6_input,
|
||||
.pr_ctlinput = sctp6_ctlinput,
|
||||
.pr_ctloutput = sctp_ctloutput,
|
||||
.pr_drain = sctp_drain,
|
||||
.pr_usrreqs = &sctp6_usrreqs
|
||||
},
|
||||
|
||||
{
|
||||
.pr_type = SOCK_STREAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_SCTP,
|
||||
.pr_flags = PR_WANTRCVD,
|
||||
.pr_input = sctp6_input,
|
||||
.pr_ctlinput = sctp6_ctlinput,
|
||||
.pr_ctloutput = sctp_ctloutput,
|
||||
.pr_drain = sctp_drain,
|
||||
.pr_usrreqs = &sctp6_usrreqs
|
||||
},
|
||||
#endif /* SCTP */
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_RAW,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = rip6_input,
|
||||
.pr_output = rip6_output,
|
||||
.pr_ctlinput = rip6_ctlinput,
|
||||
.pr_ctloutput = rip6_ctloutput,
|
||||
.pr_usrreqs = &rip6_usrreqs
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_ICMPV6,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
|
||||
.pr_input = icmp6_input,
|
||||
.pr_output = rip6_output,
|
||||
.pr_ctlinput = rip6_ctlinput,
|
||||
.pr_ctloutput = rip6_ctloutput,
|
||||
.pr_fasttimo = icmp6_fasttimo,
|
||||
.pr_slowtimo = icmp6_slowtimo,
|
||||
.pr_usrreqs = &rip6_usrreqs
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_DSTOPTS,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = dest6_input,
|
||||
.pr_usrreqs = &nousrreqs
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_ROUTING,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = route6_input,
|
||||
.pr_usrreqs = &nousrreqs
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_FRAGMENT,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = frag6_input,
|
||||
.pr_usrreqs = &nousrreqs
|
||||
},
|
||||
#ifdef IPSEC
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_AH,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = ipsec6_common_input,
|
||||
.pr_usrreqs = &nousrreqs,
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_ESP,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = ipsec6_common_input,
|
||||
.pr_ctlinput = esp6_ctlinput,
|
||||
.pr_usrreqs = &nousrreqs,
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_IPCOMP,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = ipsec6_common_input,
|
||||
.pr_usrreqs = &nousrreqs,
|
||||
},
|
||||
#endif /* IPSEC */
|
||||
#ifdef INET
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_IPV4,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
|
||||
.pr_input = encap6_input,
|
||||
.pr_output = rip6_output,
|
||||
.pr_ctloutput = rip6_ctloutput,
|
||||
.pr_init = encap_init,
|
||||
.pr_usrreqs = &rip6_usrreqs
|
||||
},
|
||||
#endif /* INET */
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_IPV6,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
|
||||
.pr_input = encap6_input,
|
||||
.pr_output = rip6_output,
|
||||
.pr_ctloutput = rip6_ctloutput,
|
||||
.pr_init = encap_init,
|
||||
.pr_usrreqs = &rip6_usrreqs
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_PIM,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
|
||||
.pr_input = encap6_input,
|
||||
.pr_output = rip6_output,
|
||||
.pr_ctloutput = rip6_ctloutput,
|
||||
.pr_usrreqs = &rip6_usrreqs
|
||||
},
|
||||
/* Spacer n-times for loadable protocols. */
|
||||
IP6PROTOSPACER,
|
||||
IP6PROTOSPACER,
|
||||
IP6PROTOSPACER,
|
||||
IP6PROTOSPACER,
|
||||
IP6PROTOSPACER,
|
||||
IP6PROTOSPACER,
|
||||
IP6PROTOSPACER,
|
||||
IP6PROTOSPACER,
|
||||
/* raw wildcard */
|
||||
{
|
||||
.pr_type = SOCK_RAW,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_input = rip6_input,
|
||||
.pr_output = rip6_output,
|
||||
.pr_ctloutput = rip6_ctloutput,
|
||||
.pr_usrreqs = &rip6_usrreqs
|
||||
},
|
||||
};
|
||||
|
||||
extern int in6_inithead(void **, int);
|
||||
#ifdef VIMAGE
|
||||
extern int in6_detachhead(void **, int);
|
||||
#endif
|
||||
|
||||
struct domain inet6domain = {
|
||||
.dom_family = AF_INET6,
|
||||
.dom_name = "internet6",
|
||||
.dom_protosw = (struct protosw *)inet6sw,
|
||||
.dom_protoswNPROTOSW = (struct protosw *)
|
||||
&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])],
|
||||
#ifdef RADIX_MPATH
|
||||
.dom_rtattach = rn6_mpath_inithead,
|
||||
#else
|
||||
.dom_rtattach = in6_inithead,
|
||||
#endif
|
||||
#ifdef VIMAGE
|
||||
.dom_rtdetach = in6_detachhead,
|
||||
#endif
|
||||
.dom_rtoffset = offsetof(struct sockaddr_in6, sin6_addr) << 3,
|
||||
.dom_maxrtkey = sizeof(struct sockaddr_in6),
|
||||
.dom_ifattach = in6_domifattach,
|
||||
.dom_ifdetach = in6_domifdetach
|
||||
};
|
||||
|
||||
VNET_DOMAIN_SET(inet6);
|
||||
|
||||
/*
|
||||
* Internet configuration info
|
||||
*/
|
||||
#ifndef IPV6FORWARDING
|
||||
#ifdef GATEWAY6
|
||||
#define IPV6FORWARDING 1 /* forward IP6 packets not for us */
|
||||
#else
|
||||
#define IPV6FORWARDING 0 /* don't forward IP6 packets not for us */
|
||||
#endif /* GATEWAY6 */
|
||||
#endif /* !IPV6FORWARDING */
|
||||
|
||||
#ifndef IPV6_SENDREDIRECTS
|
||||
#define IPV6_SENDREDIRECTS 1
|
||||
#endif
|
||||
|
||||
VNET_DEFINE(int, ip6_forwarding) = IPV6FORWARDING; /* act as router? */
|
||||
VNET_DEFINE(int, ip6_sendredirects) = IPV6_SENDREDIRECTS;
|
||||
VNET_DEFINE(int, ip6_defhlim) = IPV6_DEFHLIM;
|
||||
VNET_DEFINE(int, ip6_defmcasthlim) = IPV6_DEFAULT_MULTICAST_HOPS;
|
||||
VNET_DEFINE(int, ip6_accept_rtadv) = 0;
|
||||
VNET_DEFINE(int, ip6_maxfragpackets); /* initialized in frag6.c:frag6_init() */
|
||||
VNET_DEFINE(int, ip6_maxfrags); /* initialized in frag6.c:frag6_init() */
|
||||
VNET_DEFINE(int, ip6_log_interval) = 5;
|
||||
VNET_DEFINE(int, ip6_hdrnestlimit) = 15;/* How many header options will we
|
||||
* process? */
|
||||
VNET_DEFINE(int, ip6_dad_count) = 1; /* DupAddrDetectionTransmits */
|
||||
VNET_DEFINE(int, ip6_auto_flowlabel) = 1;
|
||||
VNET_DEFINE(int, ip6_use_deprecated) = 1;/* allow deprecated addr
|
||||
* (RFC2462 5.5.4) */
|
||||
VNET_DEFINE(int, ip6_rr_prune) = 5; /* router renumbering prefix
|
||||
* walk list every 5 sec. */
|
||||
VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */
|
||||
VNET_DEFINE(int, ip6_v6only) = 1;
|
||||
|
||||
VNET_DEFINE(int, ip6_keepfaith) = 0;
|
||||
VNET_DEFINE(time_t, ip6_log_time) = (time_t)0L;
|
||||
#ifdef IPSTEALTH
|
||||
VNET_DEFINE(int, ip6stealth) = 0;
|
||||
#endif
|
||||
VNET_DEFINE(int, nd6_onlink_ns_rfc4861) = 0;/* allow 'on-link' nd6 NS
|
||||
* (RFC 4861) */
|
||||
|
||||
/* icmp6 */
|
||||
/*
|
||||
* BSDI4 defines these variables in in_proto.c...
|
||||
* XXX: what if we don't define INET? Should we define pmtu6_expire
|
||||
* or so? (jinmei@kame.net 19990310)
|
||||
*/
|
||||
VNET_DEFINE(int, pmtu_expire) = 60*10;
|
||||
VNET_DEFINE(int, pmtu_probe) = 60*2;
|
||||
|
||||
/* raw IP6 parameters */
|
||||
/*
|
||||
* Nominal space allocated to a raw ip socket.
|
||||
*/
|
||||
#define RIPV6SNDQ 8192
|
||||
#define RIPV6RCVQ 8192
|
||||
|
||||
VNET_DEFINE(u_long, rip6_sendspace) = RIPV6SNDQ;
|
||||
VNET_DEFINE(u_long, rip6_recvspace) = RIPV6RCVQ;
|
||||
|
||||
/* ICMPV6 parameters */
|
||||
VNET_DEFINE(int, icmp6_rediraccept) = 1;/* accept and process redirects */
|
||||
VNET_DEFINE(int, icmp6_redirtimeout) = 10 * 60; /* 10 minutes */
|
||||
VNET_DEFINE(int, icmp6errppslim) = 100; /* 100pps */
|
||||
/* control how to respond to NI queries */
|
||||
VNET_DEFINE(int, icmp6_nodeinfo) =
|
||||
(ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK);
|
||||
|
||||
/* UDP on IP6 parameters */
|
||||
VNET_DEFINE(int, udp6_sendspace) = 9216;/* really max datagram size */
|
||||
VNET_DEFINE(int, udp6_recvspace) = 40 * (1024 + sizeof(struct sockaddr_in6));
|
||||
/* 40 1K datagrams */
|
||||
|
||||
/*
|
||||
* sysctl related items.
|
||||
*/
|
||||
SYSCTL_NODE(_net, PF_INET6, inet6, CTLFLAG_RW, 0,
|
||||
"Internet6 Family");
|
||||
|
||||
/* net.inet6 */
|
||||
SYSCTL_NODE(_net_inet6, IPPROTO_IPV6, ip6, CTLFLAG_RW, 0, "IP6");
|
||||
SYSCTL_NODE(_net_inet6, IPPROTO_ICMPV6, icmp6, CTLFLAG_RW, 0, "ICMP6");
|
||||
SYSCTL_NODE(_net_inet6, IPPROTO_UDP, udp6, CTLFLAG_RW, 0, "UDP6");
|
||||
SYSCTL_NODE(_net_inet6, IPPROTO_TCP, tcp6, CTLFLAG_RW, 0, "TCP6");
|
||||
#ifdef SCTP
|
||||
SYSCTL_NODE(_net_inet6, IPPROTO_SCTP, sctp6, CTLFLAG_RW, 0, "SCTP6");
|
||||
#endif
|
||||
#ifdef IPSEC
|
||||
SYSCTL_NODE(_net_inet6, IPPROTO_ESP, ipsec6, CTLFLAG_RW, 0, "IPSEC6");
|
||||
#endif /* IPSEC */
|
||||
|
||||
/* net.inet6.ip6 */
|
||||
static int
|
||||
sysctl_ip6_temppltime(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error = 0;
|
||||
int old;
|
||||
|
||||
VNET_SYSCTL_ARG(req, arg1);
|
||||
|
||||
error = SYSCTL_OUT(req, arg1, sizeof(int));
|
||||
if (error || !req->newptr)
|
||||
return (error);
|
||||
old = V_ip6_temp_preferred_lifetime;
|
||||
error = SYSCTL_IN(req, arg1, sizeof(int));
|
||||
if (V_ip6_temp_preferred_lifetime <
|
||||
V_ip6_desync_factor + V_ip6_temp_regen_advance) {
|
||||
V_ip6_temp_preferred_lifetime = old;
|
||||
return (EINVAL);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_ip6_tempvltime(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error = 0;
|
||||
int old;
|
||||
|
||||
VNET_SYSCTL_ARG(req, arg1);
|
||||
|
||||
error = SYSCTL_OUT(req, arg1, sizeof(int));
|
||||
if (error || !req->newptr)
|
||||
return (error);
|
||||
old = V_ip6_temp_valid_lifetime;
|
||||
error = SYSCTL_IN(req, arg1, sizeof(int));
|
||||
if (V_ip6_temp_valid_lifetime < V_ip6_temp_preferred_lifetime) {
|
||||
V_ip6_temp_preferred_lifetime = old;
|
||||
return (EINVAL);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_FORWARDING, forwarding, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_forwarding), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_SENDREDIRECTS, redirect, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_sendredirects), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DEFHLIM, hlim, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_defhlim), 0, "");
|
||||
SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6CTL_STATS, stats, CTLFLAG_RD,
|
||||
&VNET_NAME(ip6stat), ip6stat, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS, maxfragpackets,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_maxfragpackets), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_ACCEPT_RTADV, accept_rtadv,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_accept_rtadv), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_keepfaith), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL, log_interval,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_log_interval), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_HDRNESTLIMIT, hdrnestlimit,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_hdrnestlimit), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DAD_COUNT, dad_count, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_dad_count), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_AUTO_FLOWLABEL, auto_flowlabel,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_auto_flowlabel), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DEFMCASTHLIM, defmcasthlim,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_defmcasthlim), 0, "");
|
||||
SYSCTL_STRING(_net_inet6_ip6, IPV6CTL_KAME_VERSION, kame_version,
|
||||
CTLFLAG_RD, __KAME_VERSION, 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_USE_DEPRECATED, use_deprecated,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_use_deprecated), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE, rr_prune, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_rr_prune), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_USETEMPADDR, use_tempaddr,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_use_tempaddr), 0, "");
|
||||
SYSCTL_VNET_PROC(_net_inet6_ip6, IPV6CTL_TEMPPLTIME, temppltime,
|
||||
CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(ip6_temp_preferred_lifetime), 0,
|
||||
sysctl_ip6_temppltime, "I", "");
|
||||
SYSCTL_VNET_PROC(_net_inet6_ip6, IPV6CTL_TEMPVLTIME, tempvltime,
|
||||
CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(ip6_temp_valid_lifetime), 0,
|
||||
sysctl_ip6_tempvltime, "I", "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_V6ONLY, v6only, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_v6only), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_AUTO_LINKLOCAL, auto_linklocal,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_auto_linklocal), 0, "");
|
||||
SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6CTL_RIP6STATS, rip6stats, CTLFLAG_RD,
|
||||
&VNET_NAME(rip6stat), rip6stat, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_PREFER_TEMPADDR, prefer_tempaddr,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_prefer_tempaddr), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_USE_DEFAULTZONE, use_defaultzone,
|
||||
CTLFLAG_RW, &VNET_NAME(ip6_use_defzone), 0,"");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGS, maxfrags, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_maxfrags), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MCAST_PMTU, mcast_pmtu, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6_mcast_pmtu), 0, "");
|
||||
#ifdef IPSTEALTH
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_STEALTH, stealth, CTLFLAG_RW,
|
||||
&VNET_NAME(ip6stealth), 0, "");
|
||||
#endif
|
||||
|
||||
/* net.inet6.icmp6 */
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRACCEPT, rediraccept,
|
||||
CTLFLAG_RW, &VNET_NAME(icmp6_rediraccept), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT, redirtimeout,
|
||||
CTLFLAG_RW, &VNET_NAME(icmp6_redirtimeout), 0, "");
|
||||
SYSCTL_VNET_STRUCT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats, CTLFLAG_RD,
|
||||
&VNET_NAME(icmp6stat), icmp6stat, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PRUNE, nd6_prune, CTLFLAG_RW,
|
||||
&VNET_NAME(nd6_prune), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DELAY, nd6_delay, CTLFLAG_RW,
|
||||
&VNET_NAME(nd6_delay), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_UMAXTRIES, nd6_umaxtries,
|
||||
CTLFLAG_RW, &VNET_NAME(nd6_umaxtries), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MMAXTRIES, nd6_mmaxtries,
|
||||
CTLFLAG_RW, &VNET_NAME(nd6_mmaxtries), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_USELOOPBACK, nd6_useloopback,
|
||||
CTLFLAG_RW, &VNET_NAME(nd6_useloopback), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_NODEINFO, nodeinfo, CTLFLAG_RW,
|
||||
&VNET_NAME(icmp6_nodeinfo), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ERRPPSLIMIT, errppslimit,
|
||||
CTLFLAG_RW, &VNET_NAME(icmp6errppslim), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXNUDHINT, nd6_maxnudhint,
|
||||
CTLFLAG_RW, &VNET_NAME(nd6_maxnudhint), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DEBUG, nd6_debug, CTLFLAG_RW,
|
||||
&VNET_NAME(nd6_debug), 0, "");
|
||||
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_ONLINKNSRFC4861,
|
||||
nd6_onlink_ns_rfc4861, CTLFLAG_RW, &VNET_NAME(nd6_onlink_ns_rfc4861),
|
||||
0, "Accept 'on-link' nd6 NS in compliance with RFC 4861.");
|
449
freebsd/netinet6/in6_rmx.c
Normal file
449
freebsd/netinet6/in6_rmx.c
Normal file
@@ -0,0 +1,449 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright 1994, 1995 Massachusetts Institute of Technology
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that both the above copyright notice and this
|
||||
* permission notice appear in all copies, that both the above
|
||||
* copyright notice and this permission notice appear in all
|
||||
* supporting documentation, and that the name of M.I.T. not be used
|
||||
* in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. M.I.T. makes
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code does two things necessary for the enhanced TCP metrics to
|
||||
* function in a useful manner:
|
||||
* 1) It marks all non-host routes as `cloning', thus ensuring that
|
||||
* every actual reference to such a route actually gets turned
|
||||
* into a reference to a host route to the specific destination
|
||||
* requested.
|
||||
* 2) When such routes lose all their references, it arranges for them
|
||||
* to be deleted in some random collection of circumstances, so that
|
||||
* a large quantity of stale routing data is not kept in kernel memory
|
||||
* indefinitely. See in6_rtqtimo() below for the exact mechanism.
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/lock.h>
|
||||
#include <rtems/freebsd/sys/sysctl.h>
|
||||
#include <rtems/freebsd/sys/queue.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/socketvar.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/rwlock.h>
|
||||
#include <rtems/freebsd/sys/syslog.h>
|
||||
#include <rtems/freebsd/sys/callout.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/ip_var.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/icmp6.h>
|
||||
#include <rtems/freebsd/netinet6/nd6.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/tcp.h>
|
||||
#include <rtems/freebsd/netinet/tcp_seq.h>
|
||||
#include <rtems/freebsd/netinet/tcp_timer.h>
|
||||
#include <rtems/freebsd/netinet/tcp_var.h>
|
||||
|
||||
extern int in6_inithead(void **head, int off);
|
||||
#ifdef VIMAGE
|
||||
extern int in6_detachhead(void **head, int off);
|
||||
#endif
|
||||
|
||||
#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */
|
||||
|
||||
/*
|
||||
* Do what we need to do when inserting a route.
|
||||
*/
|
||||
static struct radix_node *
|
||||
in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
|
||||
struct radix_node *treenodes)
|
||||
{
|
||||
struct rtentry *rt = (struct rtentry *)treenodes;
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt);
|
||||
struct radix_node *ret;
|
||||
|
||||
RADIX_NODE_HEAD_WLOCK_ASSERT(head);
|
||||
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
|
||||
rt->rt_flags |= RTF_MULTICAST;
|
||||
|
||||
/*
|
||||
* A little bit of help for both IPv6 output and input:
|
||||
* For local addresses, we make sure that RTF_LOCAL is set,
|
||||
* with the thought that this might one day be used to speed up
|
||||
* ip_input().
|
||||
*
|
||||
* We also mark routes to multicast addresses as such, because
|
||||
* it's easy to do and might be useful (but this is much more
|
||||
* dubious since it's so easy to inspect the address). (This
|
||||
* is done above.)
|
||||
*
|
||||
* XXX
|
||||
* should elaborate the code.
|
||||
*/
|
||||
if (rt->rt_flags & RTF_HOST) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr)
|
||||
->sin6_addr,
|
||||
&sin6->sin6_addr)) {
|
||||
rt->rt_flags |= RTF_LOCAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rt->rt_rmx.rmx_mtu && rt->rt_ifp)
|
||||
rt->rt_rmx.rmx_mtu = IN6_LINKMTU(rt->rt_ifp);
|
||||
|
||||
ret = rn_addroute(v_arg, n_arg, head, treenodes);
|
||||
if (ret == NULL) {
|
||||
struct rtentry *rt2;
|
||||
/*
|
||||
* We are trying to add a net route, but can't.
|
||||
* The following case should be allowed, so we'll make a
|
||||
* special check for this:
|
||||
* Two IPv6 addresses with the same prefix is assigned
|
||||
* to a single interrface.
|
||||
* # ifconfig if0 inet6 3ffe:0501::1 prefix 64 alias (*1)
|
||||
* # ifconfig if0 inet6 3ffe:0501::2 prefix 64 alias (*2)
|
||||
* In this case, (*1) and (*2) want to add the same
|
||||
* net route entry, 3ffe:0501:: -> if0.
|
||||
* This case should not raise an error.
|
||||
*/
|
||||
rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED);
|
||||
if (rt2) {
|
||||
if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0)
|
||||
&& rt2->rt_gateway
|
||||
&& rt2->rt_gateway->sa_family == AF_LINK
|
||||
&& rt2->rt_ifp == rt->rt_ifp) {
|
||||
ret = rt2->rt_nodes;
|
||||
}
|
||||
RTFREE_LOCKED(rt2);
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* This code is the inverse of in6_clsroute: on first reference, if we
|
||||
* were managing the route, stop doing so and set the expiration timer
|
||||
* back off again.
|
||||
*/
|
||||
static struct radix_node *
|
||||
in6_matroute(void *v_arg, struct radix_node_head *head)
|
||||
{
|
||||
struct radix_node *rn = rn_match(v_arg, head);
|
||||
struct rtentry *rt = (struct rtentry *)rn;
|
||||
|
||||
if (rt) {
|
||||
RT_LOCK(rt);
|
||||
if (rt->rt_flags & RTPRF_OURS) {
|
||||
rt->rt_flags &= ~RTPRF_OURS;
|
||||
rt->rt_rmx.rmx_expire = 0;
|
||||
}
|
||||
RT_UNLOCK(rt);
|
||||
}
|
||||
return rn;
|
||||
}
|
||||
|
||||
SYSCTL_DECL(_net_inet6_ip6);
|
||||
|
||||
static VNET_DEFINE(int, rtq_reallyold6) = 60*60;
|
||||
/* one hour is ``really old'' */
|
||||
#define V_rtq_reallyold6 VNET(rtq_reallyold6)
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTEXPIRE, rtexpire, CTLFLAG_RW,
|
||||
&VNET_NAME(rtq_reallyold6) , 0, "");
|
||||
|
||||
static VNET_DEFINE(int, rtq_minreallyold6) = 10;
|
||||
/* never automatically crank down to less */
|
||||
#define V_rtq_minreallyold6 VNET(rtq_minreallyold6)
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW,
|
||||
&VNET_NAME(rtq_minreallyold6) , 0, "");
|
||||
|
||||
static VNET_DEFINE(int, rtq_toomany6) = 128;
|
||||
/* 128 cached routes is ``too many'' */
|
||||
#define V_rtq_toomany6 VNET(rtq_toomany6)
|
||||
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW,
|
||||
&VNET_NAME(rtq_toomany6) , 0, "");
|
||||
|
||||
struct rtqk_arg {
|
||||
struct radix_node_head *rnh;
|
||||
int mode;
|
||||
int updating;
|
||||
int draining;
|
||||
int killed;
|
||||
int found;
|
||||
time_t nextstop;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get rid of old routes. When draining, this deletes everything, even when
|
||||
* the timeout is not expired yet. When updating, this makes sure that
|
||||
* nothing has a timeout longer than the current value of rtq_reallyold6.
|
||||
*/
|
||||
static int
|
||||
in6_rtqkill(struct radix_node *rn, void *rock)
|
||||
{
|
||||
struct rtqk_arg *ap = rock;
|
||||
struct rtentry *rt = (struct rtentry *)rn;
|
||||
int err;
|
||||
|
||||
RADIX_NODE_HEAD_WLOCK_ASSERT(ap->rnh);
|
||||
|
||||
if (rt->rt_flags & RTPRF_OURS) {
|
||||
ap->found++;
|
||||
|
||||
if (ap->draining || rt->rt_rmx.rmx_expire <= time_uptime) {
|
||||
if (rt->rt_refcnt > 0)
|
||||
panic("rtqkill route really not free");
|
||||
|
||||
err = rtrequest(RTM_DELETE,
|
||||
(struct sockaddr *)rt_key(rt),
|
||||
rt->rt_gateway, rt_mask(rt),
|
||||
rt->rt_flags|RTF_RNH_LOCKED, 0);
|
||||
if (err) {
|
||||
log(LOG_WARNING, "in6_rtqkill: error %d", err);
|
||||
} else {
|
||||
ap->killed++;
|
||||
}
|
||||
} else {
|
||||
if (ap->updating
|
||||
&& (rt->rt_rmx.rmx_expire - time_uptime
|
||||
> V_rtq_reallyold6)) {
|
||||
rt->rt_rmx.rmx_expire = time_uptime
|
||||
+ V_rtq_reallyold6;
|
||||
}
|
||||
ap->nextstop = lmin(ap->nextstop,
|
||||
rt->rt_rmx.rmx_expire);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */
|
||||
static VNET_DEFINE(int, rtq_timeout6) = RTQ_TIMEOUT;
|
||||
static VNET_DEFINE(struct callout, rtq_timer6);
|
||||
|
||||
#define V_rtq_timeout6 VNET(rtq_timeout6)
|
||||
#define V_rtq_timer6 VNET(rtq_timer6)
|
||||
|
||||
static void
|
||||
in6_rtqtimo(void *rock)
|
||||
{
|
||||
CURVNET_SET_QUIET((struct vnet *) rock);
|
||||
struct radix_node_head *rnh;
|
||||
struct rtqk_arg arg;
|
||||
struct timeval atv;
|
||||
static time_t last_adjusted_timeout = 0;
|
||||
|
||||
rnh = rt_tables_get_rnh(0, AF_INET6);
|
||||
if (rnh == NULL) {
|
||||
CURVNET_RESTORE();
|
||||
return;
|
||||
}
|
||||
arg.found = arg.killed = 0;
|
||||
arg.rnh = rnh;
|
||||
arg.nextstop = time_uptime + V_rtq_timeout6;
|
||||
arg.draining = arg.updating = 0;
|
||||
RADIX_NODE_HEAD_LOCK(rnh);
|
||||
rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
|
||||
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||
|
||||
/*
|
||||
* Attempt to be somewhat dynamic about this:
|
||||
* If there are ``too many'' routes sitting around taking up space,
|
||||
* then crank down the timeout, and see if we can't make some more
|
||||
* go away. However, we make sure that we will never adjust more
|
||||
* than once in rtq_timeout6 seconds, to keep from cranking down too
|
||||
* hard.
|
||||
*/
|
||||
if ((arg.found - arg.killed > V_rtq_toomany6)
|
||||
&& (time_uptime - last_adjusted_timeout >= V_rtq_timeout6)
|
||||
&& V_rtq_reallyold6 > V_rtq_minreallyold6) {
|
||||
V_rtq_reallyold6 = 2*V_rtq_reallyold6 / 3;
|
||||
if (V_rtq_reallyold6 < V_rtq_minreallyold6) {
|
||||
V_rtq_reallyold6 = V_rtq_minreallyold6;
|
||||
}
|
||||
|
||||
last_adjusted_timeout = time_uptime;
|
||||
#ifdef DIAGNOSTIC
|
||||
log(LOG_DEBUG, "in6_rtqtimo: adjusted rtq_reallyold6 to %d",
|
||||
V_rtq_reallyold6);
|
||||
#endif
|
||||
arg.found = arg.killed = 0;
|
||||
arg.updating = 1;
|
||||
RADIX_NODE_HEAD_LOCK(rnh);
|
||||
rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
|
||||
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||
}
|
||||
|
||||
atv.tv_usec = 0;
|
||||
atv.tv_sec = arg.nextstop - time_uptime;
|
||||
callout_reset(&V_rtq_timer6, tvtohz(&atv), in6_rtqtimo, rock);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
/*
|
||||
* Age old PMTUs.
|
||||
*/
|
||||
struct mtuex_arg {
|
||||
struct radix_node_head *rnh;
|
||||
time_t nextstop;
|
||||
};
|
||||
static VNET_DEFINE(struct callout, rtq_mtutimer);
|
||||
#define V_rtq_mtutimer VNET(rtq_mtutimer)
|
||||
|
||||
static int
|
||||
in6_mtuexpire(struct radix_node *rn, void *rock)
|
||||
{
|
||||
struct rtentry *rt = (struct rtentry *)rn;
|
||||
struct mtuex_arg *ap = rock;
|
||||
|
||||
/* sanity */
|
||||
if (!rt)
|
||||
panic("rt == NULL in in6_mtuexpire");
|
||||
|
||||
if (rt->rt_rmx.rmx_expire && !(rt->rt_flags & RTF_PROBEMTU)) {
|
||||
if (rt->rt_rmx.rmx_expire <= time_uptime) {
|
||||
rt->rt_flags |= RTF_PROBEMTU;
|
||||
} else {
|
||||
ap->nextstop = lmin(ap->nextstop,
|
||||
rt->rt_rmx.rmx_expire);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MTUTIMO_DEFAULT (60*1)
|
||||
|
||||
static void
|
||||
in6_mtutimo(void *rock)
|
||||
{
|
||||
CURVNET_SET_QUIET((struct vnet *) rock);
|
||||
struct radix_node_head *rnh;
|
||||
struct mtuex_arg arg;
|
||||
struct timeval atv;
|
||||
|
||||
rnh = rt_tables_get_rnh(0, AF_INET6);
|
||||
if (rnh == NULL) {
|
||||
CURVNET_RESTORE();
|
||||
return;
|
||||
}
|
||||
arg.rnh = rnh;
|
||||
arg.nextstop = time_uptime + MTUTIMO_DEFAULT;
|
||||
RADIX_NODE_HEAD_LOCK(rnh);
|
||||
rnh->rnh_walktree(rnh, in6_mtuexpire, &arg);
|
||||
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||
|
||||
atv.tv_usec = 0;
|
||||
atv.tv_sec = arg.nextstop - time_uptime;
|
||||
if (atv.tv_sec < 0) {
|
||||
printf("invalid mtu expiration time on routing table\n");
|
||||
arg.nextstop = time_uptime + 30; /* last resort */
|
||||
atv.tv_sec = 30;
|
||||
}
|
||||
callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize our routing tree.
|
||||
* XXX MRT When off == 0, we are being called from vfs_export.c
|
||||
* so just set up their table and leave. (we know what the correct
|
||||
* value should be so just use that).. FIX AFTER RELENG_7 is MFC'd
|
||||
* see also comments in in_inithead() vfs_export.c and domain.h
|
||||
*/
|
||||
int
|
||||
in6_inithead(void **head, int off)
|
||||
{
|
||||
struct radix_node_head *rnh;
|
||||
|
||||
if (!rn_inithead(head, offsetof(struct sockaddr_in6, sin6_addr) << 3))
|
||||
return 0; /* See above */
|
||||
|
||||
if (off == 0) /* See above */
|
||||
return 1; /* only do the rest for the real thing */
|
||||
|
||||
rnh = *head;
|
||||
KASSERT(rnh == rt_tables_get_rnh(0, AF_INET6), ("rnh?"));
|
||||
rnh->rnh_addaddr = in6_addroute;
|
||||
rnh->rnh_matchaddr = in6_matroute;
|
||||
callout_init(&V_rtq_timer6, CALLOUT_MPSAFE);
|
||||
callout_init(&V_rtq_mtutimer, CALLOUT_MPSAFE);
|
||||
in6_rtqtimo(curvnet); /* kick off timeout first time */
|
||||
in6_mtutimo(curvnet); /* kick off timeout first time */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef VIMAGE
|
||||
int
|
||||
in6_detachhead(void **head, int off)
|
||||
{
|
||||
|
||||
callout_drain(&V_rtq_timer6);
|
||||
callout_drain(&V_rtq_mtutimer);
|
||||
return (1);
|
||||
}
|
||||
#endif
|
1204
freebsd/netinet6/in6_src.c
Normal file
1204
freebsd/netinet6/in6_src.c
Normal file
File diff suppressed because it is too large
Load Diff
786
freebsd/netinet6/in6_var.h
Normal file
786
freebsd/netinet6/in6_var.h
Normal file
@@ -0,0 +1,786 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: in6_var.h,v 1.56 2001/03/29 05:34:31 itojun Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1985, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)in_var.h 8.1 (Berkeley) 6/10/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IN6_VAR_HH_
|
||||
#define _NETINET6_IN6_VAR_HH_
|
||||
|
||||
#include <rtems/freebsd/sys/tree.h>
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <rtems/freebsd/sys/libkern.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interface address, Internet version. One of these structures
|
||||
* is allocated for each interface with an Internet address.
|
||||
* The ifaddr structure contains the protocol-independent part
|
||||
* of the structure and is assumed to be first.
|
||||
*/
|
||||
|
||||
/*
|
||||
* pltime/vltime are just for future reference (required to implements 2
|
||||
* hour rule for hosts). they should never be modified by nd6_timeout or
|
||||
* anywhere else.
|
||||
* userland -> kernel: accept pltime/vltime
|
||||
* kernel -> userland: throw up everything
|
||||
* in kernel: modify preferred/expire only
|
||||
*/
|
||||
struct in6_addrlifetime {
|
||||
time_t ia6t_expire; /* valid lifetime expiration time */
|
||||
time_t ia6t_preferred; /* preferred lifetime expiration time */
|
||||
u_int32_t ia6t_vltime; /* valid lifetime */
|
||||
u_int32_t ia6t_pltime; /* prefix lifetime */
|
||||
};
|
||||
|
||||
struct nd_ifinfo;
|
||||
struct scope6_id;
|
||||
struct lltable;
|
||||
struct mld_ifinfo;
|
||||
|
||||
struct in6_ifextra {
|
||||
struct in6_ifstat *in6_ifstat;
|
||||
struct icmp6_ifstat *icmp6_ifstat;
|
||||
struct nd_ifinfo *nd_ifinfo;
|
||||
struct scope6_id *scope6_id;
|
||||
struct lltable *lltable;
|
||||
struct mld_ifinfo *mld_ifinfo;
|
||||
};
|
||||
|
||||
#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
|
||||
|
||||
struct in6_ifaddr {
|
||||
struct ifaddr ia_ifa; /* protocol-independent info */
|
||||
#define ia_ifp ia_ifa.ifa_ifp
|
||||
#define ia_flags ia_ifa.ifa_flags
|
||||
struct sockaddr_in6 ia_addr; /* interface address */
|
||||
struct sockaddr_in6 ia_net; /* network number of interface */
|
||||
struct sockaddr_in6 ia_dstaddr; /* space for destination addr */
|
||||
struct sockaddr_in6 ia_prefixmask; /* prefix mask */
|
||||
u_int32_t ia_plen; /* prefix length */
|
||||
TAILQ_ENTRY(in6_ifaddr) ia_link; /* list of IPv6 addresses */
|
||||
int ia6_flags;
|
||||
|
||||
struct in6_addrlifetime ia6_lifetime;
|
||||
time_t ia6_createtime; /* the creation time of this address, which is
|
||||
* currently used for temporary addresses only.
|
||||
*/
|
||||
time_t ia6_updatetime;
|
||||
|
||||
/* back pointer to the ND prefix (for autoconfigured addresses only) */
|
||||
struct nd_prefix *ia6_ndpr;
|
||||
|
||||
/* multicast addresses joined from the kernel */
|
||||
LIST_HEAD(, in6_multi_mship) ia6_memberships;
|
||||
};
|
||||
|
||||
/* List of in6_ifaddr's. */
|
||||
TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr);
|
||||
|
||||
/* control structure to manage address selection policy */
|
||||
struct in6_addrpolicy {
|
||||
struct sockaddr_in6 addr; /* prefix address */
|
||||
struct sockaddr_in6 addrmask; /* prefix mask */
|
||||
int preced; /* precedence */
|
||||
int label; /* matching label */
|
||||
u_quad_t use; /* statistics */
|
||||
};
|
||||
|
||||
/*
|
||||
* IPv6 interface statistics, as defined in RFC2465 Ipv6IfStatsEntry (p12).
|
||||
*/
|
||||
struct in6_ifstat {
|
||||
u_quad_t ifs6_in_receive; /* # of total input datagram */
|
||||
u_quad_t ifs6_in_hdrerr; /* # of datagrams with invalid hdr */
|
||||
u_quad_t ifs6_in_toobig; /* # of datagrams exceeded MTU */
|
||||
u_quad_t ifs6_in_noroute; /* # of datagrams with no route */
|
||||
u_quad_t ifs6_in_addrerr; /* # of datagrams with invalid dst */
|
||||
u_quad_t ifs6_in_protounknown; /* # of datagrams with unknown proto */
|
||||
/* NOTE: increment on final dst if */
|
||||
u_quad_t ifs6_in_truncated; /* # of truncated datagrams */
|
||||
u_quad_t ifs6_in_discard; /* # of discarded datagrams */
|
||||
/* NOTE: fragment timeout is not here */
|
||||
u_quad_t ifs6_in_deliver; /* # of datagrams delivered to ULP */
|
||||
/* NOTE: increment on final dst if */
|
||||
u_quad_t ifs6_out_forward; /* # of datagrams forwarded */
|
||||
/* NOTE: increment on outgoing if */
|
||||
u_quad_t ifs6_out_request; /* # of outgoing datagrams from ULP */
|
||||
/* NOTE: does not include forwrads */
|
||||
u_quad_t ifs6_out_discard; /* # of discarded datagrams */
|
||||
u_quad_t ifs6_out_fragok; /* # of datagrams fragmented */
|
||||
u_quad_t ifs6_out_fragfail; /* # of datagrams failed on fragment */
|
||||
u_quad_t ifs6_out_fragcreat; /* # of fragment datagrams */
|
||||
/* NOTE: this is # after fragment */
|
||||
u_quad_t ifs6_reass_reqd; /* # of incoming fragmented packets */
|
||||
/* NOTE: increment on final dst if */
|
||||
u_quad_t ifs6_reass_ok; /* # of reassembled packets */
|
||||
/* NOTE: this is # after reass */
|
||||
/* NOTE: increment on final dst if */
|
||||
u_quad_t ifs6_reass_fail; /* # of reass failures */
|
||||
/* NOTE: may not be packet count */
|
||||
/* NOTE: increment on final dst if */
|
||||
u_quad_t ifs6_in_mcast; /* # of inbound multicast datagrams */
|
||||
u_quad_t ifs6_out_mcast; /* # of outbound multicast datagrams */
|
||||
};
|
||||
|
||||
/*
|
||||
* ICMPv6 interface statistics, as defined in RFC2466 Ipv6IfIcmpEntry.
|
||||
* XXX: I'm not sure if this file is the right place for this structure...
|
||||
*/
|
||||
struct icmp6_ifstat {
|
||||
/*
|
||||
* Input statistics
|
||||
*/
|
||||
/* ipv6IfIcmpInMsgs, total # of input messages */
|
||||
u_quad_t ifs6_in_msg;
|
||||
/* ipv6IfIcmpInErrors, # of input error messages */
|
||||
u_quad_t ifs6_in_error;
|
||||
/* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */
|
||||
u_quad_t ifs6_in_dstunreach;
|
||||
/* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */
|
||||
u_quad_t ifs6_in_adminprohib;
|
||||
/* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */
|
||||
u_quad_t ifs6_in_timeexceed;
|
||||
/* ipv6IfIcmpInParmProblems, # of input parameter problem errors */
|
||||
u_quad_t ifs6_in_paramprob;
|
||||
/* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */
|
||||
u_quad_t ifs6_in_pkttoobig;
|
||||
/* ipv6IfIcmpInEchos, # of input echo requests */
|
||||
u_quad_t ifs6_in_echo;
|
||||
/* ipv6IfIcmpInEchoReplies, # of input echo replies */
|
||||
u_quad_t ifs6_in_echoreply;
|
||||
/* ipv6IfIcmpInRouterSolicits, # of input router solicitations */
|
||||
u_quad_t ifs6_in_routersolicit;
|
||||
/* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */
|
||||
u_quad_t ifs6_in_routeradvert;
|
||||
/* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */
|
||||
u_quad_t ifs6_in_neighborsolicit;
|
||||
/* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */
|
||||
u_quad_t ifs6_in_neighboradvert;
|
||||
/* ipv6IfIcmpInRedirects, # of input redirects */
|
||||
u_quad_t ifs6_in_redirect;
|
||||
/* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */
|
||||
u_quad_t ifs6_in_mldquery;
|
||||
/* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */
|
||||
u_quad_t ifs6_in_mldreport;
|
||||
/* ipv6IfIcmpInGroupMembReductions, # of input MLD done */
|
||||
u_quad_t ifs6_in_mlddone;
|
||||
|
||||
/*
|
||||
* Output statistics. We should solve unresolved routing problem...
|
||||
*/
|
||||
/* ipv6IfIcmpOutMsgs, total # of output messages */
|
||||
u_quad_t ifs6_out_msg;
|
||||
/* ipv6IfIcmpOutErrors, # of output error messages */
|
||||
u_quad_t ifs6_out_error;
|
||||
/* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */
|
||||
u_quad_t ifs6_out_dstunreach;
|
||||
/* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */
|
||||
u_quad_t ifs6_out_adminprohib;
|
||||
/* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */
|
||||
u_quad_t ifs6_out_timeexceed;
|
||||
/* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */
|
||||
u_quad_t ifs6_out_paramprob;
|
||||
/* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */
|
||||
u_quad_t ifs6_out_pkttoobig;
|
||||
/* ipv6IfIcmpOutEchos, # of output echo requests */
|
||||
u_quad_t ifs6_out_echo;
|
||||
/* ipv6IfIcmpOutEchoReplies, # of output echo replies */
|
||||
u_quad_t ifs6_out_echoreply;
|
||||
/* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */
|
||||
u_quad_t ifs6_out_routersolicit;
|
||||
/* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */
|
||||
u_quad_t ifs6_out_routeradvert;
|
||||
/* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */
|
||||
u_quad_t ifs6_out_neighborsolicit;
|
||||
/* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */
|
||||
u_quad_t ifs6_out_neighboradvert;
|
||||
/* ipv6IfIcmpOutRedirects, # of output redirects */
|
||||
u_quad_t ifs6_out_redirect;
|
||||
/* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */
|
||||
u_quad_t ifs6_out_mldquery;
|
||||
/* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */
|
||||
u_quad_t ifs6_out_mldreport;
|
||||
/* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */
|
||||
u_quad_t ifs6_out_mlddone;
|
||||
};
|
||||
|
||||
struct in6_ifreq {
|
||||
char ifr_name[IFNAMSIZ];
|
||||
union {
|
||||
struct sockaddr_in6 ifru_addr;
|
||||
struct sockaddr_in6 ifru_dstaddr;
|
||||
int ifru_flags;
|
||||
int ifru_flags6;
|
||||
int ifru_metric;
|
||||
caddr_t ifru_data;
|
||||
struct in6_addrlifetime ifru_lifetime;
|
||||
struct in6_ifstat ifru_stat;
|
||||
struct icmp6_ifstat ifru_icmp6stat;
|
||||
u_int32_t ifru_scope_id[16];
|
||||
} ifr_ifru;
|
||||
};
|
||||
|
||||
struct in6_aliasreq {
|
||||
char ifra_name[IFNAMSIZ];
|
||||
struct sockaddr_in6 ifra_addr;
|
||||
struct sockaddr_in6 ifra_dstaddr;
|
||||
struct sockaddr_in6 ifra_prefixmask;
|
||||
int ifra_flags;
|
||||
struct in6_addrlifetime ifra_lifetime;
|
||||
};
|
||||
|
||||
/* prefix type macro */
|
||||
#define IN6_PREFIX_ND 1
|
||||
#define IN6_PREFIX_RR 2
|
||||
|
||||
/*
|
||||
* prefix related flags passed between kernel(NDP related part) and
|
||||
* user land command(ifconfig) and daemon(rtadvd).
|
||||
*/
|
||||
struct in6_prflags {
|
||||
struct prf_ra {
|
||||
u_char onlink : 1;
|
||||
u_char autonomous : 1;
|
||||
u_char reserved : 6;
|
||||
} prf_ra;
|
||||
u_char prf_reserved1;
|
||||
u_short prf_reserved2;
|
||||
/* want to put this on 4byte offset */
|
||||
struct prf_rr {
|
||||
u_char decrvalid : 1;
|
||||
u_char decrprefd : 1;
|
||||
u_char reserved : 6;
|
||||
} prf_rr;
|
||||
u_char prf_reserved3;
|
||||
u_short prf_reserved4;
|
||||
};
|
||||
|
||||
struct in6_prefixreq {
|
||||
char ipr_name[IFNAMSIZ];
|
||||
u_char ipr_origin;
|
||||
u_char ipr_plen;
|
||||
u_int32_t ipr_vltime;
|
||||
u_int32_t ipr_pltime;
|
||||
struct in6_prflags ipr_flags;
|
||||
struct sockaddr_in6 ipr_prefix;
|
||||
};
|
||||
|
||||
#define PR_ORIG_RA 0
|
||||
#define PR_ORIG_RR 1
|
||||
#define PR_ORIG_STATIC 2
|
||||
#define PR_ORIG_KERNEL 3
|
||||
|
||||
#define ipr_raf_onlink ipr_flags.prf_ra.onlink
|
||||
#define ipr_raf_auto ipr_flags.prf_ra.autonomous
|
||||
|
||||
#define ipr_statef_onlink ipr_flags.prf_state.onlink
|
||||
|
||||
#define ipr_rrf_decrvalid ipr_flags.prf_rr.decrvalid
|
||||
#define ipr_rrf_decrprefd ipr_flags.prf_rr.decrprefd
|
||||
|
||||
struct in6_rrenumreq {
|
||||
char irr_name[IFNAMSIZ];
|
||||
u_char irr_origin;
|
||||
u_char irr_m_len; /* match len for matchprefix */
|
||||
u_char irr_m_minlen; /* minlen for matching prefix */
|
||||
u_char irr_m_maxlen; /* maxlen for matching prefix */
|
||||
u_char irr_u_uselen; /* uselen for adding prefix */
|
||||
u_char irr_u_keeplen; /* keeplen from matching prefix */
|
||||
struct irr_raflagmask {
|
||||
u_char onlink : 1;
|
||||
u_char autonomous : 1;
|
||||
u_char reserved : 6;
|
||||
} irr_raflagmask;
|
||||
u_int32_t irr_vltime;
|
||||
u_int32_t irr_pltime;
|
||||
struct in6_prflags irr_flags;
|
||||
struct sockaddr_in6 irr_matchprefix;
|
||||
struct sockaddr_in6 irr_useprefix;
|
||||
};
|
||||
|
||||
#define irr_raf_mask_onlink irr_raflagmask.onlink
|
||||
#define irr_raf_mask_auto irr_raflagmask.autonomous
|
||||
#define irr_raf_mask_reserved irr_raflagmask.reserved
|
||||
|
||||
#define irr_raf_onlink irr_flags.prf_ra.onlink
|
||||
#define irr_raf_auto irr_flags.prf_ra.autonomous
|
||||
|
||||
#define irr_statef_onlink irr_flags.prf_state.onlink
|
||||
|
||||
#define irr_rrf irr_flags.prf_rr
|
||||
#define irr_rrf_decrvalid irr_flags.prf_rr.decrvalid
|
||||
#define irr_rrf_decrprefd irr_flags.prf_rr.decrprefd
|
||||
|
||||
/*
|
||||
* Given a pointer to an in6_ifaddr (ifaddr),
|
||||
* return a pointer to the addr as a sockaddr_in6
|
||||
*/
|
||||
#define IA6_IN6(ia) (&((ia)->ia_addr.sin6_addr))
|
||||
#define IA6_DSTIN6(ia) (&((ia)->ia_dstaddr.sin6_addr))
|
||||
#define IA6_MASKIN6(ia) (&((ia)->ia_prefixmask.sin6_addr))
|
||||
#define IA6_SIN6(ia) (&((ia)->ia_addr))
|
||||
#define IA6_DSTSIN6(ia) (&((ia)->ia_dstaddr))
|
||||
#define IFA_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr)
|
||||
#define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr)
|
||||
|
||||
#define IFPR_IN6(x) (&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr)
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
|
||||
(((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \
|
||||
(((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \
|
||||
(((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \
|
||||
(((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
|
||||
#endif
|
||||
|
||||
#define SIOCSIFADDR_IN6 _IOW('i', 12, struct in6_ifreq)
|
||||
#define SIOCGIFADDR_IN6 _IOWR('i', 33, struct in6_ifreq)
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* SIOCSxxx ioctls should be unused (see comments in in6.c), but
|
||||
* we do not shift numbers for binary compatibility.
|
||||
*/
|
||||
#define SIOCSIFDSTADDR_IN6 _IOW('i', 14, struct in6_ifreq)
|
||||
#define SIOCSIFNETMASK_IN6 _IOW('i', 22, struct in6_ifreq)
|
||||
#endif
|
||||
|
||||
#define SIOCGIFDSTADDR_IN6 _IOWR('i', 34, struct in6_ifreq)
|
||||
#define SIOCGIFNETMASK_IN6 _IOWR('i', 37, struct in6_ifreq)
|
||||
|
||||
#define SIOCDIFADDR_IN6 _IOW('i', 25, struct in6_ifreq)
|
||||
#define SIOCAIFADDR_IN6 _IOW('i', 26, struct in6_aliasreq)
|
||||
|
||||
#define SIOCSIFPHYADDR_IN6 _IOW('i', 70, struct in6_aliasreq)
|
||||
#define SIOCGIFPSRCADDR_IN6 _IOWR('i', 71, struct in6_ifreq)
|
||||
#define SIOCGIFPDSTADDR_IN6 _IOWR('i', 72, struct in6_ifreq)
|
||||
|
||||
#define SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq)
|
||||
|
||||
#define SIOCGDRLST_IN6 _IOWR('i', 74, struct in6_drlist)
|
||||
#ifdef _KERNEL
|
||||
/* XXX: SIOCGPRLST_IN6 is exposed in KAME but in6_oprlist is not. */
|
||||
#define SIOCGPRLST_IN6 _IOWR('i', 75, struct in6_oprlist)
|
||||
#endif
|
||||
#ifdef _KERNEL
|
||||
#define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq)
|
||||
#endif
|
||||
#define SIOCGIFINFO_IN6 _IOWR('i', 108, struct in6_ndireq)
|
||||
#define SIOCSIFINFO_IN6 _IOWR('i', 109, struct in6_ndireq)
|
||||
#define SIOCSNDFLUSH_IN6 _IOWR('i', 77, struct in6_ifreq)
|
||||
#define SIOCGNBRINFO_IN6 _IOWR('i', 78, struct in6_nbrinfo)
|
||||
#define SIOCSPFXFLUSH_IN6 _IOWR('i', 79, struct in6_ifreq)
|
||||
#define SIOCSRTRFLUSH_IN6 _IOWR('i', 80, struct in6_ifreq)
|
||||
|
||||
#define SIOCGIFALIFETIME_IN6 _IOWR('i', 81, struct in6_ifreq)
|
||||
#define SIOCSIFALIFETIME_IN6 _IOWR('i', 82, struct in6_ifreq)
|
||||
#define SIOCGIFSTAT_IN6 _IOWR('i', 83, struct in6_ifreq)
|
||||
#define SIOCGIFSTAT_ICMP6 _IOWR('i', 84, struct in6_ifreq)
|
||||
|
||||
#define SIOCSDEFIFACE_IN6 _IOWR('i', 85, struct in6_ndifreq)
|
||||
#define SIOCGDEFIFACE_IN6 _IOWR('i', 86, struct in6_ndifreq)
|
||||
|
||||
#define SIOCSIFINFO_FLAGS _IOWR('i', 87, struct in6_ndireq) /* XXX */
|
||||
|
||||
#define SIOCSSCOPE6 _IOW('i', 88, struct in6_ifreq)
|
||||
#define SIOCGSCOPE6 _IOWR('i', 89, struct in6_ifreq)
|
||||
#define SIOCGSCOPE6DEF _IOWR('i', 90, struct in6_ifreq)
|
||||
|
||||
#define SIOCSIFPREFIX_IN6 _IOW('i', 100, struct in6_prefixreq) /* set */
|
||||
#define SIOCGIFPREFIX_IN6 _IOWR('i', 101, struct in6_prefixreq) /* get */
|
||||
#define SIOCDIFPREFIX_IN6 _IOW('i', 102, struct in6_prefixreq) /* del */
|
||||
#define SIOCAIFPREFIX_IN6 _IOW('i', 103, struct in6_rrenumreq) /* add */
|
||||
#define SIOCCIFPREFIX_IN6 _IOW('i', 104, \
|
||||
struct in6_rrenumreq) /* change */
|
||||
#define SIOCSGIFPREFIX_IN6 _IOW('i', 105, \
|
||||
struct in6_rrenumreq) /* set global */
|
||||
|
||||
#define SIOCGETSGCNT_IN6 _IOWR('u', 106, \
|
||||
struct sioc_sg_req6) /* get s,g pkt cnt */
|
||||
#define SIOCGETMIFCNT_IN6 _IOWR('u', 107, \
|
||||
struct sioc_mif_req6) /* get pkt cnt per if */
|
||||
|
||||
#define SIOCAADDRCTL_POLICY _IOW('u', 108, struct in6_addrpolicy)
|
||||
#define SIOCDADDRCTL_POLICY _IOW('u', 109, struct in6_addrpolicy)
|
||||
|
||||
#define IN6_IFF_ANYCAST 0x01 /* anycast address */
|
||||
#define IN6_IFF_TENTATIVE 0x02 /* tentative address */
|
||||
#define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */
|
||||
#define IN6_IFF_DETACHED 0x08 /* may be detached from the link */
|
||||
#define IN6_IFF_DEPRECATED 0x10 /* deprecated address */
|
||||
#define IN6_IFF_NODAD 0x20 /* don't perform DAD on this address
|
||||
* (used only at first SIOC* call)
|
||||
*/
|
||||
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
|
||||
#define IN6_IFF_TEMPORARY 0x80 /* temporary (anonymous) address. */
|
||||
#define IN6_IFF_NOPFX 0x8000 /* skip kernel prefix management.
|
||||
* XXX: this should be temporary.
|
||||
*/
|
||||
|
||||
/* do not input/output */
|
||||
#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define IN6_ARE_SCOPE_CMP(a,b) ((a)-(b))
|
||||
#define IN6_ARE_SCOPE_EQUAL(a,b) ((a)==(b))
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead);
|
||||
#define V_in6_ifaddrhead VNET(in6_ifaddrhead)
|
||||
|
||||
extern struct rwlock in6_ifaddr_lock;
|
||||
#define IN6_IFADDR_LOCK_ASSERT( ) rw_assert(&in6_ifaddr_lock, RA_LOCKED)
|
||||
#define IN6_IFADDR_RLOCK() rw_rlock(&in6_ifaddr_lock)
|
||||
#define IN6_IFADDR_RLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_RLOCKED)
|
||||
#define IN6_IFADDR_RUNLOCK() rw_runlock(&in6_ifaddr_lock)
|
||||
#define IN6_IFADDR_WLOCK() rw_wlock(&in6_ifaddr_lock)
|
||||
#define IN6_IFADDR_WLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_WLOCKED)
|
||||
#define IN6_IFADDR_WUNLOCK() rw_wunlock(&in6_ifaddr_lock)
|
||||
|
||||
VNET_DECLARE(struct icmp6stat, icmp6stat);
|
||||
#define V_icmp6stat VNET(icmp6stat)
|
||||
#define in6_ifstat_inc(ifp, tag) \
|
||||
do { \
|
||||
if (ifp) \
|
||||
((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->in6_ifstat->tag++; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
extern struct in6_addr zeroin6_addr;
|
||||
extern u_char inet6ctlerrmap[];
|
||||
VNET_DECLARE(unsigned long, in6_maxmtu);
|
||||
#define V_in6_maxmtu VNET(in6_maxmtu)
|
||||
#endif /* _KERNEL */
|
||||
|
||||
/*
|
||||
* IPv6 multicast MLD-layer source entry.
|
||||
*/
|
||||
struct ip6_msource {
|
||||
RB_ENTRY(ip6_msource) im6s_link; /* RB tree links */
|
||||
struct in6_addr im6s_addr;
|
||||
struct im6s_st {
|
||||
uint16_t ex; /* # of exclusive members */
|
||||
uint16_t in; /* # of inclusive members */
|
||||
} im6s_st[2]; /* state at t0, t1 */
|
||||
uint8_t im6s_stp; /* pending query */
|
||||
};
|
||||
RB_HEAD(ip6_msource_tree, ip6_msource);
|
||||
|
||||
/*
|
||||
* IPv6 multicast PCB-layer source entry.
|
||||
*
|
||||
* NOTE: overlapping use of struct ip6_msource fields at start.
|
||||
*/
|
||||
struct in6_msource {
|
||||
RB_ENTRY(ip6_msource) im6s_link; /* Common field */
|
||||
struct in6_addr im6s_addr; /* Common field */
|
||||
uint8_t im6sl_st[2]; /* state before/at commit */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* IPv6 source tree comparison function.
|
||||
*
|
||||
* An ordered predicate is necessary; bcmp() is not documented to return
|
||||
* an indication of order, memcmp() is, and is an ISO C99 requirement.
|
||||
*/
|
||||
static __inline int
|
||||
ip6_msource_cmp(const struct ip6_msource *a, const struct ip6_msource *b)
|
||||
{
|
||||
|
||||
return (memcmp(&a->im6s_addr, &b->im6s_addr, sizeof(struct in6_addr)));
|
||||
}
|
||||
RB_PROTOTYPE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
/*
|
||||
* IPv6 multicast PCB-layer group filter descriptor.
|
||||
*/
|
||||
struct in6_mfilter {
|
||||
struct ip6_msource_tree im6f_sources; /* source list for (S,G) */
|
||||
u_long im6f_nsrc; /* # of source entries */
|
||||
uint8_t im6f_st[2]; /* state before/at commit */
|
||||
};
|
||||
|
||||
/*
|
||||
* Legacy KAME IPv6 multicast membership descriptor.
|
||||
*/
|
||||
struct in6_multi_mship {
|
||||
struct in6_multi *i6mm_maddr;
|
||||
LIST_ENTRY(in6_multi_mship) i6mm_chain;
|
||||
};
|
||||
|
||||
/*
|
||||
* IPv6 group descriptor.
|
||||
*
|
||||
* For every entry on an ifnet's if_multiaddrs list which represents
|
||||
* an IP multicast group, there is one of these structures.
|
||||
*
|
||||
* If any source filters are present, then a node will exist in the RB-tree
|
||||
* to permit fast lookup by source whenever an operation takes place.
|
||||
* This permits pre-order traversal when we issue reports.
|
||||
* Source filter trees are kept separately from the socket layer to
|
||||
* greatly simplify locking.
|
||||
*
|
||||
* When MLDv2 is active, in6m_timer is the response to group query timer.
|
||||
* The state-change timer in6m_sctimer is separate; whenever state changes
|
||||
* for the group the state change record is generated and transmitted,
|
||||
* and kept if retransmissions are necessary.
|
||||
*
|
||||
* FUTURE: in6m_link is now only used when groups are being purged
|
||||
* on a detaching ifnet. It could be demoted to a SLIST_ENTRY, but
|
||||
* because it is at the very start of the struct, we can't do this
|
||||
* w/o breaking the ABI for ifmcstat.
|
||||
*/
|
||||
struct in6_multi {
|
||||
LIST_ENTRY(in6_multi) in6m_entry; /* list glue */
|
||||
struct in6_addr in6m_addr; /* IPv6 multicast address */
|
||||
struct ifnet *in6m_ifp; /* back pointer to ifnet */
|
||||
struct ifmultiaddr *in6m_ifma; /* back pointer to ifmultiaddr */
|
||||
u_int in6m_refcount; /* reference count */
|
||||
u_int in6m_state; /* state of the membership */
|
||||
u_int in6m_timer; /* MLD6 listener report timer */
|
||||
|
||||
/* New fields for MLDv2 follow. */
|
||||
struct mld_ifinfo *in6m_mli; /* MLD info */
|
||||
SLIST_ENTRY(in6_multi) in6m_nrele; /* to-be-released by MLD */
|
||||
struct ip6_msource_tree in6m_srcs; /* tree of sources */
|
||||
u_long in6m_nsrc; /* # of tree entries */
|
||||
|
||||
struct ifqueue in6m_scq; /* queue of pending
|
||||
* state-change packets */
|
||||
struct timeval in6m_lastgsrtv; /* last G-S-R query */
|
||||
uint16_t in6m_sctimer; /* state-change timer */
|
||||
uint16_t in6m_scrv; /* state-change rexmit count */
|
||||
|
||||
/*
|
||||
* SSM state counters which track state at T0 (the time the last
|
||||
* state-change report's RV timer went to zero) and T1
|
||||
* (time of pending report, i.e. now).
|
||||
* Used for computing MLDv2 state-change reports. Several refcounts
|
||||
* are maintained here to optimize for common use-cases.
|
||||
*/
|
||||
struct in6m_st {
|
||||
uint16_t iss_fmode; /* MLD filter mode */
|
||||
uint16_t iss_asm; /* # of ASM listeners */
|
||||
uint16_t iss_ex; /* # of exclusive members */
|
||||
uint16_t iss_in; /* # of inclusive members */
|
||||
uint16_t iss_rec; /* # of recorded sources */
|
||||
} in6m_st[2]; /* state at t0, t1 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper function to derive the filter mode on a source entry
|
||||
* from its internal counters. Predicates are:
|
||||
* A source is only excluded if all listeners exclude it.
|
||||
* A source is only included if no listeners exclude it,
|
||||
* and at least one listener includes it.
|
||||
* May be used by ifmcstat(8).
|
||||
*/
|
||||
static __inline uint8_t
|
||||
im6s_get_mode(const struct in6_multi *inm, const struct ip6_msource *ims,
|
||||
uint8_t t)
|
||||
{
|
||||
|
||||
t = !!t;
|
||||
if (inm->in6m_st[t].iss_ex > 0 &&
|
||||
inm->in6m_st[t].iss_ex == ims->im6s_st[t].ex)
|
||||
return (MCAST_EXCLUDE);
|
||||
else if (ims->im6s_st[t].in > 0 && ims->im6s_st[t].ex == 0)
|
||||
return (MCAST_INCLUDE);
|
||||
return (MCAST_UNDEFINED);
|
||||
}
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* Lock macros for IPv6 layer multicast address lists. IPv6 lock goes
|
||||
* before link layer multicast locks in the lock order. In most cases,
|
||||
* consumers of IN_*_MULTI() macros should acquire the locks before
|
||||
* calling them; users of the in_{add,del}multi() functions should not.
|
||||
*/
|
||||
extern struct mtx in6_multi_mtx;
|
||||
#define IN6_MULTI_LOCK() mtx_lock(&in6_multi_mtx)
|
||||
#define IN6_MULTI_UNLOCK() mtx_unlock(&in6_multi_mtx)
|
||||
#define IN6_MULTI_LOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_OWNED)
|
||||
#define IN6_MULTI_UNLOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_NOTOWNED)
|
||||
|
||||
/*
|
||||
* Look up an in6_multi record for an IPv6 multicast address
|
||||
* on the interface ifp.
|
||||
* If no record found, return NULL.
|
||||
*
|
||||
* SMPng: The IN6_MULTI_LOCK and IF_ADDR_LOCK on ifp must be held.
|
||||
*/
|
||||
static __inline struct in6_multi *
|
||||
in6m_lookup_locked(struct ifnet *ifp, const struct in6_addr *mcaddr)
|
||||
{
|
||||
struct ifmultiaddr *ifma;
|
||||
struct in6_multi *inm;
|
||||
|
||||
IN6_MULTI_LOCK_ASSERT();
|
||||
IF_ADDR_LOCK_ASSERT(ifp);
|
||||
|
||||
inm = NULL;
|
||||
TAILQ_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family == AF_INET6) {
|
||||
inm = (struct in6_multi *)ifma->ifma_protospec;
|
||||
if (IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, mcaddr))
|
||||
break;
|
||||
inm = NULL;
|
||||
}
|
||||
}
|
||||
return (inm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for in6m_lookup_locked().
|
||||
*
|
||||
* SMPng: Assumes that neithr the IN6_MULTI_LOCK() or IF_ADDR_LOCK() are held.
|
||||
*/
|
||||
static __inline struct in6_multi *
|
||||
in6m_lookup(struct ifnet *ifp, const struct in6_addr *mcaddr)
|
||||
{
|
||||
struct in6_multi *inm;
|
||||
|
||||
IN6_MULTI_LOCK();
|
||||
IF_ADDR_LOCK(ifp);
|
||||
inm = in6m_lookup_locked(ifp, mcaddr);
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
IN6_MULTI_UNLOCK();
|
||||
|
||||
return (inm);
|
||||
}
|
||||
|
||||
/* Acquire an in6_multi record. */
|
||||
static __inline void
|
||||
in6m_acquire_locked(struct in6_multi *inm)
|
||||
{
|
||||
|
||||
IN6_MULTI_LOCK_ASSERT();
|
||||
++inm->in6m_refcount;
|
||||
}
|
||||
|
||||
struct ip6_moptions;
|
||||
struct sockopt;
|
||||
|
||||
/* Multicast KPIs. */
|
||||
int im6o_mc_filter(const struct ip6_moptions *, const struct ifnet *,
|
||||
const struct sockaddr *, const struct sockaddr *);
|
||||
int in6_mc_join(struct ifnet *, const struct in6_addr *,
|
||||
struct in6_mfilter *, struct in6_multi **, int);
|
||||
int in6_mc_join_locked(struct ifnet *, const struct in6_addr *,
|
||||
struct in6_mfilter *, struct in6_multi **, int);
|
||||
int in6_mc_leave(struct in6_multi *, struct in6_mfilter *);
|
||||
int in6_mc_leave_locked(struct in6_multi *, struct in6_mfilter *);
|
||||
void in6m_clear_recorded(struct in6_multi *);
|
||||
void in6m_commit(struct in6_multi *);
|
||||
void in6m_print(const struct in6_multi *);
|
||||
int in6m_record_source(struct in6_multi *, const struct in6_addr *);
|
||||
void in6m_release_locked(struct in6_multi *);
|
||||
void ip6_freemoptions(struct ip6_moptions *);
|
||||
int ip6_getmoptions(struct inpcb *, struct sockopt *);
|
||||
int ip6_setmoptions(struct inpcb *, struct sockopt *);
|
||||
|
||||
/* Legacy KAME multicast KPIs. */
|
||||
struct in6_multi_mship *
|
||||
in6_joingroup(struct ifnet *, struct in6_addr *, int *, int);
|
||||
int in6_leavegroup(struct in6_multi_mship *);
|
||||
|
||||
/* flags to in6_update_ifa */
|
||||
#define IN6_IFAUPDATE_DADDELAY 0x1 /* first time to configure an address */
|
||||
|
||||
int in6_mask2len __P((struct in6_addr *, u_char *));
|
||||
int in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
|
||||
struct thread *));
|
||||
int in6_update_ifa __P((struct ifnet *, struct in6_aliasreq *,
|
||||
struct in6_ifaddr *, int));
|
||||
void in6_purgeaddr __P((struct ifaddr *));
|
||||
int in6if_do_dad __P((struct ifnet *));
|
||||
void in6_purgeif __P((struct ifnet *));
|
||||
void in6_savemkludge __P((struct in6_ifaddr *));
|
||||
void *in6_domifattach __P((struct ifnet *));
|
||||
void in6_domifdetach __P((struct ifnet *, void *));
|
||||
void in6_setmaxmtu __P((void));
|
||||
int in6_if2idlen __P((struct ifnet *));
|
||||
struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *, int));
|
||||
struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *, struct in6_addr *));
|
||||
char *ip6_sprintf __P((char *, const struct in6_addr *));
|
||||
int in6_addr2zoneid __P((struct ifnet *, struct in6_addr *, u_int32_t *));
|
||||
int in6_matchlen __P((struct in6_addr *, struct in6_addr *));
|
||||
int in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int));
|
||||
void in6_prefixlen2mask __P((struct in6_addr *, int));
|
||||
int in6_prefix_ioctl __P((struct socket *, u_long, caddr_t,
|
||||
struct ifnet *));
|
||||
int in6_prefix_add_ifid __P((int, struct in6_ifaddr *));
|
||||
void in6_prefix_remove_ifid __P((int, struct in6_ifaddr *));
|
||||
void in6_purgeprefix __P((struct ifnet *));
|
||||
void in6_ifremloop(struct ifaddr *);
|
||||
void in6_ifaddloop(struct ifaddr *);
|
||||
|
||||
int in6_is_addr_deprecated __P((struct sockaddr_in6 *));
|
||||
struct inpcb;
|
||||
int in6_src_ioctl __P((u_long, caddr_t));
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET6_IN6_VAR_HH_ */
|
4
freebsd/netinet6/ip6.h
Normal file
4
freebsd/netinet6/ip6.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $KAME: ip6.h,v 1.7 2000/03/25 07:23:36 sumikawa Exp $ */
|
||||
|
||||
#error "netinet6/ip6.h is obsolete. use netinet/ip6.h"
|
41
freebsd/netinet6/ip6_ecn.h
Normal file
41
freebsd/netinet6/ip6_ecn.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*-
|
||||
* Copyright (C) 1999 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* ECN consideration on tunnel ingress/egress operation.
|
||||
* http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
|
||||
*/
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern void ip6_ecn_ingress(int, u_int32_t *, const u_int32_t *);
|
||||
extern int ip6_ecn_egress(int, const u_int32_t *, u_int32_t *);
|
||||
#endif
|
626
freebsd/netinet6/ip6_forward.c
Normal file
626
freebsd/netinet6/ip6_forward.c
Normal file
@@ -0,0 +1,626 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: ip6_forward.c,v 1.69 2001/05/17 03:48:30 itojun Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_inet.h>
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
#include <rtems/freebsd/local/opt_ipsec.h>
|
||||
#include <rtems/freebsd/local/opt_ipstealth.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/domain.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/errno.h>
|
||||
#include <rtems/freebsd/sys/time.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/syslog.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
#include <rtems/freebsd/net/pfil.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/in_systm.h>
|
||||
#include <rtems/freebsd/netinet/ip.h>
|
||||
#include <rtems/freebsd/netinet/ip_var.h>
|
||||
#include <rtems/freebsd/netinet6/in6_var.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/scope6_var.h>
|
||||
#include <rtems/freebsd/netinet/icmp6.h>
|
||||
#include <rtems/freebsd/netinet6/nd6.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in_pcb.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <rtems/freebsd/netipsec/ipsec.h>
|
||||
#include <rtems/freebsd/netipsec/ipsec6.h>
|
||||
#include <rtems/freebsd/netipsec/key.h>
|
||||
#endif /* IPSEC */
|
||||
|
||||
#include <rtems/freebsd/netinet6/ip6protosw.h>
|
||||
|
||||
/*
|
||||
* Forward a packet. If some error occurs return the sender
|
||||
* an icmp packet. Note we can't always generate a meaningful
|
||||
* icmp message because icmp doesn't have a large enough repertoire
|
||||
* of codes and types.
|
||||
*
|
||||
* If not forwarding, just drop the packet. This could be confusing
|
||||
* if ipforwarding was zero but some routing protocol was advancing
|
||||
* us as a gateway to somewhere. However, we must let the routing
|
||||
* protocol deal with that.
|
||||
*
|
||||
*/
|
||||
void
|
||||
ip6_forward(struct mbuf *m, int srcrt)
|
||||
{
|
||||
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
|
||||
struct sockaddr_in6 *dst = NULL;
|
||||
struct rtentry *rt = NULL;
|
||||
struct route_in6 rin6;
|
||||
int error, type = 0, code = 0;
|
||||
struct mbuf *mcopy = NULL;
|
||||
struct ifnet *origifp; /* maybe unnecessary */
|
||||
u_int32_t inzone, outzone;
|
||||
struct in6_addr src_in6, dst_in6;
|
||||
#ifdef IPSEC
|
||||
struct secpolicy *sp = NULL;
|
||||
int ipsecrt = 0;
|
||||
#endif
|
||||
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
|
||||
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
/*
|
||||
* Don't increment ip6s_cantforward because this is the check
|
||||
* before forwarding packet actually.
|
||||
*/
|
||||
if (ipsec6_in_reject(m, NULL)) {
|
||||
V_ipsec6stat.in_polvio++;
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
|
||||
/*
|
||||
* Do not forward packets to multicast destination (should be handled
|
||||
* by ip6_mforward().
|
||||
* Do not forward packets with unspecified source. It was discussed
|
||||
* in July 2000, on the ipngwg mailing list.
|
||||
*/
|
||||
if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
|
||||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
|
||||
if (V_ip6_log_time + V_ip6_log_interval < time_second) {
|
||||
V_ip6_log_time = time_second;
|
||||
log(LOG_DEBUG,
|
||||
"cannot forward "
|
||||
"from %s to %s nxt %d received on %s\n",
|
||||
ip6_sprintf(ip6bufs, &ip6->ip6_src),
|
||||
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
|
||||
ip6->ip6_nxt,
|
||||
if_name(m->m_pkthdr.rcvif));
|
||||
}
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef IPSTEALTH
|
||||
if (!V_ip6stealth) {
|
||||
#endif
|
||||
if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
|
||||
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
|
||||
icmp6_error(m, ICMP6_TIME_EXCEEDED,
|
||||
ICMP6_TIME_EXCEED_TRANSIT, 0);
|
||||
return;
|
||||
}
|
||||
ip6->ip6_hlim -= IPV6_HLIMDEC;
|
||||
|
||||
#ifdef IPSTEALTH
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -
|
||||
* size of IPv6 + ICMPv6 headers) bytes of the packet in case
|
||||
* we need to generate an ICMP6 message to the src.
|
||||
* Thanks to M_EXT, in most cases copy will not occur.
|
||||
*
|
||||
* It is important to save it before IPsec processing as IPsec
|
||||
* processing may modify the mbuf.
|
||||
*/
|
||||
mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
|
||||
|
||||
#ifdef IPSEC
|
||||
/* get a security policy for this packet */
|
||||
sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND,
|
||||
IP_FORWARDING, &error);
|
||||
if (sp == NULL) {
|
||||
V_ipsec6stat.out_inval++;
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
if (mcopy) {
|
||||
#if 0
|
||||
/* XXX: what icmp ? */
|
||||
#else
|
||||
m_freem(mcopy);
|
||||
#endif
|
||||
}
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
/* check policy */
|
||||
switch (sp->policy) {
|
||||
case IPSEC_POLICY_DISCARD:
|
||||
/*
|
||||
* This packet is just discarded.
|
||||
*/
|
||||
V_ipsec6stat.out_polvio++;
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
KEY_FREESP(&sp);
|
||||
if (mcopy) {
|
||||
#if 0
|
||||
/* XXX: what icmp ? */
|
||||
#else
|
||||
m_freem(mcopy);
|
||||
#endif
|
||||
}
|
||||
m_freem(m);
|
||||
return;
|
||||
|
||||
case IPSEC_POLICY_BYPASS:
|
||||
case IPSEC_POLICY_NONE:
|
||||
/* no need to do IPsec. */
|
||||
KEY_FREESP(&sp);
|
||||
goto skip_ipsec;
|
||||
|
||||
case IPSEC_POLICY_IPSEC:
|
||||
if (sp->req == NULL) {
|
||||
/* XXX should be panic ? */
|
||||
printf("ip6_forward: No IPsec request specified.\n");
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
KEY_FREESP(&sp);
|
||||
if (mcopy) {
|
||||
#if 0
|
||||
/* XXX: what icmp ? */
|
||||
#else
|
||||
m_freem(mcopy);
|
||||
#endif
|
||||
}
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
/* do IPsec */
|
||||
break;
|
||||
|
||||
case IPSEC_POLICY_ENTRUST:
|
||||
default:
|
||||
/* should be panic ?? */
|
||||
printf("ip6_forward: Invalid policy found. %d\n", sp->policy);
|
||||
KEY_FREESP(&sp);
|
||||
goto skip_ipsec;
|
||||
}
|
||||
|
||||
{
|
||||
struct ipsecrequest *isr = NULL;
|
||||
struct ipsec_output_state state;
|
||||
|
||||
/*
|
||||
* when the kernel forwards a packet, it is not proper to apply
|
||||
* IPsec transport mode to the packet is not proper. this check
|
||||
* avoid from this.
|
||||
* at present, if there is even a transport mode SA request in the
|
||||
* security policy, the kernel does not apply IPsec to the packet.
|
||||
* this check is not enough because the following case is valid.
|
||||
* ipsec esp/tunnel/xxx-xxx/require esp/transport//require;
|
||||
*/
|
||||
for (isr = sp->req; isr; isr = isr->next) {
|
||||
if (isr->saidx.mode == IPSEC_MODE_ANY)
|
||||
goto doipsectunnel;
|
||||
if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
|
||||
goto doipsectunnel;
|
||||
}
|
||||
|
||||
/*
|
||||
* if there's no need for tunnel mode IPsec, skip.
|
||||
*/
|
||||
if (!isr)
|
||||
goto skip_ipsec;
|
||||
|
||||
doipsectunnel:
|
||||
/*
|
||||
* All the extension headers will become inaccessible
|
||||
* (since they can be encrypted).
|
||||
* Don't panic, we need no more updates to extension headers
|
||||
* on inner IPv6 packet (since they are now encapsulated).
|
||||
*
|
||||
* IPv6 [ESP|AH] IPv6 [extension headers] payload
|
||||
*/
|
||||
bzero(&state, sizeof(state));
|
||||
state.m = m;
|
||||
state.ro = NULL; /* update at ipsec6_output_tunnel() */
|
||||
state.dst = NULL; /* update at ipsec6_output_tunnel() */
|
||||
|
||||
error = ipsec6_output_tunnel(&state, sp, 0);
|
||||
|
||||
m = state.m;
|
||||
KEY_FREESP(&sp);
|
||||
|
||||
if (error) {
|
||||
/* mbuf is already reclaimed in ipsec6_output_tunnel. */
|
||||
switch (error) {
|
||||
case EHOSTUNREACH:
|
||||
case ENETUNREACH:
|
||||
case EMSGSIZE:
|
||||
case ENOBUFS:
|
||||
case ENOMEM:
|
||||
break;
|
||||
default:
|
||||
printf("ip6_output (ipsec): error code %d\n", error);
|
||||
/* FALLTHROUGH */
|
||||
case ENOENT:
|
||||
/* don't show these error codes to the user */
|
||||
break;
|
||||
}
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
if (mcopy) {
|
||||
#if 0
|
||||
/* XXX: what icmp ? */
|
||||
#else
|
||||
m_freem(mcopy);
|
||||
#endif
|
||||
}
|
||||
m_freem(m);
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* In the FAST IPSec case we have already
|
||||
* re-injected the packet and it has been freed
|
||||
* by the ipsec_done() function. So, just clean
|
||||
* up after ourselves.
|
||||
*/
|
||||
m = NULL;
|
||||
goto freecopy;
|
||||
}
|
||||
|
||||
if ((m != NULL) && (ip6 != mtod(m, struct ip6_hdr *)) ){
|
||||
/*
|
||||
* now tunnel mode headers are added. we are originating
|
||||
* packet instead of forwarding the packet.
|
||||
*/
|
||||
ip6_output(m, NULL, NULL, IPV6_FORWARDING/*XXX*/, NULL, NULL,
|
||||
NULL);
|
||||
goto freecopy;
|
||||
}
|
||||
|
||||
/* adjust pointer */
|
||||
dst = (struct sockaddr_in6 *)state.dst;
|
||||
rt = state.ro ? state.ro->ro_rt : NULL;
|
||||
if (dst != NULL && rt != NULL)
|
||||
ipsecrt = 1;
|
||||
}
|
||||
if (ipsecrt)
|
||||
goto skip_routing;
|
||||
skip_ipsec:
|
||||
#endif
|
||||
|
||||
bzero(&rin6, sizeof(struct route_in6));
|
||||
dst = (struct sockaddr_in6 *)&rin6.ro_dst;
|
||||
dst->sin6_len = sizeof(struct sockaddr_in6);
|
||||
dst->sin6_family = AF_INET6;
|
||||
dst->sin6_addr = ip6->ip6_dst;
|
||||
|
||||
rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
|
||||
if (rin6.ro_rt != NULL)
|
||||
RT_UNLOCK(rin6.ro_rt);
|
||||
else {
|
||||
V_ip6stat.ip6s_noroute++;
|
||||
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
|
||||
if (mcopy) {
|
||||
icmp6_error(mcopy, ICMP6_DST_UNREACH,
|
||||
ICMP6_DST_UNREACH_NOROUTE, 0);
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
rt = rin6.ro_rt;
|
||||
#ifdef IPSEC
|
||||
skip_routing:
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Source scope check: if a packet can't be delivered to its
|
||||
* destination for the reason that the destination is beyond the scope
|
||||
* of the source address, discard the packet and return an icmp6
|
||||
* destination unreachable error with Code 2 (beyond scope of source
|
||||
* address). We use a local copy of ip6_src, since in6_setscope()
|
||||
* will possibly modify its first argument.
|
||||
* [draft-ietf-ipngwg-icmp-v3-04.txt, Section 3.1]
|
||||
*/
|
||||
src_in6 = ip6->ip6_src;
|
||||
if (in6_setscope(&src_in6, rt->rt_ifp, &outzone)) {
|
||||
/* XXX: this should not happen */
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
V_ip6stat.ip6s_badscope++;
|
||||
goto bad;
|
||||
}
|
||||
if (in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone)) {
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
V_ip6stat.ip6s_badscope++;
|
||||
goto bad;
|
||||
}
|
||||
if (inzone != outzone
|
||||
#ifdef IPSEC
|
||||
&& !ipsecrt
|
||||
#endif
|
||||
) {
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
V_ip6stat.ip6s_badscope++;
|
||||
in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
|
||||
|
||||
if (V_ip6_log_time + V_ip6_log_interval < time_second) {
|
||||
V_ip6_log_time = time_second;
|
||||
log(LOG_DEBUG,
|
||||
"cannot forward "
|
||||
"src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
|
||||
ip6_sprintf(ip6bufs, &ip6->ip6_src),
|
||||
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
|
||||
ip6->ip6_nxt,
|
||||
if_name(m->m_pkthdr.rcvif), if_name(rt->rt_ifp));
|
||||
}
|
||||
if (mcopy)
|
||||
icmp6_error(mcopy, ICMP6_DST_UNREACH,
|
||||
ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destination scope check: if a packet is going to break the scope
|
||||
* zone of packet's destination address, discard it. This case should
|
||||
* usually be prevented by appropriately-configured routing table, but
|
||||
* we need an explicit check because we may mistakenly forward the
|
||||
* packet to a different zone by (e.g.) a default route.
|
||||
*/
|
||||
dst_in6 = ip6->ip6_dst;
|
||||
if (in6_setscope(&dst_in6, m->m_pkthdr.rcvif, &inzone) != 0 ||
|
||||
in6_setscope(&dst_in6, rt->rt_ifp, &outzone) != 0 ||
|
||||
inzone != outzone) {
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
V_ip6stat.ip6s_badscope++;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
|
||||
in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
|
||||
if (mcopy) {
|
||||
u_long mtu;
|
||||
#ifdef IPSEC
|
||||
struct secpolicy *sp;
|
||||
int ipsecerror;
|
||||
size_t ipsechdrsiz;
|
||||
#endif /* IPSEC */
|
||||
|
||||
mtu = IN6_LINKMTU(rt->rt_ifp);
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* When we do IPsec tunnel ingress, we need to play
|
||||
* with the link value (decrement IPsec header size
|
||||
* from mtu value). The code is much simpler than v4
|
||||
* case, as we have the outgoing interface for
|
||||
* encapsulated packet as "rt->rt_ifp".
|
||||
*/
|
||||
sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
|
||||
IP_FORWARDING, &ipsecerror);
|
||||
if (sp) {
|
||||
ipsechdrsiz = ipsec_hdrsiz(mcopy,
|
||||
IPSEC_DIR_OUTBOUND, NULL);
|
||||
if (ipsechdrsiz < mtu)
|
||||
mtu -= ipsechdrsiz;
|
||||
}
|
||||
|
||||
/*
|
||||
* if mtu becomes less than minimum MTU,
|
||||
* tell minimum MTU (and I'll need to fragment it).
|
||||
*/
|
||||
if (mtu < IPV6_MMTU)
|
||||
mtu = IPV6_MMTU;
|
||||
#endif /* IPSEC */
|
||||
icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (rt->rt_flags & RTF_GATEWAY)
|
||||
dst = (struct sockaddr_in6 *)rt->rt_gateway;
|
||||
|
||||
/*
|
||||
* If we are to forward the packet using the same interface
|
||||
* as one we got the packet from, perhaps we should send a redirect
|
||||
* to sender to shortcut a hop.
|
||||
* Only send redirect if source is sending directly to us,
|
||||
* and if packet was not source routed (or has any options).
|
||||
* Also, don't send redirect if forwarding using a route
|
||||
* modified by a redirect.
|
||||
*/
|
||||
if (V_ip6_sendredirects && rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
|
||||
#ifdef IPSEC
|
||||
!ipsecrt &&
|
||||
#endif /* IPSEC */
|
||||
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
|
||||
if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) {
|
||||
/*
|
||||
* If the incoming interface is equal to the outgoing
|
||||
* one, and the link attached to the interface is
|
||||
* point-to-point, then it will be highly probable
|
||||
* that a routing loop occurs. Thus, we immediately
|
||||
* drop the packet and send an ICMPv6 error message.
|
||||
*
|
||||
* type/code is based on suggestion by Rich Draves.
|
||||
* not sure if it is the best pick.
|
||||
*/
|
||||
icmp6_error(mcopy, ICMP6_DST_UNREACH,
|
||||
ICMP6_DST_UNREACH_ADDR, 0);
|
||||
goto bad;
|
||||
}
|
||||
type = ND_REDIRECT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fake scoped addresses. Note that even link-local source or
|
||||
* destinaion can appear, if the originating node just sends the
|
||||
* packet to us (without address resolution for the destination).
|
||||
* Since both icmp6_error and icmp6_redirect_output fill the embedded
|
||||
* link identifiers, we can do this stuff after making a copy for
|
||||
* returning an error.
|
||||
*/
|
||||
if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
|
||||
/*
|
||||
* See corresponding comments in ip6_output.
|
||||
* XXX: but is it possible that ip6_forward() sends a packet
|
||||
* to a loopback interface? I don't think so, and thus
|
||||
* I bark here. (jinmei@kame.net)
|
||||
* XXX: it is common to route invalid packets to loopback.
|
||||
* also, the codepath will be visited on use of ::1 in
|
||||
* rthdr. (itojun)
|
||||
*/
|
||||
#if 1
|
||||
if (0)
|
||||
#else
|
||||
if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
|
||||
#endif
|
||||
{
|
||||
printf("ip6_forward: outgoing interface is loopback. "
|
||||
"src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
|
||||
ip6_sprintf(ip6bufs, &ip6->ip6_src),
|
||||
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
|
||||
ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
|
||||
if_name(rt->rt_ifp));
|
||||
}
|
||||
|
||||
/* we can just use rcvif in forwarding. */
|
||||
origifp = m->m_pkthdr.rcvif;
|
||||
}
|
||||
else
|
||||
origifp = rt->rt_ifp;
|
||||
/*
|
||||
* clear embedded scope identifiers if necessary.
|
||||
* in6_clearscope will touch the addresses only when necessary.
|
||||
*/
|
||||
in6_clearscope(&ip6->ip6_src);
|
||||
in6_clearscope(&ip6->ip6_dst);
|
||||
|
||||
/* Jump over all PFIL processing if hooks are not active. */
|
||||
if (!PFIL_HOOKED(&V_inet6_pfil_hook))
|
||||
goto pass;
|
||||
|
||||
/* Run through list of hooks for output packets. */
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
|
||||
if (error != 0)
|
||||
goto senderr;
|
||||
if (m == NULL)
|
||||
goto freecopy;
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
||||
pass:
|
||||
error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
|
||||
if (error) {
|
||||
in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
} else {
|
||||
V_ip6stat.ip6s_forward++;
|
||||
in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward);
|
||||
if (type)
|
||||
V_ip6stat.ip6s_redirectsent++;
|
||||
else {
|
||||
if (mcopy)
|
||||
goto freecopy;
|
||||
}
|
||||
}
|
||||
|
||||
senderr:
|
||||
if (mcopy == NULL)
|
||||
goto out;
|
||||
switch (error) {
|
||||
case 0:
|
||||
if (type == ND_REDIRECT) {
|
||||
icmp6_redirect_output(mcopy, rt);
|
||||
goto out;
|
||||
}
|
||||
goto freecopy;
|
||||
|
||||
case EMSGSIZE:
|
||||
/* xxx MTU is constant in PPP? */
|
||||
goto freecopy;
|
||||
|
||||
case ENOBUFS:
|
||||
/* Tell source to slow down like source quench in IP? */
|
||||
goto freecopy;
|
||||
|
||||
case ENETUNREACH: /* shouldn't happen, checked above */
|
||||
case EHOSTUNREACH:
|
||||
case ENETDOWN:
|
||||
case EHOSTDOWN:
|
||||
default:
|
||||
type = ICMP6_DST_UNREACH;
|
||||
code = ICMP6_DST_UNREACH_ADDR;
|
||||
break;
|
||||
}
|
||||
icmp6_error(mcopy, type, code, 0);
|
||||
goto out;
|
||||
|
||||
freecopy:
|
||||
m_freem(mcopy);
|
||||
goto out;
|
||||
bad:
|
||||
m_freem(m);
|
||||
out:
|
||||
if (rt != NULL
|
||||
#ifdef IPSEC
|
||||
&& !ipsecrt
|
||||
#endif
|
||||
)
|
||||
RTFREE(rt);
|
||||
}
|
269
freebsd/netinet6/ip6_id.c
Normal file
269
freebsd/netinet6/ip6_id.c
Normal file
@@ -0,0 +1,269 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 2003 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: ip6_id.c,v 1.13 2003/09/16 09:11:19 itojun Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright 1998 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
|
||||
* such a mathematical system to generate more random (yet non-repeating)
|
||||
* ids to solve the resolver/named problem. But Niels designed the
|
||||
* actual system based on the constraints.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Niels Provos.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* seed = random (bits - 1) bit
|
||||
* n = prime, g0 = generator to n,
|
||||
* j = random so that gcd(j,n-1) == 1
|
||||
* g = g0^j mod n will be a generator again.
|
||||
*
|
||||
* X[0] = random seed.
|
||||
* X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
|
||||
* with a = 7^(even random) mod m,
|
||||
* b = random with gcd(b,m) == 1
|
||||
* m = constant and a maximal period of m-1.
|
||||
*
|
||||
* The transaction id is determined by:
|
||||
* id[n] = seed xor (g^X[n] mod n)
|
||||
*
|
||||
* Effectivly the id is restricted to the lower (bits - 1) bits, thus
|
||||
* yielding two different cycles by toggling the msb on and off.
|
||||
* This avoids reuse issues caused by reseeding.
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/types.h>
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/libkern.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX 0x7fffffffU
|
||||
#endif
|
||||
|
||||
struct randomtab {
|
||||
const int ru_bits; /* resulting bits */
|
||||
const long ru_out; /* Time after wich will be reseeded */
|
||||
const u_int32_t ru_max; /* Uniq cycle, avoid blackjack prediction */
|
||||
const u_int32_t ru_gen; /* Starting generator */
|
||||
const u_int32_t ru_n; /* ru_n: prime, ru_n - 1: product of pfacts[] */
|
||||
const u_int32_t ru_agen; /* determine ru_a as ru_agen^(2*rand) */
|
||||
const u_int32_t ru_m; /* ru_m = 2^x*3^y */
|
||||
const u_int32_t pfacts[4]; /* factors of ru_n */
|
||||
|
||||
u_int32_t ru_counter;
|
||||
u_int32_t ru_msb;
|
||||
|
||||
u_int32_t ru_x;
|
||||
u_int32_t ru_seed, ru_seed2;
|
||||
u_int32_t ru_a, ru_b;
|
||||
u_int32_t ru_g;
|
||||
long ru_reseed;
|
||||
};
|
||||
|
||||
static struct randomtab randomtab_32 = {
|
||||
32, /* resulting bits */
|
||||
180, /* Time after wich will be reseeded */
|
||||
1000000000, /* Uniq cycle, avoid blackjack prediction */
|
||||
2, /* Starting generator */
|
||||
2147483629, /* RU_N-1 = 2^2*3^2*59652323 */
|
||||
7, /* determine ru_a as RU_AGEN^(2*rand) */
|
||||
1836660096, /* RU_M = 2^7*3^15 - don't change */
|
||||
{ 2, 3, 59652323, 0 }, /* factors of ru_n */
|
||||
};
|
||||
|
||||
static struct randomtab randomtab_20 = {
|
||||
20, /* resulting bits */
|
||||
180, /* Time after wich will be reseeded */
|
||||
200000, /* Uniq cycle, avoid blackjack prediction */
|
||||
2, /* Starting generator */
|
||||
524269, /* RU_N-1 = 2^2*3^2*14563 */
|
||||
7, /* determine ru_a as RU_AGEN^(2*rand) */
|
||||
279936, /* RU_M = 2^7*3^7 - don't change */
|
||||
{ 2, 3, 14563, 0 }, /* factors of ru_n */
|
||||
};
|
||||
|
||||
static u_int32_t pmod(u_int32_t, u_int32_t, u_int32_t);
|
||||
static void initid(struct randomtab *);
|
||||
static u_int32_t randomid(struct randomtab *);
|
||||
|
||||
/*
|
||||
* Do a fast modular exponation, returned value will be in the range
|
||||
* of 0 - (mod-1)
|
||||
*/
|
||||
static u_int32_t
|
||||
pmod(u_int32_t gen, u_int32_t expo, u_int32_t mod)
|
||||
{
|
||||
u_int64_t s, t, u;
|
||||
|
||||
s = 1;
|
||||
t = gen;
|
||||
u = expo;
|
||||
|
||||
while (u) {
|
||||
if (u & 1)
|
||||
s = (s * t) % mod;
|
||||
u >>= 1;
|
||||
t = (t * t) % mod;
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initalizes the seed and chooses a suitable generator. Also toggles
|
||||
* the msb flag. The msb flag is used to generate two distinct
|
||||
* cycles of random numbers and thus avoiding reuse of ids.
|
||||
*
|
||||
* This function is called from id_randomid() when needed, an
|
||||
* application does not have to worry about it.
|
||||
*/
|
||||
static void
|
||||
initid(struct randomtab *p)
|
||||
{
|
||||
u_int32_t j, i;
|
||||
int noprime = 1;
|
||||
|
||||
p->ru_x = arc4random() % p->ru_m;
|
||||
|
||||
/* (bits - 1) bits of random seed */
|
||||
p->ru_seed = arc4random() & (~0U >> (32 - p->ru_bits + 1));
|
||||
p->ru_seed2 = arc4random() & (~0U >> (32 - p->ru_bits + 1));
|
||||
|
||||
/* Determine the LCG we use */
|
||||
p->ru_b = (arc4random() & (~0U >> (32 - p->ru_bits))) | 1;
|
||||
p->ru_a = pmod(p->ru_agen,
|
||||
(arc4random() & (~0U >> (32 - p->ru_bits))) & (~1U), p->ru_m);
|
||||
while (p->ru_b % 3 == 0)
|
||||
p->ru_b += 2;
|
||||
|
||||
j = arc4random() % p->ru_n;
|
||||
|
||||
/*
|
||||
* Do a fast gcd(j, RU_N - 1), so we can find a j with
|
||||
* gcd(j, RU_N - 1) == 1, giving a new generator for
|
||||
* RU_GEN^j mod RU_N
|
||||
*/
|
||||
while (noprime) {
|
||||
for (i = 0; p->pfacts[i] > 0; i++)
|
||||
if (j % p->pfacts[i] == 0)
|
||||
break;
|
||||
|
||||
if (p->pfacts[i] == 0)
|
||||
noprime = 0;
|
||||
else
|
||||
j = (j + 1) % p->ru_n;
|
||||
}
|
||||
|
||||
p->ru_g = pmod(p->ru_gen, j, p->ru_n);
|
||||
p->ru_counter = 0;
|
||||
|
||||
p->ru_reseed = time_second + p->ru_out;
|
||||
p->ru_msb = p->ru_msb ? 0 : (1U << (p->ru_bits - 1));
|
||||
}
|
||||
|
||||
static u_int32_t
|
||||
randomid(struct randomtab *p)
|
||||
{
|
||||
int i, n;
|
||||
u_int32_t tmp;
|
||||
|
||||
if (p->ru_counter >= p->ru_max || time_second > p->ru_reseed)
|
||||
initid(p);
|
||||
|
||||
tmp = arc4random();
|
||||
|
||||
/* Skip a random number of ids */
|
||||
n = tmp & 0x3; tmp = tmp >> 2;
|
||||
if (p->ru_counter + n >= p->ru_max)
|
||||
initid(p);
|
||||
|
||||
for (i = 0; i <= n; i++) {
|
||||
/* Linear Congruential Generator */
|
||||
p->ru_x = (u_int32_t)((u_int64_t)p->ru_a * p->ru_x + p->ru_b) % p->ru_m;
|
||||
}
|
||||
|
||||
p->ru_counter += i;
|
||||
|
||||
return (p->ru_seed ^ pmod(p->ru_g, p->ru_seed2 ^ p->ru_x, p->ru_n)) |
|
||||
p->ru_msb;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
ip6_randomid(void)
|
||||
{
|
||||
|
||||
return randomid(&randomtab_32);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
ip6_randomflowlabel(void)
|
||||
{
|
||||
|
||||
return randomid(&randomtab_20) & 0xfffff;
|
||||
}
|
1759
freebsd/netinet6/ip6_input.c
Normal file
1759
freebsd/netinet6/ip6_input.c
Normal file
File diff suppressed because it is too large
Load Diff
386
freebsd/netinet6/ip6_ipsec.c
Normal file
386
freebsd/netinet6/ip6_ipsec.c
Normal file
@@ -0,0 +1,386 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
#include <rtems/freebsd/local/opt_ipsec.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/kernel.h>
|
||||
#include <rtems/freebsd/sys/mac.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/socketvar.h>
|
||||
#include <rtems/freebsd/sys/sysctl.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
#include <rtems/freebsd/net/vnet.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_systm.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/ip.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet/in_pcb.h>
|
||||
#include <rtems/freebsd/netinet/ip_var.h>
|
||||
#include <rtems/freebsd/netinet/ip_options.h>
|
||||
|
||||
#include <rtems/freebsd/machine/in_cksum.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <rtems/freebsd/netipsec/ipsec.h>
|
||||
#include <rtems/freebsd/netipsec/ipsec6.h>
|
||||
#include <rtems/freebsd/netipsec/xform.h>
|
||||
#include <rtems/freebsd/netipsec/key.h>
|
||||
#ifdef IPSEC_DEBUG
|
||||
#include <rtems/freebsd/netipsec/key_debug.h>
|
||||
#else
|
||||
#define KEYDEBUG(lev,arg)
|
||||
#endif
|
||||
#endif /*IPSEC*/
|
||||
|
||||
#include <rtems/freebsd/netinet6/ip6_ipsec.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
|
||||
extern struct protosw inet6sw[];
|
||||
|
||||
|
||||
#ifdef INET6
|
||||
#ifdef IPSEC
|
||||
#ifdef IPSEC_FILTERTUNNEL
|
||||
static VNET_DEFINE(int, ip6_ipsec6_filtertunnel) = 1;
|
||||
#else
|
||||
static VNET_DEFINE(int, ip6_ipsec6_filtertunnel) = 0;
|
||||
#endif
|
||||
#define V_ip6_ipsec6_filtertunnel VNET(ip6_ipsec6_filtertunnel)
|
||||
|
||||
SYSCTL_DECL(_net_inet6_ipsec6);
|
||||
SYSCTL_VNET_INT(_net_inet6_ipsec6, OID_AUTO,
|
||||
filtertunnel, CTLFLAG_RW, &VNET_NAME(ip6_ipsec6_filtertunnel), 0,
|
||||
"If set filter packets from an IPsec tunnel.");
|
||||
#endif /* IPSEC */
|
||||
#endif /* INET6 */
|
||||
|
||||
/*
|
||||
* Check if we have to jump over firewall processing for this packet.
|
||||
* Called from ip_input().
|
||||
* 1 = jump over firewall, 0 = packet goes through firewall.
|
||||
*/
|
||||
int
|
||||
ip6_ipsec_filtertunnel(struct mbuf *m)
|
||||
{
|
||||
#if defined(IPSEC)
|
||||
|
||||
/*
|
||||
* Bypass packet filtering for packets from a tunnel.
|
||||
*/
|
||||
if (!V_ip6_ipsec6_filtertunnel &&
|
||||
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if this packet has an active SA and needs to be dropped instead
|
||||
* of forwarded.
|
||||
* Called from ip_input().
|
||||
* 1 = drop packet, 0 = forward packet.
|
||||
*/
|
||||
int
|
||||
ip6_ipsec_fwd(struct mbuf *m)
|
||||
{
|
||||
#ifdef IPSEC
|
||||
struct m_tag *mtag;
|
||||
struct tdb_ident *tdbi;
|
||||
struct secpolicy *sp;
|
||||
int s, error;
|
||||
mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
|
||||
s = splnet();
|
||||
if (mtag != NULL) {
|
||||
tdbi = (struct tdb_ident *)(mtag + 1);
|
||||
sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
|
||||
} else {
|
||||
sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
|
||||
IP_FORWARDING, &error);
|
||||
}
|
||||
if (sp == NULL) { /* NB: can happen if error */
|
||||
splx(s);
|
||||
/*XXX error stat???*/
|
||||
DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check security policy against packet attributes.
|
||||
*/
|
||||
error = ipsec_in_reject(sp, m);
|
||||
KEY_FREESP(&sp);
|
||||
splx(s);
|
||||
if (error) {
|
||||
V_ip6stat.ip6s_cantforward++;
|
||||
return 1;
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if protocol type doesn't have a further header and do IPSEC
|
||||
* decryption or reject right now. Protocols with further headers get
|
||||
* their IPSEC treatment within the protocol specific processing.
|
||||
* Called from ip_input().
|
||||
* 1 = drop packet, 0 = continue processing packet.
|
||||
*/
|
||||
int
|
||||
ip6_ipsec_input(struct mbuf *m, int nxt)
|
||||
{
|
||||
#ifdef IPSEC
|
||||
struct m_tag *mtag;
|
||||
struct tdb_ident *tdbi;
|
||||
struct secpolicy *sp;
|
||||
int s, error;
|
||||
/*
|
||||
* enforce IPsec policy checking if we are seeing last header.
|
||||
* note that we do not visit this with protocols with pcb layer
|
||||
* code - like udp/tcp/raw ip.
|
||||
*/
|
||||
if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
|
||||
ipsec6_in_reject(m, NULL)) {
|
||||
|
||||
/*
|
||||
* Check if the packet has already had IPsec processing
|
||||
* done. If so, then just pass it along. This tag gets
|
||||
* set during AH, ESP, etc. input handling, before the
|
||||
* packet is returned to the ip input queue for delivery.
|
||||
*/
|
||||
mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
|
||||
s = splnet();
|
||||
if (mtag != NULL) {
|
||||
tdbi = (struct tdb_ident *)(mtag + 1);
|
||||
sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
|
||||
} else {
|
||||
sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
|
||||
IP_FORWARDING, &error);
|
||||
}
|
||||
if (sp != NULL) {
|
||||
/*
|
||||
* Check security policy against packet attributes.
|
||||
*/
|
||||
error = ipsec_in_reject(sp, m);
|
||||
KEY_FREESP(&sp);
|
||||
} else {
|
||||
/* XXX error stat??? */
|
||||
error = EINVAL;
|
||||
DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
|
||||
return 1;
|
||||
}
|
||||
splx(s);
|
||||
if (error)
|
||||
return 1;
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from ip6_output().
|
||||
* 1 = drop packet, 0 = continue processing packet,
|
||||
* -1 = packet was reinjected and stop processing packet
|
||||
*/
|
||||
|
||||
int
|
||||
ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
|
||||
struct ifnet **ifp, struct secpolicy **sp)
|
||||
{
|
||||
#ifdef IPSEC
|
||||
struct tdb_ident *tdbi;
|
||||
struct m_tag *mtag;
|
||||
/* XXX int s; */
|
||||
if (sp == NULL)
|
||||
return 1;
|
||||
mtag = m_tag_find(*m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
|
||||
if (mtag != NULL) {
|
||||
tdbi = (struct tdb_ident *)(mtag + 1);
|
||||
*sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
|
||||
if (*sp == NULL)
|
||||
*error = -EINVAL; /* force silent drop */
|
||||
m_tag_delete(*m, mtag);
|
||||
} else {
|
||||
*sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags,
|
||||
error, inp);
|
||||
}
|
||||
|
||||
/*
|
||||
* There are four return cases:
|
||||
* sp != NULL apply IPsec policy
|
||||
* sp == NULL, error == 0 no IPsec handling needed
|
||||
* sp == NULL, error == -EINVAL discard packet w/o error
|
||||
* sp == NULL, error != 0 discard packet, report error
|
||||
*/
|
||||
if (*sp != NULL) {
|
||||
/* Loop detection, check if ipsec processing already done */
|
||||
KASSERT((*sp)->req != NULL, ("ip_output: no ipsec request"));
|
||||
for (mtag = m_tag_first(*m); mtag != NULL;
|
||||
mtag = m_tag_next(*m, mtag)) {
|
||||
if (mtag->m_tag_cookie != MTAG_ABI_COMPAT)
|
||||
continue;
|
||||
if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE &&
|
||||
mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
|
||||
continue;
|
||||
/*
|
||||
* Check if policy has an SA associated with it.
|
||||
* This can happen when an SP has yet to acquire
|
||||
* an SA; e.g. on first reference. If it occurs,
|
||||
* then we let ipsec4_process_packet do its thing.
|
||||
*/
|
||||
if ((*sp)->req->sav == NULL)
|
||||
break;
|
||||
tdbi = (struct tdb_ident *)(mtag + 1);
|
||||
if (tdbi->spi == (*sp)->req->sav->spi &&
|
||||
tdbi->proto == (*sp)->req->sav->sah->saidx.proto &&
|
||||
bcmp(&tdbi->dst, &(*sp)->req->sav->sah->saidx.dst,
|
||||
sizeof (union sockaddr_union)) == 0) {
|
||||
/*
|
||||
* No IPsec processing is needed, free
|
||||
* reference to SP.
|
||||
*
|
||||
* NB: null pointer to avoid free at
|
||||
* done: below.
|
||||
*/
|
||||
KEY_FREESP(sp), *sp = NULL;
|
||||
/* XXX splx(s); */
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do delayed checksums now because we send before
|
||||
* this is done in the normal processing path.
|
||||
*/
|
||||
if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
|
||||
in_delayed_cksum(*m);
|
||||
(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preserve KAME behaviour: ENOENT can be returned
|
||||
* when an SA acquire is in progress. Don't propagate
|
||||
* this to user-level; it confuses applications.
|
||||
*
|
||||
* XXX this will go away when the SADB is redone.
|
||||
*/
|
||||
if (*error == ENOENT)
|
||||
*error = 0;
|
||||
goto do_ipsec;
|
||||
} else { /* sp == NULL */
|
||||
if (*error != 0) {
|
||||
/*
|
||||
* Hack: -EINVAL is used to signal that a packet
|
||||
* should be silently discarded. This is typically
|
||||
* because we asked key management for an SA and
|
||||
* it was delayed (e.g. kicked up to IKE).
|
||||
*/
|
||||
if (*error == -EINVAL)
|
||||
*error = 0;
|
||||
goto bad;
|
||||
} else {
|
||||
/* No IPsec processing for this packet. */
|
||||
}
|
||||
}
|
||||
done:
|
||||
return 0;
|
||||
do_ipsec:
|
||||
return -1;
|
||||
bad:
|
||||
return 1;
|
||||
#endif /* IPSEC */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Compute the MTU for a forwarded packet that gets IPSEC encapsulated.
|
||||
* Called from ip_forward().
|
||||
* Returns MTU suggestion for ICMP needfrag reply.
|
||||
*/
|
||||
int
|
||||
ip6_ipsec_mtu(struct mbuf *m)
|
||||
{
|
||||
int mtu = 0;
|
||||
/*
|
||||
* If the packet is routed over IPsec tunnel, tell the
|
||||
* originator the tunnel MTU.
|
||||
* tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
|
||||
* XXX quickhack!!!
|
||||
*/
|
||||
#ifdef IPSEC
|
||||
struct secpolicy *sp = NULL;
|
||||
int ipsecerror;
|
||||
int ipsechdr;
|
||||
struct route *ro;
|
||||
sp = ipsec_getpolicybyaddr(m,
|
||||
IPSEC_DIR_OUTBOUND,
|
||||
IP_FORWARDING,
|
||||
&ipsecerror);
|
||||
if (sp != NULL) {
|
||||
/* count IPsec header size */
|
||||
ipsechdr = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, NULL);
|
||||
|
||||
/*
|
||||
* find the correct route for outer IPv4
|
||||
* header, compute tunnel MTU.
|
||||
*/
|
||||
if (sp->req != NULL &&
|
||||
sp->req->sav != NULL &&
|
||||
sp->req->sav->sah != NULL) {
|
||||
ro = &sp->req->sav->sah->route_cache.sa_route;
|
||||
if (ro->ro_rt && ro->ro_rt->rt_ifp) {
|
||||
mtu =
|
||||
ro->ro_rt->rt_rmx.rmx_mtu ?
|
||||
ro->ro_rt->rt_rmx.rmx_mtu :
|
||||
ro->ro_rt->rt_ifp->if_mtu;
|
||||
mtu -= ipsechdr;
|
||||
}
|
||||
}
|
||||
KEY_FREESP(&sp);
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
/* XXX else case missing. */
|
||||
return mtu;
|
||||
}
|
||||
#endif
|
43
freebsd/netinet6/ip6_ipsec.h
Normal file
43
freebsd/netinet6/ip6_ipsec.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET_IP6_IPSEC_HH_
|
||||
#define _NETINET_IP6_IPSEC_HH_
|
||||
|
||||
int ip6_ipsec_filtertunnel(struct mbuf *);
|
||||
int ip6_ipsec_fwd(struct mbuf *);
|
||||
int ip6_ipsec_input(struct mbuf *, int);
|
||||
int ip6_ipsec_output(struct mbuf **, struct inpcb *, int *, int *,
|
||||
struct ifnet **, struct secpolicy **sp);
|
||||
#if 0
|
||||
int ip6_ipsec_mtu(struct mbuf *);
|
||||
#endif
|
||||
#endif
|
2065
freebsd/netinet6/ip6_mroute.c
Normal file
2065
freebsd/netinet6/ip6_mroute.c
Normal file
File diff suppressed because it is too large
Load Diff
271
freebsd/netinet6/ip6_mroute.h
Normal file
271
freebsd/netinet6/ip6_mroute.h
Normal file
@@ -0,0 +1,271 @@
|
||||
/*-
|
||||
* Copyright (C) 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: ip6_mroute.h,v 1.19 2001/06/14 06:12:55 suz Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* BSDI ip_mroute.h,v 2.5 1996/10/11 16:01:48 pjd Exp */
|
||||
|
||||
/*
|
||||
* Definitions for IP multicast forwarding.
|
||||
*
|
||||
* Written by David Waitzman, BBN Labs, August 1988.
|
||||
* Modified by Steve Deering, Stanford, February 1989.
|
||||
* Modified by Ajit Thyagarajan, PARC, August 1993.
|
||||
* Modified by Ajit Thyagarajan, PARC, August 1994.
|
||||
* Modified by Ahmed Helmy, USC, September 1996.
|
||||
*
|
||||
* MROUTING Revision: 1.2
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IP6_MROUTE_HH_
|
||||
#define _NETINET6_IP6_MROUTE_HH_
|
||||
|
||||
/*
|
||||
* Multicast Routing set/getsockopt commands.
|
||||
*/
|
||||
#ifdef _KERNEL
|
||||
#define MRT6_OINIT 100 /* initialize forwarder (omrt6msg) */
|
||||
#endif
|
||||
#define MRT6_DONE 101 /* shut down forwarder */
|
||||
#define MRT6_ADD_MIF 102 /* add multicast interface */
|
||||
#define MRT6_DEL_MIF 103 /* delete multicast interface */
|
||||
#define MRT6_ADD_MFC 104 /* insert forwarding cache entry */
|
||||
#define MRT6_DEL_MFC 105 /* delete forwarding cache entry */
|
||||
#define MRT6_PIM 107 /* enable pim code */
|
||||
#define MRT6_INIT 108 /* initialize forwarder (mrt6msg) */
|
||||
|
||||
#if BSD >= 199103
|
||||
#define GET_TIME(t) microtime(&t)
|
||||
#elif defined(sun)
|
||||
#define GET_TIME(t) uniqtime(&t)
|
||||
#else
|
||||
#define GET_TIME(t) ((t) = time)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Types and macros for handling bitmaps with one bit per multicast interface.
|
||||
*/
|
||||
typedef u_short mifi_t; /* type of a mif index */
|
||||
#define MAXMIFS 64
|
||||
|
||||
#ifndef IF_SETSIZE
|
||||
#define IF_SETSIZE 256
|
||||
#endif
|
||||
|
||||
typedef u_int32_t if_mask;
|
||||
#define NIFBITS (sizeof(if_mask) * NBBY) /* bits per mask */
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
|
||||
#endif
|
||||
|
||||
typedef struct if_set {
|
||||
if_mask ifs_bits[howmany(IF_SETSIZE, NIFBITS)];
|
||||
} if_set;
|
||||
|
||||
#define IF_SET(n, p) ((p)->ifs_bits[(n)/NIFBITS] |= (1 << ((n) % NIFBITS)))
|
||||
#define IF_CLR(n, p) ((p)->ifs_bits[(n)/NIFBITS] &= ~(1 << ((n) % NIFBITS)))
|
||||
#define IF_ISSET(n, p) ((p)->ifs_bits[(n)/NIFBITS] & (1 << ((n) % NIFBITS)))
|
||||
#define IF_COPY(f, t) bcopy(f, t, sizeof(*(f)))
|
||||
#define IF_ZERO(p) bzero(p, sizeof(*(p)))
|
||||
|
||||
/*
|
||||
* Argument structure for MRT6_ADD_IF.
|
||||
*/
|
||||
struct mif6ctl {
|
||||
mifi_t mif6c_mifi; /* the index of the mif to be added */
|
||||
u_char mif6c_flags; /* MIFF_ flags defined below */
|
||||
u_short mif6c_pifi; /* the index of the physical IF */
|
||||
};
|
||||
|
||||
#define MIFF_REGISTER 0x1 /* mif represents a register end-point */
|
||||
|
||||
/*
|
||||
* Argument structure for MRT6_ADD_MFC and MRT6_DEL_MFC
|
||||
*/
|
||||
struct mf6cctl {
|
||||
struct sockaddr_in6 mf6cc_origin; /* IPv6 origin of mcasts */
|
||||
struct sockaddr_in6 mf6cc_mcastgrp; /* multicast group associated */
|
||||
mifi_t mf6cc_parent; /* incoming ifindex */
|
||||
struct if_set mf6cc_ifset; /* set of forwarding ifs */
|
||||
};
|
||||
|
||||
/*
|
||||
* The kernel's multicast routing statistics.
|
||||
*/
|
||||
struct mrt6stat {
|
||||
u_quad_t mrt6s_mfc_lookups; /* # forw. cache hash table hits */
|
||||
u_quad_t mrt6s_mfc_misses; /* # forw. cache hash table misses */
|
||||
u_quad_t mrt6s_upcalls; /* # calls to multicast routing daemon */
|
||||
u_quad_t mrt6s_no_route; /* no route for packet's origin */
|
||||
u_quad_t mrt6s_bad_tunnel; /* malformed tunnel options */
|
||||
u_quad_t mrt6s_cant_tunnel; /* no room for tunnel options */
|
||||
u_quad_t mrt6s_wrong_if; /* arrived on wrong interface */
|
||||
u_quad_t mrt6s_upq_ovflw; /* upcall Q overflow */
|
||||
u_quad_t mrt6s_cache_cleanups; /* # entries with no upcalls */
|
||||
u_quad_t mrt6s_drop_sel; /* pkts dropped selectively */
|
||||
u_quad_t mrt6s_q_overflow; /* pkts dropped - Q overflow */
|
||||
u_quad_t mrt6s_pkt2large; /* pkts dropped - size > BKT SIZE */
|
||||
u_quad_t mrt6s_upq_sockfull; /* upcalls dropped - socket full */
|
||||
};
|
||||
|
||||
#ifdef MRT6_OINIT
|
||||
/*
|
||||
* Struct used to communicate from kernel to multicast router
|
||||
* note the convenient similarity to an IPv6 header.
|
||||
* XXX old version, superseded by mrt6msg.
|
||||
*/
|
||||
struct omrt6msg {
|
||||
u_long unused1;
|
||||
u_char im6_msgtype; /* what type of message */
|
||||
#if 0
|
||||
#define MRT6MSG_NOCACHE 1
|
||||
#define MRT6MSG_WRONGMIF 2
|
||||
#define MRT6MSG_WHOLEPKT 3 /* used for user level encap*/
|
||||
#endif
|
||||
u_char im6_mbz; /* must be zero */
|
||||
u_char im6_mif; /* mif rec'd on */
|
||||
u_char unused2;
|
||||
struct in6_addr im6_src, im6_dst;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure used to communicate from kernel to multicast router.
|
||||
* We'll overlay the structure onto an MLD header (not an IPv6 header
|
||||
* like igmpmsg{} used for IPv4 implementation). This is because this
|
||||
* structure will be passed via an IPv6 raw socket, on which an application
|
||||
* will only receive the payload i.e. the data after the IPv6 header and all
|
||||
* the extension headers. (see Section 3 of RFC3542)
|
||||
*/
|
||||
struct mrt6msg {
|
||||
#define MRT6MSG_NOCACHE 1
|
||||
#define MRT6MSG_WRONGMIF 2
|
||||
#define MRT6MSG_WHOLEPKT 3 /* used for user level encap*/
|
||||
u_char im6_mbz; /* must be zero */
|
||||
u_char im6_msgtype; /* what type of message */
|
||||
u_int16_t im6_mif; /* mif rec'd on */
|
||||
u_int32_t im6_pad; /* padding for 64bit arch */
|
||||
struct in6_addr im6_src, im6_dst;
|
||||
};
|
||||
|
||||
/*
|
||||
* Argument structure used by multicast routing daemon to get src-grp
|
||||
* packet counts
|
||||
*/
|
||||
struct sioc_sg_req6 {
|
||||
struct sockaddr_in6 src;
|
||||
struct sockaddr_in6 grp;
|
||||
u_quad_t pktcnt;
|
||||
u_quad_t bytecnt;
|
||||
u_quad_t wrong_if;
|
||||
};
|
||||
|
||||
/*
|
||||
* Argument structure used by mrouted to get mif pkt counts
|
||||
*/
|
||||
struct sioc_mif_req6 {
|
||||
mifi_t mifi; /* mif number */
|
||||
u_quad_t icount; /* Input packet count on mif */
|
||||
u_quad_t ocount; /* Output packet count on mif */
|
||||
u_quad_t ibytes; /* Input byte count on mif */
|
||||
u_quad_t obytes; /* Output byte count on mif */
|
||||
};
|
||||
|
||||
#if defined(_KERNEL) || defined(KERNEL)
|
||||
/*
|
||||
* The kernel's multicast-interface structure.
|
||||
*/
|
||||
struct mif6 {
|
||||
u_char m6_flags; /* MIFF_ flags defined above */
|
||||
u_int m6_rate_limit; /* max rate */
|
||||
struct in6_addr m6_lcl_addr; /* local interface address */
|
||||
struct ifnet *m6_ifp; /* pointer to interface */
|
||||
u_quad_t m6_pkt_in; /* # pkts in on interface */
|
||||
u_quad_t m6_pkt_out; /* # pkts out on interface */
|
||||
u_quad_t m6_bytes_in; /* # bytes in on interface */
|
||||
u_quad_t m6_bytes_out; /* # bytes out on interface */
|
||||
struct route_in6 m6_route; /* cached route */
|
||||
#ifdef notyet
|
||||
u_int m6_rsvp_on; /* RSVP listening on this vif */
|
||||
struct socket *m6_rsvpd; /* RSVP daemon socket */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* The kernel's multicast forwarding cache entry structure
|
||||
*/
|
||||
struct mf6c {
|
||||
struct sockaddr_in6 mf6c_origin; /* IPv6 origin of mcasts */
|
||||
struct sockaddr_in6 mf6c_mcastgrp; /* multicast group associated*/
|
||||
mifi_t mf6c_parent; /* incoming IF */
|
||||
struct if_set mf6c_ifset; /* set of outgoing IFs */
|
||||
|
||||
u_quad_t mf6c_pkt_cnt; /* pkt count for src-grp */
|
||||
u_quad_t mf6c_byte_cnt; /* byte count for src-grp */
|
||||
u_quad_t mf6c_wrong_if; /* wrong if for src-grp */
|
||||
int mf6c_expire; /* time to clean entry up */
|
||||
struct timeval mf6c_last_assert; /* last time I sent an assert*/
|
||||
struct rtdetq *mf6c_stall; /* pkts waiting for route */
|
||||
struct mf6c *mf6c_next; /* hash table linkage */
|
||||
};
|
||||
|
||||
#define MF6C_INCOMPLETE_PARENT ((mifi_t)-1)
|
||||
|
||||
/*
|
||||
* Argument structure used for pkt info. while upcall is made
|
||||
*/
|
||||
#ifndef _NETINET_IP_MROUTE_HH_
|
||||
struct rtdetq { /* XXX: rtdetq is also defined in ip_mroute.h */
|
||||
struct mbuf *m; /* A copy of the packet */
|
||||
struct ifnet *ifp; /* Interface pkt came in on */
|
||||
#ifdef UPCALL_TIMING
|
||||
struct timeval t; /* Timestamp */
|
||||
#endif /* UPCALL_TIMING */
|
||||
struct rtdetq *next;
|
||||
};
|
||||
#endif /* _NETINET_IP_MROUTE_HH_ */
|
||||
|
||||
#define MF6CTBLSIZ 256
|
||||
#if (MF6CTBLSIZ & (MF6CTBLSIZ - 1)) == 0 /* from sys:route.h */
|
||||
#define MF6CHASHMOD(h) ((h) & (MF6CTBLSIZ - 1))
|
||||
#else
|
||||
#define MF6CHASHMOD(h) ((h) % MF6CTBLSIZ)
|
||||
#endif
|
||||
|
||||
#define MAX_UPQ6 4 /* max. no of pkts in upcall Q */
|
||||
|
||||
extern int (*ip6_mrouter_set)(struct socket *so, struct sockopt *sopt);
|
||||
extern int (*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt);
|
||||
extern int (*ip6_mrouter_done)(void);
|
||||
extern int (*mrt6_ioctl)(u_long, caddr_t);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_NETINET6_IP6_MROUTE_HH_ */
|
2928
freebsd/netinet6/ip6_output.c
Normal file
2928
freebsd/netinet6/ip6_output.c
Normal file
File diff suppressed because it is too large
Load Diff
444
freebsd/netinet6/ip6_var.h
Normal file
444
freebsd/netinet6/ip6_var.h
Normal file
@@ -0,0 +1,444 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: ip6_var.h,v 1.62 2001/05/03 14:51:48 itojun Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ip_var.h 8.1 (Berkeley) 6/10/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IP6_VAR_HH_
|
||||
#define _NETINET6_IP6_VAR_HH_
|
||||
|
||||
/*
|
||||
* IP6 reassembly queue structure. Each fragment
|
||||
* being reassembled is attached to one of these structures.
|
||||
*/
|
||||
struct ip6q {
|
||||
struct ip6asfrag *ip6q_down;
|
||||
struct ip6asfrag *ip6q_up;
|
||||
u_int32_t ip6q_ident;
|
||||
u_int8_t ip6q_nxt;
|
||||
u_int8_t ip6q_ecn;
|
||||
u_int8_t ip6q_ttl;
|
||||
struct in6_addr ip6q_src, ip6q_dst;
|
||||
struct ip6q *ip6q_next;
|
||||
struct ip6q *ip6q_prev;
|
||||
int ip6q_unfrglen; /* len of unfragmentable part */
|
||||
#ifdef notyet
|
||||
u_char *ip6q_nxtp;
|
||||
#endif
|
||||
int ip6q_nfrag; /* # of fragments */
|
||||
struct label *ip6q_label;
|
||||
};
|
||||
|
||||
struct ip6asfrag {
|
||||
struct ip6asfrag *ip6af_down;
|
||||
struct ip6asfrag *ip6af_up;
|
||||
struct mbuf *ip6af_m;
|
||||
int ip6af_offset; /* offset in ip6af_m to next header */
|
||||
int ip6af_frglen; /* fragmentable part length */
|
||||
int ip6af_off; /* fragment offset */
|
||||
u_int16_t ip6af_mff; /* more fragment bit in frag off */
|
||||
};
|
||||
|
||||
#define IP6_REASS_MBUF(ip6af) (*(struct mbuf **)&((ip6af)->ip6af_m))
|
||||
|
||||
/*
|
||||
* Structure attached to inpcb.in6p_moptions and
|
||||
* passed to ip6_output when IPv6 multicast options are in use.
|
||||
* This structure is lazy-allocated.
|
||||
*/
|
||||
struct ip6_moptions {
|
||||
struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
|
||||
u_char im6o_multicast_hlim; /* hoplimit for outgoing multicasts */
|
||||
u_char im6o_multicast_loop; /* 1 >= hear sends if a member */
|
||||
u_short im6o_num_memberships; /* no. memberships this socket */
|
||||
u_short im6o_max_memberships; /* max memberships this socket */
|
||||
struct in6_multi **im6o_membership; /* group memberships */
|
||||
struct in6_mfilter *im6o_mfilters; /* source filters */
|
||||
};
|
||||
|
||||
/*
|
||||
* Control options for outgoing packets
|
||||
*/
|
||||
|
||||
/* Routing header related info */
|
||||
struct ip6po_rhinfo {
|
||||
struct ip6_rthdr *ip6po_rhi_rthdr; /* Routing header */
|
||||
struct route_in6 ip6po_rhi_route; /* Route to the 1st hop */
|
||||
};
|
||||
#define ip6po_rthdr ip6po_rhinfo.ip6po_rhi_rthdr
|
||||
#define ip6po_route ip6po_rhinfo.ip6po_rhi_route
|
||||
|
||||
/* Nexthop related info */
|
||||
struct ip6po_nhinfo {
|
||||
struct sockaddr *ip6po_nhi_nexthop;
|
||||
struct route_in6 ip6po_nhi_route; /* Route to the nexthop */
|
||||
};
|
||||
#define ip6po_nexthop ip6po_nhinfo.ip6po_nhi_nexthop
|
||||
#define ip6po_nextroute ip6po_nhinfo.ip6po_nhi_route
|
||||
|
||||
struct ip6_pktopts {
|
||||
struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */
|
||||
int ip6po_hlim; /* Hoplimit for outgoing packets */
|
||||
|
||||
/* Outgoing IF/address information */
|
||||
struct in6_pktinfo *ip6po_pktinfo;
|
||||
|
||||
/* Next-hop address information */
|
||||
struct ip6po_nhinfo ip6po_nhinfo;
|
||||
|
||||
struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */
|
||||
|
||||
/* Destination options header (before a routing header) */
|
||||
struct ip6_dest *ip6po_dest1;
|
||||
|
||||
/* Routing header related info. */
|
||||
struct ip6po_rhinfo ip6po_rhinfo;
|
||||
|
||||
/* Destination options header (after a routing header) */
|
||||
struct ip6_dest *ip6po_dest2;
|
||||
|
||||
int ip6po_tclass; /* traffic class */
|
||||
|
||||
int ip6po_minmtu; /* fragment vs PMTU discovery policy */
|
||||
#define IP6PO_MINMTU_MCASTONLY -1 /* default; send at min MTU for multicast*/
|
||||
#define IP6PO_MINMTU_DISABLE 0 /* always perform pmtu disc */
|
||||
#define IP6PO_MINMTU_ALL 1 /* always send at min MTU */
|
||||
|
||||
int ip6po_prefer_tempaddr; /* whether temporary addresses are
|
||||
preferred as source address */
|
||||
#define IP6PO_TEMPADDR_SYSTEM -1 /* follow the system default */
|
||||
#define IP6PO_TEMPADDR_NOTPREFER 0 /* not prefer temporary address */
|
||||
#define IP6PO_TEMPADDR_PREFER 1 /* prefer temporary address */
|
||||
|
||||
int ip6po_flags;
|
||||
#if 0 /* parameters in this block is obsolete. do not reuse the values. */
|
||||
#define IP6PO_REACHCONF 0x01 /* upper-layer reachability confirmation. */
|
||||
#define IP6PO_MINMTU 0x02 /* use minimum MTU (IPV6_USE_MIN_MTU) */
|
||||
#endif
|
||||
#define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */
|
||||
#define IP6PO_USECOA 0x08 /* use care of address */
|
||||
};
|
||||
|
||||
/*
|
||||
* Control options for incoming packets
|
||||
*/
|
||||
|
||||
struct ip6stat {
|
||||
u_quad_t ip6s_total; /* total packets received */
|
||||
u_quad_t ip6s_tooshort; /* packet too short */
|
||||
u_quad_t ip6s_toosmall; /* not enough data */
|
||||
u_quad_t ip6s_fragments; /* fragments received */
|
||||
u_quad_t ip6s_fragdropped; /* frags dropped(dups, out of space) */
|
||||
u_quad_t ip6s_fragtimeout; /* fragments timed out */
|
||||
u_quad_t ip6s_fragoverflow; /* fragments that exceeded limit */
|
||||
u_quad_t ip6s_forward; /* packets forwarded */
|
||||
u_quad_t ip6s_cantforward; /* packets rcvd for unreachable dest */
|
||||
u_quad_t ip6s_redirectsent; /* packets forwarded on same net */
|
||||
u_quad_t ip6s_delivered; /* datagrams delivered to upper level*/
|
||||
u_quad_t ip6s_localout; /* total ip packets generated here */
|
||||
u_quad_t ip6s_odropped; /* lost packets due to nobufs, etc. */
|
||||
u_quad_t ip6s_reassembled; /* total packets reassembled ok */
|
||||
u_quad_t ip6s_fragmented; /* datagrams successfully fragmented */
|
||||
u_quad_t ip6s_ofragments; /* output fragments created */
|
||||
u_quad_t ip6s_cantfrag; /* don't fragment flag was set, etc. */
|
||||
u_quad_t ip6s_badoptions; /* error in option processing */
|
||||
u_quad_t ip6s_noroute; /* packets discarded due to no route */
|
||||
u_quad_t ip6s_badvers; /* ip6 version != 6 */
|
||||
u_quad_t ip6s_rawout; /* total raw ip packets generated */
|
||||
u_quad_t ip6s_badscope; /* scope error */
|
||||
u_quad_t ip6s_notmember; /* don't join this multicast group */
|
||||
u_quad_t ip6s_nxthist[256]; /* next header history */
|
||||
u_quad_t ip6s_m1; /* one mbuf */
|
||||
u_quad_t ip6s_m2m[32]; /* two or more mbuf */
|
||||
u_quad_t ip6s_mext1; /* one ext mbuf */
|
||||
u_quad_t ip6s_mext2m; /* two or more ext mbuf */
|
||||
u_quad_t ip6s_exthdrtoolong; /* ext hdr are not continuous */
|
||||
u_quad_t ip6s_nogif; /* no match gif found */
|
||||
u_quad_t ip6s_toomanyhdr; /* discarded due to too many headers */
|
||||
|
||||
/*
|
||||
* statistics for improvement of the source address selection
|
||||
* algorithm:
|
||||
* XXX: hardcoded 16 = # of ip6 multicast scope types + 1
|
||||
*/
|
||||
/* number of times that address selection fails */
|
||||
u_quad_t ip6s_sources_none;
|
||||
/* number of times that an address on the outgoing I/F is chosen */
|
||||
u_quad_t ip6s_sources_sameif[16];
|
||||
/* number of times that an address on a non-outgoing I/F is chosen */
|
||||
u_quad_t ip6s_sources_otherif[16];
|
||||
/*
|
||||
* number of times that an address that has the same scope
|
||||
* from the destination is chosen.
|
||||
*/
|
||||
u_quad_t ip6s_sources_samescope[16];
|
||||
/*
|
||||
* number of times that an address that has a different scope
|
||||
* from the destination is chosen.
|
||||
*/
|
||||
u_quad_t ip6s_sources_otherscope[16];
|
||||
/* number of times that a deprecated address is chosen */
|
||||
u_quad_t ip6s_sources_deprecated[16];
|
||||
|
||||
/* number of times that each rule of source selection is applied. */
|
||||
u_quad_t ip6s_sources_rule[16];
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define IP6STAT_ADD(name, val) V_ip6stat.name += (val)
|
||||
#define IP6STAT_SUB(name, val) V_ip6stat.name -= (val)
|
||||
#define IP6STAT_INC(name) IP6STAT_ADD(name, 1)
|
||||
#define IP6STAT_DEC(name) IP6STAT_SUB(name, 1)
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* IPv6 onion peeling state.
|
||||
* it will be initialized when we come into ip6_input().
|
||||
* XXX do not make it a kitchen sink!
|
||||
*/
|
||||
struct ip6aux {
|
||||
u_int32_t ip6a_flags;
|
||||
#define IP6A_SWAP 0x01 /* swapped home/care-of on packet */
|
||||
#define IP6A_HASEEN 0x02 /* HA was present */
|
||||
#define IP6A_BRUID 0x04 /* BR Unique Identifier was present */
|
||||
#define IP6A_RTALERTSEEN 0x08 /* rtalert present */
|
||||
|
||||
/* ip6.ip6_src */
|
||||
struct in6_addr ip6a_careof; /* care-of address of the peer */
|
||||
struct in6_addr ip6a_home; /* home address of the peer */
|
||||
u_int16_t ip6a_bruid; /* BR unique identifier */
|
||||
|
||||
/* ip6.ip6_dst */
|
||||
struct in6_ifaddr *ip6a_dstia6; /* my ifaddr that matches ip6_dst */
|
||||
|
||||
/* rtalert */
|
||||
u_int16_t ip6a_rtalert; /* rtalert option value */
|
||||
|
||||
/*
|
||||
* decapsulation history will be here.
|
||||
* with IPsec it may not be accurate.
|
||||
*/
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* flags passed to ip6_output as last parameter */
|
||||
#define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */
|
||||
#define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */
|
||||
#define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */
|
||||
|
||||
#ifdef __NO_STRICT_ALIGNMENT
|
||||
#define IP6_HDR_ALIGNED_P(ip) 1
|
||||
#else
|
||||
#define IP6_HDR_ALIGNED_P(ip) ((((intptr_t) (ip)) & 3) == 0)
|
||||
#endif
|
||||
|
||||
VNET_DECLARE(struct ip6stat, ip6stat); /* statistics */
|
||||
VNET_DECLARE(int, ip6_defhlim); /* default hop limit */
|
||||
VNET_DECLARE(int, ip6_defmcasthlim); /* default multicast hop limit */
|
||||
VNET_DECLARE(int, ip6_forwarding); /* act as router? */
|
||||
VNET_DECLARE(int, ip6_use_deprecated); /* allow deprecated addr as source */
|
||||
VNET_DECLARE(int, ip6_rr_prune); /* router renumbering prefix
|
||||
* walk list every 5 sec. */
|
||||
VNET_DECLARE(int, ip6_mcast_pmtu); /* enable pMTU discovery for multicast? */
|
||||
VNET_DECLARE(int, ip6_v6only);
|
||||
#define V_ip6stat VNET(ip6stat)
|
||||
#define V_ip6_defhlim VNET(ip6_defhlim)
|
||||
#define V_ip6_defmcasthlim VNET(ip6_defmcasthlim)
|
||||
#define V_ip6_forwarding VNET(ip6_forwarding)
|
||||
#define V_ip6_use_deprecated VNET(ip6_use_deprecated)
|
||||
#define V_ip6_rr_prune VNET(ip6_rr_prune)
|
||||
#define V_ip6_mcast_pmtu VNET(ip6_mcast_pmtu)
|
||||
#define V_ip6_v6only VNET(ip6_v6only)
|
||||
|
||||
VNET_DECLARE(struct socket *, ip6_mrouter); /* multicast routing daemon */
|
||||
VNET_DECLARE(int, ip6_sendredirects); /* send IP redirects when forwarding? */
|
||||
VNET_DECLARE(int, ip6_maxfragpackets); /* Maximum packets in reassembly
|
||||
* queue */
|
||||
VNET_DECLARE(int, ip6_maxfrags); /* Maximum fragments in reassembly
|
||||
* queue */
|
||||
VNET_DECLARE(int, ip6_accept_rtadv); /* Acts as a host not a router */
|
||||
VNET_DECLARE(int, ip6_keepfaith); /* Firewall Aided Internet Translator */
|
||||
VNET_DECLARE(int, ip6_log_interval);
|
||||
VNET_DECLARE(time_t, ip6_log_time);
|
||||
VNET_DECLARE(int, ip6_hdrnestlimit); /* upper limit of # of extension
|
||||
* headers */
|
||||
VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */
|
||||
#define V_ip6_mrouter VNET(ip6_mrouter)
|
||||
#define V_ip6_sendredirects VNET(ip6_sendredirects)
|
||||
#define V_ip6_maxfragpackets VNET(ip6_maxfragpackets)
|
||||
#define V_ip6_maxfrags VNET(ip6_maxfrags)
|
||||
#define V_ip6_accept_rtadv VNET(ip6_accept_rtadv)
|
||||
#define V_ip6_keepfaith VNET(ip6_keepfaith)
|
||||
#define V_ip6_log_interval VNET(ip6_log_interval)
|
||||
#define V_ip6_log_time VNET(ip6_log_time)
|
||||
#define V_ip6_hdrnestlimit VNET(ip6_hdrnestlimit)
|
||||
#define V_ip6_dad_count VNET(ip6_dad_count)
|
||||
|
||||
VNET_DECLARE(int, ip6_auto_flowlabel);
|
||||
VNET_DECLARE(int, ip6_auto_linklocal);
|
||||
#define V_ip6_auto_flowlabel VNET(ip6_auto_flowlabel)
|
||||
#define V_ip6_auto_linklocal VNET(ip6_auto_linklocal)
|
||||
|
||||
VNET_DECLARE(int, ip6_use_tempaddr); /* Whether to use temporary addresses */
|
||||
VNET_DECLARE(int, ip6_prefer_tempaddr); /* Whether to prefer temporary
|
||||
* addresses in the source address
|
||||
* selection */
|
||||
#define V_ip6_use_tempaddr VNET(ip6_use_tempaddr)
|
||||
#define V_ip6_prefer_tempaddr VNET(ip6_prefer_tempaddr)
|
||||
|
||||
VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope
|
||||
* zone when unspecified */
|
||||
#define V_ip6_use_defzone VNET(ip6_use_defzone)
|
||||
|
||||
VNET_DECLARE (struct pfil_head, inet6_pfil_hook); /* packet filter hooks */
|
||||
#define V_inet6_pfil_hook VNET(inet6_pfil_hook)
|
||||
#ifdef IPSTEALTH
|
||||
VNET_DECLARE(int, ip6stealth);
|
||||
#define V_ip6stealth VNET(ip6stealth)
|
||||
#endif
|
||||
|
||||
extern struct pr_usrreqs rip6_usrreqs;
|
||||
struct sockopt;
|
||||
|
||||
struct inpcb;
|
||||
|
||||
int icmp6_ctloutput __P((struct socket *, struct sockopt *sopt));
|
||||
|
||||
struct in6_ifaddr;
|
||||
void ip6_init __P((void));
|
||||
#ifdef VIMAGE
|
||||
void ip6_destroy __P((void));
|
||||
#endif
|
||||
int ip6proto_register(short);
|
||||
int ip6proto_unregister(short);
|
||||
|
||||
void ip6_input __P((struct mbuf *));
|
||||
struct in6_ifaddr *ip6_getdstifaddr __P((struct mbuf *));
|
||||
void ip6_freepcbopts __P((struct ip6_pktopts *));
|
||||
|
||||
int ip6_unknown_opt __P((u_int8_t *, struct mbuf *, int));
|
||||
char * ip6_get_prevhdr __P((struct mbuf *, int));
|
||||
int ip6_nexthdr __P((struct mbuf *, int, int, int *));
|
||||
int ip6_lasthdr __P((struct mbuf *, int, int, int *));
|
||||
|
||||
struct ip6aux *ip6_addaux __P((struct mbuf *));
|
||||
struct ip6aux *ip6_findaux __P((struct mbuf *));
|
||||
void ip6_delaux __P((struct mbuf *));
|
||||
|
||||
extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *,
|
||||
struct mbuf *);
|
||||
|
||||
int ip6_process_hopopts __P((struct mbuf *, u_int8_t *, int, u_int32_t *,
|
||||
u_int32_t *));
|
||||
struct mbuf **ip6_savecontrol_v4(struct inpcb *, struct mbuf *,
|
||||
struct mbuf **, int *);
|
||||
void ip6_savecontrol __P((struct inpcb *, struct mbuf *, struct mbuf **));
|
||||
void ip6_notify_pmtu __P((struct inpcb *, struct sockaddr_in6 *,
|
||||
u_int32_t *));
|
||||
int ip6_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
|
||||
|
||||
void ip6_forward __P((struct mbuf *, int));
|
||||
|
||||
void ip6_mloopback __P((struct ifnet *, struct mbuf *, struct sockaddr_in6 *));
|
||||
int ip6_output __P((struct mbuf *, struct ip6_pktopts *,
|
||||
struct route_in6 *,
|
||||
int,
|
||||
struct ip6_moptions *, struct ifnet **,
|
||||
struct inpcb *));
|
||||
int ip6_ctloutput __P((struct socket *, struct sockopt *));
|
||||
int ip6_raw_ctloutput __P((struct socket *, struct sockopt *));
|
||||
void ip6_initpktopts __P((struct ip6_pktopts *));
|
||||
int ip6_setpktopts __P((struct mbuf *, struct ip6_pktopts *,
|
||||
struct ip6_pktopts *, struct ucred *, int));
|
||||
void ip6_clearpktopts __P((struct ip6_pktopts *, int));
|
||||
struct ip6_pktopts *ip6_copypktopts __P((struct ip6_pktopts *, int));
|
||||
int ip6_optlen __P((struct inpcb *));
|
||||
|
||||
int route6_input __P((struct mbuf **, int *, int));
|
||||
|
||||
void frag6_init __P((void));
|
||||
int frag6_input __P((struct mbuf **, int *, int));
|
||||
void frag6_slowtimo __P((void));
|
||||
void frag6_drain __P((void));
|
||||
|
||||
void rip6_init __P((void));
|
||||
int rip6_input __P((struct mbuf **, int *, int));
|
||||
void rip6_ctlinput __P((int, struct sockaddr *, void *));
|
||||
int rip6_ctloutput __P((struct socket *, struct sockopt *));
|
||||
int rip6_output __P((struct mbuf *, ...));
|
||||
int rip6_usrreq __P((struct socket *,
|
||||
int, struct mbuf *, struct mbuf *, struct mbuf *, struct thread *));
|
||||
|
||||
int dest6_input __P((struct mbuf **, int *, int));
|
||||
int none_input __P((struct mbuf **, int *, int));
|
||||
|
||||
int in6_selectsrc(struct sockaddr_in6 *, struct ip6_pktopts *,
|
||||
struct inpcb *inp, struct route_in6 *, struct ucred *cred,
|
||||
struct ifnet **, struct in6_addr *);
|
||||
int in6_selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
|
||||
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
|
||||
struct rtentry **));
|
||||
u_int32_t ip6_randomid __P((void));
|
||||
u_int32_t ip6_randomflowlabel __P((void));
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_NETINET6_IP6_VAR_HH_ */
|
148
freebsd/netinet6/ip6protosw.h
Normal file
148
freebsd/netinet6/ip6protosw.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: ip6protosw.h,v 1.25 2001/09/26 06:13:03 keiichi Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)protosw.h 8.1 (Berkeley) 6/2/93
|
||||
* BSDI protosw.h,v 2.3 1996/10/11 16:02:40 pjd Exp
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IP6PROTOSW_HH_
|
||||
#define _NETINET6_IP6PROTOSW_HH_
|
||||
|
||||
/*
|
||||
* Protocol switch table for IPv6.
|
||||
* All other definitions should refer to sys/protosw.h
|
||||
*/
|
||||
|
||||
struct mbuf;
|
||||
struct sockaddr;
|
||||
struct socket;
|
||||
struct domain;
|
||||
struct thread;
|
||||
struct ip6_hdr;
|
||||
struct icmp6_hdr;
|
||||
struct in6_addr;
|
||||
struct pr_usrreqs;
|
||||
|
||||
/*
|
||||
* argument type for the last arg of pr_ctlinput().
|
||||
* should be consulted only with AF_INET6 family.
|
||||
*
|
||||
* IPv6 ICMP IPv6 [exthdrs] finalhdr payload
|
||||
* ^ ^ ^ ^
|
||||
* | | ip6c_ip6 ip6c_off
|
||||
* | ip6c_icmp6
|
||||
* ip6c_m
|
||||
*
|
||||
* ip6c_finaldst usually points to ip6c_ip6->ip6_dst. if the original
|
||||
* (internal) packet carries a routing header, it may point the final
|
||||
* dstination address in the routing header.
|
||||
*
|
||||
* ip6c_src: ip6c_ip6->ip6_src + scope info + flowlabel in ip6c_ip6
|
||||
* (beware of flowlabel, if you try to compare it against others)
|
||||
* ip6c_dst: ip6c_finaldst + scope info
|
||||
*/
|
||||
struct ip6ctlparam {
|
||||
struct mbuf *ip6c_m; /* start of mbuf chain */
|
||||
struct icmp6_hdr *ip6c_icmp6; /* icmp6 header of target packet */
|
||||
struct ip6_hdr *ip6c_ip6; /* ip6 header of target packet */
|
||||
int ip6c_off; /* offset of the target proto header */
|
||||
struct sockaddr_in6 *ip6c_src; /* srcaddr w/ additional info */
|
||||
struct sockaddr_in6 *ip6c_dst; /* (final) dstaddr w/ additional info */
|
||||
struct in6_addr *ip6c_finaldst; /* final destination address */
|
||||
void *ip6c_cmdarg; /* control command dependent data */
|
||||
u_int8_t ip6c_nxt; /* final next header field */
|
||||
};
|
||||
|
||||
struct ip6protosw {
|
||||
short pr_type; /* socket type used for */
|
||||
struct domain *pr_domain; /* domain protocol a member of */
|
||||
short pr_protocol; /* protocol number */
|
||||
short pr_flags; /* see below */
|
||||
|
||||
/* protocol-protocol hooks */
|
||||
int (*pr_input) /* input to protocol (from below) */
|
||||
__P((struct mbuf **, int *, int));
|
||||
int (*pr_output) /* output to protocol (from above) */
|
||||
__P((struct mbuf *, ...));
|
||||
void (*pr_ctlinput) /* control input (from below) */
|
||||
__P((int, struct sockaddr *, void *));
|
||||
int (*pr_ctloutput) /* control output (from above) */
|
||||
__P((struct socket *, struct sockopt *));
|
||||
|
||||
/* utility hooks */
|
||||
void (*pr_init) /* initialization hook */
|
||||
__P((void));
|
||||
void (*pr_destroy) /* cleanup hook */
|
||||
__P((void));
|
||||
|
||||
void (*pr_fasttimo) /* fast timeout (200ms) */
|
||||
__P((void));
|
||||
void (*pr_slowtimo) /* slow timeout (500ms) */
|
||||
__P((void));
|
||||
void (*pr_drain) /* flush any excess space possible */
|
||||
__P((void));
|
||||
struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern struct ip6protosw inet6sw[];
|
||||
#endif
|
||||
|
||||
#endif /* !_NETINET6_IP6PROTOSW_HH_ */
|
3311
freebsd/netinet6/mld6.c
Normal file
3311
freebsd/netinet6/mld6.c
Normal file
File diff suppressed because it is too large
Load Diff
112
freebsd/netinet6/mld6.h
Normal file
112
freebsd/netinet6/mld6.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Bruce Simpson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_MLD6_HH_
|
||||
#define _NETINET6_MLD6_HH_
|
||||
|
||||
/*
|
||||
* Multicast Listener Discovery (MLD) definitions.
|
||||
*/
|
||||
|
||||
/* Minimum length of any MLD protocol message. */
|
||||
#define MLD_MINLEN sizeof(struct icmp6_hdr)
|
||||
|
||||
/*
|
||||
* MLD v2 query format.
|
||||
* See <netinet/icmp6.h> for struct mld_hdr
|
||||
* (MLDv1 query and host report format).
|
||||
*/
|
||||
struct mldv2_query {
|
||||
struct icmp6_hdr mld_icmp6_hdr; /* ICMPv6 header */
|
||||
struct in6_addr mld_addr; /* address being queried */
|
||||
uint8_t mld_misc; /* reserved/suppress/robustness */
|
||||
uint8_t mld_qqi; /* querier's query interval */
|
||||
uint16_t mld_numsrc; /* number of sources */
|
||||
/* followed by 1..numsrc source addresses */
|
||||
} __packed;
|
||||
#define MLD_V2_QUERY_MINLEN sizeof(struct mldv2_query)
|
||||
#define MLD_MRC_EXP(x) ((ntohs((x)) >> 12) & 0x0007)
|
||||
#define MLD_MRC_MANT(x) (ntohs((x)) & 0x0fff)
|
||||
#define MLD_QQIC_EXP(x) (((x) >> 4) & 0x07)
|
||||
#define MLD_QQIC_MANT(x) ((x) & 0x0f)
|
||||
#define MLD_QRESV(x) (((x) >> 4) & 0x0f)
|
||||
#define MLD_SFLAG(x) (((x) >> 3) & 0x01)
|
||||
#define MLD_QRV(x) ((x) & 0x07)
|
||||
|
||||
/*
|
||||
* MLDv2 host membership report header.
|
||||
* mld_type: MLDV2_LISTENER_REPORT
|
||||
*/
|
||||
struct mldv2_report {
|
||||
struct icmp6_hdr mld_icmp6_hdr;
|
||||
/* followed by 1..numgrps records */
|
||||
} __packed;
|
||||
/* overlaid on struct icmp6_hdr. */
|
||||
#define mld_numrecs mld_icmp6_hdr.icmp6_data16[1]
|
||||
|
||||
struct mldv2_record {
|
||||
uint8_t mr_type; /* record type */
|
||||
uint8_t mr_datalen; /* length of auxiliary data */
|
||||
uint16_t mr_numsrc; /* number of sources */
|
||||
struct in6_addr mr_addr; /* address being reported */
|
||||
/* followed by 1..numsrc source addresses */
|
||||
} __packed;
|
||||
#define MLD_V2_REPORT_MAXRECS 65535
|
||||
|
||||
/*
|
||||
* MLDv2 report modes.
|
||||
*/
|
||||
#define MLD_DO_NOTHING 0 /* don't send a record */
|
||||
#define MLD_MODE_IS_INCLUDE 1 /* MODE_IN */
|
||||
#define MLD_MODE_IS_EXCLUDE 2 /* MODE_EX */
|
||||
#define MLD_CHANGE_TO_INCLUDE_MODE 3 /* TO_IN */
|
||||
#define MLD_CHANGE_TO_EXCLUDE_MODE 4 /* TO_EX */
|
||||
#define MLD_ALLOW_NEW_SOURCES 5 /* ALLOW_NEW */
|
||||
#define MLD_BLOCK_OLD_SOURCES 6 /* BLOCK_OLD */
|
||||
|
||||
/*
|
||||
* MLDv2 query types.
|
||||
*/
|
||||
#define MLD_V2_GENERAL_QUERY 1
|
||||
#define MLD_V2_GROUP_QUERY 2
|
||||
#define MLD_V2_GROUP_SOURCE_QUERY 3
|
||||
|
||||
/*
|
||||
* Maximum report interval for MLDv1 host membership reports.
|
||||
*/
|
||||
#define MLD_V1_MAX_RI 10
|
||||
|
||||
/*
|
||||
* MLD_TIMER_SCALE denotes that the MLD code field specifies
|
||||
* time in milliseconds.
|
||||
*/
|
||||
#define MLD_TIMER_SCALE 1000
|
||||
|
||||
#endif /* _NETINET6_MLD6_HH_ */
|
164
freebsd/netinet6/mld6_var.h
Normal file
164
freebsd/netinet6/mld6_var.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Bruce Simpson.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#ifndef _NETINET6_MLD6_VAR_HH_
|
||||
#define _NETINET6_MLD6_VAR_HH_
|
||||
|
||||
/*
|
||||
* Multicast Listener Discovery (MLD)
|
||||
* implementation-specific definitions.
|
||||
*/
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* Per-link MLD state.
|
||||
*/
|
||||
struct mld_ifinfo {
|
||||
LIST_ENTRY(mld_ifinfo) mli_link;
|
||||
struct ifnet *mli_ifp; /* interface this instance belongs to */
|
||||
uint32_t mli_version; /* MLDv1 Host Compatibility Mode */
|
||||
uint32_t mli_v1_timer; /* MLDv1 Querier Present timer (s) */
|
||||
uint32_t mli_v2_timer; /* MLDv2 General Query (interface) timer (s)*/
|
||||
uint32_t mli_flags; /* MLD per-interface flags */
|
||||
uint32_t mli_rv; /* MLDv2 Robustness Variable */
|
||||
uint32_t mli_qi; /* MLDv2 Query Interval (s) */
|
||||
uint32_t mli_qri; /* MLDv2 Query Response Interval (s) */
|
||||
uint32_t mli_uri; /* MLDv2 Unsolicited Report Interval (s) */
|
||||
SLIST_HEAD(,in6_multi) mli_relinmhead; /* released groups */
|
||||
struct ifqueue mli_gq; /* queue of general query responses */
|
||||
};
|
||||
#define MLIF_SILENT 0x00000001 /* Do not use MLD on this ifp */
|
||||
#define MLIF_USEALLOW 0x00000002 /* Use ALLOW/BLOCK for joins/leaves */
|
||||
|
||||
#define MLD_RANDOM_DELAY(X) (arc4random() % (X) + 1)
|
||||
#define MLD_MAX_STATE_CHANGES 24 /* Max pending changes per group */
|
||||
|
||||
/*
|
||||
* MLD per-group states.
|
||||
*/
|
||||
#define MLD_NOT_MEMBER 0 /* Can garbage collect group */
|
||||
#define MLD_SILENT_MEMBER 1 /* Do not perform MLD for group */
|
||||
#define MLD_REPORTING_MEMBER 2 /* MLDv1 we are reporter */
|
||||
#define MLD_IDLE_MEMBER 3 /* MLDv1 we reported last */
|
||||
#define MLD_LAZY_MEMBER 4 /* MLDv1 other member reporting */
|
||||
#define MLD_SLEEPING_MEMBER 5 /* MLDv1 start query response */
|
||||
#define MLD_AWAKENING_MEMBER 6 /* MLDv1 group timer will start */
|
||||
#define MLD_G_QUERY_PENDING_MEMBER 7 /* MLDv2 group query pending */
|
||||
#define MLD_SG_QUERY_PENDING_MEMBER 8 /* MLDv2 source query pending */
|
||||
#define MLD_LEAVING_MEMBER 9 /* MLDv2 dying gasp (pending last */
|
||||
/* retransmission of INCLUDE {}) */
|
||||
|
||||
/*
|
||||
* MLD version tag.
|
||||
*/
|
||||
#define MLD_VERSION_NONE 0 /* Invalid */
|
||||
#define MLD_VERSION_1 1
|
||||
#define MLD_VERSION_2 2 /* Default */
|
||||
|
||||
/*
|
||||
* MLDv2 protocol control variables.
|
||||
*/
|
||||
#define MLD_RV_INIT 2 /* Robustness Variable */
|
||||
#define MLD_RV_MIN 1
|
||||
#define MLD_RV_MAX 7
|
||||
|
||||
#define MLD_QI_INIT 125 /* Query Interval (s) */
|
||||
#define MLD_QI_MIN 1
|
||||
#define MLD_QI_MAX 255
|
||||
|
||||
#define MLD_QRI_INIT 10 /* Query Response Interval (s) */
|
||||
#define MLD_QRI_MIN 1
|
||||
#define MLD_QRI_MAX 255
|
||||
|
||||
#define MLD_URI_INIT 3 /* Unsolicited Report Interval (s) */
|
||||
#define MLD_URI_MIN 0
|
||||
#define MLD_URI_MAX 10
|
||||
|
||||
#define MLD_MAX_GS_SOURCES 256 /* # of sources in rx GS query */
|
||||
#define MLD_MAX_G_GS_PACKETS 8 /* # of packets to answer G/GS */
|
||||
#define MLD_MAX_STATE_CHANGE_PACKETS 8 /* # of packets per state change */
|
||||
#define MLD_MAX_RESPONSE_PACKETS 16 /* # of packets for general query */
|
||||
#define MLD_MAX_RESPONSE_BURST 4 /* # of responses to send at once */
|
||||
#define MLD_RESPONSE_BURST_INTERVAL (PR_FASTHZ / 2) /* 500ms */
|
||||
|
||||
/*
|
||||
* MLD-specific mbuf flags.
|
||||
*/
|
||||
#define M_MLDV1 M_PROTO1 /* Packet is MLDv1 */
|
||||
#define M_GROUPREC M_PROTO3 /* mbuf chain is a group record */
|
||||
|
||||
/*
|
||||
* Leading space for MLDv2 reports inside MTU.
|
||||
*
|
||||
* NOTE: This differs from IGMPv3 significantly. KAME IPv6 requires
|
||||
* that a fully formed mbuf chain *without* the Router Alert option
|
||||
* is passed to ip6_output(), however we must account for it in the
|
||||
* MTU if we need to split an MLDv2 report into several packets.
|
||||
*
|
||||
* We now put the MLDv2 report header in the initial mbuf containing
|
||||
* the IPv6 header.
|
||||
*/
|
||||
#define MLD_MTUSPACE (sizeof(struct ip6_hdr) + sizeof(struct mld_raopt) + \
|
||||
sizeof(struct icmp6_hdr))
|
||||
|
||||
/*
|
||||
* Subsystem lock macros.
|
||||
* The MLD lock is only taken with MLD. Currently it is system-wide.
|
||||
* VIMAGE: The lock could be pushed to per-VIMAGE granularity in future.
|
||||
*/
|
||||
#define MLD_LOCK_INIT() mtx_init(&mld_mtx, "mld_mtx", NULL, MTX_DEF)
|
||||
#define MLD_LOCK_DESTROY() mtx_destroy(&mld_mtx)
|
||||
#define MLD_LOCK() mtx_lock(&mld_mtx)
|
||||
#define MLD_LOCK_ASSERT() mtx_assert(&mld_mtx, MA_OWNED)
|
||||
#define MLD_UNLOCK() mtx_unlock(&mld_mtx)
|
||||
#define MLD_UNLOCK_ASSERT() mtx_assert(&mld_mtx, MA_NOTOWNED)
|
||||
|
||||
/*
|
||||
* Per-link MLD context.
|
||||
*/
|
||||
#define MLD_IFINFO(ifp) \
|
||||
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->mld_ifinfo)
|
||||
|
||||
int mld_change_state(struct in6_multi *, const int);
|
||||
struct mld_ifinfo *
|
||||
mld_domifattach(struct ifnet *);
|
||||
void mld_domifdetach(struct ifnet *);
|
||||
void mld_fasttimo(void);
|
||||
void mld_ifdetach(struct ifnet *);
|
||||
int mld_input(struct mbuf *, int, int);
|
||||
void mld_slowtimo(void);
|
||||
|
||||
#ifdef SYSCTL_DECL
|
||||
SYSCTL_DECL(_net_inet6_mld);
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET6_MLD6_VAR_HH_ */
|
2249
freebsd/netinet6/nd6.c
Normal file
2249
freebsd/netinet6/nd6.c
Normal file
File diff suppressed because it is too large
Load Diff
455
freebsd/netinet6/nd6.h
Normal file
455
freebsd/netinet6/nd6.h
Normal file
@@ -0,0 +1,455 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: nd6.h,v 1.76 2001/12/18 02:10:31 itojun Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_ND6_HH_
|
||||
#define _NETINET6_ND6_HH_
|
||||
|
||||
/* see net/route.h, or net/if_inarp.h */
|
||||
#ifndef RTF_ANNOUNCE
|
||||
#define RTF_ANNOUNCE RTF_PROTO2
|
||||
#endif
|
||||
|
||||
#include <rtems/freebsd/sys/queue.h>
|
||||
#include <rtems/freebsd/sys/callout.h>
|
||||
|
||||
struct llentry;
|
||||
|
||||
#define ND6_LLINFO_NOSTATE -2
|
||||
/*
|
||||
* We don't need the WAITDELETE state any more, but we keep the definition
|
||||
* in a comment line instead of removing it. This is necessary to avoid
|
||||
* unintentionally reusing the value for another purpose, which might
|
||||
* affect backward compatibility with old applications.
|
||||
* (20000711 jinmei@kame.net)
|
||||
*/
|
||||
/* #define ND6_LLINFO_WAITDELETE -1 */
|
||||
#define ND6_LLINFO_INCOMPLETE 0
|
||||
#define ND6_LLINFO_REACHABLE 1
|
||||
#define ND6_LLINFO_STALE 2
|
||||
#define ND6_LLINFO_DELAY 3
|
||||
#define ND6_LLINFO_PROBE 4
|
||||
|
||||
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
|
||||
#define ND6_LLINFO_PERMANENT(n) (((n)->la_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))
|
||||
|
||||
struct nd_ifinfo {
|
||||
u_int32_t linkmtu; /* LinkMTU */
|
||||
u_int32_t maxmtu; /* Upper bound of LinkMTU */
|
||||
u_int32_t basereachable; /* BaseReachableTime */
|
||||
u_int32_t reachable; /* Reachable Time */
|
||||
u_int32_t retrans; /* Retrans Timer */
|
||||
u_int32_t flags; /* Flags */
|
||||
int recalctm; /* BaseReacable re-calculation timer */
|
||||
u_int8_t chlim; /* CurHopLimit */
|
||||
u_int8_t initialized; /* Flag to see the entry is initialized */
|
||||
/* the following 3 members are for privacy extension for addrconf */
|
||||
u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
|
||||
u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */
|
||||
u_int8_t randomid[8]; /* current random ID */
|
||||
};
|
||||
|
||||
#define ND6_IFF_PERFORMNUD 0x1
|
||||
#define ND6_IFF_ACCEPT_RTADV 0x2
|
||||
#define ND6_IFF_PREFER_SOURCE 0x4 /* XXX: not related to ND. */
|
||||
#define ND6_IFF_IFDISABLED 0x8 /* IPv6 operation is disabled due to
|
||||
* DAD failure. (XXX: not ND-specific)
|
||||
*/
|
||||
#define ND6_IFF_DONT_SET_IFROUTE 0x10
|
||||
|
||||
#define ND6_CREATE LLE_CREATE
|
||||
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define ND_IFINFO(ifp) \
|
||||
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
|
||||
#define IN6_LINKMTU(ifp) \
|
||||
((ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) \
|
||||
? ND_IFINFO(ifp)->linkmtu \
|
||||
: ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) \
|
||||
? ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu))
|
||||
#endif
|
||||
|
||||
struct in6_nbrinfo {
|
||||
char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */
|
||||
struct in6_addr addr; /* IPv6 address of the neighbor */
|
||||
long asked; /* number of queries already sent for this addr */
|
||||
int isrouter; /* if it acts as a router */
|
||||
int state; /* reachability state */
|
||||
int expire; /* lifetime for NDP state transition */
|
||||
};
|
||||
|
||||
#define DRLSTSIZ 10
|
||||
#define PRLSTSIZ 10
|
||||
struct in6_drlist {
|
||||
char ifname[IFNAMSIZ];
|
||||
struct {
|
||||
struct in6_addr rtaddr;
|
||||
u_char flags;
|
||||
u_short rtlifetime;
|
||||
u_long expire;
|
||||
u_short if_index;
|
||||
} defrouter[DRLSTSIZ];
|
||||
};
|
||||
|
||||
struct in6_defrouter {
|
||||
struct sockaddr_in6 rtaddr;
|
||||
u_char flags;
|
||||
u_short rtlifetime;
|
||||
u_long expire;
|
||||
u_short if_index;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct in6_oprlist {
|
||||
char ifname[IFNAMSIZ];
|
||||
struct {
|
||||
struct in6_addr prefix;
|
||||
struct prf_ra raflags;
|
||||
u_char prefixlen;
|
||||
u_char origin;
|
||||
u_long vltime;
|
||||
u_long pltime;
|
||||
u_long expire;
|
||||
u_short if_index;
|
||||
u_short advrtrs; /* number of advertisement routers */
|
||||
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
|
||||
} prefix[PRLSTSIZ];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct in6_prlist {
|
||||
char ifname[IFNAMSIZ];
|
||||
struct {
|
||||
struct in6_addr prefix;
|
||||
struct prf_ra raflags;
|
||||
u_char prefixlen;
|
||||
u_char origin;
|
||||
u_int32_t vltime;
|
||||
u_int32_t pltime;
|
||||
time_t expire;
|
||||
u_short if_index;
|
||||
u_short advrtrs; /* number of advertisement routers */
|
||||
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
|
||||
} prefix[PRLSTSIZ];
|
||||
};
|
||||
|
||||
struct in6_prefix {
|
||||
struct sockaddr_in6 prefix;
|
||||
struct prf_ra raflags;
|
||||
u_char prefixlen;
|
||||
u_char origin;
|
||||
u_int32_t vltime;
|
||||
u_int32_t pltime;
|
||||
time_t expire;
|
||||
u_int32_t flags;
|
||||
int refcnt;
|
||||
u_short if_index;
|
||||
u_short advrtrs; /* number of advertisement routers */
|
||||
/* struct sockaddr_in6 advrtr[] */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct in6_ondireq {
|
||||
char ifname[IFNAMSIZ];
|
||||
struct {
|
||||
u_int32_t linkmtu; /* LinkMTU */
|
||||
u_int32_t maxmtu; /* Upper bound of LinkMTU */
|
||||
u_int32_t basereachable; /* BaseReachableTime */
|
||||
u_int32_t reachable; /* Reachable Time */
|
||||
u_int32_t retrans; /* Retrans Timer */
|
||||
u_int32_t flags; /* Flags */
|
||||
int recalctm; /* BaseReacable re-calculation timer */
|
||||
u_int8_t chlim; /* CurHopLimit */
|
||||
u_int8_t receivedra;
|
||||
} ndi;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct in6_ndireq {
|
||||
char ifname[IFNAMSIZ];
|
||||
struct nd_ifinfo ndi;
|
||||
};
|
||||
|
||||
struct in6_ndifreq {
|
||||
char ifname[IFNAMSIZ];
|
||||
u_long ifindex;
|
||||
};
|
||||
|
||||
/* Prefix status */
|
||||
#define NDPRF_ONLINK 0x1
|
||||
#define NDPRF_DETACHED 0x2
|
||||
|
||||
/* protocol constants */
|
||||
#define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */
|
||||
#define RTR_SOLICITATION_INTERVAL 4 /* 4sec */
|
||||
#define MAX_RTR_SOLICITATIONS 3
|
||||
|
||||
#define ND6_INFINITE_LIFETIME 0xffffffff
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* node constants */
|
||||
#define MAX_REACHABLE_TIME 3600000 /* msec */
|
||||
#define REACHABLE_TIME 30000 /* msec */
|
||||
#define RETRANS_TIMER 1000 /* msec */
|
||||
#define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */
|
||||
#define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */
|
||||
#define DEF_TEMP_VALID_LIFETIME 604800 /* 1 week */
|
||||
#define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */
|
||||
#define TEMPADDR_REGEN_ADVANCE 5 /* sec */
|
||||
#define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */
|
||||
#define ND_COMPUTE_RTIME(x) \
|
||||
(((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \
|
||||
((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)
|
||||
|
||||
TAILQ_HEAD(nd_drhead, nd_defrouter);
|
||||
struct nd_defrouter {
|
||||
TAILQ_ENTRY(nd_defrouter) dr_entry;
|
||||
struct in6_addr rtaddr;
|
||||
u_char flags; /* flags on RA message */
|
||||
u_short rtlifetime;
|
||||
u_long expire;
|
||||
struct ifnet *ifp;
|
||||
int installed; /* is installed into kernel routing table */
|
||||
};
|
||||
|
||||
struct nd_prefixctl {
|
||||
struct ifnet *ndpr_ifp;
|
||||
|
||||
/* prefix */
|
||||
struct sockaddr_in6 ndpr_prefix;
|
||||
u_char ndpr_plen;
|
||||
|
||||
u_int32_t ndpr_vltime; /* advertised valid lifetime */
|
||||
u_int32_t ndpr_pltime; /* advertised preferred lifetime */
|
||||
|
||||
struct prf_ra ndpr_flags;
|
||||
};
|
||||
|
||||
|
||||
struct nd_prefix {
|
||||
struct ifnet *ndpr_ifp;
|
||||
LIST_ENTRY(nd_prefix) ndpr_entry;
|
||||
struct sockaddr_in6 ndpr_prefix; /* prefix */
|
||||
struct in6_addr ndpr_mask; /* netmask derived from the prefix */
|
||||
|
||||
u_int32_t ndpr_vltime; /* advertised valid lifetime */
|
||||
u_int32_t ndpr_pltime; /* advertised preferred lifetime */
|
||||
|
||||
time_t ndpr_expire; /* expiration time of the prefix */
|
||||
time_t ndpr_preferred; /* preferred time of the prefix */
|
||||
time_t ndpr_lastupdate; /* reception time of last advertisement */
|
||||
|
||||
struct prf_ra ndpr_flags;
|
||||
u_int32_t ndpr_stateflags; /* actual state flags */
|
||||
/* list of routers that advertise the prefix: */
|
||||
LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs;
|
||||
u_char ndpr_plen;
|
||||
int ndpr_refcnt; /* reference couter from addresses */
|
||||
};
|
||||
|
||||
#define ndpr_next ndpr_entry.le_next
|
||||
|
||||
#define ndpr_raf ndpr_flags
|
||||
#define ndpr_raf_onlink ndpr_flags.onlink
|
||||
#define ndpr_raf_auto ndpr_flags.autonomous
|
||||
#define ndpr_raf_router ndpr_flags.router
|
||||
|
||||
/*
|
||||
* Message format for use in obtaining information about prefixes
|
||||
* from inet6 sysctl function
|
||||
*/
|
||||
struct inet6_ndpr_msghdr {
|
||||
u_short inpm_msglen; /* to skip over non-understood messages */
|
||||
u_char inpm_version; /* future binary compatibility */
|
||||
u_char inpm_type; /* message type */
|
||||
struct in6_addr inpm_prefix;
|
||||
u_long prm_vltim;
|
||||
u_long prm_pltime;
|
||||
u_long prm_expire;
|
||||
u_long prm_preferred;
|
||||
struct in6_prflags prm_flags;
|
||||
u_short prm_index; /* index for associated ifp */
|
||||
u_char prm_plen; /* length of prefix in bits */
|
||||
};
|
||||
|
||||
#define prm_raf_onlink prm_flags.prf_ra.onlink
|
||||
#define prm_raf_auto prm_flags.prf_ra.autonomous
|
||||
|
||||
#define prm_statef_onlink prm_flags.prf_state.onlink
|
||||
|
||||
#define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid
|
||||
#define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd
|
||||
|
||||
struct nd_pfxrouter {
|
||||
LIST_ENTRY(nd_pfxrouter) pfr_entry;
|
||||
#define pfr_next pfr_entry.le_next
|
||||
struct nd_defrouter *router;
|
||||
};
|
||||
|
||||
LIST_HEAD(nd_prhead, nd_prefix);
|
||||
|
||||
/* nd6.c */
|
||||
VNET_DECLARE(int, nd6_prune);
|
||||
VNET_DECLARE(int, nd6_delay);
|
||||
VNET_DECLARE(int, nd6_umaxtries);
|
||||
VNET_DECLARE(int, nd6_mmaxtries);
|
||||
VNET_DECLARE(int, nd6_useloopback);
|
||||
VNET_DECLARE(int, nd6_maxnudhint);
|
||||
VNET_DECLARE(int, nd6_gctimer);
|
||||
VNET_DECLARE(struct nd_drhead, nd_defrouter);
|
||||
VNET_DECLARE(struct nd_prhead, nd_prefix);
|
||||
VNET_DECLARE(int, nd6_debug);
|
||||
VNET_DECLARE(int, nd6_onlink_ns_rfc4861);
|
||||
#define V_nd6_prune VNET(nd6_prune)
|
||||
#define V_nd6_delay VNET(nd6_delay)
|
||||
#define V_nd6_umaxtries VNET(nd6_umaxtries)
|
||||
#define V_nd6_mmaxtries VNET(nd6_mmaxtries)
|
||||
#define V_nd6_useloopback VNET(nd6_useloopback)
|
||||
#define V_nd6_maxnudhint VNET(nd6_maxnudhint)
|
||||
#define V_nd6_gctimer VNET(nd6_gctimer)
|
||||
#define V_nd_defrouter VNET(nd_defrouter)
|
||||
#define V_nd_prefix VNET(nd_prefix)
|
||||
#define V_nd6_debug VNET(nd6_debug)
|
||||
#define V_nd6_onlink_ns_rfc4861 VNET(nd6_onlink_ns_rfc4861)
|
||||
|
||||
#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0)
|
||||
|
||||
VNET_DECLARE(struct callout, nd6_timer_ch);
|
||||
#define V_nd6_timer_ch VNET(nd6_timer_ch)
|
||||
|
||||
/* nd6_rtr.c */
|
||||
VNET_DECLARE(int, nd6_defifindex);
|
||||
VNET_DECLARE(int, ip6_desync_factor); /* seconds */
|
||||
VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */
|
||||
VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */
|
||||
VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */
|
||||
#define V_nd6_defifindex VNET(nd6_defifindex)
|
||||
#define V_ip6_desync_factor VNET(ip6_desync_factor)
|
||||
#define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime)
|
||||
#define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime)
|
||||
#define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance)
|
||||
|
||||
union nd_opts {
|
||||
struct nd_opt_hdr *nd_opt_array[8]; /* max = target address list */
|
||||
struct {
|
||||
struct nd_opt_hdr *zero;
|
||||
struct nd_opt_hdr *src_lladdr;
|
||||
struct nd_opt_hdr *tgt_lladdr;
|
||||
struct nd_opt_prefix_info *pi_beg; /* multiple opts, start */
|
||||
struct nd_opt_rd_hdr *rh;
|
||||
struct nd_opt_mtu *mtu;
|
||||
struct nd_opt_hdr *search; /* multiple opts */
|
||||
struct nd_opt_hdr *last; /* multiple opts */
|
||||
int done;
|
||||
struct nd_opt_prefix_info *pi_end;/* multiple opts, end */
|
||||
} nd_opt_each;
|
||||
};
|
||||
#define nd_opts_src_lladdr nd_opt_each.src_lladdr
|
||||
#define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr
|
||||
#define nd_opts_pi nd_opt_each.pi_beg
|
||||
#define nd_opts_pi_end nd_opt_each.pi_end
|
||||
#define nd_opts_rh nd_opt_each.rh
|
||||
#define nd_opts_mtu nd_opt_each.mtu
|
||||
#define nd_opts_search nd_opt_each.search
|
||||
#define nd_opts_last nd_opt_each.last
|
||||
#define nd_opts_done nd_opt_each.done
|
||||
|
||||
/* XXX: need nd6_var.h?? */
|
||||
/* nd6.c */
|
||||
void nd6_init __P((void));
|
||||
#ifdef VIMAGE
|
||||
void nd6_destroy __P((void));
|
||||
#endif
|
||||
struct nd_ifinfo *nd6_ifattach __P((struct ifnet *));
|
||||
void nd6_ifdetach __P((struct nd_ifinfo *));
|
||||
int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));
|
||||
void nd6_option_init __P((void *, int, union nd_opts *));
|
||||
struct nd_opt_hdr *nd6_option __P((union nd_opts *));
|
||||
int nd6_options __P((union nd_opts *));
|
||||
struct llentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
|
||||
void nd6_setmtu __P((struct ifnet *));
|
||||
void nd6_llinfo_settimer __P((struct llentry *, long));
|
||||
void nd6_llinfo_settimer_locked __P((struct llentry *, long));
|
||||
void nd6_timer __P((void *));
|
||||
void nd6_purge __P((struct ifnet *));
|
||||
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
|
||||
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
|
||||
struct sockaddr *, u_char *));
|
||||
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
|
||||
struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
|
||||
char *, int, int, int));
|
||||
int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
|
||||
struct sockaddr_in6 *, struct rtentry *));
|
||||
int nd6_output_lle __P((struct ifnet *, struct ifnet *, struct mbuf *,
|
||||
struct sockaddr_in6 *, struct rtentry *, struct llentry *,
|
||||
struct mbuf **));
|
||||
int nd6_output_flush __P((struct ifnet *, struct ifnet *, struct mbuf *,
|
||||
struct sockaddr_in6 *, struct route *));
|
||||
int nd6_need_cache __P((struct ifnet *));
|
||||
int nd6_storelladdr __P((struct ifnet *, struct mbuf *,
|
||||
struct sockaddr *, u_char *, struct llentry **));
|
||||
|
||||
/* nd6_nbr.c */
|
||||
void nd6_na_input __P((struct mbuf *, int, int));
|
||||
void nd6_na_output __P((struct ifnet *, const struct in6_addr *,
|
||||
const struct in6_addr *, u_long, int, struct sockaddr *));
|
||||
void nd6_ns_input __P((struct mbuf *, int, int));
|
||||
void nd6_ns_output __P((struct ifnet *, const struct in6_addr *,
|
||||
const struct in6_addr *, struct llentry *, int));
|
||||
caddr_t nd6_ifptomac __P((struct ifnet *));
|
||||
void nd6_dad_start __P((struct ifaddr *, int));
|
||||
void nd6_dad_stop __P((struct ifaddr *));
|
||||
void nd6_dad_duplicated __P((struct ifaddr *));
|
||||
|
||||
/* nd6_rtr.c */
|
||||
void nd6_rs_input __P((struct mbuf *, int, int));
|
||||
void nd6_ra_input __P((struct mbuf *, int, int));
|
||||
void prelist_del __P((struct nd_prefix *));
|
||||
void defrouter_addreq __P((struct nd_defrouter *));
|
||||
void defrouter_reset __P((void));
|
||||
void defrouter_select __P((void));
|
||||
void defrtrlist_del __P((struct nd_defrouter *));
|
||||
void prelist_remove __P((struct nd_prefix *));
|
||||
int nd6_prelist_add __P((struct nd_prefixctl *, struct nd_defrouter *,
|
||||
struct nd_prefix **));
|
||||
int nd6_prefix_onlink __P((struct nd_prefix *));
|
||||
int nd6_prefix_offlink __P((struct nd_prefix *));
|
||||
void pfxlist_onlink_check __P((void));
|
||||
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, struct ifnet *));
|
||||
struct nd_prefix *nd6_prefix_lookup __P((struct nd_prefixctl *));
|
||||
void rt6_flush __P((struct in6_addr *, struct ifnet *));
|
||||
int nd6_setdefaultiface __P((int));
|
||||
int in6_tmpifadd __P((const struct in6_ifaddr *, int, int));
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET6_ND6_HH_ */
|
1514
freebsd/netinet6/nd6_nbr.c
Normal file
1514
freebsd/netinet6/nd6_nbr.c
Normal file
File diff suppressed because it is too large
Load Diff
2162
freebsd/netinet6/nd6_rtr.c
Normal file
2162
freebsd/netinet6/nd6_rtr.c
Normal file
File diff suppressed because it is too large
Load Diff
69
freebsd/netinet6/pim6.h
Normal file
69
freebsd/netinet6/pim6.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*-
|
||||
* Copyright (C) 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: pim6.h,v 1.3 2000/03/25 07:23:58 sumikawa Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
* Protocol Independent Multicast (PIM) definitions
|
||||
*
|
||||
* Written by Ahmed Helmy, SGI, July 1996
|
||||
*
|
||||
* MULTICAST
|
||||
*/
|
||||
|
||||
/*
|
||||
* PIM packet header
|
||||
*/
|
||||
#define PIM_VERSION 2
|
||||
struct pim {
|
||||
#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
u_char pim_type:4, /* the PIM message type, currently they are:
|
||||
* Hello, Register, Register-Stop, Join/Prune,
|
||||
* Bootstrap, Assert, Graft (PIM-DM only),
|
||||
* Graft-Ack (PIM-DM only), C-RP-Adv
|
||||
*/
|
||||
pim_ver:4; /* PIM version number; 2 for PIMv2 */
|
||||
#else
|
||||
u_char pim_ver:4, /* PIM version */
|
||||
pim_type:4; /* PIM type */
|
||||
#endif
|
||||
u_char pim_rsv; /* Reserved */
|
||||
u_short pim_cksum; /* IP style check sum */
|
||||
};
|
||||
|
||||
#define PIM_MINLEN 8 /* The header min. length is 8 */
|
||||
#define PIM6_REG_MINLEN (PIM_MINLEN+40) /* Register message + inner IP6 header */
|
||||
|
||||
/*
|
||||
* Message types
|
||||
*/
|
||||
#define PIM_REGISTER 1 /* PIM Register type is 1 */
|
||||
|
||||
/* second bit in reg_head is the null bit */
|
||||
#define PIM_NULL_REGISTER 0x40000000
|
68
freebsd/netinet6/pim6_var.h
Normal file
68
freebsd/netinet6/pim6_var.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* Copyright (C) 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: pim6_var.h,v 1.8 2000/06/06 08:07:43 jinmei Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Protocol Independent Multicast (PIM),
|
||||
* implementation-specific definitions.
|
||||
*
|
||||
* Written by George Edmond Eddy (Rusty), ISI, February 1998
|
||||
* Modified by Pavlin Ivanov Radoslavov, USC/ISI, May 1998
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_PIM6_VAR_HH_
|
||||
#define _NETINET6_PIM6_VAR_HH_
|
||||
|
||||
struct pim6stat {
|
||||
u_quad_t pim6s_rcv_total; /* total PIM messages received */
|
||||
u_quad_t pim6s_rcv_tooshort; /* received with too few bytes */
|
||||
u_quad_t pim6s_rcv_badsum; /* received with bad checksum */
|
||||
u_quad_t pim6s_rcv_badversion; /* received bad PIM version */
|
||||
u_quad_t pim6s_rcv_registers; /* received registers */
|
||||
u_quad_t pim6s_rcv_badregisters; /* received invalid registers */
|
||||
u_quad_t pim6s_snd_registers; /* sent registers */
|
||||
};
|
||||
|
||||
#if (defined(KERNEL)) || (defined(_KERNEL))
|
||||
int pim6_input __P((struct mbuf **, int*, int));
|
||||
#endif /* KERNEL */
|
||||
|
||||
/*
|
||||
* Names for PIM sysctl objects
|
||||
*/
|
||||
#define PIM6CTL_STATS 1 /* statistics (read-only) */
|
||||
#define PIM6CTL_MAXID 2
|
||||
|
||||
#define PIM6CTL_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
{ 0, 0 }, \
|
||||
}
|
||||
#endif /* _NETINET6_PIM6_VAR_HH_ */
|
905
freebsd/netinet6/raw_ip6.c
Normal file
905
freebsd/netinet6/raw_ip6.c
Normal file
@@ -0,0 +1,905 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1988, 1993
|
||||
* The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_ipsec.h>
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/errno.h>
|
||||
#include <rtems/freebsd/sys/jail.h>
|
||||
#include <rtems/freebsd/sys/lock.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/priv.h>
|
||||
#include <rtems/freebsd/sys/proc.h>
|
||||
#include <rtems/freebsd/sys/protosw.h>
|
||||
#include <rtems/freebsd/sys/signalvar.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/socketvar.h>
|
||||
#include <rtems/freebsd/sys/sx.h>
|
||||
#include <rtems/freebsd/sys/syslog.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/if_types.h>
|
||||
#include <rtems/freebsd/net/route.h>
|
||||
#include <rtems/freebsd/net/vnet.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet/in_var.h>
|
||||
#include <rtems/freebsd/netinet/in_systm.h>
|
||||
#include <rtems/freebsd/netinet/in_pcb.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/icmp6.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6protosw.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_mroute.h>
|
||||
#include <rtems/freebsd/netinet6/in6_pcb.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/nd6.h>
|
||||
#include <rtems/freebsd/netinet6/raw_ip6.h>
|
||||
#include <rtems/freebsd/netinet6/scope6_var.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <rtems/freebsd/netipsec/ipsec.h>
|
||||
#include <rtems/freebsd/netipsec/ipsec6.h>
|
||||
#endif /* IPSEC */
|
||||
|
||||
#include <rtems/freebsd/machine/stdarg.h>
|
||||
|
||||
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
|
||||
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
|
||||
|
||||
/*
|
||||
* Raw interface to IP6 protocol.
|
||||
*/
|
||||
|
||||
VNET_DECLARE(struct inpcbhead, ripcb);
|
||||
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
|
||||
#define V_ripcb VNET(ripcb)
|
||||
#define V_ripcbinfo VNET(ripcbinfo)
|
||||
|
||||
extern u_long rip_sendspace;
|
||||
extern u_long rip_recvspace;
|
||||
|
||||
VNET_DEFINE(struct rip6stat, rip6stat);
|
||||
|
||||
/*
|
||||
* Hooks for multicast routing. They all default to NULL, so leave them not
|
||||
* initialized and rely on BSS being set to 0.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The socket used to communicate with the multicast routing daemon.
|
||||
*/
|
||||
VNET_DEFINE(struct socket *, ip6_mrouter);
|
||||
|
||||
/*
|
||||
* The various mrouter functions.
|
||||
*/
|
||||
int (*ip6_mrouter_set)(struct socket *, struct sockopt *);
|
||||
int (*ip6_mrouter_get)(struct socket *, struct sockopt *);
|
||||
int (*ip6_mrouter_done)(void);
|
||||
int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *);
|
||||
int (*mrt6_ioctl)(u_long, caddr_t);
|
||||
|
||||
/*
|
||||
* Setup generic address and protocol structures for raw_input routine, then
|
||||
* pass them along with mbuf chain.
|
||||
*/
|
||||
int
|
||||
rip6_input(struct mbuf **mp, int *offp, int proto)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
struct mbuf *m = *mp;
|
||||
register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
|
||||
register struct inpcb *in6p;
|
||||
struct inpcb *last = 0;
|
||||
struct mbuf *opts = NULL;
|
||||
struct sockaddr_in6 fromsa;
|
||||
|
||||
V_rip6stat.rip6s_ipackets++;
|
||||
|
||||
if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
|
||||
/* XXX Send icmp6 host/port unreach? */
|
||||
m_freem(m);
|
||||
return (IPPROTO_DONE);
|
||||
}
|
||||
|
||||
init_sin6(&fromsa, m); /* general init */
|
||||
|
||||
ifp = m->m_pkthdr.rcvif;
|
||||
|
||||
INP_INFO_RLOCK(&V_ripcbinfo);
|
||||
LIST_FOREACH(in6p, &V_ripcb, inp_list) {
|
||||
/* XXX inp locking */
|
||||
if ((in6p->inp_vflag & INP_IPV6) == 0)
|
||||
continue;
|
||||
if (in6p->inp_ip_p &&
|
||||
in6p->inp_ip_p != proto)
|
||||
continue;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
|
||||
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
|
||||
continue;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
|
||||
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
|
||||
continue;
|
||||
if (jailed_without_vnet(in6p->inp_cred)) {
|
||||
/*
|
||||
* Allow raw socket in jail to receive multicast;
|
||||
* assume process had PRIV_NETINET_RAW at attach,
|
||||
* and fall through into normal filter path if so.
|
||||
*/
|
||||
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
|
||||
prison_check_ip6(in6p->inp_cred,
|
||||
&ip6->ip6_dst) != 0)
|
||||
continue;
|
||||
}
|
||||
if (in6p->in6p_cksum != -1) {
|
||||
V_rip6stat.rip6s_isum++;
|
||||
if (in6_cksum(m, proto, *offp,
|
||||
m->m_pkthdr.len - *offp)) {
|
||||
INP_RUNLOCK(in6p);
|
||||
V_rip6stat.rip6s_badsum++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
INP_RLOCK(in6p);
|
||||
/*
|
||||
* If this raw socket has multicast state, and we
|
||||
* have received a multicast, check if this socket
|
||||
* should receive it, as multicast filtering is now
|
||||
* the responsibility of the transport layer.
|
||||
*/
|
||||
if (in6p->in6p_moptions &&
|
||||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
/*
|
||||
* If the incoming datagram is for MLD, allow it
|
||||
* through unconditionally to the raw socket.
|
||||
*
|
||||
* Use the M_RTALERT_MLD flag to check for MLD
|
||||
* traffic without having to inspect the mbuf chain
|
||||
* more deeply, as all MLDv1/v2 host messages MUST
|
||||
* contain the Router Alert option.
|
||||
*
|
||||
* In the case of MLDv1, we may not have explicitly
|
||||
* joined the group, and may have set IFF_ALLMULTI
|
||||
* on the interface. im6o_mc_filter() may discard
|
||||
* control traffic we actually need to see.
|
||||
*
|
||||
* Userland multicast routing daemons should continue
|
||||
* filter the control traffic appropriately.
|
||||
*/
|
||||
int blocked;
|
||||
|
||||
blocked = MCAST_PASS;
|
||||
if ((m->m_flags & M_RTALERT_MLD) == 0) {
|
||||
struct sockaddr_in6 mcaddr;
|
||||
|
||||
bzero(&mcaddr, sizeof(struct sockaddr_in6));
|
||||
mcaddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
mcaddr.sin6_family = AF_INET6;
|
||||
mcaddr.sin6_addr = ip6->ip6_dst;
|
||||
|
||||
blocked = im6o_mc_filter(in6p->in6p_moptions,
|
||||
ifp,
|
||||
(struct sockaddr *)&mcaddr,
|
||||
(struct sockaddr *)&fromsa);
|
||||
}
|
||||
if (blocked != MCAST_PASS) {
|
||||
IP6STAT_INC(ip6s_notmember);
|
||||
INP_RUNLOCK(in6p);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (last != NULL) {
|
||||
struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
|
||||
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if (n && ipsec6_in_reject(n, last)) {
|
||||
m_freem(n);
|
||||
V_ipsec6stat.in_polvio++;
|
||||
/* Do not inject data into pcb. */
|
||||
} else
|
||||
#endif /* IPSEC */
|
||||
if (n) {
|
||||
if (last->inp_flags & INP_CONTROLOPTS ||
|
||||
last->inp_socket->so_options & SO_TIMESTAMP)
|
||||
ip6_savecontrol(last, n, &opts);
|
||||
/* strip intermediate headers */
|
||||
m_adj(n, *offp);
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv,
|
||||
(struct sockaddr *)&fromsa,
|
||||
n, opts) == 0) {
|
||||
m_freem(n);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
V_rip6stat.rip6s_fullsock++;
|
||||
} else
|
||||
sorwakeup(last->inp_socket);
|
||||
opts = NULL;
|
||||
}
|
||||
INP_RUNLOCK(last);
|
||||
}
|
||||
last = in6p;
|
||||
}
|
||||
INP_INFO_RUNLOCK(&V_ripcbinfo);
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if ((last != NULL) && ipsec6_in_reject(m, last)) {
|
||||
m_freem(m);
|
||||
V_ipsec6stat.in_polvio++;
|
||||
V_ip6stat.ip6s_delivered--;
|
||||
/* Do not inject data into pcb. */
|
||||
INP_RUNLOCK(last);
|
||||
} else
|
||||
#endif /* IPSEC */
|
||||
if (last != NULL) {
|
||||
if (last->inp_flags & INP_CONTROLOPTS ||
|
||||
last->inp_socket->so_options & SO_TIMESTAMP)
|
||||
ip6_savecontrol(last, m, &opts);
|
||||
/* Strip intermediate headers. */
|
||||
m_adj(m, *offp);
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv,
|
||||
(struct sockaddr *)&fromsa, m, opts) == 0) {
|
||||
m_freem(m);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
V_rip6stat.rip6s_fullsock++;
|
||||
} else
|
||||
sorwakeup(last->inp_socket);
|
||||
INP_RUNLOCK(last);
|
||||
} else {
|
||||
V_rip6stat.rip6s_nosock++;
|
||||
if (m->m_flags & M_MCAST)
|
||||
V_rip6stat.rip6s_nosockmcast++;
|
||||
if (proto == IPPROTO_NONE)
|
||||
m_freem(m);
|
||||
else {
|
||||
char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
|
||||
icmp6_error(m, ICMP6_PARAM_PROB,
|
||||
ICMP6_PARAMPROB_NEXTHEADER,
|
||||
prvnxtp - mtod(m, char *));
|
||||
}
|
||||
V_ip6stat.ip6s_delivered--;
|
||||
}
|
||||
return (IPPROTO_DONE);
|
||||
}
|
||||
|
||||
void
|
||||
rip6_ctlinput(int cmd, struct sockaddr *sa, void *d)
|
||||
{
|
||||
struct ip6_hdr *ip6;
|
||||
struct mbuf *m;
|
||||
int off = 0;
|
||||
struct ip6ctlparam *ip6cp = NULL;
|
||||
const struct sockaddr_in6 *sa6_src = NULL;
|
||||
void *cmdarg;
|
||||
struct inpcb *(*notify)(struct inpcb *, int) = in6_rtchange;
|
||||
|
||||
if (sa->sa_family != AF_INET6 ||
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
return;
|
||||
|
||||
if ((unsigned)cmd >= PRC_NCMDS)
|
||||
return;
|
||||
if (PRC_IS_REDIRECT(cmd))
|
||||
notify = in6_rtchange, d = NULL;
|
||||
else if (cmd == PRC_HOSTDEAD)
|
||||
d = NULL;
|
||||
else if (inet6ctlerrmap[cmd] == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the parameter is from icmp6, decode it.
|
||||
*/
|
||||
if (d != NULL) {
|
||||
ip6cp = (struct ip6ctlparam *)d;
|
||||
m = ip6cp->ip6c_m;
|
||||
ip6 = ip6cp->ip6c_ip6;
|
||||
off = ip6cp->ip6c_off;
|
||||
cmdarg = ip6cp->ip6c_cmdarg;
|
||||
sa6_src = ip6cp->ip6c_src;
|
||||
} else {
|
||||
m = NULL;
|
||||
ip6 = NULL;
|
||||
cmdarg = NULL;
|
||||
sa6_src = &sa6_any;
|
||||
}
|
||||
|
||||
(void) in6_pcbnotify(&V_ripcbinfo, sa, 0,
|
||||
(const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate IPv6 header and pass packet to ip6_output. Tack on options user
|
||||
* may have setup with control call.
|
||||
*/
|
||||
int
|
||||
#if __STDC__
|
||||
rip6_output(struct mbuf *m, ...)
|
||||
#else
|
||||
rip6_output(m, va_alist)
|
||||
struct mbuf *m;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
struct mbuf *control;
|
||||
struct socket *so;
|
||||
struct sockaddr_in6 *dstsock;
|
||||
struct in6_addr *dst;
|
||||
struct ip6_hdr *ip6;
|
||||
struct inpcb *in6p;
|
||||
u_int plen = m->m_pkthdr.len;
|
||||
int error = 0;
|
||||
struct ip6_pktopts opt, *optp;
|
||||
struct ifnet *oifp = NULL;
|
||||
int type = 0, code = 0; /* for ICMPv6 output statistics only */
|
||||
int scope_ambiguous = 0;
|
||||
int use_defzone = 0;
|
||||
struct in6_addr in6a;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, m);
|
||||
so = va_arg(ap, struct socket *);
|
||||
dstsock = va_arg(ap, struct sockaddr_in6 *);
|
||||
control = va_arg(ap, struct mbuf *);
|
||||
va_end(ap);
|
||||
|
||||
in6p = sotoinpcb(so);
|
||||
INP_WLOCK(in6p);
|
||||
|
||||
dst = &dstsock->sin6_addr;
|
||||
if (control != NULL) {
|
||||
if ((error = ip6_setpktopts(control, &opt,
|
||||
in6p->in6p_outputopts, so->so_cred,
|
||||
so->so_proto->pr_protocol)) != 0) {
|
||||
goto bad;
|
||||
}
|
||||
optp = &opt;
|
||||
} else
|
||||
optp = in6p->in6p_outputopts;
|
||||
|
||||
/*
|
||||
* Check and convert scope zone ID into internal form.
|
||||
*
|
||||
* XXX: we may still need to determine the zone later.
|
||||
*/
|
||||
if (!(so->so_state & SS_ISCONNECTED)) {
|
||||
if (!optp || !optp->ip6po_pktinfo ||
|
||||
!optp->ip6po_pktinfo->ipi6_ifindex)
|
||||
use_defzone = V_ip6_use_defzone;
|
||||
if (dstsock->sin6_scope_id == 0 && !use_defzone)
|
||||
scope_ambiguous = 1;
|
||||
if ((error = sa6_embedscope(dstsock, use_defzone)) != 0)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* For an ICMPv6 packet, we should know its type and code to update
|
||||
* statistics.
|
||||
*/
|
||||
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
|
||||
struct icmp6_hdr *icmp6;
|
||||
if (m->m_len < sizeof(struct icmp6_hdr) &&
|
||||
(m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
icmp6 = mtod(m, struct icmp6_hdr *);
|
||||
type = icmp6->icmp6_type;
|
||||
code = icmp6->icmp6_code;
|
||||
}
|
||||
|
||||
M_PREPEND(m, sizeof(*ip6), M_DONTWAIT);
|
||||
if (m == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto bad;
|
||||
}
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
||||
/*
|
||||
* Source address selection.
|
||||
*/
|
||||
error = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
|
||||
&oifp, &in6a);
|
||||
if (error)
|
||||
goto bad;
|
||||
error = prison_check_ip6(in6p->inp_cred, &in6a);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
ip6->ip6_src = in6a;
|
||||
|
||||
if (oifp && scope_ambiguous) {
|
||||
/*
|
||||
* Application should provide a proper zone ID or the use of
|
||||
* default zone IDs should be enabled. Unfortunately, some
|
||||
* applications do not behave as it should, so we need a
|
||||
* workaround. Even if an appropriate ID is not determined
|
||||
* (when it's required), if we can determine the outgoing
|
||||
* interface. determine the zone ID based on the interface.
|
||||
*/
|
||||
error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
|
||||
if (error != 0)
|
||||
goto bad;
|
||||
}
|
||||
ip6->ip6_dst = dstsock->sin6_addr;
|
||||
|
||||
/*
|
||||
* Fill in the rest of the IPv6 header fields.
|
||||
*/
|
||||
ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
|
||||
(in6p->inp_flow & IPV6_FLOWINFO_MASK);
|
||||
ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
|
||||
(IPV6_VERSION & IPV6_VERSION_MASK);
|
||||
|
||||
/*
|
||||
* ip6_plen will be filled in ip6_output, so not fill it here.
|
||||
*/
|
||||
ip6->ip6_nxt = in6p->inp_ip_p;
|
||||
ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
|
||||
|
||||
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
|
||||
in6p->in6p_cksum != -1) {
|
||||
struct mbuf *n;
|
||||
int off;
|
||||
u_int16_t *p;
|
||||
|
||||
/* Compute checksum. */
|
||||
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
|
||||
off = offsetof(struct icmp6_hdr, icmp6_cksum);
|
||||
else
|
||||
off = in6p->in6p_cksum;
|
||||
if (plen < off + 1) {
|
||||
error = EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
off += sizeof(struct ip6_hdr);
|
||||
|
||||
n = m;
|
||||
while (n && n->m_len <= off) {
|
||||
off -= n->m_len;
|
||||
n = n->m_next;
|
||||
}
|
||||
if (!n)
|
||||
goto bad;
|
||||
p = (u_int16_t *)(mtod(n, caddr_t) + off);
|
||||
*p = 0;
|
||||
*p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
|
||||
}
|
||||
|
||||
error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p);
|
||||
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
|
||||
if (oifp)
|
||||
icmp6_ifoutstat_inc(oifp, type, code);
|
||||
ICMP6STAT_INC(icp6s_outhist[type]);
|
||||
} else
|
||||
V_rip6stat.rip6s_opackets++;
|
||||
|
||||
goto freectl;
|
||||
|
||||
bad:
|
||||
if (m)
|
||||
m_freem(m);
|
||||
|
||||
freectl:
|
||||
if (control != NULL) {
|
||||
ip6_clearpktopts(&opt, -1);
|
||||
m_freem(control);
|
||||
}
|
||||
INP_WUNLOCK(in6p);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Raw IPv6 socket option processing.
|
||||
*/
|
||||
int
|
||||
rip6_ctloutput(struct socket *so, struct sockopt *sopt)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (sopt->sopt_level == IPPROTO_ICMPV6)
|
||||
/*
|
||||
* XXX: is it better to call icmp6_ctloutput() directly
|
||||
* from protosw?
|
||||
*/
|
||||
return (icmp6_ctloutput(so, sopt));
|
||||
else if (sopt->sopt_level != IPPROTO_IPV6)
|
||||
return (EINVAL);
|
||||
|
||||
error = 0;
|
||||
|
||||
switch (sopt->sopt_dir) {
|
||||
case SOPT_GET:
|
||||
switch (sopt->sopt_name) {
|
||||
case MRT6_INIT:
|
||||
case MRT6_DONE:
|
||||
case MRT6_ADD_MIF:
|
||||
case MRT6_DEL_MIF:
|
||||
case MRT6_ADD_MFC:
|
||||
case MRT6_DEL_MFC:
|
||||
case MRT6_PIM:
|
||||
error = ip6_mrouter_get ? ip6_mrouter_get(so, sopt) :
|
||||
EOPNOTSUPP;
|
||||
break;
|
||||
case IPV6_CHECKSUM:
|
||||
error = ip6_raw_ctloutput(so, sopt);
|
||||
break;
|
||||
default:
|
||||
error = ip6_ctloutput(so, sopt);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SOPT_SET:
|
||||
switch (sopt->sopt_name) {
|
||||
case MRT6_INIT:
|
||||
case MRT6_DONE:
|
||||
case MRT6_ADD_MIF:
|
||||
case MRT6_DEL_MIF:
|
||||
case MRT6_ADD_MFC:
|
||||
case MRT6_DEL_MFC:
|
||||
case MRT6_PIM:
|
||||
error = ip6_mrouter_set ? ip6_mrouter_set(so, sopt) :
|
||||
EOPNOTSUPP;
|
||||
break;
|
||||
case IPV6_CHECKSUM:
|
||||
error = ip6_raw_ctloutput(so, sopt);
|
||||
break;
|
||||
default:
|
||||
error = ip6_ctloutput(so, sopt);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
rip6_attach(struct socket *so, int proto, struct thread *td)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
struct icmp6_filter *filter;
|
||||
int error;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp == NULL, ("rip6_attach: inp != NULL"));
|
||||
|
||||
error = priv_check(td, PRIV_NETINET_RAW);
|
||||
if (error)
|
||||
return (error);
|
||||
error = soreserve(so, rip_sendspace, rip_recvspace);
|
||||
if (error)
|
||||
return (error);
|
||||
filter = malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
|
||||
if (filter == NULL)
|
||||
return (ENOMEM);
|
||||
INP_INFO_WLOCK(&V_ripcbinfo);
|
||||
error = in_pcballoc(so, &V_ripcbinfo);
|
||||
if (error) {
|
||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||
free(filter, M_PCB);
|
||||
return (error);
|
||||
}
|
||||
inp = (struct inpcb *)so->so_pcb;
|
||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||
inp->inp_vflag |= INP_IPV6;
|
||||
inp->inp_ip_p = (long)proto;
|
||||
inp->in6p_hops = -1; /* use kernel default */
|
||||
inp->in6p_cksum = -1;
|
||||
inp->in6p_icmp6filt = filter;
|
||||
ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
|
||||
INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
rip6_detach(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
|
||||
|
||||
if (so == V_ip6_mrouter && ip6_mrouter_done)
|
||||
ip6_mrouter_done();
|
||||
/* xxx: RSVP */
|
||||
INP_INFO_WLOCK(&V_ripcbinfo);
|
||||
INP_WLOCK(inp);
|
||||
free(inp->in6p_icmp6filt, M_PCB);
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||
}
|
||||
|
||||
/* XXXRW: This can't ever be called. */
|
||||
static void
|
||||
rip6_abort(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_abort: inp == NULL"));
|
||||
|
||||
soisdisconnected(so);
|
||||
}
|
||||
|
||||
static void
|
||||
rip6_close(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_close: inp == NULL"));
|
||||
|
||||
soisdisconnected(so);
|
||||
}
|
||||
|
||||
static int
|
||||
rip6_disconnect(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_disconnect: inp == NULL"));
|
||||
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0)
|
||||
return (ENOTCONN);
|
||||
inp->in6p_faddr = in6addr_any;
|
||||
rip6_abort(so);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
|
||||
struct ifaddr *ifa = NULL;
|
||||
int error = 0;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_bind: inp == NULL"));
|
||||
|
||||
if (nam->sa_len != sizeof(*addr))
|
||||
return (EINVAL);
|
||||
if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0)
|
||||
return (error);
|
||||
if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6)
|
||||
return (EADDRNOTAVAIL);
|
||||
if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
|
||||
return (error);
|
||||
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
|
||||
(ifa = ifa_ifwithaddr((struct sockaddr *)addr)) == NULL)
|
||||
return (EADDRNOTAVAIL);
|
||||
if (ifa != NULL &&
|
||||
((struct in6_ifaddr *)ifa)->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
|
||||
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
|
||||
ifa_free(ifa);
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
if (ifa != NULL)
|
||||
ifa_free(ifa);
|
||||
INP_INFO_WLOCK(&V_ripcbinfo);
|
||||
INP_WLOCK(inp);
|
||||
inp->in6p_laddr = addr->sin6_addr;
|
||||
INP_WUNLOCK(inp);
|
||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
|
||||
struct in6_addr in6a;
|
||||
struct ifnet *ifp = NULL;
|
||||
int error = 0, scope_ambiguous = 0;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_connect: inp == NULL"));
|
||||
|
||||
if (nam->sa_len != sizeof(*addr))
|
||||
return (EINVAL);
|
||||
if (TAILQ_EMPTY(&V_ifnet))
|
||||
return (EADDRNOTAVAIL);
|
||||
if (addr->sin6_family != AF_INET6)
|
||||
return (EAFNOSUPPORT);
|
||||
|
||||
/*
|
||||
* Application should provide a proper zone ID or the use of default
|
||||
* zone IDs should be enabled. Unfortunately, some applications do
|
||||
* not behave as it should, so we need a workaround. Even if an
|
||||
* appropriate ID is not determined, we'll see if we can determine
|
||||
* the outgoing interface. If we can, determine the zone ID based on
|
||||
* the interface below.
|
||||
*/
|
||||
if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone)
|
||||
scope_ambiguous = 1;
|
||||
if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
|
||||
return (error);
|
||||
|
||||
INP_INFO_WLOCK(&V_ripcbinfo);
|
||||
INP_WLOCK(inp);
|
||||
/* Source address selection. XXX: need pcblookup? */
|
||||
error = in6_selectsrc(addr, inp->in6p_outputopts,
|
||||
inp, NULL, so->so_cred, &ifp, &in6a);
|
||||
if (error) {
|
||||
INP_WUNLOCK(inp);
|
||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* XXX: see above */
|
||||
if (ifp && scope_ambiguous &&
|
||||
(error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
|
||||
INP_WUNLOCK(inp);
|
||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||
return (error);
|
||||
}
|
||||
inp->in6p_faddr = addr->sin6_addr;
|
||||
inp->in6p_laddr = in6a;
|
||||
soisconnected(so);
|
||||
INP_WUNLOCK(inp);
|
||||
INP_INFO_WUNLOCK(&V_ripcbinfo);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rip6_shutdown(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_shutdown: inp == NULL"));
|
||||
|
||||
INP_WLOCK(inp);
|
||||
socantsendmore(so);
|
||||
INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
struct mbuf *control, struct thread *td)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
struct sockaddr_in6 tmp;
|
||||
struct sockaddr_in6 *dst;
|
||||
int ret;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip6_send: inp == NULL"));
|
||||
|
||||
/* Always copy sockaddr to avoid overwrites. */
|
||||
/* Unlocked read. */
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
if (nam) {
|
||||
m_freem(m);
|
||||
return (EISCONN);
|
||||
}
|
||||
/* XXX */
|
||||
bzero(&tmp, sizeof(tmp));
|
||||
tmp.sin6_family = AF_INET6;
|
||||
tmp.sin6_len = sizeof(struct sockaddr_in6);
|
||||
INP_RLOCK(inp);
|
||||
bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
INP_RUNLOCK(inp);
|
||||
dst = &tmp;
|
||||
} else {
|
||||
if (nam == NULL) {
|
||||
m_freem(m);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
if (nam->sa_len != sizeof(struct sockaddr_in6)) {
|
||||
m_freem(m);
|
||||
return (EINVAL);
|
||||
}
|
||||
tmp = *(struct sockaddr_in6 *)nam;
|
||||
dst = &tmp;
|
||||
|
||||
if (dst->sin6_family == AF_UNSPEC) {
|
||||
/*
|
||||
* XXX: we allow this case for backward
|
||||
* compatibility to buggy applications that
|
||||
* rely on old (and wrong) kernel behavior.
|
||||
*/
|
||||
log(LOG_INFO, "rip6 SEND: address family is "
|
||||
"unspec. Assume AF_INET6\n");
|
||||
dst->sin6_family = AF_INET6;
|
||||
} else if (dst->sin6_family != AF_INET6) {
|
||||
m_freem(m);
|
||||
return(EAFNOSUPPORT);
|
||||
}
|
||||
}
|
||||
ret = rip6_output(m, so, dst, control);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
struct pr_usrreqs rip6_usrreqs = {
|
||||
.pru_abort = rip6_abort,
|
||||
.pru_attach = rip6_attach,
|
||||
.pru_bind = rip6_bind,
|
||||
.pru_connect = rip6_connect,
|
||||
.pru_control = in6_control,
|
||||
.pru_detach = rip6_detach,
|
||||
.pru_disconnect = rip6_disconnect,
|
||||
.pru_peeraddr = in6_getpeeraddr,
|
||||
.pru_send = rip6_send,
|
||||
.pru_shutdown = rip6_shutdown,
|
||||
.pru_sockaddr = in6_getsockaddr,
|
||||
.pru_close = rip6_close,
|
||||
};
|
55
freebsd/netinet6/raw_ip6.h
Normal file
55
freebsd/netinet6/raw_ip6.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*-
|
||||
* Copyright (C) 2001 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: raw_ip6.h,v 1.2 2001/05/27 13:28:35 itojun Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_RAW_IP6_HH_
|
||||
#define _NETINET6_RAW_IP6_HH_
|
||||
|
||||
/*
|
||||
* ICMPv6 stat is counted separately. see netinet/icmp6.h
|
||||
*/
|
||||
struct rip6stat {
|
||||
u_quad_t rip6s_ipackets; /* total input packets */
|
||||
u_quad_t rip6s_isum; /* input checksum computations */
|
||||
u_quad_t rip6s_badsum; /* of above, checksum error */
|
||||
u_quad_t rip6s_nosock; /* no matching socket */
|
||||
u_quad_t rip6s_nosockmcast; /* of above, arrived as multicast */
|
||||
u_quad_t rip6s_fullsock; /* not delivered, input socket full */
|
||||
|
||||
u_quad_t rip6s_opackets; /* total output packets */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
VNET_DECLARE(struct rip6stat, rip6stat);
|
||||
#define V_rip6stat VNET(rip6stat)
|
||||
#endif
|
||||
|
||||
#endif
|
111
freebsd/netinet6/route6.c
Normal file
111
freebsd/netinet6/route6.c
Normal file
@@ -0,0 +1,111 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: route6.c,v 1.24 2001/03/14 03:07:05 itojun Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/local/opt_inet.h>
|
||||
#include <rtems/freebsd/local/opt_inet6.h>
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/queue.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
#include <rtems/freebsd/netinet6/in6_var.h>
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/scope6_var.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/icmp6.h>
|
||||
|
||||
/*
|
||||
* proto - is unused
|
||||
*/
|
||||
|
||||
int
|
||||
route6_input(struct mbuf **mp, int *offp, int proto)
|
||||
{
|
||||
struct ip6_hdr *ip6;
|
||||
struct mbuf *m = *mp;
|
||||
struct ip6_rthdr *rh;
|
||||
int off = *offp, rhlen;
|
||||
struct ip6aux *ip6a;
|
||||
|
||||
ip6a = ip6_findaux(m);
|
||||
if (ip6a) {
|
||||
/* XXX reject home-address option before rthdr */
|
||||
if (ip6a->ip6a_flags & IP6A_SWAP) {
|
||||
V_ip6stat.ip6s_badoptions++;
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off, sizeof(*rh), IPPROTO_DONE);
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
rh = (struct ip6_rthdr *)((caddr_t)ip6 + off);
|
||||
#else
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
IP6_EXTHDR_GET(rh, struct ip6_rthdr *, m, off, sizeof(*rh));
|
||||
if (rh == NULL) {
|
||||
V_ip6stat.ip6s_tooshort++;
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* While this switch may look gratuitous, leave it in
|
||||
* in favour of RH2 implementations, etc.
|
||||
*/
|
||||
switch (rh->ip6r_type) {
|
||||
default:
|
||||
/* Unknown routing header type. */
|
||||
if (rh->ip6r_segleft == 0) {
|
||||
rhlen = (rh->ip6r_len + 1) << 3;
|
||||
break; /* Final dst. Just ignore the header. */
|
||||
}
|
||||
V_ip6stat.ip6s_badoptions++;
|
||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||
(caddr_t)&rh->ip6r_type - (caddr_t)ip6);
|
||||
return (IPPROTO_DONE);
|
||||
}
|
||||
|
||||
*offp += rhlen;
|
||||
return (rh->ip6r_nxt);
|
||||
}
|
498
freebsd/netinet6/scope6.c
Normal file
498
freebsd/netinet6/scope6.c
Normal file
@@ -0,0 +1,498 @@
|
||||
#include <rtems/freebsd/machine/rtems-bsd-config.h>
|
||||
|
||||
/*-
|
||||
* Copyright (C) 2000 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: scope6.c,v 1.10 2000/07/24 13:29:31 itojun Exp $
|
||||
*/
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <rtems/freebsd/sys/param.h>
|
||||
#include <rtems/freebsd/sys/malloc.h>
|
||||
#include <rtems/freebsd/sys/mbuf.h>
|
||||
#include <rtems/freebsd/sys/socket.h>
|
||||
#include <rtems/freebsd/sys/systm.h>
|
||||
#include <rtems/freebsd/sys/queue.h>
|
||||
#include <rtems/freebsd/sys/syslog.h>
|
||||
|
||||
#include <rtems/freebsd/net/if.h>
|
||||
#include <rtems/freebsd/net/vnet.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/in.h>
|
||||
|
||||
#include <rtems/freebsd/netinet/ip6.h>
|
||||
#include <rtems/freebsd/netinet6/in6_var.h>
|
||||
#include <rtems/freebsd/netinet6/ip6_var.h>
|
||||
#include <rtems/freebsd/netinet6/scope6_var.h>
|
||||
|
||||
#ifdef ENABLE_DEFAULT_SCOPE
|
||||
VNET_DEFINE(int, ip6_use_defzone) = 1;
|
||||
#else
|
||||
VNET_DEFINE(int, ip6_use_defzone) = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The scope6_lock protects the global sid default stored in
|
||||
* sid_default below.
|
||||
*/
|
||||
static struct mtx scope6_lock;
|
||||
#define SCOPE6_LOCK_INIT() mtx_init(&scope6_lock, "scope6_lock", NULL, MTX_DEF)
|
||||
#define SCOPE6_LOCK() mtx_lock(&scope6_lock)
|
||||
#define SCOPE6_UNLOCK() mtx_unlock(&scope6_lock)
|
||||
#define SCOPE6_LOCK_ASSERT() mtx_assert(&scope6_lock, MA_OWNED)
|
||||
|
||||
static VNET_DEFINE(struct scope6_id, sid_default);
|
||||
#define V_sid_default VNET(sid_default)
|
||||
|
||||
#define SID(ifp) \
|
||||
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->scope6_id)
|
||||
|
||||
void
|
||||
scope6_init(void)
|
||||
{
|
||||
|
||||
bzero(&V_sid_default, sizeof(V_sid_default));
|
||||
|
||||
if (!IS_DEFAULT_VNET(curvnet))
|
||||
return;
|
||||
|
||||
SCOPE6_LOCK_INIT();
|
||||
}
|
||||
|
||||
struct scope6_id *
|
||||
scope6_ifattach(struct ifnet *ifp)
|
||||
{
|
||||
struct scope6_id *sid;
|
||||
|
||||
sid = (struct scope6_id *)malloc(sizeof(*sid), M_IFADDR, M_WAITOK);
|
||||
bzero(sid, sizeof(*sid));
|
||||
|
||||
/*
|
||||
* XXX: IPV6_ADDR_SCOPE_xxx macros are not standard.
|
||||
* Should we rather hardcode here?
|
||||
*/
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] = ifp->if_index;
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = ifp->if_index;
|
||||
#ifdef MULTI_SCOPE
|
||||
/* by default, we don't care about scope boundary for these scopes. */
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL] = 1;
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1;
|
||||
#endif
|
||||
|
||||
return sid;
|
||||
}
|
||||
|
||||
void
|
||||
scope6_ifdetach(struct scope6_id *sid)
|
||||
{
|
||||
|
||||
free(sid, M_IFADDR);
|
||||
}
|
||||
|
||||
int
|
||||
scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
|
||||
{
|
||||
int i;
|
||||
int error = 0;
|
||||
struct scope6_id *sid = NULL;
|
||||
|
||||
IF_AFDATA_LOCK(ifp);
|
||||
sid = SID(ifp);
|
||||
|
||||
if (!sid) { /* paranoid? */
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: We need more consistency checks of the relationship among
|
||||
* scopes (e.g. an organization should be larger than a site).
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO(XXX): after setting, we should reflect the changes to
|
||||
* interface addresses, routing table entries, PCB entries...
|
||||
*/
|
||||
|
||||
SCOPE6_LOCK();
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (idlist->s6id_list[i] &&
|
||||
idlist->s6id_list[i] != sid->s6id_list[i]) {
|
||||
/*
|
||||
* An interface zone ID must be the corresponding
|
||||
* interface index by definition.
|
||||
*/
|
||||
if (i == IPV6_ADDR_SCOPE_INTFACELOCAL &&
|
||||
idlist->s6id_list[i] != ifp->if_index) {
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
SCOPE6_UNLOCK();
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
|
||||
idlist->s6id_list[i] > V_if_index) {
|
||||
/*
|
||||
* XXX: theoretically, there should be no
|
||||
* relationship between link IDs and interface
|
||||
* IDs, but we check the consistency for
|
||||
* safety in later use.
|
||||
*/
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
SCOPE6_UNLOCK();
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: we must need lots of work in this case,
|
||||
* but we simply set the new value in this initial
|
||||
* implementation.
|
||||
*/
|
||||
sid->s6id_list[i] = idlist->s6id_list[i];
|
||||
}
|
||||
}
|
||||
SCOPE6_UNLOCK();
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
scope6_get(struct ifnet *ifp, struct scope6_id *idlist)
|
||||
{
|
||||
/* We only need to lock the interface's afdata for SID() to work. */
|
||||
IF_AFDATA_LOCK(ifp);
|
||||
struct scope6_id *sid = SID(ifp);
|
||||
|
||||
if (sid == NULL) { /* paranoid? */
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
SCOPE6_LOCK();
|
||||
*idlist = *sid;
|
||||
SCOPE6_UNLOCK();
|
||||
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get a scope of the address. Node-local, link-local, site-local or global.
|
||||
*/
|
||||
int
|
||||
in6_addrscope(struct in6_addr *addr)
|
||||
{
|
||||
int scope;
|
||||
|
||||
if (addr->s6_addr[0] == 0xfe) {
|
||||
scope = addr->s6_addr[1] & 0xc0;
|
||||
|
||||
switch (scope) {
|
||||
case 0x80:
|
||||
return IPV6_ADDR_SCOPE_LINKLOCAL;
|
||||
break;
|
||||
case 0xc0:
|
||||
return IPV6_ADDR_SCOPE_SITELOCAL;
|
||||
break;
|
||||
default:
|
||||
return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (addr->s6_addr[0] == 0xff) {
|
||||
scope = addr->s6_addr[1] & 0x0f;
|
||||
|
||||
/*
|
||||
* due to other scope such as reserved,
|
||||
* return scope doesn't work.
|
||||
*/
|
||||
switch (scope) {
|
||||
case IPV6_ADDR_SCOPE_INTFACELOCAL:
|
||||
return IPV6_ADDR_SCOPE_INTFACELOCAL;
|
||||
break;
|
||||
case IPV6_ADDR_SCOPE_LINKLOCAL:
|
||||
return IPV6_ADDR_SCOPE_LINKLOCAL;
|
||||
break;
|
||||
case IPV6_ADDR_SCOPE_SITELOCAL:
|
||||
return IPV6_ADDR_SCOPE_SITELOCAL;
|
||||
break;
|
||||
default:
|
||||
return IPV6_ADDR_SCOPE_GLOBAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Regard loopback and unspecified addresses as global, since
|
||||
* they have no ambiguity.
|
||||
*/
|
||||
if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
|
||||
if (addr->s6_addr[15] == 1) /* loopback */
|
||||
return IPV6_ADDR_SCOPE_LINKLOCAL;
|
||||
if (addr->s6_addr[15] == 0) /* unspecified */
|
||||
return IPV6_ADDR_SCOPE_GLOBAL; /* XXX: correct? */
|
||||
}
|
||||
|
||||
return IPV6_ADDR_SCOPE_GLOBAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ifp - note that this might be NULL
|
||||
*/
|
||||
|
||||
void
|
||||
scope6_setdefault(struct ifnet *ifp)
|
||||
{
|
||||
|
||||
/*
|
||||
* Currently, this function just sets the default "interfaces"
|
||||
* and "links" according to the given interface.
|
||||
* We might eventually have to separate the notion of "link" from
|
||||
* "interface" and provide a user interface to set the default.
|
||||
*/
|
||||
SCOPE6_LOCK();
|
||||
if (ifp) {
|
||||
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] =
|
||||
ifp->if_index;
|
||||
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] =
|
||||
ifp->if_index;
|
||||
} else {
|
||||
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] = 0;
|
||||
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0;
|
||||
}
|
||||
SCOPE6_UNLOCK();
|
||||
}
|
||||
|
||||
int
|
||||
scope6_get_default(struct scope6_id *idlist)
|
||||
{
|
||||
|
||||
SCOPE6_LOCK();
|
||||
*idlist = V_sid_default;
|
||||
SCOPE6_UNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
scope6_addr2default(struct in6_addr *addr)
|
||||
{
|
||||
u_int32_t id;
|
||||
|
||||
/*
|
||||
* special case: The loopback address should be considered as
|
||||
* link-local, but there's no ambiguity in the syntax.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LOOPBACK(addr))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* XXX: 32-bit read is atomic on all our platforms, is it OK
|
||||
* not to lock here?
|
||||
*/
|
||||
SCOPE6_LOCK();
|
||||
id = V_sid_default.s6id_list[in6_addrscope(addr)];
|
||||
SCOPE6_UNLOCK();
|
||||
return (id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the specified scope zone ID in the sin6_scope_id field. If the ID
|
||||
* is unspecified (=0), needs to be specified, and the default zone ID can be
|
||||
* used, the default value will be used.
|
||||
* This routine then generates the kernel-internal form: if the address scope
|
||||
* of is interface-local or link-local, embed the interface index in the
|
||||
* address.
|
||||
*/
|
||||
int
|
||||
sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
u_int32_t zoneid;
|
||||
|
||||
if ((zoneid = sin6->sin6_scope_id) == 0 && defaultok)
|
||||
zoneid = scope6_addr2default(&sin6->sin6_addr);
|
||||
|
||||
if (zoneid != 0 &&
|
||||
(IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
|
||||
IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr))) {
|
||||
/*
|
||||
* At this moment, we only check interface-local and
|
||||
* link-local scope IDs, and use interface indices as the
|
||||
* zone IDs assuming a one-to-one mapping between interfaces
|
||||
* and links.
|
||||
*/
|
||||
if (V_if_index < zoneid)
|
||||
return (ENXIO);
|
||||
ifp = ifnet_byindex(zoneid);
|
||||
if (ifp == NULL) /* XXX: this can happen for some OS */
|
||||
return (ENXIO);
|
||||
|
||||
/* XXX assignment to 16bit from 32bit variable */
|
||||
sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff);
|
||||
|
||||
sin6->sin6_scope_id = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* generate standard sockaddr_in6 from embedded form.
|
||||
*/
|
||||
int
|
||||
sa6_recoverscope(struct sockaddr_in6 *sin6)
|
||||
{
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
u_int32_t zoneid;
|
||||
|
||||
if (sin6->sin6_scope_id != 0) {
|
||||
log(LOG_NOTICE,
|
||||
"sa6_recoverscope: assumption failure (non 0 ID): %s%%%d\n",
|
||||
ip6_sprintf(ip6buf, &sin6->sin6_addr), sin6->sin6_scope_id);
|
||||
/* XXX: proceed anyway... */
|
||||
}
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
|
||||
IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)) {
|
||||
/*
|
||||
* KAME assumption: link id == interface id
|
||||
*/
|
||||
zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
|
||||
if (zoneid) {
|
||||
/* sanity check */
|
||||
if (zoneid < 0 || V_if_index < zoneid)
|
||||
return (ENXIO);
|
||||
if (!ifnet_byindex(zoneid))
|
||||
return (ENXIO);
|
||||
sin6->sin6_addr.s6_addr16[1] = 0;
|
||||
sin6->sin6_scope_id = zoneid;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the appropriate scope zone ID for in6 and ifp. If ret_id is
|
||||
* non NULL, it is set to the zone ID. If the zone ID needs to be embedded
|
||||
* in the in6_addr structure, in6 will be modified.
|
||||
*
|
||||
* ret_id - unnecessary?
|
||||
*/
|
||||
int
|
||||
in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
|
||||
{
|
||||
int scope;
|
||||
u_int32_t zoneid = 0;
|
||||
struct scope6_id *sid;
|
||||
|
||||
IF_AFDATA_LOCK(ifp);
|
||||
|
||||
sid = SID(ifp);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (sid == NULL) { /* should not happen */
|
||||
panic("in6_setscope: scope array is NULL");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* special case: the loopback address can only belong to a loopback
|
||||
* interface.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LOOPBACK(in6)) {
|
||||
if (!(ifp->if_flags & IFF_LOOPBACK)) {
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
return (EINVAL);
|
||||
} else {
|
||||
if (ret_id != NULL)
|
||||
*ret_id = 0; /* there's no ambiguity */
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
scope = in6_addrscope(in6);
|
||||
|
||||
SCOPE6_LOCK();
|
||||
switch (scope) {
|
||||
case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */
|
||||
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL];
|
||||
break;
|
||||
|
||||
case IPV6_ADDR_SCOPE_LINKLOCAL:
|
||||
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL];
|
||||
break;
|
||||
|
||||
case IPV6_ADDR_SCOPE_SITELOCAL:
|
||||
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL];
|
||||
break;
|
||||
|
||||
case IPV6_ADDR_SCOPE_ORGLOCAL:
|
||||
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL];
|
||||
break;
|
||||
|
||||
default:
|
||||
zoneid = 0; /* XXX: treat as global. */
|
||||
break;
|
||||
}
|
||||
SCOPE6_UNLOCK();
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
|
||||
if (ret_id != NULL)
|
||||
*ret_id = zoneid;
|
||||
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6))
|
||||
in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just clear the embedded scope identifier. Return 0 if the original address
|
||||
* is intact; return non 0 if the address is modified.
|
||||
*/
|
||||
int
|
||||
in6_clearscope(struct in6_addr *in6)
|
||||
{
|
||||
int modified = 0;
|
||||
|
||||
if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
|
||||
if (in6->s6_addr16[1] != 0)
|
||||
modified = 1;
|
||||
in6->s6_addr16[1] = 0;
|
||||
}
|
||||
|
||||
return (modified);
|
||||
}
|
60
freebsd/netinet6/scope6_var.h
Normal file
60
freebsd/netinet6/scope6_var.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*-
|
||||
* Copyright (C) 2000 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $KAME: scope6_var.h,v 1.4 2000/05/18 15:03:27 jinmei Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_SCOPE6_VAR_HH_
|
||||
#define _NETINET6_SCOPE6_VAR_HH_
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct scope6_id {
|
||||
/*
|
||||
* 16 is correspondent to 4bit multicast scope field.
|
||||
* i.e. from node-local to global with some reserved/unassigned types.
|
||||
*/
|
||||
u_int32_t s6id_list[16];
|
||||
};
|
||||
|
||||
void scope6_init __P((void));
|
||||
struct scope6_id *scope6_ifattach __P((struct ifnet *));
|
||||
void scope6_ifdetach __P((struct scope6_id *));
|
||||
int scope6_set __P((struct ifnet *, struct scope6_id *));
|
||||
int scope6_get __P((struct ifnet *, struct scope6_id *));
|
||||
void scope6_setdefault __P((struct ifnet *));
|
||||
int scope6_get_default __P((struct scope6_id *));
|
||||
u_int32_t scope6_in6_addrscope __P((struct in6_addr *));
|
||||
u_int32_t scope6_addr2default __P((struct in6_addr *));
|
||||
int sa6_embedscope __P((struct sockaddr_in6 *, int));
|
||||
int sa6_recoverscope __P((struct sockaddr_in6 *));
|
||||
int in6_setscope __P((struct in6_addr *, struct ifnet *, u_int32_t *));
|
||||
int in6_clearscope __P((struct in6_addr *));
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET6_SCOPE6_VAR_HH_ */
|
1319
freebsd/netinet6/sctp6_usrreq.c
Normal file
1319
freebsd/netinet6/sctp6_usrreq.c
Normal file
File diff suppressed because it is too large
Load Diff
61
freebsd/netinet6/sctp6_var.h
Normal file
61
freebsd/netinet6/sctp6_var.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*-
|
||||
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* a) Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* b) Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* c) Neither the name of Cisco Systems, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* $KAME: sctp6_var.h,v 1.7 2004/08/17 04:06:22 itojun Exp $ */
|
||||
|
||||
#ifndef _NETINET6_SCTP6_VAR_HH_
|
||||
#define _NETINET6_SCTP6_VAR_HH_
|
||||
|
||||
#include <rtems/freebsd/sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* TODO __Userspace__ IPv6 stuff... */
|
||||
#if defined(_KERNEL)
|
||||
|
||||
SYSCTL_DECL(_net_inet6_sctp6);
|
||||
extern struct pr_usrreqs sctp6_usrreqs;
|
||||
|
||||
|
||||
int sctp6_input __P((struct mbuf **, int *, int));
|
||||
int sctp6_output
|
||||
__P((struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
|
||||
struct mbuf *, struct proc *));
|
||||
void sctp6_ctlinput __P((int, struct sockaddr *, void *));
|
||||
|
||||
|
||||
extern void sctp6_notify(struct sctp_inpcb *inp,
|
||||
struct icmp6_hdr *icmph,
|
||||
struct sctphdr *sh,
|
||||
struct sockaddr *to,
|
||||
struct sctp_tcb *stcb,
|
||||
struct sctp_nets *net);
|
||||
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif
|
83
freebsd/netinet6/tcp6_var.h
Normal file
83
freebsd/netinet6/tcp6_var.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1993, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_var.h 8.4 (Berkeley) 5/24/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET_TCP6_VAR_HH_
|
||||
#define _NETINET_TCP6_VAR_HH_
|
||||
|
||||
#ifdef _KERNEL
|
||||
#ifdef SYSCTL_DECL
|
||||
SYSCTL_DECL(_net_inet6_tcp6);
|
||||
|
||||
VNET_DECLARE(int, tcp_v6mssdflt); /* XXX */
|
||||
#define V_tcp_v6mssdflt VNET(tcp_v6mssdflt)
|
||||
#endif
|
||||
|
||||
struct ip6_hdr;
|
||||
void tcp6_ctlinput __P((int, struct sockaddr *, void *));
|
||||
void tcp6_init __P((void));
|
||||
int tcp6_input __P((struct mbuf **, int *, int));
|
||||
struct rtentry *tcp_rtlookup6(struct in_conninfo *);
|
||||
|
||||
extern struct pr_usrreqs tcp6_usrreqs;
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET_TCP6_VAR_HH_ */
|
1112
freebsd/netinet6/udp6_usrreq.c
Normal file
1112
freebsd/netinet6/udp6_usrreq.c
Normal file
File diff suppressed because it is too large
Load Diff
75
freebsd/netinet6/udp6_var.h
Normal file
75
freebsd/netinet6/udp6_var.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)udp_var.h 8.1 (Berkeley) 6/10/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_UDP6_VAR_HH_
|
||||
#define _NETINET6_UDP6_VAR_HH_
|
||||
|
||||
#ifdef _KERNEL
|
||||
SYSCTL_DECL(_net_inet6_udp6);
|
||||
|
||||
extern struct pr_usrreqs udp6_usrreqs;
|
||||
|
||||
void udp6_ctlinput(int, struct sockaddr *, void *);
|
||||
int udp6_input(struct mbuf **, int *, int);
|
||||
#endif
|
||||
|
||||
#endif /*_NETINET6_UDP6_VAR_HH_*/
|
Reference in New Issue
Block a user