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:
parent
ed63a7aaef
commit
7d56d3747c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=55163
@ -62,6 +62,7 @@
|
|||||||
#define _NETDB_H_
|
#define _NETDB_H_
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#ifndef _PATH_HEQUIV
|
#ifndef _PATH_HEQUIV
|
||||||
# define _PATH_HEQUIV "/etc/hosts.equiv"
|
# define _PATH_HEQUIV "/etc/hosts.equiv"
|
||||||
@ -111,6 +112,17 @@ struct protoent {
|
|||||||
int p_proto; /* protocol # */
|
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()
|
* Error return codes from gethostbyname() and gethostbyaddr()
|
||||||
* (left in extern int h_errno).
|
* (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_DATA 4 /* Valid name, no data record of requested type */
|
||||||
#define NO_ADDRESS NO_DATA /* no address, look for MX record */
|
#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
|
__BEGIN_DECLS
|
||||||
void endhostent __P((void));
|
void endhostent __P((void));
|
||||||
void endnetent __P((void));
|
void endnetent __P((void));
|
||||||
void endprotoent __P((void));
|
void endprotoent __P((void));
|
||||||
void endservent __P((void));
|
void endservent __P((void));
|
||||||
|
void freehostent __P((struct hostent *));
|
||||||
struct hostent *gethostbyaddr __P((const char *, int, int));
|
struct hostent *gethostbyaddr __P((const char *, int, int));
|
||||||
struct hostent *gethostbyname __P((const char *));
|
struct hostent *gethostbyname __P((const char *));
|
||||||
struct hostent *gethostbyname2 __P((const char *, int));
|
struct hostent *gethostbyname2 __P((const char *, int));
|
||||||
struct hostent *gethostent __P((void));
|
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 *getnetbyaddr __P((unsigned long, int));
|
||||||
struct netent *getnetbyname __P((const char *));
|
struct netent *getnetbyname __P((const char *));
|
||||||
struct netent *getnetent __P((void));
|
struct netent *getnetent __P((void));
|
||||||
@ -148,6 +219,12 @@ void sethostent __P((int));
|
|||||||
/* void sethostfile __P((const char *)); */
|
/* void sethostfile __P((const char *)); */
|
||||||
void setnetent __P((int));
|
void setnetent __P((int));
|
||||||
void setprotoent __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));
|
void setservent __P((int));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -116,6 +117,21 @@ struct __res_state {
|
|||||||
char pad[72]; /* on an i386 this means 512b total */
|
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)
|
* Resolver options (keep these in synch with res_debug.c, please)
|
||||||
*/
|
*/
|
||||||
@ -181,6 +197,9 @@ struct res_sym {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern struct __res_state _res;
|
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_class_syms[];
|
||||||
extern const struct res_sym __p_type_syms[];
|
extern const struct res_sym __p_type_syms[];
|
||||||
|
|
||||||
|
@ -4,15 +4,16 @@
|
|||||||
# machine-independent net sources
|
# machine-independent net sources
|
||||||
.PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/net ${.CURDIR}/../libc/net
|
.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 \
|
gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \
|
||||||
|
getnameinfo.c \
|
||||||
getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
|
getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
|
||||||
getproto.c getprotoent.c getprotoname.c getservbyname.c \
|
getproto.c getprotoent.c getprotoname.c getservbyname.c \
|
||||||
getservbyport.c getservent.c herror.c inet_addr.c ifname.c \
|
getservbyport.c getservent.c herror.c inet_addr.c ifname.c \
|
||||||
inet_lnaof.c \
|
inet_lnaof.c \
|
||||||
inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.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_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_name.c ns_netint.c \
|
||||||
ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c nsap_addr.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 \
|
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
|
res_update.c rthdr.c send.c vars.c
|
||||||
# not supported: iso_addr.c
|
# not supported: iso_addr.c
|
||||||
|
|
||||||
|
CFLAGS+=-DINET6
|
||||||
|
|
||||||
# machine-dependent net sources
|
# machine-dependent net sources
|
||||||
.include "${.CURDIR}/../libc/${MACHINE_ARCH}/net/Makefile.inc"
|
.include "${.CURDIR}/../libc/${MACHINE_ARCH}/net/Makefile.inc"
|
||||||
|
|
||||||
.if ${LIB} == "c"
|
.if ${LIB} == "c"
|
||||||
MAN3+= addr2ascii.3 byteorder.3 ethers.3 gethostbyname.3 \
|
MAN3+= addr2ascii.3 byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 \
|
||||||
getnetent.3 getprotoent.3 getservent.3 if_indextoname.3 \
|
getipnodebyname.3 \
|
||||||
|
getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 if_indextoname.3 \
|
||||||
inet.3 linkaddr.3 rcmd.3 resolver.3
|
inet.3 linkaddr.3 rcmd.3 resolver.3
|
||||||
# not installed: iso_addr.3 ns.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
|
byteorder.3 ntohs.3
|
||||||
MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.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
|
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 \
|
MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
|
||||||
gethostbyname.3 gethostbyname2.3 gethostbyname.3 gethostent.3 \
|
gethostbyname.3 gethostbyname2.3 gethostbyname.3 gethostent.3 \
|
||||||
gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \
|
gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \
|
||||||
gethostbyname.3 sethostent.3
|
gethostbyname.3 sethostent.3
|
||||||
|
MLINKS+=getipnodebyname.3 getipnodebyaddr.3 getipnodebyname.3 freehostent.3
|
||||||
MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
|
MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
|
||||||
getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
|
getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
|
||||||
MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
|
MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
|
||||||
|
408
lib/libc/net/getaddrinfo.3
Normal file
408
lib/libc/net/getaddrinfo.3
Normal 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
1014
lib/libc/net/getaddrinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
446
lib/libc/net/getipnodebyname.3
Normal file
446
lib/libc/net/getipnodebyname.3
Normal 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
232
lib/libc/net/getnameinfo.3
Normal 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
228
lib/libc/net/getnameinfo.c
Normal 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
1260
lib/libc/net/name6.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -112,6 +112,9 @@ struct __res_state _res
|
|||||||
# endif
|
# endif
|
||||||
;
|
;
|
||||||
|
|
||||||
|
#ifdef INET6
|
||||||
|
struct __res_state_ext _res_ext;
|
||||||
|
#endif /* INET6 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up default settings. If the configuration file exist, the values
|
* Set up default settings. If the configuration file exist, the values
|
||||||
@ -314,6 +317,9 @@ res_init()
|
|||||||
#ifdef RESOLVSORT
|
#ifdef RESOLVSORT
|
||||||
if (MATCH(buf, "sortlist")) {
|
if (MATCH(buf, "sortlist")) {
|
||||||
struct in_addr a;
|
struct in_addr a;
|
||||||
|
#ifdef INET6
|
||||||
|
struct in6_addr a6;
|
||||||
|
#endif /* INET6 */
|
||||||
|
|
||||||
cp = buf + sizeof("sortlist") - 1;
|
cp = buf + sizeof("sortlist") - 1;
|
||||||
while (nsort < MAXRESOLVSORT) {
|
while (nsort < MAXRESOLVSORT) {
|
||||||
@ -347,8 +353,61 @@ res_init()
|
|||||||
_res.sort_list[nsort].mask =
|
_res.sort_list[nsort].mask =
|
||||||
net_mask(_res.sort_list[nsort].addr);
|
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++;
|
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;
|
*cp = n;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -50,11 +50,13 @@ SUBDIR= adjkerntz \
|
|||||||
nologin \
|
nologin \
|
||||||
nos-tun \
|
nos-tun \
|
||||||
ping \
|
ping \
|
||||||
|
ping6 \
|
||||||
quotacheck \
|
quotacheck \
|
||||||
reboot \
|
reboot \
|
||||||
restore \
|
restore \
|
||||||
route \
|
route \
|
||||||
routed \
|
routed \
|
||||||
|
rtsol \
|
||||||
savecore \
|
savecore \
|
||||||
shutdown \
|
shutdown \
|
||||||
slattach \
|
slattach \
|
||||||
|
25
sbin/ping6/Makefile
Normal file
25
sbin/ping6/Makefile
Normal 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
332
sbin/ping6/ping6.8
Normal 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
1549
sbin/ping6/ping6.c
Normal file
File diff suppressed because it is too large
Load Diff
29
sbin/rtsol/Makefile
Normal file
29
sbin/rtsol/Makefile
Normal 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>
|
@ -777,7 +777,7 @@ init_newprefix(struct in6_rrenumreq *irr, struct ifprefix *ifpr,
|
|||||||
return error;
|
return error;
|
||||||
rap->ra_ifid = orap->ra_ifid;
|
rap->ra_ifid = orap->ra_ifid;
|
||||||
rap->ra_flags.anycast = (orap->ra_addr != NULL &&
|
rap->ra_flags.anycast = (orap->ra_addr != NULL &&
|
||||||
(orap->ra_addr->ia_flags &
|
(orap->ra_addr->ia6_flags &
|
||||||
IN6_IFF_ANYCAST) != 0) ? 1 : 0;
|
IN6_IFF_ANYCAST) != 0) ? 1 : 0;
|
||||||
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
|
LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
|
||||||
}
|
}
|
||||||
|
@ -390,23 +390,14 @@ ip6_stats(off, name)
|
|||||||
printf("\tMbuf statistics:\n");
|
printf("\tMbuf statistics:\n");
|
||||||
printf("\t\t%lu one mbuf\n", ip6stat.ip6s_m1);
|
printf("\t\t%lu one mbuf\n", ip6stat.ip6s_m1);
|
||||||
for (first = 1, i = 0; i < 32; i++) {
|
for (first = 1, i = 0; i < 32; i++) {
|
||||||
|
char ifbuf[IFNAMSIZ];
|
||||||
if (ip6stat.ip6s_m2m[i] != 0) {
|
if (ip6stat.ip6s_m2m[i] != 0) {
|
||||||
if (first) {
|
if (first) {
|
||||||
printf("\t\ttwo or more mbuf:\n");
|
printf("\t\ttwo or more mbuf:\n");
|
||||||
first = 0;
|
first = 0;
|
||||||
}
|
}
|
||||||
printf("\t\t\t"
|
printf("\t\t\t%s= %ld\n",
|
||||||
#ifdef notyet
|
|
||||||
"%s"
|
|
||||||
#else
|
|
||||||
"if%d"
|
|
||||||
#endif
|
|
||||||
"= %ld\n",
|
|
||||||
#ifdef notyet
|
|
||||||
if_indextoname(i, ifbuf),
|
if_indextoname(i, ifbuf),
|
||||||
#else
|
|
||||||
i,
|
|
||||||
#endif
|
|
||||||
ip6stat.ip6s_m2m[i]);
|
ip6stat.ip6s_m2m[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,11 +129,11 @@ static struct nlist nl[] = {
|
|||||||
{ "_ip6stat" },
|
{ "_ip6stat" },
|
||||||
#define N_ICMP6STAT 29
|
#define N_ICMP6STAT 29
|
||||||
{ "_icmp6stat" },
|
{ "_icmp6stat" },
|
||||||
#ifdef notyet
|
|
||||||
#define N_IPSECSTAT 30
|
#define N_IPSECSTAT 30
|
||||||
{ "_ipsecstat" },
|
{ "_ipsecstat" },
|
||||||
#define N_IPSEC6STAT 31
|
#define N_IPSEC6STAT 31
|
||||||
{ "_ipsec6stat" },
|
{ "_ipsec6stat" },
|
||||||
|
#ifdef notyet
|
||||||
#define N_PIM6STAT 32
|
#define N_PIM6STAT 32
|
||||||
{ "_pim6stat" },
|
{ "_pim6stat" },
|
||||||
#define N_MRT6PROTO 33
|
#define N_MRT6PROTO 33
|
||||||
|
@ -605,7 +605,7 @@ p_rtentry(rt)
|
|||||||
WID_DST);
|
WID_DST);
|
||||||
p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST,
|
p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST,
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
kgetsa(rt->rt_gateway)->sa_family == AF_INET6 ? WID_GW6 :
|
addr.u_sa.sa_family == AF_INET6 ? WID_GW6 :
|
||||||
#endif
|
#endif
|
||||||
WID_GW);
|
WID_GW);
|
||||||
p_flags(rt->rt_flags, "%-6.6s ");
|
p_flags(rt->rt_flags, "%-6.6s ");
|
||||||
@ -763,16 +763,17 @@ netname6(sa6, mask)
|
|||||||
u_char *p = (u_char *)mask;
|
u_char *p = (u_char *)mask;
|
||||||
u_char *lim;
|
u_char *lim;
|
||||||
int masklen, illegal = 0;
|
int masklen, illegal = 0;
|
||||||
#ifdef notyet
|
|
||||||
int flag = NI_WITHSCOPEID;
|
int flag = NI_WITHSCOPEID;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mask) {
|
if (mask) {
|
||||||
for (masklen = 0, lim = p + 16; p < lim; p++) {
|
for (masklen = 0, lim = p + 16; p < lim; p++) {
|
||||||
switch (*p) {
|
if (*p == 0xff)
|
||||||
case 0xff:
|
|
||||||
masklen += 8;
|
masklen += 8;
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
if (p < lim) {
|
||||||
|
switch (*p) {
|
||||||
case 0xfe:
|
case 0xfe:
|
||||||
masklen += 7;
|
masklen += 7;
|
||||||
break;
|
break;
|
||||||
@ -810,14 +811,10 @@ netname6(sa6, mask)
|
|||||||
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
||||||
return("default");
|
return("default");
|
||||||
|
|
||||||
#ifdef notyet
|
|
||||||
if (nflag)
|
if (nflag)
|
||||||
flag |= NI_NUMERICHOST;
|
flag |= NI_NUMERICHOST;
|
||||||
getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
|
getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
|
||||||
NULL, 0, flag);
|
NULL, 0, flag);
|
||||||
#else
|
|
||||||
inet_ntop(AF_INET6, (void *)&sa6->sin6_addr, line, sizeof(line));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nflag)
|
if (nflag)
|
||||||
sprintf(&line[strlen(line)], "/%d", masklen);
|
sprintf(&line[strlen(line)], "/%d", masklen);
|
||||||
@ -829,37 +826,14 @@ char *
|
|||||||
routename6(sa6)
|
routename6(sa6)
|
||||||
struct sockaddr_in6 *sa6;
|
struct sockaddr_in6 *sa6;
|
||||||
{
|
{
|
||||||
#ifdef notyet
|
static char line[MAXHOSTNAMELEN + 1];
|
||||||
int flag = NI_WITHSCOPEID;
|
int flag = NI_WITHSCOPEID;
|
||||||
|
|
||||||
if (nflag)
|
if (nflag)
|
||||||
flag |= NI_NUMERICHOST;
|
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),
|
getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
|
||||||
NULL, 0, flag);
|
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;
|
return line;
|
||||||
}
|
}
|
||||||
|
21
usr.sbin/gifconfig/Makefile
Normal file
21
usr.sbin/gifconfig/Makefile
Normal 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>
|
140
usr.sbin/gifconfig/gifconfig.8
Normal file
140
usr.sbin/gifconfig/gifconfig.8
Normal 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)
|
834
usr.sbin/gifconfig/gifconfig.c
Normal file
834
usr.sbin/gifconfig/gifconfig.c
Normal 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*/
|
14
usr.sbin/ifmcstat/Makefile
Normal file
14
usr.sbin/ifmcstat/Makefile
Normal 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>
|
34
usr.sbin/ifmcstat/ifmcstat.8
Normal file
34
usr.sbin/ifmcstat/ifmcstat.8
Normal 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.
|
338
usr.sbin/ifmcstat/ifmcstat.c
Normal file
338
usr.sbin/ifmcstat/ifmcstat.c
Normal 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
12
usr.sbin/prefix/Makefile
Normal 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
217
usr.sbin/prefix/prefix.8
Normal 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
592
usr.sbin/prefix/prefix.c
Normal 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;
|
||||||
|
}
|
9
usr.sbin/rip6query/Makefile
Normal file
9
usr.sbin/rip6query/Makefile
Normal 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>
|
62
usr.sbin/rip6query/rip6query.8
Normal file
62
usr.sbin/rip6query/rip6query.8
Normal 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.
|
206
usr.sbin/rip6query/rip6query.c
Normal file
206
usr.sbin/rip6query/rip6query.c
Normal 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));
|
||||||
|
}
|
9
usr.sbin/route6d/Makefile
Normal file
9
usr.sbin/route6d/Makefile
Normal 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
64
usr.sbin/route6d/misc/chkrt
Executable 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";
|
||||||
|
}
|
52
usr.sbin/route6d/misc/cksum.c
Normal file
52
usr.sbin/route6d/misc/cksum.c
Normal 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
234
usr.sbin/route6d/route6d.8
Normal 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
2913
usr.sbin/route6d/route6d.c
Normal file
File diff suppressed because it is too large
Load Diff
91
usr.sbin/route6d/route6d.h
Normal file
91
usr.sbin/route6d/route6d.h
Normal 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
25
usr.sbin/rtsold/Makefile
Normal 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
137
usr.sbin/rtsold/dump.c
Normal 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
423
usr.sbin/rtsold/if.c
Normal 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
179
usr.sbin/rtsold/probe.c
Normal 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
312
usr.sbin/rtsold/rtsol.c
Normal 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
175
usr.sbin/rtsold/rtsold.8
Normal 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
622
usr.sbin/rtsold/rtsold.c
Normal 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
91
usr.sbin/rtsold/rtsold.h
Normal 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 *));
|
26
usr.sbin/traceroute6/Makefile
Normal file
26
usr.sbin/traceroute6/Makefile
Normal 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>
|
96
usr.sbin/traceroute6/traceroute6.8
Normal file
96
usr.sbin/traceroute6/traceroute6.8
Normal 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)
|
1127
usr.sbin/traceroute6/traceroute6.c
Normal file
1127
usr.sbin/traceroute6/traceroute6.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user