udp IPv6 support, IPv6/IPv4 tunneling support in kernel,
packet divert at kernel for IPv6/IPv4 translater daemon This includes queue related patch submitted by jburkhol@home.com. Submitted by: queue related patch from jburkhol@home.com Reviewed by: freebsd-arch, cvs-committers Obtained from: KAME project
This commit is contained in:
parent
07677171f8
commit
cfa1ca9dfa
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=54263
@ -7,6 +7,7 @@ SRCS= ifconfig.c
|
||||
#comment out to exclude SIOC[GS]IFMEDIA support
|
||||
SRCS+= ifmedia.c
|
||||
CFLAGS+=-DUSE_IF_MEDIA
|
||||
#CFLAGS+=-DINET6
|
||||
|
||||
#comment out to exclude SIOC[GS]ETVLAN support
|
||||
SRCS+= ifvlan.c
|
||||
|
@ -109,6 +109,7 @@ with different naming schemes, specifying the address family is recommended.
|
||||
The address or protocol families currently
|
||||
supported are
|
||||
.Dq inet ,
|
||||
.Dq inet6 ,
|
||||
.Dq atalk ,
|
||||
.\" .Dq iso ,
|
||||
and
|
||||
@ -135,6 +136,13 @@ This is sometimes useful when changing network numbers, and
|
||||
one wishes to accept packets addressed to the old interface.
|
||||
If the alias is on the same subnet as the first network adress
|
||||
for this interface, a netmask of 0xffffffff has to be specified.
|
||||
.It Cm anycast
|
||||
(Inet6 only)
|
||||
Specify that the address configured is an anycast address.
|
||||
Based on the current specification,
|
||||
only routers may configure anycast addresses.
|
||||
Anycast address will not be used as source address of any of outgoing
|
||||
IPv6 packets.
|
||||
.It Cm arp
|
||||
Enable the use of the Address Resolution Protocol in mapping
|
||||
between network level addresses and link level addresses (default).
|
||||
@ -279,6 +287,16 @@ and 0's for the host part.
|
||||
The mask should contain at least the standard network portion,
|
||||
and the subnet field should be contiguous with the network
|
||||
portion.
|
||||
.It Cm prefixlen Ar len
|
||||
(Inet6 only)
|
||||
Specify that
|
||||
.Ar len
|
||||
bits are reserved for subdividing networks into sub-networks.
|
||||
The
|
||||
.Ar len
|
||||
must be integer, and for syntactical reason it must be between 0 to 128.
|
||||
It is almost always 64 under the current IPv6 assignment rule.
|
||||
If the parameter is ommitted, 64 is used.
|
||||
.\" see
|
||||
.\" Xr eon 5 .
|
||||
.\" .It Cm nsellength Ar n
|
||||
@ -345,6 +363,11 @@ will report only the details specific to that protocol family.
|
||||
If the driver does supports the media selection system, the supported
|
||||
media list will be included in the output.
|
||||
.Pp
|
||||
If
|
||||
.Fl L
|
||||
flag is supplied, address lifetime is dislayed for IPv6 addresses,
|
||||
as time offset string.
|
||||
.Pp
|
||||
Optionally, the
|
||||
.Fl a
|
||||
flag may be used instead of an interface name. This flag instructs
|
||||
@ -375,6 +398,12 @@ it (or have need for it).
|
||||
Messages indicating the specified interface does not exist, the
|
||||
requested address is unknown, or the user is not privileged and
|
||||
tried to alter an interface's configuration.
|
||||
.Sh BUGS
|
||||
IPv6 link-local addresses are required for several basic communication
|
||||
between IPv6 node. If they are deleted by
|
||||
.Nm ifconfig
|
||||
manually, the kernel might show very strange behavior.
|
||||
So, such manuall deletions are strongly discouraged.
|
||||
.Sh SEE ALSO
|
||||
.Xr netstat 1 ,
|
||||
.Xr netintro 4 ,
|
||||
|
@ -96,6 +96,10 @@ static const char rcsid[] =
|
||||
|
||||
struct ifreq ifr, ridreq;
|
||||
struct ifaliasreq addreq;
|
||||
#ifdef INET6
|
||||
struct in6_ifreq in6_ridreq;
|
||||
struct in6_aliasreq in6_addreq;
|
||||
#endif
|
||||
struct sockaddr_in netmask;
|
||||
struct netrange at_nr; /* AppleTalk net range */
|
||||
|
||||
@ -108,9 +112,16 @@ int setipdst;
|
||||
int doalias;
|
||||
int clearaddr;
|
||||
int newaddr = 1;
|
||||
#ifdef INET6
|
||||
static int ip6lifetime;
|
||||
#endif
|
||||
|
||||
struct afswtch;
|
||||
|
||||
#ifdef INET6
|
||||
char ntop_buf[INET6_ADDRSTRLEN]; /*inet_ntop()*/
|
||||
#endif
|
||||
|
||||
void Perror __P((const char *cmd));
|
||||
void checkatrange __P((struct sockaddr_at *));
|
||||
int ifconfig __P((int argc, char *const *argv, const struct afswtch *afp));
|
||||
@ -123,9 +134,19 @@ void status __P((const struct afswtch *afp, int addrcount,
|
||||
void usage __P((void));
|
||||
void ifmaybeload __P((char *name));
|
||||
|
||||
#ifdef INET6
|
||||
int prefix __P((void *, int));
|
||||
static char *sec2str __P((time_t));
|
||||
int explicit_prefix = 0;
|
||||
#endif
|
||||
|
||||
typedef void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp));
|
||||
c_func setatphase, setatrange;
|
||||
c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask;
|
||||
#ifdef INET6
|
||||
c_func setifprefixlen;
|
||||
c_func setip6flags;
|
||||
#endif
|
||||
c_func setifipdst;
|
||||
c_func setifflags, setifmetric, setifmtu;
|
||||
|
||||
@ -153,6 +174,12 @@ struct cmd {
|
||||
{ "-swabips", -EN_SWABIPS, setifflags },
|
||||
#endif
|
||||
{ "netmask", NEXTARG, setifnetmask },
|
||||
#ifdef INET6
|
||||
{ "prefixlen", NEXTARG, setifprefixlen },
|
||||
{ "anycast", IN6_IFF_ANYCAST, setip6flags },
|
||||
{ "tentative", IN6_IFF_TENTATIVE, setip6flags },
|
||||
{ "-tentative", -IN6_IFF_TENTATIVE, setip6flags },
|
||||
#endif
|
||||
{ "range", NEXTARG, setatrange },
|
||||
{ "phase", NEXTARG, setatphase },
|
||||
{ "metric", NEXTARG, setifmetric },
|
||||
@ -188,10 +215,16 @@ struct cmd {
|
||||
*/
|
||||
typedef void af_status __P((int, struct rt_addrinfo *));
|
||||
typedef void af_getaddr __P((const char *, int));
|
||||
typedef void af_getprefix __P((const char *, int));
|
||||
|
||||
af_status in_status, ipx_status, at_status, ether_status;
|
||||
af_getaddr in_getaddr, ipx_getaddr, at_getaddr;
|
||||
|
||||
#ifdef INET6
|
||||
af_status in6_status;
|
||||
af_getaddr in6_getaddr;
|
||||
af_getprefix in6_getprefix;
|
||||
#endif /*INET6*/
|
||||
#ifdef NS
|
||||
af_status xns_status;
|
||||
af_getaddr xns_getaddr;
|
||||
@ -204,29 +237,35 @@ struct afswtch {
|
||||
short af_af;
|
||||
af_status *af_status;
|
||||
af_getaddr *af_getaddr;
|
||||
af_getprefix *af_getprefix;
|
||||
u_long af_difaddr;
|
||||
u_long af_aifaddr;
|
||||
caddr_t af_ridreq;
|
||||
caddr_t af_addreq;
|
||||
} afs[] = {
|
||||
#define C(x) ((caddr_t) &x)
|
||||
{ "inet", AF_INET, in_status, in_getaddr,
|
||||
{ "inet", AF_INET, in_status, in_getaddr, NULL,
|
||||
SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
|
||||
{ "ipx", AF_IPX, ipx_status, ipx_getaddr,
|
||||
#ifdef INET6
|
||||
{ "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix,
|
||||
SIOCDIFADDR_IN6, SIOCAIFADDR_IN6,
|
||||
C(in6_ridreq), C(in6_addreq) },
|
||||
#endif /*INET6*/
|
||||
{ "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL,
|
||||
SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
|
||||
{ "atalk", AF_APPLETALK, at_status, at_getaddr,
|
||||
{ "atalk", AF_APPLETALK, at_status, at_getaddr, NULL,
|
||||
SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) },
|
||||
#ifdef NS
|
||||
{ "ns", AF_NS, xns_status, xns_getaddr,
|
||||
{ "ns", AF_NS, xns_status, xns_getaddr, NULL,
|
||||
SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
|
||||
#endif
|
||||
{ "ether", AF_INET, ether_status, NULL }, /* XXX not real!! */
|
||||
{ "ether", AF_INET, ether_status, NULL, NULL }, /* XXX not real!! */
|
||||
#if 0 /* XXX conflicts with the media command */
|
||||
#ifdef USE_IF_MEDIA
|
||||
{ "media", AF_INET, media_status, NULL }, /* XXX not real!! */
|
||||
{ "media", AF_INET, media_status, NULL, NULL, }, /* XXX not real!! */
|
||||
#endif
|
||||
#ifdef USE_VLANS
|
||||
{ "vlan", AF_INET, media_status, NULL }, /* XXX not real!! */
|
||||
{ "vlan", AF_INET, media_status, NULL, NULL, }, /* XXX not real!! */
|
||||
#endif
|
||||
#endif
|
||||
{ 0, 0, 0, 0 }
|
||||
@ -262,11 +301,19 @@ rt_xaddrs(cp, cplim, rtinfo)
|
||||
void
|
||||
usage()
|
||||
{
|
||||
#ifndef INET6
|
||||
fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
||||
"usage: ifconfig interface address_family [address [dest_address]]",
|
||||
" [parameters]",
|
||||
" ifconfig -a [-d] [-u] [address_family]",
|
||||
" ifconfig -l [-d] [-u] [address_family]");
|
||||
#else
|
||||
fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
||||
"usage: ifconfig [-L] interface address_family [address [dest_address]]",
|
||||
" [parameters]",
|
||||
" ifconfig -a [-L] [-d] [-u] [address_family]",
|
||||
" ifconfig -l [-d] [-u] [address_family]");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -291,11 +338,20 @@ main(argc, argv)
|
||||
|
||||
/* Parse leading line options */
|
||||
all = downonly = uponly = namesonly = 0;
|
||||
while ((c = getopt(argc, argv, "adlmu")) != -1) {
|
||||
while ((c = getopt(argc, argv, "adlmu"
|
||||
#ifdef INET6
|
||||
"L"
|
||||
#endif
|
||||
)) != -1) {
|
||||
switch (c) {
|
||||
case 'a': /* scan all interfaces */
|
||||
all++;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case 'L':
|
||||
ip6lifetime++; /* print IPv6 adress lifetime */
|
||||
break;
|
||||
#endif
|
||||
case 'l': /* scan interface names only */
|
||||
namesonly++;
|
||||
break;
|
||||
@ -502,6 +558,15 @@ ifconfig(argc, argv, afp)
|
||||
}
|
||||
argc--, argv++;
|
||||
}
|
||||
#ifdef INET6
|
||||
if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) {
|
||||
/* Aggregatable address architecture defines all prefixes
|
||||
are 64. So, it is convenient to set prefixlen to 64 if
|
||||
it is not specified. */
|
||||
setifprefixlen("64", 0, s, afp);
|
||||
/* in6_getprefix("64", MASK) if MASK is available here... */
|
||||
}
|
||||
#endif
|
||||
if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) {
|
||||
struct ipxip_req rq;
|
||||
int size = sizeof(rq);
|
||||
@ -592,6 +657,36 @@ setifnetmask(addr, dummy, s, afp)
|
||||
(*afp->af_getaddr)(addr, MASK);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
void
|
||||
setifprefixlen(addr, dummy, s, afp)
|
||||
const char *addr;
|
||||
int dummy __unused;
|
||||
int s;
|
||||
const struct afswtch *afp;
|
||||
{
|
||||
if (*afp->af_getprefix)
|
||||
(*afp->af_getprefix)(addr, MASK);
|
||||
explicit_prefix = 1;
|
||||
}
|
||||
|
||||
void
|
||||
setip6flags(dummyaddr, flag, dummysoc, afp)
|
||||
const char *dummyaddr __unused;
|
||||
int flag;
|
||||
int dummysoc __unused;
|
||||
const struct afswtch *afp;
|
||||
{
|
||||
if (afp->af_af != AF_INET6)
|
||||
err(1, "address flags can be set only for inet6 addresses");
|
||||
|
||||
if (flag < 0)
|
||||
in6_addreq.ifra_flags &= ~(-flag);
|
||||
else
|
||||
in6_addreq.ifra_flags |= flag;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
setifbroadaddr(addr, dummy, s, afp)
|
||||
const char *addr;
|
||||
@ -854,6 +949,99 @@ in_status(s, info)
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
void
|
||||
in6_status(s, info)
|
||||
int s __unused;
|
||||
struct rt_addrinfo * info;
|
||||
{
|
||||
struct sockaddr_in6 *sin, null_sin;
|
||||
struct in6_ifreq ifr6;
|
||||
int s6;
|
||||
u_int32_t flags6;
|
||||
struct in6_addrlifetime lifetime;
|
||||
time_t t = time(NULL);
|
||||
|
||||
memset(&null_sin, 0, sizeof(null_sin));
|
||||
|
||||
sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA];
|
||||
strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
|
||||
if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
|
||||
perror("ifconfig: socket");
|
||||
return;
|
||||
}
|
||||
ifr6.ifr_addr = *sin;
|
||||
if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
|
||||
perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)");
|
||||
close(s6);
|
||||
return;
|
||||
}
|
||||
flags6 = ifr6.ifr_ifru.ifru_flags6;
|
||||
memset(&lifetime, 0, sizeof(lifetime));
|
||||
ifr6.ifr_addr = *sin;
|
||||
if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) {
|
||||
perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)");
|
||||
close(s6);
|
||||
return;
|
||||
}
|
||||
lifetime = ifr6.ifr_ifru.ifru_lifetime;
|
||||
close(s6);
|
||||
|
||||
printf("\tinet6 %s ", inet_ntop(AF_INET6, &sin->sin6_addr,
|
||||
ntop_buf, sizeof(ntop_buf)));
|
||||
|
||||
|
||||
if (flags & IFF_POINTOPOINT) {
|
||||
/* note RTAX_BRD overlap with IFF_BROADCAST */
|
||||
sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD];
|
||||
/*
|
||||
* some of the interfaces do not have valid destination
|
||||
* address.
|
||||
*/
|
||||
if (sin && sin->sin6_family == AF_INET6) {
|
||||
printf("--> %s ", inet_ntop(AF_INET6, &sin->sin6_addr,
|
||||
ntop_buf, sizeof(ntop_buf)));
|
||||
}
|
||||
}
|
||||
|
||||
sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK];
|
||||
if (!sin)
|
||||
sin = &null_sin;
|
||||
printf("prefixlen %d ", prefix(&sin->sin6_addr,
|
||||
sizeof(struct in6_addr)));
|
||||
|
||||
if (flags6 & IN6_IFF_ANYCAST)
|
||||
printf("anycast ");
|
||||
if (flags6 & IN6_IFF_TENTATIVE)
|
||||
printf("tentative ");
|
||||
if (flags6 & IN6_IFF_DUPLICATED)
|
||||
printf("duplicated ");
|
||||
if (flags6 & IN6_IFF_DETACHED)
|
||||
printf("detached ");
|
||||
if (flags6 & IN6_IFF_DEPRECATED)
|
||||
printf("deprecated ");
|
||||
|
||||
|
||||
if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) {
|
||||
printf("pltime ");
|
||||
if (lifetime.ia6t_preferred) {
|
||||
printf("%s ", lifetime.ia6t_preferred < t
|
||||
? "0" : sec2str(lifetime.ia6t_preferred - t));
|
||||
} else
|
||||
printf("infty ");
|
||||
|
||||
printf("vltime ");
|
||||
if (lifetime.ia6t_expire) {
|
||||
printf("%s ", lifetime.ia6t_expire < t
|
||||
? "0" : sec2str(lifetime.ia6t_expire - t));
|
||||
} else
|
||||
printf("infty ");
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
#endif /*INET6*/
|
||||
|
||||
void
|
||||
ipx_status(s, info)
|
||||
int s __unused;
|
||||
@ -1005,6 +1193,54 @@ in_getaddr(s, which)
|
||||
errx(1, "%s: bad value", s);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
#define SIN6(x) ((struct sockaddr_in6 *) &(x))
|
||||
struct sockaddr_in6 *sin6tab[] = {
|
||||
SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
|
||||
SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)};
|
||||
|
||||
void
|
||||
in6_getaddr(s, which)
|
||||
const char *s;
|
||||
int which;
|
||||
{
|
||||
register struct sockaddr_in6 *sin = sin6tab[which];
|
||||
|
||||
newaddr &= 1;
|
||||
|
||||
sin->sin6_len = sizeof(*sin);
|
||||
if (which != MASK)
|
||||
sin->sin6_family = AF_INET6;
|
||||
|
||||
if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1)
|
||||
errx(1, "%s: bad value", s);
|
||||
}
|
||||
|
||||
void
|
||||
in6_getprefix(plen, which)
|
||||
const char *plen;
|
||||
int which;
|
||||
{
|
||||
register struct sockaddr_in6 *sin = sin6tab[which];
|
||||
register u_char *cp;
|
||||
int len = atoi(plen);
|
||||
|
||||
if ((len < 0) || (len > 128))
|
||||
errx(1, "%s: bad value", plen);
|
||||
sin->sin6_len = sizeof(*sin);
|
||||
if (which != MASK)
|
||||
sin->sin6_family = AF_INET6;
|
||||
if ((len == 0) || (len == 128)) {
|
||||
memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr));
|
||||
return;
|
||||
}
|
||||
memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr));
|
||||
for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8)
|
||||
*cp++ = 0xff;
|
||||
*cp = 0xff << (8 - len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Print a value a la the %b format of the kernel's printf
|
||||
*/
|
||||
@ -1150,6 +1386,68 @@ xns_getaddr(addr, which)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
int
|
||||
prefix(val, size)
|
||||
void *val;
|
||||
int size;
|
||||
{
|
||||
register u_char *name = (u_char *)val;
|
||||
register int byte, bit, plen = 0;
|
||||
|
||||
for (byte = 0; byte < size; byte++, plen += 8)
|
||||
if (name[byte] != 0xff)
|
||||
break;
|
||||
if (byte == size)
|
||||
return (plen);
|
||||
for (bit = 7; bit != 0; bit--, plen++)
|
||||
if (!(name[byte] & (1 << bit)))
|
||||
break;
|
||||
for (; bit != 0; bit--)
|
||||
if (name[byte] & (1 << bit))
|
||||
return(0);
|
||||
byte++;
|
||||
for (; byte < size; byte++)
|
||||
if (name[byte])
|
||||
return(0);
|
||||
return (plen);
|
||||
}
|
||||
|
||||
static char *
|
||||
sec2str(total)
|
||||
time_t total;
|
||||
{
|
||||
static char result[256];
|
||||
int days, hours, mins, secs;
|
||||
int first = 1;
|
||||
char *p = result;
|
||||
|
||||
if (0) {
|
||||
days = total / 3600 / 24;
|
||||
hours = (total / 3600) % 24;
|
||||
mins = (total / 60) % 60;
|
||||
secs = total % 60;
|
||||
|
||||
if (days) {
|
||||
first = 0;
|
||||
p += sprintf(p, "%dd", days);
|
||||
}
|
||||
if (!first || hours) {
|
||||
first = 0;
|
||||
p += sprintf(p, "%dh", hours);
|
||||
}
|
||||
if (!first || mins) {
|
||||
first = 0;
|
||||
p += sprintf(p, "%dm", mins);
|
||||
}
|
||||
sprintf(p, "%ds", secs);
|
||||
} else
|
||||
sprintf(result, "%lu", (unsigned long)total);
|
||||
|
||||
return(result);
|
||||
}
|
||||
#endif /*INET6*/
|
||||
|
||||
void
|
||||
ifmaybeload(name)
|
||||
char *name;
|
||||
|
@ -1,9 +1,11 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/5/93
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= route
|
||||
MAN8= route.8
|
||||
SRCS= route.c keywords.h
|
||||
CFLAGS+=-I. -Wall -DNS
|
||||
#CFLAGS+=-DINET6
|
||||
CLEANFILES+=keywords.h
|
||||
BINMODE=4555
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
# @(#)keywords 8.2 (Berkeley) 3/19/94
|
||||
# $FreeBSD$
|
||||
|
||||
add
|
||||
atalk
|
||||
@ -19,6 +20,7 @@ interface
|
||||
ifa
|
||||
ifp
|
||||
inet
|
||||
inet6
|
||||
iso
|
||||
link
|
||||
llinfo
|
||||
@ -31,6 +33,7 @@ net
|
||||
netmask
|
||||
nostatic
|
||||
osi
|
||||
prefixlen
|
||||
proto1
|
||||
proto2
|
||||
recvpipe
|
||||
|
@ -69,7 +69,7 @@ Bypass attempts to print host and network names symbolically
|
||||
when reporting actions. (The process of translating between symbolic
|
||||
names and numerical equivalents can be quite time consuming, and
|
||||
may require correct operation of the network; thus it may be expedient
|
||||
to forgo this, especially when attempting to repair networking operations).
|
||||
to forgot this, especially when attempting to repair networking operations).
|
||||
.It Fl v
|
||||
(verbose) Print additional details.
|
||||
.It Fl q
|
||||
@ -120,6 +120,7 @@ When the address family may is specified by any of the
|
||||
.Fl osi ,
|
||||
.Fl xns ,
|
||||
.Fl atalk ,
|
||||
.Fl inet6 ,
|
||||
or
|
||||
.Fl inet
|
||||
modifiers, only routes having destinations with addresses in the
|
||||
@ -225,6 +226,28 @@ One specifies an additional ensuing address parameter
|
||||
The implicit network mask generated in the AF_INET case
|
||||
can be overridden by making sure this option follows the destination parameter.
|
||||
.Pp
|
||||
For
|
||||
.Dv AF_INET6 ,
|
||||
the
|
||||
.Fl prefixlen
|
||||
qualifier
|
||||
is available instead of the
|
||||
.Fl mask
|
||||
qualifier because non-continuous masks are not allowed in IPv6.
|
||||
For example,
|
||||
.Fl prefixlen Li 32
|
||||
specifies network mask of
|
||||
.Li ffff:ffff:0000:0000:0000:0000:0000:0000
|
||||
to be used.
|
||||
The default value of prefixlen is 64 to get along with
|
||||
the aggregatable address.
|
||||
But 0 is assumed if
|
||||
.Cm default
|
||||
is specified.
|
||||
Note that the qualifier works only for
|
||||
.Dv AF_INET6
|
||||
address family.
|
||||
.Pp
|
||||
Routes have associated flags which influence operation of the protocols
|
||||
when sending to destinations matched by the routes.
|
||||
These flags may be set (or sometimes cleared)
|
||||
|
@ -84,6 +84,9 @@ struct ortentry route;
|
||||
union sockunion {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
struct sockaddr_at sat;
|
||||
#ifdef NS
|
||||
struct sockaddr_ns sns;
|
||||
@ -105,10 +108,15 @@ char *routename(), *netname();
|
||||
void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
|
||||
void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
|
||||
int getaddr(), rtmsg(), x25_makemask();
|
||||
int prefixlen();
|
||||
extern char *iso_ntoa();
|
||||
|
||||
void usage __P((const char *)) __dead2;
|
||||
|
||||
#ifdef INET6
|
||||
char ntop_buf[INET6_ADDRSTRLEN]; /*for inet_ntop()*/
|
||||
#endif
|
||||
|
||||
void
|
||||
usage(cp)
|
||||
const char *cp;
|
||||
@ -219,6 +227,11 @@ flushroutes(argc, argv)
|
||||
case K_INET:
|
||||
af = AF_INET;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case K_INET6:
|
||||
af = AF_INET6;
|
||||
break;
|
||||
#endif
|
||||
case K_ATALK:
|
||||
af = AF_APPLETALK;
|
||||
break;
|
||||
@ -346,6 +359,21 @@ routename(sa)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{ struct sockaddr_in6 *sin6;
|
||||
int gap;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
gap = sizeof(struct sockaddr_in6) - sin6->sin6_len;
|
||||
if (gap > 0)
|
||||
bzero((char *)(sin6) + sin6->sin6_len, gap);
|
||||
(void) snprintf(line, sizeof(line), "%s",
|
||||
inet_ntop(AF_INET6, &sin6->sin6_addr,
|
||||
ntop_buf, sizeof(ntop_buf)));
|
||||
}
|
||||
#endif
|
||||
|
||||
case AF_APPLETALK:
|
||||
(void) snprintf(line, sizeof(line), "atalk %s",
|
||||
atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
|
||||
@ -443,6 +471,21 @@ netname(sa)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{ struct in6_addr in6;
|
||||
int gap;
|
||||
|
||||
in6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
|
||||
gap = sizeof(struct sockaddr_in6) - sa->sa_len;
|
||||
if (gap > 0)
|
||||
bzero((char *)(&in6 + 1) - gap, gap);
|
||||
(void)snprintf(line, sizeof(line), "%s",
|
||||
inet_ntop(AF_INET6, &in6, ntop_buf,
|
||||
sizeof(ntop_buf)));
|
||||
}
|
||||
#endif
|
||||
|
||||
case AF_APPLETALK:
|
||||
(void) snprintf(line, sizeof(line), "atalk %s",
|
||||
atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
|
||||
@ -526,6 +569,19 @@ newroute(argc, argv)
|
||||
af = AF_INET;
|
||||
aflen = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case K_INET6:
|
||||
af = AF_INET6;
|
||||
aflen = sizeof(struct sockaddr_in6);
|
||||
if (prefixlen("64") != 64) {
|
||||
fprintf(stderr, "internal error: "
|
||||
"setting prefixlen=64\n");
|
||||
exit(1);
|
||||
}
|
||||
forcenet = 0;
|
||||
ishost = 1;
|
||||
break;
|
||||
#endif
|
||||
case K_ATALK:
|
||||
af = AF_APPLETALK;
|
||||
aflen = sizeof(struct sockaddr_at);
|
||||
@ -614,6 +670,17 @@ newroute(argc, argv)
|
||||
case K_NET:
|
||||
forcenet++;
|
||||
break;
|
||||
case K_PREFIXLEN:
|
||||
if (!--argc)
|
||||
usage((char *)NULL);
|
||||
if (prefixlen(*++argv) == -1) {
|
||||
forcenet = 0;
|
||||
ishost = 1;
|
||||
} else {
|
||||
forcenet = 1;
|
||||
ishost = 0;
|
||||
}
|
||||
break;
|
||||
case K_MTU:
|
||||
case K_HOPCOUNT:
|
||||
case K_EXPIRE:
|
||||
@ -641,8 +708,15 @@ newroute(argc, argv)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (forcehost)
|
||||
if (forcehost) {
|
||||
ishost = 1;
|
||||
#ifdef INET6
|
||||
if (af == AF_INET6) {
|
||||
rtm_addrs &= ~RTA_NETMASK;
|
||||
memset((void *)&so_mask, 0, sizeof(so_mask));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (forcenet)
|
||||
ishost = 0;
|
||||
flags |= RTF_UP;
|
||||
@ -754,11 +828,13 @@ getaddr(which, s, hpp)
|
||||
struct netent *np;
|
||||
u_long val;
|
||||
char *q,qs;
|
||||
int afamily; /* local copy of af so we can change it */
|
||||
|
||||
if (af == 0) {
|
||||
af = AF_INET;
|
||||
aflen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
afamily = af;
|
||||
rtm_addrs |= which;
|
||||
switch (which) {
|
||||
case RTA_DST:
|
||||
@ -818,6 +894,7 @@ getaddr(which, s, hpp)
|
||||
break;
|
||||
case RTA_IFP:
|
||||
su = &so_ifp;
|
||||
afamily = AF_LINK;
|
||||
break;
|
||||
case RTA_IFA:
|
||||
su = &so_ifa;
|
||||
@ -827,7 +904,7 @@ getaddr(which, s, hpp)
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
su->sa.sa_len = aflen;
|
||||
su->sa.sa_family = af; /* cases that don't want it have left already */
|
||||
su->sa.sa_family = afamily; /* cases that don't want it have left already */
|
||||
if (strcmp(s, "default") == 0) {
|
||||
/*
|
||||
* Default is net 0.0.0.0/0
|
||||
@ -844,7 +921,16 @@ getaddr(which, s, hpp)
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
switch (af) {
|
||||
switch (afamily) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (inet_pton(AF_INET6, s, (void *)&su->sin6.sin6_addr) == -1) {
|
||||
(void) fprintf(stderr, "%s: bad value\n", s);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef NS
|
||||
case AF_NS:
|
||||
if (which == RTA_DST) {
|
||||
@ -926,6 +1012,51 @@ getaddr(which, s, hpp)
|
||||
errx(EX_NOHOST, "bad address: %s", s);
|
||||
}
|
||||
|
||||
int
|
||||
prefixlen(s)
|
||||
char *s;
|
||||
{
|
||||
int len = atoi(s), q, r;
|
||||
int max;
|
||||
char *p;
|
||||
|
||||
rtm_addrs |= RTA_NETMASK;
|
||||
switch (af) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
max = 128;
|
||||
p = (char *)&so_mask.sin6.sin6_addr;
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
max = 32;
|
||||
p = (char *)&so_mask.sin.sin_addr;
|
||||
break;
|
||||
default:
|
||||
(void) fprintf(stderr, "prefixlen not supported in this af\n");
|
||||
exit(1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if (len < 0 || max < len) {
|
||||
(void) fprintf(stderr, "%s: bad value\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
q = len >> 3;
|
||||
r = len & 7;
|
||||
so_mask.sa.sa_family = af;
|
||||
so_mask.sa.sa_len = aflen;
|
||||
memset((void *)p, 0, max / 8);
|
||||
if (q > 0)
|
||||
memset((void *)p, 0xff, q);
|
||||
if (r > 0)
|
||||
*((u_char *)p + q) = (0xff00 >> r) & 0xff;
|
||||
if (len == max)
|
||||
return -1;
|
||||
else
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef NS
|
||||
short ns_nullh[] = {0,0,0};
|
||||
@ -1017,8 +1148,10 @@ monitor()
|
||||
exit(0);
|
||||
}
|
||||
for(;;) {
|
||||
time_t now;
|
||||
n = read(s, msg, 2048);
|
||||
(void) printf("got message of size %d\n", n);
|
||||
now = time(NULL);
|
||||
(void) printf("got message of size %d on %s", n, ctime(&now));
|
||||
print_rtmsg((struct rt_msghdr *)msg, n);
|
||||
}
|
||||
}
|
||||
@ -1115,6 +1248,9 @@ mask_addr()
|
||||
case AF_NS:
|
||||
#endif
|
||||
case AF_INET:
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
#endif
|
||||
case AF_APPLETALK:
|
||||
case 0:
|
||||
return;
|
||||
|
@ -437,6 +437,11 @@ device mn0 # Munich32x/Falc54 Nx64kbit/sec cards.
|
||||
# included for testing purposes.
|
||||
# The `tun' pseudo-device implements (user-)ppp and nos-tun
|
||||
# The `streams' pseudo-device implements SysVR4 STREAMS emulation.
|
||||
# The `gif' pseudo-device implements IPv6 over IP4 tunneling,
|
||||
# IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and
|
||||
# IPv6 over IPv6 tunneling.
|
||||
# The `faith' pseudo-device captures packets sent to it and diverts them
|
||||
# to the IPv4/IPv6 translation daemon.
|
||||
#
|
||||
# The PPP_BSDCOMP option enables support for compress(1) style entire
|
||||
# packet compression, the PPP_DEFLATE is for zlib/gzip style compression.
|
||||
@ -459,6 +464,10 @@ options PPP_BSDCOMP #PPP BSD-compress support
|
||||
options PPP_DEFLATE #PPP zlib/deflate/gzip support
|
||||
options PPP_FILTER #enable bpf filtering (needs bpf)
|
||||
|
||||
# for IPv6
|
||||
pseudo-device gif 4 #IPv6 and IPv4 tunneling
|
||||
pseudo-device faith 1 #for IPv6 and IPv4 translation
|
||||
|
||||
#
|
||||
# Internet family options:
|
||||
#
|
||||
|
@ -465,7 +465,9 @@ net/if_atmsubr.c optional atm
|
||||
net/if_disc.c optional disc
|
||||
net/if_ethersubr.c optional ether
|
||||
net/if_iso88025subr.c optional token
|
||||
net/if_faith.c optional faith
|
||||
net/if_fddisubr.c optional fddi
|
||||
net/if_gif.c optional gif
|
||||
net/if_loop.c optional loop
|
||||
net/if_media.c standard
|
||||
net/if_mib.c standard
|
||||
@ -474,6 +476,7 @@ net/if_sl.c optional sl
|
||||
net/if_spppsubr.c optional sppp
|
||||
net/if_tun.c optional tun
|
||||
net/if_vlan.c optional vlan
|
||||
net/net_osdep.c standard
|
||||
net/ppp_deflate.c optional ppp_deflate
|
||||
net/ppp_tty.c optional ppp
|
||||
net/radix.c standard
|
||||
@ -484,7 +487,6 @@ net/rtsock.c standard
|
||||
net/slcompress.c optional ppp
|
||||
net/slcompress.c optional sl
|
||||
net/zlib.c optional ppp_deflate
|
||||
net/net_osdep.c standard
|
||||
netatalk/aarp.c optional netatalk
|
||||
netatalk/at_control.c optional netatalk
|
||||
netatalk/at_proto.c optional netatalk
|
||||
@ -595,6 +597,7 @@ netgraph/ng_vjc.c optional netgraph_vjc
|
||||
net/slcompress.c optional netgraph_vjc
|
||||
netinet/if_atm.c optional atm
|
||||
netinet/if_ether.c optional ether
|
||||
netinet/in_gif.c optional gif inet
|
||||
netinet/igmp.c optional inet
|
||||
netinet/in.c optional inet
|
||||
#netinet/in_hostcache.c optional inet
|
||||
@ -617,25 +620,6 @@ netinet/tcp_subr.c optional inet
|
||||
netinet/tcp_timer.c optional inet
|
||||
netinet/tcp_usrreq.c optional inet
|
||||
netinet/udp_usrreq.c optional inet
|
||||
netinet6/in6.c optional inet6
|
||||
netinet6/in6_ifattach.c optional inet6
|
||||
netinet6/in6_cksum.c optional inet6
|
||||
netinet6/in6_pcb.c optional inet6
|
||||
netinet6/in6_proto.c optional inet6
|
||||
netinet6/in6_rmx.c optional inet6
|
||||
netinet6/in6_prefix.c optional inet6
|
||||
netinet6/dest6.c optional inet6
|
||||
netinet6/frag6.c optional inet6
|
||||
netinet6/icmp6.c optional inet6
|
||||
netinet6/ip6_input.c optional inet6
|
||||
netinet6/ip6_forward.c optional inet6
|
||||
netinet6/ip6_output.c optional inet6
|
||||
netinet6/route6.c optional inet6
|
||||
netinet6/mld6.c optional inet6
|
||||
netinet6/nd6.c optional inet6
|
||||
netinet6/nd6_nbr.c optional inet6
|
||||
netinet6/nd6_rtr.c optional inet6
|
||||
netinet6/raw_ip6.c optional inet6
|
||||
netinet/ip_fil.c optional ipfilter inet
|
||||
netinet/fil.c optional ipfilter inet
|
||||
netinet/ip_nat.c optional ipfilter inet
|
||||
@ -645,6 +629,27 @@ netinet/ip_auth.c optional ipfilter inet
|
||||
netinet/ip_proxy.c optional ipfilter inet
|
||||
netinet/ip_log.c optional ipfilter inet
|
||||
netinet/mlfk_ipl.c optional ipfilter inet
|
||||
netinet6/dest6.c optional inet6
|
||||
netinet6/frag6.c optional inet6
|
||||
netinet6/icmp6.c optional inet6
|
||||
netinet6/in6.c optional inet6
|
||||
netinet6/in6_cksum.c optional inet6
|
||||
netinet6/in6_gif.c optional gif inet6
|
||||
netinet6/ip6_forward.c optional inet6
|
||||
netinet6/in6_ifattach.c optional inet6
|
||||
netinet6/ip6_input.c optional inet6
|
||||
netinet6/ip6_output.c optional inet6
|
||||
netinet6/in6_pcb.c optional inet6
|
||||
netinet6/in6_prefix.c optional inet6
|
||||
netinet6/in6_proto.c optional inet6
|
||||
netinet6/in6_rmx.c optional inet6
|
||||
netinet6/mld6.c optional inet6
|
||||
netinet6/nd6.c optional inet6
|
||||
netinet6/nd6_nbr.c optional inet6
|
||||
netinet6/nd6_rtr.c optional inet6
|
||||
netinet6/raw_ip6.c optional inet6
|
||||
netinet6/route6.c optional inet6
|
||||
netinet6/udp6_usrreq.c optional inet6
|
||||
netipx/ipx.c optional ipx
|
||||
netipx/ipx_cksum.c optional ipx
|
||||
netipx/ipx_input.c optional ipx
|
||||
|
@ -217,7 +217,7 @@ BOOTP_WIRED_TO opt_bootp.h
|
||||
BRIDGE opt_bdg.h
|
||||
MROUTING opt_mrouting.h
|
||||
INET opt_inet.h
|
||||
INET6 opt_inet.h
|
||||
INET6 opt_inet6.h
|
||||
IPDIVERT
|
||||
DUMMYNET opt_ipdn.h
|
||||
IPFILTER opt_ipfilter.h
|
||||
|
@ -437,6 +437,11 @@ device mn0 # Munich32x/Falc54 Nx64kbit/sec cards.
|
||||
# included for testing purposes.
|
||||
# The `tun' pseudo-device implements (user-)ppp and nos-tun
|
||||
# The `streams' pseudo-device implements SysVR4 STREAMS emulation.
|
||||
# The `gif' pseudo-device implements IPv6 over IP4 tunneling,
|
||||
# IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and
|
||||
# IPv6 over IPv6 tunneling.
|
||||
# The `faith' pseudo-device captures packets sent to it and diverts them
|
||||
# to the IPv4/IPv6 translation daemon.
|
||||
#
|
||||
# The PPP_BSDCOMP option enables support for compress(1) style entire
|
||||
# packet compression, the PPP_DEFLATE is for zlib/gzip style compression.
|
||||
@ -459,6 +464,10 @@ options PPP_BSDCOMP #PPP BSD-compress support
|
||||
options PPP_DEFLATE #PPP zlib/deflate/gzip support
|
||||
options PPP_FILTER #enable bpf filtering (needs bpf)
|
||||
|
||||
# for IPv6
|
||||
pseudo-device gif 4 #IPv6 and IPv4 tunneling
|
||||
pseudo-device faith 1 #for IPv6 and IPv4 translation
|
||||
|
||||
#
|
||||
# Internet family options:
|
||||
#
|
||||
|
@ -437,6 +437,11 @@ device mn0 # Munich32x/Falc54 Nx64kbit/sec cards.
|
||||
# included for testing purposes.
|
||||
# The `tun' pseudo-device implements (user-)ppp and nos-tun
|
||||
# The `streams' pseudo-device implements SysVR4 STREAMS emulation.
|
||||
# The `gif' pseudo-device implements IPv6 over IP4 tunneling,
|
||||
# IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and
|
||||
# IPv6 over IPv6 tunneling.
|
||||
# The `faith' pseudo-device captures packets sent to it and diverts them
|
||||
# to the IPv4/IPv6 translation daemon.
|
||||
#
|
||||
# The PPP_BSDCOMP option enables support for compress(1) style entire
|
||||
# packet compression, the PPP_DEFLATE is for zlib/gzip style compression.
|
||||
@ -459,6 +464,10 @@ options PPP_BSDCOMP #PPP BSD-compress support
|
||||
options PPP_DEFLATE #PPP zlib/deflate/gzip support
|
||||
options PPP_FILTER #enable bpf filtering (needs bpf)
|
||||
|
||||
# for IPv6
|
||||
pseudo-device gif 4 #IPv6 and IPv4 tunneling
|
||||
pseudo-device faith 1 #for IPv6 and IPv4 translation
|
||||
|
||||
#
|
||||
# Internet family options:
|
||||
#
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
.PATH: ${.CURDIR}/../../net
|
||||
KMOD= if_disc
|
||||
SRCS= if_disc.c opt_inet.h
|
||||
SRCS= if_disc.c opt_inet.h opt_inet6.h
|
||||
NOMAN=
|
||||
|
||||
NBPF?= 1
|
||||
@ -12,4 +12,7 @@ CFLAGS+= ${PROTOS}
|
||||
opt_inet.h:
|
||||
echo "#define INET 1" > opt_inet.h
|
||||
|
||||
#opt_inet6.h:
|
||||
# echo "#define INET6 1" > opt_inet6.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
|
@ -30,6 +30,8 @@
|
||||
* 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$
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -37,6 +39,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_natm.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include <net/bpf.h>
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#ifdef TINY_DSMTU
|
||||
#define DSMTU (1024+512)
|
||||
@ -180,6 +181,10 @@ discioctl(ifp, cmd, data)
|
||||
case AF_INET:
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
error = EAFNOSUPPORT;
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
#include "opt_atalk.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_ipx.h"
|
||||
#include "opt_bdg.h"
|
||||
#include "opt_netgraph.h"
|
||||
|
97
sys/net/if_faith.c
Normal file
97
sys/net/if_faith.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 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$
|
||||
*/
|
||||
/*
|
||||
* derived from
|
||||
* @(#)if_loop.c 8.1 (Berkeley) 6/10/93
|
||||
* Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
|
||||
*/
|
||||
|
||||
/*
|
||||
* Loopback interface driver for protocol testing and timing.
|
||||
*/
|
||||
|
||||
#include "faith.h"
|
||||
#if NFAITH > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/route.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
extern int loioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
extern int looutput __P((struct ifnet *ifp,
|
||||
struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
|
||||
|
||||
void faithattach __P((void *));
|
||||
PSEUDO_SET(faithattach, if_faith);
|
||||
static struct ifnet faithif[NFAITH];
|
||||
|
||||
#define FAITHMTU 1500
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
faithattach(faith)
|
||||
void *faith;
|
||||
{
|
||||
register struct ifnet *ifp;
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < NFAITH; i++) {
|
||||
ifp = &faithif[i];
|
||||
bzero(ifp, sizeof(faithif[i]));
|
||||
ifp->if_name = "faith";
|
||||
ifp->if_unit = i;
|
||||
ifp->if_mtu = FAITHMTU;
|
||||
/* Change to BROADCAST experimentaly to announce its prefix. */
|
||||
ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
|
||||
ifp->if_ioctl = loioctl;
|
||||
ifp->if_output = looutput;
|
||||
ifp->if_type = IFT_FAITH;
|
||||
ifp->if_snd.ifq_maxlen = ifqmaxlen;
|
||||
ifp->if_hdrlen = 0;
|
||||
ifp->if_addrlen = 0;
|
||||
if_attach(ifp);
|
||||
bpfattach(ifp, DLT_NULL, sizeof(u_int));
|
||||
}
|
||||
}
|
||||
#endif /* NFAITH > 0 */
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "opt_atalk.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_ipx.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -52,11 +53,14 @@
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#ifdef INET
|
||||
#if defined(INET) || defined(INET6)
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#endif
|
||||
#ifdef INET6
|
||||
#include <netinet6/nd6.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
#include <netinet/if_fddi.h>
|
||||
#else
|
||||
@ -186,6 +190,16 @@ fddi_output(ifp, m0, dst, rt0)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
|
||||
/* this must be impossible, so we bark */
|
||||
printf("nd6_storelladdr failed\n");
|
||||
return(0);
|
||||
}
|
||||
type = htons(ETHERTYPE_IPV6);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IPX
|
||||
case AF_IPX:
|
||||
type = htons(ETHERTYPE_IPX);
|
||||
@ -481,7 +495,7 @@ fddi_input(ifp, fh, m)
|
||||
|
||||
l = mtod(m, struct llc *);
|
||||
switch (l->llc_dsap) {
|
||||
#if defined(INET) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
|
||||
#if defined(INET) || defined(INET6) || defined(NS) || defined(DECNET) || defined(IPX) || defined(NETATALK)
|
||||
case LLC_SNAP_LSAP:
|
||||
{
|
||||
u_int16_t type;
|
||||
@ -528,6 +542,12 @@ fddi_input(ifp, fh, m)
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case ETHERTYPE_IPV6:
|
||||
schednetisr(NETISR_IPV6);
|
||||
inq = &ip6intrq;
|
||||
break;
|
||||
#endif
|
||||
#ifdef IPX
|
||||
case ETHERTYPE_IPX:
|
||||
schednetisr(NETISR_IPX);
|
||||
|
468
sys/net/if_gif.c
Normal file
468
sys/net/if_gif.c
Normal file
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* gif.c
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/route.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in_gif.h>
|
||||
#endif /* INET */
|
||||
|
||||
#ifdef INET6
|
||||
#ifndef INET
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/in6_gif.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
#include <net/if_gif.h>
|
||||
|
||||
#include "gif.h"
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
#if NGIF > 0
|
||||
|
||||
void gifattach __P((void *));
|
||||
|
||||
/*
|
||||
* gif global variable definitions
|
||||
*/
|
||||
int ngif = NGIF; /* number of interfaces */
|
||||
struct gif_softc *gif = 0;
|
||||
|
||||
void
|
||||
gifattach(dummy)
|
||||
void *dummy;
|
||||
{
|
||||
register struct gif_softc *sc;
|
||||
register int i;
|
||||
|
||||
gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT);
|
||||
bzero(sc, ngif * sizeof(struct gif_softc));
|
||||
for (i = 0; i < ngif; sc++, i++) {
|
||||
sc->gif_if.if_name = "gif";
|
||||
sc->gif_if.if_unit = i;
|
||||
sc->gif_if.if_mtu = GIF_MTU;
|
||||
sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
|
||||
sc->gif_if.if_ioctl = gif_ioctl;
|
||||
sc->gif_if.if_output = gif_output;
|
||||
sc->gif_if.if_type = IFT_GIF;
|
||||
sc->gif_if.if_snd.ifq_maxlen = ifqmaxlen;
|
||||
if_attach(&sc->gif_if);
|
||||
bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
|
||||
}
|
||||
}
|
||||
|
||||
PSEUDO_SET(gifattach, if_gif);
|
||||
|
||||
int
|
||||
gif_output(ifp, m, dst, rt)
|
||||
struct ifnet *ifp;
|
||||
struct mbuf *m;
|
||||
struct sockaddr *dst;
|
||||
struct rtentry *rt; /* added in net2 */
|
||||
{
|
||||
register struct gif_softc *sc = (struct gif_softc*)ifp;
|
||||
int error = 0;
|
||||
static int called = 0; /* XXX: MUTEX */
|
||||
int calllimit = 10; /* XXX: adhoc */
|
||||
|
||||
/*
|
||||
* gif may cause infinite recursion calls when misconfigured.
|
||||
* We'll prevent this by introducing upper limit.
|
||||
* XXX: this mechanism may introduce another problem about
|
||||
* mutual exclusion of the variable CALLED, especially if we
|
||||
* use kernel thread.
|
||||
*/
|
||||
if (++called >= calllimit) {
|
||||
log(LOG_NOTICE,
|
||||
"gif_output: recursively called too many times(%d)\n",
|
||||
called);
|
||||
m_freem(m);
|
||||
error = EIO; /* is there better errno? */
|
||||
goto end;
|
||||
}
|
||||
getmicrotime(&ifp->if_lastchange);
|
||||
m->m_flags &= ~(M_BCAST|M_MCAST);
|
||||
if (!(ifp->if_flags & IFF_UP) ||
|
||||
sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
|
||||
m_freem(m);
|
||||
error = ENETDOWN;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ifp->if_bpf) {
|
||||
/*
|
||||
* We need to prepend the address family as
|
||||
* a four byte field. Cons up a dummy header
|
||||
* to pacify bpf. This is safe because bpf
|
||||
* will only read from the mbuf (i.e., it won't
|
||||
* try to free it or keep a pointer a to it).
|
||||
*/
|
||||
struct mbuf m0;
|
||||
u_int af = dst->sa_family;
|
||||
|
||||
m0.m_next = m;
|
||||
m0.m_len = 4;
|
||||
m0.m_data = (char *)⁡
|
||||
|
||||
bpf_mtap(ifp, &m0);
|
||||
}
|
||||
ifp->if_opackets++;
|
||||
ifp->if_obytes += m->m_pkthdr.len;
|
||||
|
||||
switch (sc->gif_psrc->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
error = in_gif_output(ifp, dst->sa_family, m, rt);
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
error = in6_gif_output(ifp, dst->sa_family, m, rt);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
m_freem(m);
|
||||
error = ENETDOWN;
|
||||
}
|
||||
|
||||
end:
|
||||
called = 0; /* reset recursion counter */
|
||||
if (error) ifp->if_oerrors++;
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
gif_input(m, af, gifp)
|
||||
struct mbuf *m;
|
||||
int af;
|
||||
struct ifnet *gifp;
|
||||
{
|
||||
int s, isr;
|
||||
register struct ifqueue *ifq = 0;
|
||||
|
||||
if (gifp == NULL) {
|
||||
/* just in case */
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m->m_pkthdr.rcvif)
|
||||
m->m_pkthdr.rcvif = gifp;
|
||||
|
||||
if (gifp->if_bpf) {
|
||||
/*
|
||||
* We need to prepend the address family as
|
||||
* a four byte field. Cons up a dummy header
|
||||
* to pacify bpf. This is safe because bpf
|
||||
* will only read from the mbuf (i.e., it won't
|
||||
* try to free it or keep a pointer a to it).
|
||||
*/
|
||||
struct mbuf m0;
|
||||
u_int af = AF_INET6;
|
||||
|
||||
m0.m_next = m;
|
||||
m0.m_len = 4;
|
||||
m0.m_data = (char *)⁡
|
||||
|
||||
bpf_mtap(gifp, &m0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the packet to the network layer input queue according to the
|
||||
* specified address family.
|
||||
* Note: older versions of gif_input directly called network layer
|
||||
* input functions, e.g. ip6_input, here. We changed the policy to
|
||||
* prevent too many recursive calls of such input functions, which
|
||||
* might cause kernel panic. But the change may introduce another
|
||||
* problem; if the input queue is full, packets are discarded.
|
||||
* We believed it rarely occurs and changed the policy. If we find
|
||||
* it occurs more times than we thought, we may change the policy
|
||||
* again.
|
||||
*/
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
ifq = &ipintrq;
|
||||
isr = NETISR_IP;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
ifq = &ip6intrq;
|
||||
isr = NETISR_IPV6;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
s = splimp();
|
||||
if (IF_QFULL(ifq)) {
|
||||
IF_DROP(ifq); /* update statistics */
|
||||
m_freem(m);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
IF_ENQUEUE(ifq, m);
|
||||
/* we need schednetisr since the address family may change */
|
||||
schednetisr(isr);
|
||||
gifp->if_ipackets++;
|
||||
gifp->if_ibytes += m->m_pkthdr.len;
|
||||
splx(s);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
gif_ioctl(ifp, cmd, data)
|
||||
struct ifnet *ifp;
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
{
|
||||
struct gif_softc *sc = (struct gif_softc*)ifp;
|
||||
struct ifreq *ifr = (struct ifreq*)data;
|
||||
int error = 0, size;
|
||||
struct sockaddr *sa, *dst, *src;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDR:
|
||||
break;
|
||||
|
||||
case SIOCSIFDSTADDR:
|
||||
break;
|
||||
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
break;
|
||||
|
||||
case SIOCGIFMTU:
|
||||
break;
|
||||
case SIOCSIFMTU:
|
||||
{
|
||||
u_long mtu;
|
||||
mtu = ifr->ifr_mtu;
|
||||
if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
|
||||
return (EINVAL);
|
||||
}
|
||||
ifp->if_mtu = mtu;
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIFPHYADDR:
|
||||
#ifdef INET6
|
||||
case SIOCSIFPHYADDR_IN6:
|
||||
#endif /* INET6 */
|
||||
switch (ifr->ifr_addr.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
src = (struct sockaddr *)
|
||||
&(((struct in_aliasreq *)data)->ifra_addr);
|
||||
dst = (struct sockaddr *)
|
||||
&(((struct in_aliasreq *)data)->ifra_dstaddr);
|
||||
|
||||
/* only one gif can have dst = INADDR_ANY */
|
||||
#define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr)
|
||||
|
||||
if (satosaddr(dst) == INADDR_ANY) {
|
||||
int i;
|
||||
struct gif_softc *sc2;
|
||||
|
||||
for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
|
||||
if (sc2 == sc) continue;
|
||||
if (sc2->gif_pdst &&
|
||||
satosaddr(sc2->gif_pdst)
|
||||
== INADDR_ANY) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
size = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
src = (struct sockaddr *)
|
||||
&(((struct in6_aliasreq *)data)->ifra_addr);
|
||||
dst = (struct sockaddr *)
|
||||
&(((struct in6_aliasreq *)data)->ifra_dstaddr);
|
||||
|
||||
/* only one gif can have dst = in6addr_any */
|
||||
#define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr)
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(satoin6(dst))) {
|
||||
int i;
|
||||
struct gif_softc *sc2;
|
||||
|
||||
for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
|
||||
if (sc2 == sc) continue;
|
||||
if (sc2->gif_pdst &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(
|
||||
satoin6(sc2->gif_pdst)
|
||||
)) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
size = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
error = EPROTOTYPE;
|
||||
goto bad;
|
||||
break;
|
||||
}
|
||||
if (sc->gif_psrc != NULL)
|
||||
free((caddr_t)sc->gif_psrc, M_IFADDR);
|
||||
if (sc->gif_pdst != NULL)
|
||||
free((caddr_t)sc->gif_pdst, M_IFADDR);
|
||||
|
||||
sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
|
||||
bzero((caddr_t)sa, size);
|
||||
bcopy((caddr_t)src, (caddr_t)sa, size);
|
||||
sc->gif_psrc = sa;
|
||||
|
||||
sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
|
||||
bzero((caddr_t)sa, size);
|
||||
bcopy((caddr_t)dst, (caddr_t)sa, size);
|
||||
sc->gif_pdst = sa;
|
||||
|
||||
ifp->if_flags |= (IFF_UP|IFF_RUNNING);
|
||||
if_up(ifp); /* send up RTM_IFINFO */
|
||||
|
||||
break;
|
||||
|
||||
case SIOCGIFPSRCADDR:
|
||||
#ifdef INET6
|
||||
case SIOCGIFPSRCADDR_IN6:
|
||||
#endif /* INET6 */
|
||||
if (sc->gif_psrc == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
src = sc->gif_psrc;
|
||||
switch (sc->gif_psrc->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
dst = &ifr->ifr_addr;
|
||||
size = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
dst = (struct sockaddr *)
|
||||
&(((struct in6_ifreq *)data)->ifr_addr);
|
||||
size = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
bcopy((caddr_t)src, (caddr_t)dst, size);
|
||||
break;
|
||||
|
||||
case SIOCGIFPDSTADDR:
|
||||
#ifdef INET6
|
||||
case SIOCGIFPDSTADDR_IN6:
|
||||
#endif /* INET6 */
|
||||
if (sc->gif_pdst == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
src = sc->gif_pdst;
|
||||
switch (sc->gif_pdst->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
dst = &ifr->ifr_addr;
|
||||
size = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
dst = (struct sockaddr *)
|
||||
&(((struct in6_ifreq *)data)->ifr_addr);
|
||||
size = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
bcopy((caddr_t)src, (caddr_t)dst, size);
|
||||
break;
|
||||
|
||||
case SIOCSIFFLAGS:
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
bad:
|
||||
return error;
|
||||
}
|
||||
#endif /*NGIF > 0*/
|
@ -36,9 +36,6 @@
|
||||
#ifndef _NET_IF_GIF_H_
|
||||
#define _NET_IF_GIF_H_
|
||||
|
||||
#include <netinet/in.h>
|
||||
/* xxx sigh, why route have struct route instead of pointer? */
|
||||
|
||||
struct gif_softc {
|
||||
struct ifnet gif_if; /* common area */
|
||||
struct sockaddr *gif_psrc; /* Physical src addr */
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include "opt_atalk.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_ipx.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -90,13 +91,13 @@
|
||||
#include <netatalk/at_var.h>
|
||||
#endif NETATALK
|
||||
|
||||
static int loioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
int loioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
|
||||
|
||||
static void loopattach __P((void *));
|
||||
PSEUDO_SET(loopattach, if_loop);
|
||||
|
||||
static int looutput __P((struct ifnet *ifp,
|
||||
int looutput __P((struct ifnet *ifp,
|
||||
struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
|
||||
|
||||
#ifdef TINY_LOMTU
|
||||
@ -131,7 +132,7 @@ loopattach(dummy)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
looutput(ifp, m, dst, rt)
|
||||
struct ifnet *ifp;
|
||||
register struct mbuf *m;
|
||||
@ -341,7 +342,7 @@ lortrequest(cmd, rt, sa)
|
||||
* Process an ioctl request.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
int
|
||||
loioctl(ifp, cmd, data)
|
||||
register struct ifnet *ifp;
|
||||
u_long cmd;
|
||||
|
@ -24,12 +24,14 @@
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_ipx.h"
|
||||
#endif
|
||||
|
||||
#ifdef NetBSD1_3
|
||||
# if NetBSD1_3 > 6
|
||||
# include "opt_inet.h"
|
||||
# include "opt_inet6.h"
|
||||
# include "opt_iso.h"
|
||||
# endif
|
||||
#endif
|
||||
@ -572,6 +574,12 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
|
||||
inq = &ipintrq;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case ETHERTYPE_IPV6:
|
||||
schednetisr (NETISR_IPV6);
|
||||
inq = &ip6intrq;
|
||||
break;
|
||||
#endif
|
||||
#ifdef IPX
|
||||
case ETHERTYPE_IPX:
|
||||
schednetisr (NETISR_IPX);
|
||||
@ -741,6 +749,15 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6: /* Internet Protocol */
|
||||
if (sp->pp_mode == IFF_CISCO)
|
||||
h->protocol = htons (ETHERTYPE_IPV6);
|
||||
else {
|
||||
goto nosupport;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef NS
|
||||
case AF_NS: /* Xerox NS Protocol */
|
||||
h->protocol = htons (sp->pp_mode == IFF_CISCO ?
|
||||
@ -759,8 +776,8 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
|
||||
goto nosupport;
|
||||
h->protocol = htons (PPP_ISO);
|
||||
break;
|
||||
nosupport:
|
||||
#endif
|
||||
nosupport:
|
||||
default:
|
||||
m_freem (m);
|
||||
++ifp->if_oerrors;
|
||||
|
@ -30,6 +30,8 @@
|
||||
* 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$
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -37,6 +39,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_natm.h"
|
||||
|
||||
#if defined(INET) || defined(INET6)
|
||||
|
311
sys/netinet/in_gif.c
Normal file
311
sys/netinet/in_gif.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* in_gif.c
|
||||
*/
|
||||
|
||||
#include "opt_mrouting.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/protosw.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/in_gif.h>
|
||||
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#endif
|
||||
|
||||
#ifdef MROUTING
|
||||
#include <netinet/ip_mroute.h>
|
||||
#endif /* MROUTING */
|
||||
|
||||
#include <net/if_gif.h>
|
||||
|
||||
#include "gif.h"
|
||||
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
#if NGIF > 0
|
||||
int ip_gif_ttl = GIF_TTL;
|
||||
#else
|
||||
int ip_gif_ttl = 0;
|
||||
#endif
|
||||
|
||||
SYSCTL_DECL(_net_inet_ip);
|
||||
SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
|
||||
&ip_gif_ttl, 0, "");
|
||||
|
||||
int
|
||||
in_gif_output(ifp, family, m, rt)
|
||||
struct ifnet *ifp;
|
||||
int family;
|
||||
struct mbuf *m;
|
||||
struct rtentry *rt;
|
||||
{
|
||||
register struct gif_softc *sc = (struct gif_softc*)ifp;
|
||||
struct sockaddr_in *dst = (struct sockaddr_in *)&sc->gif_ro.ro_dst;
|
||||
struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc;
|
||||
struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst;
|
||||
struct ip iphdr; /* capsule IP header, host byte ordered */
|
||||
int proto, error;
|
||||
u_int8_t tos;
|
||||
|
||||
if (sin_src == NULL || sin_dst == NULL ||
|
||||
sin_src->sin_family != AF_INET ||
|
||||
sin_dst->sin_family != AF_INET) {
|
||||
m_freem(m);
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
switch (family) {
|
||||
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 *);
|
||||
tos = ip->ip_tos;
|
||||
break;
|
||||
}
|
||||
#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 *);
|
||||
tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
|
||||
break;
|
||||
}
|
||||
#endif /*INET6*/
|
||||
default:
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("in_gif_output: warning: unknown family %d passed\n",
|
||||
family);
|
||||
#endif
|
||||
m_freem(m);
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
bzero(&iphdr, sizeof(iphdr));
|
||||
iphdr.ip_src = sin_src->sin_addr;
|
||||
if (ifp->if_flags & IFF_LINK0) {
|
||||
/* multi-destination mode */
|
||||
if (sin_dst->sin_addr.s_addr != INADDR_ANY)
|
||||
iphdr.ip_dst = sin_dst->sin_addr;
|
||||
else if (rt) {
|
||||
iphdr.ip_dst = ((struct sockaddr_in *)
|
||||
(rt->rt_gateway))->sin_addr;
|
||||
} else {
|
||||
m_freem(m);
|
||||
return ENETUNREACH;
|
||||
}
|
||||
} else {
|
||||
/* bidirectional configured tunnel mode */
|
||||
if (sin_dst->sin_addr.s_addr != INADDR_ANY)
|
||||
iphdr.ip_dst = sin_dst->sin_addr;
|
||||
else {
|
||||
m_freem(m);
|
||||
return ENETUNREACH;
|
||||
}
|
||||
}
|
||||
iphdr.ip_p = proto;
|
||||
/* version will be set in ip_output() */
|
||||
iphdr.ip_ttl = ip_gif_ttl;
|
||||
iphdr.ip_len = m->m_pkthdr.len + sizeof(struct ip);
|
||||
|
||||
/* prepend new IP header */
|
||||
M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
|
||||
if (m && m->m_len < sizeof(struct ip))
|
||||
m = m_pullup(m, sizeof(struct ip));
|
||||
if (m == NULL) {
|
||||
printf("ENOBUFS in in_gif_output %d\n", __LINE__);
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
*(mtod(m, struct ip *)) = iphdr;
|
||||
|
||||
if (dst->sin_family != sin_dst->sin_family ||
|
||||
dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) {
|
||||
/* cache route doesn't match */
|
||||
dst->sin_family = sin_dst->sin_family;
|
||||
dst->sin_len = sizeof(struct sockaddr_in);
|
||||
dst->sin_addr = sin_dst->sin_addr;
|
||||
if (sc->gif_ro.ro_rt) {
|
||||
RTFREE(sc->gif_ro.ro_rt);
|
||||
sc->gif_ro.ro_rt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->gif_ro.ro_rt == NULL) {
|
||||
rtalloc(&sc->gif_ro);
|
||||
if (sc->gif_ro.ro_rt == NULL) {
|
||||
m_freem(m);
|
||||
return ENETUNREACH;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IPSEC
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
#endif /*IPSEC*/
|
||||
error = ip_output(m, 0, &sc->gif_ro, 0, 0);
|
||||
return(error);
|
||||
}
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
in_gif_input(struct mbuf *m, ...)
|
||||
#else
|
||||
in_gif_input(m, va_alist)
|
||||
struct mbuf *m;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
int off, proto;
|
||||
struct gif_softc *sc;
|
||||
struct ifnet *gifp = NULL;
|
||||
struct ip *ip;
|
||||
int i, af;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, m);
|
||||
off = va_arg(ap, int);
|
||||
proto = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
|
||||
/* this code will be soon improved. */
|
||||
#define satosin(sa) ((struct sockaddr_in *)(sa))
|
||||
for (i = 0, sc = gif; i < ngif; i++, sc++) {
|
||||
if (sc->gif_psrc == NULL
|
||||
|| sc->gif_pdst == NULL
|
||||
|| sc->gif_psrc->sa_family != AF_INET
|
||||
|| sc->gif_pdst->sa_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((sc->gif_if.if_flags & IFF_UP) == 0)
|
||||
continue;
|
||||
|
||||
if ((sc->gif_if.if_flags & IFF_LINK0)
|
||||
&& satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
|
||||
&& satosin(sc->gif_pdst)->sin_addr.s_addr == INADDR_ANY) {
|
||||
gifp = &sc->gif_if;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
|
||||
&& satosin(sc->gif_pdst)->sin_addr.s_addr == ip->ip_src.s_addr)
|
||||
{
|
||||
gifp = &sc->gif_if;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gifp == NULL) {
|
||||
#ifdef MROUTING
|
||||
/* for backward compatibility */
|
||||
if (proto == IPPROTO_IPV4) {
|
||||
ipip_input(m, off, proto);
|
||||
return;
|
||||
}
|
||||
#endif /*MROUTING*/
|
||||
m_freem(m);
|
||||
ipstat.ips_nogif++;
|
||||
return;
|
||||
}
|
||||
|
||||
m_adj(m, off);
|
||||
|
||||
switch (proto) {
|
||||
case IPPROTO_IPV4:
|
||||
{
|
||||
struct ip *ip;
|
||||
af = AF_INET;
|
||||
if (m->m_len < sizeof(*ip)) {
|
||||
m = m_pullup(m, sizeof(*ip));
|
||||
if (!m)
|
||||
return;
|
||||
}
|
||||
ip = mtod(m, struct ip *);
|
||||
break;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ip6->ip6_flow &= ~htonl(0xff << 20);
|
||||
break;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
ipstat.ips_nogif++;
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
gif_input(m, af, gifp);
|
||||
return;
|
||||
}
|
42
sys/netinet/in_gif.h
Normal file
42
sys/netinet/in_gif.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET_IN_GIF_H_
|
||||
#define _NETINET_IN_GIF_H_
|
||||
|
||||
#define GIF_TTL 30
|
||||
|
||||
extern int ip_gif_ttl;
|
||||
|
||||
void in_gif_input __P((struct mbuf *, ...));
|
||||
int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *));
|
||||
|
||||
#endif /*_NETINET_IN_GIF_H_*/
|
@ -34,10 +34,13 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
@ -51,12 +54,25 @@
|
||||
#include <vm/vm_zone.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
#include "faith.h"
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#include <netkey/key.h>
|
||||
#include <netkey/key_debug.h>
|
||||
#endif /* IPSEC */
|
||||
|
||||
struct in_addr zeroin_addr;
|
||||
|
||||
@ -212,14 +228,35 @@ in_pcbbind(inp, nam, p)
|
||||
(t->inp_socket->so_options &
|
||||
SO_REUSEPORT) == 0) &&
|
||||
(so->so_cred->cr_uid !=
|
||||
t->inp_socket->so_cred->cr_uid))
|
||||
t->inp_socket->so_cred->cr_uid)) {
|
||||
#if defined(INET6)
|
||||
if (ip6_mapped_addr_on == 0 ||
|
||||
ntohl(sin->sin_addr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
ntohl(t->inp_laddr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
INP_SOCKAF(so) ==
|
||||
INP_SOCKAF(t->inp_socket))
|
||||
#endif /* defined(INET6) */
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
}
|
||||
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
|
||||
lport, prison ? 0 : wild);
|
||||
if (t && (reuseport & t->inp_socket->so_options) == 0)
|
||||
if (t &&
|
||||
(reuseport & t->inp_socket->so_options) == 0) {
|
||||
#if defined(INET6)
|
||||
if (ip6_mapped_addr_on == 0 ||
|
||||
ntohl(sin->sin_addr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
ntohl(t->inp_laddr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
INP_SOCKAF(so) ==
|
||||
INP_SOCKAF(t->inp_socket))
|
||||
#endif /* defined(INET6) */
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
}
|
||||
inp->inp_laddr = sin->sin_addr;
|
||||
}
|
||||
if (lport == 0) {
|
||||
@ -452,7 +489,7 @@ in_pcbconnect(inp, nam, p)
|
||||
|
||||
if (in_pcblookup_hash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port,
|
||||
inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
|
||||
inp->inp_lport, 0) != NULL) {
|
||||
inp->inp_lport, 0, NULL) != NULL) {
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
if (inp->inp_laddr.s_addr == INADDR_ANY) {
|
||||
@ -488,6 +525,9 @@ in_pcbdetach(inp)
|
||||
struct socket *so = inp->inp_socket;
|
||||
struct inpcbinfo *ipi = inp->inp_pcbinfo;
|
||||
|
||||
#ifdef IPSEC
|
||||
ipsec4_delete_pcbpolicy(inp);
|
||||
#endif /*IPSEC*/
|
||||
inp->inp_gencnt = ++ipi->ipi_gencnt;
|
||||
in_pcbremlists(inp);
|
||||
so->so_pcb = 0;
|
||||
@ -497,6 +537,7 @@ in_pcbdetach(inp)
|
||||
if (inp->inp_route.ro_rt)
|
||||
rtfree(inp->inp_route.ro_rt);
|
||||
ip_freemoptions(inp->inp_moptions);
|
||||
inp->inp_vflag = 0;
|
||||
zfreei(ipi->ipi_zone, inp);
|
||||
}
|
||||
|
||||
@ -620,6 +661,12 @@ in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
|
||||
errno = inetctlerrmap[cmd];
|
||||
s = splnet();
|
||||
for (inp = head->lh_first; inp != NULL;) {
|
||||
#ifdef INET6
|
||||
if ((inp->inp_vflag & INP_IPV4) == NULL) {
|
||||
inp = LIST_NEXT(inp, inp_list);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (inp->inp_faddr.s_addr != faddr.s_addr ||
|
||||
inp->inp_socket == 0 ||
|
||||
(lport && inp->inp_lport != lport) ||
|
||||
@ -711,6 +758,10 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
|
||||
*/
|
||||
head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
|
||||
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
|
||||
#ifdef INET6
|
||||
if ((inp->inp_vflag & INP_IPV4) == NULL)
|
||||
continue;
|
||||
#endif
|
||||
if (inp->inp_faddr.s_addr == INADDR_ANY &&
|
||||
inp->inp_laddr.s_addr == laddr.s_addr &&
|
||||
inp->inp_lport == lport) {
|
||||
@ -748,6 +799,10 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
|
||||
for (inp = phd->phd_pcblist.lh_first; inp != NULL;
|
||||
inp = inp->inp_portlist.le_next) {
|
||||
wildcard = 0;
|
||||
#ifdef INET6
|
||||
if ((inp->inp_vflag & INP_IPV4) == NULL)
|
||||
continue;
|
||||
#endif
|
||||
if (inp->inp_faddr.s_addr != INADDR_ANY)
|
||||
wildcard++;
|
||||
if (inp->inp_laddr.s_addr != INADDR_ANY) {
|
||||
@ -776,11 +831,13 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
|
||||
* Lookup PCB in hash list.
|
||||
*/
|
||||
struct inpcb *
|
||||
in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
|
||||
in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard,
|
||||
ifp)
|
||||
struct inpcbinfo *pcbinfo;
|
||||
struct in_addr faddr, laddr;
|
||||
u_int fport_arg, lport_arg;
|
||||
int wildcard;
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct inpcbhead *head;
|
||||
register struct inpcb *inp;
|
||||
@ -791,6 +848,10 @@ in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
|
||||
*/
|
||||
head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)];
|
||||
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
|
||||
#ifdef INET6
|
||||
if ((inp->inp_vflag & INP_IPV4) == NULL)
|
||||
continue;
|
||||
#endif
|
||||
if (inp->inp_faddr.s_addr == faddr.s_addr &&
|
||||
inp->inp_laddr.s_addr == laddr.s_addr &&
|
||||
inp->inp_fport == fport &&
|
||||
@ -803,17 +864,40 @@ in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
|
||||
}
|
||||
if (wildcard) {
|
||||
struct inpcb *local_wild = NULL;
|
||||
#if defined(INET6)
|
||||
struct inpcb *local_wild_mapped = NULL;
|
||||
#endif /* defined(INET6) */
|
||||
|
||||
head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
|
||||
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
|
||||
#ifdef INET6
|
||||
if ((inp->inp_vflag & INP_IPV4) == NULL)
|
||||
continue;
|
||||
#endif
|
||||
if (inp->inp_faddr.s_addr == INADDR_ANY &&
|
||||
inp->inp_lport == lport) {
|
||||
#if defined(NFAITH) && NFAITH > 0
|
||||
if (ifp && ifp->if_type == IFT_FAITH &&
|
||||
(inp->inp_flags & INP_FAITH) == 0)
|
||||
continue;
|
||||
#endif
|
||||
if (inp->inp_laddr.s_addr == laddr.s_addr)
|
||||
return (inp);
|
||||
else if (inp->inp_laddr.s_addr == INADDR_ANY)
|
||||
else if (inp->inp_laddr.s_addr == INADDR_ANY) {
|
||||
#if defined(INET6)
|
||||
if (INP_CHECK_SOCKAF(inp->inp_socket,
|
||||
AF_INET6))
|
||||
local_wild_mapped = inp;
|
||||
else
|
||||
#endif /* defined(INET6) */
|
||||
local_wild = inp;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(INET6)
|
||||
if (local_wild == NULL)
|
||||
return (local_wild_mapped);
|
||||
#endif /* defined(INET6) */
|
||||
return (local_wild);
|
||||
}
|
||||
|
||||
@ -834,8 +918,16 @@ in_pcbinshash(inp)
|
||||
struct inpcbporthead *pcbporthash;
|
||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
|
||||
struct inpcbport *phd;
|
||||
u_int32_t hashkey_faddr;
|
||||
|
||||
pcbhash = &pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,
|
||||
#ifdef INET6
|
||||
if (inp->inp_vflag & INP_IPV6)
|
||||
hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
|
||||
else
|
||||
#endif /* INET6 */
|
||||
hashkey_faddr = inp->inp_faddr.s_addr;
|
||||
|
||||
pcbhash = &pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
|
||||
inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)];
|
||||
|
||||
pcbporthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(inp->inp_lport,
|
||||
@ -877,8 +969,16 @@ in_pcbrehash(inp)
|
||||
struct inpcb *inp;
|
||||
{
|
||||
struct inpcbhead *head;
|
||||
u_int32_t hashkey_faddr;
|
||||
|
||||
head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,
|
||||
#ifdef INET6
|
||||
if (inp->inp_vflag & INP_IPV6)
|
||||
hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
|
||||
else
|
||||
#endif /* INET6 */
|
||||
hashkey_faddr = inp->inp_faddr.s_addr;
|
||||
|
||||
head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
|
||||
inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)];
|
||||
|
||||
LIST_REMOVE(inp, inp_hash);
|
||||
|
@ -287,7 +287,8 @@ struct inpcb *
|
||||
struct in_addr, u_int, int));
|
||||
struct inpcb *
|
||||
in_pcblookup_hash __P((struct inpcbinfo *,
|
||||
struct in_addr, u_int, struct in_addr, u_int, int));
|
||||
struct in_addr, u_int, struct in_addr, u_int,
|
||||
int, struct ifnet *));
|
||||
void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
|
||||
u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
|
||||
void in_pcbrehash __P((struct inpcb *));
|
||||
|
@ -63,6 +63,11 @@
|
||||
* TCP/IP protocol family: IP, ICMP, UDP, TCP.
|
||||
*/
|
||||
|
||||
#include "gif.h"
|
||||
#if NGIF > 0
|
||||
#include <netinet/in_gif.h>
|
||||
#endif
|
||||
|
||||
#ifdef IPXIP
|
||||
#include <netipx/ipx_ip.h>
|
||||
#endif
|
||||
@ -119,12 +124,29 @@ struct protosw inetsw[] = {
|
||||
0, 0, 0, 0,
|
||||
&rip_usrreqs
|
||||
},
|
||||
#if NGIF > 0
|
||||
{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
|
||||
in_gif_input, 0, 0, 0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&nousrreqs
|
||||
},
|
||||
# ifdef INET6
|
||||
{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
|
||||
in_gif_input, 0, 0, 0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&nousrreqs
|
||||
},
|
||||
#endif
|
||||
#else /*NGIF*/
|
||||
{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR,
|
||||
ipip_input, 0, 0, rip_ctloutput,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&rip_usrreqs
|
||||
},
|
||||
#endif /*NGIF*/
|
||||
#ifdef IPDIVERT
|
||||
{ SOCK_RAW, &inetdomain, IPPROTO_DIVERT, PR_ATOMIC|PR_ADDR,
|
||||
div_input, 0, 0, ip_ctloutput,
|
||||
|
@ -707,10 +707,12 @@ non_ip: ip = NULL ;
|
||||
|
||||
if (oif)
|
||||
P = in_pcblookup_hash(&tcbinfo, ip->ip_dst,
|
||||
tcp->th_dport, ip->ip_src, tcp->th_sport, 0);
|
||||
tcp->th_dport, ip->ip_src, tcp->th_sport, 0,
|
||||
oif);
|
||||
else
|
||||
P = in_pcblookup_hash(&tcbinfo, ip->ip_src,
|
||||
tcp->th_sport, ip->ip_dst, tcp->th_dport, 0);
|
||||
tcp->th_sport, ip->ip_dst, tcp->th_dport, 0,
|
||||
NULL);
|
||||
|
||||
if (P && P->inp_socket) {
|
||||
if (f->fw_flg & IP_FW_F_UID) {
|
||||
@ -738,10 +740,12 @@ non_ip: ip = NULL ;
|
||||
|
||||
if (oif)
|
||||
P = in_pcblookup_hash(&udbinfo, ip->ip_dst,
|
||||
udp->uh_dport, ip->ip_src, udp->uh_sport, 1);
|
||||
udp->uh_dport, ip->ip_src, udp->uh_sport, 1,
|
||||
oif);
|
||||
else
|
||||
P = in_pcblookup_hash(&udbinfo, ip->ip_src,
|
||||
udp->uh_sport, ip->ip_dst, udp->uh_dport, 1);
|
||||
udp->uh_sport, ip->ip_dst, udp->uh_dport, 1,
|
||||
NULL);
|
||||
|
||||
if (P && P->inp_socket) {
|
||||
if (f->fw_flg & IP_FW_F_UID) {
|
||||
|
@ -390,7 +390,7 @@ tcp_input(m, iphlen)
|
||||
* already got one like this?
|
||||
*/
|
||||
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
|
||||
ti->ti_dst, ti->ti_dport, 0);
|
||||
ti->ti_dst, ti->ti_dport, 0, m->m_pkthdr.rcvif);
|
||||
if (!inp) {
|
||||
/*
|
||||
* No, then it's new. Try find the ambushing socket
|
||||
@ -398,12 +398,13 @@ tcp_input(m, iphlen)
|
||||
if (!ip_fw_fwd_addr->sin_port) {
|
||||
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src,
|
||||
ti->ti_sport, ip_fw_fwd_addr->sin_addr,
|
||||
ti->ti_dport, 1);
|
||||
ti->ti_dport, 1, m->m_pkthdr.rcvif);
|
||||
} else {
|
||||
inp = in_pcblookup_hash(&tcbinfo,
|
||||
ti->ti_src, ti->ti_sport,
|
||||
ip_fw_fwd_addr->sin_addr,
|
||||
ntohs(ip_fw_fwd_addr->sin_port), 1);
|
||||
ntohs(ip_fw_fwd_addr->sin_port), 1,
|
||||
m->m_pkthdr.rcvif);
|
||||
}
|
||||
}
|
||||
ip_fw_fwd_addr = NULL;
|
||||
@ -411,7 +412,7 @@ tcp_input(m, iphlen)
|
||||
#endif /* IPFIREWALL_FORWARD */
|
||||
|
||||
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
|
||||
ti->ti_dst, ti->ti_dport, 1);
|
||||
ti->ti_dst, ti->ti_dport, 1, m->m_pkthdr.rcvif);
|
||||
|
||||
/*
|
||||
* If the state is CLOSED (i.e., TCB does not exist) then
|
||||
|
@ -390,7 +390,7 @@ tcp_input(m, iphlen)
|
||||
* already got one like this?
|
||||
*/
|
||||
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
|
||||
ti->ti_dst, ti->ti_dport, 0);
|
||||
ti->ti_dst, ti->ti_dport, 0, m->m_pkthdr.rcvif);
|
||||
if (!inp) {
|
||||
/*
|
||||
* No, then it's new. Try find the ambushing socket
|
||||
@ -398,12 +398,13 @@ tcp_input(m, iphlen)
|
||||
if (!ip_fw_fwd_addr->sin_port) {
|
||||
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src,
|
||||
ti->ti_sport, ip_fw_fwd_addr->sin_addr,
|
||||
ti->ti_dport, 1);
|
||||
ti->ti_dport, 1, m->m_pkthdr.rcvif);
|
||||
} else {
|
||||
inp = in_pcblookup_hash(&tcbinfo,
|
||||
ti->ti_src, ti->ti_sport,
|
||||
ip_fw_fwd_addr->sin_addr,
|
||||
ntohs(ip_fw_fwd_addr->sin_port), 1);
|
||||
ntohs(ip_fw_fwd_addr->sin_port), 1,
|
||||
m->m_pkthdr.rcvif);
|
||||
}
|
||||
}
|
||||
ip_fw_fwd_addr = NULL;
|
||||
@ -411,7 +412,7 @@ tcp_input(m, iphlen)
|
||||
#endif /* IPFIREWALL_FORWARD */
|
||||
|
||||
inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
|
||||
ti->ti_dst, ti->ti_dport, 1);
|
||||
ti->ti_dst, ti->ti_dport, 1, m->m_pkthdr.rcvif);
|
||||
|
||||
/*
|
||||
* If the state is CLOSED (i.e., TCB does not exist) then
|
||||
|
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_tcpdebug.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -647,7 +647,7 @@ tcp_getcred SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
s = splnet();
|
||||
inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
|
||||
addrs[0].sin_addr, addrs[0].sin_port, 0);
|
||||
addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
|
||||
if (inp == NULL || inp->inp_socket == NULL) {
|
||||
error = ENOENT;
|
||||
goto out;
|
||||
|
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_tcpdebug.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -647,7 +647,7 @@ tcp_getcred SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
s = splnet();
|
||||
inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
|
||||
addrs[0].sin_addr, addrs[0].sin_port, 0);
|
||||
addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
|
||||
if (inp == NULL || inp->inp_socket == NULL) {
|
||||
error = ENOENT;
|
||||
goto out;
|
||||
|
@ -34,6 +34,7 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_tcpdebug.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -535,7 +536,7 @@ tcp_connect(tp, nam, p)
|
||||
sin->sin_addr, sin->sin_port,
|
||||
inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
|
||||
: ifaddr->sin_addr,
|
||||
inp->inp_lport, 0);
|
||||
inp->inp_lport, 0, NULL);
|
||||
if (oinp) {
|
||||
if (oinp != inp && (otp = intotcpcb(oinp)) != NULL &&
|
||||
otp->t_state == TCPS_TIME_WAIT &&
|
||||
@ -731,6 +732,9 @@ tcp_attach(so, p)
|
||||
if (error)
|
||||
return (error);
|
||||
inp = sotoinpcb(so);
|
||||
#ifdef INET6
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
#endif
|
||||
tp = tcp_newtcpcb(inp);
|
||||
if (tp == 0) {
|
||||
int nofd = so->so_state & SS_NOFDREF; /* XXX */
|
||||
|
@ -34,11 +34,14 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
@ -54,14 +57,24 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#endif
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ip6_var.h>
|
||||
#endif
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#endif /*IPSEC*/
|
||||
|
||||
/*
|
||||
* UDP protocol implementation.
|
||||
* Per RFC 768, August, 1980.
|
||||
@ -83,6 +96,7 @@ SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
|
||||
&blackhole, 0, "Do not send port unreachables for refused connects");
|
||||
|
||||
struct inpcbhead udb; /* from udp_var.h */
|
||||
#define udb6 udb /* for KAME src sync over BSD*'s */
|
||||
struct inpcbinfo udbinfo;
|
||||
|
||||
#ifndef UDBHASHSIZE
|
||||
@ -94,7 +108,27 @@ SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
|
||||
&udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
|
||||
|
||||
static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
|
||||
#ifdef INET6
|
||||
struct udp_in6 {
|
||||
struct sockaddr_in6 uin6_sin;
|
||||
u_char uin6_init_done : 1;
|
||||
} udp_in6 = {
|
||||
{ sizeof(udp_in6.uin6_sin), AF_INET6 },
|
||||
0
|
||||
};
|
||||
struct udp_ip6 {
|
||||
struct ip6_hdr uip6_ip6;
|
||||
u_char uip6_init_done : 1;
|
||||
} udp_ip6;
|
||||
#endif /* INET6 */
|
||||
|
||||
static void udp_append __P((struct inpcb *last, struct ip *ip,
|
||||
struct mbuf *n, int off));
|
||||
#ifdef INET6
|
||||
static void ip_2_ip6_hdr __P((struct ip6_hdr *ip6, struct ip *ip));
|
||||
#endif
|
||||
|
||||
static int udp_detach __P((struct socket *so));
|
||||
static int udp_output __P((struct inpcb *, struct mbuf *, struct sockaddr *,
|
||||
struct mbuf *, struct proc *));
|
||||
|
||||
@ -111,16 +145,18 @@ udp_init()
|
||||
}
|
||||
|
||||
void
|
||||
udp_input(m, iphlen)
|
||||
udp_input(m, off, proto)
|
||||
register struct mbuf *m;
|
||||
int iphlen;
|
||||
int off, proto;
|
||||
{
|
||||
int iphlen = off;
|
||||
register struct ip *ip;
|
||||
register struct udphdr *uh;
|
||||
register struct inpcb *inp;
|
||||
struct mbuf *opts = 0;
|
||||
int len;
|
||||
struct ip save_ip;
|
||||
struct sockaddr *append_sa;
|
||||
|
||||
udpstat.udps_ipackets++;
|
||||
|
||||
@ -205,14 +241,19 @@ udp_input(m, iphlen)
|
||||
*/
|
||||
udp_in.sin_port = uh->uh_sport;
|
||||
udp_in.sin_addr = ip->ip_src;
|
||||
m->m_len -= sizeof (struct udpiphdr);
|
||||
m->m_data += sizeof (struct udpiphdr);
|
||||
/*
|
||||
* Locate pcb(s) for datagram.
|
||||
* (Algorithm copied from raw_intr().)
|
||||
*/
|
||||
last = NULL;
|
||||
for (inp = udb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
|
||||
#ifdef INET6
|
||||
udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0;
|
||||
#endif
|
||||
LIST_FOREACH(inp, &udb, inp_list) {
|
||||
#ifdef INET6
|
||||
if ((inp->inp_vflag & INP_IPV4) == NULL)
|
||||
continue;
|
||||
#endif
|
||||
if (inp->inp_lport != uh->uh_dport)
|
||||
continue;
|
||||
if (inp->inp_laddr.s_addr != INADDR_ANY) {
|
||||
@ -230,21 +271,17 @@ udp_input(m, iphlen)
|
||||
if (last != NULL) {
|
||||
struct mbuf *n;
|
||||
|
||||
if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
|
||||
if (last->inp_flags & INP_CONTROLOPTS
|
||||
|| last->inp_socket->so_options & SO_TIMESTAMP)
|
||||
ip_savecontrol(last, &opts, ip, n);
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in,
|
||||
n, opts) == 0) {
|
||||
m_freem(n);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
udpstat.udps_fullsock++;
|
||||
} else
|
||||
sorwakeup(last->inp_socket);
|
||||
opts = 0;
|
||||
}
|
||||
#ifdef IPSEC
|
||||
/* check AH/ESP integrity. */
|
||||
if (ipsec4_in_reject_so(m, last->inp_socket))
|
||||
ipsecstat.in_polvio++;
|
||||
/* do not inject data to pcb */
|
||||
else
|
||||
#endif /*IPSEC*/
|
||||
if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
|
||||
udp_append(last, ip, n,
|
||||
iphlen +
|
||||
sizeof(struct udphdr));
|
||||
}
|
||||
last = inp;
|
||||
/*
|
||||
@ -268,23 +305,21 @@ udp_input(m, iphlen)
|
||||
udpstat.udps_noportbcast++;
|
||||
goto bad;
|
||||
}
|
||||
if (last->inp_flags & INP_CONTROLOPTS
|
||||
|| last->inp_socket->so_options & SO_TIMESTAMP)
|
||||
ip_savecontrol(last, &opts, ip, m);
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in,
|
||||
m, opts) == 0) {
|
||||
udpstat.udps_fullsock++;
|
||||
#ifdef IPSEC
|
||||
/* check AH/ESP integrity. */
|
||||
if (ipsec4_in_reject_so(m, last->inp_socket)) {
|
||||
ipsecstat.in_polvio++;
|
||||
goto bad;
|
||||
}
|
||||
sorwakeup(last->inp_socket);
|
||||
#endif /*IPSEC*/
|
||||
udp_append(last, ip, m, iphlen + sizeof(struct udphdr));
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Locate pcb for datagram.
|
||||
*/
|
||||
inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
|
||||
ip->ip_dst, uh->uh_dport, 1);
|
||||
ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
|
||||
if (inp == NULL) {
|
||||
if (log_in_vain) {
|
||||
char buf[4*sizeof "123"];
|
||||
@ -311,6 +346,12 @@ udp_input(m, iphlen)
|
||||
goto bad;
|
||||
return;
|
||||
}
|
||||
#ifdef IPSEC
|
||||
if (ipsec4_in_reject_so(m, inp->inp_socket)) {
|
||||
ipsecstat.in_polvio++;
|
||||
goto bad;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
|
||||
/*
|
||||
* Construct sockaddr format source address.
|
||||
@ -319,14 +360,30 @@ udp_input(m, iphlen)
|
||||
udp_in.sin_port = uh->uh_sport;
|
||||
udp_in.sin_addr = ip->ip_src;
|
||||
if (inp->inp_flags & INP_CONTROLOPTS
|
||||
|| inp->inp_socket->so_options & SO_TIMESTAMP)
|
||||
|| inp->inp_socket->so_options & SO_TIMESTAMP) {
|
||||
#ifdef INET6
|
||||
if (inp->inp_vflag & INP_IPV6) {
|
||||
int savedflags;
|
||||
|
||||
ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
|
||||
savedflags = inp->inp_flags;
|
||||
inp->inp_flags &= ~INP_UNMAPPABLEOPTS;
|
||||
ip6_savecontrol(inp, &opts, &udp_ip6.uip6_ip6, m);
|
||||
inp->inp_flags = savedflags;
|
||||
} else
|
||||
#endif
|
||||
ip_savecontrol(inp, &opts, ip, m);
|
||||
}
|
||||
iphlen += sizeof(struct udphdr);
|
||||
m->m_len -= iphlen;
|
||||
m->m_pkthdr.len -= iphlen;
|
||||
m->m_data += iphlen;
|
||||
if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
|
||||
m, opts) == 0) {
|
||||
m_adj(m, iphlen);
|
||||
#ifdef INET6
|
||||
if (inp->inp_vflag & INP_IPV6) {
|
||||
in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
|
||||
append_sa = (struct sockaddr *)&udp_in6;
|
||||
} else
|
||||
#endif
|
||||
append_sa = (struct sockaddr *)&udp_in;
|
||||
if (sbappendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts) == 0) {
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
@ -336,6 +393,78 @@ udp_input(m, iphlen)
|
||||
m_freem(m);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(INET6)
|
||||
static void
|
||||
ip_2_ip6_hdr(ip6, ip)
|
||||
struct ip6_hdr *ip6;
|
||||
struct ip *ip;
|
||||
{
|
||||
bzero(ip6, sizeof(*ip6));
|
||||
|
||||
ip6->ip6_vfc = IPV6_VERSION;
|
||||
ip6->ip6_plen = ip->ip_len;
|
||||
ip6->ip6_nxt = ip->ip_p;
|
||||
ip6->ip6_hlim = ip->ip_ttl;
|
||||
ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
|
||||
IPV6_ADDR_INT32_SMP;
|
||||
ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
|
||||
ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* subroutine of udp_input(), mainly for source code readability.
|
||||
* caller must properly init udp_ip6 and udp_in6 beforehand.
|
||||
*/
|
||||
static void
|
||||
udp_append(last, ip, n, off)
|
||||
struct inpcb *last;
|
||||
struct ip *ip;
|
||||
struct mbuf *n;
|
||||
int off;
|
||||
{
|
||||
struct sockaddr *append_sa;
|
||||
struct mbuf *opts = 0;
|
||||
|
||||
if (last->inp_flags & INP_CONTROLOPTS ||
|
||||
last->inp_socket->so_options & SO_TIMESTAMP) {
|
||||
#ifdef INET6
|
||||
if (last->inp_vflag & INP_IPV6) {
|
||||
int savedflags;
|
||||
|
||||
if (udp_ip6.uip6_init_done == 0) {
|
||||
ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
|
||||
udp_ip6.uip6_init_done = 1;
|
||||
}
|
||||
savedflags = last->inp_flags;
|
||||
last->inp_flags &= ~INP_UNMAPPABLEOPTS;
|
||||
ip6_savecontrol(last, &opts, &udp_ip6.uip6_ip6, n);
|
||||
last->inp_flags = savedflags;
|
||||
} else
|
||||
#endif
|
||||
ip_savecontrol(last, &opts, ip, n);
|
||||
}
|
||||
#ifdef INET6
|
||||
if (last->inp_vflag & INP_IPV6) {
|
||||
if (udp_in6.uin6_init_done == 0) {
|
||||
in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
|
||||
udp_in6.uin6_init_done = 1;
|
||||
}
|
||||
append_sa = (struct sockaddr *)&udp_in6.uin6_sin;
|
||||
} else
|
||||
#endif
|
||||
append_sa = (struct sockaddr *)&udp_in;
|
||||
m_adj(n, off);
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv, append_sa, n, opts) == 0) {
|
||||
m_freem(n);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
udpstat.udps_fullsock++;
|
||||
} else
|
||||
sorwakeup(last->inp_socket);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -473,7 +602,7 @@ udp_getcred SYSCTL_HANDLER_ARGS
|
||||
return (error);
|
||||
s = splnet();
|
||||
inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
|
||||
addrs[0].sin_addr, addrs[0].sin_port, 1);
|
||||
addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
|
||||
if (inp == NULL || inp->inp_socket == NULL) {
|
||||
error = ENOENT;
|
||||
goto out;
|
||||
@ -570,6 +699,11 @@ udp_output(inp, m, addr, control, p)
|
||||
((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
|
||||
((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
|
||||
udpstat.udps_opackets++;
|
||||
|
||||
#ifdef IPSEC
|
||||
m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket;
|
||||
#endif /*IPSEC*/
|
||||
|
||||
error = ip_output(m, inp->inp_options, &inp->inp_route,
|
||||
inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
|
||||
inp->inp_moptions);
|
||||
@ -591,7 +725,13 @@ u_long udp_sendspace = 9216; /* really max datagram size */
|
||||
SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
|
||||
&udp_sendspace, 0, "Maximum outgoing UDP datagram size");
|
||||
|
||||
u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
|
||||
u_long udp_recvspace = 40 * (1024 +
|
||||
#ifdef INET6
|
||||
sizeof(struct sockaddr_in6)
|
||||
#else
|
||||
sizeof(struct sockaddr_in)
|
||||
#endif
|
||||
);
|
||||
SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
|
||||
&udp_recvspace, 0, "Maximum incoming UDP datagram size");
|
||||
|
||||
@ -621,15 +761,27 @@ udp_attach(struct socket *so, int proto, struct proc *p)
|
||||
if (inp != 0)
|
||||
return EINVAL;
|
||||
|
||||
error = soreserve(so, udp_sendspace, udp_recvspace);
|
||||
if (error)
|
||||
return error;
|
||||
s = splnet();
|
||||
error = in_pcballoc(so, &udbinfo, p);
|
||||
splx(s);
|
||||
if (error)
|
||||
return error;
|
||||
error = soreserve(so, udp_sendspace, udp_recvspace);
|
||||
if (error)
|
||||
|
||||
inp = (struct inpcb *)so->so_pcb;
|
||||
#ifdef INET6
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
#endif
|
||||
inp->inp_ip_ttl = ip_defttl;
|
||||
#ifdef IPSEC
|
||||
error = ipsec_init_policy(so, &inp->inp_sp);
|
||||
if (error != 0) {
|
||||
in_pcbdetach(inp);
|
||||
return error;
|
||||
((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ extern int log_in_vain;
|
||||
|
||||
void udp_ctlinput __P((int, struct sockaddr *, void *));
|
||||
void udp_init __P((void));
|
||||
void udp_input __P((struct mbuf *, int));
|
||||
void udp_input __P((struct mbuf *, int, int));
|
||||
|
||||
void udp_notify __P((struct inpcb *inp, int errno));
|
||||
int udp_shutdown __P((struct socket *so));
|
||||
|
@ -64,7 +64,6 @@
|
||||
* @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_key.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -97,15 +96,10 @@
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ipsec6.h>
|
||||
#endif /* INET6 */
|
||||
#include <netkey/key.h>
|
||||
#ifdef KEY_DEBUG
|
||||
#include <netkey/key_debug.h>
|
||||
#ifdef INET6
|
||||
#include <netkey/key_debug6.h>
|
||||
#endif /* INET6 */
|
||||
#else
|
||||
#define DPRINTF(lev,arg)
|
||||
#define DDO(lev, stmt)
|
||||
@ -113,7 +107,7 @@
|
||||
#endif /* KEY_DEBUG */
|
||||
#endif /* IPSEC */
|
||||
|
||||
/* #include "faith.h" */
|
||||
#include "faith.h"
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
@ -910,8 +904,7 @@ ni6_addrs(ni6, m, ifpp)
|
||||
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
|
||||
{
|
||||
addrsofif = 0;
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa;
|
||||
ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
@ -976,8 +969,7 @@ ni6_store_addrs(ni6, nni6, ifp0, resid)
|
||||
|
||||
for (; ifp; ifp = TAILQ_NEXT(ifp, if_list))
|
||||
{
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa;
|
||||
ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
docopy = 0;
|
||||
|
||||
|
@ -516,6 +516,9 @@ struct icmp6stat {
|
||||
#define RTF_PROBEMTU RTF_PROTO1
|
||||
|
||||
#ifdef _KERNEL
|
||||
#ifdef SYSCTL_DECL
|
||||
SYSCTL_DECL(_net_inet6_icmp6);
|
||||
#endif
|
||||
# ifdef __STDC__
|
||||
struct rtentry;
|
||||
struct rttimer;
|
||||
|
@ -64,8 +64,6 @@
|
||||
* @(#)in.c 8.2 (Berkeley) 11/15/93
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -81,10 +79,8 @@
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
/* #include "gif.h" */
|
||||
#if NGIF > 0
|
||||
#include <net/if_gif.h>
|
||||
#endif
|
||||
#include "gif.h"
|
||||
|
||||
#include <net/if_dl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
@ -96,6 +92,9 @@
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/mld6_var.h>
|
||||
#include <netinet6/in6_ifattach.h>
|
||||
#if NGIF > 0
|
||||
#include <net/if_gif.h>
|
||||
#endif
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
@ -348,7 +347,7 @@ in6_ifindex2scopeid(idx)
|
||||
return -1;
|
||||
ifp = ifindex2ifnet[idx];
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
@ -1059,9 +1058,7 @@ in6_lifaddr_ioctl(so, cmd, data, ifp, p)
|
||||
}
|
||||
}
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first;
|
||||
ifa;
|
||||
ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
@ -1311,7 +1308,7 @@ in6ifa_ifpforlinklocal(ifp)
|
||||
{
|
||||
register struct ifaddr *ifa;
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue; /* just for safety */
|
||||
@ -1335,7 +1332,7 @@ in6ifa_ifpwithaddr(ifp, addr)
|
||||
{
|
||||
register struct ifaddr *ifa;
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue; /* just for safety */
|
||||
@ -1575,7 +1572,7 @@ in6_ifawithscope(ifp, dst)
|
||||
* If two or more, return one which matches the dst longest.
|
||||
* If none, return one of global addresses assigned other ifs.
|
||||
*/
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
@ -1661,7 +1658,7 @@ in6_ifawithifp(ifp, dst)
|
||||
* If two or more, return one which matches the dst longest.
|
||||
* If none, return one of global addresses assigned other ifs.
|
||||
*/
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
@ -1696,7 +1693,7 @@ in6_ifawithifp(ifp, dst)
|
||||
if (besta)
|
||||
return(besta);
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
@ -1742,7 +1739,7 @@ in6_if_up(ifp)
|
||||
bzero(&ea, sizeof(ea));
|
||||
sdl = NULL;
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6
|
||||
&& IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
|
||||
@ -1789,7 +1786,7 @@ in6_if_up(ifp)
|
||||
|
||||
dad:
|
||||
dad_delay = 0;
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
@ -74,6 +74,7 @@
|
||||
* Identification of the network protocol stack
|
||||
*/
|
||||
#define __KAME__
|
||||
#define __KAME_VERSION "SNAP 19991101"
|
||||
|
||||
/*
|
||||
* Local port number conventions:
|
||||
@ -342,13 +343,6 @@ extern const struct in6_addr in6addr_linklocal_allrouters;
|
||||
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wildcard Socket
|
||||
*/
|
||||
#if 0 /*pre-RFC2553*/
|
||||
#define IN6_IS_ADDR_ANY(a) IN6_IS_ADDR_UNSPECIFIED(a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* KAME Scope
|
||||
*/
|
||||
@ -522,65 +516,12 @@ struct in6_pktinfo {
|
||||
#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 */
|
||||
#define IPV6CTL_MAPPED_ADDR 23
|
||||
/* New entries should be added here from current IPV6CTL_MAXID value. */
|
||||
#define IPV6CTL_MAXID 24
|
||||
|
||||
#define IPV6CTL_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
{ "forwarding", CTLTYPE_INT }, \
|
||||
{ "redirect", CTLTYPE_INT }, \
|
||||
{ "hlim", CTLTYPE_INT }, \
|
||||
{ "mtu", CTLTYPE_INT }, \
|
||||
{ "forwsrcrt", CTLTYPE_INT }, \
|
||||
{ 0, 0 }, \
|
||||
{ 0, 0 }, \
|
||||
{ "mrtproto", CTLTYPE_INT }, \
|
||||
{ "maxfragpackets", CTLTYPE_INT }, \
|
||||
{ "sourcecheck", CTLTYPE_INT }, \
|
||||
{ "sourcecheck_logint", CTLTYPE_INT }, \
|
||||
{ "accept_rtadv", CTLTYPE_INT }, \
|
||||
{ "keepfaith", CTLTYPE_INT }, \
|
||||
{ "log_interval", CTLTYPE_INT }, \
|
||||
{ "hdrnestlimit", CTLTYPE_INT }, \
|
||||
{ "dad_count", CTLTYPE_INT }, \
|
||||
{ "auto_flowlabel", CTLTYPE_INT }, \
|
||||
{ "defmcasthlim", CTLTYPE_INT }, \
|
||||
{ "gifhlim", CTLTYPE_INT }, \
|
||||
{ 0, 0 }, \
|
||||
{ "use_deprecated", CTLTYPE_INT }, \
|
||||
{ "rr_prune", CTLTYPE_INT }, \
|
||||
{ "mapped_addr", CTLTYPE_INT }, \
|
||||
}
|
||||
|
||||
#define IPV6CTL_VARS { \
|
||||
0, \
|
||||
&ip6_forwarding, \
|
||||
&ip6_sendredirects, \
|
||||
&ip6_defhlim, \
|
||||
0, \
|
||||
&ip6_forward_srcrt, \
|
||||
0, \
|
||||
0, \
|
||||
0, \
|
||||
&ip6_maxfragpackets, \
|
||||
&ip6_sourcecheck, \
|
||||
&ip6_sourcecheck_interval, \
|
||||
&ip6_accept_rtadv, \
|
||||
&ip6_keepfaith, \
|
||||
&ip6_log_interval, \
|
||||
&ip6_hdrnestlimit, \
|
||||
&ip6_dad_count, \
|
||||
&ip6_auto_flowlabel, \
|
||||
&ip6_defmcasthlim, \
|
||||
&ip6_gif_hlim, \
|
||||
0, \
|
||||
&ip6_use_deprecated, \
|
||||
&ip6_rr_prune, \
|
||||
&ip6_mapped_addr_on, \
|
||||
}
|
||||
#endif /* !_XOPEN_SOURCE */
|
||||
|
||||
/*
|
||||
@ -633,9 +574,6 @@ extern struct cmsghdr *inet6_rthdr_init __P((void *, int));
|
||||
extern int inet6_rthdr_add __P((struct cmsghdr *, const struct in6_addr *,
|
||||
u_int));
|
||||
extern int inet6_rthdr_lasthop __P((struct cmsghdr *, u_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));
|
||||
|
263
sys/netinet6/in6_gif.c
Normal file
263
sys/netinet6/in6_gif.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* in6_gif.c
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/protosw.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#ifdef INET
|
||||
#include <netinet/ip.h>
|
||||
#endif
|
||||
#include <netinet6/ip6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/in6_gif.h>
|
||||
#include <netinet6/ip6.h>
|
||||
|
||||
#include <net/if_gif.h>
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
int
|
||||
in6_gif_output(ifp, family, m, rt)
|
||||
struct ifnet *ifp;
|
||||
int family; /* family of the packet to be encapsulate. */
|
||||
struct mbuf *m;
|
||||
struct rtentry *rt;
|
||||
{
|
||||
struct gif_softc *sc = (struct gif_softc*)ifp;
|
||||
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;
|
||||
int proto;
|
||||
|
||||
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 *);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
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 *);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("in6_gif_output: warning: unknown family %d passed\n",
|
||||
family);
|
||||
#endif
|
||||
m_freem(m);
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
/* prepend new IP header */
|
||||
M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
|
||||
if (m && m->m_len < sizeof(struct ip6_hdr))
|
||||
m = m_pullup(m, sizeof(struct ip6_hdr));
|
||||
if (m == NULL) {
|
||||
printf("ENOBUFS in in6_gif_output %d\n", __LINE__);
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ip6->ip6_flow = 0;
|
||||
ip6->ip6_vfc = IPV6_VERSION;
|
||||
ip6->ip6_plen = htons((u_short)m->m_pkthdr.len);
|
||||
ip6->ip6_nxt = proto;
|
||||
ip6->ip6_hlim = ip6_gif_hlim;
|
||||
ip6->ip6_src = sin6_src->sin6_addr;
|
||||
if (ifp->if_flags & IFF_LINK0) {
|
||||
/* multi-destination mode */
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
|
||||
ip6->ip6_dst = sin6_dst->sin6_addr;
|
||||
else if (rt) {
|
||||
ip6->ip6_dst = ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
|
||||
} else {
|
||||
m_freem(m);
|
||||
return ENETUNREACH;
|
||||
}
|
||||
} else {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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 (sc->gif_ro6.ro_rt == NULL) {
|
||||
rtalloc((struct route *)&sc->gif_ro6);
|
||||
if (sc->gif_ro6.ro_rt == NULL) {
|
||||
m_freem(m);
|
||||
return ENETUNREACH;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IPSEC
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
#endif /*IPSEC*/
|
||||
return(ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL));
|
||||
}
|
||||
|
||||
int in6_gif_input(mp, offp, proto)
|
||||
struct mbuf **mp;
|
||||
int *offp, proto;
|
||||
{
|
||||
struct mbuf *m = *mp;
|
||||
struct gif_softc *sc;
|
||||
struct ifnet *gifp = NULL;
|
||||
struct ip6_hdr *ip6;
|
||||
int i;
|
||||
int af = 0;
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
||||
#define satoin6(sa) (((struct sockaddr_in6 *)(sa))->sin6_addr)
|
||||
for (i = 0, sc = gif; i < ngif; i++, sc++) {
|
||||
if (sc->gif_psrc == NULL ||
|
||||
sc->gif_pdst == NULL ||
|
||||
sc->gif_psrc->sa_family != AF_INET6 ||
|
||||
sc->gif_pdst->sa_family != AF_INET6) {
|
||||
continue;
|
||||
}
|
||||
if ((sc->gif_if.if_flags & IFF_UP) == 0)
|
||||
continue;
|
||||
if ((sc->gif_if.if_flags & IFF_LINK0) &&
|
||||
IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&satoin6(sc->gif_pdst))) {
|
||||
gifp = &sc->gif_if;
|
||||
continue;
|
||||
}
|
||||
if (IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) &&
|
||||
IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_pdst), &ip6->ip6_src)) {
|
||||
gifp = &sc->gif_if;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gifp == NULL) {
|
||||
m_freem(m);
|
||||
ip6stat.ip6s_nogif++;
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
m_adj(m, *offp);
|
||||
|
||||
switch (proto) {
|
||||
#ifdef INET
|
||||
case IPPROTO_IPV4:
|
||||
{
|
||||
struct ip *ip;
|
||||
af = AF_INET;
|
||||
if (m->m_len < sizeof(*ip)) {
|
||||
m = m_pullup(m, sizeof(*ip));
|
||||
if (!m)
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
ip = mtod(m, struct ip *);
|
||||
break;
|
||||
}
|
||||
#endif /* INET */
|
||||
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 *);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ip6stat.ip6s_nogif++;
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
gif_input(m, af, gifp);
|
||||
return IPPROTO_DONE;
|
||||
}
|
40
sys/netinet6/in6_gif.h
Normal file
40
sys/netinet6/in6_gif.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_IN6_GIF_H_
|
||||
#define _NETINET6_IN6_GIF_H_
|
||||
|
||||
#define GIF_HLIM 30
|
||||
|
||||
int in6_gif_input __P((struct mbuf **, int *, int));
|
||||
int in6_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *));
|
||||
|
||||
#endif /*_NETINET6_IN6_GIF_H_*/
|
@ -153,13 +153,11 @@ in6_ifattach_getifid(ifp0)
|
||||
if (found_first_ifid)
|
||||
return 0;
|
||||
|
||||
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
|
||||
TAILQ_FOREACH(ifp, &ifnet, if_list)
|
||||
{
|
||||
if (ifp0 != NULL && ifp0 != ifp)
|
||||
continue;
|
||||
for (ifa = ifp->if_addrlist.tqh_first;
|
||||
ifa;
|
||||
ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
@ -239,7 +237,7 @@ in6_ifattach_p2p()
|
||||
if (found_first_ifid == 0)
|
||||
return;
|
||||
|
||||
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
|
||||
TAILQ_FOREACH(ifp, &ifnet, if_list)
|
||||
{
|
||||
switch (ifp->if_type) {
|
||||
case IFT_GIF:
|
||||
@ -645,7 +643,7 @@ in6_ifdetach(ifp)
|
||||
struct rtentry *rt;
|
||||
short rtflags;
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6
|
||||
|| !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
|
||||
|
@ -65,7 +65,6 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_key.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -96,19 +95,14 @@
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet6/in6_pcb.h>
|
||||
|
||||
/* #include "faith.h" */
|
||||
#include "faith.h"
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ipsec6.h>
|
||||
#endif /* INET6 */
|
||||
#include <netkey/key.h>
|
||||
#ifdef KEY_DEBUG
|
||||
#include <netkey/key_debug.h>
|
||||
#ifdef INET6
|
||||
#include <netkey/key_debug6.h>
|
||||
#endif /* INET6 */
|
||||
#else
|
||||
#define DPRINTF(lev,arg)
|
||||
#define DDO(lev, stmt)
|
||||
@ -1065,7 +1059,7 @@ in6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp)
|
||||
head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */,
|
||||
lport, fport,
|
||||
pcbinfo->hashmask)];
|
||||
for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
|
||||
LIST_FOREACH(inp, head, inp_hash) {
|
||||
if ((inp->inp_vflag & INP_IPV6) == NULL)
|
||||
continue;
|
||||
if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
|
||||
@ -1083,8 +1077,7 @@ in6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp)
|
||||
|
||||
head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
|
||||
pcbinfo->hashmask)];
|
||||
for (inp = head->lh_first; inp != NULL;
|
||||
inp = inp->inp_hash.le_next) {
|
||||
LIST_FOREACH(inp, head, inp_hash) {
|
||||
if ((inp->inp_vflag & INP_IPV6) == NULL)
|
||||
continue;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
|
||||
|
@ -184,7 +184,7 @@ search_matched_prefix(struct ifnet *ifp, struct in6_prefixreq *ipr)
|
||||
* which matches the addr
|
||||
*/
|
||||
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
@ -249,7 +249,7 @@ mark_matched_prefixes(u_long cmd, struct ifnet *ifp, struct in6_rrenumreq *irr)
|
||||
* search matched addr, and then search prefixes
|
||||
* which matche the addr
|
||||
*/
|
||||
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
struct rr_prefix *rpp;
|
||||
|
||||
@ -364,8 +364,7 @@ search_ifidwithprefix(struct rr_prefix *rpp, struct in6_addr *ifid)
|
||||
{
|
||||
struct rp_addr *rap;
|
||||
|
||||
for (rap = rpp->rp_addrhead.lh_first; rap != NULL;
|
||||
rap = rap->ra_entry.le_next)
|
||||
LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry)
|
||||
if (rr_are_ifid_equal(ifid, &rap->ra_ifid,
|
||||
(sizeof(struct in6_addr) << 3) -
|
||||
rpp->rp_plen))
|
||||
@ -682,8 +681,7 @@ rrpr_update(struct socket *so, struct rr_prefix *new)
|
||||
* If it existed but not pointing to the prefix yet,
|
||||
* init the prefix pointer.
|
||||
*/
|
||||
for (rap = rpp->rp_addrhead.lh_first; rap != NULL;
|
||||
rap = rap->ra_entry.le_next) {
|
||||
LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry) {
|
||||
if (rap->ra_addr != NULL) {
|
||||
if (rap->ra_addr->ia6_ifpr == NULL)
|
||||
rap->ra_addr->ia6_ifpr = rp2ifpr(rpp);
|
||||
@ -771,8 +769,7 @@ init_newprefix(struct in6_rrenumreq *irr, struct ifprefix *ifpr,
|
||||
irr->irr_u_uselen,
|
||||
min(ifpr->ifpr_plen - irr->irr_u_uselen,
|
||||
irr->irr_u_keeplen));
|
||||
for (orap = (ifpr2rp(ifpr)->rp_addrhead).lh_first; orap != NULL;
|
||||
orap = orap->ra_entry.le_next) {
|
||||
LIST_FOREACH(orap, &(ifpr2rp(ifpr)->rp_addrhead), ra_entry) {
|
||||
struct rp_addr *rap;
|
||||
int error = 0;
|
||||
|
||||
@ -845,8 +842,7 @@ unprefer_prefix(struct rr_prefix *rpp)
|
||||
{
|
||||
struct rp_addr *rap;
|
||||
|
||||
for (rap = rpp->rp_addrhead.lh_first; rap != NULL;
|
||||
rap = rap->ra_entry.le_next) {
|
||||
LIST_FOREACH(rap, &rpp->rp_addrhead, ra_entry) {
|
||||
if (rap->ra_addr == NULL)
|
||||
continue;
|
||||
rap->ra_addr->ia6_lifetime.ia6t_preferred = time_second;
|
||||
@ -863,7 +859,7 @@ delete_each_prefix(struct socket *so, struct rr_prefix *rpp, u_char origin)
|
||||
if (rpp->rp_origin > origin)
|
||||
return(EPERM);
|
||||
|
||||
while (rpp->rp_addrhead.lh_first != NULL) {
|
||||
while (!LIST_EMPTY(&rpp->rp_addrhead)) {
|
||||
struct rp_addr *rap;
|
||||
int s;
|
||||
|
||||
@ -923,8 +919,7 @@ link_stray_ia6s(struct rr_prefix *rpp)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
|
||||
for (ifa = rpp->rp_ifp->if_addrlist.tqh_first; ifa;
|
||||
ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &rpp->rp_ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
struct rp_addr *rap;
|
||||
struct rr_prefix *orpp;
|
||||
|
@ -64,8 +64,6 @@
|
||||
* @(#)in_proto.c 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
@ -104,9 +102,7 @@
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ipsec6.h>
|
||||
#endif /* INET6 */
|
||||
#include <netinet6/ah.h>
|
||||
#ifdef IPSEC_ESP
|
||||
#include <netinet6/esp.h>
|
||||
@ -116,7 +112,7 @@
|
||||
|
||||
#include <netinet6/ip6protosw.h>
|
||||
|
||||
/* #include "gif.h" */
|
||||
#include "gif.h"
|
||||
#if NGIF > 0
|
||||
#include <netinet6/in6_gif.h>
|
||||
#endif
|
||||
@ -139,6 +135,12 @@ struct ip6protosw inet6sw[] = {
|
||||
ip6_init, 0, frag6_slowtimo, frag6_drain,
|
||||
&nousrreqs,
|
||||
},
|
||||
{ SOCK_DGRAM, &inet6domain, IPPROTO_UDP, PR_ATOMIC | PR_ADDR,
|
||||
udp6_input, 0, udp6_ctlinput, ip6_ctloutput,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&udp6_usrreqs,
|
||||
},
|
||||
{ SOCK_RAW, &inet6domain, IPPROTO_RAW, PR_ATOMIC | PR_ADDR,
|
||||
rip6_input, rip6_output, 0, rip6_ctloutput,
|
||||
0,
|
||||
@ -198,14 +200,12 @@ struct ip6protosw inet6sw[] = {
|
||||
0, 0, 0, 0,
|
||||
&nousrreqs
|
||||
},
|
||||
#ifdef INET6
|
||||
{ SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
|
||||
in6_gif_input,0, 0, 0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&nousrreqs
|
||||
},
|
||||
#endif /* INET6 */
|
||||
#endif /* GIF */
|
||||
/* raw wildcard */
|
||||
{ SOCK_RAW, &inet6domain, 0, PR_ATOMIC | PR_ADDR,
|
||||
@ -334,8 +334,8 @@ sysctl_ip6_forwarding SYSCTL_HANDLER_ARGS
|
||||
int s = splnet();
|
||||
struct nd_prefix *pr, *next;
|
||||
|
||||
for (pr = nd_prefix.lh_first; pr; pr = next) {
|
||||
next = pr->ndpr_next;
|
||||
for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) {
|
||||
next = LIST_NEXT(pr, ndpr_entry);
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
|
||||
in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
|
||||
prelist_remove(pr);
|
||||
@ -379,6 +379,8 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFMCASTHLIM,
|
||||
defmcasthlim, CTLFLAG_RW, &ip6_defmcasthlim, 0, "");
|
||||
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM,
|
||||
gifhlim, CTLFLAG_RW, &ip6_gif_hlim, 0, "");
|
||||
SYSCTL_STRING(_net_inet6_ip6, IPV6CTL_KAME_VERSION,
|
||||
kame_version, CTLFLAG_RD, __KAME_VERSION, 0, "");
|
||||
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_USE_DEPRECATED,
|
||||
use_deprecated, CTLFLAG_RW, &ip6_use_deprecated, 0, "");
|
||||
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE,
|
||||
|
@ -437,7 +437,7 @@ MALLOC_DECLARE(M_IPMADDR);
|
||||
/* struct in6_ifaddr *ia; */ \
|
||||
do { \
|
||||
struct ifaddr *ifa; \
|
||||
for (ifa = (ifp)->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) { \
|
||||
TAILQ_FOREACH(ifa, &(ifp)->if_addrlist, ifa_list) { \
|
||||
if (!ifa->ifa_addr) \
|
||||
continue; \
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6) \
|
||||
@ -467,6 +467,11 @@ struct in6_multi {
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#ifdef SYSCTL_DECL
|
||||
SYSCTL_DECL(_net_inet6_ip6);
|
||||
#endif
|
||||
|
||||
extern LIST_HEAD(in6_multihead, in6_multi) in6_multihead;
|
||||
|
||||
/*
|
||||
@ -512,14 +517,14 @@ do { \
|
||||
/* struct in6_multi *in6m; */ \
|
||||
do { \
|
||||
if (((in6m) = (step).i_in6m) != NULL) \
|
||||
(step).i_in6m = (step).i_in6m->in6m_entry.le_next; \
|
||||
(step).i_in6m = LIST_NEXT((step).i_in6m, in6m_entry); \
|
||||
} while(0)
|
||||
|
||||
#define IN6_FIRST_MULTI(step, in6m) \
|
||||
/* struct in6_multistep step; */ \
|
||||
/* struct in6_multi *in6m */ \
|
||||
do { \
|
||||
(step).i_in6m = in6_multihead.lh_first; \
|
||||
(step).i_in6m = LIST_FIRST(&in6_multihead); \
|
||||
IN6_NEXT_MULTI((step), (in6m)); \
|
||||
} while(0)
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_key.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -56,15 +55,10 @@
|
||||
|
||||
#ifdef IPSEC_IPV6FWD
|
||||
#include <netinet6/ipsec.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ipsec6.h>
|
||||
#endif /* INET6 */
|
||||
#include <netkey/key.h>
|
||||
#ifdef KEY_DEBUG
|
||||
#include <netkey/key_debug.h>
|
||||
#ifdef INET6
|
||||
#include <netkey/key_debug6.h>
|
||||
#endif /* INET6 */
|
||||
#else
|
||||
#define DPRINTF(lev,arg)
|
||||
#define DDO(lev, stmt)
|
||||
|
@ -64,8 +64,6 @@
|
||||
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -88,10 +86,8 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#ifdef INET
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#endif /*INET*/
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/ip6.h>
|
||||
@ -113,9 +109,9 @@
|
||||
|
||||
/* we need it for NLOOP. */
|
||||
#include "loop.h"
|
||||
/* #include "faith.h" */
|
||||
|
||||
/* #include "gif.h" */
|
||||
#include "faith.h"
|
||||
#include "gif.h"
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
@ -793,7 +789,6 @@ ip6_savecontrol(in6p, mp, ip6, m)
|
||||
if (p && !suser(p))
|
||||
privileged++;
|
||||
|
||||
#ifdef SO_TIMESTAMP
|
||||
if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
struct timeval tv;
|
||||
|
||||
@ -803,7 +798,6 @@ ip6_savecontrol(in6p, mp, ip6, m)
|
||||
if (*mp)
|
||||
mp = &(*mp)->m_next;
|
||||
}
|
||||
#endif
|
||||
if (in6p->in6p_flags & IN6P_RECVDSTADDR) {
|
||||
*mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst,
|
||||
sizeof(struct in6_addr), IPV6_RECVDSTADDR,
|
||||
|
@ -64,7 +64,6 @@
|
||||
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_key.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -91,15 +90,10 @@
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ipsec6.h>
|
||||
#endif /* INET6 */
|
||||
#include <netkey/key.h>
|
||||
#ifdef KEY_DEBUG
|
||||
#include <netkey/key_debug.h>
|
||||
#ifdef INET6
|
||||
#include <netkey/key_debug6.h>
|
||||
#endif /* INET6 */
|
||||
#else
|
||||
#define DPRINTF(lev,arg)
|
||||
#define DDO(lev, stmt)
|
||||
@ -1764,8 +1758,7 @@ ip6_setmoptions(optname, im6op, m)
|
||||
/*
|
||||
* See if the membership already exists.
|
||||
*/
|
||||
for (imm = im6o->im6o_memberships.lh_first;
|
||||
imm != NULL; imm = imm->i6mm_chain.le_next)
|
||||
LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain)
|
||||
if (imm->i6mm_maddr->in6m_ifp == ifp &&
|
||||
IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
|
||||
&mreq->ipv6mr_multiaddr))
|
||||
@ -1831,8 +1824,7 @@ ip6_setmoptions(optname, im6op, m)
|
||||
/*
|
||||
* Find the membership in the membership list.
|
||||
*/
|
||||
for (imm = im6o->im6o_memberships.lh_first;
|
||||
imm != NULL; imm = imm->i6mm_chain.le_next) {
|
||||
LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) {
|
||||
if ((ifp == NULL ||
|
||||
imm->i6mm_maddr->in6m_ifp == ifp) &&
|
||||
IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
|
||||
@ -1864,7 +1856,7 @@ ip6_setmoptions(optname, im6op, m)
|
||||
if (im6o->im6o_multicast_ifp == NULL &&
|
||||
im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
|
||||
im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
|
||||
im6o->im6o_memberships.lh_first == NULL) {
|
||||
LIST_EMPTY(&im6o->im6o_memberships)) {
|
||||
free(*im6op, M_IPMOPTS);
|
||||
*im6op = NULL;
|
||||
}
|
||||
@ -1931,7 +1923,7 @@ ip6_freemoptions(im6o)
|
||||
if (im6o == NULL)
|
||||
return;
|
||||
|
||||
while ((imm = im6o->im6o_memberships.lh_first) != NULL) {
|
||||
while ((imm = LIST_FIRST(&im6o->im6o_memberships)) != NULL) {
|
||||
LIST_REMOVE(imm, i6mm_chain);
|
||||
if (imm->i6mm_maddr)
|
||||
in6_delmulti(imm->i6mm_maddr);
|
||||
|
@ -68,8 +68,6 @@
|
||||
* @(#)igmp.c 8.1 (Berkeley) 7/19/93
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
|
@ -458,17 +458,17 @@ nd6_timer(ignored_arg)
|
||||
}
|
||||
|
||||
/* expire */
|
||||
dr = nd_defrouter.lh_first;
|
||||
dr = LIST_FIRST(&nd_defrouter);
|
||||
while (dr) {
|
||||
if (dr->expire && dr->expire < time_second) {
|
||||
struct nd_defrouter *t;
|
||||
t = dr->dr_next;
|
||||
t = LIST_NEXT(dr, dr_entry);
|
||||
defrtrlist_del(dr);
|
||||
dr = t;
|
||||
} else
|
||||
dr = dr->dr_next;
|
||||
dr = LIST_NEXT(dr, dr_entry);
|
||||
}
|
||||
pr = nd_prefix.lh_first;
|
||||
pr = LIST_FIRST(&nd_prefix);
|
||||
while (pr) {
|
||||
struct in6_ifaddr *ia6;
|
||||
struct in6_addrlifetime *lt6;
|
||||
@ -503,7 +503,7 @@ nd6_timer(ignored_arg)
|
||||
if (pr->ndpr_expire
|
||||
&& pr->ndpr_expire + NDPR_KEEP_EXPIRED < time_second) {
|
||||
struct nd_prefix *t;
|
||||
t = pr->ndpr_next;
|
||||
t = LIST_NEXT(pr, ndpr_entry);
|
||||
|
||||
/*
|
||||
* address expiration and prefix expiration are
|
||||
@ -513,7 +513,7 @@ nd6_timer(ignored_arg)
|
||||
prelist_remove(pr);
|
||||
pr = t;
|
||||
} else
|
||||
pr = pr->ndpr_next;
|
||||
pr = LIST_NEXT(pr, ndpr_entry);
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
@ -627,9 +627,7 @@ nd6_is_addr_neighbor(addr, ifp)
|
||||
* If the address matches one of our addresses,
|
||||
* it should be a neighbor.
|
||||
*/
|
||||
for (ifa = ifp->if_addrlist.tqh_first;
|
||||
ifa;
|
||||
ifa = ifa->ifa_list.tqe_next)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
next: continue;
|
||||
@ -967,7 +965,7 @@ nd6_ioctl(cmd, data, ifp)
|
||||
case SIOCGDRLST_IN6:
|
||||
bzero(drl, sizeof(*drl));
|
||||
s = splnet();
|
||||
dr = nd_defrouter.lh_first;
|
||||
dr = LIST_FIRST(&nd_defrouter);
|
||||
while (dr && i < DRLSTSIZ) {
|
||||
drl->defrouter[i].rtaddr = dr->rtaddr;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&drl->defrouter[i].rtaddr)) {
|
||||
@ -984,14 +982,14 @@ nd6_ioctl(cmd, data, ifp)
|
||||
drl->defrouter[i].expire = dr->expire;
|
||||
drl->defrouter[i].if_index = dr->ifp->if_index;
|
||||
i++;
|
||||
dr = dr->dr_next;
|
||||
dr = LIST_NEXT(dr, dr_entry);
|
||||
}
|
||||
splx(s);
|
||||
break;
|
||||
case SIOCGPRLST_IN6:
|
||||
bzero(prl, sizeof(*prl));
|
||||
s = splnet();
|
||||
pr = nd_prefix.lh_first;
|
||||
pr = LIST_FIRST(&nd_prefix);
|
||||
while (pr && i < PRLSTSIZ) {
|
||||
struct nd_pfxrouter *pfr;
|
||||
int j;
|
||||
@ -1004,7 +1002,7 @@ nd6_ioctl(cmd, data, ifp)
|
||||
prl->prefix[i].if_index = pr->ndpr_ifp->if_index;
|
||||
prl->prefix[i].expire = pr->ndpr_expire;
|
||||
|
||||
pfr = pr->ndpr_advrtrs.lh_first;
|
||||
pfr = LIST_FIRST(&pr->ndpr_advrtrs);
|
||||
j = 0;
|
||||
while(pfr) {
|
||||
if (j < DRLSTSIZ) {
|
||||
@ -1022,12 +1020,12 @@ nd6_ioctl(cmd, data, ifp)
|
||||
#undef RTRADDR
|
||||
}
|
||||
j++;
|
||||
pfr = pfr->pfr_next;
|
||||
pfr = LIST_NEXT(pfr, pfr_entry);
|
||||
}
|
||||
prl->prefix[i].advrtrs = j;
|
||||
|
||||
i++;
|
||||
pr = pr->ndpr_next;
|
||||
pr = LIST_NEXT(pr, ndpr_entry);
|
||||
}
|
||||
splx(s);
|
||||
{
|
||||
@ -1069,8 +1067,8 @@ nd6_ioctl(cmd, data, ifp)
|
||||
struct nd_prefix *pr, *next;
|
||||
|
||||
s = splnet();
|
||||
for (pr = nd_prefix.lh_first; pr; pr = next) {
|
||||
next = pr->ndpr_next;
|
||||
for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) {
|
||||
next = LIST_NEXT(pr, ndpr_entry);
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
|
||||
in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
|
||||
prelist_remove(pr);
|
||||
@ -1084,16 +1082,16 @@ nd6_ioctl(cmd, data, ifp)
|
||||
struct nd_defrouter *dr, *next;
|
||||
|
||||
s = splnet();
|
||||
if ((dr = nd_defrouter.lh_first) != NULL) {
|
||||
if ((dr = LIST_FIRST(&nd_defrouter)) != NULL) {
|
||||
/*
|
||||
* The first entry of the list may be stored in
|
||||
* the routing table, so we'll delete it later.
|
||||
*/
|
||||
for (dr = dr->dr_next; dr; dr = next) {
|
||||
next = dr->dr_next;
|
||||
for (dr = LIST_NEXT(dr, dr_entry); dr; dr = next) {
|
||||
next = LIST_NEXT(dr, dr_entry);
|
||||
defrtrlist_del(dr);
|
||||
}
|
||||
defrtrlist_del(nd_defrouter.lh_first);
|
||||
defrtrlist_del(LIST_FIRST(&nd_defrouter));
|
||||
}
|
||||
splx(s);
|
||||
break;
|
||||
|
@ -126,7 +126,6 @@ struct in6_ndireq {
|
||||
|
||||
struct nd_defrouter {
|
||||
LIST_ENTRY(nd_defrouter) dr_entry;
|
||||
#define dr_next dr_entry.le_next
|
||||
struct in6_addr rtaddr;
|
||||
u_char flags;
|
||||
u_short rtlifetime;
|
||||
@ -154,8 +153,6 @@ struct nd_prefix {
|
||||
} ndpr_stateflags;
|
||||
};
|
||||
|
||||
#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
|
||||
@ -200,7 +197,6 @@ struct inet6_ndpr_msghdr {
|
||||
|
||||
struct nd_pfxrouter {
|
||||
LIST_ENTRY(nd_pfxrouter) pfr_entry;
|
||||
#define pfr_next pfr_entry.le_next
|
||||
struct nd_defrouter *router;
|
||||
};
|
||||
|
||||
|
@ -29,8 +29,6 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -818,7 +816,7 @@ nd6_dad_find(ifa)
|
||||
{
|
||||
struct dadq *dp;
|
||||
|
||||
for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) {
|
||||
TAILQ_FOREACH(dp, &dadq, dad_list) {
|
||||
if (dp->dad_ifa == ifa)
|
||||
return dp;
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ defrouter_lookup(addr, ifp)
|
||||
{
|
||||
struct nd_defrouter *dr;
|
||||
|
||||
for(dr = nd_defrouter.lh_first; dr; dr = dr->dr_next)
|
||||
LIST_FOREACH(dr, &nd_defrouter, dr_entry)
|
||||
if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
|
||||
return(dr);
|
||||
|
||||
@ -405,8 +405,8 @@ defrouter_delreq(dr, dofree)
|
||||
if (dofree)
|
||||
free(dr, M_IP6NDP);
|
||||
|
||||
if (nd_defrouter.lh_first)
|
||||
defrouter_addreq(nd_defrouter.lh_first);
|
||||
if (!LIST_EMPTY(&nd_defrouter))
|
||||
defrouter_addreq(LIST_FIRST(&nd_defrouter));
|
||||
|
||||
/*
|
||||
* xxx update the Destination Cache entries for all
|
||||
@ -430,7 +430,7 @@ defrtrlist_del(dr)
|
||||
rt6_flush(&dr->rtaddr, dr->ifp);
|
||||
}
|
||||
|
||||
if (dr == nd_defrouter.lh_first)
|
||||
if (dr == LIST_FIRST(&nd_defrouter))
|
||||
deldr = dr; /* The router is primary. */
|
||||
|
||||
LIST_REMOVE(dr, dr_entry);
|
||||
@ -438,7 +438,7 @@ defrtrlist_del(dr)
|
||||
/*
|
||||
* Also delete all the pointers to the router in each prefix lists.
|
||||
*/
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
|
||||
LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
|
||||
struct nd_pfxrouter *pfxrtr;
|
||||
if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
|
||||
pfxrtr_del(pfxrtr);
|
||||
@ -489,11 +489,11 @@ defrtrlist_update(new)
|
||||
}
|
||||
bzero(n, sizeof(*n));
|
||||
*n = *new;
|
||||
if (nd_defrouter.lh_first == NULL) {
|
||||
if (LIST_EMPTY(&nd_defrouter)) {
|
||||
LIST_INSERT_HEAD(&nd_defrouter, n, dr_entry);
|
||||
defrouter_addreq(n);
|
||||
} else {
|
||||
LIST_INSERT_AFTER(nd_defrouter.lh_first, n, dr_entry);
|
||||
LIST_INSERT_AFTER(LIST_FIRST(&nd_defrouter), n, dr_entry);
|
||||
defrouter_addreq(n);
|
||||
}
|
||||
splx(s);
|
||||
@ -508,7 +508,7 @@ pfxrtr_lookup(pr, dr)
|
||||
{
|
||||
struct nd_pfxrouter *search;
|
||||
|
||||
for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
|
||||
LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) {
|
||||
if (search->router == dr)
|
||||
break;
|
||||
}
|
||||
@ -548,7 +548,7 @@ prefix_lookup(pr)
|
||||
{
|
||||
struct nd_prefix *search;
|
||||
|
||||
for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
|
||||
LIST_FOREACH(search, &nd_prefix, ndpr_entry) {
|
||||
if (pr->ndpr_ifp == search->ndpr_ifp &&
|
||||
pr->ndpr_plen == search->ndpr_plen &&
|
||||
in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
|
||||
@ -611,8 +611,8 @@ prelist_remove(pr)
|
||||
splx(s);
|
||||
|
||||
/* free list of routers that adversed the prefix */
|
||||
for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
|
||||
next = pfr->pfr_next;
|
||||
for (pfr = LIST_FIRST(&pr->ndpr_advrtrs); pfr; pfr = next) {
|
||||
next = LIST_NEXT(pfr, pfr_entry);
|
||||
|
||||
free(pfr, M_IP6NDP);
|
||||
}
|
||||
@ -809,8 +809,8 @@ pfxlist_onlink_check()
|
||||
{
|
||||
struct nd_prefix *pr;
|
||||
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next)
|
||||
if (pr->ndpr_advrtrs.lh_first) /* pr has an available router */
|
||||
LIST_FOREACH(pr, &nd_prefix, ndpr_entry)
|
||||
if (!LIST_EMPTY(&pr->ndpr_advrtrs)) /* pr has an available router */
|
||||
break;
|
||||
|
||||
if (pr) {
|
||||
@ -821,21 +821,21 @@ pfxlist_onlink_check()
|
||||
* attached prefix and a detached prefix may have a same
|
||||
* interface route.
|
||||
*/
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
|
||||
if (pr->ndpr_advrtrs.lh_first == NULL &&
|
||||
LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
|
||||
if (LIST_EMPTY(&pr->ndpr_advrtrs) &&
|
||||
pr->ndpr_statef_onlink) {
|
||||
pr->ndpr_statef_onlink = 0;
|
||||
nd6_detach_prefix(pr);
|
||||
}
|
||||
}
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
|
||||
if (pr->ndpr_advrtrs.lh_first &&
|
||||
LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
|
||||
if (!LIST_EMPTY(&pr->ndpr_advrtrs) &&
|
||||
pr->ndpr_statef_onlink == 0)
|
||||
nd6_attach_prefix(pr);
|
||||
}
|
||||
} else {
|
||||
/* there is no prefix that has a router */
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next)
|
||||
LIST_FOREACH(pr, &nd_prefix, ndpr_entry)
|
||||
if (pr->ndpr_statef_onlink == 0)
|
||||
nd6_attach_prefix(pr);
|
||||
}
|
||||
@ -993,7 +993,7 @@ in6_ifadd(ifp, in6, addr, prefixlen)
|
||||
in6_ifaddr = ia;
|
||||
|
||||
/* link to if_addrlist */
|
||||
if (ifp->if_addrlist.tqh_first != NULL) {
|
||||
if (!TAILQ_EMPTY(&ifp->if_addrlist)) {
|
||||
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
|
||||
ifa_list);
|
||||
}
|
||||
|
@ -64,8 +64,6 @@
|
||||
* @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -94,14 +92,12 @@
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#ifdef INET6
|
||||
#include <netinet6/ipsec6.h>
|
||||
#endif /* INET6 */
|
||||
#endif /*IPSEC*/
|
||||
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
/* #include "faith.h" */
|
||||
#include "faith.h"
|
||||
|
||||
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
|
||||
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
|
||||
|
835
sys/netinet6/udp6_usrreq.c
Normal file
835
sys/netinet6/udp6_usrreq.c
Normal file
@ -0,0 +1,835 @@
|
||||
/*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#include <netinet6/ip6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/in6_pcb.h>
|
||||
#include <netinet6/icmp6.h>
|
||||
#include <netinet6/udp6_var.h>
|
||||
#include <netinet6/ip6protosw.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#endif /*IPSEC*/
|
||||
|
||||
#include "faith.h"
|
||||
|
||||
/*
|
||||
* UDP protocol inplementation.
|
||||
* Per RFC 768, August, 1980.
|
||||
*/
|
||||
|
||||
extern struct protosw inetsw[];
|
||||
static int in6_mcmatch __P((struct inpcb *, struct in6_addr *, struct ifnet *));
|
||||
static int udp6_detach __P((struct socket *so));
|
||||
|
||||
static int
|
||||
in6_mcmatch(in6p, ia6, ifp)
|
||||
struct inpcb *in6p;
|
||||
register struct in6_addr *ia6;
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct ip6_moptions *im6o = in6p->in6p_moptions;
|
||||
struct in6_multi_mship *imm;
|
||||
|
||||
if (im6o == NULL)
|
||||
return 0;
|
||||
|
||||
for (imm = im6o->im6o_memberships.lh_first; imm != NULL;
|
||||
imm = imm->i6mm_chain.le_next) {
|
||||
if ((ifp == NULL ||
|
||||
imm->i6mm_maddr->in6m_ifp == ifp) &&
|
||||
IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
|
||||
ia6))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
udp6_input(mp, offp, proto)
|
||||
struct mbuf **mp;
|
||||
int *offp, proto;
|
||||
{
|
||||
struct mbuf *m = *mp;
|
||||
register struct ip6_hdr *ip6;
|
||||
register struct udphdr *uh;
|
||||
register struct inpcb *in6p;
|
||||
struct mbuf *opts = 0;
|
||||
int off = *offp;
|
||||
int plen, ulen;
|
||||
struct sockaddr_in6 udp_in6;
|
||||
|
||||
#if defined(NFAITH) && 0 < NFAITH
|
||||
if (m->m_pkthdr.rcvif) {
|
||||
if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
|
||||
/* XXX send icmp6 host/port unreach? */
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
udpstat.udps_ipackets++;
|
||||
|
||||
IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6);
|
||||
uh = (struct udphdr *)((caddr_t)ip6 + off);
|
||||
ulen = ntohs((u_short)uh->uh_ulen);
|
||||
|
||||
if (plen != ulen) {
|
||||
udpstat.udps_badlen++;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checksum extended UDP header and data.
|
||||
*/
|
||||
if (uh->uh_sum == 0)
|
||||
udpstat.udps_nosum++;
|
||||
else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
|
||||
udpstat.udps_badsum++;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
struct inpcb *last;
|
||||
|
||||
/*
|
||||
* Deliver a multicast datagram to all sockets
|
||||
* for which the local and remote addresses and ports match
|
||||
* those of the incoming datagram. This allows more than
|
||||
* one process to receive multicasts on the same port.
|
||||
* (This really ought to be done for unicast datagrams as
|
||||
* well, but that would cause problems with existing
|
||||
* applications that open both address-specific sockets and
|
||||
* a wildcard socket listening to the same port -- they would
|
||||
* end up receiving duplicates of every unicast datagram.
|
||||
* Those applications open the multiple sockets to overcome an
|
||||
* inadequacy of the UDP socket interface, but for backwards
|
||||
* compatibility we avoid the problem here rather than
|
||||
* fixing the interface. Maybe 4.5BSD will remedy this?)
|
||||
*/
|
||||
|
||||
/*
|
||||
* In a case that laddr should be set to the link-local
|
||||
* address (this happens in RIPng), the multicast address
|
||||
* specified in the received packet does not match with
|
||||
* laddr. To cure this situation, the matching is relaxed
|
||||
* if the receiving interface is the same as one specified
|
||||
* in the socket and if the destination multicast address
|
||||
* matches one of the multicast groups specified in the socket.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Construct sockaddr format source address.
|
||||
*/
|
||||
init_sin6(&udp_in6, m); /* general init */
|
||||
udp_in6.sin6_port = uh->uh_sport;
|
||||
/*
|
||||
* KAME note: usually we drop udphdr from mbuf here.
|
||||
* We need udphdr for IPsec processing so we do that later.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Locate pcb(s) for datagram.
|
||||
* (Algorithm copied from raw_intr().)
|
||||
*/
|
||||
last = NULL;
|
||||
LIST_FOREACH(in6p, &udb, inp_list) {
|
||||
if ((in6p->inp_vflag & INP_IPV6) == NULL)
|
||||
continue;
|
||||
if (in6p->in6p_lport != uh->uh_dport)
|
||||
continue;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
|
||||
&ip6->ip6_dst) &&
|
||||
!in6_mcmatch(in6p, &ip6->ip6_dst,
|
||||
m->m_pkthdr.rcvif))
|
||||
continue;
|
||||
}
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
|
||||
&ip6->ip6_src) ||
|
||||
in6p->in6p_fport != uh->uh_sport)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (last != NULL) {
|
||||
struct mbuf *n;
|
||||
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if (last != NULL &&
|
||||
ipsec6_in_reject_so(m, last->inp_socket)) {
|
||||
ipsec6stat.in_polvio++;
|
||||
/* do not inject data into pcb */
|
||||
} else
|
||||
#endif /*IPSEC*/
|
||||
if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
|
||||
/*
|
||||
* KAME NOTE: do not
|
||||
* m_copy(m, offset, ...) above.
|
||||
* sbappendaddr() expects M_PKTHDR,
|
||||
* and m_copy() will copy M_PKTHDR
|
||||
* only if offset is 0.
|
||||
*/
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| last->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
ip6_savecontrol(last, &opts,
|
||||
ip6, n);
|
||||
m_adj(n, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in6,
|
||||
n, opts) == 0) {
|
||||
m_freem(n);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
udpstat.udps_fullsock++;
|
||||
} else
|
||||
sorwakeup(last->in6p_socket);
|
||||
opts = 0;
|
||||
}
|
||||
}
|
||||
last = in6p;
|
||||
/*
|
||||
* Don't look for additional matches if this one does
|
||||
* not have either the SO_REUSEPORT or SO_REUSEADDR
|
||||
* socket options set. This heuristic avoids searching
|
||||
* through all pcbs in the common case of a non-shared
|
||||
* port. It assumes that an application will never
|
||||
* clear these options after setting them.
|
||||
*/
|
||||
if ((last->in6p_socket->so_options &
|
||||
(SO_REUSEPORT|SO_REUSEADDR)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (last == NULL) {
|
||||
/*
|
||||
* No matching pcb found; discard datagram.
|
||||
* (No need to send an ICMP Port Unreachable
|
||||
* for a broadcast or multicast datgram.)
|
||||
*/
|
||||
udpstat.udps_noport++;
|
||||
udpstat.udps_noportmcast++;
|
||||
goto bad;
|
||||
}
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if (last != NULL && ipsec6_in_reject_so(m, last->inp_socket)) {
|
||||
ipsec6stat.in_polvio++;
|
||||
goto bad;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| last->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
ip6_savecontrol(last, &opts, ip6, m);
|
||||
|
||||
m_adj(m, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in6,
|
||||
m, opts) == 0) {
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
sorwakeup(last->in6p_socket);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
/*
|
||||
* Locate pcb for datagram.
|
||||
*/
|
||||
in6p = in6_pcblookup_hash(&udbinfo, &ip6->ip6_src, uh->uh_sport,
|
||||
&ip6->ip6_dst, uh->uh_dport, 1,
|
||||
m->m_pkthdr.rcvif);
|
||||
if (in6p == 0) {
|
||||
if (log_in_vain) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
strcpy(buf, ip6_sprintf(&ip6->ip6_dst));
|
||||
log(LOG_INFO,
|
||||
"Connection attempt to UDP %s:%d from %s:%d\n",
|
||||
buf, ntohs(uh->uh_dport),
|
||||
ip6_sprintf(&ip6->ip6_src), ntohs(uh->uh_sport));
|
||||
}
|
||||
udpstat.udps_noport++;
|
||||
if (m->m_flags & M_MCAST) {
|
||||
printf("UDP6: M_MCAST is set in a unicast packet.\n");
|
||||
udpstat.udps_noportmcast++;
|
||||
goto bad;
|
||||
}
|
||||
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if (in6p != NULL && ipsec6_in_reject_so(m, in6p->in6p_socket)) {
|
||||
ipsec6stat.in_polvio++;
|
||||
goto bad;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
|
||||
/*
|
||||
* Construct sockaddr format source address.
|
||||
* Stuff source address and datagram in user buffer.
|
||||
*/
|
||||
init_sin6(&udp_in6, m); /* general init */
|
||||
udp_in6.sin6_port = uh->uh_sport;
|
||||
if (in6p->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| in6p->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
ip6_savecontrol(in6p, &opts, ip6, m);
|
||||
m_adj(m, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&in6p->in6p_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in6,
|
||||
m, opts) == 0) {
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
sorwakeup(in6p->in6p_socket);
|
||||
return IPPROTO_DONE;
|
||||
bad:
|
||||
if (m)
|
||||
m_freem(m);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
void
|
||||
udp6_ctlinput(cmd, sa, d)
|
||||
int cmd;
|
||||
struct sockaddr *sa;
|
||||
void *d;
|
||||
{
|
||||
register struct udphdr *uhp;
|
||||
struct udphdr uh;
|
||||
struct sockaddr_in6 sa6;
|
||||
struct ip6_hdr *ip6;
|
||||
struct mbuf *m;
|
||||
int off;
|
||||
|
||||
if (sa->sa_family != AF_INET6 ||
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
return;
|
||||
|
||||
if (!PRC_IS_REDIRECT(cmd) &&
|
||||
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
|
||||
return;
|
||||
|
||||
/* if the parameter is from icmp6, decode it. */
|
||||
if (d != NULL) {
|
||||
struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
|
||||
m = ip6cp->ip6c_m;
|
||||
ip6 = ip6cp->ip6c_ip6;
|
||||
off = ip6cp->ip6c_off;
|
||||
} else {
|
||||
m = NULL;
|
||||
ip6 = NULL;
|
||||
}
|
||||
|
||||
/* translate addresses into internal form */
|
||||
sa6 = *(struct sockaddr_in6 *)sa;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr))
|
||||
sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
|
||||
if (ip6) {
|
||||
/*
|
||||
* XXX: We assume that when IPV6 is non NULL,
|
||||
* M and OFF are valid.
|
||||
*/
|
||||
struct in6_addr s;
|
||||
|
||||
/* translate addresses into internal form */
|
||||
memcpy(&s, &ip6->ip6_src, sizeof(s));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&s))
|
||||
s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
|
||||
if (m->m_len < off + sizeof(uh)) {
|
||||
/*
|
||||
* this should be rare case,
|
||||
* so we compromise on this copy...
|
||||
*/
|
||||
m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
|
||||
uhp = &uh;
|
||||
} else
|
||||
uhp = (struct udphdr *)(mtod(m, caddr_t) + off);
|
||||
(void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6,
|
||||
uhp->uh_dport, &s,
|
||||
uhp->uh_sport, cmd, udp_notify);
|
||||
} else
|
||||
(void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6, 0,
|
||||
&zeroin6_addr, 0, cmd, udp_notify);
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_getcred SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
struct sockaddr_in6 addrs[2];
|
||||
struct inpcb *inp;
|
||||
int error, s;
|
||||
|
||||
error = suser(req->p);
|
||||
if (error)
|
||||
return (error);
|
||||
error = SYSCTL_IN(req, addrs, sizeof(addrs));
|
||||
if (error)
|
||||
return (error);
|
||||
s = splnet();
|
||||
inp = in6_pcblookup_hash(&udbinfo, &addrs[1].sin6_addr,
|
||||
addrs[1].sin6_port,
|
||||
&addrs[0].sin6_addr, addrs[0].sin6_port,
|
||||
1, NULL);
|
||||
if (!inp || !inp->inp_socket || !inp->inp_socket->so_cred) {
|
||||
error = ENOENT;
|
||||
goto out;
|
||||
}
|
||||
error = SYSCTL_OUT(req, inp->inp_socket->so_cred,
|
||||
sizeof(struct ucred));
|
||||
|
||||
out:
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
|
||||
0, 0,
|
||||
udp6_getcred, "S,ucred", "Get the ucred of a UDP6 connection");
|
||||
|
||||
int
|
||||
udp6_output(in6p, m, addr6, control, p)
|
||||
register struct inpcb *in6p;
|
||||
register struct mbuf *m;
|
||||
struct sockaddr *addr6;
|
||||
struct mbuf *control;
|
||||
struct proc *p;
|
||||
{
|
||||
register int ulen = m->m_pkthdr.len;
|
||||
int plen = sizeof(struct udphdr) + ulen;
|
||||
struct ip6_hdr *ip6;
|
||||
struct udphdr *udp6;
|
||||
struct in6_addr laddr6;
|
||||
int s = 0, error = 0;
|
||||
struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts;
|
||||
|
||||
if (control) {
|
||||
if ((error = ip6_setpktoptions(control, &opt, suser(p))) != 0)
|
||||
goto release;
|
||||
in6p->in6p_outputopts = &opt;
|
||||
}
|
||||
|
||||
if (addr6) {
|
||||
laddr6 = in6p->in6p_laddr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
|
||||
error = EISCONN;
|
||||
goto release;
|
||||
}
|
||||
/*
|
||||
* Must block input while temporarily connected.
|
||||
*/
|
||||
s = splnet();
|
||||
/*
|
||||
* XXX: the user might want to overwrite the local address
|
||||
* via an ancillary data.
|
||||
*/
|
||||
bzero(&in6p->in6p_laddr, sizeof(struct in6_addr));
|
||||
error = in6_pcbconnect(in6p, addr6, p);
|
||||
if (error) {
|
||||
splx(s);
|
||||
goto release;
|
||||
}
|
||||
} else {
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
|
||||
error = ENOTCONN;
|
||||
goto release;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Calculate data length and get a mbuf
|
||||
* for UDP and IP6 headers.
|
||||
*/
|
||||
M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr),
|
||||
M_DONTWAIT);
|
||||
if (m == 0) {
|
||||
error = ENOBUFS;
|
||||
if (addr6)
|
||||
splx(s);
|
||||
goto release;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff checksum and output datagram.
|
||||
*/
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
|
||||
ip6->ip6_vfc = IPV6_VERSION;
|
||||
/* ip6_plen will be filled in ip6_output. */
|
||||
ip6->ip6_nxt = IPPROTO_UDP;
|
||||
ip6->ip6_hlim = in6_selecthlim(in6p,
|
||||
in6p->in6p_route.ro_rt ?
|
||||
in6p->in6p_route.ro_rt->rt_ifp :
|
||||
NULL);
|
||||
ip6->ip6_src = in6p->in6p_laddr;
|
||||
ip6->ip6_dst = in6p->in6p_faddr;
|
||||
|
||||
udp6 = (struct udphdr *)(ip6 + 1);
|
||||
udp6->uh_sport = in6p->in6p_lport;
|
||||
udp6->uh_dport = in6p->in6p_fport;
|
||||
udp6->uh_ulen = htons((u_short)plen);
|
||||
udp6->uh_sum = 0;
|
||||
|
||||
if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
|
||||
sizeof(struct ip6_hdr), plen)) == 0) {
|
||||
udp6->uh_sum = 0xffff;
|
||||
}
|
||||
|
||||
udpstat.udps_opackets++;
|
||||
|
||||
#ifdef IPSEC
|
||||
m->m_pkthdr.rcvif = (struct ifnet *)in6p->in6p_socket;
|
||||
#endif /*IPSEC*/
|
||||
error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
|
||||
0, in6p->in6p_moptions, NULL);
|
||||
|
||||
if (addr6) {
|
||||
in6_pcbdisconnect(in6p);
|
||||
in6p->in6p_laddr = laddr6;
|
||||
splx(s);
|
||||
}
|
||||
goto releaseopt;
|
||||
|
||||
release:
|
||||
m_freem(m);
|
||||
|
||||
releaseopt:
|
||||
if (control) {
|
||||
in6p->in6p_outputopts = stickyopt;
|
||||
m_freem(control);
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_abort(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int s;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0)
|
||||
return EINVAL; /* ??? possible? panic instead? */
|
||||
soisdisconnected(so);
|
||||
s = splnet();
|
||||
in6_pcbdetach(inp);
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_attach(struct socket *so, int proto, struct proc *p)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int s, error;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
if (inp != 0)
|
||||
return EINVAL;
|
||||
|
||||
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
|
||||
error = soreserve(so, udp_sendspace, udp_recvspace);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
s = splnet();
|
||||
error = in_pcballoc(so, &udbinfo, p);
|
||||
splx(s);
|
||||
if (error)
|
||||
return error;
|
||||
inp = (struct inpcb *)so->so_pcb;
|
||||
inp->inp_vflag |= INP_IPV6;
|
||||
inp->in6p_hops = -1; /* use kernel default */
|
||||
inp->in6p_cksum = -1; /* just to be sure */
|
||||
#ifdef IPSEC
|
||||
error = ipsec_init_policy(so, &inp->in6p_sp);
|
||||
if (error != 0) {
|
||||
in6_pcbdetach(inp);
|
||||
return (error);
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int s, error;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0)
|
||||
return EINVAL;
|
||||
|
||||
inp->inp_vflag &= ~INP_IPV4;
|
||||
inp->inp_vflag |= INP_IPV6;
|
||||
if (ip6_mapped_addr_on && (inp->inp_flags & IN6P_BINDV6ONLY) == NULL) {
|
||||
struct sockaddr_in6 *sin6_p;
|
||||
|
||||
sin6_p = (struct sockaddr_in6 *)nam;
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr))
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
in6_sin6_2_sin(&sin, sin6_p);
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
inp->inp_vflag &= ~INP_IPV6;
|
||||
s = splnet();
|
||||
error = in_pcbbind(inp, (struct sockaddr *)&sin, p);
|
||||
splx(s);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
s = splnet();
|
||||
error = in6_pcbbind(inp, nam, p);
|
||||
splx(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int s, error;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0)
|
||||
return EINVAL;
|
||||
|
||||
if (ip6_mapped_addr_on) {
|
||||
struct sockaddr_in6 *sin6_p;
|
||||
|
||||
sin6_p = (struct sockaddr_in6 *)nam;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (inp->inp_faddr.s_addr != INADDR_ANY)
|
||||
return EISCONN;
|
||||
in6_sin6_2_sin(&sin, sin6_p);
|
||||
s = splnet();
|
||||
error = in_pcbconnect(inp, (struct sockaddr *)&sin, p);
|
||||
splx(s);
|
||||
if (error == NULL) {
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
inp->inp_vflag &= ~INP_IPV6;
|
||||
soisconnected(so);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
|
||||
return EISCONN;
|
||||
s = splnet();
|
||||
error = in6_pcbconnect(inp, nam, p);
|
||||
if (ip6_auto_flowlabel) {
|
||||
inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
|
||||
inp->in6p_flowinfo |=
|
||||
(htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
|
||||
}
|
||||
splx(s);
|
||||
if (error == NULL) {
|
||||
if (ip6_mapped_addr_on) { /* should be non mapped addr */
|
||||
inp->inp_vflag &= ~INP_IPV4;
|
||||
inp->inp_vflag |= INP_IPV6;
|
||||
}
|
||||
soisconnected(so);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_detach(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int s;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0)
|
||||
return EINVAL;
|
||||
s = splnet();
|
||||
in6_pcbdetach(inp);
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_disconnect(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
int s;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0)
|
||||
return EINVAL;
|
||||
|
||||
if (inp->inp_vflag & INP_IPV4) {
|
||||
struct pr_usrreqs *pru;
|
||||
|
||||
pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
|
||||
return ((*pru->pru_disconnect)(so));
|
||||
}
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
|
||||
return ENOTCONN;
|
||||
|
||||
s = splnet();
|
||||
in6_pcbdisconnect(inp);
|
||||
inp->in6p_laddr = in6addr_any;
|
||||
splx(s);
|
||||
so->so_state &= ~SS_ISCONNECTED; /* XXX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
udp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
|
||||
struct mbuf *control, struct proc *p)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0) {
|
||||
m_freem(m);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (ip6_mapped_addr_on) {
|
||||
int hasv4addr;
|
||||
struct sockaddr_in6 *sin6 = 0;
|
||||
|
||||
if (addr == 0)
|
||||
hasv4addr = (inp->inp_vflag & INP_IPV4);
|
||||
else {
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)
|
||||
? 1 : 0;
|
||||
}
|
||||
if (hasv4addr) {
|
||||
struct pr_usrreqs *pru;
|
||||
int error;
|
||||
|
||||
if (sin6)
|
||||
in6_sin6_2_sin_in_sock(addr);
|
||||
pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
|
||||
error = ((*pru->pru_send)(so, flags, m, addr, control,
|
||||
p));
|
||||
/* addr will just be freed in sendit(). */
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return udp6_output(inp, m, addr, control, p);
|
||||
}
|
||||
|
||||
struct pr_usrreqs udp6_usrreqs = {
|
||||
udp6_abort, pru_accept_notsupp, udp6_attach, udp6_bind, udp6_connect,
|
||||
pru_connect2_notsupp, in6_control, udp6_detach, udp6_disconnect,
|
||||
pru_listen_notsupp, in6_mapped_peeraddr, pru_rcvd_notsupp,
|
||||
pru_rcvoob_notsupp, udp6_send, pru_sense_null, udp_shutdown,
|
||||
in6_mapped_sockaddr, sosend, soreceive, sopoll
|
||||
};
|
@ -68,6 +68,8 @@
|
||||
#define _NETINET6_UDP6_VAR_H_
|
||||
|
||||
#ifdef KERNEL
|
||||
SYSCTL_DECL(_net_inet6_udp6);
|
||||
|
||||
extern struct pr_usrreqs udp6_usrreqs;
|
||||
|
||||
void udp6_ctlinput __P((int, struct sockaddr *, void *));
|
||||
|
@ -2,7 +2,7 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/12/93
|
||||
|
||||
PROG= netstat
|
||||
SRCS= if.c inet.c main.c mbuf.c mroute.c ipx.c route.c \
|
||||
SRCS= if.c inet.c inet6.c main.c mbuf.c mroute.c ipx.c route.c \
|
||||
unix.c atalk.c netgraph.c # iso.c ns.c tp_astring.c
|
||||
CFLAGS+=-Wall
|
||||
|
||||
@ -12,5 +12,6 @@ BINGRP= kmem
|
||||
BINMODE=2555
|
||||
DPADD= ${LIBKVM} ${LIBIPX} ${LIBNETGRAPH}
|
||||
LDADD= -lkvm -lipx -lnetgraph
|
||||
#CFLAGS+= -DINET6
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -78,6 +78,12 @@ static const char rcsid[] =
|
||||
static void sidewaysintpr __P((u_int, u_long));
|
||||
static void catchalarm __P((int));
|
||||
|
||||
#ifdef INET6
|
||||
char *netname6 __P((struct sockaddr_in6 *, struct in6_addr *));
|
||||
static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
|
||||
static int bdg_done;
|
||||
#endif
|
||||
|
||||
void
|
||||
bdg_stats(u_long dummy, char *name) /* print bridge statistics */
|
||||
{
|
||||
@ -94,6 +100,12 @@ bdg_stats(u_long dummy, char *name) /* print bridge statistics */
|
||||
mib[3] = PF_BDG ;
|
||||
if (sysctl(mib,4, &s,&slen,NULL,0)==-1)
|
||||
return ; /* no bridging */
|
||||
#ifdef INET6
|
||||
if (bdg_done != 0)
|
||||
return;
|
||||
else
|
||||
bdg_done = 1;
|
||||
#endif
|
||||
printf("-- Bridging statistics (%s) --\n", name) ;
|
||||
printf(
|
||||
"Name In Out Forward Drop Bcast Mcast Local Unknown\n");
|
||||
@ -116,15 +128,19 @@ bdg_stats(u_long dummy, char *name) /* print bridge statistics */
|
||||
* Print a description of the network interfaces.
|
||||
*/
|
||||
void
|
||||
intpr(interval, ifnetaddr)
|
||||
intpr(interval, ifnetaddr, pfunc)
|
||||
int interval;
|
||||
u_long ifnetaddr;
|
||||
void (*pfunc)(char *);
|
||||
{
|
||||
struct ifnet ifnet;
|
||||
struct ifnethead ifnethead;
|
||||
union {
|
||||
struct ifaddr ifa;
|
||||
struct in_ifaddr in;
|
||||
#ifdef INET6
|
||||
struct in6_ifaddr in6;
|
||||
#endif
|
||||
struct ipx_ifaddr ipx;
|
||||
#ifdef NS
|
||||
struct ns_ifaddr ns;
|
||||
@ -153,6 +169,7 @@ intpr(interval, ifnetaddr)
|
||||
if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
|
||||
return;
|
||||
|
||||
if (!sflag && !pflag) {
|
||||
printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
|
||||
"Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
|
||||
if (bflag)
|
||||
@ -166,9 +183,13 @@ intpr(interval, ifnetaddr)
|
||||
if (dflag)
|
||||
printf(" %s", "Drop");
|
||||
putchar('\n');
|
||||
}
|
||||
ifaddraddr = 0;
|
||||
while (ifnetaddr || ifaddraddr) {
|
||||
struct sockaddr_in *sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
register char *cp;
|
||||
int n, m;
|
||||
|
||||
@ -183,6 +204,12 @@ intpr(interval, ifnetaddr)
|
||||
if (interface != 0 && (strcmp(name, interface) != 0))
|
||||
continue;
|
||||
cp = index(name, '\0');
|
||||
|
||||
if (pfunc) {
|
||||
(*pfunc)(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ifnet.if_flags&IFF_UP) == 0)
|
||||
*cp++ = '*';
|
||||
*cp = '\0';
|
||||
@ -225,6 +252,18 @@ intpr(interval, ifnetaddr)
|
||||
printf("%-15.15s ",
|
||||
routename(sin->sin_addr.s_addr));
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
printf("%-11.11s ",
|
||||
netname6(&ifaddr.in6.ia_addr,
|
||||
&ifaddr.in6.ia_prefixmask.sin6_addr));
|
||||
printf("%-17.17s ",
|
||||
(char *)inet_ntop(AF_INET6,
|
||||
&sin6->sin6_addr,
|
||||
ntop_buf, sizeof(ntop_buf)));
|
||||
break;
|
||||
#endif /*INET6*/
|
||||
case AF_IPX:
|
||||
{
|
||||
struct sockaddr_ipx *sipx =
|
||||
@ -266,10 +305,12 @@ intpr(interval, ifnetaddr)
|
||||
{
|
||||
struct sockaddr_dl *sdl =
|
||||
(struct sockaddr_dl *)sa;
|
||||
char linknum[10];
|
||||
cp = (char *)LLADDR(sdl);
|
||||
n = sdl->sdl_alen;
|
||||
sprintf(linknum, "<Link#%d>", sdl->sdl_index);
|
||||
m = printf("%-11.11s ", linknum);
|
||||
}
|
||||
m = printf("%-11.11s ", "<Link>");
|
||||
goto hexprint;
|
||||
default:
|
||||
m = printf("(%d)", sa->sa_family);
|
||||
@ -311,6 +352,9 @@ intpr(interval, ifnetaddr)
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 in6;
|
||||
#endif /* INET6 */
|
||||
struct sockaddr_dl dl;
|
||||
} msa;
|
||||
const char *fmt;
|
||||
@ -332,7 +376,15 @@ intpr(interval, ifnetaddr)
|
||||
case AF_INET:
|
||||
fmt = routename(msa.in.sin_addr.s_addr);
|
||||
break;
|
||||
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
printf("%23s %-19.19s(refs: %d)\n", "",
|
||||
inet_ntop(AF_INET6,
|
||||
&msa.in6.sin6_addr,
|
||||
ntop_buf,
|
||||
sizeof(ntop_buf)),
|
||||
ifma.ifma_refcount);
|
||||
#endif /* INET6 */
|
||||
case AF_LINK:
|
||||
switch (ifnet.if_type) {
|
||||
case IFT_ETHER:
|
||||
|
@ -50,6 +50,9 @@ static const char rcsid[] =
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#endif /* INET6 */
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
@ -65,6 +68,9 @@ static const char rcsid[] =
|
||||
#include <netinet/tcp_debug.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <err.h>
|
||||
@ -78,6 +84,10 @@ static const char rcsid[] =
|
||||
|
||||
char *inetname __P((struct in_addr *));
|
||||
void inetprint __P((struct in_addr *, int, char *, int));
|
||||
#ifdef INET6
|
||||
extern void inet6print __P((struct in6_addr *, int, char *, int));
|
||||
static int udp_done, tcp_done;
|
||||
#endif /* INET6 */
|
||||
|
||||
/*
|
||||
* Print a summary of connections related to an Internet
|
||||
@ -86,9 +96,10 @@ void inetprint __P((struct in_addr *, int, char *, int));
|
||||
* -a (all) flag is specified.
|
||||
*/
|
||||
void
|
||||
protopr(proto, name)
|
||||
protopr(proto, name, af)
|
||||
u_long proto; /* for sysctl version we pass proto # */
|
||||
char *name;
|
||||
int af;
|
||||
{
|
||||
int istcp;
|
||||
static int first = 1;
|
||||
@ -103,10 +114,22 @@ protopr(proto, name)
|
||||
istcp = 0;
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
#ifdef INET6
|
||||
if (tcp_done != 0)
|
||||
return;
|
||||
else
|
||||
tcp_done = 1;
|
||||
#endif
|
||||
istcp = 1;
|
||||
mibvar = "net.inet.tcp.pcblist";
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
#ifdef INET6
|
||||
if (udp_done != 0)
|
||||
return;
|
||||
else
|
||||
udp_done = 1;
|
||||
#endif
|
||||
mibvar = "net.inet.udp.pcblist";
|
||||
break;
|
||||
case IPPROTO_DIVERT:
|
||||
@ -153,7 +176,35 @@ protopr(proto, name)
|
||||
if (inp->inp_gencnt > oxig->xig_gen)
|
||||
continue;
|
||||
|
||||
if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
|
||||
if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
|
||||
#ifdef INET6
|
||||
|| (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
|
||||
#endif /* INET6 */
|
||||
|| (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
|
||||
#ifdef INET6
|
||||
&& (inp->inp_vflag &
|
||||
INP_IPV6) == 0
|
||||
#endif /* INET6 */
|
||||
))
|
||||
)
|
||||
continue;
|
||||
if (!aflag &&
|
||||
(
|
||||
(af == AF_INET &&
|
||||
inet_lnaof(inp->inp_laddr) == INADDR_ANY)
|
||||
#ifdef INET6
|
||||
|| (af == AF_INET6 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
|
||||
#endif /* INET6 */
|
||||
|| (af == AF_UNSPEC &&
|
||||
(((inp->inp_vflag & INP_IPV4) != 0 &&
|
||||
inet_lnaof(inp->inp_laddr) == INADDR_ANY)
|
||||
#ifdef INET6
|
||||
|| ((inp->inp_vflag & INP_IPV6) != 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
|
||||
#endif
|
||||
))
|
||||
))
|
||||
continue;
|
||||
|
||||
if (first) {
|
||||
@ -163,7 +214,9 @@ protopr(proto, name)
|
||||
putchar('\n');
|
||||
if (Aflag)
|
||||
printf("%-8.8s ", "Socket");
|
||||
printf("%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
|
||||
printf(Aflag ?
|
||||
"%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
|
||||
"%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
|
||||
"Proto", "Recv-Q", "Send-Q",
|
||||
"Local Address", "Foreign Address", "(state)");
|
||||
first = 0;
|
||||
@ -174,23 +227,61 @@ protopr(proto, name)
|
||||
else
|
||||
printf("%8lx ", (u_long)so->so_pcb);
|
||||
}
|
||||
printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc,
|
||||
printf("%-3.3s%s%s %6ld %6ld ", name,
|
||||
(inp->inp_vflag & INP_IPV4) ? "4" : "",
|
||||
#ifdef INET6
|
||||
(inp->inp_vflag & INP_IPV6) ? "6" :
|
||||
#endif
|
||||
"",
|
||||
so->so_rcv.sb_cc,
|
||||
so->so_snd.sb_cc);
|
||||
if (nflag) {
|
||||
if (inp->inp_vflag & INP_IPV4) {
|
||||
inetprint(&inp->inp_laddr, (int)inp->inp_lport,
|
||||
name, 1);
|
||||
inetprint(&inp->inp_faddr, (int)inp->inp_fport,
|
||||
name, 1);
|
||||
}
|
||||
#ifdef INET6
|
||||
else if (inp->inp_vflag & INP_IPV6) {
|
||||
inet6print(&inp->in6p_laddr,
|
||||
(int)inp->inp_lport, name, 1);
|
||||
inet6print(&inp->in6p_faddr,
|
||||
(int)inp->inp_fport, name, 1);
|
||||
} /* else nothing printed now */
|
||||
#endif /* INET6 */
|
||||
} else if (inp->inp_flags & INP_ANONPORT) {
|
||||
if (inp->inp_vflag & INP_IPV4) {
|
||||
inetprint(&inp->inp_laddr, (int)inp->inp_lport,
|
||||
name, 1);
|
||||
inetprint(&inp->inp_faddr, (int)inp->inp_fport,
|
||||
name, 0);
|
||||
}
|
||||
#ifdef INET6
|
||||
else if (inp->inp_vflag & INP_IPV6) {
|
||||
inet6print(&inp->in6p_laddr,
|
||||
(int)inp->inp_lport, name, 1);
|
||||
inet6print(&inp->in6p_faddr,
|
||||
(int)inp->inp_fport, name, 0);
|
||||
} /* else nothing printed now */
|
||||
#endif /* INET6 */
|
||||
} else {
|
||||
if (inp->inp_vflag & INP_IPV4) {
|
||||
inetprint(&inp->inp_laddr, (int)inp->inp_lport,
|
||||
name, 0);
|
||||
inetprint(&inp->inp_faddr, (int)inp->inp_fport,
|
||||
name, inp->inp_lport != inp->inp_fport);
|
||||
name,
|
||||
inp->inp_lport != inp->inp_fport);
|
||||
}
|
||||
#ifdef INET6
|
||||
else if (inp->inp_vflag & INP_IPV6) {
|
||||
inet6print(&inp->in6p_laddr,
|
||||
(int)inp->inp_lport, name, 0);
|
||||
inet6print(&inp->in6p_faddr,
|
||||
(int)inp->inp_fport, name,
|
||||
inp->inp_lport != inp->inp_fport);
|
||||
} /* else nothing printed now */
|
||||
#endif /* INET6 */
|
||||
}
|
||||
if (istcp) {
|
||||
if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
|
||||
@ -237,6 +328,13 @@ tcp_stats(off, name)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (tcp_done != 0)
|
||||
return;
|
||||
else
|
||||
tcp_done = 1;
|
||||
#endif
|
||||
|
||||
printf ("%s:\n", name);
|
||||
|
||||
#define p(f, m) if (tcpstat.f || sflag <= 1) \
|
||||
@ -331,6 +429,13 @@ udp_stats(off, name)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (udp_done != 0)
|
||||
return;
|
||||
else
|
||||
udp_done = 1;
|
||||
#endif
|
||||
|
||||
printf("%s:\n", name);
|
||||
#define p(f, m) if (udpstat.f || sflag <= 1) \
|
||||
printf(m, udpstat.f, plural(udpstat.f))
|
||||
@ -386,6 +491,7 @@ ip_stats(off, name)
|
||||
p(ips_badsum, "\t%lu bad header checksum%s\n");
|
||||
p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
|
||||
p1a(ips_tooshort, "\t%lu with data size < data length\n");
|
||||
p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
|
||||
p1a(ips_badhlen, "\t%lu with header length < data size\n");
|
||||
p1a(ips_badlen, "\t%lu with data length < header length\n");
|
||||
p1a(ips_badoptions, "\t%lu with bad options\n");
|
||||
@ -412,6 +518,7 @@ ip_stats(off, name)
|
||||
p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
|
||||
p(ips_ofragments, "\t%lu fragment%s created\n");
|
||||
p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
|
||||
p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
|
||||
#undef p
|
||||
#undef p1a
|
||||
}
|
||||
@ -541,6 +648,109 @@ igmp_stats(off, name)
|
||||
#undef py
|
||||
}
|
||||
|
||||
#ifdef IPSEC
|
||||
static char *ipsec_ahnames[] = {
|
||||
"none",
|
||||
"hmac MD5",
|
||||
"hmac SHA1",
|
||||
"keyed MD5",
|
||||
"keyed SHA1",
|
||||
"null",
|
||||
};
|
||||
|
||||
static char *ipsec_espnames[] = {
|
||||
"none",
|
||||
"DES CBC",
|
||||
"3DES CBC",
|
||||
"simple",
|
||||
"blowfish CBC",
|
||||
"CAST128 CBC",
|
||||
"RC5 CBC",
|
||||
};
|
||||
|
||||
/*
|
||||
* Dump IPSEC statistics structure.
|
||||
*/
|
||||
void
|
||||
ipsec_stats(off, name)
|
||||
u_long off;
|
||||
char *name;
|
||||
{
|
||||
struct ipsecstat ipsecstat;
|
||||
int first, proto;
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
printf ("%s:\n", name);
|
||||
kread(off, (char *)&ipsecstat, sizeof (ipsecstat));
|
||||
|
||||
#define p(f, m) if (ipsecstat.f || sflag <= 1) \
|
||||
printf(m, ipsecstat.f, plural(ipsecstat.f))
|
||||
|
||||
p(in_success, "\t%lu inbound packet%s processed successfully\n");
|
||||
p(in_polvio, "\t%lu inbound packet%s violated process security "
|
||||
"policy\n");
|
||||
p(in_nosa, "\t%lu inbound packet%s with no SA available\n");
|
||||
p(in_inval, "\t%lu inbound packet%s failed processing due to EINVAL\n");
|
||||
p(in_badspi, "\t%lu inbound packet%s failed getting SPI\n");
|
||||
p(in_ahreplay, "\t%lu inbound packet%s failed on AH replay check\n");
|
||||
p(in_espreplay, "\t%lu inbound packet%s failed on ESP replay check\n");
|
||||
p(in_ahauthsucc, "\t%lu inbound AH packet%s considered authentic\n");
|
||||
p(in_ahauthfail, "\t%lu inbound AH packet%s failed on authentication\n");
|
||||
p(in_espauthsucc, "\t%lu inbound ESP packet%s considered authentic\n");
|
||||
p(in_espauthfail, "\t%lu inbound ESP packet%s failed on authentication\n");
|
||||
for (first = 1, proto = 0; proto < SADB_AALG_MAX; proto++) {
|
||||
if (ipsecstat.in_ahhist[proto] <= 0)
|
||||
continue;
|
||||
if (first) {
|
||||
printf("\tAH input histogram:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t%s: %lu\n", ipsec_ahnames[proto],
|
||||
ipsecstat.in_ahhist[proto]);
|
||||
}
|
||||
for (first = 1, proto = 0; proto < SADB_EALG_MAX; proto++) {
|
||||
if (ipsecstat.in_esphist[proto] <= 0)
|
||||
continue;
|
||||
if (first) {
|
||||
printf("\tESP input histogram:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t%s: %lu\n", ipsec_espnames[proto],
|
||||
ipsecstat.in_esphist[proto]);
|
||||
}
|
||||
|
||||
p(out_success, "\t%lu outbound packet%s processed successfully\n");
|
||||
p(out_polvio, "\t%lu outbound packet%s violated process security "
|
||||
"policy\n");
|
||||
p(out_nosa, "\t%lu outbound packet%s with no SA available\n");
|
||||
p(out_inval, "\t%lu outbound packet%s failed processing due to "
|
||||
"EINVAL\n");
|
||||
p(out_noroute, "\t%lu outbound packet%s with no route\n");
|
||||
for (first = 1, proto = 0; proto < SADB_AALG_MAX; proto++) {
|
||||
if (ipsecstat.out_ahhist[proto] <= 0)
|
||||
continue;
|
||||
if (first) {
|
||||
printf("\tAH output histogram:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t%s: %lu\n", ipsec_ahnames[proto],
|
||||
ipsecstat.out_ahhist[proto]);
|
||||
}
|
||||
for (first = 1, proto = 0; proto < SADB_EALG_MAX; proto++) {
|
||||
if (ipsecstat.out_esphist[proto] <= 0)
|
||||
continue;
|
||||
if (first) {
|
||||
printf("\tESP output histogram:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t%s: %lu\n", ipsec_espnames[proto],
|
||||
ipsecstat.out_esphist[proto]);
|
||||
}
|
||||
#undef p
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
|
||||
/*
|
||||
* Pretty print an Internet address (net address + port).
|
||||
*/
|
||||
@ -553,6 +763,7 @@ inetprint(in, port, proto,numeric)
|
||||
{
|
||||
struct servent *sp = 0;
|
||||
char line[80], *cp;
|
||||
int width;
|
||||
|
||||
sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in));
|
||||
cp = index(line, '\0');
|
||||
@ -562,7 +773,8 @@ inetprint(in, port, proto,numeric)
|
||||
sprintf(cp, "%.15s", sp ? sp->s_name : "*");
|
||||
else
|
||||
sprintf(cp, "%d", ntohs((u_short)port));
|
||||
printf("%-21.21s ", line);
|
||||
width = Aflag ? 18 : 22;
|
||||
printf(" %-*.*s", width, width, line);
|
||||
}
|
||||
|
||||
/*
|
||||
|
962
usr.bin/netstat/inet6.c
Normal file
962
usr.bin/netstat/inet6.c
Normal file
@ -0,0 +1,962 @@
|
||||
/* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
|
||||
/*
|
||||
* Copyright (c) 1983, 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 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 lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)inet6.c 8.4 (Berkeley) 4/20/94";
|
||||
*/
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/protosw.h>
|
||||
|
||||
#include <net/route.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet6/in6_pcb.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/pim6_var.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "netstat.h"
|
||||
|
||||
struct socket sockb;
|
||||
|
||||
char *inet6name __P((struct in6_addr *));
|
||||
void inet6print __P((struct in6_addr *, int, char *, int));
|
||||
|
||||
static char ntop_buf[INET6_ADDRSTRLEN];
|
||||
|
||||
static char *ip6nh[] = {
|
||||
"hop by hop",
|
||||
"ICMP",
|
||||
"IGMP",
|
||||
"#3",
|
||||
"IP",
|
||||
"#5",
|
||||
"TCP",
|
||||
"#7",
|
||||
"#8",
|
||||
"#9",
|
||||
"#10",
|
||||
"#11",
|
||||
"#12",
|
||||
"#13",
|
||||
"#14",
|
||||
"#15",
|
||||
"#16",
|
||||
"UDP",
|
||||
"#18",
|
||||
"#19",
|
||||
"#20",
|
||||
"#21",
|
||||
"IDP",
|
||||
"#23",
|
||||
"#24",
|
||||
"#25",
|
||||
"#26",
|
||||
"#27",
|
||||
"#28",
|
||||
"TP",
|
||||
"#30",
|
||||
"#31",
|
||||
"#32",
|
||||
"#33",
|
||||
"#34",
|
||||
"#35",
|
||||
"#36",
|
||||
"#37",
|
||||
"#38",
|
||||
"#39",
|
||||
"#40",
|
||||
"IP6",
|
||||
"#42",
|
||||
"routing",
|
||||
"fragment",
|
||||
"#45",
|
||||
"#46",
|
||||
"#47",
|
||||
"#48",
|
||||
"#49",
|
||||
"ESP",
|
||||
"AH",
|
||||
"#52",
|
||||
"#53",
|
||||
"#54",
|
||||
"#55",
|
||||
"#56",
|
||||
"#57",
|
||||
"ICMP6",
|
||||
"no next header",
|
||||
"destination option",
|
||||
"#61",
|
||||
"#62",
|
||||
"#63",
|
||||
"#64",
|
||||
"#65",
|
||||
"#66",
|
||||
"#67",
|
||||
"#68",
|
||||
"#69",
|
||||
"#70",
|
||||
"#71",
|
||||
"#72",
|
||||
"#73",
|
||||
"#74",
|
||||
"#75",
|
||||
"#76",
|
||||
"#77",
|
||||
"#78",
|
||||
"#79",
|
||||
"ISOIP",
|
||||
"#81",
|
||||
"#82",
|
||||
"#83",
|
||||
"#84",
|
||||
"#85",
|
||||
"#86",
|
||||
"#87",
|
||||
"#88",
|
||||
"#89",
|
||||
"#80",
|
||||
"#91",
|
||||
"#92",
|
||||
"#93",
|
||||
"#94",
|
||||
"#95",
|
||||
"#96",
|
||||
"Ethernet",
|
||||
"#98",
|
||||
"#99",
|
||||
"#100",
|
||||
"#101",
|
||||
"#102",
|
||||
"PIM",
|
||||
"#104",
|
||||
"#105",
|
||||
"#106",
|
||||
"#107",
|
||||
"#108",
|
||||
"#109",
|
||||
"#110",
|
||||
"#111",
|
||||
"#112",
|
||||
"#113",
|
||||
"#114",
|
||||
"#115",
|
||||
"#116",
|
||||
"#117",
|
||||
"#118",
|
||||
"#119",
|
||||
"#120",
|
||||
"#121",
|
||||
"#122",
|
||||
"#123",
|
||||
"#124",
|
||||
"#125",
|
||||
"#126",
|
||||
"#127",
|
||||
"#128",
|
||||
"#129",
|
||||
"#130",
|
||||
"#131",
|
||||
"#132",
|
||||
"#133",
|
||||
"#134",
|
||||
"#135",
|
||||
"#136",
|
||||
"#137",
|
||||
"#138",
|
||||
"#139",
|
||||
"#140",
|
||||
"#141",
|
||||
"#142",
|
||||
"#143",
|
||||
"#144",
|
||||
"#145",
|
||||
"#146",
|
||||
"#147",
|
||||
"#148",
|
||||
"#149",
|
||||
"#150",
|
||||
"#151",
|
||||
"#152",
|
||||
"#153",
|
||||
"#154",
|
||||
"#155",
|
||||
"#156",
|
||||
"#157",
|
||||
"#158",
|
||||
"#159",
|
||||
"#160",
|
||||
"#161",
|
||||
"#162",
|
||||
"#163",
|
||||
"#164",
|
||||
"#165",
|
||||
"#166",
|
||||
"#167",
|
||||
"#168",
|
||||
"#169",
|
||||
"#170",
|
||||
"#171",
|
||||
"#172",
|
||||
"#173",
|
||||
"#174",
|
||||
"#175",
|
||||
"#176",
|
||||
"#177",
|
||||
"#178",
|
||||
"#179",
|
||||
"#180",
|
||||
"#181",
|
||||
"#182",
|
||||
"#183",
|
||||
"#184",
|
||||
"#185",
|
||||
"#186",
|
||||
"#187",
|
||||
"#188",
|
||||
"#189",
|
||||
"#180",
|
||||
"#191",
|
||||
"#192",
|
||||
"#193",
|
||||
"#194",
|
||||
"#195",
|
||||
"#196",
|
||||
"#197",
|
||||
"#198",
|
||||
"#199",
|
||||
"#200",
|
||||
"#201",
|
||||
"#202",
|
||||
"#203",
|
||||
"#204",
|
||||
"#205",
|
||||
"#206",
|
||||
"#207",
|
||||
"#208",
|
||||
"#209",
|
||||
"#210",
|
||||
"#211",
|
||||
"#212",
|
||||
"#213",
|
||||
"#214",
|
||||
"#215",
|
||||
"#216",
|
||||
"#217",
|
||||
"#218",
|
||||
"#219",
|
||||
"#220",
|
||||
"#221",
|
||||
"#222",
|
||||
"#223",
|
||||
"#224",
|
||||
"#225",
|
||||
"#226",
|
||||
"#227",
|
||||
"#228",
|
||||
"#229",
|
||||
"#230",
|
||||
"#231",
|
||||
"#232",
|
||||
"#233",
|
||||
"#234",
|
||||
"#235",
|
||||
"#236",
|
||||
"#237",
|
||||
"#238",
|
||||
"#239",
|
||||
"#240",
|
||||
"#241",
|
||||
"#242",
|
||||
"#243",
|
||||
"#244",
|
||||
"#245",
|
||||
"#246",
|
||||
"#247",
|
||||
"#248",
|
||||
"#249",
|
||||
"#250",
|
||||
"#251",
|
||||
"#252",
|
||||
"#253",
|
||||
"#254",
|
||||
"#255",
|
||||
};
|
||||
|
||||
/*
|
||||
* Dump IP6 statistics structure.
|
||||
*/
|
||||
void
|
||||
ip6_stats(off, name)
|
||||
u_long off;
|
||||
char *name;
|
||||
{
|
||||
struct ip6stat ip6stat;
|
||||
int first, i;
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
|
||||
kread(off, (char *)&ip6stat, sizeof (ip6stat));
|
||||
printf("%s:\n", name);
|
||||
|
||||
#define p(f, m) if (ip6stat.f || sflag <= 1) \
|
||||
printf(m, ip6stat.f, plural(ip6stat.f))
|
||||
#define p1a(f, m) if (ip6stat.f || sflag <= 1) \
|
||||
printf(m, ip6stat.f)
|
||||
|
||||
p(ip6s_total, "\t%lu total packet%s received\n");
|
||||
p1a(ip6s_toosmall, "\t%lu with size smaller than minimum\n");
|
||||
p1a(ip6s_tooshort, "\t%lu with data size < data length\n");
|
||||
p1a(ip6s_badoptions, "\t%lu with bad options\n");
|
||||
p1a(ip6s_badvers, "\t%lu with incorrect version number\n");
|
||||
p(ip6s_fragments, "\t%lu fragment%s received\n");
|
||||
p(ip6s_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
|
||||
p(ip6s_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
|
||||
p(ip6s_fragoverflow, "\t%lu fragment%s that exceeded limit\n");
|
||||
p(ip6s_reassembled, "\t%lu packet%s reassembled ok\n");
|
||||
p(ip6s_delivered, "\t%lu packet%s for this host\n");
|
||||
p(ip6s_forward, "\t%lu packet%s forwarded\n");
|
||||
p(ip6s_cantforward, "\t%lu packet%s not forwardable\n");
|
||||
p(ip6s_redirectsent, "\t%lu redirect%s sent\n");
|
||||
p(ip6s_localout, "\t%lu packet%s sent from this host\n");
|
||||
p(ip6s_rawout, "\t%lu packet%s sent with fabricated ip header\n");
|
||||
p(ip6s_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n");
|
||||
p(ip6s_noroute, "\t%lu output packet%s discarded due to no route\n");
|
||||
p(ip6s_fragmented, "\t%lu output datagram%s fragmented\n");
|
||||
p(ip6s_ofragments, "\t%lu fragment%s created\n");
|
||||
p(ip6s_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
|
||||
p(ip6s_badscope, "\t%lu packet%s that violated scope rules\n");
|
||||
p(ip6s_notmember, "\t%lu multicast packet%s which we don't join\n");
|
||||
for (first = 1, i = 0; i < 256; i++)
|
||||
if (ip6stat.ip6s_nxthist[i] != 0) {
|
||||
if (first) {
|
||||
printf("\tInput histogram:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t%s: %lu\n", ip6nh[i],
|
||||
ip6stat.ip6s_nxthist[i]);
|
||||
}
|
||||
printf("\tMbuf statistics:\n");
|
||||
printf("\t\t%lu one mbuf\n", ip6stat.ip6s_m1);
|
||||
for (first = 1, i = 0; i < 32; i++) {
|
||||
if (ip6stat.ip6s_m2m[i] != 0) {
|
||||
if (first) {
|
||||
printf("\t\ttwo or more mbuf:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t\t"
|
||||
#ifdef notyet
|
||||
"%s"
|
||||
#else
|
||||
"if%d"
|
||||
#endif
|
||||
"= %ld\n",
|
||||
#ifdef notyet
|
||||
if_indextoname(i, ifbuf),
|
||||
#else
|
||||
i,
|
||||
#endif
|
||||
ip6stat.ip6s_m2m[i]);
|
||||
}
|
||||
}
|
||||
printf("\t\t%lu one ext mbuf\n", ip6stat.ip6s_mext1);
|
||||
printf("\t\t%lu two or more ext mbuf\n", ip6stat.ip6s_mext2m);
|
||||
p(ip6s_exthdrtoolong, "\t%lu packet%s whose headers are not continuous\n");
|
||||
p(ip6s_nogif, "\t%lu tunneling packet%s that can't find gif\n");
|
||||
p(ip6s_toomanyhdr, "\t%lu packet%s discarded due to too may headers\n");
|
||||
#undef p
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump IPv6 per-interface statistics based on RFC 2465.
|
||||
*/
|
||||
void
|
||||
ip6_ifstats(ifname)
|
||||
char *ifname;
|
||||
{
|
||||
struct in6_ifreq ifr;
|
||||
int s;
|
||||
#define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
|
||||
printf(m, ifr.ifr_ifru.ifru_stat.f, plural(ifr.ifr_ifru.ifru_stat.f))
|
||||
#define p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
|
||||
printf(m, ip6stat.f)
|
||||
|
||||
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
|
||||
perror("Warning: socket(AF_INET6)");
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(ifr.ifr_name, ifname);
|
||||
printf("ip6 on %s:\n", ifr.ifr_name);
|
||||
|
||||
if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
|
||||
perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
|
||||
goto end;
|
||||
}
|
||||
|
||||
p(ifs6_in_receive, "\t%qu total input datagram%s\n");
|
||||
p(ifs6_in_hdrerr, "\t%qu datagram%s with invalid header received\n");
|
||||
p(ifs6_in_toobig, "\t%qu datagram%s exceeded MTU received\n");
|
||||
p(ifs6_in_noroute, "\t%qu datagram%s with no route received\n");
|
||||
p(ifs6_in_addrerr, "\t%qu datagram%s with invalid dst received\n");
|
||||
p(ifs6_in_protounknown, "\t%qu datagram%s with unknown proto received\n");
|
||||
p(ifs6_in_truncated, "\t%qu truncated datagram%s received\n");
|
||||
p(ifs6_in_discard, "\t%qu input datagram%s discarded\n");
|
||||
p(ifs6_in_deliver,
|
||||
"\t%qu datagram%s delivered to an upper layer protocol\n");
|
||||
p(ifs6_out_forward, "\t%qu datagram%s forwarded to this interface\n");
|
||||
p(ifs6_out_request,
|
||||
"\t%qu datagram%s sent from an upper layer protocol\n");
|
||||
p(ifs6_out_discard, "\t%qu total discarded output datagram%s\n");
|
||||
p(ifs6_out_fragok, "\t%qu output datagram%s fragmented\n");
|
||||
p(ifs6_out_fragfail, "\t%qu output datagram%s failed on fragment\n");
|
||||
p(ifs6_out_fragcreat, "\t%qu output datagram%s succeeded on fragment\n");
|
||||
p(ifs6_reass_reqd, "\t%qu incoming datagram%s fragmented\n");
|
||||
p(ifs6_reass_ok, "\t%qu datagram%s reassembled\n");
|
||||
p(ifs6_reass_fail, "\t%qu datagram%s failed on reassembling\n");
|
||||
p(ifs6_in_mcast, "\t%qu multicast datagram%s received\n");
|
||||
p(ifs6_out_mcast, "\t%qu multicast datagram%s sent\n");
|
||||
|
||||
end:
|
||||
close(s);
|
||||
|
||||
#undef p
|
||||
#undef p_5
|
||||
}
|
||||
|
||||
static char *icmp6names[] = {
|
||||
"#0",
|
||||
"unreach",
|
||||
"packet too big",
|
||||
"time exceed",
|
||||
"parameter problem",
|
||||
"#5",
|
||||
"#6",
|
||||
"#7",
|
||||
"#8",
|
||||
"#9",
|
||||
"#10",
|
||||
"#11",
|
||||
"#12",
|
||||
"#13",
|
||||
"#14",
|
||||
"#15",
|
||||
"#16",
|
||||
"#17",
|
||||
"#18",
|
||||
"#19",
|
||||
"#20",
|
||||
"#21",
|
||||
"#22",
|
||||
"#23",
|
||||
"#24",
|
||||
"#25",
|
||||
"#26",
|
||||
"#27",
|
||||
"#28",
|
||||
"#29",
|
||||
"#30",
|
||||
"#31",
|
||||
"#32",
|
||||
"#33",
|
||||
"#34",
|
||||
"#35",
|
||||
"#36",
|
||||
"#37",
|
||||
"#38",
|
||||
"#39",
|
||||
"#40",
|
||||
"#41",
|
||||
"#42",
|
||||
"#43",
|
||||
"#44",
|
||||
"#45",
|
||||
"#46",
|
||||
"#47",
|
||||
"#48",
|
||||
"#49",
|
||||
"#50",
|
||||
"#51",
|
||||
"#52",
|
||||
"#53",
|
||||
"#54",
|
||||
"#55",
|
||||
"#56",
|
||||
"#57",
|
||||
"#58",
|
||||
"#59",
|
||||
"#60",
|
||||
"#61",
|
||||
"#62",
|
||||
"#63",
|
||||
"#64",
|
||||
"#65",
|
||||
"#66",
|
||||
"#67",
|
||||
"#68",
|
||||
"#69",
|
||||
"#70",
|
||||
"#71",
|
||||
"#72",
|
||||
"#73",
|
||||
"#74",
|
||||
"#75",
|
||||
"#76",
|
||||
"#77",
|
||||
"#78",
|
||||
"#79",
|
||||
"#80",
|
||||
"#81",
|
||||
"#82",
|
||||
"#83",
|
||||
"#84",
|
||||
"#85",
|
||||
"#86",
|
||||
"#87",
|
||||
"#88",
|
||||
"#89",
|
||||
"#80",
|
||||
"#91",
|
||||
"#92",
|
||||
"#93",
|
||||
"#94",
|
||||
"#95",
|
||||
"#96",
|
||||
"#97",
|
||||
"#98",
|
||||
"#99",
|
||||
"#100",
|
||||
"#101",
|
||||
"#102",
|
||||
"#103",
|
||||
"#104",
|
||||
"#105",
|
||||
"#106",
|
||||
"#107",
|
||||
"#108",
|
||||
"#109",
|
||||
"#110",
|
||||
"#111",
|
||||
"#112",
|
||||
"#113",
|
||||
"#114",
|
||||
"#115",
|
||||
"#116",
|
||||
"#117",
|
||||
"#118",
|
||||
"#119",
|
||||
"#120",
|
||||
"#121",
|
||||
"#122",
|
||||
"#123",
|
||||
"#124",
|
||||
"#125",
|
||||
"#126",
|
||||
"#127",
|
||||
"echo",
|
||||
"echo reply",
|
||||
"multicast listener query",
|
||||
"multicast listener report",
|
||||
"multicast listener done",
|
||||
"router solicitation",
|
||||
"router advertisment",
|
||||
"neighbor solicitation",
|
||||
"neighbor advertisment",
|
||||
"redirect",
|
||||
"router renumbering",
|
||||
"node information request",
|
||||
"node information reply",
|
||||
"#141",
|
||||
"#142",
|
||||
"#143",
|
||||
"#144",
|
||||
"#145",
|
||||
"#146",
|
||||
"#147",
|
||||
"#148",
|
||||
"#149",
|
||||
"#150",
|
||||
"#151",
|
||||
"#152",
|
||||
"#153",
|
||||
"#154",
|
||||
"#155",
|
||||
"#156",
|
||||
"#157",
|
||||
"#158",
|
||||
"#159",
|
||||
"#160",
|
||||
"#161",
|
||||
"#162",
|
||||
"#163",
|
||||
"#164",
|
||||
"#165",
|
||||
"#166",
|
||||
"#167",
|
||||
"#168",
|
||||
"#169",
|
||||
"#170",
|
||||
"#171",
|
||||
"#172",
|
||||
"#173",
|
||||
"#174",
|
||||
"#175",
|
||||
"#176",
|
||||
"#177",
|
||||
"#178",
|
||||
"#179",
|
||||
"#180",
|
||||
"#181",
|
||||
"#182",
|
||||
"#183",
|
||||
"#184",
|
||||
"#185",
|
||||
"#186",
|
||||
"#187",
|
||||
"#188",
|
||||
"#189",
|
||||
"#180",
|
||||
"#191",
|
||||
"#192",
|
||||
"#193",
|
||||
"#194",
|
||||
"#195",
|
||||
"#196",
|
||||
"#197",
|
||||
"#198",
|
||||
"#199",
|
||||
"#200",
|
||||
"#201",
|
||||
"#202",
|
||||
"#203",
|
||||
"#204",
|
||||
"#205",
|
||||
"#206",
|
||||
"#207",
|
||||
"#208",
|
||||
"#209",
|
||||
"#210",
|
||||
"#211",
|
||||
"#212",
|
||||
"#213",
|
||||
"#214",
|
||||
"#215",
|
||||
"#216",
|
||||
"#217",
|
||||
"#218",
|
||||
"#219",
|
||||
"#220",
|
||||
"#221",
|
||||
"#222",
|
||||
"#223",
|
||||
"#224",
|
||||
"#225",
|
||||
"#226",
|
||||
"#227",
|
||||
"#228",
|
||||
"#229",
|
||||
"#230",
|
||||
"#231",
|
||||
"#232",
|
||||
"#233",
|
||||
"#234",
|
||||
"#235",
|
||||
"#236",
|
||||
"#237",
|
||||
"#238",
|
||||
"#239",
|
||||
"#240",
|
||||
"#241",
|
||||
"#242",
|
||||
"#243",
|
||||
"#244",
|
||||
"#245",
|
||||
"#246",
|
||||
"#247",
|
||||
"#248",
|
||||
"#249",
|
||||
"#250",
|
||||
"#251",
|
||||
"#252",
|
||||
"#253",
|
||||
"#254",
|
||||
"#255",
|
||||
};
|
||||
|
||||
/*
|
||||
* Dump ICMP6 statistics.
|
||||
*/
|
||||
void
|
||||
icmp6_stats(off, name)
|
||||
u_long off;
|
||||
char *name;
|
||||
{
|
||||
struct icmp6stat icmp6stat;
|
||||
register int i, first;
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
kread(off, (char *)&icmp6stat, sizeof (icmp6stat));
|
||||
printf("%s:\n", name);
|
||||
|
||||
#define p(f, m) if (icmp6stat.f || sflag <= 1) \
|
||||
printf(m, icmp6stat.f, plural(icmp6stat.f))
|
||||
|
||||
p(icp6s_error, "\t%lu call%s to icmp_error\n");
|
||||
p(icp6s_canterror,
|
||||
"\t%lu error%s not generated because old message was icmp error or so\n");
|
||||
p(icp6s_toofreq,
|
||||
"\t%lu error%s not generated because rate limitation\n");
|
||||
for (first = 1, i = 0; i < 256; i++)
|
||||
if (icmp6stat.icp6s_outhist[i] != 0) {
|
||||
if (first) {
|
||||
printf("\tOutput histogram:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t%s: %lu\n", icmp6names[i],
|
||||
icmp6stat.icp6s_outhist[i]);
|
||||
}
|
||||
p(icp6s_badcode, "\t%lu message%s with bad code fields\n");
|
||||
p(icp6s_tooshort, "\t%lu message%s < minimum length\n");
|
||||
p(icp6s_checksum, "\t%lu bad checksum%s\n");
|
||||
p(icp6s_badlen, "\t%lu message%s with bad length\n");
|
||||
for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
|
||||
if (icmp6stat.icp6s_inhist[i] != 0) {
|
||||
if (first) {
|
||||
printf("\tInput histogram:\n");
|
||||
first = 0;
|
||||
}
|
||||
printf("\t\t%s: %lu\n", icmp6names[i],
|
||||
icmp6stat.icp6s_inhist[i]);
|
||||
}
|
||||
p(icp6s_reflect, "\t%lu message response%s generated\n");
|
||||
#undef p
|
||||
#undef p_5
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump ICMPv6 per-interface statistics based on RFC 2466.
|
||||
*/
|
||||
void
|
||||
icmp6_ifstats(ifname)
|
||||
char *ifname;
|
||||
{
|
||||
struct in6_ifreq ifr;
|
||||
int s;
|
||||
#define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
|
||||
printf(m, (u_quad_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
|
||||
|
||||
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
|
||||
perror("Warning: socket(AF_INET6)");
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(ifr.ifr_name, ifname);
|
||||
printf("icmp6 on %s:\n", ifr.ifr_name);
|
||||
|
||||
if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
|
||||
perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
|
||||
goto end;
|
||||
}
|
||||
|
||||
p(ifs6_in_msg, "\t%qu total input message%s\n");
|
||||
p(ifs6_in_error, "\t%qu total input error message%s\n");
|
||||
p(ifs6_in_dstunreach, "\t%qu input destination unreachable error%s\n");
|
||||
p(ifs6_in_adminprohib, "\t%qu input administratively prohibited error%s\n");
|
||||
p(ifs6_in_timeexceed, "\t%qu input time exceeded error%s\n");
|
||||
p(ifs6_in_paramprob, "\t%qu input parameter problem error%s\n");
|
||||
p(ifs6_in_pkttoobig, "\t%qu input packet too big error%s\n");
|
||||
p(ifs6_in_echo, "\t%qu input echo request%s\n");
|
||||
p(ifs6_in_echoreply, "\t%qu input echo reply%s\n");
|
||||
p(ifs6_in_routersolicit, "\t%qu input router solicitation%s\n");
|
||||
p(ifs6_in_routeradvert, "\t%qu input router advertisement%s\n");
|
||||
p(ifs6_in_neighborsolicit, "\t%qu input neighbor solicitation%s\n");
|
||||
p(ifs6_in_neighboradvert, "\t%qu input neighbor advertisement%s\n");
|
||||
p(ifs6_in_redirect, "\t%qu input redirect%s\n");
|
||||
p(ifs6_in_mldquery, "\t%qu input MLD query%s\n");
|
||||
p(ifs6_in_mldreport, "\t%qu input MLD report%s\n");
|
||||
p(ifs6_in_mlddone, "\t%qu input MLD done%s\n");
|
||||
|
||||
p(ifs6_out_msg, "\t%qu total output message%s\n");
|
||||
p(ifs6_out_error, "\t%qu total output error message%s\n");
|
||||
p(ifs6_out_dstunreach, "\t%qu output destination unreachable error%s\n");
|
||||
p(ifs6_out_adminprohib, "\t%qu output administratively prohibited error%s\n");
|
||||
p(ifs6_out_timeexceed, "\t%qu output time exceeded error%s\n");
|
||||
p(ifs6_out_paramprob, "\t%qu output parameter problem error%s\n");
|
||||
p(ifs6_out_pkttoobig, "\t%qu output packet too big error%s\n");
|
||||
p(ifs6_out_echo, "\t%qu output echo request%s\n");
|
||||
p(ifs6_out_echoreply, "\t%qu output echo reply%s\n");
|
||||
p(ifs6_out_routersolicit, "\t%qu output router solicitation%s\n");
|
||||
p(ifs6_out_routeradvert, "\t%qu output router advertisement%s\n");
|
||||
p(ifs6_out_neighborsolicit, "\t%qu output neighbor solicitation%s\n");
|
||||
p(ifs6_out_neighboradvert, "\t%qu output neighbor advertisement%s\n");
|
||||
p(ifs6_out_redirect, "\t%qu output redirect%s\n");
|
||||
p(ifs6_out_mldquery, "\t%qu output MLD query%s\n");
|
||||
p(ifs6_out_mldreport, "\t%qu output MLD report%s\n");
|
||||
p(ifs6_out_mlddone, "\t%qu output MLD done%s\n");
|
||||
|
||||
end:
|
||||
close(s);
|
||||
#undef p
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump PIM statistics structure.
|
||||
*/
|
||||
void
|
||||
pim6_stats(off, name)
|
||||
u_long off;
|
||||
char *name;
|
||||
{
|
||||
struct pim6stat pim6stat;
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
kread(off, (char *)&pim6stat, sizeof(pim6stat));
|
||||
printf("%s:\n", name);
|
||||
|
||||
#define p(f, m) if (pim6stat.f || sflag <= 1) \
|
||||
printf(m, pim6stat.f, plural(pim6stat.f))
|
||||
p(pim6s_rcv_total, "\t%u message%s received\n");
|
||||
p(pim6s_rcv_tooshort, "\t%u message%s received with too few bytes\n");
|
||||
p(pim6s_rcv_badsum, "\t%u message%s received with bad checksum\n");
|
||||
p(pim6s_rcv_badversion, "\t%u message%s received with bad version\n");
|
||||
p(pim6s_rcv_registers, "\t%u register%s received\n");
|
||||
p(pim6s_rcv_badregisters, "\t%u bad register%s received\n");
|
||||
p(pim6s_snd_registers, "\t%u register%s sent\n");
|
||||
#undef p
|
||||
}
|
||||
|
||||
/*
|
||||
* Pretty print an Internet address (net address + port).
|
||||
* If the nflag was specified, use numbers instead of names.
|
||||
*/
|
||||
#define GETSERVBYPORT6(port, proto, ret)\
|
||||
{\
|
||||
if (strcmp((proto), "tcp6") == 0)\
|
||||
(ret) = getservbyport((int)(port), "tcp");\
|
||||
else if (strcmp((proto), "udp6") == 0)\
|
||||
(ret) = getservbyport((int)(port), "udp");\
|
||||
else\
|
||||
(ret) = getservbyport((int)(port), (proto));\
|
||||
};
|
||||
|
||||
void
|
||||
inet6print(in6, port, proto, numeric)
|
||||
register struct in6_addr *in6;
|
||||
int port;
|
||||
char *proto;
|
||||
int numeric;
|
||||
{
|
||||
struct servent *sp = 0;
|
||||
char line[80], *cp;
|
||||
int width;
|
||||
|
||||
sprintf(line, "%.*s.", lflag ? 39 :
|
||||
(Aflag && !numeric) ? 12 : 16, inet6name(in6));
|
||||
cp = index(line, '\0');
|
||||
if (!numeric && port)
|
||||
GETSERVBYPORT6(port, proto, sp);
|
||||
if (sp || port == 0)
|
||||
sprintf(cp, "%.8s", sp ? sp->s_name : "*");
|
||||
else
|
||||
sprintf(cp, "%d", ntohs((u_short)port));
|
||||
width = lflag ? 45 : Aflag ? 18 : 22;
|
||||
printf(" %-*.*s", width, width, line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct an Internet address representation.
|
||||
* If the nflag has been supplied, give
|
||||
* numeric value, otherwise try for symbolic name.
|
||||
*/
|
||||
|
||||
char *
|
||||
inet6name(in6p)
|
||||
struct in6_addr *in6p;
|
||||
{
|
||||
register char *cp;
|
||||
static char line[50];
|
||||
struct hostent *hp;
|
||||
static char domain[MAXHOSTNAMELEN + 1];
|
||||
static int first = 1;
|
||||
|
||||
if (first && !nflag) {
|
||||
first = 0;
|
||||
if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
|
||||
(cp = index(domain, '.')))
|
||||
(void) strcpy(domain, cp + 1);
|
||||
else
|
||||
domain[0] = 0;
|
||||
}
|
||||
cp = 0;
|
||||
if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
|
||||
hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
|
||||
if (hp) {
|
||||
if ((cp = index(hp->h_name, '.')) &&
|
||||
!strcmp(cp + 1, domain))
|
||||
*cp = 0;
|
||||
cp = hp->h_name;
|
||||
}
|
||||
}
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(in6p))
|
||||
strcpy(line, "*");
|
||||
else if (cp)
|
||||
strcpy(line, cp);
|
||||
else
|
||||
sprintf(line, "%s",
|
||||
inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
|
||||
sizeof(ntop_buf)));
|
||||
return (line);
|
||||
}
|
@ -125,6 +125,26 @@ static struct nlist nl[] = {
|
||||
{ "_ddpcb"},
|
||||
#define N_NGSOCKS 27
|
||||
{ "_ngsocklist"},
|
||||
#define N_IP6STAT 28
|
||||
{ "_ip6stat" },
|
||||
#define N_ICMP6STAT 29
|
||||
{ "_icmp6stat" },
|
||||
#ifdef notyet
|
||||
#define N_IPSECSTAT 30
|
||||
{ "_ipsecstat" },
|
||||
#define N_IPSEC6STAT 31
|
||||
{ "_ipsec6stat" },
|
||||
#define N_PIM6STAT 32
|
||||
{ "_pim6stat" },
|
||||
#define N_MRT6PROTO 33
|
||||
{ "_ip6_mrtproto" },
|
||||
#define N_MRT6STAT 34
|
||||
{ "_mrt6stat" },
|
||||
#define N_MF6CTABLE 35
|
||||
{ "_mf6ctable" },
|
||||
#define N_MIF6TABLE 36
|
||||
{ "_mif6table" },
|
||||
#endif
|
||||
{ "" },
|
||||
};
|
||||
|
||||
@ -134,81 +154,116 @@ struct protox {
|
||||
u_char pr_wanted; /* 1 if wanted, 0 otherwise */
|
||||
void (*pr_cblocks)(); /* control blocks printing routine */
|
||||
void (*pr_stats)(); /* statistics printing routine */
|
||||
void (*pr_istats)(); /* per/if statistics printing routine */
|
||||
char *pr_name; /* well-known name */
|
||||
int pr_usesysctl; /* true if we use sysctl, not kvm */
|
||||
} protox[] = {
|
||||
{ -1, -1, 1, protopr,
|
||||
tcp_stats, "tcp", IPPROTO_TCP },
|
||||
tcp_stats, NULL, "tcp", IPPROTO_TCP },
|
||||
{ -1, -1, 1, protopr,
|
||||
udp_stats, "udp", IPPROTO_UDP },
|
||||
udp_stats, NULL, "udp", IPPROTO_UDP },
|
||||
{ -1, -1, 1, protopr,
|
||||
NULL, "divert", IPPROTO_DIVERT },
|
||||
NULL, NULL, "divert",IPPROTO_DIVERT },
|
||||
{ -1, -1, 1, protopr,
|
||||
ip_stats, "ip", IPPROTO_RAW },
|
||||
ip_stats, NULL, "ip", IPPROTO_RAW },
|
||||
{ -1, -1, 1, protopr,
|
||||
icmp_stats, "icmp", IPPROTO_ICMP },
|
||||
icmp_stats, NULL, "icmp", IPPROTO_ICMP },
|
||||
{ -1, -1, 1, protopr,
|
||||
igmp_stats, "igmp", IPPROTO_IGMP },
|
||||
igmp_stats, NULL, "igmp", IPPROTO_IGMP },
|
||||
#ifdef IPSEC
|
||||
{ -1, N_IPSECSTAT, 1, 0,
|
||||
ipsec_stats, NULL, "ipsec", 0},
|
||||
#endif
|
||||
{ -1, -1, 1, protopr,
|
||||
bdg_stats, "bdg", 1 /* bridging... */ },
|
||||
bdg_stats, NULL, "bdg", 1 /* bridging... */ },
|
||||
{ -1, -1, 0, 0,
|
||||
0, 0 }
|
||||
0, NULL, 0 }
|
||||
};
|
||||
|
||||
#ifdef INET6
|
||||
struct protox ip6protox[] = {
|
||||
{ -1, -1, 1, protopr,
|
||||
tcp_stats, NULL, "tcp", IPPROTO_TCP },
|
||||
{ -1, -1, 1, protopr,
|
||||
udp_stats, NULL, "udp", IPPROTO_UDP },
|
||||
{ -1, N_IP6STAT, 1, 0,
|
||||
ip6_stats, ip6_ifstats, "ip6", 0 },
|
||||
{ -1, N_ICMP6STAT, 1, 0,
|
||||
icmp6_stats, icmp6_ifstats, "icmp6",0 },
|
||||
#ifdef IPSEC
|
||||
{ -1, N_IPSEC6STAT, 1, 0,
|
||||
ipsec_stats, NULL, "ipsec6",0 },
|
||||
#endif
|
||||
#ifdef notyet
|
||||
{ -1, N_PIM6STAT, 1, 0,
|
||||
pim6_stats, NULL, "pim6", 0 },
|
||||
#endif
|
||||
{ -1, -1, 1, protopr,
|
||||
bdg_stats, NULL, "bdg", 1 /* bridging... */ },
|
||||
{ -1, -1, 0, 0,
|
||||
0, NULL, 0, 0 }
|
||||
};
|
||||
#endif /*INET6*/
|
||||
|
||||
struct protox atalkprotox[] = {
|
||||
{ N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
|
||||
ddp_stats, "ddp" },
|
||||
ddp_stats, NULL, "ddp" },
|
||||
{ -1, -1, 0, 0,
|
||||
0, 0 }
|
||||
0, NULL, 0 }
|
||||
};
|
||||
|
||||
struct protox netgraphprotox[] = {
|
||||
{ N_NGSOCKS, -1, 1, netgraphprotopr,
|
||||
NULL, "ctrl" },
|
||||
NULL, NULL, "ctrl" },
|
||||
{ N_NGSOCKS, -1, 1, netgraphprotopr,
|
||||
NULL, "data" },
|
||||
{ -1, -1, 0, 0,
|
||||
0, 0 }
|
||||
NULL, NULL, "data" },
|
||||
{ -1, NULL, 0, 0,
|
||||
0, NULL, 0 }
|
||||
};
|
||||
|
||||
struct protox ipxprotox[] = {
|
||||
{ N_IPX, N_IPXSTAT, 1, ipxprotopr,
|
||||
ipx_stats, "ipx", 0 },
|
||||
ipx_stats, NULL, "ipx", 0 },
|
||||
{ N_IPX, N_SPXSTAT, 1, ipxprotopr,
|
||||
spx_stats, "spx", 0 },
|
||||
spx_stats, NULL, "spx", 0 },
|
||||
{ -1, -1, 0, 0,
|
||||
0, 0, 0 }
|
||||
0, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
#ifdef NS
|
||||
struct protox nsprotox[] = {
|
||||
{ N_IDP, N_IDPSTAT, 1, nsprotopr,
|
||||
idp_stats, "idp" },
|
||||
idp_stats, NULL, "idp" },
|
||||
{ N_IDP, N_SPPSTAT, 1, nsprotopr,
|
||||
spp_stats, "spp" },
|
||||
spp_stats, NULL, "spp" },
|
||||
{ -1, N_NSERR, 1, 0,
|
||||
nserr_stats, "ns_err" },
|
||||
nserr_stats, NULL, "ns_err" },
|
||||
{ -1, -1, 0, 0,
|
||||
0, 0 }
|
||||
0, NULL, 0 }
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ISO
|
||||
struct protox isoprotox[] = {
|
||||
{ ISO_TP, N_TPSTAT, 1, iso_protopr,
|
||||
tp_stats, "tp" },
|
||||
tp_stats, NULL, "tp" },
|
||||
{ N_CLTP, N_CLTPSTAT, 1, iso_protopr,
|
||||
cltp_stats, "cltp" },
|
||||
cltp_stats, NULL, "cltp" },
|
||||
{ -1, N_CLNPSTAT, 1, 0,
|
||||
clnp_stats, "clnp"},
|
||||
clnp_stats, NULL, "clnp"},
|
||||
{ -1, N_ESISSTAT, 1, 0,
|
||||
esis_stats, "esis"},
|
||||
esis_stats, NULL, "esis"},
|
||||
{ -1, -1, 0, 0,
|
||||
0, 0 }
|
||||
0, NULL, 0 }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct protox *protoprotox[] = { protox, ipxprotox, atalkprotox,
|
||||
struct protox *protoprotox[] = {
|
||||
protox,
|
||||
#ifdef INET6
|
||||
ip6protox,
|
||||
#endif
|
||||
ipxprotox, atalkprotox,
|
||||
#ifdef NS
|
||||
nsprotox,
|
||||
#endif
|
||||
@ -230,13 +285,12 @@ main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register struct protoent *p;
|
||||
register struct protox *tp = NULL; /* for printing cblocks & stats */
|
||||
int ch;
|
||||
|
||||
af = AF_UNSPEC;
|
||||
|
||||
while ((ch = getopt(argc, argv, "Aabdf:ghI:iM:mN:np:rstuw:")) != -1)
|
||||
while ((ch = getopt(argc, argv, "Aabdf:ghI:liM:mN:np:rstuw:")) != -1)
|
||||
switch(ch) {
|
||||
case 'A':
|
||||
Aflag = 1;
|
||||
@ -260,6 +314,10 @@ main(argc, argv)
|
||||
af = AF_IPX;
|
||||
else if (strcmp(optarg, "inet") == 0)
|
||||
af = AF_INET;
|
||||
#ifdef INET6
|
||||
else if (strcmp(optarg, "inet6") == 0)
|
||||
af = AF_INET6;
|
||||
#endif /*INET6*/
|
||||
else if (strcmp(optarg, "unix") == 0)
|
||||
af = AF_UNIX;
|
||||
else if (strcmp(optarg, "atalk") == 0)
|
||||
@ -290,6 +348,9 @@ main(argc, argv)
|
||||
case 'i':
|
||||
iflag = 1;
|
||||
break;
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
break;
|
||||
case 'M':
|
||||
memf = optarg;
|
||||
break;
|
||||
@ -363,6 +424,11 @@ main(argc, argv)
|
||||
exit(0);
|
||||
}
|
||||
if (pflag) {
|
||||
if (iflag && tp->pr_istats) {
|
||||
kread(0, 0, 0);
|
||||
intpr(interval, nl[N_IFNET].n_value, tp->pr_istats);
|
||||
exit(0);
|
||||
}
|
||||
if (!tp->pr_stats) {
|
||||
printf("%s: no stats routine\n", tp->pr_name);
|
||||
exit(0);
|
||||
@ -391,8 +457,11 @@ main(argc, argv)
|
||||
*/
|
||||
#endif
|
||||
if (iflag) {
|
||||
if (af != AF_UNSPEC)
|
||||
goto protostat;
|
||||
|
||||
kread(0, 0, 0);
|
||||
intpr(interval, nl[N_IFNET].n_value);
|
||||
intpr(interval, nl[N_IFNET].n_value, NULL);
|
||||
exit(0);
|
||||
}
|
||||
if (rflag) {
|
||||
@ -405,27 +474,40 @@ main(argc, argv)
|
||||
}
|
||||
if (gflag) {
|
||||
kread(0, 0, 0);
|
||||
if (sflag)
|
||||
if (sflag) {
|
||||
if (af == AF_INET || af == AF_UNSPEC)
|
||||
mrt_stats(nl[N_MRTSTAT].n_value);
|
||||
else
|
||||
#ifdef INET6
|
||||
#ifdef notyet
|
||||
if (af == AF_INET6 || af == AF_UNSPEC)
|
||||
mrt6_stats(nl[N_MRT6STAT].n_value);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
if (af == AF_INET || af == AF_UNSPEC)
|
||||
mroutepr(nl[N_MFCTABLE].n_value,
|
||||
nl[N_VIFTABLE].n_value);
|
||||
#ifdef INET6
|
||||
#ifdef notyet
|
||||
if (af == AF_INET6 || af == AF_UNSPEC)
|
||||
mroute6pr(nl[N_MF6CTABLE].n_value,
|
||||
nl[N_MIF6TABLE].n_value);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
if (af == AF_INET || af == AF_UNSPEC) {
|
||||
setprotoent(1);
|
||||
setservent(1);
|
||||
/* ugh, this is O(MN) ... why do we do this? */
|
||||
while ((p = getprotoent())) {
|
||||
|
||||
protostat:
|
||||
kread(0, 0, 0);
|
||||
if (af == AF_INET || af == AF_UNSPEC)
|
||||
for (tp = protox; tp->pr_name; tp++)
|
||||
if (strcmp(tp->pr_name, p->p_name) == 0)
|
||||
break;
|
||||
if (tp->pr_name == 0 || tp->pr_wanted == 0)
|
||||
continue;
|
||||
printproto(tp, p->p_name);
|
||||
}
|
||||
endprotoent();
|
||||
}
|
||||
printproto(tp, tp->pr_name);
|
||||
#ifdef INET6
|
||||
if (af == AF_INET6 || af == AF_UNSPEC)
|
||||
for (tp = ip6protox; tp->pr_name; tp++)
|
||||
printproto(tp, tp->pr_name);
|
||||
#endif /*INET6*/
|
||||
if (af == AF_IPX || af == AF_UNSPEC) {
|
||||
kread(0, 0, 0);
|
||||
for (tp = ipxprotox; tp->pr_name; tp++)
|
||||
@ -466,16 +548,24 @@ printproto(tp, name)
|
||||
u_long off;
|
||||
|
||||
if (sflag) {
|
||||
if (iflag) {
|
||||
if (tp->pr_istats)
|
||||
intpr(interval, nl[N_IFNET].n_value,
|
||||
tp->pr_istats);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
pr = tp->pr_stats;
|
||||
off = tp->pr_usesysctl ? tp->pr_usesysctl
|
||||
: nl[tp->pr_sindex].n_value;
|
||||
}
|
||||
} else {
|
||||
pr = tp->pr_cblocks;
|
||||
off = tp->pr_usesysctl ? tp->pr_usesysctl
|
||||
: nl[tp->pr_index].n_value;
|
||||
}
|
||||
if (pr != NULL && (off || af != AF_UNSPEC))
|
||||
(*pr)(off, name);
|
||||
(*pr)(off, name, af);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -566,11 +656,11 @@ name2protox(name)
|
||||
* Try to find the name in the list of "well-known" names. If that
|
||||
* fails, check if name is an alias for an Internet protocol.
|
||||
*/
|
||||
if ((tp = knownname(name)))
|
||||
if ((tp = knownname(name)) != NULL)
|
||||
return (tp);
|
||||
|
||||
setprotoent(1); /* make protocol lookup cheaper */
|
||||
while ((p = getprotoent())) {
|
||||
while ((p = getprotoent()) != NULL) {
|
||||
/* assert: name not same as p->name */
|
||||
for (alias = p->p_aliases; *alias; alias++)
|
||||
if (strcmp(name, *alias) == 0) {
|
||||
|
@ -45,7 +45,7 @@
|
||||
.Op Fl M Ar core
|
||||
.Op Fl N Ar system
|
||||
.Nm netstat
|
||||
.Op Fl bdghimnrs
|
||||
.Op Fl bdghilmnrs
|
||||
.Op Fl f Ar address_family
|
||||
.Op Fl M Ar core
|
||||
.Op Fl N Ar system
|
||||
@ -59,6 +59,15 @@
|
||||
.Op Fl p Ar protocol
|
||||
.Op Fl M Ar core
|
||||
.Op Fl N Ar system
|
||||
.Nm netstat
|
||||
.Op Fl p Ar protocol
|
||||
.Op Fl i
|
||||
.Op Fl I Ar Interface
|
||||
.Nm netstat
|
||||
.Op Fl s
|
||||
.Op Fl f Ar address_family
|
||||
.Op Fl i
|
||||
.Op Fl I Ar Interface
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm netstat
|
||||
@ -77,6 +86,8 @@ interval specified,
|
||||
will continuously display the information regarding packet
|
||||
traffic on the configured network interfaces.
|
||||
The fourth form displays statistics about the named protocol.
|
||||
The fifth and sixth forms display per interface statistics for
|
||||
the specified protocol or address family.
|
||||
.Pp
|
||||
The options have the following meaning:
|
||||
.Bl -tag -width flag
|
||||
@ -112,6 +123,9 @@ are recognized:
|
||||
.Ar inet ,
|
||||
for
|
||||
.Dv AF_INET ,
|
||||
.Ar inet6 ,
|
||||
for
|
||||
.Dv AF_INET6 ,
|
||||
.Ar ipx ,
|
||||
for
|
||||
.Dv AF_IPX ,
|
||||
@ -148,6 +162,19 @@ Show information about the specified interface;
|
||||
used with a
|
||||
.Ar wait
|
||||
interval as described below.
|
||||
If the
|
||||
.Fl f Ar address_family
|
||||
option (with the
|
||||
.Fl s
|
||||
option) or the
|
||||
.Fl p Ar protocol
|
||||
option is present, show per-interface statistics on the
|
||||
.Ar interface
|
||||
for the specfied
|
||||
.Ar address_family
|
||||
or
|
||||
.Ar protocol,
|
||||
respectively.
|
||||
.It Fl i
|
||||
Show the state of interfaces which have been auto-configured
|
||||
(interfaces statically configured into a system, but not
|
||||
@ -158,6 +185,18 @@ options is also present, multicast addresses currently in use are shown
|
||||
for each Ethernet interface and for each IP interface address.
|
||||
Multicast addresses are shown on separate lines following the interface
|
||||
address with which they are associated.
|
||||
If the
|
||||
.Fl f Ar address_family
|
||||
option (with the
|
||||
.Fl s
|
||||
option) or the
|
||||
.Fl p Ar protocol
|
||||
option is present, show per-interface statistics on all interfaces
|
||||
for the specfied
|
||||
.Ar address_family
|
||||
or
|
||||
.Ar protocol,
|
||||
respectively.
|
||||
.It Fl M
|
||||
Extract values associated with the name list from the specified core
|
||||
instead of the default
|
||||
@ -199,6 +238,11 @@ to show protocol-cloned routes.
|
||||
When
|
||||
.Fl s
|
||||
is also present, show routing statistics instead.
|
||||
When
|
||||
.Fl l
|
||||
is also present,
|
||||
.Nm
|
||||
assumes more columns are there.
|
||||
.It Fl w Ar wait
|
||||
Show network interface statistics at intervals of
|
||||
.Ar wait
|
||||
@ -317,6 +361,8 @@ The
|
||||
.Nm netstat
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
.Pp
|
||||
IPv6 support was added by WIDE/KAME project.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /dev/kmem -compact
|
||||
.It Pa /kernel
|
||||
|
@ -42,6 +42,7 @@ int bflag; /* show i/f total bytes in/out */
|
||||
int dflag; /* show i/f dropped packets */
|
||||
int gflag; /* show group (multicast) routing or stats */
|
||||
int iflag; /* show interfaces */
|
||||
int lflag; /* show routing table with use and ref */
|
||||
int mflag; /* show memory stats */
|
||||
int nflag; /* show addresses numerically */
|
||||
int pflag; /* show given protocol */
|
||||
@ -61,21 +62,36 @@ char *plural __P((int));
|
||||
char *plurales __P((int));
|
||||
void trimdomain __P((char *));
|
||||
|
||||
void protopr __P((u_long, char *));
|
||||
void protopr __P((u_long, char *, int));
|
||||
void tcp_stats __P((u_long, char *));
|
||||
void udp_stats __P((u_long, char *));
|
||||
void ip_stats __P((u_long, char *));
|
||||
void icmp_stats __P((u_long, char *));
|
||||
void igmp_stats __P((u_long, char *));
|
||||
#ifdef IPSEC
|
||||
void ipsec_stats __P((u_long, char *));
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
void ip6_stats __P((u_long, char *));
|
||||
void ip6_ifstats __P((char *));
|
||||
void icmp6_stats __P((u_long, char *));
|
||||
void icmp6_ifstats __P((char *));
|
||||
#ifdef notyet
|
||||
void pim6_stats __P((u_long, char *));
|
||||
void mroute6pr __P((u_long, u_long));
|
||||
void mrt6_stats __P((u_long));
|
||||
#endif
|
||||
#endif /*INET6*/
|
||||
|
||||
void bdg_stats __P((u_long, char *));
|
||||
void protopr __P((u_long, char *));
|
||||
|
||||
void mbpr __P((void));
|
||||
|
||||
void hostpr __P((u_long, u_long));
|
||||
void impstats __P((u_long, u_long));
|
||||
|
||||
void intpr __P((int, u_long));
|
||||
void intpr __P((int, u_long, void (*) __P((char *))));
|
||||
|
||||
void pr_rthdr __P(());
|
||||
void pr_family __P((int));
|
||||
@ -108,8 +124,6 @@ void ddp_stats __P((u_long, char *));
|
||||
|
||||
void netgraphprotopr __P((u_long, char *));
|
||||
|
||||
void intpr __P((int, u_long));
|
||||
|
||||
void unixpr __P((void));
|
||||
|
||||
void esis_stats __P((u_long, char *));
|
||||
|
@ -61,6 +61,7 @@ static const char rcsid[] =
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -127,6 +128,11 @@ static void p_rtentry __P((struct rtentry *));
|
||||
static u_long forgemask __P((u_long));
|
||||
static void domask __P((char *, u_long, u_long));
|
||||
|
||||
#ifdef INET6
|
||||
char *routename6 __P((struct sockaddr_in6 *));
|
||||
char *netname6 __P((struct sockaddr_in6 *, struct in6_addr *));
|
||||
#endif /*INET6*/
|
||||
|
||||
/*
|
||||
* Print routing tables.
|
||||
*/
|
||||
@ -180,6 +186,11 @@ pr_family(af)
|
||||
case AF_INET:
|
||||
afname = "Internet";
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
afname = "Internet6";
|
||||
break;
|
||||
#endif /*INET6*/
|
||||
case AF_IPX:
|
||||
afname = "IPX";
|
||||
break;
|
||||
@ -211,8 +222,13 @@ pr_family(af)
|
||||
}
|
||||
|
||||
/* column widths; each followed by one space */
|
||||
#ifndef INET6
|
||||
#define WID_DST 18 /* width of destination column */
|
||||
#define WID_GW 18 /* width of gateway column */
|
||||
#else
|
||||
#define WID_DST (lflag ? 39 : (nflag ? 33: 18)) /* width of dest column */
|
||||
#define WID_GW (lflag ? 31 : (nflag ? 29 : 18)) /* width of gateway column */
|
||||
#endif /*INET6*/
|
||||
|
||||
/*
|
||||
* Print header for routing table columns.
|
||||
@ -222,10 +238,16 @@ pr_rthdr()
|
||||
{
|
||||
if (Aflag)
|
||||
printf("%-8.8s ","Address");
|
||||
if (lflag)
|
||||
printf("%-*.*s %-*.*s %-6.6s %6.6s%8.8s %8.8s %6s\n",
|
||||
WID_DST, WID_DST, "Destination",
|
||||
WID_GW, WID_GW, "Gateway",
|
||||
"Flags", "Refs", "Use", "Netif", "Expire");
|
||||
else
|
||||
printf("%-*.*s %-*.*s %-6.6s %8.8s %6s\n",
|
||||
WID_DST, WID_DST, "Destination",
|
||||
WID_GW, WID_GW, "Gateway",
|
||||
"Flags", "Netif", "Expire");
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
@ -379,8 +401,6 @@ np_rtentry(rtm)
|
||||
p_sockaddr(sa, NULL, 0, 36);
|
||||
else {
|
||||
p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
|
||||
if (sa->sa_len == 0)
|
||||
sa->sa_len = sizeof(long);
|
||||
sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
|
||||
p_sockaddr(sa, NULL, 0, 18);
|
||||
}
|
||||
@ -414,6 +434,35 @@ p_sockaddr(sa, mask, flags, width)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
|
||||
struct in6_addr *in6 = &sa6->sin6_addr;
|
||||
|
||||
/*
|
||||
* XXX: This is a special workaround for KAME kernels.
|
||||
* sin6_scope_id field of SA should be set in the future.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LINKLOCAL(in6) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
|
||||
/* XXX: override is ok? */
|
||||
sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
|
||||
*(u_short *)&in6->s6_addr[2] = 0;
|
||||
}
|
||||
|
||||
if (flags & RTF_HOST)
|
||||
cp = routename6(sa6);
|
||||
else if (mask)
|
||||
cp = netname6(sa6,
|
||||
&((struct sockaddr_in6 *)mask)->sin6_addr);
|
||||
else {
|
||||
cp = netname6(sa6, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /*INET6*/
|
||||
|
||||
case AF_IPX:
|
||||
{
|
||||
struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
|
||||
@ -539,6 +588,7 @@ p_rtentry(rt)
|
||||
p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, WID_DST);
|
||||
p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW);
|
||||
p_flags(rt->rt_flags, "%-6.6s ");
|
||||
if (lflag)
|
||||
printf("%6ld %8ld ", rt->rt_refcnt, rt->rt_use);
|
||||
if (rt->rt_ifp) {
|
||||
if (rt->rt_ifp != lastif) {
|
||||
@ -546,7 +596,7 @@ p_rtentry(rt)
|
||||
kread((u_long)ifnet.if_name, name, 16);
|
||||
lastif = rt->rt_ifp;
|
||||
snprintf(prettyname, sizeof prettyname,
|
||||
"%.6s%d", name, ifnet.if_unit);
|
||||
"%s%d", name, ifnet.if_unit);
|
||||
}
|
||||
printf("%8.8s", prettyname);
|
||||
if (rt->rt_rmx.rmx_expire) {
|
||||
@ -556,7 +606,10 @@ p_rtentry(rt)
|
||||
rt->rt_rmx.rmx_expire - time((time_t *)0)) > 0)
|
||||
printf(" %6d%s", (int)expire_time,
|
||||
rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
|
||||
else
|
||||
goto ifandkey;
|
||||
} else if (rt->rt_nodes[0].rn_dupedkey) {
|
||||
ifandkey:;
|
||||
printf(" =>");
|
||||
}
|
||||
|
||||
@ -679,6 +732,118 @@ netname(in, mask)
|
||||
return (line);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
char *
|
||||
netname6(sa6, mask)
|
||||
struct sockaddr_in6 *sa6;
|
||||
struct in6_addr *mask;
|
||||
{
|
||||
static char line[MAXHOSTNAMELEN + 1];
|
||||
u_char *p = (u_char *)mask;
|
||||
u_char *lim;
|
||||
int masklen, illegal = 0;
|
||||
#ifdef notyet
|
||||
int flag = NI_WITHSCOPEID;
|
||||
#endif
|
||||
|
||||
if (mask) {
|
||||
for (masklen = 0, lim = p + 16; p < lim; p++) {
|
||||
switch (*p) {
|
||||
case 0xff:
|
||||
masklen += 8;
|
||||
break;
|
||||
case 0xfe:
|
||||
masklen += 7;
|
||||
break;
|
||||
case 0xfc:
|
||||
masklen += 6;
|
||||
break;
|
||||
case 0xf8:
|
||||
masklen += 5;
|
||||
break;
|
||||
case 0xf0:
|
||||
masklen += 4;
|
||||
break;
|
||||
case 0xe0:
|
||||
masklen += 3;
|
||||
break;
|
||||
case 0xc0:
|
||||
masklen += 2;
|
||||
break;
|
||||
case 0x80:
|
||||
masklen += 1;
|
||||
break;
|
||||
case 0x00:
|
||||
break;
|
||||
default:
|
||||
illegal ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (illegal)
|
||||
fprintf(stderr, "illegal prefixlen\n");
|
||||
}
|
||||
else
|
||||
masklen = 128;
|
||||
|
||||
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
||||
return("default");
|
||||
|
||||
#ifdef notyet
|
||||
if (nflag)
|
||||
flag |= NI_NUMERICHOST;
|
||||
getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
|
||||
NULL, 0, flag);
|
||||
#else
|
||||
inet_ntop(AF_INET6, (void *)&sa6->sin6_addr, line, sizeof(line));
|
||||
#endif
|
||||
|
||||
if (nflag)
|
||||
sprintf(&line[strlen(line)], "/%d", masklen);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
char *
|
||||
routename6(sa6)
|
||||
struct sockaddr_in6 *sa6;
|
||||
{
|
||||
#ifdef notyet
|
||||
int flag = NI_WITHSCOPEID;
|
||||
|
||||
if (nflag)
|
||||
flag |= NI_NUMERICHOST;
|
||||
#else
|
||||
register char *cp;
|
||||
#endif
|
||||
static char line[MAXHOSTNAMELEN + 1];
|
||||
struct hostent *hp;
|
||||
|
||||
#ifdef notyet
|
||||
getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
|
||||
NULL, 0, flag);
|
||||
#else
|
||||
cp = 0;
|
||||
if (!nflag) {
|
||||
hp = gethostbyaddr((char *)&sa6->sin6_addr,
|
||||
sizeof(sa6->sin6_addr), AF_INET6);
|
||||
if (hp) {
|
||||
cp = hp->h_name;
|
||||
trimdomain(cp);
|
||||
}
|
||||
}
|
||||
if (cp) {
|
||||
strncpy(line, cp, sizeof(line) - 1);
|
||||
line[sizeof(line) - 1] = '\0';
|
||||
} else
|
||||
inet_ntop(AF_INET6, (void *)&sa6->sin6_addr, line,
|
||||
sizeof(line));
|
||||
#endif
|
||||
|
||||
return line;
|
||||
}
|
||||
#endif /*INET6*/
|
||||
|
||||
/*
|
||||
* Print routing statistics
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user