Getaddrinfo(), getnameinfo(), and etc support in libc/net.

Several udp and raw apps IPv6 support.

Reviewed by: freebsd-arch, cvs-committers
Obtained from: KAME project
This commit is contained in:
shin 1999-12-28 02:37:14 +00:00
parent 56f680165a
commit 2958040f73
49 changed files with 14758 additions and 52 deletions

View File

@ -62,6 +62,7 @@
#define _NETDB_H_
#include <sys/cdefs.h>
#include <sys/types.h>
#ifndef _PATH_HEQUIV
# define _PATH_HEQUIV "/etc/hosts.equiv"
@ -111,6 +112,17 @@ struct protoent {
int p_proto; /* protocol # */
};
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
/*
* Error return codes from gethostbyname() and gethostbyaddr()
* (left in extern int h_errno).
@ -124,15 +136,74 @@ struct protoent {
#define NO_DATA 4 /* Valid name, no data record of requested type */
#define NO_ADDRESS NO_DATA /* no address, look for MX record */
/*
* Error return codes from getaddrinfo()
*/
#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
#define EAI_AGAIN 2 /* temporary failure in name resolution */
#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
#define EAI_FAMILY 5 /* ai_family not supported */
#define EAI_MEMORY 6 /* memory allocation failure */
#define EAI_NODATA 7 /* no address associated with hostname */
#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
#define EAI_SYSTEM 11 /* system error returned in errno */
#define EAI_BADHINTS 12
#define EAI_PROTOCOL 13
#define EAI_RESNULL 14
#define EAI_MAX 15
/*
* Flag values for getaddrinfo()
*/
#define AI_PASSIVE 0x00000001 /* get address to use bind() */
#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
/* valid flags for addrinfo */
#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
/* special recommended flags for getipnodebyname */
#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
/*
* Constants for getnameinfo()
*/
#define NI_MAXHOST 1025
#define NI_MAXSERV 32
/*
* Flag values for getnameinfo()
*/
#define NI_NOFQDN 0x00000001
#define NI_NUMERICHOST 0x00000002
#define NI_NAMEREQD 0x00000004
#define NI_NUMERICSERV 0x00000008
#define NI_DGRAM 0x00000010
#define NI_WITHSCOPEID 0x00000020
/*
* Scope delimit character
*/
#define SCOPE_DELIMITER '@'
__BEGIN_DECLS
void endhostent __P((void));
void endnetent __P((void));
void endprotoent __P((void));
void endservent __P((void));
void freehostent __P((struct hostent *));
struct hostent *gethostbyaddr __P((const char *, int, int));
struct hostent *gethostbyname __P((const char *));
struct hostent *gethostbyname2 __P((const char *, int));
struct hostent *gethostent __P((void));
struct hostent *getipnodebyaddr __P((const void *, size_t, int, int *));
struct hostent *getipnodebyname __P((const char *, int, int, int *));
struct netent *getnetbyaddr __P((unsigned long, int));
struct netent *getnetbyname __P((const char *));
struct netent *getnetent __P((void));
@ -148,6 +219,12 @@ void sethostent __P((int));
/* void sethostfile __P((const char *)); */
void setnetent __P((int));
void setprotoent __P((int));
int getaddrinfo __P((const char *, const char *,
const struct addrinfo *, struct addrinfo **));
int getnameinfo __P((const struct sockaddr *, size_t, char *,
size_t, char *, size_t, int));
void freeaddrinfo __P((struct addrinfo *));
char *gai_strerror __P((int));
void setservent __P((int));
/*

View File

@ -60,6 +60,7 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/socket.h>
#include <stdio.h>
/*
@ -116,6 +117,21 @@ struct __res_state {
char pad[72]; /* on an i386 this means 512b total */
};
/* for INET6 */
/*
* replacement of __res_state, separated to keep binary compatibility.
*/
struct __res_state_ext {
struct sockaddr_storage nsaddr_list[MAXNS];
struct {
int af; /* address family for addr, mask */
union {
struct in_addr ina;
struct in6_addr in6a;
} addr, mask;
} sort_list[MAXRESOLVSORT];
};
/*
* Resolver options (keep these in synch with res_debug.c, please)
*/
@ -181,6 +197,9 @@ struct res_sym {
};
extern struct __res_state _res;
/* for INET6 */
extern struct __res_state_ext _res_ext;
extern const struct res_sym __p_class_syms[];
extern const struct res_sym __p_type_syms[];

View File

@ -4,15 +4,16 @@
# machine-independent net sources
.PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/net ${.CURDIR}/../libc/net
SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c \
SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c getaddrinfo.c \
gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \
getnameinfo.c \
getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
getproto.c getprotoent.c getprotoname.c getservbyname.c \
getservbyport.c getservent.c herror.c inet_addr.c ifname.c \
inet_lnaof.c \
inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.c \
inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \
inet_pton.c ip6opt.c linkaddr.c map_v4v6.c ns_addr.c \
inet_pton.c ip6opt.c linkaddr.c map_v4v6.c name6.c ns_addr.c \
ns_name.c ns_netint.c \
ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c nsap_addr.c \
rcmd.c recv.c res_comp.c res_data.c res_debug.c \
@ -20,12 +21,15 @@ SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c \
res_update.c rthdr.c send.c vars.c
# not supported: iso_addr.c
CFLAGS+=-DINET6
# machine-dependent net sources
.include "${.CURDIR}/../libc/${MACHINE_ARCH}/net/Makefile.inc"
.if ${LIB} == "c"
MAN3+= addr2ascii.3 byteorder.3 ethers.3 gethostbyname.3 \
getnetent.3 getprotoent.3 getservent.3 if_indextoname.3 \
MAN3+= addr2ascii.3 byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 \
getipnodebyname.3 \
getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 if_indextoname.3 \
inet.3 linkaddr.3 rcmd.3 resolver.3
# not installed: iso_addr.3 ns.3
@ -34,10 +38,12 @@ MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
byteorder.3 ntohs.3
MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3
MLINKS+=getaddrinfo.3 freeaddrinfo.3 getaddrinfo.3 gai_strerror.3
MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
gethostbyname.3 gethostbyname2.3 gethostbyname.3 gethostent.3 \
gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \
gethostbyname.3 sethostent.3
MLINKS+=getipnodebyname.3 getipnodebyaddr.3 getipnodebyname.3 freehostent.3
MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \

408
lib/libc/net/getaddrinfo.3 Normal file
View File

@ -0,0 +1,408 @@
.\" Copyright (c) 1983, 1987, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 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.
.\"
.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
.\" $Id: getaddrinfo.3,v 1.3 1999/10/07 08:22:04 jinmei Exp $
.\" $FreeBSD$
.\"
.Dd May 25, 1995
.Dt GETADDRINFO 3
.Os KAME
.\"
.Sh NAME
.Nm getaddrinfo
.Nm freeaddrinfo ,
.Nm gai_strerror
.Nd nodename-to-address translation in protocol-independent manner
.\"
.Sh SYNOPSIS
.Fd #include <sys/socket.h>
.Fd #include <netdb.h>
.Ft int
.Fn getaddrinfo "const char *nodename" "const char *servname" \
"const struct addrinfo *hints" "struct addrinfo **res"
.Ft void
.Fn freeaddrinfo "struct addrinfo *ai"
.Ft "char *"
.Fn gai_strerror "int ecode"
.\"
.Sh DESCRIPTION
The
.Fn getaddrinfo
function is defined for protocol-independent nodename-to-address translation.
It performs functionality of
.Xr gethostbyname 3
and
.Xr getservbyname 3 ,
in more sophisticated manner.
.Pp
The addrinfo structure is defined as a result of including the
.Li <netdb.h>
header:
.Bd -literal -offset
struct addrinfo { *
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for nodename */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
.Ed
.Pp
The
.Fa nodename
and
.Fa servname
arguments are pointers to null-terminated strings or
.Dv NULL .
One or both of these two arguments must be a
.Pf non Dv -NULL
pointer.
In the normal client scenario, both the
.Fa nodename
and
.Fa servname
are specified.
In the normal server scenario, only the
.Fa servname
is specified.
A
.Pf non Dv -NULL
.Fa nodename
string can be either a node name or a numeric host address string
.Po
i.e., a dotted-decimal IPv4 address or an IPv6 hex address
.Pc .
A
.Pf non Dv -NULL
.Fa servname
string can be either a service name or a decimal port number.
.Pp
The caller can optionally pass an
.Li addrinfo
structure, pointed to by the third argument,
to provide hints concerning the type of socket that the caller supports.
In this
.Fa hints
structure all members other than
.Fa ai_flags ,
.Fa ai_family ,
.Fa ai_socktype ,
and
.Fa ai_protocol
must be zero or a
.Dv NULL
pointer.
A value of
.Dv PF_UNSPEC
for
.Fa ai_family
means the caller will accept any protocol family.
A value of 0 for
.Fa ai_socktype
means the caller will accept any socket type.
A value of 0 for
.Fa ai_protocol
means the caller will accept any protocol.
For example, if the caller handles only TCP and not UDP, then the
.Fa ai_socktype
member of the hints structure should be set to
.Dv SOCK_STREAM
when
.Fn getaddrinfo
is called.
If the caller handles only IPv4 and not IPv6, then the
.Fa ai_family
member of the
.Fa hints
structure should be set to
.Dv PF_INET
when
.Fn getaddrinfo
is called.
If the third argument to
.Fn getaddrinfo
is a
.Dv NULL
pointer, this is the same as if the caller had filled in an
.Li addrinfo
structure initialized to zero with
.Fa ai_family
set to PF_UNSPEC.
.Pp
Upon successful return a pointer to a linked list of one or more
.Li addrinfo
structures is returned through the final argument.
The caller can process each
.Li addrinfo
structure in this list by following the
.Fa ai_next
pointer, until a
.Dv NULL
pointer is encountered.
In each returned
.Li addrinfo
structure the three members
.Fa ai_family ,
.Fa ai_socktype ,
and
.Fa ai_protocol
are the corresponding arguments for a call to the
.Fn socket
function.
In each
.Li addrinfo
structure the
.Fa ai_addr
member points to a filled-in socket address structure whose length is
specified by the
.Fa ai_addrlen
member.
.Pp
If the
.Dv AI_PASSIVE
bit is set in the
.Fa ai_flags
member of the
.Fa hints
structure, then the caller plans to use the returned socket address
structure in a call to
.Fn bind .
In this case, if the
.Fa nodename
argument is a
.Dv NULL
pointer, then the IP address portion of the socket
address structure will be set to
.Dv INADDR_ANY
for an IPv4 address or
.Dv IN6ADDR_ANY_INIT
for an IPv6 address.
.Pp
If the
.Dv AI_PASSIVE
bit is not set in the
.Fa ai_flags
member of the
.Fa hints
structure, then the returned socket address structure will be ready for a
call to
.Fn connect
.Pq for a connection-oriented protocol
or either
.Fn connect ,
.Fn sendto , or
.Fn sendmsg
.Pq for a connectionless protocol .
In this case, if the
.Fa nodename
argument is a
.Dv NULL
pointer, then the IP address portion of the
socket address structure will be set to the loopback address.
.Pp
If the
.Dv AI_CANONNAME
bit is set in the
.Fa ai_flags
member of the
.Fa hints
structure, then upon successful return the
.Fa ai_canonname
member of the first
.Li addrinfo
structure in the linked list will point to a null-terminated string
containing the canonical name of the specified
.Fa nodename .
.Pp
If the
.Dv AI_NUMERICHOST
bit is set in the
.Fa ai_flags
member of the
.Fa hints
structure, then a
.Pf non Dv -NULL
.Fa nodename
string must be a numeric host address string.
Otherwise an error of
.Dv EAI_NONAME
is returned.
This flag prevents any type of name resolution service (e.g., the DNS)
from being called.
.Pp
All of the information returned by
.Fn getaddrinfo
is dynamically allocated:
the
.Li addrinfo
structures, and the socket address structures and canonical node name
strings pointed to by the addrinfo structures.
To return this information to the system the function
.Fn freeaddrinfo
is called.
The
.Fa addrinfo
structure pointed to by the
.Fa ai argument
is freed, along with any dynamic storage pointed to by the structure.
This operation is repeated until a
.Dv NULL
.Fa ai_next
pointer is encountered.
.Pp
To aid applications in printing error messages based on the
.Dv EAI_xxx
codes returned by
.Fn getaddrinfo ,
.Fn gai_strerror
is defined.
The argument is one of the
.Dv EAI_xxx
values defined earlier and the return value points to a string describing
the error.
If the argument is not one of the
.Dv EAI_xxx
values, the function still returns a pointer to a string whose contents
indicate an unknown error.
.\"
.Sh EXTENSION
The implementation allows experimental numeric IPv6 address notation with
scope identifier.
By appending atmark and scope identifier to addresses, you can fill
.Li sin6_scope_id
field for addresses.
This would make management of scoped address easier,
and allows cut-and-paste input of scoped address.
.Pp
At this moment the code supports only link-local addresses with the format.
Scope identifier is hardcoded to name of hardware interface associated
with the link.
.Po
such as
.Li ne0
.Pc .
Example would be like
.Dq Li fe80::1@ne0 ,
which means
.Do
.Li fe80::1
on the link associated with
.Li ne0
interface
.Dc .
.Pp
The implementation is still very experimental and non-standard.
The current implementation assumes one-by-one relationship between
interface and link, which is not necessarily true from the specification.
.\"
.Sh FILES
.Bl -tag -width /etc/resolv.conf -compact
.It Pa /etc/hosts
.It Pa /etc/host.conf
.It Pa /etc/resolv.conf
.El
.\"
.Sh DIAGNOSTICS
Error return status from
.Fn getaddrinfo
is zero on success and non-zero on errors.
Non-zero error codes are defined in
.Li <netdb.h> ,
and as follows:
.Pp
.Bl -tag -width EAI_ADDRFAMILY -compact
.It Dv EAI_ADDRFAMILY
address family for nodename not supported
.It Dv EAI_AGAIN
temporary failure in name resolution
.It Dv EAI_BADFLAGS
invalid value for ai_flags
.It Dv EAI_FAIL
non-recoverable failure in name resolution
.It Dv EAI_FAMILY
ai_family not supported
.It Dv EAI_MEMORY
memory allocation failure
.It Dv EAI_NODATA
no address associated with nodename
.It Dv EAI_NONAME
nodename nor servname provided, or not known
.It Dv EAI_SERVICE
servname not supported for ai_socktype
.It Dv EAI_SOCKTYPE
ai_socktype not supported
.It Dv EAI_SYSTEM
system error returned in errno
.El
.Pp
If called with proper argument,
.Fn gai_strerror
returns a pointer to a string describing the given error code.
If the argument is not one of the
.Dv EAI_xxx
values, the function still returns a pointer to a string whose contents
indicate an unknown error.
.\"
.Sh SEE ALSO
.Xr getnameinfo 3 ,
.Xr gethostbyname 3 ,
.Xr getservbyname 3 ,
.Xr hosts 5 ,
.Xr services 5 ,
.Xr hostname 7 ,
.Xr named 8 .
.Pp
.Rs
.%A R. Gilligan
.%A S. Thomson
.%A J. Bound
.%A W. Stevens
.%T Basic Socket Interface Extensions for IPv6
.%R RFC2553
.%D March 1999
.Re
.\"
.Sh HISTORY
The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
.\"
.Sh STANDARDS
The
.Fn getaddrinfo
function is defined IEEE POSIX 1003.1g draft specification,
and documented in ``Basic Socket Interface Extensions for IPv6''
.Pq RFC2533 .
.\"
.Sh BUGS
The text was shamelessly copied from RFC2553.

1014
lib/libc/net/getaddrinfo.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,446 @@
.\" Copyright (c) 1983, 1987, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 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.
.\"
.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
.\" $Id: getipnodebyname.3,v 1.2 1999/09/13 16:04:51 itojun Exp $
.\ $FreeBSD$
.\"
.Dd May 25, 1995
.Dt GETIPNODEBYNAME 3
.Os KAME
.\"
.Sh NAME
.Nm getipnodebyname ,
.Nm getipnodebyaddr ,
.Nm freehostent
.Nd nodename-to-address and address-to-nodename translation
.\"
.Sh SYNOPSIS
.Fd #include <sys/socket.h>
.Fd #include <netdb.h>
.Ft "struct hostent *"
.Fn getipnodebyname "const char *name" "int af" "int flags" "int *error_num"
.Ft "struct hostent *"
.Fn getipnodebyaddr "const void *src" "size_t len" "int af" "int *error_num"
.Ft void
.Fn freehostent "struct hostent *ptr"
.\"
.Sh DESCRIPTION
.Fn getipnodebyname
and
.Fn getipnodebyaddr
functions are very similar to
.Xr gethostbyname 3 ,
.Xr gethostbyname2 3
and
.Xr gethostbyaddr 3 .
The functions cover all the functionalities provided by the older ones,
and provide better interface to programmers.
The functions require additional arguments,
.Ar af ,
and
.Ar flags ,
for specifying address family and operation mode.
The additional arguments allow programmer to get address for a nodename,
for specific address family
.Po
such as
.Dv AF_INET
or
.Dv AF_INET6
.Pc .
The functions also require an additional pointer argument,
.Ar error_num
to return the appropriate error code,
to support thread safe error code returns.
.Pp
The type and usage of the return value,
.Li "struct hostent"
is described in
.Xr gethostbyname 3 .
.Pp
For
.Fn getipnodebyname ,
the
.Ar name
argument can be either a node name or a numeric address
string
.Po
i.e., a dotted-decimal IPv4 address or an IPv6 hex address
.Pc .
The
.Ar af
argument specifies the address family, either
.Dv AF_INET
or
.Dv AF_INET6 .
The
.Ar flags
argument specifies the types of addresses that are searched for,
and the types of addresses that are returned.
We note that a special flags value of
.Dv AI_DEFAULT
.Pq defined below
should handle most applications.
That is, porting simple applications to use IPv6 replaces the call
.Bd -literal -offset
hptr = gethostbyname(name);
.Ed
.Pp
with
.Bd -literal -offset
hptr = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num);
.Ed
.Pp
Applications desiring finer control over the types of addresses
searched for and returned, can specify other combinations of the
.Ar flags
argument.
.Pp
A
.Ar flags
of
.Li 0
implies a strict interpretation of the
.Ar af
argument:
.Bl -bullet
.It
If
.Ar flags
is 0 and
.Ar af
is
.Dv AF_INET ,
then the caller wants only IPv4 addresses.
A query is made for
.Li A
records.
If successful, the IPv4 addresses are returned and the
.Li h_length
member of the
.Li hostent
structure will be 4, else the function returns a
.Dv NULL
pointer.
.It
If
.Ar flags
is 0 and if
.Ar af
is
.Li AF_INET6 ,
then the caller wants only IPv6 addresses.
A query is made for
.Li AAAA
records.
If successful, the IPv6 addresses are returned and the
.Li h_length
member of the
.Li hostent
structure will be 16, else the function returns a
.Dv NULL
pointer.
.El
.Pp
Other constants can be logically-ORed into the
.Ar flags
argument, to modify the behavior of the function.
.Bl -bullet
.It
If the
.Dv AI_V4MAPPED
flag is specified along with an
.Ar af
of
.Dv AF_INET6 ,
then the caller will accept IPv4-mapped IPv6 addresses.
That is, if no
.Li AAAA
records are found then a query is made for
.Li A
records and any found are returned as IPv4-mapped IPv6 addresses
.Po
.Li h_length
will be 16
.Pc .
The
.Dv AI_V4MAPPED
flag is ignored unless
.Ar af
equals
.Dv AF_INET6 .
.It
The
.Dv AI_V4MAPPED_CFG
flag is exact same as the
.Dv AI_V4MAPPED
flag only if the kernel supports IPv4-mapped IPv6 address.
.It
If the
.Dv AI_ALL
flag is used in conjunction with the
.Dv AI_V4MAPPED
flag, and only used with the IPv6 address family.
When
.Dv AI_ALL
is logically or'd with
.Dv AI_V4MAPPED
flag then the caller wants all addresses: IPv6 and IPv4-mapped IPv6.
A query is first made for
.Li AAAA
records and if successful, the
IPv6 addresses are returned. Another query is then made for
.Li A
records and any found are returned as IPv4-mapped IPv6 addresses.
.Li h_length
will be 16. Only if both queries fail does the function
return a
.Dv NULL
pointer. This flag is ignored unless af equals
AF_INET6. If both
.Dv AI_ALL
and
.Dv AI_V4MAPPED
are specified,
.Dv AI_ALL
takes precedence.
.It
The
.Dv AI_ADDRCONFIG
flag specifies that a query for
.Li AAAA
records
should occur only if the node has at least one IPv6 source
address configured and a query for
.Li A
records should occur only if the node has at least one IPv4 source address
configured.
.Pp
For example, if the node has no IPv6 source addresses configured,
and
.Ar af
equals AF_INET6, and the node name being looked up has both
.Li AAAA
and
.Li A
records, then:
(a) if only
.Dv AI_ADDRCONFIG
is
specified, the function returns a
.Dv NULL
pointer;
(b) if
.Dv AI_ADDRCONFIG
|
.Dv AI_V4MAPPED
is specified, the
.Li A
records are returned as IPv4-mapped IPv6 addresses;
.El
.Pp
The special flags value of
.Dv AI_DEFAULT
is defined as
.Bd -literal -offset
#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
.Ed
.Pp
We noted that the
.Fn getipnodebyname
function must allow the
.Ar name
argument to be either a node name or a literal address string
.Po
i.e., a dotted-decimal IPv4 address or an IPv6 hex address
.Pc .
This saves applications from having to call
.Xr inet_pton 3
to handle literal address strings.
When the
.Ar name
argument is a literal address string,
the
.Ar flags
argument is always ignored.
.Pp
There are four scenarios based on the type of literal address string
and the value of the
.Ar af
argument.
The two simple cases are when
.Ar name
is a dotted-decimal IPv4 address and
.Ar af
equals
.Dv AF_INET ,
or when
.Ar name
is an IPv6 hex address and
.Ar af
equals
.Dv AF_INET6 .
The members of the
returned hostent structure are:
.Li h_name
points to a copy of the
.Ar name
argument,
.Li h_aliases
is a
.Dv NULL
pointer,
.Li h_addrtype
is a copy of the
.Ar af
argument,
.Li h_length
is either 4
.Po
for
.Dv AF_INET
.Pc
or 16
.Po
for
.Dv AF_INET6
.Pc ,
.Li h_addr_list[0]
is a pointer to the 4-byte or 16-byte binary address,
and
.Li h_addr_list[1]
is a
.Dv NULL
pointer.
.Pp
When
.Ar name
is a dotted-decimal IPv4 address and
.Ar af
equals
.Dv AF_INET6 ,
and
.Dv AI_V4MAPPED
is specified,
an IPv4-mapped IPv6 address is returned:
.Li h_name
points to an IPv6 hex address containing the IPv4-mapped IPv6 address,
.Li h_aliases
is a
.Dv NULL
pointer,
.Li h_addrtype
is
.Dv AF_INET6 ,
.Li h_length
is 16,
.Li h_addr_list[0]
is a pointer to the 16-byte binary address, and
.Li h_addr_list[1]
is a
.Dv NULL
pointer.
.Pp
It is an error when
.Ar name
is an IPv6 hex address and
.Ar af
equals
.Dv AF_INET .
The function's return value is a
.Dv NULL
pointer and the value pointed to by
.Ar error_num
equals
.Dv HOST_NOT_FOUND .
.Pp
.Fn getipnodebyaddr
takes almost the same argument as
.Xr gethostbyaddr 3 ,
but adds a pointer to return an error number.
Additionally it takes care of IPv4-mapped IPv6 addresses,
and IPv4-compatible IPv6 addresses.
.Pp
.Fn getipnodebyname
and
.Fn getipnodebyaddr
dynamically allocate the structure to be returned to the caller.
.Fn freehostent
reclaims memory region allocated and returned by
.Fn getipnodebyname
or
.Fn getipnodebyaddr .
.\"
.Sh FILES
.Bl -tag -width /etc/resolv.conf -compact
.It Pa /etc/hosts
.It Pa /etc/host.conf
.It Pa /etc/resolv.conf
.El
.\"
.Sh DIAGNOSTICS
.Nm getipnodebyname
and
.Nm getipnodebyaddr
returns
.Dv NULL
on errors.
The integer values pointed to by
.Ar error_num
may then be checked to see whether this is a temporary failure
or an invalid or unknown host.
The meanings of each error code are described in
.Xr gethostbyname 3 .
.\"
.Sh SEE ALSO
.Xr gethostbyname 3 ,
.Xr gethostbyaddr 3 ,
.Xr hosts 5 ,
.Xr services 5 ,
.Xr hostname 7 ,
.Xr named 8
.Pp
R. Gilligan, S. Thomson, J. Bound, and W. Stevens,
``Basic Socket Interface Extensions for IPv6,'' RFC2553, March 1999.
.\"
.Sh HISTORY
The implementation first appeared in KAME advanced networking kit.
.\"
.Sh STANDARDS
.Fn getipnodebyname
and
.Fn getipnodebyaddr
are documented in ``Basic Socket Interface Extensions for IPv6''
.Pq RFC2553 .
.\"
.Sh BUGS
The text was shamelessly copied from RFC2553.

232
lib/libc/net/getnameinfo.3 Normal file
View File

@ -0,0 +1,232 @@
.\" Copyright (c) 1983, 1987, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 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.
.\"
.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
.\" $Id: getnameinfo.3,v 1.2 1999/10/07 04:46:27 itojun Exp $
.\" $FreeBSD$
.\"
.Dd May 25, 1995
.Dt GETNAMEINFO 3
.Os KAME
.\"
.Sh NAME
.Nm getnameinfo
.Nd address-to-nodename translation in protocol-independent manner
.\"
.Sh SYNOPSIS
.Fd #include <sys/socket.h>
.Fd #include <netdb.h>
.Ft int
.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" \
"char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags"
.\"
.Sh DESCRIPTION
The
.Fn getnameinfo
function is defined for protocol-independent address-to-nodename translation.
Its functionality is a reverse conversion of
.Xr getaddrinfo 3 ,
and implements similar functionality with
.Xr gethostbyaddr 3 and
.Xr getservbyport 3
in more sophisticated manner.
.Pp
This function looks up an IP address and port number provided by the
caller in the DNS and system-specific database, and returns text
strings for both in buffers provided by the caller.
The function indicates successful completion by a zero return value;
a non-zero return value indicates failure.
.Pp
The first argument,
.Fa sa ,
points to either a
.Fa sockaddr_in
structure (for IPv4) or a
.Fa sockaddr_in6
structure (for IPv6) that holds the IP address and port number.
The
.Fa salen
argument gives the length of the
.Fa sockaddr_in
or
.Fa sockaddr_in6
structure.
.Pp
The function returns the nodename associated with the IP address in
the buffer pointed to by the
.Fa host
argument.
The caller provides the size of this buffer via the
.Fa hostlen
argument.
The service name associated with the port number is returned in the buffer
pointed to by
.Fa serv ,
and the
.Fa servlen
argument gives the length of this buffer.
The caller specifies not to return either string by providing a zero
value for the
.Fa hostlen
or
.Fa servlen
arguments.
Otherwise, the caller must provide buffers large enough to hold the
nodename and the service name, including the terminating null characters.
.Pp
Unfortunately most systems do not provide constants that specify the
maximum size of either a fully-qualified domain name or a service name.
Therefore to aid the application in allocating buffers for these two
returned strings the following constants are defined in
.Li <netdb.h> :
.Bd -literal -offset
#define NI_MAXHOST 1025
#define NI_MAXSERV 32
.Ed
.Pp
The first value is actually defined as the constant
.Dv MAXDNAME
in recent versions of BIND's
.Li <arpa/nameser.h>
header
.Po
older versions of BIND define this constant to be 256
.Pc
and the second is a guess based on the services listed in the current
Assigned Numbers RFC.
.Pp
The final argument is a
.Fa flag
that changes the default actions of this function.
By default the fully-qualified domain name (FQDN) for the host is
looked up in the DNS and returned.
If the flag bit
.Dv NI_NOFQDN
is set, only the nodename portion of the FQDN is returned for local hosts.
.Pp
If the
.Fa flag
bit
.Dv NI_NUMERICHOST
is set, or if the host's name cannot be located in the DNS,
the numeric form of the host's address is returned instead of its name
.Po
e.g., by calling
.Fn inet_ntop
instead of
.Fn getnodebyaddr
.Pc .
If the
.Fa flag
bit
.Dv NI_NAMEREQD
is set, an error is returned if the host's name cannot be located in the DNS.
.Pp
If the flag bit
.Dv NI_NUMERICSERV
is set, the numeric form of the service address is returned
.Pq e.g., its port number
instead of its name.
The two
.Dv NI_NUMERICxxx
flags are required to support the
.Li "-n"
flag that many commands provide.
.Pp
A fifth flag bit,
.Dv NI_DGRAM ,
specifies that the service is a datagram service, and causes
.Fn getservbyport
to be called with a second argument of "udp" instead of its default of "tcp".
This is required for the few ports (512-514)
that have different services for UDP and TCP.
.Pp
These
.Dv NI_xxx
flags are defined in
.Li <netdb.h> .
.\"
.Sh EXTENSION
The implementation allows experimental numeric IPv6 address notation with
scope identifier.
IPv6 link-local address will appear as string like
.Dq Li fe80::1@ne0 ,
if
.Dv NI_WITHSCOPEID
bit is enabled in
.Ar flags
argument.
Refer to
.Xr getaddrinfo 3
for the notation.
.\"
.Sh FILES
.Bl -tag -width /etc/resolv.conf -compact
.It Pa /etc/hosts
.It Pa /etc/host.conf
.It Pa /etc/resolv.conf
.El
.\"
.Sh DIAGNOSTICS
The function indicates successful completion by a zero return value;
a non-zero return value indicates failure.
.\"
.Sh SEE ALSO
.Xr getaddrinfo 3 ,
.Xr gethostbyaddr 3 ,
.Xr getservbyport 3 ,
.Xr hosts 5 ,
.Xr services 5 ,
.Xr hostname 7 ,
.Xr named 8
.Pp
.Rs
.%A R. Gilligan
.%A S. Thomson
.%A J. Bound
.%A W. Stevens
.%T Basic Socket Interface Extensions for IPv6
.%R RFC2553
.%D March 1999
.Re
.\"
.Sh HISTORY
The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
.\"
.Sh STANDARDS
The
.Fn getaddrinfo
function is defined IEEE POSIX 1003.1g draft specification,
and documented in ``Basic Socket Interface Extensions for IPv6''
.Pq RFC2533 .
.\"
.Sh BUGS
The text was shamelessly copied from RFC2553.

228
lib/libc/net/getnameinfo.c Normal file
View File

@ -0,0 +1,228 @@
/*
* 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$
*/
/*
* Issues to be discussed:
* - Thread safe-ness must be checked
* - Return values. There seems to be no standard for return value (RFC2553)
* but INRIA implementation returns EAI_xxx defined for getaddrinfo().
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
#include <string.h>
#include <stddef.h>
#define SUCCESS 0
#define ANY 0
#define YES 1
#define NO 0
static struct afd {
int a_af;
int a_addrlen;
int a_socklen;
int a_off;
} afdl [] = {
#ifdef INET6
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
offsetof(struct sockaddr_in6, sin6_addr)},
#endif
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
offsetof(struct sockaddr_in, sin_addr)},
{0, 0, 0},
};
struct sockinet {
u_char si_len;
u_char si_family;
u_short si_port;
};
#define ENI_NOSOCKET 0
#define ENI_NOSERVHOST 1
#define ENI_NOHOSTNAME 2
#define ENI_MEMORY 3
#define ENI_SYSTEM 4
#define ENI_FAMILY 5
#define ENI_SALEN 6
int
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
const struct sockaddr *sa;
size_t salen;
char *host;
size_t hostlen;
char *serv;
size_t servlen;
int flags;
{
struct afd *afd;
struct servent *sp;
struct hostent *hp;
u_short port;
int family, i;
char *addr, *p;
u_long v4a;
int h_error;
char numserv[512];
char numaddr[512];
int noserv = 0;
if (sa == NULL)
return ENI_NOSOCKET;
if (sa->sa_len != salen)
return ENI_SALEN;
family = sa->sa_family;
for (i = 0; afdl[i].a_af; i++)
if (afdl[i].a_af == family) {
afd = &afdl[i];
goto found;
}
return ENI_FAMILY;
found:
if (salen != afd->a_socklen)
return ENI_SALEN;
port = ((struct sockinet *)sa)->si_port; /* network byte order */
addr = (char *)sa + afd->a_off;
if (serv == NULL || servlen == 0) {
noserv = 1;
} else {
if (flags & NI_NUMERICSERV)
sp = NULL;
else {
sp = getservbyport(port,
(flags & NI_DGRAM) ? "udp" : "tcp");
}
if (sp) {
if (strlen(sp->s_name) > servlen)
return ENI_MEMORY;
strcpy(serv, sp->s_name);
} else {
snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
if (strlen(numserv) > servlen)
return ENI_MEMORY;
strcpy(serv, numserv);
}
}
switch (sa->sa_family) {
case AF_INET:
v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
flags |= NI_NUMERICHOST;
v4a >>= IN_CLASSA_NSHIFT;
if (v4a == 0 || v4a == IN_LOOPBACKNET)
flags |= NI_NUMERICHOST;
break;
#ifdef INET6
case AF_INET6:
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)sa;
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
flags |= NI_NUMERICHOST;
}
break;
#endif
}
if (host == NULL || hostlen == 0) {
if (noserv == 1)
return ENI_NOSERVHOST;
} else if (flags & NI_NUMERICHOST) {
/* NUMERICHOST and NAMEREQD conflicts with each other */
if (flags & NI_NAMEREQD)
return ENI_NOHOSTNAME;
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_SYSTEM;
if (strlen(numaddr) > hostlen)
return ENI_MEMORY;
strcpy(host, numaddr);
#ifdef INET6
if (afd->a_af == AF_INET6 &&
(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&
((struct sockaddr_in6 *)sa)->sin6_scope_id) {
if (flags & NI_WITHSCOPEID) {
char *ep = strchr(host, '\0');
unsigned int ifindex =
((struct sockaddr_in6 *)sa)->sin6_scope_id;
char ifname[IF_NAMESIZE * 2 /* for safety */];
if ((if_indextoname(ifindex, ifname)) == NULL)
return ENI_SYSTEM;
if (strlen(host) + 1 /* SCOPE_DELIMITER */
+ strlen(ifname) > hostlen)
return ENI_MEMORY;
*ep = SCOPE_DELIMITER;
strcpy(ep + 1, ifname);
}
}
#endif /* INET6 */
} else {
hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
if (hp) {
if (flags & NI_NOFQDN) {
p = strchr(hp->h_name, '.');
if (p) *p = '\0';
}
if (strlen(hp->h_name) > hostlen) {
freehostent(hp);
return ENI_MEMORY;
}
strcpy(host, hp->h_name);
freehostent(hp);
} else {
if (flags & NI_NAMEREQD)
return ENI_NOHOSTNAME;
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_NOHOSTNAME;
if (strlen(numaddr) > hostlen)
return ENI_MEMORY;
strcpy(host, numaddr);
}
}
return SUCCESS;
}

1260
lib/libc/net/name6.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -112,6 +112,9 @@ struct __res_state _res
# endif
;
#ifdef INET6
struct __res_state_ext _res_ext;
#endif /* INET6 */
/*
* Set up default settings. If the configuration file exist, the values
@ -314,6 +317,9 @@ res_init()
#ifdef RESOLVSORT
if (MATCH(buf, "sortlist")) {
struct in_addr a;
#ifdef INET6
struct in6_addr a6;
#endif /* INET6 */
cp = buf + sizeof("sortlist") - 1;
while (nsort < MAXRESOLVSORT) {
@ -347,8 +353,61 @@ res_init()
_res.sort_list[nsort].mask =
net_mask(_res.sort_list[nsort].addr);
}
#ifdef INET6
_res_ext.sort_list[nsort].af = AF_INET;
_res_ext.sort_list[nsort].addr.ina =
_res.sort_list[nsort].addr;
_res_ext.sort_list[nsort].mask.ina.s_addr =
_res.sort_list[nsort].mask;
#endif /* INET6 */
nsort++;
}
#ifdef INET6
else if (inet_pton(AF_INET6, net, &a6) == 1) {
int m, i;
u_char *u;
_res_ext.sort_list[nsort].af = AF_INET6;
_res_ext.sort_list[nsort].addr.in6a = a6;
u = (u_char *)&_res_ext.sort_list[nsort].mask.in6a;
*cp++ = n;
net = cp;
while (*cp && *cp != ';' &&
isascii(*cp) && !isspace(*cp))
cp++;
m = n;
n = *cp;
*cp = 0;
switch (m) {
case '/':
m = atoi(net);
break;
case '&':
if (inet_pton(AF_INET6, net, u) == 1) {
m = -1;
break;
}
/*FALLTHROUGH*/
default:
m = sizeof(struct in6_addr) * NBBY;
break;
}
if (m >= 0) {
for (i = 0; i < sizeof(struct in6_addr); i++) {
if (m <= 0) {
*u = 0;
} else {
m -= NBBY;
*u = (u_char)~0;
if (m < 0)
*u <<= -m;
}
u++;
}
}
nsort++;
}
#endif /* INET6 */
*cp = n;
}
continue;

View File

@ -50,11 +50,13 @@ SUBDIR= adjkerntz \
nologin \
nos-tun \
ping \
ping6 \
quotacheck \
reboot \
restore \
route \
routed \
rtsol \
savecore \
shutdown \
slattach \

25
sbin/ping6/Makefile Normal file
View File

@ -0,0 +1,25 @@
# Copyright (c) 1996 WIDE Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modifications, are permitted provided that the above copyright notice
# and this paragraph are duplicated in all such forms and that any
# documentation, advertising materials, and other materials related to
# such distribution and use acknowledge that the software was developed
# by the WIDE Project, Japan. The name of the Project may not be used to
# endorse or promote products derived from this software without
# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE.
# $FreeBSD$
PROG= ping6
MAN8= ping6.8
BINMODE = 4555
COPTS+= -Wall -Wmissing-prototypes
.if ${MACHINE_ARCH} == "alpha"
COPTS+= -fno-builtin # GCC's builtin memcpy doesn't do unaligned copies
.endif
CFLAGS+= -DINET6
.include <bsd.prog.mk>

332
sbin/ping6/ping6.8 Normal file
View File

@ -0,0 +1,332 @@
.\" 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.
.\"
.\" $Id: ping6.8,v 1.4 1999/10/07 05:29:03 itojun Exp $
.\" $FreeBSD$
.\"
.Dd May 17, 1998
.Dt PING6 8
.Os KAME
.Sh NAME
.Nm ping6
.Nd send
.Tn ICMPv6 ECHO_REQUEST
packets to network hosts
.Sh SYNOPSIS
.Nm
.Op Fl AdEfnqRrvw
.Op Fl a Ar addrtype
.Op Fl b Ar bufsiz
.Op Fl c Ar count
.Op Fl h Ar hoplimit
.Op Fl I Ar interface
.Op Fl i Ar wait
.Op Fl l Ar preload
.Op Fl p Ar pattern
.Op Fl s Ar packetsize
.Ar host
.Sh DESCRIPTION
.Bl -tag -width Ds
.It Fl A
Enables transport-mode IPsec authentication header. (experimental)
.It Fl a Ar addrtype
Generate ICMPv6 Node Information Node Addresses query, rather than echo-request.
.Ar addrtype
must be a string constructed of the following charaters.
.Bl -tag -width Ds -compact
.It Ic a
requires all the responder's unicast addresses. If the charater is ommited,
only those addresses which belong to the interface which has the
responder's address are required.
.It Ic g
requires responder's global-scope addresses.
.It Ic s
requires responder's site-local addresses.
.It Ic l
requires responder's link-local addresses.
.It Ic A
requires responder's anycast addresses. Without this character, the responder
will return unicast addresses only. With this character, the responder
will return anycast addresses only.
Note that the specification does not specify how to get responder's
anycast addresses. This is an experimental option.
.El
.It Fl b Ar bufsiz
Set socket buffer size.
.It Fl c Ar count
Stop after sending
.Pq and receiving
.Ar count
.Tn ECHO_RESPONSE
packets.
.It Fl d
Set the
.Dv SO_DEBUG
option on the socket being used.
.It Fl E
Enables transport-mode IPsec encapsulated security payload. (experimental)
.It Fl f
Flood ping.
Outputs packets as fast as they come back or one hundred times per second,
whichever is more.
For every
.Tn ECHO_REQUEST
sent a period
.Dq \&.
is printed, while for every
.Tn ECHO_REPLY
received a backspace is printed.
This provides a rapid display of how many packets are being dropped.
Only the super-user may use this option.
.Bf -emphasis
This can be very hard on a network and should be used with caution.
.Ef
.It Fl h Ar hoplimit
Set the IPv6 hoplimit.
.It Fl I Ar interface
Source packets with the given interface address.
This flag applies if the ping destination is a multicast address,
or link-local/site-local unicast address.
.It Fl i Ar wait
Wait
.Ar wait
seconds
.Em between sending each packet .
The default is to wait for one second between each packet.
This option is incompatible with the
.Fl f
option.
.It Fl l Ar preload
If
.Ar preload
is specified,
.Nm ping
sends that many packets as fast as possible before falling into its normal
mode of behavior.
Only the super-user may use this option.
.It Fl n
Numeric output only.
No attempt will be made to lookup symbolic names for host addresses.
.It Fl p Ar pattern
You may specify up to 16
.Dq pad
bytes to fill out the packet you send.
This is useful for diagnosing data-dependent problems in a network.
For example,
.Dq Li \-p ff
will cause the sent packet to be filled with all
ones.
.Fl Q
flag,
.Nm
prints out any ICMP error messages caused by its own ECHO_REQUEST
messages.
.It Fl q
Quiet output.
Nothing is displayed except the summary lines at startup time and
when finished.
.It Fl R
Record route.
Includes the
.Tn RECORD_ROUTE
option in the
.Tn ECHO_REQUEST
packet and displays
the route buffer on returned packets.
Note that the IP header is only large enough for nine such routes;
the
.Xr traceroute 8
command is usually better at determining the route packets take to a
particular destination.
Many hosts ignore or discard the
.Tn RECORD_ROUTE
option.
.It Fl r
Bypass the normal routing tables and send directly to a host on an attached
network.
If the host is not on a directly-attached network, an error is returned.
This option can be used to ping a local host through an interface
that has no route through it
.Po
e.g., after the interface was dropped by
.Xr routed 8
.Pc .
.It Fl s Ar packetsize
Specifies the number of data bytes to be sent.
The default is 56, which translates into 64
.Tn ICMP
data bytes when combined
with the 8 bytes of
.Tn ICMP
header data.
You may need to specify
.Fl b
as well to extend socket buffer size.
.It Fl v
Verbose output.
.Tn ICMP
packets other than
.Tn ECHO_RESPONSE
that are received are listed.
.It Fl w
Generate ICMPv6 Node Information FQDN query, rather than echo-request.
.Fl s
has no effect if
.Fl w
is specified.
.It Fl W
Same as
.Fl w .
This option was remained for backward compatibility.
.Fl s
has no effect if
.Fl w
is specified.
.El
.Pp
When using
.Nm
for fault isolation, it should first be run on the local host, to verify
that the local network interface is up and running.
Then, hosts and gateways further and further away should be
.Dq pinged .
Round-trip times and packet loss statistics are computed.
If duplicate packets are received, they are not included in the packet
loss calculation, although the round trip time of these packets is used
in calculating the round-trip time statistics.
When the specified number of packets have been sent
.Pq and received
or if the program is terminated with a
.Dv SIGINT ,
a brief summary is displayed, showing the number of packets sent and
received, and the minimum, maximum, mean, and standard deviation of
the round-trip times.
.Pp
This program is intended for use in network testing, measurement and
management.
Because of the load it can impose on the network, it is unwise to use
.Nm
during normal operations or from automated scripts.
.\" .Sh ICMP PACKET DETAILS
.\" An IP header without options is 20 bytes.
.\" An
.\" .Tn ICMP
.\" .Tn ECHO_REQUEST
.\" packet contains an additional 8 bytes worth of
.\" .Tn ICMP
.\" header followed by an arbitrary amount of data.
.\" When a
.\" .Ar packetsize
.\" is given, this indicated the size of this extra piece of data
.\" .Pq the default is 56 .
.\" Thus the amount of data received inside of an IP packet of type
.\" .Tn ICMP
.\" .Tn ECHO_REPLY
.\" will always be 8 bytes more than the requested data space
.\" .Pq the Tn ICMP header .
.\" .Pp
.\" If the data space is at least eight bytes large,
.\" .Nm
.\" uses the first eight bytes of this space to include a timestamp which
.\" it uses in the computation of round trip times.
.\" If less than eight bytes of pad are specified, no round trip times are
.\" given.
.Sh DUPLICATE AND DAMAGED PACKETS
.Nm Ping6
will report duplicate and damaged packets.
Duplicate packets should never occur when pinging a unicast address,
and seem to be caused by
inappropriate link-level retransmissions.
Duplicates may occur in many situations and are rarely
.Pq if ever
a good sign, although the presence of low levels of duplicates may not
always be cause for alarm.
Duplicates are expected when pinging a broadcast or multicast address,
since they are not really duplicates but replies from different hosts
to the same request.
.Pp
Damaged packets are obviously serious cause for alarm and often
indicate broken hardware somewhere in the
.Nm ping
packet's path
.Pq in the network or in the hosts .
.Sh TRYING DIFFERENT DATA PATTERNS
The
(inter)network
layer should never treat packets differently depending on the data
contained in the data portion.
Unfortunately, data-dependent problems have been known to sneak into
networks and remain undetected for long periods of time.
In many cases the particular pattern that will have problems is something
that does not have sufficient
.Dq transitions ,
such as all ones or all zeros, or a pattern right at the edge, such as
almost all zeros.
It is not
necessarily enough to specify a data pattern of all zeros (for example)
on the command line because the pattern that is of interest is
at the data link level, and the relationship between what you type and
what the controllers transmit can be complicated.
.Pp
This means that if you have a data-dependent problem you will probably
have to do a lot of testing to find it.
If you are lucky, you may manage to find a file that either
cannot
be sent across your network or that takes much longer to transfer than
other similar length files.
You can then examine this file for repeated patterns that you can test
using the
.Fl p
option of
.Nm Ns .
.Sh RETURN VALUES
The
.Nm
command returns an exit status of zero if at least one response was
heard from the specified
.Ar host ;
a status of two if the transmission was successful but no responses
were received; or another value
.Pq from Aq Pa sysexits.h
if an error occurred.
.Sh SEE ALSO
.Xr netstat 1 ,
.Xr ifconfig 8 ,
.Xr routed 8 ,
.Xr ping 8 ,
.Xr traceroute 8 ,
.Xr traceroute6 8
.Sh HISTORY
The
.Nm ping
command appeared in
.Bx 4.3 .
.Nm Ping6
command with IPv6 support first appeared in WIDE Hydrangea IPv6 protocol stack
kit.
.\" .Sh BUGS
.\" (to be written)

1549
sbin/ping6/ping6.c Normal file

File diff suppressed because it is too large Load Diff

29
sbin/rtsol/Makefile Normal file
View File

@ -0,0 +1,29 @@
# Copyright (c) 1996 WIDE Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modifications, are permitted provided that the above copyright notice
# and this paragraph are duplicated in all such forms and that any
# documentation, advertising materials, and other materials related to
# such distribution and use acknowledge that the software was developed
# by the WIDE Project, Japan. The name of the Project may not be used to
# endorse or promote products derived from this software without
# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE.
# $FreeBSD$
SRCDIR= ${.CURDIR}/../../usr.sbin/rtsold
PROG= rtsol
SRCS= rtsold.c rtsol.c if.c probe.c dump.c
CFLAGS+=-DINET6
LDADD+= -lkvm
DPADD+= ${LIBKVM}
NOMAN= yes
.PATH: ${SRCDIR}
.include <bsd.prog.mk>

View File

@ -777,7 +777,7 @@ init_newprefix(struct in6_rrenumreq *irr, struct ifprefix *ifpr,
return error;
rap->ra_ifid = orap->ra_ifid;
rap->ra_flags.anycast = (orap->ra_addr != NULL &&
(orap->ra_addr->ia_flags &
(orap->ra_addr->ia6_flags &
IN6_IFF_ANYCAST) != 0) ? 1 : 0;
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
}

View File

@ -12,6 +12,6 @@ BINGRP= kmem
BINMODE=2555
DPADD= ${LIBKVM} ${LIBIPX} ${LIBNETGRAPH}
LDADD= -lkvm -lipx -lnetgraph
CFLAGS+= -DINET6
CFLAGS+=-DINET6
.include <bsd.prog.mk>

View File

@ -390,23 +390,14 @@ ip6_stats(off, name)
printf("\tMbuf statistics:\n");
printf("\t\t%lu one mbuf\n", ip6stat.ip6s_m1);
for (first = 1, i = 0; i < 32; i++) {
char ifbuf[IFNAMSIZ];
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
printf("\t\t\t%s= %ld\n",
if_indextoname(i, ifbuf),
#else
i,
#endif
ip6stat.ip6s_m2m[i]);
}
}

View File

@ -129,11 +129,11 @@ static struct nlist nl[] = {
{ "_ip6stat" },
#define N_ICMP6STAT 29
{ "_icmp6stat" },
#ifdef notyet
#define N_IPSECSTAT 30
{ "_ipsecstat" },
#define N_IPSEC6STAT 31
{ "_ipsec6stat" },
#ifdef notyet
#define N_PIM6STAT 32
{ "_pim6stat" },
#define N_MRT6PROTO 33

View File

@ -605,7 +605,7 @@ p_rtentry(rt)
WID_DST);
p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST,
#ifdef INET6
kgetsa(rt->rt_gateway)->sa_family == AF_INET6 ? WID_GW6 :
addr.u_sa.sa_family == AF_INET6 ? WID_GW6 :
#endif
WID_GW);
p_flags(rt->rt_flags, "%-6.6s ");
@ -763,16 +763,17 @@ netname6(sa6, mask)
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++) {
if (*p == 0xff)
masklen += 8;
else
break;
}
if (p < lim) {
switch (*p) {
case 0xff:
masklen += 8;
break;
case 0xfe:
masklen += 7;
break;
@ -810,14 +811,10 @@ netname6(sa6, mask)
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);
@ -829,37 +826,14 @@ char *
routename6(sa6)
struct sockaddr_in6 *sa6;
{
#ifdef notyet
static char line[MAXHOSTNAMELEN + 1];
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;
}

View File

@ -0,0 +1,21 @@
# Copyright (c) 1996 WIDE Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modifications, are permitted provided that the above copyright notice
# and this paragraph are duplicated in all such forms and that any
# documentation, advertising materials, and other materials related to
# such distribution and use acknowledge that the software was developed
# by the WIDE Project, Japan. The name of the Project may not be used to
# endorse or promote products derived from this software without
# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE.
# $FreeBSD$
PROG= gifconfig
MAN8= gifconfig.8
CFLAGS+=-DINET6
.include <bsd.prog.mk>

View File

@ -0,0 +1,140 @@
.\" 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.
.\"
.\" $Id: gifconfig.8,v 1.2 1999/10/07 04:25:54 itojun Exp $
.\" $FreeBSD$
.\"
.Dd May 17, 1998
.Dt GIFCONFIG 8
.Os KAME
.\"
.Sh NAME
.Nm gifconfig
.Nd configure generic IP tunnel
.\"
.Sh SYNOPSIS
.Nm
.Ar interface
.Op Ar af
.Op Ar physsrc physdest
.Nm gifconfig
.Fl a
.\"
.Sh DESCRIPTION
.Nm
configures the physical address for the generic IP tunnel
inteface, such as "gif0".
Argument
.Ar physsrc
and
.Ar physdest
are interpreted as the outer source/destination address for
encapsulating IPv4/v6 header.
Argument
.Ar af
specifies the address family for
.Ar physsrc
and
.Ar physdest .
.Ar Af
can be
.Li inet
or
.Li inet6 ,
and will be treated as
.Li inet
if ommitted.
.Pp
.Nm
takes the following optional argument:
.Bl -tag -width Ds
.It Fl a
Display information associated all generic IP tunnel interfaces.
.El
.Pp
Please note that it is very easy to create infinite routing loop,
when you configure tunnel over same address family
.Po
e.g. IPv4-over-IPv4
.Pc .
.\"
.Sh EXAMPLES
If you would like to configure IPv6 over IPv4
.Pq aka IPv6 in IPv4
tunnel between
.Li 10.1.1.1
and
.Li 10.2.3.4 ,
you should perform the following command:
.Bd -literal -offset
# gifconfig gif0 inet 10.1.1.1 10.2.3.4
.Ed
.Pp
.\" To use the
.\" .Li 0.0.0.0
.\" feature to establish a tunnel from host1 to host3
.\" which will encapsulate and carry packets from host2, on host1 do:
.\" .Bd -literal -offset
.\" # ifconfig gif0 inet host1 127.0.0.2 # assign an address to gif0
.\" # gifconfig gif0 inet host1 0.0.0.0 # assign encapsulation addresses
.\" # route add host2 host3 -ifp gif0: # encap host2 packets, send to host3
.\" .Ed
.\" .Pp
.\" Note: the
.\" .Fl ifp
.\" option to route does not work as documented in
.\" most versions of FreeBSD.
.\" .Pp
.\" On host3 do:
.\" .Bd -literal -offset
.\" # ifconfig gif0 inet host3 127.0.0.2 # assign an address to gif0
.\" # gifconfig gif0 inet host3 0.0.0.0 # assign encapsulation addresses
.\" .Ed
.\" .Pp
.\" Now if you ping host2 from host1, the packets should be encapsulated
.\" with outer source address = host1 and outer destination address = host3,
.\" and delivered to host3.
.\" host3 will decapsulate the packet and deliver it normally to host2.
.\" .Pp
This is also possible to use IPv6 as outer proto, by replacing
.Li inet
to
.Li inet6 ,
and IPv4 addresses to some appropriate IPv6 addresses in above example.
.\"
.Sh RETURN VALUES
The command exits with exit status of 1 on errors, 0 on success.
.\"
.Sh SEE ALSO
.Xr gif 4 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
.\" .Sh BUGS
.\" (to be written)

View File

@ -0,0 +1,834 @@
/*
* Copyright (c) 1983, 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$
*/
/*
* gifconfig, derived from ifconfig
*
* @(#) Copyright (c) 1983, 1993\n\
* The Regents of the University of California. All rights reserved.\n
*
* @(#)ifconfig.c 8.2 (Berkeley) 2/16/94
*/
/*
* 951109 - Andrew@pubnix.net - Changed to iterative buffer growing mechanism
* for ifconfig -a so all interfaces are queried.
*
* 960101 - peter@freebsd.org - Blow away the SIOCGIFCONF code and use
* sysctl() to get the structured interface conf
* and parse the messages in there. REALLY UGLY!
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/protosw.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <nlist.h>
#include <kvm.h>
#include <fcntl.h>
struct ifreq ifr;
struct ifaliasreq addreq;
#ifdef INET6
struct in6_ifreq in6_ifr;
struct in6_aliasreq in6_addreq;
#endif
char name[32];
int flags;
int metric;
int mtu;
int setpsrc = 0;
int s;
kvm_t *kvmd;
extern int errno;
#ifdef INET6
char ntop_buf[INET6_ADDRSTRLEN]; /*inet_ntop()*/
#endif
void setifpsrc __P((char *, int));
void setifpdst __P((char *, int));
void setifflags __P((char *, int));
#define NEXTARG 0xffffff
struct cmd {
char *c_name;
int c_parameter; /* NEXTARG means next argv */
void (*c_func) __P((char *, int));
} cmds[] = {
{ "up", IFF_UP, setifflags } ,
{ "down", -IFF_UP, setifflags },
{ 0, 0, setifpsrc },
{ 0, 0, setifpdst },
};
/*
* XNS support liberally adapted from code written at the University of
* Maryland principally by James O'Toole and Chris Torek.
*/
int main __P((int, char *[]));
void status __P((void));
void phys_status __P((int));
void in_status __P((int));
#ifdef INET6
void in6_status __P((int));
#endif
void ether_status __P((int));
void Perror __P((char *));
void in_getaddr __P((char *, int));
#ifdef INET6
void in6_getaddr __P((char *, int));
void in6_getprefix __P((char *, int));
#endif
void printb __P((char *, unsigned int, char *));
int prefix __P((void *, int));
char ntop_buf[INET6_ADDRSTRLEN];
/* Known address families */
struct afswtch {
char *af_name;
short af_af;
void (*af_status) __P((int));
void (*af_getaddr) __P((char *, int));
void (*af_getprefix) __P((char *, int));
u_long af_pifaddr;
caddr_t af_addreq;
caddr_t af_req;
} afs[] = {
#define C(x) ((caddr_t) &x)
{ "inet", AF_INET, in_status, in_getaddr, 0,
SIOCSIFPHYADDR, C(addreq), C(ifr) },
#ifdef INET6
{ "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix,
SIOCSIFPHYADDR_IN6, C(in6_addreq), C(in6_ifr) },
#endif
{ "ether", AF_INET, ether_status, NULL, NULL }, /* XXX not real!! */
{ 0, 0, 0, 0, 0 }
};
struct afswtch *afp = NULL; /*the address family being set or asked about*/
void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
int ifconfig __P((int argc, char *argv[], int af, struct afswtch *rafp));
/*
* Expand the compacted form of addresses as returned via the
* configuration read via sysctl().
*/
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
void
rt_xaddrs(cp, cplim, rtinfo)
caddr_t cp, cplim;
struct rt_addrinfo *rtinfo;
{
struct sockaddr *sa;
int i;
memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
if ((rtinfo->rti_addrs & (1 << i)) == 0)
continue;
rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
ADVANCE(cp, sa);
}
}
/*
* Grunge for new-style sysctl() decoding.. :-(
* Apologies to the world for committing gross things like this in 1996..
*/
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct sockaddr_dl *sdl;
struct rt_addrinfo info;
char *buf, *lim, *next;
int
main(argc, argv)
int argc;
char *argv[];
{
int af = AF_INET;
struct afswtch *rafp = NULL;
size_t needed;
int mib[6];
int all;
if (argc < 2) {
fprintf(stderr, "usage: gifconfig interface %s",
"[ af ] physsrc physdst\n");
exit(1);
}
argc--, argv++;
strncpy(name, *argv, sizeof(name));
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
argc--, argv++;
if (argc > 0) {
for (afp = rafp = afs; rafp->af_name; rafp++)
if (strcmp(rafp->af_name, *argv) == 0) {
afp = rafp; argc--; argv++;
break;
}
rafp = afp;
af = ifr.ifr_addr.sa_family = rafp->af_af;
}
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0; /* address family */
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
/* if particular family specified, only ask about it */
if (afp) {
mib[3] = afp->af_af;
}
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
errx(1, "iflist-sysctl-estimate");
if ((buf = malloc(needed)) == NULL)
errx(1, "malloc");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
errx(1, "actual retrieval of interface table");
lim = buf + needed;
all = 0;
if (strcmp(name, "-a") == 0)
all = 1; /* All interfaces */
else if (strcmp(name, "-au") == 0)
all = 2; /* All IFF_UPinterfaces */
else if (strcmp(name, "-ad") == 0)
all = 3; /* All !IFF_UP interfaces */
for (next = buf; next < lim; next += ifm->ifm_msglen) {
ifm = (struct if_msghdr *)next;
/* XXX: Swallow up leftover NEWADDR messages */
if (ifm->ifm_type == RTM_NEWADDR)
continue;
if (ifm->ifm_type == RTM_IFINFO) {
sdl = (struct sockaddr_dl *)(ifm + 1);
flags = ifm->ifm_flags;
} else {
errx(1, "out of sync parsing NET_RT_IFLIST");
}
switch(all) {
case -1:
case 0:
if (strlen(name) != sdl->sdl_nlen)
continue; /* not same len */
if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
continue; /* not same name */
break;
case 1:
break; /* always do it */
case 2:
if ((flags & IFF_UP) == 0)
continue; /* not up */
break;
case 3:
if (flags & IFF_UP)
continue; /* not down */
break;
}
/*
* Let's just do it for gif only
*/
if (sdl->sdl_type != IFT_GIF) {
if (all != 0)
continue;
fprintf(stderr, "gifconfig: %s is not gif.\n",
ifr.ifr_name);
exit(1);
}
if (all > 0) {
strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
name[sdl->sdl_nlen] = '\0';
}
if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
perror("gifconfig: socket");
exit(1);
}
ifconfig(argc,argv,af,rafp);
close(s);
if (all == 0) {
all = -1; /* flag it as 'done' */
break;
}
}
free(buf);
if (all == 0)
errx(1, "interface %s does not exist", name);
exit (0);
}
int
ifconfig(argc, argv, af, rafp)
int argc;
char *argv[];
int af;
struct afswtch *rafp;
{
af = 0; /*fool gcc*/
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
#ifdef INET6
strncpy(in6_ifr.ifr_name, name, sizeof in6_ifr.ifr_name);
#endif /* INET6 */
if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
perror("ioctl (SIOCGIFMETRIC)");
else
metric = ifr.ifr_metric;
#if defined(SIOCGIFMTU) && !defined(__OpenBSD__)
if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
perror("ioctl (SIOCGIFMTU)");
else
mtu = ifr.ifr_mtu;
#else
mtu = 0;
#endif
if (argc == 0) {
status();
return(0);
}
while (argc > 0) {
register struct cmd *p;
for (p = cmds; p->c_name; p++)
if (strcmp(*argv, p->c_name) == 0)
break;
if (p->c_name == 0 && setpsrc)
p++; /* got src, do dst */
if (p->c_func) {
if (p->c_parameter == NEXTARG) {
if (argv[1] == NULL)
errx(1, "'%s' requires argument",
p->c_name);
(*p->c_func)(argv[1], 0);
argc--, argv++;
} else
(*p->c_func)(*argv, p->c_parameter);
}
argc--, argv++;
}
if (1 /*newaddr*/) {
strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name);
if (ioctl(s, rafp->af_pifaddr, rafp->af_addreq) < 0)
Perror("ioctl (SIOCSIFPHYADDR)");
}
return(0);
}
#define PSRC 0
#define PDST 1
/*ARGSUSED*/
void
setifpsrc(addr, param)
char *addr;
int param;
{
param = 0; /*fool gcc*/
(*afp->af_getaddr)(addr, PSRC);
setpsrc = 1;
}
/*ARGSUSED*/
void
setifpdst(addr, param)
char *addr;
int param;
{
param = 0; /*fool gcc*/
(*afp->af_getaddr)(addr, PDST);
}
void
setifflags(vname, value)
char *vname;
int value;
{
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
Perror("ioctl (SIOCGIFFLAGS)");
exit(1);
}
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
flags = ifr.ifr_flags;
if (value < 0) {
value = -value;
flags &= ~value;
} else
flags |= value;
ifr.ifr_flags = flags;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
Perror(vname);
}
#define IFFBITS \
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
/*
* Print the status of the interface. If an address family was
* specified, show it and it only; otherwise, show them all.
*/
void
status()
{
struct afswtch *p = NULL;
char *mynext;
struct if_msghdr *myifm;
printf("%s: ", name);
printb("flags", flags, IFFBITS);
if (metric)
printf(" metric %d", metric);
if (mtu)
printf(" mtu %d", mtu);
putchar('\n');
/*
* XXX: Sigh. This is bad, I know. At this point, we may have
* *zero* RTM_NEWADDR's, so we have to "feel the water" before
* incrementing the loop. One day, I might feel inspired enough
* to get the top level loop to pass a count down here so we
* dont have to mess with this. -Peter
*/
myifm = ifm;
while (1) {
mynext = next + ifm->ifm_msglen;
if (mynext >= lim)
break;
myifm = (struct if_msghdr *)mynext;
if (myifm->ifm_type != RTM_NEWADDR)
break;
next = mynext;
ifm = (struct if_msghdr *)next;
ifam = (struct ifa_msghdr *)myifm;
info.rti_addrs = ifam->ifam_addrs;
/* Expand the compacted addresses */
rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
&info);
if (afp) {
if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family &&
afp->af_status != ether_status) {
p = afp;
if (p->af_status != ether_status)
(*p->af_status)(1);
}
} else for (p = afs; p->af_name; p++) {
if (p->af_af == info.rti_info[RTAX_IFA]->sa_family &&
p->af_status != ether_status)
(*p->af_status)(0);
}
}
if (afp == NULL || afp->af_status == ether_status)
ether_status(0);
else if (afp && !p) {
warnx("%s has no %s IFA address!", name, afp->af_name);
}
phys_status(0);
}
void
phys_status(force)
int force;
{
char psrcaddr[256];
char pdstaddr[256];
char hostname[NI_MAXHOST];
u_long srccmd, dstcmd;
int flags = NI_NUMERICHOST;
struct ifreq *ifrp;
char *ver = "";
force = 0; /*fool gcc*/
psrcaddr[0] = pdstaddr[0] = '\0';
#ifdef INET6
srccmd = SIOCGIFPSRCADDR_IN6;
dstcmd = SIOCGIFPDSTADDR_IN6;
ifrp = (struct ifreq *)&in6_ifr;
#else /* INET6 */
ifrp = ifr;
srccmd = SIOCGIFPSRCADDR;
dstcmd = SIOCGIFPDSTADDR;
#endif /* INET6 */
if (0 <= ioctl(s, srccmd, (caddr_t)ifrp)) {
getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
hostname, NI_MAXHOST, 0, 0, flags);
#ifdef INET6
if (ifrp->ifr_addr.sa_family == AF_INET6)
ver = "6";
#endif /* INET6 */
sprintf(psrcaddr, "inet%s %s", ver, hostname);
}
if (0 <= ioctl(s, dstcmd, (caddr_t)ifrp)) {
getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
hostname, NI_MAXHOST, 0, 0, flags);
sprintf(pdstaddr, "%s", hostname);
}
printf("\tphysical address %s --> %s\n", psrcaddr, pdstaddr);
}
void
in_status(force)
int force;
{
struct sockaddr_in *sin, null_sin;
#if 0
char *inet_ntoa();
#endif
memset(&null_sin, 0, sizeof(null_sin));
sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
if (!sin || sin->sin_family != AF_INET) {
if (!force)
return;
/* warnx("%s has no AF_INET IFA address!", name); */
sin = &null_sin;
}
printf("\tinet %s ", inet_ntoa(sin->sin_addr));
if (flags & IFF_POINTOPOINT) {
/* note RTAX_BRD overlap with IFF_BROADCAST */
sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
if (!sin)
sin = &null_sin;
printf("--> %s ", inet_ntoa(sin->sin_addr));
}
sin = (struct sockaddr_in *)info.rti_info[RTAX_NETMASK];
if (!sin)
sin = &null_sin;
printf("netmask 0x%x ", (u_int32_t)ntohl(sin->sin_addr.s_addr));
if (flags & IFF_BROADCAST) {
/* note RTAX_BRD overlap with IFF_POINTOPOINT */
sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
if (sin && sin->sin_addr.s_addr != 0)
printf("broadcast %s", inet_ntoa(sin->sin_addr));
}
putchar('\n');
}
#ifdef INET6
void
in6_status(force)
int force;
{
struct sockaddr_in6 *sin, null_sin;
#if 0
char *inet_ntop();
#endif
memset(&null_sin, 0, sizeof(null_sin));
sin = (struct sockaddr_in6 *)info.rti_info[RTAX_IFA];
if (!sin || sin->sin6_family != AF_INET6) {
if (!force)
return;
/* warnx("%s has no AF_INET6 IFA address!", name); */
sin = &null_sin;
}
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 ther interfaces do not have valid destination
* address.
*/
if (sin->sin6_family == AF_INET6) {
if (!sin)
sin = &null_sin;
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)));
putchar('\n');
}
#endif /*INET6*/
/*ARGSUSED*/
void
ether_status(dummy)
int dummy;
{
char *cp;
int n;
dummy = 0; /*fool gcc*/
cp = (char *)LLADDR(sdl);
if ((n = sdl->sdl_alen) > 0) {
if (sdl->sdl_type == IFT_ETHER)
printf ("\tether ");
else
printf ("\tlladdr ");
while (--n >= 0)
printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' ');
putchar('\n');
}
}
void
Perror(cmd)
char *cmd;
{
extern int errno;
switch (errno) {
case ENXIO:
errx(1, "%s: no such interface", cmd);
break;
case EPERM:
errx(1, "%s: permission denied", cmd);
break;
default:
err(1, "%s", cmd);
}
}
#define SIN(x) ((struct sockaddr_in *) &(x))
struct sockaddr_in *sintab[] = {
SIN(addreq.ifra_addr), SIN(addreq.ifra_dstaddr)};
void
in_getaddr(s, which)
char *s;
int which;
{
register struct sockaddr_in *sin = sintab[which];
struct hostent *hp;
struct netent *np;
sin->sin_len = sizeof(*sin);
sin->sin_family = AF_INET;
if (inet_aton(s, &sin->sin_addr))
;
else if ((hp = gethostbyname(s)) != NULL)
bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
else if ((np = getnetbyname(s)) != NULL)
sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
else
errx(1, "%s: bad value", s);
}
#ifdef INET6
#define SIN6(x) ((struct sockaddr_in6 *) &(x))
struct sockaddr_in6 *sin6tab[] = {
SIN6(in6_addreq.ifra_addr), SIN6(in6_addreq.ifra_dstaddr)};
void
in6_getaddr(s, which)
char *s;
int which;
{
register struct sockaddr_in6 *sin = sin6tab[which];
sin->sin6_len = sizeof(*sin);
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)
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);
sin->sin6_family = AF_INET6;
if ((len == 0) || (len == 128)) {
memset(&sin->sin6_addr, -1, sizeof(struct in6_addr));
return;
}
for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8)
*cp++ = -1;
*cp = (-1) << (8 - len);
}
#endif
/*
* Print a value a la the %b format of the kernel's printf
*/
void
printb(s, v, bits)
char *s;
register unsigned int v;
register char *bits;
{
register int i, any = 0;
register char c;
if (bits && *bits == 8)
printf("%s=%o", s, v & 0xffff);
else
printf("%s=%x", s, v & 0xffff);
bits++;
if (bits) {
putchar('<');
while ((i = *bits++) != 0) {
if ((v & (1 << (i-1))) != 0) {
if (any)
putchar(',');
any = 1;
for (; (c = *bits) > 32; bits++)
putchar(c);
} else
for (; *bits > 32; bits++)
;
}
putchar('>');
}
}
#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);
}
#endif /*INET6*/

View File

@ -0,0 +1,14 @@
# @(#)Makefile 8.1 (Berkeley) 6/5/93
# $FreeBSD$
PROG= ifmcstat
MAN8= ifmcstat.8
BINGRP= kmem
BINMODE=2555
LDADD= -lkvm
DPADD= ${LIBKVM}
CFLAGS+=-DINET6
.include <bsd.prog.mk>

View File

@ -0,0 +1,34 @@
.\" Copyright (c) 1996 WIDE Project. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modifications, are permitted provided that the above copyright notice
.\" and this paragraph are duplicated in all such forms and that any
.\" documentation, advertising materials, and other materials related to
.\" such distribution and use acknowledge that the software was developed
.\" by the WIDE Project, Japan. The name of the Project may not be used to
.\" endorse or promote products derived from this software without
.\" specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
.\" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
.\" LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
.\" A PARTICULAR PURPOSE.
.\"
.\" $FreeBSD$
.\"
.Dd May 21, 1998
.Dt IFMCSTAT 8
.Os KAME
.Sh NAME
.Nm ifmcstat
.Nd dump multicast group management statistics per interface
.Sh SYNOPSIS
.Nm
.\"
.Sh DESCRIPTION
The
.Nm Ifmcstat
dumps multicast group information in the kernel.
.Pp
There are no command-line options.
.\"
.\" .Sh SEE ALSO
.\" RFC2080 -- IPng for IPv6. G. Malkin, R. Minnear. January 1997.

View File

@ -0,0 +1,338 @@
/*
* 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$
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <kvm.h>
#include <nlist.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
# include <net/if_var.h>
#endif
#include <net/if_types.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#ifndef __NetBSD__
# ifdef __FreeBSD__
# define KERNEL
# endif
# include <netinet/if_ether.h>
# ifdef __FreeBSD__
# undef KERNEL
# endif
#else
# include <net/if_ether.h>
#endif
#include <netinet/in_var.h>
#include <arpa/inet.h>
kvm_t *kvmd;
struct nlist nl[] = {
#define N_IFNET 0
{ "_ifnet" },
{ "" },
};
const char *inet6_n2a __P((struct in6_addr *));
int main __P((void));
char *ifname __P((struct ifnet *));
void kread __P((u_long, void *, int));
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
void acmc __P((struct ether_multi *));
#endif
void if6_addrlist __P((struct ifaddr *));
void in6_multilist __P((struct in6_multi *));
struct in6_multi * in6_multientry __P((struct in6_multi *));
#if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__)
#ifdef __bsdi__
struct ether_addr {
u_int8_t ether_addr_octet[6];
};
#endif
static char *ether_ntoa __P((struct ether_addr *));
#endif
#define KREAD(addr, buf, type) \
kread((u_long)addr, (void *)buf, sizeof(type))
const char *inet6_n2a(p)
struct in6_addr *p;
{
static char buf[BUFSIZ];
if (IN6_IS_ADDR_UNSPECIFIED(p))
return "*";
return inet_ntop(AF_INET6, (void *)p, buf, sizeof(buf));
}
int main()
{
char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ];
struct ifnet *ifp, *nifp, ifnet;
#ifndef __NetBSD__
struct arpcom arpcom;
#else
struct ethercom ec;
struct sockaddr_dl sdl;
#endif
if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) {
perror("kvm_openfiles");
exit(1);
}
if (kvm_nlist(kvmd, nl) < 0) {
perror("kvm_nlist");
exit(1);
}
if (nl[N_IFNET].n_value == 0) {
printf("symbol %s not found\n", nl[N_IFNET].n_name);
exit(1);
}
KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *);
while (ifp) {
KREAD(ifp, &ifnet, struct ifnet);
printf("%s:\n", if_indextoname(ifnet.if_index, ifname));
#if defined(__NetBSD__) || defined(__OpenBSD__)
if6_addrlist(ifnet.if_addrlist.tqh_first);
nifp = ifnet.if_list.tqe_next;
#elif defined(__FreeBSD__) && __FreeBSD__ >= 3
if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
nifp = ifnet.if_link.tqe_next;
#else
if6_addrlist(ifnet.if_addrlist);
nifp = ifnet.if_next;
#endif
#ifdef __NetBSD__
KREAD(ifnet.if_sadl, &sdl, struct sockaddr_dl);
if (sdl.sdl_type == IFT_ETHER) {
printf("\tenaddr %s",
ether_ntoa((struct ether_addr *)LLADDR(&sdl)));
KREAD(ifp, &ec, struct ethercom);
printf(" multicnt %d", ec.ec_multicnt);
acmc(ec.ec_multiaddrs.lh_first);
printf("\n");
}
#elif defined(__FreeBSD__) && __FreeBSD__ >= 3
/* not supported */
#else
if (ifnet.if_type == IFT_ETHER) {
KREAD(ifp, &arpcom, struct arpcom);
printf("\tenaddr %s",
ether_ntoa((struct ether_addr *)arpcom.ac_enaddr));
KREAD(ifp, &arpcom, struct arpcom);
printf(" multicnt %d", arpcom.ac_multicnt);
#ifdef __OpenBSD__
acmc(arpcom.ac_multiaddrs.lh_first);
#else
acmc(arpcom.ac_multiaddrs);
#endif
printf("\n");
}
#endif
ifp = nifp;
}
exit(0);
/*NOTREACHED*/
}
char *ifname(ifp)
struct ifnet *ifp;
{
static char buf[BUFSIZ];
#if defined(__NetBSD__) || defined(__OpenBSD__)
KREAD(ifp->if_xname, buf, IFNAMSIZ);
#else
KREAD(ifp->if_name, buf, IFNAMSIZ);
#endif
return buf;
}
void kread(addr, buf, len)
u_long addr;
void *buf;
int len;
{
if (kvm_read(kvmd, addr, buf, len) != len) {
perror("kvm_read");
exit(1);
}
}
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
void acmc(am)
struct ether_multi *am;
{
struct ether_multi em;
while (am) {
KREAD(am, &em, struct ether_multi);
printf("\n\t\t");
printf("%s -- ", ether_ntoa((struct ether_addr *)em.enm_addrlo));
printf("%s ", ether_ntoa((struct ether_addr *)&em.enm_addrhi));
printf("%d", em.enm_refcount);
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
am = em.enm_next;
#else
am = em.enm_list.le_next;
#endif
}
}
#endif
void
if6_addrlist(ifap)
struct ifaddr *ifap;
{
static char in6buf[BUFSIZ];
struct ifaddr ifa;
struct sockaddr sa;
struct in6_ifaddr if6a;
struct in6_multi *mc = 0;
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
struct ifaddr *ifap0;
#endif /* __FreeBSD__ >= 3 */
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
ifap0 = ifap;
#endif /* __FreeBSD__ >= 3 */
while (ifap) {
KREAD(ifap, &ifa, struct ifaddr);
if (ifa.ifa_addr == NULL)
goto nextifap;
KREAD(ifa.ifa_addr, &sa, struct sockaddr);
if (sa.sa_family != PF_INET6)
goto nextifap;
KREAD(ifap, &if6a, struct in6_ifaddr);
printf("\tinet6 %s\n",
inet_ntop(AF_INET6,
(const void *)&if6a.ia_addr.sin6_addr,
in6buf, sizeof(in6buf)));
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
mc = mc ? mc : if6a.ia6_multiaddrs.lh_first;
#endif
nextifap:
#if defined(__NetBSD__) || defined(__OpenBSD__)
ifap = ifa.ifa_list.tqe_next;
#elif defined(__FreeBSD__) && __FreeBSD__ >= 3
ifap = ifa.ifa_link.tqe_next;
#else
ifap = ifa.ifa_next;
#endif /* __FreeBSD__ >= 3 */
}
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
if (ifap0) {
struct ifnet ifnet;
struct ifmultiaddr ifm, *ifmp = 0;
struct sockaddr_in6 sin6;
struct in6_multi in6m;
struct sockaddr_dl sdl;
int in6_multilist_done = 0;
KREAD(ifap0, &ifa, struct ifaddr);
KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
if (ifnet.if_multiaddrs.lh_first)
ifmp = ifnet.if_multiaddrs.lh_first;
while (ifmp) {
KREAD(ifmp, &ifm, struct ifmultiaddr);
if (ifm.ifma_addr == NULL)
goto nextmulti;
KREAD(ifm.ifma_addr, &sa, struct sockaddr);
if (sa.sa_family != AF_INET6)
goto nextmulti;
(void)in6_multientry((struct in6_multi *)
ifm.ifma_protospec);
if (ifm.ifma_lladdr == 0)
goto nextmulti;
KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl);
printf("\t\t\tmcast-macaddr %s multicnt %d\n",
ether_ntoa((struct ether_addr *)LLADDR(&sdl)),
ifm.ifma_refcount);
nextmulti:
ifmp = ifm.ifma_link.le_next;
}
}
#else
if (mc)
in6_multilist(mc);
#endif
}
struct in6_multi *
in6_multientry(mc)
struct in6_multi *mc;
{
static char mcbuf[BUFSIZ];
struct in6_multi multi;
KREAD(mc, &multi, struct in6_multi);
printf("\t\tgroup %s\n", inet_ntop(AF_INET6,
(const void *)&multi.in6m_addr,
mcbuf, sizeof(mcbuf)));
return(multi.in6m_entry.le_next);
}
void
in6_multilist(mc)
struct in6_multi *mc;
{
while (mc)
mc = in6_multientry(mc);
}
#if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__)
static char *
ether_ntoa(e)
struct ether_addr *e;
{
static char buf[20];
u_char *p;
p = (u_char *)e;
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
p[0], p[1], p[2], p[3], p[4], p[5]);
return buf;
}
#endif

12
usr.sbin/prefix/Makefile Normal file
View File

@ -0,0 +1,12 @@
# From: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.1.1.1 1999/08/08 23:31:13 itojun Exp $
# $FreeBSD$
PROG= prefix
SRCS= prefix.c
MAN8= prefix.8
CFLAGS+=-DINET6
.include <bsd.prog.mk>

217
usr.sbin/prefix/prefix.8 Normal file
View File

@ -0,0 +1,217 @@
.\" 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.
.\"
.\" $Id: prefix.8,v 1.1.1.1 1999/08/08 23:31:13 itojun Exp $
.\" $FreeBSD$
.\"
.Dd October 10, 1998
.Dt PREFIX 8
.Os KAME
.Sh NAME
.Nm prefix
.Nd configure network interface prefixes
.Sh SYNOPSIS
.Nm prefix
.Ar interface prefix
.Op Ar parameters
.Op Cm set|delete
.Nm prefix
.Ar interface
.Cm matchpr
.Ar match_prefix
.Cm mp_len
.Ar match_prefix_len
.Cm usepr
.Ar use_prefix
.Cm up_uselen
.Ar use_prefix_len
.Op Ar parameters
.Op Cm add|change|setglobal
.Nm prefix
.Fl a
.Op Fl d
.Op Fl u
.Cm matchpr
.Ar match_prefix
.Cm mp_len
.Ar match_prefix_len
.Cm usepr
.Ar use_prefix
.Cm up_uselen
.Ar use_prefix_uselen
.Op Ar parameters
.Op Cm add|change|setglobal
.Sh DESCRIPTION
.Nm Prefix
is used to assign an prefix
to a network interface and/or renumbering
network interface prefixes.
.Nm Prefix
must be used at boot time to define the network prefix
of each interface present on a machine; it may also be used at
a later time to renumbering multiple interface's prefixes
and other prefix related parameters.
.Nm Prefix
is router-only command, so you must do following to use it.
.Dl % sysctl -w net.inet6.ip6.forwarding=1
If net.inet6.ip6.forwarding is set to 0,
.Nm Prefix
command fails by EPERM error.
.Pp
The following options are available:
.Bl -tag -width indent
.It Ar interface
Specify an
.Ar interface
for which
.Ar prefix
is/are assigned or renumbered to.
This parameter is a string of the form
.Dq name unit ,
for example,
.Dq en0 .
.It Ar prefix
Assign/Delete an
.Ar prefix
to a network interface.
.It Cm prefixlen Ar len
Specify that
.Ar len
bits are reserved as identifier for IPv6 sub-networks in
.Ar prefix.
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.
.It Cm matchpr Ar match_prefix
Specify
.Ar match_prefix
that is used for matching with preassigned prefixes to which
.Cm add|change|setglobal
command should be applied.
.It Cm mp_len Ar match_prefix_len
Specify the starting part of
.Ar match_prefix
to be used for matching with preassigned prefixes, as decimal bit number.
.It Cm mp_minlen Ar match_prefix_minlen
Specify the minimum length of prefixes which is allowed to be matched to
.Ar match_prefix ,
as decimal bit number.
.Cm add|change|setglobal
is not applied to preassigned prefixes with smaller prefix len than
.Ar match_prefix_minlen .
.It Cm mp_maxlen Ar match_prefix_maxlen
Specify the maximum length of prefixes which is allowed to be matched to
.Ar match_prefix ,
as decimal bit number.
.Cm add|change|setglobal
is not applied to preassigned prefixes with bigger prefix len than
.Ar match_prefix_maxlen .
.It Cm usepr Ar use_prefix
Specify
.Ar use_prefix
that is used for prefixes to be added on
.Cm add|change|setglobal
command.
.It Cm up_uselen Ar use_prefix_uselen
Specify the starting part of
.Ar use_prefix
copied to the starting part of prefixes to be added on
.Cm add|change|setglobal
command, as decimal bit number.
.It Cm up_keeplen Ar use_prefix_keeplen
Specify the midium part of
.Ar use_prefix
just next to the starting part specified by
.Ar use_prefix_uselen
, as decimal bit number.
Contiguous bits part in the same bit position of an existent prefix
matched with
.Ar match_prefix
is copied to the same bit position of prefixes to be added.
.It Cm pltime Ar time
Assign an
.Ar time
as prefix preferred life time for a prefix to be added.
Valid value for
.Ar time
is decimal seconds number or special format as "d00h00m00s00",
where 00 can take any decimal number, and "d" means days, "h" means hours,
"m" means minutes, "s" means seconds. And alternatively, special keyword
"infinity" can be also be specified.
.It Cm vltime Ar time
Assign an
.Ar time
as prefix valid life time for a prefix to be added.
Valid value for
.Ar time
is same as for
.Cm pltime.
.It Cm raf_auto
Enable the autonomous address auto configuration for the prefix to be
added.
.It Fl raf_auto
Disable the autonomous address auto configuration for the prefix to be
added.
.It Cm raf_onlink
Let the prefix to be added to have onlink nature for the assigned
interface.
.It Fl raf_onlink
Let the prefix to be added not to have onlink nature for the assigned
interface.
.It Cm rrf_decrprefd
Enable the decrementation of the pltime.
.It Fl rrf_decrprefd
Disable the decrementation of the pltime.
.It Cm rrf_decrvalid
Enable the decrementation of the vltime.
.It Fl rrf_decrvalid
Disable the decrementation of the vltime.
.El
.Sh DIAGNOSTICS
Messages indicating the specified interface does not exist, the
requested prefix is unknown, or the user is not privileged and
tried to alter an interface's configuration.
.Sh SEE ALSO
M. Crawford,
Router Renumbering for IPv6,
internet-draft,
draft-ietf-ipngwg-router-renum-05.txt
.Pp
.Xr ifconfig 8 ,
.Xr netstat 1 ,
.Xr netintro 4 ,
.Xr rc 8 ,
.Xr routed 8
.Sh HISTORY
The
.Nm
command first appeared in WIDE/KAME IPv6 protocol stack kit.
.\"
.\" .Sh BUGS
.\" (to be written)

592
usr.sbin/prefix/prefix.c Normal file
View File

@ -0,0 +1,592 @@
/*
* 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$
*/
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEF_ADVVALIDLIFETIME 2592000
#define DEF_ADVPREFERREDLIFETIME 604800
struct in6_prefixreq prereq = {{NULL}, /* interface name */
PR_ORIG_STATIC,
64, /* default plen */
2592000, /* vltime=30days */
604800, /* pltime=7days */
/* ra onlink=1 autonomous=1 */
{{1,1,0}},
{NULL}}; /* prefix */
struct in6_rrenumreq rrreq = {{NULL}, /* interface name */
PR_ORIG_STATIC, /* default origin */
64, /* default match len */
0, /* default min match len */
128, /* default max match len */
0, /* default uselen */
0, /* default keeplen */
{1,1,0}, /* default raflag mask */
2592000, /* vltime=30days */
604800, /* pltime=7days */
/* ra onlink=1 autonomous=1 */
{{1,1,0}},
{NULL}, /* match prefix */
{NULL} /* use prefix */
};
#define C(x) ((caddr_t) &x)
struct prefix_cmds {
const char *errmsg;
int cmd;
caddr_t req;
} prcmds[] = {
{"SIOCSIFPREFIX_IN6 failed", SIOCSIFPREFIX_IN6, C(prereq)},
{"SIOCDIFPREFIX_IN6 failed", SIOCDIFPREFIX_IN6, C(prereq)},
{"SIOCAIFPREFIX_IN6 failed", SIOCAIFPREFIX_IN6, C(rrreq)},
{"SIOCCIFPREFIX_IN6 failed", SIOCCIFPREFIX_IN6, C(rrreq)},
{"SIOCSGIFPREFIX_IN6 failed", SIOCSGIFPREFIX_IN6, C(rrreq)}
};
#define PREF_CMD_SET 0
#define PREF_CMD_DELETE 1
#define PREF_CMD_ADD 2
#define PREF_CMD_CHANGE 3
#define PREF_CMD_SETGLOBAL 4
#define PREF_CMD_MAX 5
u_int prcmd = PREF_CMD_SET; /* default command */
char name[32];
int flags;
int newprefix_setdel, newprefix_match, newprefix_use, newprefix_uselen,
newprefix_keeplen;
char ntop_buf[INET6_ADDRSTRLEN]; /*inet_ntop()*/
void Perror __P((const char *cmd));
int prefix __P((int argc, char *const *argv));
void usage __P((void));
void setlifetime __P((const char *atime, u_int32_t *btime));
int all, explicit_prefix = 0;
typedef void c_func __P((const char *cmd, int arg));
c_func set_vltime, set_pltime, set_raf_onlink,
set_raf_auto, set_rrf_decrvalid, set_rrf_decrprefd,
get_setdelprefix, get_matchprefix, get_useprefix, set_matchlen,
set_match_minlen, set_match_maxlen,
set_use_uselen, set_use_keeplen, set_prefix_cmd;
void getprefixlen __P((const char *, int));
void getprefix __P((const char *, int));
#define NEXTARG 0xffffff
const
struct cmd {
const char *c_name;
int c_parameter; /* NEXTARG means next argv */
void (*c_func) __P((const char *, int));
} cmds[] = {
{ "set", PREF_CMD_SET, set_prefix_cmd },
{ "delete", PREF_CMD_DELETE, set_prefix_cmd },
{ "prefixlen", NEXTARG, getprefixlen },
{ "add", PREF_CMD_ADD, set_prefix_cmd },
{ "change", PREF_CMD_CHANGE, set_prefix_cmd },
{ "setglobal", PREF_CMD_SETGLOBAL, set_prefix_cmd },
{ "matchpr", NEXTARG, get_matchprefix },
{ "usepr", NEXTARG, get_useprefix },
{ "mp_len", NEXTARG, set_matchlen },
{ "mp_minlen", NEXTARG, set_match_minlen },
{ "mp_maxlen", NEXTARG, set_match_maxlen },
{ "up_uselen", NEXTARG, set_use_uselen },
{ "up_keeplen", NEXTARG, set_use_keeplen },
{ "vltime", NEXTARG, set_vltime },
{ "pltime", NEXTARG, set_pltime },
{ "raf_onlink", 1, set_raf_onlink },
{ "-raf_onlink", 0, set_raf_onlink },
{ "raf_auto", 1, set_raf_auto },
{ "-raf_auto", 0, set_raf_auto },
{ "rrf_decrvalid", 1, set_rrf_decrvalid },
{ "-rrf_decrvalid", 0, set_rrf_decrvalid },
{ "rrf_decrprefd", 1, set_rrf_decrprefd },
{ "-rrf_decrprefd", 0, set_rrf_decrprefd },
{ 0, 0, get_setdelprefix },
{ 0, 0, 0 },
};
void
usage()
{
fprintf(stderr, "%s",
"usage: prefix interface prefix_value [parameters] [set|delete]\n"
" prefix interface\n"
" matchpr matchpr_value mp_len mp_len_value\n"
" usepr usepr_value up_uselen up_uselen_value\n"
" [parameters] [add|change|setglobal]\n"
" prefix -a [-d] [-u]\n"
" matchpr matchpr_value mp_len mp_len_value\n"
" usepr usepr_value up_uselen up_uselen_value\n"
" [parameters] [add|change|setglobal]\n");
exit(1);
}
int
main(argc, argv)
int argc;
char *const *argv;
{
int c;
int downonly, uponly;
int foundit = 0;
int addrcount;
struct if_msghdr *ifm, *nextifm;
struct ifa_msghdr *ifam;
struct sockaddr_dl *sdl;
char *buf, *lim, *next;
size_t needed;
int mib[6];
/* Parse leading line options */
all = downonly = uponly = 0;
while ((c = getopt(argc, argv, "adu")) != -1) {
switch (c) {
case 'a': /* scan all interfaces */
all++;
break;
case 'd': /* restrict scan to "down" interfaces */
downonly++;
break;
case 'u': /* restrict scan to "up" interfaces */
uponly++;
break;
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
/* nonsense.. */
if (uponly && downonly)
usage();
if (!all) {
/* not listing, need an argument */
if (argc < 1)
usage();
strncpy(name, *argv, sizeof(name));
argc--, argv++;
}
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET6; /* address family */
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
errx(1, "iflist-sysctl-estimate");
if ((buf = malloc(needed)) == NULL)
errx(1, "malloc");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
errx(1, "actual retrieval of interface table");
lim = buf + needed;
next = buf;
while (next < lim) {
ifm = (struct if_msghdr *)next;
if (ifm->ifm_type == RTM_IFINFO) {
sdl = (struct sockaddr_dl *)(ifm + 1);
flags = ifm->ifm_flags;
} else {
fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n");
fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO,
ifm->ifm_type);
fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next,
lim);
exit (1);
}
next += ifm->ifm_msglen;
ifam = NULL;
addrcount = 0;
while (next < lim) {
nextifm = (struct if_msghdr *)next;
if (nextifm->ifm_type != RTM_NEWADDR)
break;
if (ifam == NULL)
ifam = (struct ifa_msghdr *)nextifm;
addrcount++;
next += nextifm->ifm_msglen;
}
if (all) {
if (uponly)
if ((flags & IFF_UP) == 0)
continue; /* not up */
if (downonly)
if (flags & IFF_UP)
continue; /* not down */
strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
name[sdl->sdl_nlen] = '\0';
} else {
if (strlen(name) != sdl->sdl_nlen)
continue; /* not same len */
if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
continue; /* not same name */
}
if (argc > 0)
prefix(argc, argv);
#if 0
else {
/* TODO: print prefix status by sysctl */
}
#endif
if (all == 0) {
foundit++; /* flag it as 'done' */
break;
}
}
free(buf);
if (all == 0 && foundit == 0)
errx(1, "interface %s does not exist", name);
exit (0);
}
int
prefix(int argc, char *const *argv)
{
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
while (argc > 0) {
register const struct cmd *p;
for (p = cmds; p->c_name; p++)
if (strcmp(*argv, p->c_name) == 0)
break;
if (p->c_func) {
if (p->c_parameter == NEXTARG) {
if (argv[1] == NULL)
errx(1, "'%s' requires argument",
p->c_name);
(*p->c_func)(argv[1], 0);
argc--, argv++;
} else
(*p->c_func)(*argv, p->c_parameter);
}
argc--, argv++;
}
if (prcmd > PREF_CMD_MAX) {
Perror("ioctl: unknown prefix cmd");
goto end;
}
if (prcmd == PREF_CMD_SET || prcmd == PREF_CMD_DELETE) {
if (!newprefix_setdel)
usage();
} else { /* ADD|CHANGE|SETGLOBAL */
if (!newprefix_match)
usage();
}
if (!newprefix_use)
rrreq.irr_u_uselen = 0; /* make clear that no use_prefix */
else if (newprefix_keeplen == NULL && rrreq.irr_u_uselen < 64)
/* init keeplen to make uselen + keeplen equal 64 */
rrreq.irr_u_keeplen = 64 - rrreq.irr_u_uselen;
if (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. */
getprefixlen("64", 0);
}
strncpy(prcmds[prcmd].req, name, IFNAMSIZ);
if (ioctl(s, prcmds[prcmd].cmd, prcmds[prcmd].req) < 0) {
if (all && errno == EADDRNOTAVAIL)
goto end;
Perror(prcmds[prcmd].errmsg);
}
end:
close(s);
return(0);
}
#define PREFIX 0
#define MPREFIX 1
#define UPREFIX 2
void
Perror(cmd)
const char *cmd;
{
switch (errno) {
case ENXIO:
errx(1, "%s: no such interface", cmd);
break;
case EPERM:
errx(1, "%s: permission denied", cmd);
break;
default:
err(1, "%s", cmd);
}
}
#define SIN6(x) ((struct sockaddr_in6 *) &(x))
struct sockaddr_in6 *sin6tab[] = {
SIN6(prereq.ipr_prefix), SIN6(rrreq.irr_matchprefix),
SIN6(rrreq.irr_useprefix)};
void
getprefixlen(const char *plen, int unused)
{
int len = atoi(plen);
if ((len < 0) || (len > 128))
errx(1, "%s: bad value", plen);
/* set plen for prereq */
prereq.ipr_plen = len;
explicit_prefix = 1;
}
void
getprefix(const char *prefix, int which)
{
register struct sockaddr_in6 *sin = sin6tab[which];
/*
* Delay the ioctl to set the interface prefix until flags are all set.
* The prefix interpretation may depend on the flags,
* and the flags may change when the prefix is set.
*/
sin->sin6_len = sizeof(*sin);
sin->sin6_family = AF_INET6;
if (inet_pton(AF_INET6, prefix, &sin->sin6_addr) != 1)
errx(1, "%s: bad value", prefix);
}
void
get_setdelprefix(const char *prefix, int unused)
{
newprefix_setdel++;
getprefix(prefix, PREFIX);
}
void
get_matchprefix(const char *prefix, int unused)
{
newprefix_match++;
prcmd = (prcmd == PREF_CMD_SET) ? PREF_CMD_ADD : prcmd;
getprefix(prefix, MPREFIX);
}
void
get_useprefix(const char *prefix, int unused)
{
newprefix_use++;
if (newprefix_uselen == 0)
rrreq.irr_u_uselen = 64;
getprefix(prefix, UPREFIX);
}
static int
get_plen(const char *plen)
{
int len;
len = atoi(plen);
if ((len < 0) || (len > 128))
errx(1, "%s: bad value", plen);
return len;
}
void
set_matchlen(const char *plen, int unused)
{
rrreq.irr_m_len = get_plen(plen);
}
void
set_match_minlen(const char *plen, int unused)
{
rrreq.irr_m_minlen = get_plen(plen);
}
void
set_match_maxlen(const char *plen, int unused)
{
rrreq.irr_m_maxlen = get_plen(plen);
}
void
set_use_uselen(const char *plen, int unused)
{
newprefix_uselen++;
rrreq.irr_u_uselen = get_plen(plen);
}
void
set_use_keeplen(const char *plen, int unused)
{
newprefix_keeplen++;
rrreq.irr_u_keeplen = get_plen(plen);
}
void
set_vltime(const char *ltime, int unused)
{
setlifetime(ltime, &prereq.ipr_vltime);
rrreq.irr_vltime = prereq.ipr_vltime;
}
void
set_pltime(const char *ltime, int unused)
{
setlifetime(ltime, &prereq.ipr_pltime);
rrreq.irr_pltime = prereq.ipr_pltime;
}
void
set_raf_onlink(const char *unused, int value)
{
/* raflagmask is only meaningful when newprefix_rrenum */
rrreq.irr_raflagmask.onlink = 1;
prereq.ipr_flags.prf_ra.onlink =
rrreq.irr_flags.prf_ra.onlink = value ? 1 : 0;
}
void
set_raf_auto(const char *unused, int value)
{
/* only meaningful when newprefix_rrenum */
rrreq.irr_raflagmask.autonomous = 1;
prereq.ipr_flags.prf_ra.autonomous =
rrreq.irr_flags.prf_ra.autonomous = value ? 1 : 0;
}
void
set_rrf_decrvalid(const char *unused, int value)
{
prereq.ipr_flags.prf_rr.decrvalid =
rrreq.irr_flags.prf_rr.decrvalid = value ? 1 : 0;
}
void
set_rrf_decrprefd(const char *unused, int value)
{
prereq.ipr_flags.prf_rr.decrprefd =
rrreq.irr_flags.prf_rr.decrprefd = value ? 1 : 0;
}
void
set_prefix_cmd(const char *unused, int cmd)
{
prcmd = cmd;
}
void
setlifetime(const char *atime, u_int32_t *btime)
{
int days = 0, hours = 0, minutes = 0, seconds = 0;
u_int32_t ttime;
char *check;
if (strcmp(atime, "infinity") == 0) {
*btime = 0xffffffff;
return;
}
ttime = strtoul(atime, &check ,10) & 0xffffffff;
if (*check == '\0') {
*btime = ttime;
return;
}
if (sscanf(atime, "d%2dh%2dm%2ds%2d", &days, &hours, &minutes,
&seconds) < 0) {
Perror("wrong time format: valid is d00h00m00s00, \n"
"where 00 can be any octal number, \n"
"\'d\' is for days, \'h\' is for hours, \n"
"\'m\' is for minutes, and \'s\' is for seconds \n");
return;
}
*btime = 0;
*btime += seconds;
*btime += minutes * 60;
*btime += hours * 3600;
*btime += days * 86400;
return;
}

View File

@ -0,0 +1,9 @@
# @(#)Makefile 8.1 (Berkeley) 6/5/93
# $FreeBSD$
PROG= rip6query
MAN8= rip6query.8
CFLAGS+=-DINET6 -I${.CURDIR}/../route6d
.include <bsd.prog.mk>

View File

@ -0,0 +1,62 @@
.\"
.\" Copyright (C) 1998 and 1999 WIDE Project.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the project nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: rip6query.8,v 1.1 1999/10/07 05:36:36 itojun Exp $
.\" $FreeBSD$
.\"
.Dd Oct 7, 1999
.Dt RIP6QUERY 8
.Os KAME
.Sh NAME
.Nm rip6query
.Nd RIPng debugging tool
.\"
.Sh SYNOPSIS
.Nm
.Op Fl I Ar interface
.Ar destination
.\"
.Sh DESCRIPTION
.Nm
requests remote RIPng daemon on
.Ar destionation
to dump RIPng routing information.
.Fl I
lets you specify outgoing
.Ar interface
for the query packet,
and is useful when link-local address is specified for
.Ar destination .
.\"
.Sh SEE ALSO
.Xr route6d 8 .
.\"
.Sh HISTORY
The
.Nm
command first appeared in WIDE Hydrangea IPv6 protocol stack kit.

View File

@ -0,0 +1,206 @@
/*
* 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$
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <err.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "route6d.h"
/* wrapper for KAME-special getnameinfo() */
#ifndef NI_WITHSCOPEID
#define NI_WITHSCOPEID 0
#endif
int s;
extern int errno;
struct sockaddr_in6 sin6;
struct rip6 *ripbuf;
#define RIPSIZE(n) (sizeof(struct rip6) + (n-1) * sizeof(struct netinfo6))
int main __P((int, char **));
static void usage __P((void));
static const char *sa_n2a __P((struct sockaddr *));
static const char *inet6_n2a __P((struct in6_addr *));
int
main(argc, argv)
int argc;
char **argv;
{
struct netinfo6 *np;
struct sockaddr_in6 fsock;
int i, n, len, flen;
int c;
extern char *optarg;
extern int optind;
int ifidx = -1;
int error;
char pbuf[10];
struct addrinfo hints, *res;
while ((c = getopt(argc, argv, "I:")) != EOF) {
switch (c) {
case 'I':
ifidx = if_nametoindex(optarg);
if (ifidx == 0) {
errx(1, "invalid interface %s", optarg);
/*NOTREACHED*/
}
break;
default:
usage();
exit(1);
/*NOTREACHED*/
}
}
argv += optind;
argc -= optind;
if (argc != 1) {
usage();
exit(-1);
}
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
err(1, "socket");
/*NOTREACHED*/
}
/* getaddrinfo is preferred for addr@ifname syntax */
snprintf(pbuf, sizeof(pbuf), "%d", RIP6_PORT);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(argv[0], pbuf, &hints, &res);
if (error) {
errx(1, "%s: %s", argv[0], gai_strerror(error));
/*NOTREACHED*/
}
if (res->ai_next) {
errx(1, "%s: %s", argv[0], "resolved to multiple addrs");
/*NOTREACHED*/
}
if (sizeof(sin6) != res->ai_addrlen) {
errx(1, "%s: %s", argv[0], "invalid addrlen");
/*NOTREACHED*/
}
memcpy(&sin6, res->ai_addr, res->ai_addrlen);
if (ifidx >= 0)
sin6.sin6_scope_id = ifidx;
if ((ripbuf = (struct rip6 *)malloc(BUFSIZ)) == NULL) {
err(1, "malloc");
/*NOTREACHED*/
}
ripbuf->rip6_cmd = RIP6_REQUEST;
ripbuf->rip6_vers = RIP6_VERSION;
ripbuf->rip6_res1[0] = 0;
ripbuf->rip6_res1[1] = 0;
np = ripbuf->rip6_nets;
bzero(&np->rip6_dest, sizeof(struct in6_addr));
np->rip6_tag = 0;
np->rip6_plen = 0;
np->rip6_metric = HOPCNT_INFINITY6;
if (sendto(s, ripbuf, RIPSIZE(1), 0, (struct sockaddr *)&sin6,
sizeof(struct sockaddr_in6)) < 0) {
err(1, "send");
/*NOTREACHED*/
}
do {
flen = sizeof(fsock);
if ((len = recvfrom(s, ripbuf, BUFSIZ, 0,
(struct sockaddr *)&fsock, &flen)) < 0) {
err(1, "recvfrom");
/*NOTREACHED*/
}
printf("Response from %s len %d\n",
sa_n2a((struct sockaddr *)&fsock), len);
n = (len - sizeof(struct rip6) + sizeof(struct netinfo6)) /
sizeof(struct netinfo6);
np = ripbuf->rip6_nets;
for (i = 0; i < n; i++, np++) {
printf("\t%s/%d [%d]", inet6_n2a(&np->rip6_dest),
np->rip6_plen, np->rip6_metric);
if (np->rip6_tag)
printf(" tag=0x%x", ntohs(np->rip6_tag));
printf("\n");
}
} while (len == RIPSIZE(24));
exit(0);
}
static void
usage()
{
fprintf(stderr, "Usage: rip6query [-I iface] address\n");
}
/* getnameinfo() is preferred as we may be able to show ifindex as ifname */
static const char *
sa_n2a(sa)
struct sockaddr *sa;
{
static char buf[BUFSIZ];
if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf),
NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0) {
snprintf(buf, sizeof(buf), "%s", "(invalid)");
}
return buf;
}
static const char *
inet6_n2a(addr)
struct in6_addr *addr;
{
static char buf[BUFSIZ];
return inet_ntop(AF_INET6, addr, buf, sizeof(buf));
}

View File

@ -0,0 +1,9 @@
# @(#)Makefile 8.1 (Berkeley) 6/5/93
# $FreeBSD$
PROG= route6d
MAN8= route6d.8
CFLAGS+= -Dss_len=__ss_len -Dss_family=__ss_family -DADVAPI -DINET6
.include <bsd.prog.mk>

64
usr.sbin/route6d/misc/chkrt Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/perl
#
# $FreeBSD$
#
$dump="/var/tmp/route6d_dump";
$pidfile="/var/run/route6d.pid";
system("rm -f $dump");
open(FD, "< $pidfile") || die "Can not open $pidfile";
$_ = <FD>;
chop;
close(FD);
system("kill -INT $_");
open(NS, "/usr/local/v6/bin/netstat -r -n|") || die "Can not open netstat";
while (<NS>) {
chop;
next unless (/^3f/ || /^5f/);
@f = split(/\s+/);
$gw{$f[0]} = $f[1];
$int{$f[0]} = $f[3];
}
close(NS);
$err=0;
sleep(2);
open(FD, "< $dump") || die "Can not open $dump";
while (<FD>) {
chop;
next unless (/^ 3f/ || /^ 5f/);
@f = split(/\s+/);
$dst = $f[1];
$f[2] =~ /if\(\d:([a-z0-9]+)\)/;
$intf = $1;
$f[3] =~ /gw\(([a-z0-9:]+)\)/;
$gateway = $1;
$f[4] =~ /\[(\d+)\]/;
$metric = $1;
$f[5] =~ /age\((\d+)\)/;
$age = $1;
unless (defined($gw{$dst})) {
print "NOT FOUND: $dst $intf $gateway $metric $age\n";
$err++;
next;
}
if ($gw{$dst} ne $gateway && $gw{$dst} !~ /link#\d+/) {
print "WRONG GW: $dst $intf $gateway $metric $age\n";
print "kernel gw: $gw{$dst}\n";
$err++;
next;
}
if ($int{$dst} ne $intf) {
print "WRONG IF: $dst $intf $gateway $metric $age\n";
print "kernel if: $int{$dst}\n";
$err++;
next;
}
}
close(FD);
if ($err == 0) {
print "No error found\n";
}

View File

@ -0,0 +1,52 @@
/*
* 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$
*/
#include <stdio.h>
unsigned short buf[BUFSIZ];
main()
{
int i;
unsigned short *p = buf, *q = &buf[4];
unsigned long sum, sum2;
while (scanf("%x", &i) != EOF) {
*p++ = i; printf("%d ", i);
}
printf("\n");
sum = buf[2] + (buf[3] >> 8) & 0xff;
while (q != p)
sum += (*q++ & 0xffff);
sum2 = (sum & 0xffff) + (sum >> 16) & 0xffff;
printf("%x, %x\n", sum, sum2);
}

234
usr.sbin/route6d/route6d.8 Normal file
View File

@ -0,0 +1,234 @@
.\" Copyright (c) 1996 WIDE Project. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modifications, are permitted provided that the above copyright notice
.\" and this paragraph are duplicated in all such forms and that any
.\" documentation, advertising materials, and other materials related to
.\" such distribution and use acknowledge that the software was developed
.\" by the WIDE Project, Japan. The name of the Project may not be used to
.\" endorse or promote products derived from this software without
.\" specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
.\" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
.\" LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
.\" A PARTICULAR PURPOSE.
.\"
.\" $FreeBSD$
.\"
.Dd January 31, 1997
.Dt ROUTE6D 8
.Os KAME
.Sh NAME
.Nm route6d
.Nd RIP6 Routing Daemon
.Sh SYNOPSIS
.Nm route6d
.Op Fl adDhlqsS
.Op Fl R Ar routelog
.Op Fl A Ar prefix/preflen,if1[,if2...]
.Op Fl L Ar prefix/preflen,if1[,if2...]
.Op Fl N Ar if1[,if2...]
.Op Fl O Ar prefix/preflen,if1[,if2...]
.Op Fl T Ar if1[,if2...]
.Op Fl t Ar tag
.\"
.Sh DESCRIPTION
The
.Nm
is a routing daemon which supports RIP over IPv6.
.Pp
Options are:
.Bl -tag -width indent
.\"
.It Fl a
Enables aging of the statically defined routes.
With this option, any
statically defined routes will be removed unless corresponding updates
arrive as if the routes are received at the startup of
.Nm route6d .
.\"
.It Fl R Ar routelog
This option makes the
.Nm
to log the route change (add/delete) to the file
.Ar routelog .
.\"
.It Fl A Ar prefix/preflen,if1[,if2...]
This option is used for aggregating routes.
.Ar prefix/preflen
specifies the prefix and the prefix length of the
aggregated route.
When advertising routes,
.Nm
filters specific routes covered by the aggregate,
and advertises the aggregated route
.Ar prefix/preflen ,
to the interfaces specified in the comma-separated interface list,
.Ar if1[,if2...] .
.Nm
creates a static route to
.Ar prefix/preflen
with
.Dv RTF_REJECT
flag, into the kernel routing table.
.\"
.It Fl d
Enables output of debugging message.
This option also instructs
.Nm
to run in foreground mode
.Pq does not become daemon .
.\"
.It Fl D
Enables extensive output of debugging message.
This option also instructs
.Nm
to run in foreground mode
.Pq does not become daemon .
.\"
.It Fl h
Disables the split horizon processing.
.\"
.It Fl l
By default,
.Nm
will not exchange site local routes for safety reasons.
This is because semantics of site local address space is rather vague,
and there is no good way to define site local boundary.
With
.Fl l
option,
.Nm
will exchange site local routes as well.
It must not be used on site boundary routers,
since
.Fl l
option assumes that all interfaces are in the same site.
.\"
.It Fl L Ar prefix/preflen,if1[,if2...]
Filter incoming routes from interfaces
.Ar if1,[if2...] .
.Nm
will accept incoming routes that are in
.Ar prefix/preflen .
If multiple
.Fl L
options are specified, any routes that match one of the options is accepted.
.Li ::/0
is treated specially as default route, not
.Do
any route that has longer prefix length than, or equal to 0
.Dc .
If you would like to accept any route, specify no
.Fl L
option.
For example, with
.Do
.Fl L
.Li 3ffe::/16,if1
.Fl L
.Li ::/0,if1
.Dc
.Nm
will accept default route and routes in 6bone test address, but no others.
.\"
.It Fl N Ar if1[,if2...]
Do not listen to, or advertise, route from/to interfaces specified by
.Ar if1,[if2...] .
.\"
.It Fl O Ar prefix/preflen,if1[,if2...]
Restrict route advertisement toward interfaces specified by
.Ar if1,[if2...] .
With this option
.Nm
will only advertise routes that matches
.Ar prefix/preflen .
.\"
.It Fl q
Makes
.Nm
in listen-only mode.
No advertisement is sent.
.\"
.It Fl s
Makes
.Nm
to advertise the statically defined routes which exist in the kernel routing
table when
.Nm
invoked.
Announcements obey the regular split horizon rule.
.\"
.It Fl S
This option is the same as
.Fl s
option except that no split horizon rule does apply.
.\"
.It Fl T Ar if1[,if2...]
Advertise only default route, toward
.Ar if1,[if2...] .
.\"
.It Fl t Ar tag
Attach route tag
.Ar tag
to originated route entries.
.Ar tag
can be decimal, octal prefixed by
.Li 0 ,
or hexadecimal prefixed by
.Li 0x .
.\"
.El
.Pp
Upon receipt of signal
.Dv SIGINT
or
.Dv SIGUSR1 ,
.Nm
will dump the current internal state into
.Pa /var/tmp/route6d_dump .
.\"
.Sh FILES
.Bl -tag -width /var/tmp/route6d_dump -compact
.It Pa /var/tmp/route6d_dump
dumps internal state on
.Dv SIGINT
or
.Dv SIGUSR1
.El
.\"
.Sh SEE ALSO
.Rs
.%A G. Malkin
.%A R. Minnear
.%T RIPng for IPv6
.%R RFC2080
.%D January 1997
.Re
.\"
.Sh NOTE
.Nm Route6d
uses IPv6 advanced API,
defined in RFC2292,
for communicating with peers using link-local addresses.
.Pp
Internally
.Nm
embeds interface identifier into bit 32 to 63 of link-local addresses
.Po
.Li fe80::xx
and
.Li ff02::xx
.Pc
so they will be visible on internal state dump file
.Pq Pa /var/tmp/route6d_dump .
.Pp
Routing table manipulation differs from IPv6 implementation to implementation.
Currently
.Nm
obeys WIDE Hydrangea/KAME IPv6 kernel,
and will not be able to run on other platforms.
.Pp
Current
.Nm
does not reduce the rate of the triggered updates when consecutive updates
arrive.

2913
usr.sbin/route6d/route6d.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
/*
* $Header: /cvsroot/kame/kame/kame/kame/route6d/route6d.h,v 1.1.1.1 1999/08/08 23:31:35 itojun Exp $
*/
/*
* 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$
*/
/* not yet in use
#define ROUTE6D_CONF "/usr/local/v6/etc/route6d.conf"
*/
#define ROUTE6D_DUMP "/var/tmp/route6d_dump"
#define ROUTE6D_PID "/var/run/route6d.pid"
#define RIP6_VERSION 1
#define RIP6_REQUEST 1
#define RIP6_RESPONSE 2
struct netinfo6 {
struct in6_addr rip6_dest;
u_short rip6_tag;
u_char rip6_plen;
u_char rip6_metric;
};
struct rip6 {
u_char rip6_cmd;
u_char rip6_vers;
u_char rip6_res1[2];
union {
struct netinfo6 ru6_nets[1];
char ru6_tracefile[1];
} rip6un;
#define rip6_nets rip6un.ru6_nets
#define rip6_tracefile rip6un.ru6_tracefile
};
#define HOPCNT_INFINITY6 16
#define NEXTHOP_METRIC 0xff
#define RIP6_MAXMTU 1500
#define IFMINMTU 576
#ifndef DEBUG
#define SUPPLY_INTERVAL6 30
#define RIP_LIFETIME 180
#define RIP_HOLDDOWN 120
#define RIP_TRIG_INT6_MAX 5
#define RIP_TRIG_INT6_MIN 1
#else
/* only for debugging; can not wait for 30sec to appear a bug */
#define SUPPLY_INTERVAL6 10
#define RIP_LIFETIME 60
#define RIP_HOLDDOWN 40
#define RIP_TRIG_INT6_MAX 5
#define RIP_TRIG_INT6_MIN 1
#endif
#define RIP6_PORT 521
#define RIP6_DEST "ff02::9"
#define LOOPBACK_IF "lo0"

25
usr.sbin/rtsold/Makefile Normal file
View File

@ -0,0 +1,25 @@
# Copyright (c) 1996 WIDE Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modifications, are permitted provided that the above copyright notice
# and this paragraph are duplicated in all such forms and that any
# documentation, advertising materials, and other materials related to
# such distribution and use acknowledge that the software was developed
# by the WIDE Project, Japan. The name of the Project may not be used to
# endorse or promote products derived from this software without
# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE.
# $FreeBSD$
PROG= rtsold
SRCS= rtsold.c rtsol.c if.c probe.c dump.c
CFLAGS+=-DINET6
LDADD+= -lkvm
DPADD+= ${LIBKVM}
MAN8= rtsold.8
MLINKS= rtsold.8 rtsol.8
.include <bsd.prog.mk>

137
usr.sbin/rtsold/dump.c Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <syslog.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "rtsold.h"
static FILE *fp;
extern struct ifinfo *iflist;
static char *sec2str __P((time_t));
char *ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE"};
static void
dump_interface_status()
{
struct ifinfo *ifinfo;
struct timeval now;
gettimeofday(&now, NULL);
for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) {
fprintf(fp, "Interface %s\n", ifinfo->ifname);
fprintf(fp, " probe interval: ");
if (ifinfo->probeinterval) {
fprintf(fp, "%d\n", ifinfo->probeinterval);
fprintf(fp, " probe timer: %d\n", ifinfo->probetimer);
}
else {
fprintf(fp, "infinity\n");
fprintf(fp, " no probe timer\n");
}
fprintf(fp, " interface status: %s\n",
ifinfo->active > 0 ? "active" : "inactive");
fprintf(fp, " rtsold status: %s\n", ifstatstr[ifinfo->state]);
fprintf(fp, " carrier detection: %s\n",
ifinfo->mediareqok ? "available" : "unavailable");
fprintf(fp, " probes: %d, dadcount = %d\n",
ifinfo->probes, ifinfo->dadcount);
if (ifinfo->timer.tv_sec == tm_max.tv_sec &&
ifinfo->timer.tv_usec == tm_max.tv_usec)
fprintf(fp, " no timer\n");
else {
fprintf(fp, " timer: interval=%d:%d, expire=%s\n",
(int)ifinfo->timer.tv_sec,
(int)ifinfo->timer.tv_usec,
(ifinfo->expire.tv_sec < now.tv_sec) ? "expired"
: sec2str(ifinfo->expire.tv_sec - now.tv_sec));
}
fprintf(fp, " number of valid RAs: %d\n", ifinfo->racnt);
}
}
void
rtsold_dump_file(dumpfile)
char *dumpfile;
{
if ((fp = fopen(dumpfile, "w")) == NULL) {
warnmsg(LOG_WARNING, __FUNCTION__, "open a dump file(%s)",
dumpfile, strerror(errno));
return;
}
dump_interface_status();
fclose(fp);
}
static char *
sec2str(total)
time_t total;
{
static char result[256];
int days, hours, mins, secs;
int first = 1;
char *p = result;
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);
return(result);
}

423
usr.sbin/rtsold/if.c Normal file
View File

@ -0,0 +1,423 @@
/*
* 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$
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <net/if_types.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#ifdef __FreeBSD__
# include <net/ethernet.h>
#endif
#ifdef __NetBSD__
#include <net/if_ether.h>
#endif
#if defined(__bsdi__) || defined(__OpenBSD__)
# include <netinet/in.h>
# include <netinet/if_ether.h>
#endif
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <netinet6/in6_var.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <kvm.h>
#include <nlist.h>
#include <limits.h>
#include "rtsold.h"
static int ifsock;
static int getifa __P((char *name, struct in6_ifaddr *ifap));
static void get_rtaddrs __P((int addrs, struct sockaddr *sa,
struct sockaddr **rti_info));
int
ifinit()
{
if ((ifsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket: %s", strerror(errno));
return(-1);
}
return(0);
}
int
interface_up(char *name)
{
struct ifreq ifr;
struct in6_ifaddr ifa;
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
warnmsg(LOG_WARNING, __FUNCTION__, "ioctl(SIOCGIFFLAGS): %s",
strerror(errno));
return(-1);
}
if (!(ifr.ifr_flags & IFF_UP)) {
ifr.ifr_flags |= IFF_UP;
if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
warnmsg(LOG_ERR, __FUNCTION__,
"ioctl(SIOCSIFFLAGS): %s", strerror(errno));
}
return(-1);
}
warnmsg(LOG_DEBUG, __FUNCTION__, "checking if %s is ready...", name);
if (getifa(name, &ifa) < 0) {
warnmsg(LOG_WARNING, __FUNCTION__,
"getifa() failed, anyway I'll try");
return 0;
}
if (!(ifa.ia6_flags & IN6_IFF_NOTREADY)) {
warnmsg(LOG_DEBUG, __FUNCTION__,
"%s is ready", name);
return(0);
}
else {
if (ifa.ia6_flags & IN6_IFF_TENTATIVE) {
warnmsg(LOG_DEBUG, __FUNCTION__, "%s is tentative",
name);
return IFS_TENTATIVE;
}
if (ifa.ia6_flags & IN6_IFF_DUPLICATED)
warnmsg(LOG_DEBUG, __FUNCTION__, "%s is duplicated",
name);
return -1;
}
}
int
interface_status(struct ifinfo *ifinfo)
{
char *ifname = ifinfo->ifname;
struct ifreq ifr;
struct ifmediareq ifmr;
/* get interface flags */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "ioctl(SIOCGIFFLAGS) on %s: %s",
ifname, strerror(errno));
return(-1);
}
/*
* if one of UP and RUNNING flags is dropped,
* the interface is not active.
*/
if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
goto inactive;
}
/* Next, check carrier on the interface, if possible */
if (!ifinfo->mediareqok)
goto active;
memset(&ifmr, 0, sizeof(ifmr));
strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
if (errno != EINVAL) {
warnmsg(LOG_DEBUG, __FUNCTION__,
"ioctl(SIOCGIFMEDIA) on %s: %s",
ifname, strerror(errno));
return(-1);
}
/*
* EINVAL simply means that the interface does not support
* the SIOCGIFMEDIA ioctl. We regard it alive.
*/
ifinfo->mediareqok = 0;
goto active;
}
if (ifmr.ifm_status & IFM_AVALID) {
switch(ifmr.ifm_active & IFM_NMASK) {
case IFM_ETHER:
if (ifmr.ifm_status & IFM_ACTIVE)
goto active;
else
goto inactive;
break;
default:
goto inactive;
}
}
inactive:
return(0);
active:
return(1);
}
#define ROUNDUP(a, size) \
(((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\
sizeof(u_long)) :\
sizeof(u_long)))
#define ROUNDUP8(a) (1 + (((a) - 1) | 7))
int
lladdropt_length(struct sockaddr_dl *sdl)
{
switch(sdl->sdl_type) {
case IFT_ETHER:
return(ROUNDUP8(ETHER_ADDR_LEN + 2));
default:
return(0);
}
}
void
lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
{
char *addr;
ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */
switch(sdl->sdl_type) {
case IFT_ETHER:
ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
addr = (char *)(ndopt + 1);
memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
break;
default:
warnmsg(LOG_ERR, __FUNCTION__,
"unsupported link type(%d)", sdl->sdl_type);
exit(1);
}
return;
}
struct sockaddr_dl *
if_nametosdl(char *name)
{
int mib[6] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
char *buf, *next, *lim;
size_t len;
struct if_msghdr *ifm;
struct sockaddr *sa, *rti_info[RTAX_MAX];
struct sockaddr_dl *sdl = NULL, *ret_sdl;
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
return(NULL);
if ((buf = malloc(len)) == NULL)
return(NULL);
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
free(buf);
return(NULL);
}
lim = buf + len;
for (next = buf; next < lim; next += ifm->ifm_msglen) {
ifm = (struct if_msghdr *)next;
if (ifm->ifm_type == RTM_IFINFO) {
sa = (struct sockaddr *)(ifm + 1);
get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
if ((sa = rti_info[RTAX_IFP]) != NULL) {
if (sa->sa_family == AF_LINK) {
sdl = (struct sockaddr_dl *)sa;
if (strncmp(&sdl->sdl_data[0],
name,
sdl->sdl_nlen) == 0) {
break;
}
}
}
}
}
if (next == lim) {
/* search failed */
free(buf);
return(NULL);
}
if ((ret_sdl = malloc(sdl->sdl_len)) == NULL)
return(NULL);
memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len);
return(ret_sdl);
}
int
getinet6sysctl(int code)
{
int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
int value;
size_t size;
mib[3] = code;
size = sizeof(value);
if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) < 0)
return -1;
else
return value;
}
/*------------------------------------------------------------*/
static struct nlist nl[] = {
#define N_IFNET 0
{ "_ifnet" },
{ "" },
};
#define KREAD(x, y, z) { \
if (kvm_read(kvmd, (u_long)x, (void *)y, sizeof(z)) != sizeof(z)) { \
warnmsg(LOG_ERR, __FUNCTION__, "kvm_read failed"); \
goto bad; \
} \
}
static int
getifa(char *name, struct in6_ifaddr *ifap)
{
u_short index;
kvm_t *kvmd = NULL;
char buf[_POSIX2_LINE_MAX];
struct ifnet *ifp;
struct ifnet ifnet;
struct in6_ifaddr *ifa;
if (!ifap)
exit(1);
index = (u_short)if_nametoindex(name);
if (index == 0) {
warnmsg(LOG_ERR, __FUNCTION__, "if_nametoindex failed for %s",
name);
goto bad;
}
if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__, "kvm_openfiles failed");
goto bad;
}
if (kvm_nlist(kvmd, nl) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "kvm_nlist failed");
goto bad;
}
if (nl[N_IFNET].n_value == 0) {
warnmsg(LOG_ERR, __FUNCTION__, "symbol \"%s\" not found",
nl[N_IFNET].n_name);
goto bad;
}
KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *);
while (ifp) {
KREAD(ifp, &ifnet, struct ifnet);
if (ifnet.if_index == index)
break;
#if defined(__NetBSD__) || defined(__OpenBSD__)
ifp = TAILQ_NEXT(&ifnet, if_list);
#elif defined(__FreeBSD__) && __FreeBSD__ >= 3
ifp = TAILQ_NEXT(&ifnet, if_link);
#else
ifp = ifnet.if_next;
#endif
}
if (!ifp) {
warnmsg(LOG_ERR, __FUNCTION__, "interface \"%s\" not found",
name);
goto bad;
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
ifa = (struct in6_ifaddr *)TAILQ_FIRST(&ifnet.if_addrlist);
#elif defined(__FreeBSD__) && __FreeBSD__ >= 3
ifa = (struct in6_ifaddr *)TAILQ_FIRST(&ifnet.if_addrhead);
#else
ifa = (struct in6_ifaddr *)ifnet.if_addrlist;
#endif
while (ifa) {
KREAD(ifa, ifap, *ifap);
if (ifap->ia_addr.sin6_family == AF_INET6
&& IN6_IS_ADDR_LINKLOCAL(&ifap->ia_addr.sin6_addr)) {
kvm_close(kvmd);
return 0;
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
ifa = (struct in6_ifaddr *)
TAILQ_NEXT((struct ifaddr *)ifap, ifa_list);
#elif defined(__FreeBSD__) && __FreeBSD__ >= 3
ifa = (struct in6_ifaddr *)
TAILQ_NEXT((struct ifaddr *)ifap, ifa_link);
#else
ifa = (struct in6_ifaddr *)(((struct ifaddr *)ifap)->ifa_next);
#endif
}
warnmsg(LOG_ERR, __FUNCTION__, "no IPv6 link-local address for %s",
name);
bad:
if (kvmd)
kvm_close(kvmd);
return -1;
}
static void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
int i;
for (i = 0; i < RTAX_MAX; i++) {
if (addrs & (1 << i)) {
rti_info[i] = sa;
NEXT_SA(sa);
}
else
rti_info[i] = NULL;
}
}

179
usr.sbin/rtsold/probe.c Normal file
View File

@ -0,0 +1,179 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <netinet/in.h>
#include <netinet6/in6_var.h>
#include <netinet/icmp6.h>
#include <netinet6/nd6.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include "rtsold.h"
static struct msghdr sndmhdr;
static struct iovec sndiov[2];
static int probesock;
static void sendprobe __P((struct in6_addr *addr, int ifindex));
int
probe_init()
{
static u_char sndcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int))];
if ((probesock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket: %s", strerror(errno));
return(-1);
}
/* make the socket send-only */
if (shutdown(probesock, 0)) {
warnmsg(LOG_ERR, __FUNCTION__, "shutdown: %s", strerror(errno));
return(-1);
}
/* initialize msghdr for sending packets */
sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
sndmhdr.msg_iov = sndiov;
sndmhdr.msg_iovlen = 1;
sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
sndmhdr.msg_controllen = sizeof(sndcmsgbuf);
return(0);
}
/*
* Probe if each router in the default router list is still alive.
*/
void
defrouter_probe(int ifindex)
{
struct in6_drlist dr;
int s, i;
u_char ntopbuf[INET6_ADDRSTRLEN];
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket: %s", strerror(errno));
return;
}
bzero(&dr, sizeof(dr));
strcpy(dr.ifname, "lo0"); /* dummy interface */
if (ioctl(s, SIOCGDRLST_IN6, (caddr_t)&dr) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "ioctl(SIOCGDRLST_IN6): %s",
strerror(errno));
goto closeandend;
}
for(i = 0; dr.defrouter[i].if_index && i < PRLSTSIZ; i++) {
if (ifindex && dr.defrouter[i].if_index == ifindex) {
/* sanity check */
if (!IN6_IS_ADDR_LINKLOCAL(&dr.defrouter[i].rtaddr)) {
warnmsg(LOG_ERR, __FUNCTION__,
"default router list contains a "
"non-linklocal address(%s)",
inet_ntop(AF_INET6,
&dr.defrouter[i].rtaddr,
ntopbuf, INET6_ADDRSTRLEN));
continue; /* ignore the address */
}
sendprobe(&dr.defrouter[i].rtaddr,
dr.defrouter[i].if_index);
}
}
closeandend:
close(s);
return;
}
static void
sendprobe(struct in6_addr *addr, int ifindex)
{
struct sockaddr_in6 sa6_probe;
struct in6_pktinfo *pi;
struct cmsghdr *cm;
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];;
bzero(&sa6_probe, sizeof(sa6_probe));
sa6_probe.sin6_family = AF_INET6;
sa6_probe.sin6_len = sizeof(sa6_probe);
sa6_probe.sin6_addr = *addr;
sndmhdr.msg_name = (caddr_t)&sa6_probe;
sndmhdr.msg_iov[0].iov_base = NULL;
sndmhdr.msg_iov[0].iov_len = 0;
cm = CMSG_FIRSTHDR(&sndmhdr);
/* specify the outgoing interface */
cm->cmsg_level = IPPROTO_IPV6;
cm->cmsg_type = IPV6_PKTINFO;
cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
pi = (struct in6_pktinfo *)CMSG_DATA(cm);
memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
pi->ipi6_ifindex = ifindex;
/* specify the hop limit of the packet for safety */
{
int hoplimit = 1;
cm = CMSG_NXTHDR(&sndmhdr, cm);
cm->cmsg_level = IPPROTO_IPV6;
cm->cmsg_type = IPV6_HOPLIMIT;
cm->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
}
warnmsg(LOG_DEBUG, __FUNCTION__, "probe a router %s on %s",
inet_ntop(AF_INET6, addr, ntopbuf, INET6_ADDRSTRLEN),
if_indextoname(ifindex, ifnamebuf));
if (sendmsg(probesock, &sndmhdr, 0))
warnmsg(LOG_ERR, __FUNCTION__, "sendmsg on %s: %s",
if_indextoname(ifindex, ifnamebuf), strerror(errno));
return;
}

312
usr.sbin/rtsold/rtsol.c Normal file
View File

@ -0,0 +1,312 @@
/*
* 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$
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <err.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include "rtsold.h"
#define ALLROUTER "ff02::2"
static struct msghdr rcvmhdr;
static struct msghdr sndmhdr;
static struct iovec rcviov[2];
static struct iovec sndiov[2];
static struct sockaddr_in6 from;
static int rssock;
static struct sockaddr_in6 sin6_allrouters = {sizeof(sin6_allrouters), AF_INET6};
int
sockopen()
{
int on;
struct icmp6_filter filt;
static u_char answer[1500];
static u_char rcvcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int))];
static u_char sndcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
CMSG_SPACE(sizeof(int))];
memset(&sin6_allrouters, 0, sizeof(struct sockaddr_in6));
if (inet_pton(AF_INET6, ALLROUTER,
&sin6_allrouters.sin6_addr.s6_addr) != 1) {
warnmsg(LOG_ERR, __FUNCTION__, "inet_pton failed for %s",
ALLROUTER);
return(-1);
}
if ((rssock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "socket: %s", strerror(errno));
return(-1);
}
/* specify to tell receiving interface */
on = 1;
if (setsockopt(rssock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
sizeof(on)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "IPV6_PKTINFO: %s",
strerror(errno));
exit(1);
}
on = 1;
/* specify to tell value of hoplimit field of received IP6 hdr */
if (setsockopt(rssock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
sizeof(on)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "IPV6_HOPLIMIT: %s",
strerror(errno));
exit(1);
}
/* specfiy to accept only router advertisements on the socket */
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
if (setsockopt(rssock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
sizeof(filt)) == -1) {
warnmsg(LOG_ERR, __FUNCTION__, "setsockopt(ICMP6_FILTER): %s",
strerror(errno));
return(-1);
}
/* initialize msghdr for receiving packets */
rcviov[0].iov_base = (caddr_t)answer;
rcviov[0].iov_len = sizeof(answer);
rcvmhdr.msg_name = (caddr_t)&from;
rcvmhdr.msg_namelen = sizeof(from);
rcvmhdr.msg_iov = rcviov;
rcvmhdr.msg_iovlen = 1;
rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
rcvmhdr.msg_controllen = sizeof(rcvcmsgbuf);
/* initialize msghdr for sending packets */
sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
sndmhdr.msg_iov = sndiov;
sndmhdr.msg_iovlen = 1;
sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
sndmhdr.msg_controllen = sizeof(sndcmsgbuf);
return(rssock);
}
void
sendpacket(struct ifinfo *ifinfo)
{
int i;
struct cmsghdr *cm;
struct in6_pktinfo *pi;
sndmhdr.msg_name = (caddr_t)&sin6_allrouters;
sndmhdr.msg_iov[0].iov_base = (caddr_t)ifinfo->rs_data;
sndmhdr.msg_iov[0].iov_len = ifinfo->rs_datalen;
cm = CMSG_FIRSTHDR(&sndmhdr);
/* specify the outgoing interface */
cm->cmsg_level = IPPROTO_IPV6;
cm->cmsg_type = IPV6_PKTINFO;
cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
pi = (struct in6_pktinfo *)CMSG_DATA(cm);
memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
pi->ipi6_ifindex = ifinfo->sdl->sdl_index;
/* specify the hop limit of the packet */
{
int hoplimit = 255;
cm = CMSG_NXTHDR(&sndmhdr, cm);
cm->cmsg_level = IPPROTO_IPV6;
cm->cmsg_type = IPV6_HOPLIMIT;
cm->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
}
warnmsg(LOG_DEBUG,
__FUNCTION__, "send RS on %s, whose state is %d",
ifinfo->ifname, ifinfo->state);
i = sendmsg(rssock, &sndmhdr, 0);
if (i < 0 || i != ifinfo->rs_datalen) {
/*
* ENETDOWN is not so serious, especially when using several
* network cards on a mobile node. We ignore it.
*/
if (errno != ENETDOWN || dflag > 0)
warnmsg(LOG_ERR, __FUNCTION__, "sendmsg on %s: %s",
ifinfo->ifname, strerror(errno));
}
/* update counter */
ifinfo->probes++;
}
void
rtsol_input(int s)
{
int i;
int *hlimp = NULL;
struct icmp6_hdr *icp;
int ifindex = 0;
struct cmsghdr *cm;
struct in6_pktinfo *pi = NULL;
struct ifinfo *ifi = NULL;
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
/* get message */
if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "recvmsg: %s", strerror(errno));
return;
}
/* extract optional information via Advanced API */
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr);
cm;
cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) {
if (cm->cmsg_level == IPPROTO_IPV6 &&
cm->cmsg_type == IPV6_PKTINFO &&
cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
ifindex = pi->ipi6_ifindex;
}
if (cm->cmsg_level == IPPROTO_IPV6 &&
cm->cmsg_type == IPV6_HOPLIMIT &&
cm->cmsg_len == CMSG_LEN(sizeof(int)))
hlimp = (int *)CMSG_DATA(cm);
}
if (ifindex == 0) {
warnmsg(LOG_ERR,
__FUNCTION__, "failed to get receiving interface");
return;
}
if (hlimp == NULL) {
warnmsg(LOG_ERR,
__FUNCTION__, "failed to get receiving hop limit");
return;
}
if (i < sizeof(struct nd_router_advert)) {
warnmsg(LOG_ERR,
__FUNCTION__, "packet size(%d) is too short", i);
return;
}
icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
if (icp->icmp6_type != ND_ROUTER_ADVERT) {
warnmsg(LOG_ERR, __FUNCTION__,
"invalid icmp type(%d) from %s on %s", icp->icmp6_type,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
if (icp->icmp6_code != 0) {
warnmsg(LOG_ERR, __FUNCTION__,
"invalid icmp code(%d) from %s on %s", icp->icmp6_code,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
if (*hlimp != 255) {
warnmsg(LOG_NOTICE, __FUNCTION__,
"invalid RA with hop limit(%d) from %s on %s",
*hlimp,
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
if (pi && !IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) {
warnmsg(LOG_NOTICE, __FUNCTION__,
"invalid RA with non link-local source from %s on %s",
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
/* xxx: more validation? */
if ((ifi = find_ifinfo(pi->ipi6_ifindex)) == NULL) {
warnmsg(LOG_NOTICE, __FUNCTION__,
"received RA from %s on an unexpeced IF(%s)",
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN),
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
warnmsg(LOG_DEBUG, __FUNCTION__,
"received RA from %s on %s, state is %d",
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
INET6_ADDRSTRLEN),
ifi->ifname, ifi->state);
ifi->racnt++;
switch(ifi->state) {
case IFS_IDLE: /* should be ignored */
case IFS_DELAY: /* right? */
break;
case IFS_PROBE:
ifi->state = IFS_IDLE;
ifi->probes = 0;
rtsol_timer_update(ifi);
break;
}
}

175
usr.sbin/rtsold/rtsold.8 Normal file
View File

@ -0,0 +1,175 @@
.\" 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.
.\"
.\" $Id: rtsold.8,v 1.4 1999/09/30 00:57:15 jinmei Exp $
.\" $FreeBSD$
.\"
.Dd May 17, 1998
.Dt RTSOLD 8
.Os KAME
.\"
.Sh NAME
.Nm rtsold
.Nd router solicitation daemon
.\"
.Sh SYNOPSIS
.Nm
.Op Fl dDfm1
.Ar interface ...
.Nm rtsol
.Op Fl dD
.Ar interface ...
.\"
.Sh DESCRIPTION
.Nm Rtsold
is the daemon program to send ICMPv6 Router Solicitation messages
on the specified interfaces.
If a node (re)attaches to a link,
.Nm
sends some Router Solicitations on the link destined to the link-local scope
all-routers multicast address to discover new routers
and to get non link-local addresses.
.Lp
Specifically,
.Nm
sends at most 3 Router Solicitations on an interface
after one of the following events:
.Bl -bullet -compact
.It
Just after invocation of
.Nm
daemon.
.It
The interface is up after a temporary interface failure.
.Nm Rtsold
detects it by periodically probing if the status of the
interface is active or not.
Note that some network cards and drivers do not allow users
to extract link state.
In such cases,
.Nm
cannot detect the change of the interface status.
.It
Every one minute if
.Fl m
option is specified and
.Nm
daemon cannot get the interface status.
This feature does not conform to IPv6 neighbor discovery
specification, but is provided for mobile stations.
Default interval of router advertisements, which is on the order of 10
minutes, is slightly long for mobile stations.
This feature is provided
for such stations so that they can find new routers as soon as possible
when they attach another link.
.El
.Lp
Once
.Nm
sends a Router Solicitation, and receives a valid Router Advertisement,
it desists from sending additional solicitations on that interface, until
the next time one of the above events occurs.
.Lp
When sending a Router Solicitation on an interface,
.Nm
includes a Source Link-layer address option if the interface
has its link-layer address.
.Pp
Upon receipt of signal
.Dv SIGUSR1 ,
.Nm
will dump the current internal state into
.Pa /var/tmp/rtsold.dump.
.\"
.Sh OPTIONS
.Bl -tag -width indent
.\"
.It Fl d
Enable debugging.
.It Fl D
Enable more debugging including to print internal timer information.
.It Fl f
.Fl f
prevents
.Nm
from becoming a daemon (foreground mode).
Warning messages are generated to standard error output,
instead of
.Xr syslog 3 .
.It Fl m
Enable mobility support.
If this option is specified,
.Nm
sends probing packets to default routers that have advertised Router
Advertisements
when the node (re)attaches to an interface.
Moreover, if the option is specified,
.Nm
periodically sends Router Solicitation on an interface that does not support
.Dv SIOCGIFMEDIA
ioctl.
.It Fl 1
Perform only one probe.
Transmit Router Solcitation packet until valid Router Advertisement packet
arrives all the interfaces more than once, then exit.
.El
.Pp
If you invoke the program as
.Nm rtsol ,
it will behave as
.Do
.Nm
.Fl f1
.Ar interfaces
.Dc .
.Sh RETURN VALUES
The program exits with 0 on success, non-zero on failures.
.\"
.Sh FILES
.Bl -tag -width /var/run/rtsold.dump -compact
.It Pa /var/run/rtsold.pid
the pid of the currently running
.Nm rtsold .
.It Pa /var/tmp/rtsold.dump
dumps internal state on.
.El
.\"
.Sh SEE ALSO
.Xr rtadvd 8 ,
.Xr sysctl 8
.\"
.Sh HISTORY
The
.Nm
command is based on
.Nm rtsol
command, which first appeared in WIDE/KAME IPv6 protocol stack kit.
.Nm rtsol
is now integrated into
.Xr rtsold 8 .
.\" .Sh BUGS
.\" (to be written)

622
usr.sbin/rtsold/rtsold.c Normal file
View File

@ -0,0 +1,622 @@
/*
* 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$
*/
#include <sys/types.h>
#include <sys/time.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <signal.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <err.h>
#include <stdarg.h>
#include "rtsold.h"
struct ifinfo *iflist;
struct timeval tm_max = {0x7fffffff, 0x7fffffff};
int dflag;
static int log_upto = 999;
static int fflag = 0;
/* protocol constatns */
#define MAX_RTR_SOLICITATION_DELAY 1 /* second */
#define RTR_SOLICITATION_INTERVAL 4 /* seconds */
#define MAX_RTR_SOLICITATIONS 3 /* times */
/* implementation dependent constants */
#define PROBE_INTERVAL 60 /* secondes XXX: should be configurable */
/* utility macros */
/* a < b */
#define TIMEVAL_LT(a, b) (((a).tv_sec < (b).tv_sec) ||\
(((a).tv_sec == (b).tv_sec) && \
((a).tv_usec < (b).tv_usec)))
/* a <= b */
#define TIMEVAL_LEQ(a, b) (((a).tv_sec < (b).tv_sec) ||\
(((a).tv_sec == (b).tv_sec) &&\
((a).tv_usec <= (b).tv_usec)))
/* a == b */
#define TIMEVAL_EQ(a, b) (((a).tv_sec==(b).tv_sec) && ((a).tv_usec==(b).tv_usec))
int main __P((int argc, char *argv[]));
/* static variables and functions */
static int mobile_node = 0;
static int do_dump;
static char *dumpfilename = "/var/tmp/rtsold.dump"; /* XXX: should be configurable */
static char *pidfilename = "/var/run/rtsold.pid"; /* should be configurable */
static int ifconfig __P((char *ifname));
static int make_packet __P((struct ifinfo *ifinfo));
static struct timeval *rtsol_check_timer __P((void));
static void TIMEVAL_ADD __P((struct timeval *a, struct timeval *b,
struct timeval *result));
static void TIMEVAL_SUB __P((struct timeval *a, struct timeval *b,
struct timeval *result));
static void rtsold_set_dump_file __P(());
static void usage __P((char *progname));
int
main(argc, argv)
int argc;
char *argv[];
{
int s, ch;
int once = 0;
struct timeval *timeout;
struct fd_set fdset;
char *argv0;
char *opts;
/*
* Initialization
*/
argv0 = argv[0];
/* get option */
if (argv0 && argv0[strlen(argv0) - 1] != 'd') {
fflag = 1;
once = 1;
opts = "dD";
} else
opts = "dDfm1";
while ((ch = getopt(argc, argv, opts)) != -1) {
switch(ch) {
case 'd':
dflag = 1;
break;
case 'D':
dflag = 2;
break;
case 'f':
fflag = 1;
break;
case 'm':
mobile_node = 1;
break;
case '1':
once = 1;
break;
default:
usage(argv0);
}
}
argc -= optind;
argv += optind;
if (argc == 0)
usage(argv0);
/* set log level */
if (dflag == 0)
log_upto = LOG_NOTICE;
if (!fflag) {
char *ident;
ident = strrchr(argv0, '/');
if (!ident)
ident = argv0;
else
ident++;
openlog(ident, LOG_NDELAY|LOG_PID, LOG_DAEMON);
if (log_upto >= 0)
setlogmask(LOG_UPTO(log_upto));
}
/* random value initilization */
srandom((u_long)time(NULL));
/* warn if accept_rtadv is down */
if (!getinet6sysctl(IPV6CTL_ACCEPT_RTADV))
warnx("kernel is configured not to accept RAs");
/* initialization to dump internal status to a file */
if (signal(SIGUSR1, (void *)rtsold_set_dump_file) < 0)
errx(1, "failed to set signal for dump status");
/* configuration per interface */
if (ifinit())
errx(1, "failed to initilizatoin interfaces");
while (argc--) {
if (ifconfig(*argv))
errx(1, "failed to initilize %s", *argv);
argv++;
}
/* open a socket for sending RS and receiving RA */
if ((s = sockopen()) < 0)
errx(1, "failed to open a socket");
/* setup for probing default routers */
if (probe_init())
errx(1, "failed to setup for probing routers");
if (!fflag)
daemon(0, 0); /* act as a daemon */
/* dump the current pid */
if (!once) {
pid_t pid = getpid();
FILE *fp;
if ((fp = fopen(pidfilename, "w")) == NULL)
warnmsg(LOG_ERR, __FUNCTION__,
"failed to open a log file(%s)",
pidfilename, strerror(errno));
else {
fprintf(fp, "%d\n", pid);
fclose(fp);
}
}
FD_ZERO(&fdset);
FD_SET(s, &fdset);
while (1) { /* main loop */
extern int errno;
int e;
struct fd_set select_fd = fdset;
if (do_dump) { /* SIGUSR1 */
do_dump = 0;
rtsold_dump_file(dumpfilename);
}
timeout = rtsol_check_timer();
if (once) {
struct ifinfo *ifi;
/* if we have no timeout, we are done (or failed) */
if (timeout == NULL)
break;
/* if all interfaces have got RA packet, we are done */
for (ifi = iflist; ifi; ifi = ifi->next) {
if (ifi->state != IFS_DOWN && ifi->racnt == 0)
break;
}
if (ifi == NULL)
break;
}
if ((e = select(s + 1, &select_fd, NULL, NULL, timeout)) < 1) {
if (e < 0 && errno != EINTR) {
warnmsg(LOG_ERR, __FUNCTION__, "select: %s",
strerror(errno));
}
continue;
}
/* packet reception */
if (FD_ISSET(s, &fdset))
rtsol_input(s);
}
/* NOTREACHED */
return 0;
}
static int
ifconfig(char *ifname)
{
struct ifinfo *ifinfo;
struct sockaddr_dl *sdl;
int flags;
if ((sdl = if_nametosdl(ifname)) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__,
"failed to get link layer information for %s", ifname);
return(-1);
}
if (find_ifinfo(sdl->sdl_index)) {
warnmsg(LOG_ERR, __FUNCTION__,
"interface %s was already cofigured", ifname);
return(-1);
}
if ((ifinfo = malloc(sizeof(*ifinfo))) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__, "memory allocation failed");
return(-1);
}
memset(ifinfo, 0, sizeof(*ifinfo));
ifinfo->sdl = sdl;
strncpy(ifinfo->ifname, ifname, sizeof(ifinfo->ifname));
/* construct a router solicitation message */
if (make_packet(ifinfo))
goto bad;
/*
* check if the interface is available.
* also check if SIOCGIFMEDIA ioctl is OK on the interface.
*/
ifinfo->mediareqok = 1;
ifinfo->active = interface_status(ifinfo);
if (!ifinfo->mediareqok) {
/*
* probe routers periodically even if the link status
* does not change.
*/
ifinfo->probeinterval = PROBE_INTERVAL;
}
/* activate interface: interface_up returns 0 on success */
flags = interface_up(ifinfo->ifname);
if (flags == 0)
ifinfo->state = IFS_DELAY;
else if (flags == IFS_TENTATIVE)
ifinfo->state = IFS_TENTATIVE;
else
ifinfo->state = IFS_DOWN;
rtsol_timer_update(ifinfo);
/* link into chain */
if (iflist)
ifinfo->next = iflist;
iflist = ifinfo;
return(0);
bad:
free(ifinfo);
free(ifinfo->sdl);
return(-1);
}
struct ifinfo *
find_ifinfo(int ifindex)
{
struct ifinfo *ifi;
for (ifi = iflist; ifi; ifi = ifi->next)
if (ifi->sdl->sdl_index == ifindex)
return(ifi);
return(NULL);
}
static int
make_packet(struct ifinfo *ifinfo)
{
char *buf;
struct nd_router_solicit *rs;
size_t packlen = sizeof(struct nd_router_solicit), lladdroptlen = 0;
if ((lladdroptlen = lladdropt_length(ifinfo->sdl)) == 0) {
warnmsg(LOG_INFO, __FUNCTION__,
"link-layer address option has null length"
" on %s. Treat as not included.", ifinfo->ifname);
}
packlen += lladdroptlen;
ifinfo->rs_datalen = packlen;
/* allocate buffer */
if ((buf = malloc(packlen)) == NULL) {
warnmsg(LOG_ERR, __FUNCTION__,
"memory allocation failed for %s", ifinfo->ifname);
return(-1);
}
ifinfo->rs_data = buf;
/* fill in the message */
rs = (struct nd_router_solicit *)buf;
rs->nd_rs_type = ND_ROUTER_SOLICIT;
rs->nd_rs_code = 0;
rs->nd_rs_cksum = 0;
rs->nd_rs_reserved = 0;
buf += sizeof(*rs);
/* fill in source link-layer address option */
if (lladdroptlen)
lladdropt_fill(ifinfo->sdl, (struct nd_opt_hdr *)buf);
return(0);
}
static struct timeval *
rtsol_check_timer()
{
static struct timeval returnval;
struct timeval now, rtsol_timer;
struct ifinfo *ifinfo;
int flags;
gettimeofday(&now, NULL);
rtsol_timer = tm_max;
for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) {
if (TIMEVAL_LEQ(ifinfo->expire, now)) {
if (dflag > 1)
warnmsg(LOG_DEBUG, __FUNCTION__,
"timer expiration on %s, "
"state = %d", ifinfo->ifname,
ifinfo->state);
switch(ifinfo->state) {
case IFS_DOWN:
case IFS_TENTATIVE:
/* interface_up returns 0 on success */
flags = interface_up(ifinfo->ifname);
if (flags == 0)
ifinfo->state = IFS_DELAY;
else if (flags == IFS_TENTATIVE)
ifinfo->state = IFS_TENTATIVE;
else
ifinfo->state = IFS_DOWN;
break;
case IFS_IDLE:
{
int oldstatus = ifinfo->active;
int probe = 0;
ifinfo->active =
interface_status(ifinfo);
if (oldstatus != ifinfo->active) {
warnmsg(LOG_DEBUG, __FUNCTION__,
"%s status is changed"
" from %d to %d",
ifinfo->ifname,
oldstatus, ifinfo->active);
probe = 1;
ifinfo->state = IFS_DELAY;
}
else if (ifinfo->probeinterval &&
(ifinfo->probetimer -=
ifinfo->timer.tv_sec) <= 0) {
/* probe timer expired */
ifinfo->probetimer =
ifinfo->probeinterval;
probe = 1;
ifinfo->state = IFS_PROBE;
}
if (probe && mobile_node)
defrouter_probe(ifinfo->sdl->sdl_index);
break;
}
case IFS_DELAY:
ifinfo->state = IFS_PROBE;
sendpacket(ifinfo);
break;
case IFS_PROBE:
if (ifinfo->probes < MAX_RTR_SOLICITATIONS)
sendpacket(ifinfo);
else {
warnmsg(LOG_INFO, __FUNCTION__,
"No answer "
"after sending %d RSs",
ifinfo->probes);
ifinfo->probes = 0;
ifinfo->state = IFS_IDLE;
}
break;
}
rtsol_timer_update(ifinfo);
}
if (TIMEVAL_LT(ifinfo->expire, rtsol_timer))
rtsol_timer = ifinfo->expire;
}
if (TIMEVAL_EQ(rtsol_timer, tm_max)) {
warnmsg(LOG_DEBUG, __FUNCTION__, "there is no timer");
return(NULL);
}
else if (TIMEVAL_LT(rtsol_timer, now))
/* this may occur when the interval is too small */
returnval.tv_sec = returnval.tv_usec = 0;
else
TIMEVAL_SUB(&rtsol_timer, &now, &returnval);
if (dflag > 1)
warnmsg(LOG_DEBUG, __FUNCTION__, "New timer is %d:%08d",
returnval.tv_sec, returnval.tv_usec);
return(&returnval);
}
void
rtsol_timer_update(struct ifinfo *ifinfo)
{
#define MILLION 1000000
#define DADRETRY 10 /* XXX: adhoc */
long interval;
struct timeval now;
bzero(&ifinfo->timer, sizeof(ifinfo->timer));
switch (ifinfo->state) {
case IFS_DOWN:
case IFS_TENTATIVE:
if (++ifinfo->dadcount > DADRETRY) {
ifinfo->dadcount = 0;
ifinfo->timer.tv_sec = PROBE_INTERVAL;
}
else
ifinfo->timer.tv_sec = 1;
break;
case IFS_IDLE:
if (mobile_node) {
/* XXX should be configurable */
ifinfo->timer.tv_sec = 3;
}
else
ifinfo->timer = tm_max; /* stop timer(valid?) */
break;
case IFS_DELAY:
interval = random() % (MAX_RTR_SOLICITATION_DELAY * MILLION);
ifinfo->timer.tv_sec = interval / MILLION;
ifinfo->timer.tv_usec = interval % MILLION;
break;
case IFS_PROBE:
ifinfo->timer.tv_sec = RTR_SOLICITATION_INTERVAL;
break;
default:
warnmsg(LOG_ERR, __FUNCTION__,
"illegal interface state(%d) on %s",
ifinfo->state, ifinfo->ifname);
return;
}
/* reset the timer */
if (TIMEVAL_EQ(ifinfo->timer, tm_max)) {
ifinfo->expire = tm_max;
warnmsg(LOG_DEBUG, __FUNCTION__,
"stop timer for %s", ifinfo->ifname);
}
else {
gettimeofday(&now, NULL);
TIMEVAL_ADD(&now, &ifinfo->timer, &ifinfo->expire);
if (dflag > 1)
warnmsg(LOG_DEBUG, __FUNCTION__,
"set timer for %s to %d:%d", ifinfo->ifname,
(int)ifinfo->timer.tv_sec,
(int)ifinfo->timer.tv_usec);
}
#undef MILLION
}
/* timer related utility functions */
#define MILLION 1000000
/* result = a + b */
static void
TIMEVAL_ADD(struct timeval *a, struct timeval *b, struct timeval *result)
{
long l;
if ((l = a->tv_usec + b->tv_usec) < MILLION) {
result->tv_usec = l;
result->tv_sec = a->tv_sec + b->tv_sec;
}
else {
result->tv_usec = l - MILLION;
result->tv_sec = a->tv_sec + b->tv_sec + 1;
}
}
/*
* result = a - b
* XXX: this function assumes that a >= b.
*/
void
TIMEVAL_SUB(struct timeval *a, struct timeval *b, struct timeval *result)
{
long l;
if ((l = a->tv_usec - b->tv_usec) >= 0) {
result->tv_usec = l;
result->tv_sec = a->tv_sec - b->tv_sec;
}
else {
result->tv_usec = MILLION + l;
result->tv_sec = a->tv_sec - b->tv_sec - 1;
}
}
static void
rtsold_set_dump_file()
{
do_dump = 1;
}
static void
usage(char *progname)
{
if (progname && progname[strlen(progname) - 1] != 'd')
fprintf(stderr, "usage: rtsol [-dD] interfaces\n");
else
fprintf(stderr, "usage: rtsold [-dDfm1] interfaces\n");
exit(1);
}
void
#if __STDC__
warnmsg(int priority, const char *func, const char *msg, ...)
#else
warnmsg(priority, func, msg, va_alist)
int priority;
const char *func;
const char *msg;
va_dcl
#endif
{
va_list ap;
char buf[BUFSIZ];
va_start(ap, msg);
if (fflag) {
if (priority <= log_upto) {
(void)vfprintf(stderr, msg, ap);
(void)fprintf(stderr, "\n");
}
} else {
snprintf(buf, sizeof(buf), "<%s> %s", func, msg);
vsyslog(priority, buf, ap);
}
va_end(ap);
}

91
usr.sbin/rtsold/rtsold.h Normal file
View File

@ -0,0 +1,91 @@
/*
* 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$
*/
struct ifinfo {
struct ifinfo *next; /* pointer to the next interface */
struct sockaddr_dl *sdl; /* link-layer address */
char ifname[16]; /* interface name */
int active; /* interface status */
int probeinterval; /* interval of probe timer(if necessary) */
int probetimer; /* rest of probe timer */
int mediareqok; /* wheter the IF supports SIOCGIFMEDIA */
int state;
int probes;
int dadcount;
struct timeval timer;
struct timeval expire;
int racnt; /* total # of valid RAs it have got */
size_t rs_datalen;
u_char *rs_data;
};
/* per interface status */
#define IFS_IDLE 0
#define IFS_DELAY 1
#define IFS_PROBE 2
#define IFS_DOWN 3
#define IFS_TENTATIVE 4
/* rtsold.c */
extern struct timeval tm_max;
extern int dflag;
struct ifinfo *find_ifinfo __P((int ifindex));
void rtsol_timer_update __P((struct ifinfo *ifinfo));
#ifdef __STDC__
extern void warnmsg __P((int, const char *, const char *, ...));
#else
extern void warnmsg __P((int, const char *, const char *, va_list));
#endif
/* if.c */
extern int ifinit __P((void));
extern int interface_up __P((char *name));
extern int interface_status __P((struct ifinfo*));
extern int lladdropt_length __P((struct sockaddr_dl *sdl));
extern void lladdropt_fill __P((struct sockaddr_dl *sdl,
struct nd_opt_hdr *ndopt));
extern struct sockaddr_dl *if_nametosdl __P((char *name));
extern int getinet6sysctl __P((int code));
/* rtsol.c */
extern int sockopen __P((void));
extern void sendpacket __P((struct ifinfo *ifinfo));
extern void rtsol_input __P((int s));
/* probe.c */
extern int probe_init __P((void));
extern void defrouter_probe __P((int ifindex));
/* dump.c */
extern void rtsold_dump_file __P((char *));

View File

@ -0,0 +1,26 @@
# Copyright (c) 1996 WIDE Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modifications, are permitted provided that the above copyright notice
# and this paragraph are duplicated in all such forms and that any
# documentation, advertising materials, and other materials related to
# such distribution and use acknowledge that the software was developed
# by the WIDE Project, Japan. The name of the Project may not be used to
# endorse or promote products derived from this software without
# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE.
# $FreeBSD$
PROG= traceroute6
BINOWN= root
BINGRP= bin
BINMODE=4555
CFLAGS+=-DINET6
MAN8= traceroute6.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,96 @@
.\" 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.
.\"
.\" $Id: traceroute6.8,v 1.1.1.1 1999/08/08 23:32:38 itojun Exp $
.\" $FreeBSD$
.\"
.Dd May 17, 1998
.Dt TRACEROUTE6 8
.Os KAME
.\"
.Sh NAME
.Nm traceroute6
.Nd print the route IPv6 packets will take to the destination
.\"
.Sh SYNOPSIS
.Nm
.Op Fl dlnrv
.Op Fl m Ar hoplimit
.Op Fl p Ar port
.Op Fl q Ar probes
.Op Fl s Ar src
.Op Fl w Ar waittime
.\"
.Sh DESCRIPTION
.Bl -tag -width Ds
.It Fl d
Debug mode.
.It Fl m Ar hoplimit
Specify maximum hoplimit.
.It Fl l
Print both host hostnames and numeric addresses.
Normally
.Nm
prints only hostnames if
.Fl n
is not specified, and only numeric addresses if
.Fl n
is specified.
.It Fl n
Do not resolve numeric address to hostname.
.It Fl p Ar port
Set UDP port number to
.Ar port .
.It Fl q Ar probes
Set the number of probe per hop count to
.Ar probes .
.It Fl r
.It Fl s Ar src
.Ar Src
specifies the source IPv6 address to be used.
.It Fl v
Be verbose.
.It Fl w Ar waittime
Specify the delay time between probes.
.El
.\"
.Sh RETURN VALUES
.Nm Traceroute6
will exit with 0 on success, and non-zero on errors.
.\"
.Sh SEE ALSO
.Xr ping 8 ,
.Xr ping6 8 ,
.Xr traceroute 8
.\"
.Sh HISTORY
The
.Nm
command first appeared in WIDE hydrangea IPv6 protocol stack kit.
.\"
.\" .Sh BUGS
.\" (to be written)

File diff suppressed because it is too large Load Diff