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:
Yoshinobu Inoue 1999-12-07 17:39:16 +00:00
parent 07677171f8
commit cfa1ca9dfa
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=54263
67 changed files with 4790 additions and 442 deletions

View File

@ -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

View File

@ -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 ,

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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};
@ -971,9 +1102,9 @@ ns_print(sns)
else
*cport = 0;
(void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s",
(unsigned long)ntohl(net.long_e),
host, cport);
(void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s",
(unsigned long)ntohl(net.long_e),
host, cport);
return (mybuf);
}
#endif
@ -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;

View File

@ -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:
#

View File

@ -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

View File

@ -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

View File

@ -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:
#

View File

@ -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:
#

View File

@ -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>

View File

@ -35,7 +35,7 @@
*/
#include "opt_compat.h"
#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/malloc.h>

View File

@ -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>

View File

@ -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;

View File

@ -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
View 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 */

View File

@ -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
View 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 *)&af;
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 *)&af;
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*/

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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
View 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
View 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_*/

View File

@ -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,13 +228,34 @@ 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;
}
@ -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);

View File

@ -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 *));

View File

@ -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,

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
View 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
View 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_*/

View File

@ -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)) {

View File

@ -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) &&

View File

@ -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;

View File

@ -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,
@ -193,19 +195,17 @@ struct ip6protosw inet6sw[] = {
#endif /* IPSEC */
#if NGIF > 0
{ SOCK_RAW, &inet6domain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
in6_gif_input,0, 0, 0,
0,
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 */
{ SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
in6_gif_input,0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs
},
#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,

View File

@ -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)

View File

@ -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)

View File

@ -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,

View File

@ -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);

View File

@ -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>

View File

@ -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;

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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);
@ -507,8 +507,8 @@ pfxrtr_lookup(pr, dr)
struct nd_defrouter *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);
}

View File

@ -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
View 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
};

View File

@ -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 *));

View File

@ -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>

View File

@ -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,22 +169,27 @@ intpr(interval, ifnetaddr)
if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
return;
printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
"Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
if (bflag)
printf(" %10.10s","Ibytes");
printf(" %8.8s %5.5s", "Opkts", "Oerrs");
if (bflag)
printf(" %10.10s","Obytes");
printf(" %5s", "Coll");
if (tflag)
printf(" %s", "Time");
if (dflag)
printf(" %s", "Drop");
putchar('\n');
if (!sflag && !pflag) {
printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
"Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
if (bflag)
printf(" %10.10s","Ibytes");
printf(" %8.8s %5.5s", "Opkts", "Oerrs");
if (bflag)
printf(" %10.10s","Obytes");
printf(" %5s", "Coll");
if (tflag)
printf(" %s", "Time");
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;
cp = (char *)LLADDR(sdl);
n = sdl->sdl_alen;
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:

View File

@ -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,
so->so_snd.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) {
inetprint(&inp->inp_laddr, (int)inp->inp_lport,
name, 1);
inetprint(&inp->inp_faddr, (int)inp->inp_fport,
name, 1);
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) {
inetprint(&inp->inp_laddr, (int)inp->inp_lport,
name, 1);
inetprint(&inp->inp_faddr, (int)inp->inp_fport,
name, 0);
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 {
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);
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);
}
#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
View 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);
}

View File

@ -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)
mrt_stats(nl[N_MRTSTAT].n_value);
else
mroutepr(nl[N_MFCTABLE].n_value,
nl[N_VIFTABLE].n_value);
if (sflag) {
if (af == AF_INET || af == AF_UNSPEC)
mrt_stats(nl[N_MRTSTAT].n_value);
#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())) {
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();
}
protostat:
kread(0, 0, 0);
if (af == AF_INET || af == AF_UNSPEC)
for (tp = protox; tp->pr_name; tp++)
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) {
pr = tp->pr_stats;
off = tp->pr_usesysctl ? tp->pr_usesysctl
: nl[tp->pr_sindex].n_value;
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) {

View File

@ -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

View File

@ -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 *));

View File

@ -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 */
#define WID_DST 18 /* width of destination column */
#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");
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");
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,14 +588,15 @@ 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 ");
printf("%6ld %8ld ", rt->rt_refcnt, rt->rt_use);
if (lflag)
printf("%6ld %8ld ", rt->rt_refcnt, rt->rt_use);
if (rt->rt_ifp) {
if (rt->rt_ifp != lastif) {
kget(rt->rt_ifp, ifnet);
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
*/