summaryrefslogtreecommitdiffstats
path: root/usr.sbin/gifconfig
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>1999-12-28 02:37:14 +0000
committershin <shin@FreeBSD.org>1999-12-28 02:37:14 +0000
commit8c2ccb59caf882ac518eda1f570ea731d4466216 (patch)
treeec4d4f8bd121d60c04c8119810151af20c92b20b /usr.sbin/gifconfig
parentb39a79861ddfb250e941d89c255bcb8cda9481dc (diff)
downloadFreeBSD-src-8c2ccb59caf882ac518eda1f570ea731d4466216.zip
FreeBSD-src-8c2ccb59caf882ac518eda1f570ea731d4466216.tar.gz
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
Diffstat (limited to 'usr.sbin/gifconfig')
-rw-r--r--usr.sbin/gifconfig/Makefile21
-rw-r--r--usr.sbin/gifconfig/gifconfig.8140
-rw-r--r--usr.sbin/gifconfig/gifconfig.c834
3 files changed, 995 insertions, 0 deletions
diff --git a/usr.sbin/gifconfig/Makefile b/usr.sbin/gifconfig/Makefile
new file mode 100644
index 0000000..b562390
--- /dev/null
+++ b/usr.sbin/gifconfig/Makefile
@@ -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>
diff --git a/usr.sbin/gifconfig/gifconfig.8 b/usr.sbin/gifconfig/gifconfig.8
new file mode 100644
index 0000000..702777f
--- /dev/null
+++ b/usr.sbin/gifconfig/gifconfig.8
@@ -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)
diff --git a/usr.sbin/gifconfig/gifconfig.c b/usr.sbin/gifconfig/gifconfig.c
new file mode 100644
index 0000000..3f36b03
--- /dev/null
+++ b/usr.sbin/gifconfig/gifconfig.c
@@ -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*/
OpenPOWER on IntegriCloud