IPv6: ifconfig and route tools support ipv6. netstat TBC.

dev
fengbojiang(姜凤波) 2019-07-12 20:57:33 +08:00
parent d7140ab746
commit 143d7be716
11 changed files with 1441 additions and 13 deletions

View File

@ -8,6 +8,11 @@ TARGET=libffcompat.a
#DEBUG=-O0 -gdwarf-2 -g3
include ${TOPDIR}/tools/opts.mk
ifneq (${MK_INET6_SUPPORT},"no")
CFLAGS+= -DINET6
endif
DPDK_CFLAGS= -g -Wall -Werror -include ${FF_DPDK}/include/rte_config.h
DPDK_CFLAGS+= -march=native -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
DPDK_CFLAGS+= -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2

View File

@ -81,6 +81,14 @@
#define ishexnumber(x) isxdigit(x)
#endif
#define CLOCK_REALTIME_FAST 10 /* FreeBSD-specific. */
#ifdef INET6
#define CLOCK_MONOTONIC_FAST 12 /* FreeBSD-specific. */
#define AF_INET6_LINUX 10
#define PF_INET6_LINUX AF_INET6
#endif
void *reallocf(void *ptr, size_t size);
int feature_present(const char *feature);

View File

@ -0,0 +1,831 @@
/*-
* 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_H_
#define _NETINET6_IN6_VAR_H_
#include <sys/tree.h>
#include <sys/counter.h>
#ifdef _KERNEL
#include <sys/fnv_hash.h>
#include <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_ifsoftc;
struct in6_ifextra {
counter_u64_t *in6_ifstat;
counter_u64_t *icmp6_ifstat;
struct nd_ifinfo *nd_ifinfo;
struct scope6_id *scope6_id;
struct lltable *lltable;
struct mld_ifsoftc *mld_ifinfo;
};
#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
#ifdef _KERNEL
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;
/* entry in bucket of inet6 addresses */
LIST_ENTRY(in6_ifaddr) ia6_hash;
};
/* List of in6_ifaddr's. */
TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr);
LIST_HEAD(in6_ifaddrlisthead, in6_ifaddr);
#endif /* _KERNEL */
/* 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 {
uint64_t ifs6_in_receive; /* # of total input datagram */
uint64_t ifs6_in_hdrerr; /* # of datagrams with invalid hdr */
uint64_t ifs6_in_toobig; /* # of datagrams exceeded MTU */
uint64_t ifs6_in_noroute; /* # of datagrams with no route */
uint64_t ifs6_in_addrerr; /* # of datagrams with invalid dst */
uint64_t ifs6_in_protounknown; /* # of datagrams with unknown proto */
/* NOTE: increment on final dst if */
uint64_t ifs6_in_truncated; /* # of truncated datagrams */
uint64_t ifs6_in_discard; /* # of discarded datagrams */
/* NOTE: fragment timeout is not here */
uint64_t ifs6_in_deliver; /* # of datagrams delivered to ULP */
/* NOTE: increment on final dst if */
uint64_t ifs6_out_forward; /* # of datagrams forwarded */
/* NOTE: increment on outgoing if */
uint64_t ifs6_out_request; /* # of outgoing datagrams from ULP */
/* NOTE: does not include forwrads */
uint64_t ifs6_out_discard; /* # of discarded datagrams */
uint64_t ifs6_out_fragok; /* # of datagrams fragmented */
uint64_t ifs6_out_fragfail; /* # of datagrams failed on fragment */
uint64_t ifs6_out_fragcreat; /* # of fragment datagrams */
/* NOTE: this is # after fragment */
uint64_t ifs6_reass_reqd; /* # of incoming fragmented packets */
/* NOTE: increment on final dst if */
uint64_t ifs6_reass_ok; /* # of reassembled packets */
/* NOTE: this is # after reass */
/* NOTE: increment on final dst if */
uint64_t ifs6_reass_fail; /* # of reass failures */
/* NOTE: may not be packet count */
/* NOTE: increment on final dst if */
uint64_t ifs6_in_mcast; /* # of inbound multicast datagrams */
uint64_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 */
uint64_t ifs6_in_msg;
/* ipv6IfIcmpInErrors, # of input error messages */
uint64_t ifs6_in_error;
/* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */
uint64_t ifs6_in_dstunreach;
/* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */
uint64_t ifs6_in_adminprohib;
/* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */
uint64_t ifs6_in_timeexceed;
/* ipv6IfIcmpInParmProblems, # of input parameter problem errors */
uint64_t ifs6_in_paramprob;
/* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */
uint64_t ifs6_in_pkttoobig;
/* ipv6IfIcmpInEchos, # of input echo requests */
uint64_t ifs6_in_echo;
/* ipv6IfIcmpInEchoReplies, # of input echo replies */
uint64_t ifs6_in_echoreply;
/* ipv6IfIcmpInRouterSolicits, # of input router solicitations */
uint64_t ifs6_in_routersolicit;
/* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */
uint64_t ifs6_in_routeradvert;
/* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */
uint64_t ifs6_in_neighborsolicit;
/* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */
uint64_t ifs6_in_neighboradvert;
/* ipv6IfIcmpInRedirects, # of input redirects */
uint64_t ifs6_in_redirect;
/* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */
uint64_t ifs6_in_mldquery;
/* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */
uint64_t ifs6_in_mldreport;
/* ipv6IfIcmpInGroupMembReductions, # of input MLD done */
uint64_t ifs6_in_mlddone;
/*
* Output statistics. We should solve unresolved routing problem...
*/
/* ipv6IfIcmpOutMsgs, total # of output messages */
uint64_t ifs6_out_msg;
/* ipv6IfIcmpOutErrors, # of output error messages */
uint64_t ifs6_out_error;
/* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */
uint64_t ifs6_out_dstunreach;
/* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */
uint64_t ifs6_out_adminprohib;
/* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */
uint64_t ifs6_out_timeexceed;
/* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */
uint64_t ifs6_out_paramprob;
/* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */
uint64_t ifs6_out_pkttoobig;
/* ipv6IfIcmpOutEchos, # of output echo requests */
uint64_t ifs6_out_echo;
/* ipv6IfIcmpOutEchoReplies, # of output echo replies */
uint64_t ifs6_out_echoreply;
/* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */
uint64_t ifs6_out_routersolicit;
/* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */
uint64_t ifs6_out_routeradvert;
/* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */
uint64_t ifs6_out_neighborsolicit;
/* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */
uint64_t ifs6_out_neighboradvert;
/* ipv6IfIcmpOutRedirects, # of output redirects */
uint64_t ifs6_out_redirect;
/* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */
uint64_t ifs6_out_mldquery;
/* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */
uint64_t ifs6_out_mldreport;
/* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */
uint64_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;
int ifra_vhid;
};
/* pre-10.x compat */
struct oin6_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 )
#define IN6_MASK_ADDR(a, m) do { \
(a)->s6_addr32[0] &= (m)->s6_addr32[0]; \
(a)->s6_addr32[1] &= (m)->s6_addr32[1]; \
(a)->s6_addr32[2] &= (m)->s6_addr32[2]; \
(a)->s6_addr32[3] &= (m)->s6_addr32[3]; \
} while (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 OSIOCAIFADDR_IN6 _IOW('i', 26, struct oin6_aliasreq)
#define SIOCAIFADDR_IN6 _IOW('i', 27, 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)
#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 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
* (obsolete)
*/
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
#define IN6_IFF_TEMPORARY 0x80 /* temporary (anonymous) address. */
#define IN6_IFF_PREFER_SOURCE 0x0100 /* preferred address for SAS */
/* 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);
VNET_DECLARE(struct in6_ifaddrlisthead *, in6_ifaddrhashtbl);
VNET_DECLARE(u_long, in6_ifaddrhmask);
#define V_in6_ifaddrhead VNET(in6_ifaddrhead)
#define V_in6_ifaddrhashtbl VNET(in6_ifaddrhashtbl)
#define V_in6_ifaddrhmask VNET(in6_ifaddrhmask)
#define IN6ADDR_NHASH_LOG2 8
#define IN6ADDR_NHASH (1 << IN6ADDR_NHASH_LOG2)
#define IN6ADDR_HASHVAL(x) (in6_addrhash(x))
#define IN6ADDR_HASH(x) \
(&V_in6_ifaddrhashtbl[IN6ADDR_HASHVAL(x) & V_in6_ifaddrhmask])
static __inline uint32_t
in6_addrhash(const struct in6_addr *in6)
{
uint32_t x;
x = in6->s6_addr32[0] ^ in6->s6_addr32[1] ^ in6->s6_addr32[2] ^
in6->s6_addr32[3];
return (fnv_32_buf(&x, sizeof(x), FNV1_32_INIT));
}
extern struct rmlock in6_ifaddr_lock;
#define IN6_IFADDR_LOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_LOCKED)
#define IN6_IFADDR_RLOCK(t) rm_rlock(&in6_ifaddr_lock, (t))
#define IN6_IFADDR_RLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_RLOCKED)
#define IN6_IFADDR_RUNLOCK(t) rm_runlock(&in6_ifaddr_lock, (t))
#define IN6_IFADDR_WLOCK() rm_wlock(&in6_ifaddr_lock)
#define IN6_IFADDR_WLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_WLOCKED)
#define IN6_IFADDR_WUNLOCK() rm_wunlock(&in6_ifaddr_lock)
#define in6_ifstat_inc(ifp, tag) \
do { \
if (ifp) \
counter_u64_add(((struct in6_ifextra *) \
((ifp)->if_afdata[AF_INET6]))->in6_ifstat[ \
offsetof(struct in6_ifstat, tag) / sizeof(uint64_t)], 1);\
} while (/*CONSTCOND*/ 0)
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);
/*
* 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_ifsoftc *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 mbufq 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);
}
/*
* 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_RLOCK(ifp);
inm = in6m_lookup_locked(ifp, mcaddr);
IF_ADDR_RUNLOCK(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(struct in6_addr *, u_char *);
int in6_control(struct socket *, u_long, caddr_t, struct ifnet *,
struct thread *);
int in6_update_ifa(struct ifnet *, struct in6_aliasreq *,
struct in6_ifaddr *, int);
void in6_prepare_ifra(struct in6_aliasreq *, const struct in6_addr *,
const struct in6_addr *);
void in6_purgeaddr(struct ifaddr *);
int in6if_do_dad(struct ifnet *);
void in6_savemkludge(struct in6_ifaddr *);
void *in6_domifattach(struct ifnet *);
void in6_domifdetach(struct ifnet *, void *);
int in6_domifmtu(struct ifnet *);
void in6_setmaxmtu(void);
int in6_if2idlen(struct ifnet *);
struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int);
struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, const struct in6_addr *);
struct in6_ifaddr *in6ifa_ifwithaddr(const struct in6_addr *, uint32_t);
struct in6_ifaddr *in6ifa_llaonifp(struct ifnet *);
int in6_addr2zoneid(struct ifnet *, struct in6_addr *, u_int32_t *);
int in6_matchlen(struct in6_addr *, struct in6_addr *);
int in6_are_prefix_equal(struct in6_addr *, struct in6_addr *, int);
void in6_prefixlen2mask(struct in6_addr *, int);
int in6_prefix_ioctl(struct socket *, u_long, caddr_t,
struct ifnet *);
int in6_prefix_add_ifid(int, struct in6_ifaddr *);
void in6_prefix_remove_ifid(int, struct in6_ifaddr *);
void in6_purgeprefix(struct ifnet *);
int in6_is_addr_deprecated(struct sockaddr_in6 *);
int in6_src_ioctl(u_long, caddr_t);
void in6_newaddrmsg(struct in6_ifaddr *, int);
/*
* Extended API for IPv6 FIB support.
*/
void in6_rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *,
int, struct sockaddr *, u_int);
int in6_rtrequest(int, struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct rtentry **, u_int);
void in6_rtalloc(struct route_in6 *, u_int);
void in6_rtalloc_ign(struct route_in6 *, u_long, u_int);
struct rtentry *in6_rtalloc1(struct sockaddr *, int, u_long, u_int);
#endif /* _KERNEL */
#endif /* _NETINET6_IN6_VAR_H_ */

View File

@ -0,0 +1,479 @@
/*-
* 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_H_
#define _NETINET6_ND6_H_
/* see net/route.h, or net/if_inarp.h */
#ifndef RTF_ANNOUNCE
#define RTF_ANNOUNCE RTF_PROTO2
#endif
#include <sys/queue.h>
#include <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 /* Not used in FreeBSD. */
#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_IFF_AUTO_LINKLOCAL 0x20
#define ND6_IFF_NO_RADR 0x40
#define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */
#define ND6_IFF_NO_DAD 0x100
#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 raflags; /* flags on RA message */
u_short rtlifetime;
u_long expire;
struct ifnet *ifp;
int installed; /* is installed into kernel routing table */
u_int refcnt;
};
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_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;
struct nd_defrouter *router;
};
LIST_HEAD(nd_prhead, nd_prefix);
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_IP6NDP);
#endif
/* 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)
/* Lock for the prefix and default router lists. */
VNET_DECLARE(struct rwlock, nd6_lock);
#define V_nd6_lock VNET(nd6_lock)
#define ND6_RLOCK() rw_rlock(&V_nd6_lock)
#define ND6_RUNLOCK() rw_runlock(&V_nd6_lock)
#define ND6_WLOCK() rw_wlock(&V_nd6_lock)
#define ND6_WUNLOCK() rw_wunlock(&V_nd6_lock)
#define ND6_WLOCK_ASSERT() rw_assert(&V_nd6_lock, RA_WLOCKED)
#define ND6_RLOCK_ASSERT() rw_assert(&V_nd6_lock, RA_RLOCKED)
#define ND6_LOCK_ASSERT() rw_assert(&V_nd6_lock, RA_LOCKED)
#define ND6_UNLOCK_ASSERT() rw_assert(&V_nd6_lock, RA_UNLOCKED)
#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0)
/* 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[16]; /* max = ND_OPT_NONCE */
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 *__res6;
struct nd_opt_hdr *__res7;
struct nd_opt_hdr *__res8;
struct nd_opt_hdr *__res9;
struct nd_opt_hdr *__res10;
struct nd_opt_hdr *__res11;
struct nd_opt_hdr *__res12;
struct nd_opt_hdr *__res13;
struct nd_opt_nonce *nonce;
struct nd_opt_hdr *__res15;
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_nonce nd_opt_each.nonce
#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(void);
#ifdef VIMAGE
void nd6_destroy(void);
#endif
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
void nd6_ifdetach(struct ifnet *, struct nd_ifinfo *);
int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
void nd6_option_init(void *, int, union nd_opts *);
struct nd_opt_hdr *nd6_option(union nd_opts *);
int nd6_options(union nd_opts *);
struct llentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *);
struct llentry *nd6_alloc(const struct in6_addr *, int, struct ifnet *);
void nd6_setmtu(struct ifnet *);
void nd6_llinfo_setstate(struct llentry *lle, int newstate);
void nd6_timer(void *);
void nd6_purge(struct ifnet *);
int nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
char *desten, uint32_t *pflags);
int nd6_resolve(struct ifnet *, int, struct mbuf *,
const struct sockaddr *, u_char *, uint32_t *, struct llentry **);
int nd6_ioctl(u_long, caddr_t, struct ifnet *);
void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
char *, int, int, int);
void nd6_grab_holdchain(struct llentry *, struct mbuf **,
struct sockaddr_in6 *);
int nd6_flush_holdchain(struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *);
int nd6_add_ifa_lle(struct in6_ifaddr *);
void nd6_rem_ifa_lle(struct in6_ifaddr *, int);
int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct route *);
/* nd6_nbr.c */
void nd6_na_input(struct mbuf *, int, int);
void nd6_na_output(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, u_long, int, struct sockaddr *);
void nd6_ns_input(struct mbuf *, int, int);
void nd6_ns_output(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, const struct in6_addr *, uint8_t *);
caddr_t nd6_ifptomac(struct ifnet *);
void nd6_dad_init(void);
void nd6_dad_start(struct ifaddr *, int);
void nd6_dad_stop(struct ifaddr *);
/* nd6_rtr.c */
void nd6_rs_input(struct mbuf *, int, int);
void nd6_ra_input(struct mbuf *, int, int);
void defrouter_reset(void);
void defrouter_select(void);
void defrouter_ref(struct nd_defrouter *);
void defrouter_rele(struct nd_defrouter *);
bool defrouter_remove(struct in6_addr *, struct ifnet *);
void defrouter_unlink(struct nd_defrouter *, struct nd_drhead *);
void defrouter_del(struct nd_defrouter *);
void prelist_remove(struct nd_prefix *);
int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *,
struct nd_prefix **);
void pfxlist_onlink_check(void);
struct nd_defrouter *defrouter_lookup(struct in6_addr *, struct ifnet *);
struct nd_defrouter *defrouter_lookup_locked(struct in6_addr *, struct ifnet *);
struct nd_prefix *nd6_prefix_lookup(struct nd_prefixctl *);
void rt6_flush(struct in6_addr *, struct ifnet *);
int nd6_setdefaultiface(int);
int in6_tmpifadd(const struct in6_ifaddr *, int, int);
#endif /* _KERNEL */
#endif /* _NETINET6_ND6_H_ */

View File

@ -53,8 +53,9 @@ ioctl_va(int fd, unsigned long com, void *data, int argc, ...)
unsigned size;
void *cpy_mem;
size_t offset, clen;
int af = 0;
if (argc != 0 && argc != 3) {
if (argc != 0 && argc != 3 && argc != 1) {
errno = EINVAL;
return -1;
}
@ -66,6 +67,11 @@ ioctl_va(int fd, unsigned long com, void *data, int argc, ...)
cpy_mem = va_arg(ap, void *);
clen = va_arg(ap, size_t);
va_end(ap);
} else if (argc == 1) {
va_list ap;
va_start(ap, argc);
af = va_arg(ap, int);
va_end(ap);
}
if (com > 0xffffffff) {
@ -92,7 +98,18 @@ ioctl_va(int fd, unsigned long com, void *data, int argc, ...)
return -1;
}
msg->msg_type = FF_IOCTL;
#ifdef INET6
if (af == AF_INET6) {
msg->msg_type = FF_IOCTL6;
} else
#endif
if (af == AF_INET)
msg->msg_type = FF_IOCTL;
else {
errno = EINVAL;
return -1;
}
msg->ioctl.cmd = com;
msg->ioctl.data = msg->buf_addr;
memcpy(msg->ioctl.data, data, size);

View File

@ -52,6 +52,7 @@ static const char rcsid[] =
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */
#include "ifconfig.h"
@ -175,9 +176,13 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
u_int32_t flags6;
struct in6_addrlifetime lifetime;
struct timespec now;
#ifndef FSTACK
int error, n_flags;
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
#else
clock_gettime(CLOCK_MONOTONIC, &now);
#endif
memset(&null_sin, 0, sizeof(null_sin));
@ -191,15 +196,25 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
return;
}
ifr6.ifr_addr = *sin;
#ifndef FSTACK
if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
#else
if (ioctl_va(s6, SIOCGIFAFLAG_IN6, &ifr6, 1, AF_INET6) == -1) {
#endif
warn("ioctl(SIOCGIFAFLAG_IN6)");
close(s6);
return;
}
flags6 = ifr6.ifr_ifru.ifru_flags6;
memset(&lifetime, 0, sizeof(lifetime));
ifr6.ifr_addr = *sin;
#ifndef FSTACK
if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) {
#else
if (ioctl_va(s6, SIOCGIFALIFETIME_IN6, &ifr6, 1, AF_INET6) == -1) {
#endif
warn("ioctl(SIOCGIFALIFETIME_IN6)");
close(s6);
return;
@ -207,6 +222,7 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
lifetime = ifr6.ifr_ifru.ifru_lifetime;
close(s6);
#ifndef FSTACK
if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
n_flags = 0;
else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
@ -217,7 +233,8 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
addr_buf, sizeof(addr_buf), NULL, 0,
n_flags);
if (error != 0)
inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
#endif
inet_ntop(AF_INET6_LINUX, &sin->sin6_addr, addr_buf,
sizeof(addr_buf));
printf("\tinet6 %s", addr_buf);
@ -230,14 +247,17 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
if (sin != NULL && sin->sin6_family == AF_INET6) {
int error;
#ifndef FSTACK
error = getnameinfo((struct sockaddr *)sin,
sin->sin6_len, addr_buf,
sizeof(addr_buf), NULL, 0,
NI_NUMERICHOST);
if (error != 0)
inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
#else
inet_ntop(AF_INET6_LINUX, &sin->sin6_addr, addr_buf,
sizeof(addr_buf));
printf(" --> %s ", addr_buf);
#endif
}
}
@ -327,8 +347,10 @@ static void
in6_getaddr(const char *s, int which)
{
struct sockaddr_in6 *sin = sin6tab[which];
#ifndef FSTACK
struct addrinfo hints, *res;
int error = -1;
#endif
newaddr &= 1;
@ -345,16 +367,22 @@ in6_getaddr(const char *s, int which)
}
}
#ifdef FSTACK
if (inet_pton(AF_INET6_LINUX, s, &sin->sin6_addr) != 1)
errx(1, "%s: bad value", s);
return;
#else
if (sin->sin6_family == AF_INET6) {
bzero(&hints, sizeof(struct addrinfo));
hints.ai_family = AF_INET6;
error = getaddrinfo(s, NULL, &hints, &res);
}
if (error != 0) {
if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1)
if (inet_pton(AF_INET6_LINUX, s, &sin->sin6_addr) != 1)
errx(1, "%s: bad value", s);
} else
bcopy(res->ai_addr, sin, res->ai_addrlen);
#endif
}
static int
@ -433,26 +461,48 @@ in6_status_tunnel(int s)
char dst[NI_MAXHOST];
struct in6_ifreq in6_ifr;
const struct sockaddr *sa = (const struct sockaddr *) &in6_ifr.ifr_addr;
#ifdef FSTACK
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
#endif
memset(&in6_ifr, 0, sizeof(in6_ifr));
strlcpy(in6_ifr.ifr_name, name, sizeof(in6_ifr.ifr_name));
#ifndef FSTACK
if (ioctl(s, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0)
#else
if (ioctl_va(s, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr, 1, AF_INET6) == -1)
#endif
return;
if (sa->sa_family != AF_INET6)
return;
#ifndef FSTACK
if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0,
NI_NUMERICHOST) != 0)
src[0] = '\0';
#else
if (inet_ntop(AF_INET6_LINUX, &sin6->sin6_addr, src, sizeof(src)) == NULL)
return;
#endif
#ifndef FSTACK
if (ioctl(s, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr) < 0)
#else
if (ioctl_va(s, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr, 1, AF_INET6) == -1)
#endif
return;
if (sa->sa_family != AF_INET6)
return;
#ifndef FSTACK
if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0,
NI_NUMERICHOST) != 0)
dst[0] = '\0';
#else
if (inet_ntop(AF_INET6_LINUX, &sin6->sin6_addr, dst, sizeof(dst)) == NULL)
return;
#endif
printf("\ttunnel inet6 %s --> %s\n", src, dst);
}
@ -467,7 +517,11 @@ in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr,
dstres->ai_addr->sa_len);
if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0)
#ifndef FSTACK
if (ioctl(s, SIOCSIFPHYADDR_IN6, (caddr_t)&in6_addreq) < 0)
#else
if (ioctl_va(s, SIOCSIFPHYADDR_IN6, (caddr_t)&in6_addreq, 1, AF_INET6) == -1)
#endif
warn("SIOCSIFPHYADDR_IN6");
}
@ -534,12 +588,12 @@ static __constructor void
inet6_ctor(void)
{
size_t i;
#ifndef FSTACK
#ifndef RESCUE
if (!feature_present("inet6"))
return;
#endif
#endif
for (i = 0; i < nitems(inet6_cmds); i++)
cmd_register(&inet6_cmds[i]);
af_register(&af_inet6);

View File

@ -50,6 +50,7 @@ static const char rcsid[] =
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
#include "ifconfig.h"

View File

@ -40,6 +40,8 @@
#include <netinet/in_var.h>
#include <netinet/ip_carp.h>
#include <netinet6/in6_var.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

View File

@ -922,7 +922,11 @@ top:
int ret;
strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, name,
sizeof ifr.ifr_name);
#ifndef FSTACK
ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
#else
ret = ioctl_va(s, afp->af_difaddr, afp->af_ridreq, 1, afp->af_af);
#endif
if (ret < 0) {
if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
/* means no previous address for interface */
@ -940,7 +944,11 @@ top:
if (newaddr && (setaddr || setmask)) {
strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name,
sizeof ifr.ifr_name);
#ifndef FSTACK
if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
#else
if (ioctl_va(s, afp->af_aifaddr, afp->af_addreq, 1, afp->af_af) < 0)
#endif
Perror("ioctl (SIOCAIFADDR)");
}

View File

@ -1,5 +1,5 @@
MK_INET_SUPPORT="yes"
MK_INET6_SUPPORT="no"
MK_INET6_SUPPORT="yes"
MK_IFMEDIA_SUPPORT="no"
MK_MAC_SUPPORT="no"
MK_SFP_SUPPORT="no"

View File

@ -84,8 +84,6 @@ __FBSDID("$FreeBSD$");
#define write(a, b, c) rtioctl((b), (c), (0))
#define CLOCK_REALTIME_FAST CLOCK_REALTIME
#endif
struct fibl {
@ -629,9 +627,16 @@ routename(struct sockaddr *sa)
rt_line, sizeof(rt_line), NULL, 0,
(nflag == 0) ? 0 : NI_NUMERICHOST);
#else
const char *dst = NULL;
error = 0;
struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
const char *dst = inet_ntop(AF_INET, &sin->sin_addr, rt_line, sizeof(rt_line));
#ifdef INET6
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
if (sa->sa_family == AF_INET6)
dst = inet_ntop(AF_INET6_LINUX, &sin6->sin6_addr, rt_line, sizeof(rt_line));
else
#endif
dst = inet_ntop(AF_INET, &sin->sin_addr, rt_line, sizeof(rt_line));
if (dst == NULL) {
error = EAI_NONAME;
}
@ -723,6 +728,7 @@ netname(struct sockaddr *sa)
cp = np->n_name;
}
#endif
#define C(x) (unsigned)((x) & 0xff)
if (cp != NULL)
strncpy(net_line, cp, sizeof(net_line));
@ -738,6 +744,7 @@ netname(struct sockaddr *sa)
(void)sprintf(net_line, "%u.%u.%u.%u", C(in.s_addr >> 24),
C(in.s_addr >> 16), C(in.s_addr >> 8),
C(in.s_addr));
#undef C
break;
}
@ -752,10 +759,15 @@ netname(struct sockaddr *sa)
memcpy(&sin6, sa, sa->sa_len);
sin6.sin6_len = sizeof(sin6);
sin6.sin6_family = AF_INET6;
#ifndef FSTACK
if (nflag)
niflags |= NI_NUMERICHOST;
if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
net_line, sizeof(net_line), NULL, 0, niflags) != 0)
#else
if (inet_ntop(AF_INET6_LINUX, &sin6.sin6_addr, net_line, sizeof(net_line)) == NULL)
#endif
strncpy(net_line, "invalid", sizeof(net_line));
return(net_line);
@ -1314,12 +1326,15 @@ getaddr(int idx, char *str, struct hostent **hpp, int nrflags)
#ifdef INET6
case AF_INET6:
{
#ifndef FSTACK
struct addrinfo hints, *res;
int ecode;
#endif
q = NULL;
if (idx == RTAX_DST && (q = strchr(str, '/')) != NULL)
*q = '\0';
#ifndef FSTACK
memset(&hints, 0, sizeof(hints));
hints.ai_family = sa->sa_family;
hints.ai_socktype = SOCK_DGRAM;
@ -1329,6 +1344,10 @@ getaddr(int idx, char *str, struct hostent **hpp, int nrflags)
errx(EX_OSERR, "%s: %s", str, gai_strerror(ecode));
memcpy(sa, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
#else
if (inet_pton(AF_INET6_LINUX, str, &((struct sockaddr_in6 *)sa)->sin6_addr) == -1)
errx(EX_OSERR, "%s: %d, %s", str, errno, strerror(errno));
#endif
if (q != NULL)
*q++ = '/';
if (idx == RTAX_DST)
@ -1961,7 +1980,11 @@ sodump(struct sockaddr *sa, const char *which)
#endif
#ifdef INET6
case AF_INET6:
#ifdef FSTACK
(void)printf("%s: inet6 %s; ", which, inet_ntop(AF_INET6_LINUX,
#else
(void)printf("%s: inet6 %s; ", which, inet_ntop(sa->sa_family,
#endif
&((struct sockaddr_in6 *)(void *)sa)->sin6_addr, nbuf,
sizeof(nbuf)));
break;