/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
+
/*-
* Copyright (c) 2001 Charles Mott <cmott@scientech.com>
* All rights reserved.
if (ftp_message_type == FTP_PORT_COMMAND) {
/* Generate PORT command string. */
- sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n",
+ snprintf(stemp, sizeof(stemp), "PORT %d,%d,%d,%d,%d,%d\r\n",
a1,a2,a3,a4,p1,p2);
} else {
/* Generate 227 reply string. */
- sprintf(stemp,
+ snprintf(stemp, sizeof(stemp),
"227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
a1,a2,a3,a4,p1,p2);
}
break;
case FTP_EPRT_COMMAND:
/* Generate EPRT command string. */
- sprintf(stemp, "EPRT |1|%d.%d.%d.%d|%d|\r\n",
+ snprintf(stemp, sizeof(stemp), "EPRT |1|%d.%d.%d.%d|%d|\r\n",
a1,a2,a3,a4,ntohs(alias_port));
break;
case FTP_229_REPLY:
/* Generate 229 reply string. */
- sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n",
+ snprintf(stemp, sizeof(stemp), "229 Entering Extended Passive Mode (|||%d|)\r\n",
ntohs(alias_port));
break;
}
/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
+
/*-
* Copyright (c) 2001 Charles Mott <cmott@scientech.com>
* All rights reserved.
switch (slen % 2)
{
case 0:
- strcat(buffer, " \n");
+ strlcat(buffer, " \n", sizeof(buffer));
slen += 2;
break;
case 1:
- strcat(buffer, "\n");
+ strlcat(buffer, "\n", sizeof(buffer));
slen += 1;
}
cmd_len = strlen(cmd);
if (cmd_len > (sizeof(buffer) - 1))
return -1;
- strcpy(buffer, cmd);
+ strlcpy(buffer, cmd, sizeof(buffer));
/* Convert to lower case */
len = strlen(buffer);
break;
case STATE_READ_PORT:
- strcpy(str_port, token);
+ strlcpy(str_port, token, sizeof(str_port));
state = STATE_READ_KEYWORD;
break;
/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
+
/*
* alias_smedia.c
*
size_t lentmp;
/* Copy into IP packet */
- sprintf(stemp, "%d", ntohs(salias));
+ snprintf(stemp, sizeof(stemp), "%d", ntohs(salias));
lentmp = strlen(stemp);
/* account for ending ';' */
if (port_newdata + lentmp + 1 > newdata + sizeof(newdata)) {
port_newdata += lentmp;
if (eport != 0) {
- sprintf(stemp, "%d", ntohs(ealias));
+ snprintf(stemp, sizeof(stemp), "%d", ntohs(ealias));
lentmp = strlen(stemp);
/* account for middle '-' and for ending ';' */
.Nm
.Op Fl n
.Op Fl i Ar interface
+.Op Fl l
.Fl a
.Nm
.Fl d Ar hostname
.Ar interface .
Applicable only to the following operations:
display one, display all, delete all.
+.It Fl l
+Show link-layer reachability information.
.It Fl n
Show network addresses as numbers (normally
.Nm
.Sh SEE ALSO
.Xr inet 3 ,
.Xr arp 4 ,
-.Xr ifconfig 8
+.Xr ifconfig 8 ,
+.Xr ndp 8
.Sh HISTORY
The
.Nm
utility appeared in
-.Bx 4.3 .
\ No newline at end of file
+.Bx 4.3 .
+/*
+ * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1984, 1993
* The Regents of the University of California. All rights reserved.
typedef void (action_fn)(struct sockaddr_dl *sdl,
struct sockaddr_inarp *s_in, struct rt_msghdr *rtm);
+typedef void (action_ext_fn)(struct sockaddr_dl *sdl,
+ struct sockaddr_inarp *s_in, struct rt_msghdr_ext *rtm);
static int search(in_addr_t addr, action_fn *action);
+static int search_ext(in_addr_t addr, action_ext_fn *action);
static action_fn print_entry;
static action_fn nuke_entry;
+static action_ext_fn print_entry_ext;
+static char *print_lladdr(struct sockaddr_dl *);
static int delete(char *host, int do_proxy);
static void usage(void);
static int set(int argc, char **argv);
static int get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr);
static struct sockaddr_inarp *getaddr(char *host);
static int valid_type(int type);
+static char *sec2str(time_t);
static int nflag; /* no reverse dns lookups */
static char *rifname;
int ch, func = 0;
int rtn = 0;
int aflag = 0; /* do it for all entries */
+ int lflag = 0;
+ uint32_t ifindex = 0;
- while ((ch = getopt(argc, argv, "andfsSi:")) != -1)
+ while ((ch = getopt(argc, argv, "andflsSi:")) != -1)
switch((char)ch) {
case 'a':
aflag = 1;
case 'n':
nflag = 1;
break;
+ case 'l':
+ lflag = 1;
+ break;
case 'S':
SETFUNC(F_REPLACE);
break;
if (rifname) {
if (func != F_GET && !(func == F_DELETE && aflag))
errx(1, "-i not applicable to this operation");
- if (if_nametoindex(rifname) == 0) {
+ if ((ifindex = if_nametoindex(rifname)) == 0) {
if (errno == ENXIO)
errx(1, "interface %s does not exist", rifname);
else
if (aflag) {
if (argc != 0)
usage();
- search(0, print_entry);
+ if (lflag) {
+ printf("%-23s %-17s %-9.9s %-9.9s %8.8s %4s "
+ "%4s\n", "Neighbor", "Linklayer Address",
+ "Expire(O)", "Expire(I)", "Netif", "Refs",
+ "Prbs");
+ search_ext(0, print_entry_ext);
+ } else {
+ search(0, print_entry);
+ }
} else {
if (argc != 1)
usage();
usage();
}
}
+ if (i > argc)
+ usage();
rtn = delete(argv[0], do_proxy);
}
break;
/*
* Stolen and adapted from ifconfig
*/
-static void
+static char *
print_lladdr(struct sockaddr_dl *sdl)
{
+ static char buf[256];
char *cp;
- int n;
+ int n, bufsize = sizeof (buf), p = 0;
+ bzero(buf, sizeof (buf));
cp = (char *)LLADDR(sdl);
if ((n = sdl->sdl_alen) > 0) {
while (--n >= 0)
- printf("%x%s",*cp++ & 0xff, n>0? ":" : "");
+ p += snprintf(buf + p, bufsize - p, "%x%s",
+ *cp++ & 0xff, n > 0 ? ":" : "");
}
+ return (buf);
}
-
/*
* Display an arp entry
*/
printf("%s (%s) at ", host, inet_ntoa(addr->sin_addr));
if (sdl->sdl_alen) {
#if 1
- print_lladdr(sdl);
+ printf("%s", print_lladdr(sdl));
#else
if ((sdl->sdl_type == IFT_ETHER ||
sdl->sdl_type == IFT_L2VLAN ||
*/
static void
nuke_entry(struct sockaddr_dl *sdl __unused,
- struct sockaddr_inarp *addr, struct rt_msghdr *rtm __unused)
+ struct sockaddr_inarp *addr, struct rt_msghdr *rtm)
{
char ip[20];
snprintf(ip, sizeof(ip), "%s", inet_ntoa(addr->sin_addr));
+ /*
+ * When deleting all entries, specify the interface scope of each entry
+ */
+ if ((rtm->rtm_flags & RTF_IFSCOPE))
+ ifscope = rtm->rtm_index;
(void)delete(ip, 0);
+ ifscope = 0;
}
static void
{
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: arp [-n] [-i interface] hostname",
- " arp [-n] [-i interface] -a",
+ " arp [-n] [-i interface] [-l] -a",
" arp -d hostname [pub] [ifscope interface]",
" arp -d [-i interface] -a",
" arp -s hostname ether_addr [temp] [reject] [blackhole] [pub [only]] [ifscope interface]",
close(sock);
return (retval);
}
+
+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 += snprintf(p, sizeof(result) - (p - result), "%dd", days);
+ }
+ if (!first || hours) {
+ first = 0;
+ p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
+ }
+ if (!first || mins) {
+ first = 0;
+ p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
+ }
+ snprintf(p, sizeof(result) - (p - result), "%ds", secs);
+
+ return(result);
+}
+
+static int
+search_ext(in_addr_t addr, action_ext_fn *action)
+{
+ int mib[6];
+ size_t needed;
+ char *lim, *buf, *newbuf, *next;
+ struct rt_msghdr_ext *ertm;
+ struct sockaddr_inarp *sin2;
+ struct sockaddr_dl *sdl;
+ char ifname[IF_NAMESIZE];
+ int st, found_entry = 0;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET;
+ mib[4] = NET_RT_DUMPX_FLAGS;
+ mib[5] = RTF_LLINFO;
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ err(1, "route-sysctl-estimate");
+ if (needed == 0) /* empty table */
+ return 0;
+ buf = NULL;
+ for (;;) {
+ newbuf = realloc(buf, needed);
+ if (newbuf == NULL) {
+ if (buf != NULL)
+ free(buf);
+ errx(1, "could not reallocate memory");
+ }
+ buf = newbuf;
+ st = sysctl(mib, 6, buf, &needed, NULL, 0);
+ if (st == 0 || errno != ENOMEM)
+ break;
+ needed += needed / 8;
+ }
+ if (st == -1)
+ err(1, "actual retrieval of routing table");
+ lim = buf + needed;
+ for (next = buf; next < lim; next += ertm->rtm_msglen) {
+ ertm = (struct rt_msghdr_ext *)next;
+ sin2 = (struct sockaddr_inarp *)(ertm + 1);
+ sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
+ if (rifname && if_indextoname(sdl->sdl_index, ifname) &&
+ strcmp(ifname, rifname))
+ continue;
+ if (addr) {
+ if (addr != sin2->sin_addr.s_addr)
+ continue;
+ found_entry = 1;
+ }
+ (*action)(sdl, sin2, ertm);
+ }
+ free(buf);
+ return (found_entry);
+}
+
+static void
+print_entry_ext(struct sockaddr_dl *sdl, struct sockaddr_inarp *addr,
+ struct rt_msghdr_ext *ertm)
+{
+ const char *host;
+ struct hostent *hp;
+ char ifname[IF_NAMESIZE];
+ struct timeval time;
+
+ if (nflag == 0)
+ hp = gethostbyaddr((caddr_t)&(addr->sin_addr),
+ sizeof (addr->sin_addr), AF_INET);
+ else
+ hp = 0;
+
+ if (hp)
+ host = hp->h_name;
+ else
+ host = inet_ntoa(addr->sin_addr);
+
+ printf("%-23s ", host);
+
+ if (sdl->sdl_alen)
+ printf("%-17s ", print_lladdr(sdl));
+ else
+ printf("%-17s ", "(incomplete)");
+
+ gettimeofday(&time, 0);
+
+ if (ertm->rtm_ri.ri_refcnt == 0 || ertm->rtm_ri.ri_snd_expire == 0)
+ printf("%-9.9s ", "(none)");
+ else if (ertm->rtm_ri.ri_snd_expire > time.tv_sec)
+ printf("%-9.9s ",
+ sec2str(ertm->rtm_ri.ri_snd_expire - time.tv_sec));
+ else
+ printf("%-9.9s ", "expired");
+
+ if (ertm->rtm_ri.ri_refcnt == 0 || ertm->rtm_ri.ri_rcv_expire == 0)
+ printf("%-9.9s", "(none)");
+ else if (ertm->rtm_ri.ri_rcv_expire > time.tv_sec)
+ printf("%-9.9s",
+ sec2str(ertm->rtm_ri.ri_rcv_expire - time.tv_sec));
+ else
+ printf("%-9.9s", "expired");
+
+ if (if_indextoname(sdl->sdl_index, ifname) == NULL)
+ snprintf(ifname, sizeof (ifname), "%s", "?");
+ printf(" %8.8s", ifname);
+
+ if (ertm->rtm_ri.ri_refcnt) {
+ printf(" %4d", ertm->rtm_ri.ri_refcnt);
+ if (ertm->rtm_ri.ri_probes)
+ printf(" %4d", ertm->rtm_ri.ri_probes);
+ }
+ printf("\n");
+}
static void
in_getaddr(const char *s, int which)
{
+#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif /* MIN */
struct sockaddr_in *sin = sintab[which];
struct hostent *hp;
struct netent *np;
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
if (days) {
first = 0;
- p += sprintf(p, "%dd", days);
+ p += snprintf(p, sizeof(result) - (p - result), "%dd", days);
}
if (!first || hours) {
first = 0;
- p += sprintf(p, "%dh", hours);
+ p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
}
if (!first || mins) {
first = 0;
- p += sprintf(p, "%dm", mins);
+ p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
}
- sprintf(p, "%ds", secs);
+ snprintf(p, sizeof(result) - (p - result), "%ds", secs);
} else
- sprintf(result, "%lu", (unsigned long)total);
+ snprintf(result, sizeof(result), "%lu", (unsigned long)total);
return(result);
}
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
char *temp;
struct sockaddr_dl sdl;
struct sockaddr *sa = &link_ridreq.ifr_addr;
+ size_t slen = strlen(addr);
if (which != ADDR)
errx(1, "can't set link-level netmask or broadcast");
- if ((temp = malloc(strlen(addr) + 2)) == NULL)
+ if ((temp = malloc(slen + 2)) == NULL)
errx(1, "malloc failed");
temp[0] = ':';
- strcpy(temp + 1, addr);
+ strlcpy(temp + 1, addr, slen + 1);
sdl.sdl_len = sizeof(sdl);
link_addr(temp, &sdl);
free(temp);
That is, one can specify an address like
.Li 192.168.0.1/16 .
.Pp
-For
+For the
.Dq inet6
family, it is also possible to specify the prefix length using the slash
notation, like
the system will not attempt to
transmit messages through that interface.
If possible, the interface will be reset to disable reception as well.
-This action does not automatically disable routes using the interface.
.It Cm ether
Another name for the
.Cm lladdr
.Ar type .
Some interfaces support the mutually exclusive use of one of several
different physical media connectors.
-For example, a 10Mb/s Ethernet
+For example, a 10Mbit/s Ethernet
interface might support the use of either
.Tn AUI
or twisted pair connectors.
Setting the media type to
-.Dq 10base5/AUI
+.Cm 10base5/AUI
would change the currently active connector to the AUI port.
Setting it to
-.Dq 10baseT/UTP
+.Cm 10baseT/UTP
would activate twisted pair.
Refer to the interfaces' driver
specific documentation or man page for a complete list of the
.It Fl mediaopt Ar opts
If the driver supports the media selection system, disable the
specified media options on the interface.
+.It Cm rxcsum , txcsum
+If the driver supports user-configurable checksum offloading,
+enable receive (or transmit) checksum offloading on the interface.
+Some drivers may not be able to enable these flags independently
+of each other, so setting one may also set the other.
+The driver will offload as much checksum work as it can reliably
+support, the exact level of offloading varies between drivers.
+.It Fl rxcsum , txcsum
+If the driver supports user-configurable checksum offloading,
+disable receive (or transmit) checksum offloading on the interface.
+These settings may not always be independent of each other.
+.It Cm tso
+If the driver supports
+.Xr tcp 4
+segmentation offloading, enable TSO on the interface.
+Some drivers may not be able to support TSO for
+.Xr ip 4
+and
+.Xr ip6 4
+packets, so they may enable only one of them.
+.It Fl tso
+If the driver supports
+.Xr tcp 4
+segmentation offloading, disable TSO on the interface.
+It will always disable TSO for
+.Xr ip 4
+and
+.Xr ip6 4 .
+.It Cm lro
+If the driver supports
+.Xr tcp 4
+large receive offloading, enable LRO on the interface.
+.It Fl lro
+If the driver supports
+.Xr tcp 4
+large receive offloading, disable LRO on the interface.
+.It Cm av
+If supported by the driver, enable 802.1 AVB on the interface.
+.It Fl av
+If supported by the driver, disable 802.1 AVB on the interface.
+.It Cm vlanmtu , vlanhwtag
+If the driver offers user-configurable VLAN support, enable
+reception of extended frames or tag processing in hardware,
+respectively.
+Note that this must be issued on a physical interface associated with
+.Xr vlan 4 ,
+not on a
+.Xr vlan 4
+interface itself.
+.It Fl vlanmtu , vlanhwtag
+If the driver offers user-configurable VLAN support, disable
+reception of extended frames or tag processing in hardware,
+respectively.
.It Cm create
Create the specified network pseudo-device.
If the interface is given without a unit number, try to create a new
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
Perror(vname);
}
-#ifndef __APPLE__
+#ifdef SIOCGIFCAP
void
setifcap(const char *vname, int value, int s, const struct afswtch *afp)
{
#define IFFBITS \
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
-"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25NEEDSGIANT"
+"\20MULTICAST"
#define IFCAPBITS \
-"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
-"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC"
+"\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \
+"\6TSO4\7TSO6\10LRO\11AV"
/*
* Print the status of the interface. If an address family was
#endif
putchar('\n');
-#ifndef __APPLE__
+#ifdef SIOCGIFCAP
if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
if (ifr.ifr_curcap != 0) {
printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
}
/* turn interface and unit into module name */
- strcpy(ifkind, "if_");
+ strlcpy(ifkind, "if_", sizeof(ifkind));
strlcpy(ifkind + MOD_PREFIX_LEN, ifname,
sizeof(ifkind) - MOD_PREFIX_LEN);
DEF_CMD("-arp", IFF_NOARP, setifflags),
DEF_CMD("debug", IFF_DEBUG, setifflags),
DEF_CMD("-debug", -IFF_DEBUG, setifflags),
-#ifdef notdef
+#ifdef IFF_PPROMISC
DEF_CMD("promisc", IFF_PPROMISC, setifflags),
DEF_CMD("-promisc", -IFF_PPROMISC, setifflags),
-#endif
+#endif /* IFF_PPROMISC */
DEF_CMD("add", IFF_UP, notealias),
DEF_CMD("alias", IFF_UP, notealias),
DEF_CMD("-alias", -IFF_UP, notealias),
DEF_CMD("-link1", -IFF_LINK1, setifflags),
DEF_CMD("link2", IFF_LINK2, setifflags),
DEF_CMD("-link2", -IFF_LINK2, setifflags),
-#ifdef notdef
+#ifdef IFF_MONITOR
DEF_CMD("monitor", IFF_MONITOR:, setifflags),
DEF_CMD("-monitor", -IFF_MONITOR, setifflags),
+#endif /* IFF_MONITOR */
+#ifdef IFF_STATICARP
DEF_CMD("staticarp", IFF_STATICARP, setifflags),
DEF_CMD("-staticarp", -IFF_STATICARP, setifflags),
+#endif /* IFF_STATICARP */
+#ifdef IFCAP_RXCSUM
DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap),
DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap),
+#endif /* IFCAP_RXCSUM */
+#ifdef IFCAP_TXCSUM
DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap),
DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap),
+#endif /* IFCAP_TXCSUM */
+#ifdef IFCAP_NETCONS
DEF_CMD("netcons", IFCAP_NETCONS, setifcap),
DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap),
+#endif /* IFCAP_NETCONS */
+#ifdef IFCAP_POLLING
DEF_CMD("polling", IFCAP_POLLING, setifcap),
DEF_CMD("-polling", -IFCAP_POLLING, setifcap),
+#endif /* IFCAP_POLLING */
+#ifdef IFCAP_TSO
DEF_CMD("tso", IFCAP_TSO, setifcap),
DEF_CMD("-tso", -IFCAP_TSO, setifcap),
+#endif /* IFCAP_TSO */
+#ifdef IFCAP_LRO
DEF_CMD("lro", IFCAP_LRO, setifcap),
DEF_CMD("-lro", -IFCAP_LRO, setifcap),
+#endif /* IFCAP_LRO */
+#ifdef IFCAP_WOL
DEF_CMD("wol", IFCAP_WOL, setifcap),
DEF_CMD("-wol", -IFCAP_WOL, setifcap),
+#endif /* IFCAP_WOL */
+#ifdef IFCAP_WOL_UCAST
DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap),
DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap),
+#endif /* IFCAP_WOL_UCAST */
+#ifdef IFCAP_WOL_MCAST
DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap),
DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap),
+#endif /* IFCAP_WOL_MCAST */
+#ifdef IFCAP_WOL_MAGIC
DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap),
DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap),
-#endif
+#endif /* IFCAP_WOL_MAGIC */
DEF_CMD("normal", -IFF_LINK0, setifflags),
DEF_CMD("compress", IFF_LINK0, setifflags),
DEF_CMD("noicmp", IFF_LINK1, setifflags),
DEF_CMD_ARG("mtu", setifmtu),
#ifdef notdef
DEF_CMD_ARG("name", setifname),
-#endif
+#endif /* notdef */
+#ifdef IFCAP_AV
+ DEF_CMD("av", IFCAP_AV, setifcap),
+ DEF_CMD("-av", -IFCAP_AV, setifcap),
+#endif /* IFCAP_AV */
};
static __constructor void
#ifdef notdef
static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
- IFM_SUBTYPE_IEEE80211_ALIASES;
+IFM_SUBTYPE_IEEE80211_ALIASES;
struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
DEF_CLONE_CMD_ARG("vlandev", setvlandev),
/* XXX For compatibility. Should become DEF_CMD() some day. */
DEF_CMD_OPTARG("-vlandev", unsetvlandev),
-#ifdef notdef
+#ifdef IFCAP_VLAN_MTU
DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap),
DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap),
+#endif /* IFCAP_VLAN_MTU */
+#ifdef IFCAP_VLAN_HWTAGGING
DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap),
DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap),
-#endif
+#endif /* IFCAP_VLAN_HWTAGGING */
};
static struct afswtch af_vlan = {
.af_name = "af_vlan",
--- /dev/null
+.\" $KAME: ip6addrctl.8,v 1.3 2003/03/22 05:56:41 jinmei Exp $
+.\"
+.\" Copyright (C) 2001 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$
+.\"
+.Dd September 25, 2001
+.Dt IP6ADDRCTL 8
+.Os
+.\"
+.Sh NAME
+.Nm ip6addrctl
+.Nd configure address selection policy for IPv6 and IPv4
+.\"
+.Sh SYNOPSIS
+.Nm
+.Op Cm show
+.Nm
+.Cm add
+.Ar prefix precedence label
+.Nm
+.Cm delete
+.Ar prefix
+.Nm
+.Cm flush
+.Nm
+.Cm install
+.Ar configfile
+.\"
+.Sh DESCRIPTION
+The
+.Nm
+utility manages the policy table of source and destination address
+selection for outgoing IPv4 and IPv6 packets.
+When
+.Nm
+is invoked without an argument or with a single argument
+.Cm show ,
+it prints the content of the policy table currently installed in the
+kernel.
+.Pp
+To modify the table, the following operations are available:
+.Bl -tag -width indent
+.It Cm add Ar prefix precedence label
+Add a policy entry.
+The
+.Ar prefix
+argument
+is an IPv6 prefix, which is a key for the entry.
+An IPv4 prefix should be specified with an IPv6 prefix using an
+IPv4-mapped IPv6 address.
+The
+.Ar precedence
+and
+.Ar label
+arguments
+are decimal numbers, which specify the precedence and label values
+for the entry, respectively.
+This operation should be performed without an existing entry for the
+prefix.
+.It Cm delete Ar prefix
+Delete a policy entry specified by
+.Ar prefix ,
+which should be an IPv6 prefix.
+A corresponding entry for the prefix should have already been
+installed.
+.It Cm flush
+Delete all existing policy entries in the kernel.
+.It Cm install Ar configfile
+Install policy entries from a configuration file named
+.Ar configfile .
+The configuration file should contain a set of policy entries.
+Each entry is specified in a single line which contains an IPv6 prefix,
+a decimal precedence value, and a decimal label value, separated with
+white space or tab characters.
+In the configuration file, lines beginning with the pound-sign
+.Pq Ql #
+are
+comments and are ignored.
+.El
+.\"
+.Sh EXIT STATUS
+.Ex -std
+.\"
+.Sh SEE ALSO
+.Rs
+.%A "Richard Draves"
+.%T "Default Address Selection for IPv6"
+.%N RFC 3484
+.Re
+.\"
+.Sh HISTORY
+The
+.Nm
+utility first appeared in the KAME IPv6 protocol stack kit.
+The original command name was
+.Nm addrselect ,
+but it was then renamed to the current one so that the name would
+describe its function well.
+.\" .Sh BUGS
+.\" (to be written)
--- /dev/null
+/* $KAME: ip6addrctl.c,v 1.3 2003/12/16 08:14:28 suz Exp $ */
+
+/*
+ * Copyright (C) 2001 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/socket.h>
+#include <sys/queue.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+
+#include <stdlib.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <err.h>
+
+static char *configfile;
+
+struct policyqueue {
+ TAILQ_ENTRY(policyqueue) pc_entry;
+ struct in6_addrpolicy pc_policy;
+};
+TAILQ_HEAD(policyhead, policyqueue);
+struct policyhead policyhead;
+
+static void usage __P((void));
+static void get_policy __P((void));
+static void dump_policy __P((void));
+static int mask2plen __P((struct sockaddr_in6 *));
+static int parse_prefix __P((const char *, struct in6_addrpolicy *));
+static void make_policy_fromfile __P((char *));
+static void plen2mask __P((struct sockaddr_in6 *, int));
+static void set_policy __P((void));
+static void add_policy __P((char *, char *, char *));
+static void delete_policy __P((char *));
+static void flush_policy __P(());
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ TAILQ_INIT(&policyhead);
+
+ if (argc == 1 || strcasecmp(argv[1], "show") == 0) {
+ get_policy();
+ dump_policy();
+ } else if (strcasecmp(argv[1], "add") == 0) {
+ if (argc < 5)
+ usage();
+ add_policy(argv[2], argv[3], argv[4]);
+ } else if (strcasecmp(argv[1], "delete") == 0) {
+ if (argc < 3)
+ usage();
+ delete_policy(argv[2]);
+ } else if (strcasecmp(argv[1], "flush") == 0) {
+ get_policy();
+ flush_policy();
+ } else if (strcasecmp(argv[1], "install") == 0) {
+ if (argc < 3)
+ usage();
+ configfile = argv[2];
+ make_policy_fromfile(configfile);
+ set_policy();
+ } else
+ usage();
+
+ exit(0);
+}
+
+static void
+get_policy()
+{
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
+ size_t l;
+ char *buf;
+ struct in6_addrpolicy *pol, *ep;
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) {
+ err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
+ /* NOTREACHED */
+ }
+ if (l == 0) {
+ printf("no source-address-selection policy is installed\n");
+ return;
+ }
+ if ((buf = malloc(l)) == NULL) {
+ errx(1, "malloc failed");
+ /* NOTREACHED */
+ }
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
+ /* NOTREACHED */
+ }
+
+ ep = (struct in6_addrpolicy *)(buf + l);
+ for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
+ struct policyqueue *new;
+
+ if ((new = malloc(sizeof(*new))) == NULL)
+ errx(1, "malloc failed\n");
+ new->pc_policy = *pol;
+ TAILQ_INSERT_TAIL(&policyhead, new, pc_entry);
+ }
+
+ free(buf);
+}
+
+static void
+dump_policy()
+{
+ size_t addrlen;
+ char addrbuf[NI_MAXHOST];
+ struct in6_addrpolicy *pol;
+ struct policyqueue *ent;
+ int plen, first = 1;
+
+ for (ent = TAILQ_FIRST(&policyhead); ent;
+ ent = TAILQ_NEXT(ent, pc_entry)) {
+ pol = &ent->pc_policy;
+ if (first) {
+ printf("%-30s %5s %5s %8s\n",
+ "Prefix", "Prec", "Label", "Use");
+ first = 0;
+ }
+
+ if ((getnameinfo((struct sockaddr *)&pol->addr,
+ sizeof(pol->addr), addrbuf, sizeof(addrbuf),
+ NULL, 0, NI_NUMERICHOST))) {
+ warnx("getnameinfo for prefix address failed");
+ continue;
+ }
+ if ((plen = mask2plen(&pol->addrmask)) < 0) {
+ warnx("invalid address mask");
+ continue;
+ }
+ addrlen = strlen(addrbuf);
+ if (addrlen + sizeof("/128") < sizeof(addrbuf)) {
+ snprintf(&addrbuf[addrlen],
+ sizeof(addrbuf) - addrlen - 1,
+ "/%d", plen);
+ printf("%-30s", addrbuf);
+ } else /* XXX */
+ printf("%s/%d", addrbuf, plen);
+ printf(" %5d %5d %8llu\n", pol->preced, pol->label,
+ (unsigned long long)pol->use);
+ }
+}
+
+#define SKIP_WHITE(p, emptyok) \
+ do { \
+ while((*(p) == ' ' || *(p) == '\t')) \
+ (p)++; \
+ if ((*(p) == '\0' || (*(p) == '\n')) && !(emptyok)) \
+ goto bad; \
+ } while (0);
+#define SKIP_WORD(p) \
+ do { \
+ while(*(p) != ' ' && *(p) != '\t') \
+ (p)++; \
+ if (*(p) == '\0' || *(p) == '\n') \
+ goto bad; \
+ } while (0);
+
+static void
+make_policy_fromfile(conf)
+ char *conf;
+{
+ char line[_POSIX2_LINE_MAX], *cp;
+ char *addrstr;
+ FILE *fp;
+ int count = 0;
+ struct in6_addrpolicy pol0;
+ struct policyqueue *new;
+
+ if ((fp = fopen(conf, "r")) == NULL)
+ err(1, "fopen: %s", conf);
+
+ while(fgets(line, sizeof(line), fp)) {
+ count++;
+ cp = line;
+
+ memset(&pol0, 0, sizeof(pol0));
+
+ /* get prefix */
+ SKIP_WHITE(cp, 1);
+ if (*cp == '\n') /* empty line */
+ continue;
+ if (*cp == '#')
+ continue;
+ addrstr = cp;
+ if (parse_prefix((const char *)addrstr, &pol0))
+ goto bad;
+
+ /* get precedence value */
+ SKIP_WORD(cp);
+ SKIP_WHITE(cp, 0);
+ pol0.preced = atoi(cp);
+
+ /* get label */
+ SKIP_WORD(cp);
+ SKIP_WHITE(cp, 0);
+ pol0.label = atoi(cp);
+
+ /* parse succeeded. make a control buffer entry. */
+ if ((new = malloc(sizeof(*new))) == NULL)
+ errx(1, "malloc failed\n");
+ memset(new, 0, sizeof(*new));
+ new->pc_policy = pol0;
+ TAILQ_INSERT_TAIL(&policyhead, new, pc_entry);
+ }
+
+ fclose(fp);
+ return;
+
+ bad:
+ errx(1, "parse failed at line %d", count);
+ /* NOTREACHED */
+}
+
+static int
+parse_prefix(prefix0, pol)
+ const char *prefix0;
+ struct in6_addrpolicy *pol;
+{
+ int e = 0, plen;
+ char *prefix, *plenstr;
+ struct addrinfo hints, *res;
+
+ if ((prefix = strdup(prefix0)) == NULL)
+ errx(1, "strdup failed");
+
+ if ((plenstr = strchr(prefix, '/')) == NULL) {
+ e = -1;
+ goto end;
+ }
+ *plenstr = '\0';
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF_INET6;
+
+ if ((e = getaddrinfo(prefix, NULL, &hints, &res)) != 0) {
+ warnx("getaddrinfo failed for %s: %s", prefix,
+ gai_strerror(e));
+ goto end;
+ }
+ memcpy(&pol->addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ plen = atoi(plenstr + 1);
+ if (plen < 0 || plen > 128) {
+ warnx("invalid prefix length: %d", plen);
+ e = -1;
+ goto end;
+ }
+ plen2mask(&pol->addrmask, plen);
+
+ end:
+ free(prefix);
+ return(e);
+}
+
+static void
+plen2mask(mask, plen)
+ struct sockaddr_in6 *mask;
+ int plen;
+{
+ u_char *cp = (unsigned char *)&mask->sin6_addr;
+
+ memset(mask, 0, sizeof(*mask));
+ mask->sin6_family = AF_INET6; /* just in case */
+ mask->sin6_len = sizeof(*mask);
+
+ for(; plen >= 8; plen -= 8)
+ *cp++ = 0xff;
+ if (plen > 0)
+ *cp = (0xff << (8 - plen));
+}
+
+static void
+set_policy()
+{
+ struct policyqueue *ent;
+ int s;
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+
+ for (ent = TAILQ_FIRST(&policyhead); ent;
+ ent = TAILQ_NEXT(ent, pc_entry)) {
+ if (ioctl(s, SIOCAADDRCTL_POLICY, &ent->pc_policy))
+ warn("ioctl(SIOCAADDRCTL_POLICY)");
+ }
+
+ close(s);
+}
+
+static int
+mask2plen(mask)
+ struct sockaddr_in6 *mask;
+{
+ int masklen, final = 0;
+ u_char *p, *lim;
+
+ masklen = 0;
+ lim = (u_char *)(mask + 1);
+ for (p = (u_char *)(&mask->sin6_addr); p < lim; p++) {
+ if (final && *p) {
+ goto bad;
+ }
+
+ switch (*p & 0xff) {
+ case 0xff:
+ masklen += 8;
+ break;
+ case 0xfe:
+ masklen += 7;
+ final++;
+ break;
+ case 0xfc:
+ masklen += 6;
+ final++;
+ break;
+ case 0xf8:
+ masklen += 5;
+ final++;
+ break;
+ case 0xf0:
+ masklen += 4;
+ final++;
+ break;
+ case 0xe0:
+ masklen += 3;
+ final++;
+ break;
+ case 0xc0:
+ masklen += 2;
+ final++;
+ break;
+ case 0x80:
+ masklen += 1;
+ final++;
+ break;
+ case 0x00:
+ final++;
+ break;
+ default:
+ goto bad;
+ break;
+ }
+ }
+ return(masklen);
+
+ bad:
+ return(-1);
+}
+
+static void
+add_policy(prefix, prec, label)
+ char *prefix, *prec, *label;
+{
+ struct in6_addrpolicy p;
+ int s;
+
+ memset(&p, 0, sizeof(p));
+
+ if (parse_prefix((const char *)prefix, &p))
+ errx(1, "bad prefix: %s", prefix);
+ p.preced = atoi(prec);
+ p.label = atoi(label);
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+ if (ioctl(s, SIOCAADDRCTL_POLICY, &p))
+ err(1, "ioctl(SIOCAADDRCTL_POLICY)");
+
+ close(s);
+}
+
+static void
+delete_policy(prefix)
+ char *prefix;
+{
+ struct in6_addrpolicy p;
+ int s;
+
+ memset(&p, 0, sizeof(p));
+
+ if (parse_prefix((const char *)prefix, &p))
+ errx(1, "bad prefix: %s", prefix);
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+ if (ioctl(s, SIOCDADDRCTL_POLICY, &p))
+ err(1, "ioctl(SIOCDADDRCTL_POLICY)");
+
+ close(s);
+}
+
+static void
+flush_policy()
+{
+ struct policyqueue *ent;
+ int s;
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+
+ for (ent = TAILQ_FIRST(&policyhead); ent;
+ ent = TAILQ_NEXT(ent, pc_entry)) {
+ if (ioctl(s, SIOCDADDRCTL_POLICY, &ent->pc_policy))
+ warn("ioctl(SIOCDADDRCTL_POLICY)");
+ }
+
+ close(s);
+}
+
+static void
+usage()
+{
+ fprintf(stderr, "usage: ip6addrctl [show]\n");
+ fprintf(stderr, " ip6addrctl add "
+ "<prefix> <precedence> <label>\n");
+ fprintf(stderr, " ip6addrctl delete <prefix>\n");
+ fprintf(stderr, " ip6addrctl flush\n");
+ fprintf(stderr, " ip6addrctl install <configfile>\n");
+
+ exit(1);
+}
--- /dev/null
+# default policy table based on RFC 3484.
+# usage: ip6addrctl install path_to_this_file
+#
+# $FreeBSD$
+#
+#Format:
+#Prefix Precedence Label
+::1/128 50 0
+::/0 40 1
+2002::/16 30 2
+::/96 20 3
+::ffff:0:0/96 10 4
.Os
.Sh NAME
.Nm ip6fw
-.Nd controlling utility for IPv6 firewall
+.Nd controlling utility for IPv6 firewall (DEPRECATED)
.Sh SYNOPSIS
.Nm
.Op Fl q
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
* Copyright (c) 1994 Ugen J.S.Antsilevich
{
char timestr[30];
- strcpy(timestr, ctime((time_t *)&chain->timestamp));
+ strlcpy(timestr, ctime((time_t *)&chain->timestamp), sizeof(timestr));
*strchr(timestr, '\n') = '\0';
printf("%s ", timestr);
}
void
fill_icmptypes(types, vp, fw_flg)
- u_long *types;
+ unsigned *types;
char **vp;
u_short *fw_flg;
{
show_usage("ICMP6 type out of range");
types[icmptype / (sizeof(unsigned) * 8)] |=
- 1 << (icmptype % (sizeof(unsigned) * 8));
+ 1U << (icmptype % (sizeof(unsigned) * 8));
*fw_flg |= IPV6_FW_F_ICMPBIT;
}
}
show_usage("can't mix 'frag' and port specifications");
}
- if (!do_quiet)
- show_ip6fw(&rule);
i = setsockopt(s, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof rule);
if (i)
err(EX_UNAVAILABLE, "setsockopt(%s)", "IPV6_FW_ADD");
+ if (!do_quiet)
+ show_ip6fw(&rule);
}
static void
#define WHITESP " \t\f\v\n\r"
char buf[BUFSIZ];
char *a, *p, *args[MAX_ARGS], *cmd = NULL;
- char linename[10];
+ char linename[16];
int i, c, lineno, qflag, pflag, status;
FILE *f = NULL;
pid_t preproc = 0;
while (fgets(buf, BUFSIZ, f)) {
lineno++;
- sprintf(linename, "Line %d", lineno);
+ snprintf(linename, sizeof(linename), "Line %d", lineno);
args[0] = linename;
if (*buf == '#')
.Sh NAME
.Nm ipfw
.Nd IP firewall and traffic shaper control program
+(DEPRECATED)
.Sh SYNOPSIS
.Nm
.Op Fl cq
.Oc
.Ar pathname
.Sh DESCRIPTION
+Note that use of this utility is
+.Cm DEPRECATED.
+Please use
+.Xr pfctl 8
+instead.
+.Pp
The
.Nm
utility is the user interface for controlling the
.Xr ipfw 4
firewall and the
.Xr dummynet 4
-traffic shaper in
-.Fx .
+traffic shaper.
.Pp
An
.Nm
When logging is enabled, these packets are
reported as being dropped by rule -1.
.It
-If you are logged in over a network, loading the
-.Xr kld 4
-version of
-.Nm
-is probably not as straightforward as you would think.
-I recommend the following command line:
-.Bd -literal -offset indent
-kldload ipfw && \e
-ipfw add 32000 allow ip from any to any
-.Ed
-.Pp
-Along the same lines, doing an
-.Bd -literal -offset indent
-ipfw flush
-.Ed
-.Pp
-in similar surroundings is also a bad idea.
-.It
The
.Nm
filter list may not be modified if the system security level
-is set to 3 or higher
-(see
-.Xr init 8
-for information on system security levels).
+is set to 3 or higher.
.El
.Sh PACKET DIVERSION
A
.Sh SEE ALSO
.Xr cpp 1 ,
.Xr m4 1 ,
-.Xr bridge 4 ,
.Xr divert 4 ,
.Xr dummynet 4 ,
.Xr ip 4 ,
.Xr ipfirewall 4 ,
.Xr protocols 5 ,
.Xr services 5 ,
-.Xr init 8 ,
-.Xr kldload 8 ,
.Xr reboot 8 ,
.Xr sysctl 8 ,
.Xr syslogd 8
/*
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2009 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
+
/*
* Copyright (c) 2002-2003 Luigi Rizzo
* Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
} else if (*s == ',' || *s == '\0' )
p[0] = p[1] = a;
else /* invalid separator */
- errx(EX_DATAERR, "invalid separator <%c> in <%s>\n",
+ errx(EX_DATAERR, "invalid separator <%c> in <%s>",
*s, av);
i++;
p += 2;
}
if (i > 0) {
if (i+1 > F_LEN_MASK)
- errx(EX_DATAERR, "too many ports/ranges\n");
+ errx(EX_DATAERR, "too many ports/ranges");
cmd->o.len |= i+1; /* leave F_NOT and F_OR untouched */
}
return i;
time_t t = (time_t)0;
if (twidth == 0) {
- strcpy(timestr, ctime(&t));
+ strlcpy(timestr, ctime(&t), sizeof(timestr));
*strchr(timestr, '\n') = '\0';
twidth = strlen(timestr);
}
#endif
t = _long_to_time(rule->timestamp);
- strcpy(timestr, ctime(&t));
+ strlcpy(timestr, ctime(&t), sizeof(timestr));
*strchr(timestr, '\n') = '\0';
printf("%s ", timestr);
} else {
l = fs->qsize;
if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
if (l >= 8192)
- sprintf(qs, "%d KB", l / 1024);
+ snprintf(qs, sizeof(qs), "%d KB", l / 1024);
else
- sprintf(qs, "%d B", l);
+ snprintf(qs, sizeof(qs), "%d B", l);
} else
- sprintf(qs, "%3d sl.", l);
+ snprintf(qs, sizeof(qs), "%3d sl.", l);
if (fs->plr)
- sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
+ snprintf(plr, sizeof(plr), "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
else
plr[0] = '\0';
if (fs->flags_fs & DN_IS_RED) /* RED parameters */
- sprintf(red,
+ snprintf(red, sizeof(red),
"\n\t %cRED w_q %f min_th %d max_th %d max_p %f",
(fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
1.0 * fs->w_q / (double)(1 << SCALE_RED),
SCALE_VAL(fs->max_th),
1.0 * fs->max_p / (double)(1 << SCALE_RED));
else
- sprintf(red, "droptail");
+ snprintf(red, sizeof(red), "droptail");
printf("%s %s%s %d queues (%d buckets) %s\n",
prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
* Print rate (or clocking interface)
*/
if (p->if_name[0] != '\0')
- sprintf(buf, "%s", p->if_name);
+ snprintf(buf, sizeof(buf), "%s", p->if_name);
else if (b == 0)
- sprintf(buf, "unlimited");
+ snprintf(buf, sizeof(buf), "unlimited");
else if (b >= 1000000)
- sprintf(buf, "%7.3f Mbit/s", b/1000000);
+ snprintf(buf, sizeof(buf), "%7.3f Mbit/s", b/1000000);
else if (b >= 1000)
- sprintf(buf, "%7.3f Kbit/s", b/1000);
+ snprintf(buf, sizeof(buf), "%7.3f Kbit/s", b/1000);
else
- sprintf(buf, "%7.3f bit/s ", b);
+ snprintf(buf, sizeof(buf), "%7.3f bit/s ", b);
- sprintf(prefix, "%05d: %s %4d ms ",
+ snprintf(prefix, sizeof(prefix), "%05d: %s %4d ms ",
p->pipe_nr, buf, p->delay);
print_flowset_parms(&(p->fs), prefix);
if (verbose)
next = (char *)fs + l;
nbytes -= l;
q = (struct dn_flow_queue *)(fs+1);
- sprintf(prefix, "q%05d: weight %d pipe %d ",
+ snprintf(prefix, sizeof(prefix), "q%05d: weight %d pipe %d ",
fs->fs_nr, fs->weight, fs->parent_nr);
print_flowset_parms(fs, prefix);
list_queues(fs, q);
struct ip_fw rule;
ac--; av++;
if (ac != 2)
- errx(EX_USAGE, "set swap needs 2 set numbers\n");
+ errx(EX_USAGE, "set swap needs 2 set numbers");
rulenum = atoi(av[0]);
new_set = atoi(av[1]);
if (!isdigit(*(av[0])) || rulenum > RESVD_SET)
- errx(EX_DATAERR, "invalid set number %s\n", av[0]);
+ errx(EX_DATAERR, "invalid set number %s", av[0]);
if (!isdigit(*(av[1])) || new_set > RESVD_SET)
- errx(EX_DATAERR, "invalid set number %s\n", av[1]);
+ errx(EX_DATAERR, "invalid set number %s", av[1]);
masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
bzero(&rule, sizeof(rule));
} else
cmd = 3;
if (ac != 3 || strncmp(av[1], "to", strlen(*av)))
- errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
+ errx(EX_USAGE, "syntax: set move [rule] X to Y");
rulenum = atoi(av[0]);
new_set = atoi(av[2]);
if (!isdigit(*(av[0])) || (cmd == 3 && rulenum > RESVD_SET) ||
(cmd == 2 && rulenum == 65535) )
- errx(EX_DATAERR, "invalid source number %s\n", av[0]);
+ errx(EX_DATAERR, "invalid source number %s", av[0]);
if (!isdigit(*(av[2])) || new_set > RESVD_SET)
- errx(EX_DATAERR, "invalid dest. set %s\n", av[1]);
+ errx(EX_DATAERR, "invalid dest. set %s", av[1]);
masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
bzero(&rule, sizeof(rule));
i = atoi(*av);
if (i < 0 || i > RESVD_SET)
errx(EX_DATAERR,
- "invalid set number %d\n", i);
+ "invalid set number %d", i);
masks[which] |= (1<<i);
} else if (!strncmp(*av, "disable", strlen(*av)))
which = 0;
which = 1;
else
errx(EX_DATAERR,
- "invalid set command %s\n", *av);
+ "invalid set command %s", *av);
av++; ac--;
}
if ( (masks[0] & masks[1]) != 0 )
errx(EX_DATAERR,
- "cannot enable and disable the same set\n");
+ "cannot enable and disable the same set");
bzero(&rule, sizeof(rule));
rule.set_masks[0] = masks[0];
if (i)
warn("set enable/disable: setsockopt(IP_FW_DEL)");
} else
- errx(EX_USAGE, "invalid set command %s\n", *av);
+ errx(EX_USAGE, "invalid set command %s", *av);
}
static void
av++;
if (ac == 0) {
- warnx("missing keyword to enable/disable\n");
+ warnx("missing keyword to enable/disable");
} else if (strncmp(*av, "firewall", strlen(*av)) == 0) {
sysctlbyname("net.inet.ip.fw.enable", NULL, 0,
&which, sizeof(which));
sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0,
&which, sizeof(which));
} else {
- warnx("unrecognize enable/disable keyword: %s\n", *av);
+ warnx("unrecognize enable/disable keyword: %s", *av);
}
}
if (len > 0)
errx(EX_DATAERR, "address set cannot be in a list");
if (i < 24 || i > 31)
- errx(EX_DATAERR, "invalid set with mask %d\n", i);
+ errx(EX_DATAERR, "invalid set with mask %d", i);
cmd->o.arg1 = 1<<(32-i); /* map length */
d[0] = ntohl(d[0]); /* base addr in host format */
cmd->o.opcode = O_IP_DST_SET; /* default */
if (s == av) { /* no parameter */
if (*av != '}')
- errx(EX_DATAERR, "set not closed\n");
+ errx(EX_DATAERR, "set not closed");
if (i != -1)
errx(EX_DATAERR, "incomplete range %d-", i);
break;
}
if (a < low || a > high)
- errx(EX_DATAERR, "addr %d out of range [%d-%d]\n",
+ errx(EX_DATAERR, "addr %d out of range [%d-%d]",
a, low, high);
a -= low;
if (i == -1) /* no previous in range */
l = 1 + (l+3)/4;
cmd->len = (cmd->len & (F_NOT | F_OR)) | l;
for (i = 0; i < ac; i++) {
- strcpy(p, av[i]);
+ /* length being checked above (max 80 chars) */
+ strlcpy(p, av[i], 80);
p += strlen(av[i]);
*p++ = ' ';
}
break;
default:
- errx(EX_DATAERR, "invalid action %s\n", av[-1]);
+ errx(EX_DATAERR, "invalid action %s", av[-1]);
}
action = next_cmd(action);
#define OR_START(target) \
if (ac && (*av[0] == '(' || *av[0] == '{')) { \
if (open_par) \
- errx(EX_USAGE, "nested \"(\" not allowed\n"); \
+ errx(EX_USAGE, "nested \"(\" not allowed"); \
prev = NULL; \
open_par = 1; \
if ( (av[0])[1] == '\0') { \
open_par = 0; \
ac--; av++; \
} else \
- errx(EX_USAGE, "missing \")\"\n"); \
+ errx(EX_USAGE, "missing \")\""); \
}
#define NOT_BLOCK \
if (ac && !strncmp(*av, "not", strlen(*av))) { \
if (cmd->len & F_NOT) \
- errx(EX_USAGE, "double \"not\" not allowed\n"); \
+ errx(EX_USAGE, "double \"not\" not allowed"); \
cmd->len |= F_NOT; \
ac--; av++; \
}
if (*s == '!') { /* alternate syntax for NOT */
if (cmd->len & F_NOT)
- errx(EX_USAGE, "double \"not\" not allowed\n");
+ errx(EX_USAGE, "double \"not\" not allowed");
cmd->len = F_NOT;
s++;
}
switch(i) {
case TOK_NOT:
if (cmd->len & F_NOT)
- errx(EX_USAGE, "double \"not\" not allowed\n");
+ errx(EX_USAGE, "double \"not\" not allowed");
cmd->len = F_NOT;
break;
case TOK_OR:
if (open_par == 0 || prev == NULL)
- errx(EX_USAGE, "invalid \"or\" block\n");
+ errx(EX_USAGE, "invalid \"or\" block");
prev->len |= F_OR;
break;
case TOK_STARTBRACE:
if (open_par)
- errx(EX_USAGE, "+nested \"(\" not allowed\n");
+ errx(EX_USAGE, "+nested \"(\" not allowed");
open_par = 1;
break;
case TOK_ENDBRACE:
if (!open_par)
- errx(EX_USAGE, "+missing \")\"\n");
+ errx(EX_USAGE, "+missing \")\"");
open_par = 0;
prev = NULL;
break;
break;
default:
- errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
+ errx(EX_USAGE, "unrecognised option [%d] %s", i, s);
}
if (F_LEN(cmd) > 0) { /* prepare to advance */
prev = cmd;
} else {
/*
* If an argument ends with ',' join with the next one.
+ * Just add its length to 'l' and continue. When we have a string
+ * without a ',' ending, we'll have the combined length in 'l'
*/
int first, i, l;
for (first = i = ac = 0, l = 0; i < oldac; i++) {
char *arg = oldav[i];
int k = strlen(arg);
-
+
l += k;
if (arg[k-1] != ',' || i == oldac-1) {
+ int buflen = l+1;
/* Time to copy. */
av[ac] = calloc(l+1, 1);
for (l=0; first <= i; first++) {
- strcat(av[ac]+l, oldav[first]);
+ strlcat(av[ac]+l, oldav[first], buflen-l);
l += strlen(oldav[first]);
}
ac++;
}
while (fgets(buf, BUFSIZ, f)) { /* read commands */
- char linename[10];
+ char linename[16];
char *args[1];
lineno++;
- sprintf(linename, "Line %d", lineno);
+ snprintf(linename, sizeof(linename), "Line %d", lineno);
setprogname(linename); /* XXX */
args[0] = buf;
ipfw_main(1, args);
return;
}
+/* update if needed, when adding new errmsgs */
+#define MAXERRMSGLEN 40
+
struct errmsg {
int e_code;
char *e_msg;
pe->e_msg = strerror(error - 100);
tp->th_code = EUNDEF; /* set 'undef' errorcode */
}
- strcpy(tp->th_msg, pe->e_msg);
+ if (strlen(pe->e_msg) > MAXERRMSGLEN) {
+ syslog(LOG_ERR, "nak: error msg too long");
+ return;
+ }
+
+ strlcpy(tp->th_msg, pe->e_msg, MAXERRMSGLEN);
length = strlen(pe->e_msg);
tp->th_msg[length] = '\0';
length += 5;
if (send(peer, buf, length, 0) != length)
syslog(LOG_ERR, "nak: %m");
+
+ return;
}
static char *
--- /dev/null
+Copyright (c) 2007-2009 Bruce Simpson.
+Copyright (c) 2000 Wilbert De Graaf.
+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.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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
+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.
\ No newline at end of file
--- /dev/null
+.\"
+.\" Copyright (c) 2007-2009 Bruce Simpson.
+.\" 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. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: src/usr.sbin/mtest/mtest.8,v 1.11 2009/04/29 09:50:04 bms Exp $
+.\"
+.Dd April 29, 2009
+.Os
+.Dt MTEST 8
+.Sh NAME
+.Nm mtest
+.Nd test multicast socket operations
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility
+is a small program for testing multicast socket operations.
+.Pp
+It accepts the following commands, interactively, or as part of a scripted
+input file (useful for automated testing):
+.Bl -tag -width "a ifname e.e.e.e e.e.e.e" -compact -offset indent
+.Pp
+.\"
+.It Ic a Ar ifname Ar mac-addr
+Join the link-layer group address
+.Ar mac-addr
+on interface
+.Ar ifname .
+The group address should be in IEEE 802 MAC format,
+delimited by colon (':') characters.
+.It Ic d Ar ifname Ar mac-addr
+Leave the link-layer group address
+.Ar mac-addr
+on interface
+.Ar ifname .
+.It Ic m Ar ifname Ar 1/0
+Set or reset ALLMULTI mode on interface
+.Ar ifname .
+This option is deprecated and is now a no-op.
+.\".It Ic p Ar ifname Ar 1/0
+.\"Set or reset promiscuous mode on interface
+.\".Ar ifname .
+.Pp
+.It Ic j Ar mcast-addr Ar ifname Op Ar source-addr
+Join the multicast address
+.Ar mcast-addr
+on the interface with name
+.Ar ifname .
+.Pp
+If an optional source
+.Ar source-addr
+is specified, a source-specific join will be performed;
+if
+.Nm
+is already joined to the multicast address, the source
+will be added to its filter list.
+.Pp
+.It Ic l Ar mcast-addr Ar ifname Op Ar source-addr
+Leave the multicast address
+.Ar mcast-addr
+on the interface with address
+.Ar ifname .
+If a source
+.Ar source-addr
+is specified, only that source will be left.
+.\"
+.It Ic i Ar mcast-addr Ar ifname Ar n Ar source-addr ...
+Set the socket with membership of
+.Ar mcast-addr
+on interface
+.Ar ifname
+to include filter mode, and add
+.Ar n
+sources beginning with
+.Ar source-addr
+to the inclusion filter list.
+.\"
+.It Ic e Ar mcast-addr Ar ifname Ar n Ar source-addr ...
+Set the socket with membership of
+.Ar mcast-addr
+on interface
+.Ar ifname
+to exclude filter mode, and add
+.Ar n
+sources beginning with
+.Ar source-addr
+to the exclusion filter list.
+.\"
+.It Ic t Ar mcast-addr Ar ifname Ar source-addr
+Set the socket with membership of
+.Ar mcast-addr
+on interface
+.Ar ifname
+to block traffic from source
+.Ar source-addr .
+.\"
+.It Ic b Ar mcast-addr Ar ifname Ar source-addr
+Set the socket with membership of
+.Ar mcast-addr
+on interface
+.Ar ifname
+to allow traffic from source
+.Ar source-addr .
+.\"
+.Pp
+.It Ic g Ar mcast-addr Ar ifname Ar n
+Print
+.Ar n
+source filter entries for
+.An mcast-addr
+on interface
+.An ifname .
+.\"
+.Pp
+.It Ic f Ar filename
+Read commands from the file
+.Ar filename .
+.It Ic s Ar n
+Sleep for
+.Ar n
+seconds.
+.It Ic ?\&
+List legal commands.
+.It Ic q
+Quit the program.
+.El
+.Sh IMPLEMENTATION NOTES
+For each command implemented by
+.Nm ,
+the address family of each argument must be identical; it is not possible
+to mix IPv4 multicast memberships with IPv6, for example.
+.Pp
+To support IPv6, all commands have now changed to accept an interface
+name rather than an interface address.
+For IPv4, the program will perform
+a lookup of the primary IP address based on the interface name.
+This may fail if no primary IP address is assigned.
+.Pp
+.Sh SEE ALSO
+.Rs
+.%A D. Thaler
+.%A B. Fenner
+.%A B. Quinn
+.%T "Socket Interface Extensions for Multicast Filters"
+.%O RFC 3678
+.Re
+.Sh AUTHORS
+.An -split
+.An "Bruce Simpson"
+.An "Steve Deering"
+.An "Wilbert De Graaf"
--- /dev/null
+/*-
+ * Copyright (c) 2007-2009 Bruce Simpson.
+ * Copyright (c) 2000 Wilbert De Graaf.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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
+ * 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.
+ */
+
+/*
+ * Diagnostic and test utility for multicast sockets.
+ * TODO: Support embedded KAME Scope ID in IPv6 group addresses.
+ * TODO: Use IPv4 link-local address when source address selection
+ * is implemented; use MCAST_JOIN_SOURCE for IPv4.
+ */
+
+#define INET6
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#ifdef INET6
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <err.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+
+#ifdef IP_ADD_SOURCE_MEMBERSHIP
+#define HAS_SSM 1
+#endif
+
+union sockunion {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_dl sdl;
+ struct sockaddr_in sin;
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+};
+typedef union sockunion sockunion_t;
+
+union mrequnion {
+ struct ip_mreq mr;
+#ifdef HAS_SSM
+ struct ip_mreq_source mrs;
+#endif
+#ifdef INET6
+ struct ipv6_mreq mr6;
+#ifdef HAS_SSM
+ struct group_source_req gr;
+#endif
+#endif
+};
+typedef union mrequnion mrequnion_t;
+
+#define MAX_ADDRS 20
+#define STR_SIZE 64
+#define LINE_LENGTH 80
+
+static int __ifindex_to_primary_ip(const uint32_t, struct in_addr *);
+static uint32_t parse_cmd_args(sockunion_t *, sockunion_t *,
+ const char *, const char *, const char *);
+static void process_file(char *, int, int);
+static void process_cmd(char*, int, int, FILE *);
+static int su_cmp(const void *, const void *);
+static void usage(void);
+
+/*
+ * Ordering predicate for qsort().
+ */
+static int
+su_cmp(const void *a, const void *b)
+{
+ const sockunion_t *sua = (const sockunion_t *)a;
+ const sockunion_t *sub = (const sockunion_t *)b;
+
+ assert(sua->sa.sa_family == sub->sa.sa_family);
+
+ switch (sua->sa.sa_family) {
+ case AF_INET:
+ return ((int)(sua->sin.sin_addr.s_addr -
+ sub->sin.sin_addr.s_addr));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ return (memcmp(&sua->sin6.sin6_addr, &sub->sin6.sin6_addr,
+ sizeof(struct in6_addr)));
+ break;
+#endif
+ default:
+ break;
+ }
+
+ assert(sua->sa.sa_len == sub->sa.sa_len);
+ return (memcmp(sua, sub, sua->sa.sa_len));
+}
+
+/*
+ * Internal: Map an interface index to primary IPv4 address.
+ * This is somewhat inefficient. This is a useful enough operation
+ * that it probably belongs in the C library.
+ * Return zero if found, -1 on error, 1 on not found.
+ */
+static int
+__ifindex_to_primary_ip(const uint32_t ifindex, struct in_addr *pina)
+{
+ char ifname[IFNAMSIZ];
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifaddrs;
+ sockunion_t *psu;
+ int retval;
+
+ assert(ifindex != 0);
+
+ retval = -1;
+ if (if_indextoname(ifindex, ifname) == NULL)
+ return (retval);
+ if (getifaddrs(&ifaddrs) < 0)
+ return (retval);
+
+ /*
+ * Find the ifaddr entry corresponding to the interface name,
+ * and return the first matching IPv4 address.
+ */
+ retval = 1;
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (strcmp(ifa->ifa_name, ifname) != 0)
+ continue;
+ psu = (sockunion_t *)ifa->ifa_addr;
+ if (psu && psu->sa.sa_family == AF_INET) {
+ retval = 0;
+ memcpy(pina, &psu->sin.sin_addr,
+ sizeof(struct in_addr));
+ break;
+ }
+ }
+
+ if (retval != 0)
+ errno = EADDRNOTAVAIL; /* XXX */
+
+ freeifaddrs(ifaddrs);
+ return (retval);
+}
+
+int
+main(int argc, char **argv)
+{
+ char line[LINE_LENGTH];
+ char *p;
+ int i, s, s6;
+
+ s = -1;
+ s6 = -1;
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == -1)
+ err(1, "can't open IPv4 socket");
+#ifdef INET6
+ s6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s6 == -1)
+ err(1, "can't open IPv6 socket");
+#endif
+
+ if (argc < 2) {
+ if (isatty(STDIN_FILENO)) {
+ printf("multicast membership test program; "
+ "enter ? for list of commands\n");
+ }
+ do {
+ if (fgets(line, sizeof(line), stdin) != NULL) {
+ if (line[0] != 'f')
+ process_cmd(line, s, s6, stdin);
+ else {
+ /* Get the filename */
+ for (i = 1; isblank(line[i]); i++);
+ if ((p = (char*)strchr(line, '\n'))
+ != NULL)
+ *p = '\0';
+ process_file(&line[i], s, s6);
+ }
+ }
+ } while (!feof(stdin));
+ } else {
+ for (i = 1; i < argc; i++) {
+ process_file(argv[i], s, s6);
+ }
+ }
+
+ if (s != -1)
+ close(s);
+ if (s6 != -1)
+ close(s6);
+
+ exit (0);
+}
+
+static void
+process_file(char *fname, int s, int s6)
+{
+ char line[80];
+ FILE *fp;
+ char *lineptr;
+
+ fp = fopen(fname, "r");
+ if (fp == NULL) {
+ warn("fopen");
+ return;
+ }
+
+ /* Skip comments and empty lines. */
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ lineptr = line;
+ while (isblank(*lineptr))
+ lineptr++;
+ if (*lineptr != '#' && *lineptr != '\n')
+ process_cmd(lineptr, s, s6, fp);
+ }
+
+ fclose(fp);
+}
+
+/*
+ * Parse join/leave/allow/block arguments, given:
+ * str1: group (as AF_INET or AF_INET6 printable)
+ * str2: ifname
+ * str3: optional source address (may be NULL).
+ * This argument must have the same parsed address family as str1.
+ * Return the ifindex of ifname, or 0 if any parse element failed.
+ */
+static uint32_t
+parse_cmd_args(sockunion_t *psu, sockunion_t *psu2,
+ const char *str1, const char *str2, const char *str3)
+{
+ struct addrinfo hints;
+ struct addrinfo *res;
+ uint32_t ifindex;
+ int af, error;
+
+ assert(psu != NULL);
+ assert(str1 != NULL);
+ assert(str2 != NULL);
+
+ af = AF_UNSPEC;
+
+ ifindex = if_nametoindex(str2);
+ if (ifindex == 0)
+ return (0);
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ memset(psu, 0, sizeof(sockunion_t));
+ psu->sa.sa_family = AF_UNSPEC;
+
+ error = getaddrinfo(str1, "0", &hints, &res);
+ if (error) {
+ warnx("getaddrinfo: %s", gai_strerror(error));
+ return (0);
+ }
+ assert(res != NULL);
+ af = res->ai_family;
+ memcpy(psu, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+
+ /* sscanf() may pass the empty string. */
+ if (psu2 != NULL && str3 != NULL && *str3 != '\0') {
+ memset(psu2, 0, sizeof(sockunion_t));
+ psu2->sa.sa_family = AF_UNSPEC;
+
+ /* look for following address family; str3 is *optional*. */
+ hints.ai_family = af;
+ error = getaddrinfo(str3, "0", &hints, &res);
+ if (error) {
+ warnx("getaddrinfo: %s", gai_strerror(error));
+ ifindex = 0;
+ } else {
+ if (af != res->ai_family) {
+ errno = EINVAL; /* XXX */
+ ifindex = 0;
+ }
+ memcpy(psu2, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ }
+ }
+
+ return (ifindex);
+}
+
+static __inline int
+af2sock(const int af, int s, int s6)
+{
+
+ if (af == AF_INET)
+ return (s);
+#ifdef INET6
+ if (af == AF_INET6)
+ return (s6);
+#endif
+ return (-1);
+}
+
+static __inline int
+af2socklen(const int af)
+{
+
+ if (af == AF_INET)
+ return (sizeof(struct sockaddr_in));
+#ifdef INET6
+ if (af == AF_INET6)
+ return (sizeof(struct sockaddr_in6));
+#endif
+ return (-1);
+}
+
+static void
+process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused)
+{
+ char str1[STR_SIZE];
+ char str2[STR_SIZE];
+ char str3[STR_SIZE];
+ mrequnion_t mr;
+ sockunion_t su, su2;
+ struct ifreq ifr;
+ char *line;
+ char *toptname;
+ void *optval;
+ uint32_t fmode, ifindex;
+ socklen_t optlen;
+ int af, error, i, level, n, optname;
+#ifndef __APPLE__
+ int f, flags;
+#endif /* __APPLE__ */
+
+ af = AF_UNSPEC;
+ su.sa.sa_family = AF_UNSPEC;
+ su2.sa.sa_family = AF_UNSPEC;
+
+ line = cmd;
+ while (isblank(*++line))
+ ; /* Skip whitespace. */
+
+ switch (*cmd) {
+ case '?':
+ usage();
+ break;
+
+ case 'q':
+ close(s);
+ exit(0);
+
+ case 's':
+ if ((sscanf(line, "%d", &n) != 1) || (n < 1)) {
+ printf("-1\n");
+ break;
+ }
+ sleep(n);
+ printf("ok\n");
+ break;
+
+ case 'j':
+ case 'l':
+ str3[0] = '\0';
+ toptname = "";
+ sscanf(line, "%s %s %s", str1, str2, str3);
+ ifindex = parse_cmd_args(&su, &su2, str1, str2, str3);
+ if (ifindex == 0) {
+ printf("-1\n");
+ break;
+ }
+ af = su.sa.sa_family;
+ if (af == AF_INET) {
+ struct in_addr ina;
+
+ error = __ifindex_to_primary_ip(ifindex, &ina);
+ if (error != 0) {
+ warn("primary_ip_lookup %s", str2);
+ printf("-1\n");
+ break;
+ }
+ level = IPPROTO_IP;
+
+#ifdef HAS_SSM
+ if (su2.sa.sa_family != AF_UNSPEC) {
+ mr.mrs.imr_multiaddr = su.sin.sin_addr;
+ mr.mrs.imr_sourceaddr = su2.sin.sin_addr;
+ mr.mrs.imr_interface = ina;
+ optname = (*cmd == 'j') ?
+ IP_ADD_SOURCE_MEMBERSHIP :
+ IP_DROP_SOURCE_MEMBERSHIP;
+ toptname = (*cmd == 'j') ?
+ "IP_ADD_SOURCE_MEMBERSHIP" :
+ "IP_DROP_SOURCE_MEMBERSHIP";
+ optval = (void *)&mr.mrs;
+ optlen = sizeof(mr.mrs);
+ } else {
+#endif
+ mr.mr.imr_multiaddr = su.sin.sin_addr;
+ mr.mr.imr_interface = ina;
+ optname = (*cmd == 'j') ?
+ IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
+ toptname = (*cmd == 'j') ?
+ "IP_ADD_MEMBERSHIP" : "IP_DROP_MEMBERSHIP";
+ optval = (void *)&mr.mr;
+ optlen = sizeof(mr.mr);
+#ifdef HAS_SSM
+ }
+#endif
+ if (setsockopt(s, level, optname, optval,
+ optlen) == 0) {
+ printf("ok\n");
+ break;
+ } else {
+ warn("setsockopt %s", toptname);
+ }
+ }
+#ifdef INET6
+ else
+#endif /* INET6 */
+#ifdef INET6
+ if (af == AF_INET6) {
+ level = IPPROTO_IPV6;
+#ifdef HAS_SSM
+ if (su2.sa.sa_family != AF_UNSPEC) {
+ mr.gr.gsr_interface = ifindex;
+ mr.gr.gsr_group = su.ss;
+ mr.gr.gsr_source = su2.ss;
+ optname = (*cmd == 'j') ?
+ MCAST_JOIN_SOURCE_GROUP:
+ MCAST_LEAVE_SOURCE_GROUP;
+ toptname = (*cmd == 'j') ?
+ "MCAST_JOIN_SOURCE_GROUP":
+ "MCAST_LEAVE_SOURCE_GROUP";
+ optval = (void *)&mr.gr;
+ optlen = sizeof(mr.gr);
+ } else {
+#endif
+ mr.mr6.ipv6mr_multiaddr = su.sin6.sin6_addr;
+ mr.mr6.ipv6mr_interface = ifindex;
+ optname = (*cmd == 'j') ?
+ IPV6_JOIN_GROUP :
+ IPV6_LEAVE_GROUP;
+ toptname = (*cmd == 'j') ?
+ "IPV6_JOIN_GROUP" :
+ "IPV6_LEAVE_GROUP";
+ optval = (void *)&mr.mr6;
+ optlen = sizeof(mr.mr6);
+#ifdef HAS_SSM
+ }
+#endif
+ if (setsockopt(s6, level, optname, optval,
+ optlen) == 0) {
+ printf("ok\n");
+ break;
+ } else {
+ warn("setsockopt %s", toptname);
+ }
+ }
+#endif /* INET6 */
+ /* FALLTHROUGH */
+ printf("-1\n");
+ break;
+
+#ifdef HAS_SSM
+ /*
+ * Set the socket to include or exclude filter mode, and
+ * add some sources to the filterlist, using the full-state API.
+ */
+ case 'i':
+ case 'e': {
+ sockunion_t sources[MAX_ADDRS];
+ struct addrinfo hints;
+ struct addrinfo *res;
+ char *cp;
+ int af1;
+
+ n = 0;
+ fmode = (*cmd == 'i') ? MCAST_INCLUDE : MCAST_EXCLUDE;
+ if ((sscanf(line, "%s %s %d", str1, str2, &n)) != 3) {
+ printf("-1\n");
+ break;
+ }
+
+ ifindex = parse_cmd_args(&su, NULL, str1, str2, NULL);
+ if (ifindex == 0 || n < 0 || n > MAX_ADDRS) {
+ printf("-1\n");
+ break;
+ }
+ af = su.sa.sa_family;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ for (i = 0; i < n; i++) {
+ sockunion_t *psu = (sockunion_t *)&sources[i];
+ /*
+ * Trim trailing whitespace, as getaddrinfo()
+ * can't cope with it.
+ */
+ fgets(str1, sizeof(str1), fp);
+ cp = strchr(str1, '\n');
+ if (cp != NULL)
+ *cp = '\0';
+
+ res = NULL;
+ error = getaddrinfo(str1, "0", &hints, &res);
+ if (error)
+ break;
+ assert(res != NULL);
+
+ memset(psu, 0, sizeof(sockunion_t));
+ af1 = res->ai_family;
+ if (af1 == af)
+ memcpy(psu, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ if (af1 != af)
+ break;
+ }
+ if (i < n) {
+ if (error)
+ warnx("getaddrinfo: %s", gai_strerror(error));
+ printf("-1\n");
+ break;
+ }
+ if (setsourcefilter(af2sock(af, s, s6), ifindex,
+ &su.sa, su.sa.sa_len, fmode, n, &sources[0].ss) != 0)
+ warn("setsourcefilter");
+ else
+ printf("ok\n");
+ } break;
+
+ /*
+ * Allow or block traffic from a source, using the
+ * delta based api.
+ */
+ case 't':
+ case 'b': {
+ str3[0] = '\0';
+ toptname = "";
+ sscanf(line, "%s %s %s", str1, str2, str3);
+ ifindex = parse_cmd_args(&su, &su2, str1, str2, str3);
+ if (ifindex == 0 || su2.sa.sa_family == AF_UNSPEC) {
+ printf("-1\n");
+ break;
+ }
+ af = su.sa.sa_family;
+
+ /* First determine our current filter mode. */
+ n = 0;
+ if (getsourcefilter(af2sock(af, s, s6), ifindex,
+ &su.sa, su.sa.sa_len, &fmode, (uint32_t *)&n, NULL) != 0) {
+ warn("getsourcefilter");
+ break;
+ }
+ if (af == AF_INET) {
+ struct in_addr ina;
+
+ error = __ifindex_to_primary_ip(ifindex, &ina);
+ if (error != 0) {
+ warn("primary_ip_lookup %s", str2);
+ printf("-1\n");
+ break;
+ }
+ level = IPPROTO_IP;
+ optval = (void *)&mr.mrs;
+ optlen = sizeof(mr.mrs);
+ mr.mrs.imr_multiaddr = su.sin.sin_addr;
+ mr.mrs.imr_sourceaddr = su2.sin.sin_addr;
+ mr.mrs.imr_interface = ina;
+ if (fmode == MCAST_EXCLUDE) {
+ /* Any-source mode socket membership. */
+ optname = (*cmd == 't') ?
+ IP_UNBLOCK_SOURCE :
+ IP_BLOCK_SOURCE;
+ toptname = (*cmd == 't') ?
+ "IP_UNBLOCK_SOURCE" :
+ "IP_BLOCK_SOURCE";
+ } else {
+ /* Source-specific mode socket membership. */
+ optname = (*cmd == 't') ?
+ IP_ADD_SOURCE_MEMBERSHIP :
+ IP_DROP_SOURCE_MEMBERSHIP;
+ toptname = (*cmd == 't') ?
+ "IP_ADD_SOURCE_MEMBERSHIP" :
+ "IP_DROP_SOURCE_MEMBERSHIP";
+ }
+ if (setsockopt(s, level, optname, optval,
+ optlen) == 0) {
+ printf("ok\n");
+ break;
+ } else {
+ warn("setsockopt %s", toptname);
+ }
+ }
+#ifdef INET6
+ else
+#endif /* INET6 */
+#ifdef INET6
+ if (af == AF_INET6) {
+ level = IPPROTO_IPV6;
+ mr.gr.gsr_interface = ifindex;
+ mr.gr.gsr_group = su.ss;
+ mr.gr.gsr_source = su2.ss;
+ if (fmode == MCAST_EXCLUDE) {
+ /* Any-source mode socket membership. */
+ optname = (*cmd == 't') ?
+ MCAST_UNBLOCK_SOURCE :
+ MCAST_BLOCK_SOURCE;
+ toptname = (*cmd == 't') ?
+ "MCAST_UNBLOCK_SOURCE" :
+ "MCAST_BLOCK_SOURCE";
+ } else {
+ /* Source-specific mode socket membership. */
+ optname = (*cmd == 't') ?
+ MCAST_JOIN_SOURCE_GROUP :
+ MCAST_LEAVE_SOURCE_GROUP;
+ toptname = (*cmd == 't') ?
+ "MCAST_JOIN_SOURCE_GROUP":
+ "MCAST_LEAVE_SOURCE_GROUP";
+ }
+ optval = (void *)&mr.gr;
+ optlen = sizeof(mr.gr);
+ if (setsockopt(s6, level, optname, optval,
+ optlen) == 0) {
+ printf("ok\n");
+ break;
+ } else {
+ warn("setsockopt %s", toptname);
+ }
+ }
+#endif /* INET6 */
+ /* FALLTHROUGH */
+ printf("-1\n");
+ } break;
+
+ case 'g': {
+ sockunion_t sources[MAX_ADDRS];
+ char addrbuf[NI_MAXHOST];
+ int nreqsrc, nsrc;
+
+ if ((sscanf(line, "%s %s %d", str1, str2, &nreqsrc)) != 3) {
+ printf("-1\n");
+ break;
+ }
+ ifindex = parse_cmd_args(&su, NULL, str1, str2, NULL);
+ if (ifindex == 0 || (n < 0 || n > MAX_ADDRS)) {
+ printf("-1\n");
+ break;
+ }
+
+ af = su.sa.sa_family;
+ nsrc = nreqsrc;
+ if (getsourcefilter(af2sock(af, s, s6), ifindex, &su.sa,
+ su.sa.sa_len, &fmode, (uint32_t *)&nsrc,
+ &sources[0].ss) != 0) {
+ warn("getsourcefilter");
+ printf("-1\n");
+ break;
+ }
+ printf("%s\n", (fmode == MCAST_INCLUDE) ? "include" :
+ "exclude");
+ printf("%d\n", nsrc);
+
+ nsrc = MIN(nreqsrc, nsrc);
+ fprintf(stderr, "hexdump of sources:\n");
+ uint8_t *bp = (uint8_t *)&sources[0];
+ for (i = 0; i < (nsrc * sizeof(sources[0])); i++) {
+ fprintf(stderr, "%02x", bp[i]);
+ }
+ fprintf(stderr, "\nend hexdump\n");
+
+ qsort(sources, nsrc, sizeof (sockunion_t), su_cmp);
+ for (i = 0; i < nsrc; i++) {
+ sockunion_t *psu = (sockunion_t *)&sources[i];
+ addrbuf[0] = '\0';
+ error = getnameinfo(&psu->sa, psu->sa.sa_len,
+ addrbuf, sizeof(addrbuf), NULL, 0,
+ NI_NUMERICHOST);
+ if (error)
+ warnx("getnameinfo: %s", gai_strerror(error));
+ else
+ printf("%s\n", addrbuf);
+ }
+ printf("ok\n");
+ } break;
+#endif
+ /* link-layer stuff follows. */
+
+ case 'a':
+ case 'd': {
+ struct sockaddr_dl *dlp;
+ struct ether_addr *ep;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+ dlp = (struct sockaddr_dl *)&ifr.ifr_addr;
+ dlp->sdl_len = sizeof(struct sockaddr_dl);
+ dlp->sdl_family = AF_LINK;
+ dlp->sdl_index = 0;
+ dlp->sdl_nlen = 0;
+ dlp->sdl_alen = ETHER_ADDR_LEN;
+ dlp->sdl_slen = 0;
+ if (sscanf(line, "%s %s", str1, str2) != 2) {
+ warnc(EINVAL, "sscanf");
+ break;
+ }
+ ep = ether_aton(str2);
+ if (ep == NULL) {
+ warnc(EINVAL, "ether_aton");
+ break;
+ }
+ strlcpy(ifr.ifr_name, str1, IF_NAMESIZE);
+ memcpy(LLADDR(dlp), ep, ETHER_ADDR_LEN);
+ if (ioctl(s, (*cmd == 'a') ? SIOCADDMULTI : SIOCDELMULTI,
+ &ifr) == -1) {
+ warn("ioctl SIOCADDMULTI/SIOCDELMULTI");
+ printf("-1\n");
+ } else
+ printf("ok\n");
+ break;
+ }
+
+ case 'm':
+ fprintf(stderr,
+ "warning: IFF_ALLMULTI cannot be set from userland "
+ "in Darwin; command ignored.\n");
+ printf("-1\n");
+ break;
+
+#ifndef __APPLE__
+ case 'p':
+ if (sscanf(line, "%s %u", ifr.ifr_name, &f) != 2) {
+ printf("-1\n");
+ break;
+ }
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
+ warn("ioctl SIOCGIFFLAGS");
+ break;
+ }
+ flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
+ if (f == 0) {
+ flags &= ~IFF_PPROMISC;
+ } else {
+ flags |= IFF_PPROMISC;
+ }
+ ifr.ifr_flags = flags & 0xffff;
+ ifr.ifr_flagshigh = flags >> 16;
+ if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1)
+ warn("ioctl SIOCGIFFLAGS");
+ else
+ printf( "changed to 0x%08x\n", flags );
+ break;
+#endif /* __APPLE__ */
+ case '\n':
+ break;
+ default:
+ printf("invalid command\n");
+ break;
+ }
+}
+
+static void
+usage(void)
+{
+
+#ifndef HAS_SSM
+ printf("j mcast-addr ifname - join IP multicast group\n");
+ printf("l mcast-addr ifname - leave IP multicast group\n");
+#else /* HAS_SSM */
+ printf("j mcast-addr ifname [src-addr] - join IP multicast group\n");
+ printf("l mcast-addr ifname [src-addr] - leave IP multicast group\n");
+ printf(
+ "i mcast-addr ifname n - set n include mode src filter\n");
+ printf(
+ "e mcast-addr ifname n - set n exclude mode src filter\n");
+ printf("t mcast-addr ifname src-addr - allow traffic from src\n");
+ printf("b mcast-addr ifname src-addr - block traffic from src\n");
+ printf("g mcast-addr ifname n - get and show n src filters\n");
+#endif
+ printf("a ifname mac-addr - add link multicast filter\n");
+ printf("d ifname mac-addr - delete link multicast filter\n");
+ printf("m ifname 1/0 - set/clear ether allmulti flag\n");
+#ifndef __APPLE__
+ printf("p ifname 1/0 - set/clear ether promisc flag\n");
+#endif /* __APPLE__ */
+ printf("f filename - read command(s) from file\n");
+ printf("s seconds - sleep for some time\n");
+ printf("q - quit\n");
+}
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+ <dict>
+ <key>OpenSourceProject</key>
+ <string>mtest</string>
+ <key>OpenSouceVersion</key>
+ <string>1.11</string>
+ <key>OpenSourceWebsiteURL</key>
+ <string>http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/</string>
+ <key>OpenSourceURL</key>
+ <string>http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/</string>
+ <key>OpenSourceSHA1</key>
+ <string></string>
+ <key>OpenSourceMD5</key>
+ <string></string>
+ <key>OpenSourceImportDate</key>
+ <string>2011-01-13</string>
+ <key>OpenSourceLicense</key>
+ <string>Other</string>
+ <key>OpenSourceLicenseFile</key>
+ <string>mtest.txt</string>
+ </dict>
+</array>
+</plist>
.Op Fl log_facility Ar facility_name
.Op Fl punch_fw Ar firewall_range
.Op Fl clamp_mss
+.Op Fl enable_natportmap
+.Op Fl natportmap_interface Ar interface
.Ek
.Sh DESCRIPTION
This program provides a Network Address Translation facility for use
MTU of the interface specified in the
.Fl interface
option.
+.It Fl enable_natportmap Xo
+.Xc
+This option enables port forwarding using the NATPMP protocol.
+.It Fl natportmap_interface Ar interface Xo
+.Xc
+This option instructs natd to listen for NATPMP requests. This option should appear for each
+interface on which natd will listen for NATPMP requests.
.El
.Sh RUNNING NATD
The following steps are necessary before attempting to run
.Nm :
.Bl -enum
.It
-Build a custom kernel with the following options:
-.Bd -literal -offset indent
-options IPFIREWALL
-options IPDIVERT
-.Ed
-.Pp
-Refer to the handbook for detailed instructions on building a custom
-kernel.
-.It
Ensure that your machine is acting as a gateway.
-This can be done by specifying the line
-.Pp
-.Dl gateway_enable=YES
-.Pp
-in the
-.Pa /etc/rc.conf
-file or using the command
+This can be done by using the command
.Pp
.Dl sysctl -w net.inet.ip.forwarding=1
.Pp
.Dl natd -interface en0
.Pp
should suffice in most cases (substituting the correct interface name).
-Please check
-.Xr rc.conf 5
-on how to configure it to be started automatically during boot.
+.Pp
Once
.Nm
is running, you must ensure that traffic is diverted to
.Nm :
.Bl -enum
.It
-You will need to adjust the
-.Pa /etc/rc.firewall
-script to taste.
If you are not interested in having a firewall, the
following lines will do:
.Bd -literal -offset indent
/sbin/ipfw -f flush
-/sbin/ipfw add divert natd all from any to any via ed0
+/sbin/ipfw add divert natd all from any to any via en0
/sbin/ipfw add pass all from any to any
.Ed
.Pp
from trusted hosts.
.Pp
If you specify real firewall rules, it is best to specify line 2 at
-the start of the script so that
+the start of the rules so that
.Nm
sees all packets before they are dropped by the firewall.
.Pp
that caused the diversion (not the next rule if there are several at the
same number).
.It
-Enable your firewall by setting
-.Pp
-.Dl firewall_enable=YES
-.Pp
-in
-.Pa /etc/rc.conf .
-This tells the system startup scripts to run the
-.Pa /etc/rc.firewall
-script.
-If you do not wish to reboot now, just run this by hand from the console.
-NEVER run this from a remote session unless you put it into the background.
-If you do, you will lock yourself out after the flush takes place, and
-execution of
-.Pa /etc/rc.firewall
-will stop at this point - blocking all accesses permanently.
-Running the script in the background should be enough to prevent this
-disaster.
+Enable your firewall by using the command
+.Pp
+.Dl sysctl -w net.inet.ip.fw.enable=1
+.Pp
.El
.Sh SEE ALSO
.Xr divert 4 ,
/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
+
/*
* natd - Network Address Translation Daemon for FreeBSD.
*
}
else {
- sprintf (msgBuf, "failed to write packet back");
+ snprintf (msgBuf, sizeof(msgBuf), "failed to write packet back");
Warn (msgBuf);
}
}
char src[20];
char dst[20];
- strcpy (src, inet_ntoa (ip->ip_src));
- strcpy (dst, inet_ntoa (ip->ip_dst));
+ strlcpy (src, inet_ntoa (ip->ip_src), sizeof(src));
+ strlcpy (dst, inet_ntoa (ip->ip_dst), sizeof(dst));
switch (ip->ip_p) {
case IPPROTO_TCP:
tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
- sprintf (buf, "[TCP] %s:%d -> %s:%d",
+ snprintf (buf, sizeof(buf), "[TCP] %s:%d -> %s:%d",
src,
ntohs (tcphdr->th_sport),
dst,
case IPPROTO_UDP:
udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
- sprintf (buf, "[UDP] %s:%d -> %s:%d",
+ snprintf (buf, sizeof(buf), "[UDP] %s:%d -> %s:%d",
src,
ntohs (udphdr->uh_sport),
dst,
case IPPROTO_ICMP:
icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
- sprintf (buf, "[ICMP] %s -> %s %u(%u)",
+ snprintf (buf, sizeof(buf), "[ICMP] %s -> %s %u(%u)",
src,
dst,
icmphdr->icmp_type,
break;
default:
- sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst);
+ snprintf (buf, sizeof(buf), "[%d] %s -> %s ", ip->ip_p, src, dst);
break;
}
int i;
struct alias_link *link = NULL;
- strcpy (buf, parms);
+ strlcpy (buf, parms, sizeof(buf));
/*
* Extract protocol.
*/
char* protoName;
struct protoent *protoent;
- strcpy (buf, parms);
+ strlcpy (buf, parms, sizeof(buf));
/*
* Extract protocol.
*/
char* serverPool;
struct alias_link *link;
- strcpy (buf, parms);
+ strlcpy (buf, parms, sizeof(buf));
/*
* Extract local address.
*/
.Sh SYNOPSIS
.Nm
.Fl a
-.Op Fl nt
+.Op Fl lnt
.Nm
.Fl A Ar wait
.Op Fl nt
interface.
NUD is usually turned on by default.
.El
+.It Fl l
+Show link-layer reachability information.
.It Fl n
Do not try to resolve numeric address to hostname.
.It Fl p
+/*
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/* $FreeBSD: src/usr.sbin/ndp/ndp.c,v 1.2.2.5 2001/08/13 02:58:26 sumikawa Exp $ */
/* $KAME: ndp.c,v 1.65 2001/05/08 04:36:34 itojun Exp $ */
void get __P((char *));
int delete __P((char *));
void dump __P((struct in6_addr *));
+void dump_ext __P((struct in6_addr *));
static struct in6_nbrinfo *getnbrinfo __P((struct in6_addr *addr,
int ifindex, int));
static char *ether_str __P((struct sockaddr_dl *));
{
int ch;
int aflag = 0, dflag = 0, sflag = 0, Hflag = 0,
- pflag = 0, rflag = 0, Pflag = 0, Rflag = 0;
+ pflag = 0, rflag = 0, Pflag = 0, Rflag = 0, lflag = 0;
pid = getpid();
// thiszone = gmt2local(0);
file(argv[2]);
exit(0);
case 'l' :
- /* obsolete, ignored */
+ lflag = 1;
break;
case 'r' :
rflag = 1;
argv += optind;
if (aflag || cflag) {
- dump(0);
+ if (lflag)
+ dump_ext(0);
+ else
+ dump(0);
exit(0);
}
if (dflag) {
} else if (IN6_IS_ADDR_MULTICAST(&sin->sin6_addr))
continue;
if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sin->sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&sin->sin6_addr)) {
/* XXX: should scope id be filled in the kernel? */
if (sin->sin6_scope_id == 0)
}
}
+/*
+ * Dump the entire neighbor cache (extended)
+ */
+void
+dump_ext(addr)
+ struct in6_addr *addr;
+{
+ int mib[6];
+ size_t needed;
+ char *lim, *buf, *next;
+ struct rt_msghdr_ext *ertm;
+ struct sockaddr_in6 *sin;
+ struct sockaddr_dl *sdl;
+ extern int h_errno;
+ struct in6_nbrinfo *nbi;
+ struct timeval time;
+ int addrwidth;
+ int llwidth;
+ int ifwidth;
+ char flgbuf[8];
+ char *ifname;
+
+ /* Print header */
+ if (!tflag && !cflag)
+ printf("%-*.*s %-*.*s %*.*s %-9.9s %-9.9s %2s %4s %4s\n",
+ W_ADDR, W_ADDR, "Neighbor", W_LL, W_LL, "Linklayer Address",
+ W_IF, W_IF, "Netif", "Expire(O)", "Expire(I)", "St",
+ "Flgs", "Prbs");
+
+again:;
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET6;
+ mib[4] = NET_RT_DUMPX_FLAGS;
+ mib[5] = RTF_LLINFO;
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ err(1, "sysctl(PF_ROUTE estimate)");
+ if (needed > 0) {
+ if ((buf = malloc(needed)) == NULL)
+ errx(1, "malloc");
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+ err(1, "sysctl(PF_ROUTE, NET_RT_FLAGS)");
+ lim = buf + needed;
+ } else
+ buf = lim = NULL;
+
+ for (next = buf; next && next < lim; next += ertm->rtm_msglen) {
+ int isrouter = 0, prbs = 0;
+
+ ertm = (struct rt_msghdr_ext *)next;
+ sin = (struct sockaddr_in6 *)(ertm + 1);
+ sdl = (struct sockaddr_dl *)((char *)sin + ROUNDUP(sin->sin6_len));
+
+ /*
+ * Some OSes can produce a route that has the LINK flag but
+ * has a non-AF_LINK gateway (e.g. fe80::xx%lo0 on FreeBSD
+ * and BSD/OS, where xx is not the interface identifier on
+ * lo0). Such routes entry would annoy getnbrinfo() below,
+ * so we skip them.
+ * XXX: such routes should have the GATEWAY flag, not the
+ * LINK flag. However, there are rotten routing software
+ * that advertises all routes that have the GATEWAY flag.
+ * Thus, KAME kernel intentionally does not set the LINK flag.
+ * What is to be fixed is not ndp, but such routing software
+ * (and the kernel workaround)...
+ */
+ if (sdl->sdl_family != AF_LINK)
+ continue;
+
+ if (addr) {
+ if (!IN6_ARE_ADDR_EQUAL(addr, &sin->sin6_addr))
+ continue;
+ found_entry = 1;
+ } else if (IN6_IS_ADDR_MULTICAST(&sin->sin6_addr))
+ continue;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sin->sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin->sin6_addr)) {
+ /* XXX: should scope id be filled in the kernel? */
+ if (sin->sin6_scope_id == 0)
+ sin->sin6_scope_id = sdl->sdl_index;
+#ifdef __KAME__
+ /* KAME specific hack; removed the embedded id */
+ *(u_int16_t *)&sin->sin6_addr.s6_addr[2] = 0;
+#endif
+ }
+ getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf,
+ sizeof(host_buf), NULL, 0,
+ NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
+ if (cflag == 1) {
+#ifdef RTF_WASCLONED
+ if (ertm->rtm_flags & RTF_WASCLONED)
+ delete(host_buf);
+#else
+ delete(host_buf);
+#endif
+ continue;
+ }
+ gettimeofday(&time, 0);
+ if (tflag)
+ ts_print(&time);
+
+ addrwidth = strlen(host_buf);
+ if (addrwidth < W_ADDR)
+ addrwidth = W_ADDR;
+ llwidth = strlen(ether_str(sdl));
+ if (W_ADDR + W_LL - addrwidth > llwidth)
+ llwidth = W_ADDR + W_LL - addrwidth;
+ ifname = if_indextoname(sdl->sdl_index, ifix_buf);
+ if (!ifname)
+ ifname = "?";
+ ifwidth = strlen(ifname);
+ if (W_ADDR + W_LL + W_IF - addrwidth - llwidth > ifwidth)
+ ifwidth = W_ADDR + W_LL + W_IF - addrwidth - llwidth;
+
+ printf("%-*.*s %-*.*s %*.*s", addrwidth, addrwidth, host_buf,
+ llwidth, llwidth, ether_str(sdl), ifwidth, ifwidth, ifname);
+
+ if (ertm->rtm_ri.ri_refcnt == 0 ||
+ ertm->rtm_ri.ri_snd_expire == 0)
+ printf(" %-9.9s", "(none)");
+ else if (ertm->rtm_ri.ri_snd_expire > time.tv_sec)
+ printf(" %-9.9s",
+ sec2str(ertm->rtm_ri.ri_snd_expire - time.tv_sec));
+ else
+ printf(" %-9.9s", "expired");
+
+ if (ertm->rtm_ri.ri_refcnt == 0 ||
+ ertm->rtm_ri.ri_rcv_expire == 0)
+ printf(" %-9.9s", "(none)");
+ else if (ertm->rtm_ri.ri_rcv_expire > time.tv_sec)
+ printf(" %-9.9s",
+ sec2str(ertm->rtm_ri.ri_rcv_expire - time.tv_sec));
+ else
+ printf(" %-9.9s", "expired");
+
+ /* Print neighbor discovery specific informations */
+ nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index, 1);
+ if (nbi) {
+ switch(nbi->state) {
+ case ND6_LLINFO_NOSTATE:
+ printf(" N");
+ break;
+#ifdef ND6_LLINFO_WAITDELETE
+ case ND6_LLINFO_WAITDELETE:
+ printf(" W");
+ break;
+#endif
+ case ND6_LLINFO_INCOMPLETE:
+ printf(" I");
+ break;
+ case ND6_LLINFO_REACHABLE:
+ printf(" R");
+ break;
+ case ND6_LLINFO_STALE:
+ printf(" S");
+ break;
+ case ND6_LLINFO_DELAY:
+ printf(" D");
+ break;
+ case ND6_LLINFO_PROBE:
+ printf(" P");
+ break;
+ default:
+ printf(" ?");
+ break;
+ }
+
+ isrouter = nbi->isrouter;
+ prbs = nbi->asked;
+ } else {
+ warnx("failed to get neighbor information");
+ printf(" ");
+ }
+ putchar(' ');
+
+ /*
+ * other flags. R: router, P: proxy, W: ??
+ */
+ if ((ertm->rtm_addrs & RTA_NETMASK) == 0) {
+ snprintf(flgbuf, sizeof(flgbuf), "%s%s",
+ isrouter ? "R" : "",
+ (ertm->rtm_flags & RTF_ANNOUNCE) ? "p" : "");
+ } else {
+ sin = (struct sockaddr_in6 *)
+ (sdl->sdl_len + (char *)sdl);
+ snprintf(flgbuf, sizeof(flgbuf), "%s%s%s%s",
+ isrouter ? "R" : "",
+ !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr)
+ ? "P" : "",
+ (sin->sin6_len != sizeof(struct sockaddr_in6))
+ ? "W" : "",
+ (ertm->rtm_flags & RTF_ANNOUNCE) ? "p" : "");
+ }
+ printf(" %-4.4s", flgbuf);
+
+ if (prbs)
+ printf(" %4d", prbs);
+
+ printf("\n");
+ }
+ if (buf != NULL)
+ free(buf);
+
+ if (repeat) {
+ printf("\n");
+ sleep(repeat);
+ goto again;
+ }
+}
+
static struct in6_nbrinfo *
getnbrinfo(addr, ifindex, warning)
struct in6_addr *addr;
if (sdl->sdl_alen) {
cp = (u_char *)LLADDR(sdl);
- sprintf(ebuf, "%x:%x:%x:%x:%x:%x",
+ snprintf(ebuf, sizeof(ebuf), "%x:%x:%x:%x:%x:%x",
cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
} else {
- sprintf(ebuf, "(incomplete)");
+ snprintf(ebuf, sizeof(ebuf), "(incomplete)");
}
return(ebuf);
usage()
{
printf("usage: ndp hostname\n");
- printf(" ndp -a[nt]\n");
+ printf(" ndp -a[lnt]\n");
printf(" ndp [-nt] -A wait\n");
printf(" ndp -c[nt]\n");
printf(" ndp -d[nt] hostname\n");
exit(1);
}
bzero(&nd, sizeof(nd));
- strcpy(nd.ifname, ifname);
+ strlcpy(nd.ifname, ifname, sizeof(nd.ifname));
if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
perror("ioctl (SIOCGIFINFO_IN6)");
exit(1);
printf("%s if=%s", host_buf,
if_indextoname(p->if_index, ifix_buf));
- printf(", flags=%s%s",
+ printf(", flags=%s%s%s%s%s",
p->flags & ND_RA_FLAG_MANAGED ? "M" : "",
- p->flags & ND_RA_FLAG_OTHER ? "O" : "");
+ p->flags & ND_RA_FLAG_OTHER ? "O" : "",
+ p->stateflags & NDDRF_INSTALLED ? "T" : "",
+ p->stateflags & NDDRF_IFSCOPE ? "I" : "",
+ p->stateflags & NDDRF_STATIC ? "S" : "");
rtpref = ((p->flags & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff;
printf(", pref=%s", rtpref_str[rtpref]);
exit(1);
}
bzero(&dr, sizeof(dr));
- strcpy(dr.ifname, "lo0"); /* dummy */
+ strlcpy(dr.ifname, "lo0", sizeof(dr.ifname)); /* dummy */
if (ioctl(s, SIOCGDRLST_IN6, (caddr_t)&dr) < 0) {
perror("ioctl (SIOCGDRLST_IN6)");
exit(1);
* meaning of fields, especially flags, is very different
* by origin. notify the difference to the users.
*/
- printf("flags=%s%s%s%s%s",
+ printf("flags=%s%s%s%s%s%s%s",
p->raflags.onlink ? "L" : "",
p->raflags.autonomous ? "A" : "",
(p->flags & NDPRF_ONLINK) != 0 ? "O" : "",
(p->flags & NDPRF_DETACHED) != 0 ? "D" : "",
+ (p->flags & NDPRF_IFSCOPE) != 0 ? "I" : "",
#ifdef NDPRF_HOME
- (p->flags & NDPRF_HOME) != 0 ? "H" : ""
+ (p->flags & NDPRF_HOME) != 0 ? "H" : "",
+#else
+ "",
+#endif
+#ifdef NDPRF_STATIC
+ (p->flags & NDPRF_STATIC) != 0 ? "S" : ""
#else
""
#endif
exit(1);
}
bzero(&pr, sizeof(pr));
- strcpy(pr.ifname, "lo0"); /* dummy */
+ strlcpy(pr.ifname, "lo0", sizeof(pr.ifname)); /* dummy */
if (ioctl(s, SIOCGPRLST_IN6, (caddr_t)&pr) < 0) {
perror("ioctl (SIOCGPRLST_IN6)");
exit(1);
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
- strcpy(dummyif, "lo0"); /* dummy */
+ strlcpy(dummyif, "lo0", sizeof(dummyif)); /* dummy */
if (ioctl(s, SIOCSPFXFLUSH_IN6, (caddr_t)&dummyif) < 0)
err(1, "ioctl(SIOCSPFXFLUSH_IN6)");
}
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
- strcpy(dummyif, "lo0"); /* dummy */
+ strlcpy(dummyif, "lo0", sizeof(dummyif)); /* dummy */
if (ioctl(s, SIOCSRTRFLUSH_IN6, (caddr_t)&dummyif) < 0)
err(1, "ioctl(SIOCSRTRFLUSH_IN6)");
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
- strcpy(dummyif, "lo0"); /* dummy */
+ strlcpy(dummyif, "lo0", sizeof(dummyif)); /* dummy */
if (ioctl(s, SIOCSNDFLUSH_IN6, (caddr_t)&dummyif) < 0)
err(1, "ioctl (SIOCSNDFLUSH_IN6)");
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
- strcpy(ndifreq.ifname, "lo0"); /* dummy */
+ strlcpy(ndifreq.ifname, "lo0", sizeof(ndifreq.ifname)); /* dummy */
ndifreq.ifindex = ifindex;
if (ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq) < 0)
err(1, "socket");
memset(&ndifreq, 0, sizeof(ndifreq));
- strcpy(ndifreq.ifname, "lo0"); /* dummy */
+ strlcpy(ndifreq.ifname, "lo0", sizeof(ndifreq.ifname)); /* dummy */
if (ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq) < 0)
err(1, "ioctl (SIOCGDEFIFACE_IN6)");
if (days) {
first = 0;
- p += sprintf(p, "%dd", days);
+ p += snprintf(p, sizeof(result) - (p - result), "%dd", days);
}
if (!first || hours) {
first = 0;
- p += sprintf(p, "%dh", hours);
+ p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
}
if (!first || mins) {
first = 0;
- p += sprintf(p, "%dm", mins);
+ p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
}
- sprintf(p, "%ds", secs);
+ snprintf(p, sizeof(result) - (p - result), "%ds", secs);
return(result);
}
/*
- * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_mib.h>
+#include <net/if_llreach.h>
#include <net/ethernet.h>
#include <net/route.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
+#include <errno.h>
#include "netstat.h"
static void sidewaysintpr ();
static void catchalarm (int);
+static char *sec2str(time_t);
+static void llreach_sysctl(uint32_t);
#ifdef INET6
char *netname6 (struct sockaddr_in6 *, struct sockaddr *);
/* Construct the format string */
if (showvalue) {
- sprintf(newfmt, "%%%d%s", width, fmt);
+ snprintf(newfmt, sizeof(newfmt), "%%%d%s", width, fmt);
printf(newfmt, value);
} else {
- sprintf(newfmt, "%%%ds", width);
+ snprintf(newfmt, sizeof(newfmt), "%%%ds", width);
printf(newfmt, "-");
}
}
memcpy(&sin6, sa, sizeof(struct sockaddr_in6));
if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) {
sin6.sin6_scope_id = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
sin6.sin6_addr.s6_addr[2] = 0;
free(buf);
return;
}
+
if (!pfunc) {
printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
"Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
- if (bflag)
+ if (prioflag >= 0)
+ printf(" %8.8s", "Itcpkts");
+ if (bflag) {
printf(" %10.10s","Ibytes");
+ if (prioflag >= 0)
+ printf(" %10.10s", "Itcbytes");
+ }
printf(" %8.8s %5.5s", "Opkts", "Oerrs");
- if (bflag)
+ if (prioflag >= 0)
+ printf(" %8.8s", "Otcpkts");
+ if (bflag) {
printf(" %10.10s","Obytes");
+ if (prioflag >= 0)
+ printf(" %10.10s", "Otcbytes");
+ }
printf(" %5s", "Coll");
if (tflag)
printf(" %s", "Time");
for (next = buf; next < lim; ) {
char *cp;
int n, m;
+ struct ifmibdata_supplemental ifmsupp;
+ u_int64_t ift_itcp = 0; /* input tc packets */
+ u_int64_t ift_itcb = 0; /* input tc bytes */
+ u_int64_t ift_otcp = 0; /* output tc packets */
+ u_int64_t ift_otcb = 0; /* output tc bytes */
+
+ bzero(&ifmsupp, sizeof(struct ifmibdata_supplemental));
network_layer = 0;
link_layer = 0;
drops = if2m->ifm_snd_drops;
mtu = if2m->ifm_data.ifi_mtu;
+ if (prioflag >= 0) {
+ int name[6];
+ size_t miblen = sizeof(struct ifmibdata_supplemental);
+
+ /* Common OID prefix */
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_IFDATA;
+ name[4] = if2m->ifm_index;
+ name[5] = IFDATA_SUPPLEMENTAL;
+ if (sysctl(name, 6, &ifmsupp, &miblen, (void *)0, 0) == -1)
+ err(1, "sysctl IFDATA_SUPPLEMENTAL");
+
+ switch (prioflag) {
+ case SO_TC_BK:
+ ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
+ ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
+ ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obkpackets;
+ ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obkbytes;
+ break;
+ case SO_TC_VI:
+ ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivipackets;
+ ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivibytes;
+ ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovipackets;
+ ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovibytes;
+ break;
+ case SO_TC_VO:
+ ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivopackets;
+ ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivobytes;
+ ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovopackets;
+ ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovobytes;
+ break;
+ default:
+ ift_itcp = 0;
+ ift_itcb = 0;
+ ift_otcp = 0;
+ ift_otcb = 0;
+ break;
+ }
+ }
+
get_rti_info(if2m->ifm_addrs, (struct sockaddr*)(if2m + 1), rti_info);
sa = rti_info[RTAX_IFP];
} else if (ifm->ifm_type == RTM_NEWADDR) {
char linknum[10];
cp = (char *)LLADDR(sdl);
n = sdl->sdl_alen;
- sprintf(linknum, "<Link#%d>", sdl->sdl_index);
+ snprintf(linknum, sizeof(linknum), "<Link#%d>", sdl->sdl_index);
m = printf("%-11.11s ", linknum);
goto hexprint;
}
printf(" ");
show_stat("llu", 5, ierrors, link_layer);
printf(" ");
+ if (prioflag >= 0) {
+ show_stat("llu", 8, ift_itcp, link_layer|network_layer);
+ printf(" ");
+ }
if (bflag) {
show_stat("llu", 10, ibytes, link_layer|network_layer);
printf(" ");
+ if (prioflag >= 0) {
+ show_stat("llu", 8, ift_itcb, link_layer|network_layer);
+ printf(" ");
+ }
}
show_stat("llu", 8, opackets, link_layer|network_layer);
printf(" ");
show_stat("llu", 5, oerrors, link_layer);
printf(" ");
+ if (prioflag >= 0) {
+ show_stat("llu", 8, ift_otcp, link_layer|network_layer);
+ printf(" ");
+ }
if (bflag) {
show_stat("llu", 10, obytes, link_layer|network_layer);
printf(" ");
+ if (prioflag >= 0) {
+ show_stat("llu", 8, ift_otcb, link_layer|network_layer);
+ printf(" ");
+ }
}
show_stat("llu", 5, collisions, link_layer);
if (tflag) {
if (aflag)
multipr(sa->sa_family, next, lim);
}
+ free(buf);
}
struct iftot {
if (interface && strcmp(ifmd->ifmd_name, interface) == 0) {
if ((interesting = calloc(ifcount, sizeof(struct iftot))) == NULL)
err(1, "malloc failed");
- interesting_row = i + 1;
+ interesting_row = if_nametoindex(interface);
snprintf(interesting->ift_name, 16, "(%s)", ifmd->ifmd_name);;
}
}
(void)setitimer(ITIMER_REAL, &timer_interval, NULL);
first = 1;
banner:
- if (prioflag)
+ if (prioflag >= 0)
printf("%37s %14s %16s", "input",
interesting ? interesting->ift_name : "(Total)", "output");
else
putchar('\n');
printf("%10s %5s %10s ",
"packets", "errs", "bytes");
- if (prioflag)
+ if (prioflag >= 0)
printf(" %10s %10s", "tcpkts", "tcbytes");
printf("%10s %5s %10s %5s",
"packets", "errs", "bytes", "colls");
if (dflag)
printf(" %5.5s", "drops");
- if (prioflag)
+ if (prioflag >= 0)
printf(" %10s %10s", "tcpkts", "tcbytes");
putchar('\n');
fflush(stdout);
if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1)
err(1, "sysctl IFDATA_GENERAL %d", interesting_row);
- if (prioflag) {
+ if (prioflag >= 0) {
len = sizeof(struct ifmibdata_supplemental);
name[3] = IFMIB_IFDATA;
name[4] = interesting_row;
name[5] = IFDATA_GENERAL;
if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
err(1, "sysctl IFMIB_IFALLDATA");
- if (prioflag) {
+ if (prioflag >= 0) {
len = ifcount * sizeof(struct ifmibdata_supplemental);
ifmsuppall = malloc(len);
if (ifmsuppall == NULL)
sum->ift_co += ifmd->ifmd_data.ifi_collisions;
sum->ift_dr += ifmd->ifmd_snd_drops;
/* private counters */
- if (prioflag) {
+ if (prioflag >= 0) {
struct ifmibdata_supplemental *ifmsupp = ifmsuppall + i;
switch (prioflag) {
case SO_TC_BK:
sum->ift_ip - total->ift_ip,
sum->ift_ie - total->ift_ie,
sum->ift_ib - total->ift_ib);
- if (prioflag)
+ if (prioflag >= 0)
printf(" %10llu %10llu",
sum->ift_itcp - total->ift_itcp,
sum->ift_itcb - total->ift_itcb);
sum->ift_co - total->ift_co);
if (dflag)
printf(" %5llu", sum->ift_dr - total->ift_dr);
- if (prioflag)
+ if (prioflag >= 0)
printf(" %10llu %10llu",
sum->ift_otcp - total->ift_otcp,
sum->ift_otcb - total->ift_otcb);
{
signalled = YES;
}
+
+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 += snprintf(p, sizeof(result) - (p - result), "%dd", days);
+ }
+ if (!first || hours) {
+ first = 0;
+ p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
+ }
+ if (!first || mins) {
+ first = 0;
+ p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
+ }
+ snprintf(p, sizeof(result) - (p - result), "%ds", secs);
+
+ return(result);
+}
+
+void
+intpr_ri(void (*pfunc)(char *))
+{
+ int mib[6];
+ char *buf = NULL, *lim, *next;
+ size_t len;
+ unsigned int ifindex = 0;
+ struct if_msghdr2 *if2m;
+
+ if (interface != 0) {
+ ifindex = if_nametoindex(interface);
+ if (ifindex == 0) {
+ printf("interface name is not valid: %s\n", interface);
+ exit(1);
+ }
+ }
+
+ mib[0] = CTL_NET; /* networking subsystem */
+ mib[1] = PF_ROUTE; /* type of information */
+ mib[2] = 0; /* protocol (IPPROTO_xxx) */
+ mib[3] = 0; /* address family */
+ mib[4] = NET_RT_IFLIST2; /* operation */
+ mib[5] = 0;
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+ return;
+ if ((buf = malloc(len)) == NULL) {
+ printf("malloc failed\n");
+ exit(1);
+ }
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ free(buf);
+ return;
+ }
+
+ printf("%-6s %-17s %8.8s %-9.9s %4s %4s\n",
+ "Proto", "Linklayer Address", "Netif", "Expire", "Refs", "Prbs");
+
+ lim = buf + len;
+ if2m = (struct if_msghdr2 *)buf;
+
+ for (next = buf; next < lim; ) {
+ if2m = (struct if_msghdr2 *)next;
+ next += if2m->ifm_msglen;
+
+ if (if2m->ifm_type != RTM_IFINFO2)
+ continue;
+ else if (interface != 0 && if2m->ifm_index != ifindex)
+ continue;
+
+ llreach_sysctl(if2m->ifm_index);
+ }
+ free(buf);
+}
+
+static void
+llreach_sysctl(uint32_t ifindex)
+{
+#define MAX_SYSCTL_TRY 5
+ int mib[6], i, ntry = 0;
+ size_t mibsize, len, needed, cnt;
+ struct if_llreach_info *lri;
+ struct timeval time;
+ char *buf;
+ char ifname[IF_NAMESIZE];
+
+ bzero(&mib, sizeof (mib));
+ mibsize = sizeof (mib) / sizeof (mib[0]);
+ if (sysctlnametomib("net.link.generic.system.llreach_info", mib,
+ &mibsize) == -1) {
+ perror("sysctlnametomib");
+ return;
+ }
+
+ needed = 0;
+ mib[5] = ifindex;
+
+ mibsize = sizeof (mib) / sizeof (mib[0]);
+ do {
+ if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
+ perror("sysctl net.link.generic.system.llreach_info");
+ return;
+ }
+ if ((buf = malloc(needed)) == NULL) {
+ perror("malloc");
+ return;
+ }
+ if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ perror("sysctl");
+ goto out_free;
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ len = needed;
+ cnt = len / sizeof (*lri);
+ lri = (struct if_llreach_info *)buf;
+
+ gettimeofday(&time, 0);
+ if (if_indextoname(ifindex, ifname) == NULL)
+ snprintf(ifname, sizeof (ifname), "%s", "?");
+
+ for (i = 0; i < cnt; i++, lri++) {
+ printf("0x%-4x %-17s %8.8s ", lri->lri_proto,
+ ether_ntoa((struct ether_addr *)lri->lri_addr), ifname);
+
+ if (lri->lri_expire > time.tv_sec)
+ printf("%-9.9s", sec2str(lri->lri_expire - time.tv_sec));
+ else if (lri->lri_expire == 0)
+ printf("%-9.9s", "permanent");
+ else
+ printf("%-9.9s", "expired");
+
+ printf(" %4d", lri->lri_refcnt);
+ if (lri->lri_probes)
+ printf(" %4d", lri->lri_probes);
+ printf("\n");
+ len -= sizeof (*lri);
+ }
+ if (len > 0) {
+ fprintf(stderr, "warning: %u trailing bytes from %s\n",
+ (unsigned int)len, "net.link.generic.system.llreach_info");
+ }
+
+out_free:
+ free(buf);
+#undef MAX_SYSCTL_TRY
+}
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ ** @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1983, 1988, 1993, 1995
#include <unistd.h>
#include "netstat.h"
+#define ROUNDUP64(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint64_t) - 1))) : sizeof(uint64_t))
+#define ADVANCE64(x, n) (((char *)x) += ROUNDUP64(n))
+
char *inetname (struct in_addr *);
void inetprint (struct in_addr *, int, char *, int);
#ifdef INET6
* Listening processes (aflag) are suppressed unless the
* -a (all) flag is specified.
*/
+#if !TARGET_OS_EMBEDDED
+
+struct xgen_n {
+ u_int32_t xgn_len; /* length of this structure */
+ u_int32_t xgn_kind; /* number of PCBs at this time */
+};
+
+#define ALL_XGN_KIND_INP (XSO_SOCKET | XSO_RCVBUF | XSO_SNDBUF | XSO_STATS | XSO_INPCB)
+#define ALL_XGN_KIND_TCP (ALL_XGN_KIND_INP | XSO_TCPCB)
+
void
protopr(uint32_t proto, /* for sysctl version we pass proto # */
- char *name, int af)
+ char *name, int af)
{
int istcp;
static int first = 1;
- char *buf;
+ char *buf, *next;
const char *mibvar;
struct xinpgen *xig, *oxig;
+ struct xgen_n *xgn;
+ size_t len;
+ struct xtcpcb_n *tp = NULL;
+ struct xinpcb_n *inp = NULL;
+ struct xsocket_n *so = NULL;
+ struct xsockbuf_n *so_rcv = NULL;
+ struct xsockbuf_n *so_snd = NULL;
+ struct xsockstat_n *so_stat = NULL;
+ int which = 0;
+
+ istcp = 0;
+ switch (proto) {
+ case IPPROTO_TCP:
+#ifdef INET6
+ if (tcp_done != 0)
+ return;
+ else
+ tcp_done = 1;
+#endif
+ istcp = 1;
+ mibvar = "net.inet.tcp.pcblist_n";
+ break;
+ case IPPROTO_UDP:
+#ifdef INET6
+ if (udp_done != 0)
+ return;
+ else
+ udp_done = 1;
+#endif
+ mibvar = "net.inet.udp.pcblist_n";
+ break;
+ case IPPROTO_DIVERT:
+ mibvar = "net.inet.divert.pcblist_n";
+ break;
+ default:
+ mibvar = "net.inet.raw.pcblist_n";
+ break;
+ }
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ return;
+ }
+ if ((buf = malloc(len)) == 0) {
+ warn("malloc %lu bytes", (u_long)len);
+ return;
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ free(buf);
+ return;
+ }
+
+ /*
+ * Bail-out to avoid logic error in the loop below when
+ * there is in fact no more control block to process
+ */
+ if (len <= sizeof(struct xinpgen)) {
+ free(buf);
+ return;
+ }
+
+ oxig = xig = (struct xinpgen *)buf;
+ for (next = buf + ROUNDUP64(xig->xig_len); next < buf + len; next += ROUNDUP64(xgn->xgn_len)) {
+
+ xgn = (struct xgen_n*)next;
+ if (xgn->xgn_len <= sizeof(struct xinpgen))
+ break;
+
+ if ((which & xgn->xgn_kind) == 0) {
+ which |= xgn->xgn_kind;
+ switch (xgn->xgn_kind) {
+ case XSO_SOCKET:
+ so = (struct xsocket_n *)xgn;
+ break;
+ case XSO_RCVBUF:
+ so_rcv = (struct xsockbuf_n *)xgn;
+ break;
+ case XSO_SNDBUF:
+ so_snd = (struct xsockbuf_n *)xgn;
+ break;
+ case XSO_STATS:
+ so_stat = (struct xsockstat_n *)xgn;
+ break;
+ case XSO_INPCB:
+ inp = (struct xinpcb_n *)xgn;
+ break;
+ case XSO_TCPCB:
+ tp = (struct xtcpcb_n *)xgn;
+ break;
+ default:
+ printf("unexpected kind %d\n", xgn->xgn_kind);
+ break;
+ }
+ } else {
+ printf("got %d twice\n", xgn->xgn_kind);
+ }
+
+ if ((istcp && which != ALL_XGN_KIND_TCP) || (!istcp && which != ALL_XGN_KIND_INP))
+ continue;
+ which = 0;
+
+ /* Ignore sockets for protocols other than the desired one. */
+ if (so->xso_protocol != (int)proto)
+ continue;
+
+ /* Ignore PCBs which were freed during copyout. */
+ if (inp->inp_gencnt > oxig->xig_gen)
+ continue;
+
+ if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
+#ifdef INET6
+ || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
+#endif /* INET6 */
+ || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
+#ifdef INET6
+ && (inp->inp_vflag &
+ INP_IPV6) == 0
+#endif /* INET6 */
+ ))
+ )
+ continue;
+
+ /*
+ * Local address is not an indication of listening socket or
+ * server sockey but just rather the socket has been bound.
+ * That why many UDP sockets were not displayed in the original code.
+ */
+ if (!aflag && istcp && tp->t_state <= TCPS_LISTEN)
+ continue;
+
+ if (Lflag && !so->so_qlimit)
+ continue;
+
+ if (first) {
+ if (!Lflag) {
+ printf("Active Internet connections");
+ if (aflag)
+ printf(" (including servers)");
+ } else
+ printf(
+ "Current listen queue sizes (qlen/incqlen/maxqlen)");
+ putchar('\n');
+ if (Aflag)
#if !TARGET_OS_EMBEDDED
- struct xtcpcb64 *tp = NULL;
- struct xinpcb64 *inp;
- struct xsocket64 *so;
+ printf("%-16.16s ", "Socket");
#else
+ printf("%-8.8s ", "Socket");
+#endif
+ if (Lflag)
+ printf("%-14.14s %-22.22s\n",
+ "Listen", "Local Address");
+ else {
+ printf((Aflag && !Wflag) ?
+ "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %-11.11s" :
+ "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %-11.11s",
+ "Proto", "Recv-Q", "Send-Q",
+ "Local Address", "Foreign Address",
+ "(state)");
+ if (bflag > 0)
+ printf(" %10.10s %10.10s", "rxbytes", "txbytes");
+ if (prioflag >= 0)
+ printf(" %7.7s[%1d] %7.7s[%1d]", "rxbytes", prioflag, "txbytes", prioflag);
+ printf("\n");
+ }
+ first = 0;
+ }
+ if (Aflag) {
+ if (istcp)
+#if !TARGET_OS_EMBEDDED
+ printf("%16lx ", (u_long)inp->inp_ppcb);
+#else
+ printf("%8lx ", (u_long)inp->inp_ppcb);
+
+#endif
+ else
+#if !TARGET_OS_EMBEDDED
+ printf("%16lx ", (u_long)so->so_pcb);
+#else
+ printf("%8lx ", (u_long)so->so_pcb);
+#endif
+ }
+ if (Lflag) {
+ char buf[15];
+
+ snprintf(buf, 15, "%d/%d/%d", so->so_qlen,
+ so->so_incqlen, so->so_qlimit);
+ printf("%-14.14s ", buf);
+ }
+ else {
+ const char *vchar;
+
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV6) != 0)
+ vchar = ((inp->inp_vflag & INP_IPV4) != 0)
+ ? "46" : "6 ";
+ else
+#endif
+ vchar = ((inp->inp_vflag & INP_IPV4) != 0)
+ ? "4 " : " ";
+
+ printf("%-3.3s%-2.2s %6u %6u ", name, vchar,
+ so_rcv->sb_cc,
+ so_snd->sb_cc);
+ }
+ if (nflag) {
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+ name, 1);
+ if (!Lflag)
+ inetprint(&inp->inp_faddr,
+ (int)inp->inp_fport, name, 1);
+ }
+#ifdef INET6
+ else if (inp->inp_vflag & INP_IPV6) {
+ inet6print(&inp->in6p_laddr,
+ (int)inp->inp_lport, name, 1);
+ if (!Lflag)
+ inet6print(&inp->in6p_faddr,
+ (int)inp->inp_fport, name, 1);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ } else if (inp->inp_flags & INP_ANONPORT) {
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+ name, 1);
+ if (!Lflag)
+ inetprint(&inp->inp_faddr,
+ (int)inp->inp_fport, name, 0);
+ }
+#ifdef INET6
+ else if (inp->inp_vflag & INP_IPV6) {
+ inet6print(&inp->in6p_laddr,
+ (int)inp->inp_lport, name, 1);
+ if (!Lflag)
+ inet6print(&inp->in6p_faddr,
+ (int)inp->inp_fport, name, 0);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ } else {
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+ name, 0);
+ if (!Lflag)
+ inetprint(&inp->inp_faddr,
+ (int)inp->inp_fport, name,
+ inp->inp_lport !=
+ inp->inp_fport);
+ }
+#ifdef INET6
+ else if (inp->inp_vflag & INP_IPV6) {
+ inet6print(&inp->in6p_laddr,
+ (int)inp->inp_lport, name, 0);
+ if (!Lflag)
+ inet6print(&inp->in6p_faddr,
+ (int)inp->inp_fport, name,
+ inp->inp_lport !=
+ inp->inp_fport);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ }
+ if (istcp && !Lflag) {
+ if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
+ printf("%-11d", tp->t_state);
+ else {
+ printf("%-11s", tcpstates[tp->t_state]);
+#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
+ /* Show T/TCP `hidden state' */
+ if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
+ putchar('*');
+#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
+ }
+ }
+ if (!istcp)
+ printf("%-11s", " ");
+ if (bflag > 0) {
+ int i;
+ u_int64_t rxbytes = 0;
+ u_int64_t txbytes = 0;
+
+ for (i = 0; i < SO_TC_MAX; i++) {
+ rxbytes += so_stat->xst_tc_stats[i].rxbytes;
+ txbytes += so_stat->xst_tc_stats[i].txbytes;
+ }
+
+ printf(" %10llu %10llu", rxbytes, txbytes);
+ }
+ if (prioflag >= 0) {
+ printf(" %10llu %10llu",
+ prioflag < SO_TC_MAX ? so_stat->xst_tc_stats[prioflag].rxbytes : 0,
+ prioflag < SO_TC_MAX ? so_stat->xst_tc_stats[prioflag].txbytes : 0);
+ }
+ putchar('\n');
+ }
+ if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
+ if (oxig->xig_count > xig->xig_count) {
+ printf("Some %s sockets may have been deleted.\n",
+ name);
+ } else if (oxig->xig_count < xig->xig_count) {
+ printf("Some %s sockets may have been created.\n",
+ name);
+ } else {
+ printf("Some %s sockets may have been created or deleted",
+ name);
+ }
+ }
+ free(buf);
+}
+
+#else /* TARGET_OS_EMBEDDED */
+
+void
+protopr(uint32_t proto, /* for sysctl version we pass proto # */
+ char *name, int af)
+{
+ int istcp;
+ static int first = 1;
+ char *buf;
+ const char *mibvar;
+ struct xinpgen *xig, *oxig;
struct tcpcb *tp = NULL;
struct inpcb *inp;
struct xsocket *so;
-#endif
size_t len;
istcp = 0;
tcp_done = 1;
#endif
istcp = 1;
-#if !TARGET_OS_EMBEDDED
- mibvar = "net.inet.tcp.pcblist64";
-#else
mibvar = "net.inet.tcp.pcblist";
-#endif
- break;
+ break;
case IPPROTO_UDP:
#ifdef INET6
if (udp_done != 0)
else
udp_done = 1;
#endif
-#if !TARGET_OS_EMBEDDED
- mibvar = "net.inet.udp.pcblist64";
-#else
mibvar = "net.inet.udp.pcblist";
-#endif
- break;
+ break;
case IPPROTO_DIVERT:
-#if !TARGET_OS_EMBEDDED
- mibvar = "net.inet.divert.pcblist64";
-#else
mibvar = "net.inet.divert.pcblist";
-#endif
- break;
+ break;
default:
-#if !TARGET_OS_EMBEDDED
- mibvar = "net.inet.raw.pcblist64";
-#else
mibvar = "net.inet.raw.pcblist";
-#endif
- break;
+ break;
}
len = 0;
if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
return;
}
- /*
- * Bail-out to avoid logic error in the loop below when
- * there is in fact no more control block to process
- */
- if (len <= sizeof(struct xinpgen)) {
- free(buf);
- return;
- }
-
+ /*
+ * Bail-out to avoid logic error in the loop below when
+ * there is in fact no more control block to process
+ */
+ if (len <= sizeof(struct xinpgen)) {
+ free(buf);
+ return;
+ }
+
oxig = xig = (struct xinpgen *)buf;
for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
xig->xig_len > sizeof(struct xinpgen);
xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
if (istcp) {
-#if !TARGET_OS_EMBEDDED
- tp = (struct xtcpcb64 *)xig;
- inp = &tp->xt_inpcb;
- so = &inp->xi_socket;
-#else
tp = &((struct xtcpcb *)xig)->xt_tp;
inp = &((struct xtcpcb *)xig)->xt_inp;
so = &((struct xtcpcb *)xig)->xt_socket;
-#endif
} else {
-#if !TARGET_OS_EMBEDDED
- inp = (struct xinpcb64 *)xig;
- so = &inp->xi_socket;
-#else
inp = &((struct xinpcb *)xig)->xi_inp;
so = &((struct xinpcb *)xig)->xi_socket;
-#endif
}
/* Ignore sockets for protocols other than the desired one. */
"Current listen queue sizes (qlen/incqlen/maxqlen)");
putchar('\n');
if (Aflag)
-#if !TARGET_OS_EMBEDDED
- printf("%-16.16s ", "Socket");
-#else
printf("%-8.8s ", "Socket");
-#endif
if (Lflag)
printf("%-14.14s %-22.22s\n",
"Listen", "Local Address");
}
if (Aflag) {
if (istcp)
-#if !TARGET_OS_EMBEDDED
- printf("%16lx ", (u_long)inp->inp_ppcb);
-#else
printf("%8lx ", (u_long)inp->inp_ppcb);
-
-#endif
else
-#if !TARGET_OS_EMBEDDED
- printf("%16lx ", (u_long)so->so_pcb);
-#else
printf("%8lx ", (u_long)so->so_pcb);
-#endif
}
if (Lflag) {
char buf[15];
}
free(buf);
}
+#endif /* TARGET_OS_EMBEDDED */
/*
* Dump TCP statistics structure.
"\t%u segment%s updated rtt (of %u attempt%s)\n");
p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n");
p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n");
+ p(tcps_rxtfindrop, "\t\t%u connection%s dropped after retransmitting FIN\n");
p(tcps_persisttimeo, "\t%u persist timeout%s\n");
p(tcps_persistdrop, "\t\t%u connection%s dropped by persist timeout\n");
p(tcps_keeptimeo, "\t%u keepalive timeout%s\n");
p(ips_cantfrag, "\t%u datagram%s that can't be fragmented\n");
p(ips_nogif, "\t%u tunneling packet%s that can't find gif\n");
p(ips_badaddr, "\t%u datagram%s with bad address in header\n");
+ p(ips_pktdropcntrl, "\t%u packet%s dropped due to no bufs for control data\n");
if (interval > 0)
bcopy(&ipstat, &pipstat, len);
void
igmp_stats(uint32_t off , char *name, int af )
{
- static struct igmpstat pigmpstat;
- struct igmpstat igmpstat;
+ static struct igmpstat_v3 pigmpstat;
+ struct igmpstat_v3 igmpstat;
size_t len = sizeof igmpstat;
- if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) {
- warn("sysctl: net.inet.igmp.stats");
+ if (sysctlbyname("net.inet.igmp.v3stats", &igmpstat, &len, 0, 0) < 0) {
+ warn("sysctl: net.inet.igmp.v3stats");
return;
}
+ if (igmpstat.igps_version != IGPS_VERSION_3) {
+ warnx("%s: version mismatch (%d != %d)", __func__,
+ igmpstat.igps_version, IGPS_VERSION_3);
+ }
+ if (igmpstat.igps_len != IGPS_VERSION3_LEN) {
+ warnx("%s: size mismatch (%d != %d)", __func__,
+ igmpstat.igps_len, IGPS_VERSION3_LEN);
+ }
+
printf("%s:\n", name);
-#define IGMPDIFF(f) (igmpstat.f - pigmpstat.f)
-#define p(f, m) if (IGMPDIFF(f) || sflag <= 1) \
+#define IGMPDIFF(f) ((uintmax_t)(igmpstat.f - pigmpstat.f))
+#define p64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
printf(m, IGMPDIFF(f), plural(IGMPDIFF(f)))
-#define py(f, m) if (IGMPDIFF(f) || sflag <= 1) \
+#define py64(f, m) if (IGMPDIFF(f) || sflag <= 1) \
printf(m, IGMPDIFF(f), IGMPDIFF(f) != 1 ? "ies" : "y")
- p(igps_rcv_total, "\t%u message%s received\n");
- p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
- p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
- py(igps_rcv_queries, "\t%u membership quer%s received\n");
- py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
- p(igps_rcv_reports, "\t%u membership report%s received\n");
- p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
- p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
- p(igps_snd_reports, "\t%u membership report%s sent\n");
+
+ p64(igps_rcv_total, "\t%ju message%s received\n");
+ p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
+ p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n");
+ p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n");
+ py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n");
+ py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n");
+ py64(igps_rcv_badqueries,
+ "\t%ju membership quer%s received with invalid field(s)\n");
+ py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n");
+ py64(igps_rcv_group_queries, "\t%ju group quer%s received\n");
+ py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n");
+ py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n");
+ p64(igps_rcv_reports, "\t%ju membership report%s received\n");
+ p64(igps_rcv_badreports,
+ "\t%ju membership report%s received with invalid field(s)\n");
+ p64(igps_rcv_ourreports,
+"\t%ju membership report%s received for groups to which we belong\n");
+ p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n");
+ p64(igps_snd_reports, "\t%ju membership report%s sent\n");
if (interval > 0)
bcopy(&igmpstat, &pigmpstat, len);
#undef IGMPDIFF
-#undef p
-#undef py
+#undef p64
+#undef py64
}
/*
int width;
if (Wflag)
- sprintf(line, "%s.", inetname(in));
+ snprintf(line, sizeof(line), "%s.", inetname(in));
else
- sprintf(line, "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
+ snprintf(line, sizeof(line), "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
cp = index(line, '\0');
if (!numeric_port && port)
#ifdef _SERVICE_CACHE_
sp = getservbyport((int)port, proto);
#endif
if (sp || port == 0)
- sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
+ snprintf(cp, sizeof(line) - (cp - line), "%.15s ", sp ? sp->s_name : "*");
else
- sprintf(cp, "%d ", ntohs((u_short)port));
+ snprintf(cp, sizeof(line) - (cp - line), "%d ", ntohs((u_short)port));
width = (Aflag && !Wflag) ? 18 : 22;
if (Wflag)
printf("%-*s ", width, line);
}
}
if (inp->s_addr == INADDR_ANY)
- strcpy(line, "*");
+ strlcpy(line, "*", sizeof(line));
else if (cp) {
strncpy(line, cp, sizeof(line) - 1);
line[sizeof(line) - 1] = '\0';
} else {
inp->s_addr = ntohl(inp->s_addr);
#define C(x) ((u_int)((x) & 0xff))
- sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
+ snprintf(line, sizeof(line), "%u.%u.%u.%u", C(inp->s_addr >> 24),
C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
}
return (line);
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
"no next header",
"destination option",
"#61",
- "#62",
+ "mobility",
"#63",
"#64",
"#65",
p1a(ip6s_forward_cachehit, "\t%llu forward cache hit\n");
p1a(ip6s_forward_cachemiss, "\t%llu forward cache miss\n");
-
+ p(ip6s_pktdropcntrl, "\t%llu packet%s dropped due to no bufs for control data\n");
+
if (interval > 0)
bcopy(&ip6stat, &pip6stat, len);
return;
}
- strcpy(ifr.ifr_name, ifname);
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
printf("ip6 on %s:\n", ifr.ifr_name);
if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
"echo",
"echo reply",
"multicast listener query",
- "multicast listener report",
- "multicast listener done",
+ "MLDv1 listener report",
+ "MLDv1 listener done",
"router solicitation",
"router advertisement",
"neighbor solicitation",
"node information reply",
"inverse neighbor solicitation",
"inverse neighbor advertisement",
- "#143",
+ "MLDv2 listener report",
"#144",
"#145",
"#146",
return;
}
- strcpy(ifr.ifr_name, ifname);
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
printf("icmp6 on %s:\n", ifr.ifr_name);
if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
char line[80], *cp;
int width;
- sprintf(line, "%.*s.", lflag ? 39 :
+ snprintf(line, sizeof(line), "%.*s.", lflag ? 39 :
(Aflag && !numeric) ? 12 : 16, inet6name(in6));
cp = index(line, '\0');
if (!numeric && port)
GETSERVBYPORT6(port, proto, sp);
if (sp || port == 0)
- sprintf(cp, "%.8s", sp ? sp->s_name : "*");
+ snprintf(cp, sizeof(line) - (cp - line), "%.8s", sp ? sp->s_name : "*");
else
- sprintf(cp, "%d", ntohs((u_short)port));
+ snprintf(cp, sizeof(line) - (cp - line), "%d", ntohs((u_short)port));
width = lflag ? 45 : Aflag ? 18 : 22;
printf("%-*.*s ", width, width, line);
}
first = 0;
if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
(cp = index(domain, '.')))
- (void) strcpy(domain, cp + 1);
+ (void) strlcpy(domain, cp + 1, sizeof(domain));
else
domain[0] = 0;
}
}
}
if (IN6_IS_ADDR_UNSPECIFIED(in6p))
- strcpy(line, "*");
+ strlcpy(line, "*", sizeof(line));
else if (cp)
strlcpy(line, cp, sizeof(line));
else {
sin6.sin6_addr = *in6p;
if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
+ IN6_IS_ADDR_MC_NODELOCAL(in6p) ||
IN6_IS_ADDR_MC_LINKLOCAL(in6p)) {
sin6.sin6_scope_id =
ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
/*
- * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
int mflag; /* show memory stats */
int nflag; /* show addresses numerically */
static int pflag; /* show given protocol */
-int prioflag; /* show packet priority statistics */
+int prioflag = -1; /* show packet priority statistics */
+int Rflag; /* show reachability information */
int rflag; /* show routing tables (or routing stats) */
int sflag; /* show protocol statistics */
int tflag; /* show i/f watchdog timers */
+int vflag; /* more verbose */
int Wflag; /* wide display */
int interval; /* repeat interval for i/f stats */
af = AF_UNSPEC;
- while ((ch = getopt(argc, argv, "Aabdf:gI:iLlmnP:p:rRstuWw:")) != -1)
+ while ((ch = getopt(argc, argv, "Aabdf:gI:iLlmnP:p:rRstuvWw:")) != -1)
switch(ch) {
case 'A':
Aflag = 1;
}
pflag = 1;
break;
+ case 'R':
+ Rflag = 1;
+ break;
case 'r':
rflag = 1;
break;
case 'u':
af = AF_UNIX;
break;
+ case 'v':
+ vflag++;
+ break;
case 'W':
Wflag = 1;
break;
mbpr();
exit(0);
}
- if (iflag && !sflag) {
- intpr(NULL);
+ if (iflag && !sflag && !gflag) {
+ if (Rflag)
+ intpr_ri(NULL);
+ else
+ intpr(NULL);
exit(0);
}
if (rflag) {
#define NETSTAT_USAGE "\
Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\
netstat [-gilns] [-f address_family]\n\
- netstat -i | -I interface [-w wait] [-abdgt]\n\
+ netstat -i | -I interface [-w wait] [-abdgRt]\n\
netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\
netstat -i | -I interface -s [-f address_family | -p protocol]\n\
netstat -m [-m]\n\
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <sys/sysctl.h>
#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "netstat.h"
mb_stat_t *mb_stat;
unsigned int njcl, njclbytes;
+mleak_stat_t *mleak_stat;
+struct mleak_table table;
#define KERN_IPC_MB_STAT "kern.ipc.mb_stat"
#define KERN_IPC_NJCL "kern.ipc.njcl"
#define KERN_IPC_NJCL_BYTES "kern.ipc.njclbytes"
+#define KERN_IPC_MLEAK_TABLE "kern.ipc.mleak_table"
+#define KERN_IPC_MLEAK_TOP_TRACE "kern.ipc.mleak_top_trace"
#define MB_STAT_HDR1 "\
class buf active ctotal total cache cached uncached memory\n\
---------- -------- -------- -------- -------- -------- --------\n\
"
+#define MB_LEAK_HDR "\n\
+ calltrace [1] calltrace [2] calltrace [3] calltrace [4] calltrace [5] \n\
+ ------------------ ------------------ ------------------ ------------------ ------------------ \n\
+"
+
+#define MB_LEAK_SPACING " "
static const char *mbpr_state(int);
static const char *mbpr_mem(u_int32_t);
static int mbpr_getdata(void);
printf("%u calls to drain routines\n", (unsigned int)mbstat.m_drain);
free(mb_stat);
+ mb_stat = NULL;
+
+ if (mleak_stat != NULL) {
+ mleak_trace_stat_t *mltr;
+
+ printf("\nmbuf leak detection table:\n");
+ printf("\ttotal captured: %u (one per %u)\n"
+ "\ttotal allocs outstanding: %llu\n"
+ "\tnew hash recorded: %llu allocs, %llu traces\n"
+ "\thash collisions: %llu allocs, %llu traces\n"
+ "\toverwrites: %llu allocs, %llu traces\n"
+ "\tlock conflicts: %llu\n\n",
+ table.mleak_capture / table.mleak_sample_factor,
+ table.mleak_sample_factor,
+ table.outstanding_allocs,
+ table.alloc_recorded, table.trace_recorded,
+ table.alloc_collisions, table.trace_collisions,
+ table.alloc_overwrites, table.trace_overwrites,
+ table.total_conflicts);
+
+ printf("top %d outstanding traces:\n", mleak_stat->ml_cnt);
+ for (i = 0; i < mleak_stat->ml_cnt; i++) {
+ mltr = &mleak_stat->ml_trace[i];
+ printf("[%d] %llu outstanding alloc(s), "
+ "%llu hit(s), %llu collision(s)\n", (i + 1),
+ mltr->mltr_allocs, mltr->mltr_hitcount,
+ mltr->mltr_collisions);
+ }
+
+ printf(MB_LEAK_HDR);
+ for (i = 0; i < MLEAK_STACK_DEPTH; i++) {
+ int j;
+
+ printf("%2d: ", (i + 1));
+ for (j = 0; j < mleak_stat->ml_cnt; j++) {
+ mltr = &mleak_stat->ml_trace[j];
+ if (i < mltr->mltr_depth) {
+ if (mleak_stat->ml_isaddr64) {
+ printf("0x%0llx ",
+ mltr->mltr_addr[i]);
+ } else {
+ printf("0x%08x ",
+ (u_int32_t)mltr->mltr_addr[i]);
+ }
+ } else {
+ printf(MB_LEAK_SPACING);
+ }
+ }
+ printf("\n");
+ }
+ free(mleak_stat);
+ mleak_stat = NULL;
+ }
}
static const char *
goto done;
}
+ /* mbuf leak detection! */
+ if (mflag > 3) {
+ errno = 0;
+ len = sizeof (table);
+ if (sysctlbyname(KERN_IPC_MLEAK_TABLE, &table, &len, 0, 0) ==
+ -1 && errno != ENXIO) {
+ (void) fprintf(stderr, "error %d getting %s\n", errno,
+ KERN_IPC_MLEAK_TABLE);
+ goto done;
+ } else if (errno == ENXIO) {
+ (void) fprintf(stderr, "mbuf leak detection is not "
+ "enabled in the kernel.\n");
+ goto skip;
+ }
+
+ if (sysctlbyname(KERN_IPC_MLEAK_TOP_TRACE, NULL, &len,
+ 0, 0) == -1) {
+ (void) fprintf(stderr, "Error retrieving length for "
+ "%s: %d\n", KERN_IPC_MB_STAT, errno);
+ goto done;
+ }
+
+ mleak_stat = calloc(1, len);
+ if (mleak_stat == NULL) {
+ (void) fprintf(stderr, "Error allocating %lu bytes "
+ "for sysctl data\n", len);
+ goto done;
+ }
+
+ if (sysctlbyname(KERN_IPC_MLEAK_TOP_TRACE, mleak_stat, &len,
+ 0, 0) == -1) {
+ (void) fprintf(stderr, "error %d getting %s\n", errno,
+ KERN_IPC_MLEAK_TOP_TRACE);
+ goto done;
+ }
+ }
+
+skip:
len = sizeof (njcl);
(void) sysctlbyname(KERN_IPC_NJCL, &njcl, &len, 0, 0);
len = sizeof (njclbytes);
error = 0;
done:
- if (error != 0 && mb_stat != NULL)
+ if (error != 0 && mb_stat != NULL) {
free(mb_stat);
+ mb_stat = NULL;
+ }
+
+ if (error != 0 && mleak_stat != NULL) {
+ free(mleak_stat);
+ mleak_stat = NULL;
+ }
return (error);
}
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
+#include <netinet/igmp_var.h>
+#include <netinet6/mld6_var.h>
#include <arpa/inet.h>
#include <netdb.h>
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
#endif
-struct ifmaddrs {
- struct ifmaddrs *ifma_next;
- struct sockaddr *ifma_name;
- struct sockaddr *ifma_addr;
- struct sockaddr *ifma_lladdr;
-};
+//struct ifmaddrs {
+// struct ifmaddrs *ifma_next;
+// struct sockaddr *ifma_name;
+// struct sockaddr *ifma_addr;
+// struct sockaddr *ifma_lladdr;
+//};
void ifmalist_dump_af(const struct ifmaddrs * const ifmap, int const af);
+static int ifmalist_dump_mcstat(struct ifmaddrs *);
+static void in_ifinfo(struct igmp_ifinfo *);
+static const char *inm_mode(u_int);
+static void inm_print_sources_sysctl(uint32_t, struct in_addr);
+#ifdef INET6
+static void in6_ifinfo(struct mld_ifinfo *);
+static void in6m_print_sources_sysctl(uint32_t, struct in6_addr *);
+static const char *inet6_n2a(struct in6_addr *);
+#endif
+static void printb(const char *, unsigned int, const char *);
+static const char *sdl_addr_to_hex(const struct sockaddr_dl *, char *, int);
+
+extern char *routename6(struct sockaddr_in6 *);
+
+#define sa_equal(a1, a2) \
+ (bcmp((a1), (a2), ((a1))->sa_len) == 0)
+
+#define sa_dl_equal(a1, a2) \
+ ((((struct sockaddr_dl *)(a1))->sdl_len == \
+ ((struct sockaddr_dl *)(a2))->sdl_len) && \
+ (bcmp(LLADDR((struct sockaddr_dl *)(a1)), \
+ LLADDR((struct sockaddr_dl *)(a2)), \
+ ((struct sockaddr_dl *)(a1))->sdl_alen) == 0))
#define SALIGN (sizeof(uint32_t) - 1)
#define SA_RLEN(sa) (sa ? ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \
#define MAX_SYSCTL_TRY 5
#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA)
-int getifmaddrs(struct ifmaddrs **);
-void freeifmaddrs(struct ifmaddrs *);
-
-
-int
-getifmaddrs(struct ifmaddrs **pif)
-{
- int icnt = 1;
- int dcnt = 0;
- int ntry = 0;
- size_t len;
- size_t needed;
- int mib[6];
- int i;
- char *buf;
- char *data;
- char *next;
- char *p;
- struct ifma_msghdr2 *ifmam;
- struct ifmaddrs *ifa, *ift;
- struct rt_msghdr *rtm;
- struct sockaddr *sa;
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0; /* protocol */
- mib[3] = 0; /* wildcard address family */
- mib[4] = NET_RT_IFLIST2;
- mib[5] = 0; /* no flags */
- do {
- if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
- return (-1);
- if ((buf = malloc(needed)) == NULL)
- return (-1);
- if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
- if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
- free(buf);
- return (-1);
- }
- free(buf);
- buf = NULL;
- }
- } while (buf == NULL);
-
- for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
- rtm = (struct rt_msghdr *)(void *)next;
- if (rtm->rtm_version != RTM_VERSION)
- continue;
- switch (rtm->rtm_type) {
- case RTM_NEWMADDR2:
- ifmam = (struct ifma_msghdr2 *)(void *)rtm;
- if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
- break;
- icnt++;
- p = (char *)(ifmam + 1);
- for (i = 0; i < RTAX_MAX; i++) {
- if ((RTA_MASKS & ifmam->ifmam_addrs &
- (1 << i)) == 0)
- continue;
- sa = (struct sockaddr *)(void *)p;
- len = SA_RLEN(sa);
- dcnt += len;
- p += len;
- }
- break;
- }
- }
-
- data = malloc(sizeof(struct ifmaddrs) * icnt + dcnt);
- if (data == NULL) {
- free(buf);
- return (-1);
- }
-
- ifa = (struct ifmaddrs *)(void *)data;
- data += sizeof(struct ifmaddrs) * icnt;
-
- memset(ifa, 0, sizeof(struct ifmaddrs) * icnt);
- ift = ifa;
-
- for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
- rtm = (struct rt_msghdr *)(void *)next;
- if (rtm->rtm_version != RTM_VERSION)
- continue;
-
- switch (rtm->rtm_type) {
- case RTM_NEWMADDR2:
- ifmam = (struct ifma_msghdr2 *)(void *)rtm;
- if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
- break;
-
- p = (char *)(ifmam + 1);
- for (i = 0; i < RTAX_MAX; i++) {
- if ((RTA_MASKS & ifmam->ifmam_addrs &
- (1 << i)) == 0)
- continue;
- sa = (struct sockaddr *)(void *)p;
- len = SA_RLEN(sa);
- switch (i) {
- case RTAX_GATEWAY:
- ift->ifma_lladdr =
- (struct sockaddr *)(void *)data;
- memcpy(data, p, len);
- data += len;
- break;
-
- case RTAX_IFP:
- ift->ifma_name =
- (struct sockaddr *)(void *)data;
- memcpy(data, p, len);
- data += len;
- break;
-
- case RTAX_IFA:
- ift->ifma_addr =
- (struct sockaddr *)(void *)data;
- memcpy(data, p, len);
- data += len;
- break;
-
- default:
- data += len;
- break;
- }
- p += len;
- }
- ift->ifma_next = ift + 1;
- ift = ift->ifma_next;
- break;
- }
- }
-
- free(buf);
-
- if (ift > ifa) {
- ift--;
- ift->ifma_next = NULL;
- *pif = ifa;
- } else {
- *pif = NULL;
- free(ifa);
- }
- return (0);
-}
-
-void
-freeifmaddrs(struct ifmaddrs *ifmp)
-{
-
- free(ifmp);
-}
-
void
ifmalist_dump_af(const struct ifmaddrs * const ifmap, int const af)
{
const struct ifmaddrs *ifma;
sockunion_t *psa;
char myifname[IFNAMSIZ];
-#ifdef INET6
- char addrbuf[INET6_ADDRSTRLEN];
-#endif
char *pcolon;
char *pafname, *pifname, *plladdr = NULL, *pgroup = NULL;
-#ifdef INET6
- void *in6addr;
-#endif
switch (af) {
case AF_INET:
break;
#ifdef INET6
case AF_INET6:
- in6addr = &psa->sin6.sin6_addr;
- inet_ntop(psa->sa.sa_family, in6addr, addrbuf,
- sizeof(addrbuf));
- pgroup = addrbuf;
+ pgroup = routename6(&(psa->sin6));
break;
#endif
case AF_LINK:
fputs("\n", stdout);
ifmalist_dump_af(ifmap, AF_INET6);
#endif
+ if (sflag) {
+ fputs("\n", stdout);
+ ifmalist_dump_mcstat(ifmap);
+ }
freeifmaddrs(ifmap);
}
+static int
+ifmalist_dump_mcstat(struct ifmaddrs *ifmap)
+{
+ char thisifname[IFNAMSIZ];
+ char addrbuf[NI_MAXHOST];
+ struct ifaddrs *ifap, *ifa;
+ struct ifmaddrs *ifma;
+ sockunion_t lastifasa;
+ sockunion_t *psa, *pgsa, *pllsa, *pifasa;
+ char *pcolon;
+ char *pafname;
+ uint32_t lastifindex, thisifindex;
+ int error;
+ uint32_t ifindex = 0;
+
+ if (interface != NULL)
+ ifindex = if_nametoindex(interface);
+
+ error = 0;
+ ifap = NULL;
+ lastifindex = 0;
+ thisifindex = 0;
+ lastifasa.ss.ss_family = AF_UNSPEC;
+
+ if (getifaddrs(&ifap) != 0) {
+ warn("getifmaddrs");
+ return (-1);
+ }
+
+ for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
+ error = 0;
+ if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
+ continue;
+
+ psa = (sockunion_t *)ifma->ifma_name;
+ if (psa->sa.sa_family != AF_LINK) {
+ fprintf(stderr,
+ "WARNING: Kernel returned invalid data.\n");
+ error = -1;
+ break;
+ }
+
+ /* Filter on interface name. */
+ thisifindex = psa->sdl.sdl_index;
+ if (ifindex != 0 && thisifindex != ifindex)
+ continue;
+
+ /* Filter on address family. */
+ pgsa = (sockunion_t *)ifma->ifma_addr;
+ if (af != 0 && pgsa->sa.sa_family != af)
+ continue;
+
+ strlcpy(thisifname, link_ntoa(&psa->sdl), IFNAMSIZ);
+ pcolon = strchr(thisifname, ':');
+ if (pcolon)
+ *pcolon = '\0';
+
+ /* Only print the banner for the first ifmaddrs entry. */
+ if (lastifindex == 0 || lastifindex != thisifindex) {
+ lastifindex = thisifindex;
+ fprintf(stdout, "%s:\n", thisifname);
+ }
+
+ /*
+ * Currently, multicast joins only take place on the
+ * primary IPv4 address, and only on the link-local IPv6
+ * address, as per IGMPv2/3 and MLDv1/2 semantics.
+ * Therefore, we only look up the primary address on
+ * the first pass.
+ */
+ pifasa = NULL;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if ((strcmp(ifa->ifa_name, thisifname) != 0) ||
+ (ifa->ifa_addr == NULL) ||
+ (ifa->ifa_addr->sa_family != pgsa->sa.sa_family))
+ continue;
+ /*
+ * For AF_INET6 only the link-local address should
+ * be returned. If built without IPv6 support,
+ * skip this address entirely.
+ */
+ pifasa = (sockunion_t *)ifa->ifa_addr;
+ if (pifasa->sa.sa_family == AF_INET6
+#ifdef INET6
+ && !IN6_IS_ADDR_LINKLOCAL(&pifasa->sin6.sin6_addr)
+#endif
+ ) {
+ pifasa = NULL;
+ continue;
+ }
+ break;
+ }
+ if (pifasa == NULL)
+ continue; /* primary address not found */
+
+ if (!vflag && pifasa->sa.sa_family == AF_LINK)
+ continue;
+
+ /* Parse and print primary address, if not already printed. */
+ if (lastifasa.ss.ss_family == AF_UNSPEC ||
+ ((lastifasa.ss.ss_family == AF_LINK &&
+ !sa_dl_equal(&lastifasa.sa, &pifasa->sa)) ||
+ !sa_equal(&lastifasa.sa, &pifasa->sa))) {
+
+ switch (pifasa->sa.sa_family) {
+ case AF_INET:
+ pafname = "inet";
+ break;
+ case AF_INET6:
+ pafname = "inet6";
+ break;
+ case AF_LINK:
+ pafname = "link";
+ break;
+ default:
+ pafname = "unknown";
+ break;
+ }
+
+ switch (pifasa->sa.sa_family) {
+ case AF_INET6:
+#ifdef INET6
+ {
+ const char *p =
+ inet6_n2a(&pifasa->sin6.sin6_addr);
+ strlcpy(addrbuf, p, sizeof(addrbuf));
+ break;
+ }
+#else
+ /* FALLTHROUGH */
+#endif
+ case AF_INET:
+ error = getnameinfo(&pifasa->sa,
+ pifasa->sa.sa_len,
+ addrbuf, sizeof(addrbuf), NULL, 0,
+ NI_NUMERICHOST);
+ if (error)
+ printf("getnameinfo: %s\n",
+ gai_strerror(error));
+ break;
+ case AF_LINK: {
+ (void) sdl_addr_to_hex(&pifasa->sdl, addrbuf,
+ sizeof (addrbuf));
+ break;
+ }
+ default:
+ addrbuf[0] = '\0';
+ break;
+ }
+
+ fprintf(stdout, "\t%s %s\n", pafname, addrbuf);
+ /*
+ * Print per-link IGMP information, if available.
+ */
+ if (pifasa->sa.sa_family == AF_INET) {
+ struct igmp_ifinfo igi;
+ size_t mibsize, len;
+ int mib[5];
+
+ mibsize = sizeof(mib) / sizeof(mib[0]);
+ if (sysctlnametomib("net.inet.igmp.ifinfo",
+ mib, &mibsize) == -1) {
+ perror("sysctlnametomib");
+ goto next_ifnet;
+ }
+ mib[mibsize] = thisifindex;
+ len = sizeof(struct igmp_ifinfo);
+ if (sysctl(mib, mibsize + 1, &igi, &len, NULL,
+ 0) == -1) {
+ perror("sysctl net.inet.igmp.ifinfo");
+ goto next_ifnet;
+ }
+ in_ifinfo(&igi);
+ }
+#ifdef INET6
+ /*
+ * Print per-link MLD information, if available.
+ */
+ if (pifasa->sa.sa_family == AF_INET6) {
+ struct mld_ifinfo mli;
+ size_t mibsize, len;
+ int mib[5];
+
+ mibsize = sizeof(mib) / sizeof(mib[0]);
+ if (sysctlnametomib("net.inet6.mld.ifinfo",
+ mib, &mibsize) == -1) {
+ perror("sysctlnametomib");
+ goto next_ifnet;
+ }
+ mib[mibsize] = thisifindex;
+ len = sizeof(struct mld_ifinfo);
+ if (sysctl(mib, mibsize + 1, &mli, &len, NULL,
+ 0) == -1) {
+ perror("sysctl net.inet6.mld.ifinfo");
+ goto next_ifnet;
+ }
+ in6_ifinfo(&mli);
+ }
+#endif /* INET6 */
+#if defined(INET6)
+next_ifnet:
+#endif
+ lastifasa = *pifasa;
+ }
+
+ /* Print this group address. */
+#ifdef INET6
+ if (pgsa->sa.sa_family == AF_INET6) {
+ const char *p = inet6_n2a(&pgsa->sin6.sin6_addr);
+ strlcpy(addrbuf, p, sizeof(addrbuf));
+ } else
+#endif
+ if (pgsa->sa.sa_family == AF_INET) {
+ error = getnameinfo(&pgsa->sa, pgsa->sa.sa_len,
+ addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
+ if (error)
+ printf("getnameinfo: %s\n",
+ gai_strerror(error));
+ } else {
+ (void) sdl_addr_to_hex(&pgsa->sdl, addrbuf,
+ sizeof (addrbuf));
+ }
+
+ fprintf(stdout, "\t\tgroup %s", addrbuf);
+ if (pgsa->sa.sa_family == AF_INET) {
+ inm_print_sources_sysctl(thisifindex,
+ pgsa->sin.sin_addr);
+ }
+#ifdef INET6
+ if (pgsa->sa.sa_family == AF_INET6) {
+ in6m_print_sources_sysctl(thisifindex,
+ &pgsa->sin6.sin6_addr);
+ }
+#endif
+ fprintf(stdout, "\n");
+
+ /* Link-layer mapping, if present. */
+ pllsa = (sockunion_t *)ifma->ifma_lladdr;
+ if (pllsa != NULL) {
+ (void) sdl_addr_to_hex(&pllsa->sdl, addrbuf,
+ sizeof (addrbuf));
+ fprintf(stdout, "\t\t\tmcast-macaddr %s\n", addrbuf);
+ }
+ }
+
+ if (ifap != NULL)
+ freeifaddrs(ifap);
+
+ return (error);
+}
+
+static void
+in_ifinfo(struct igmp_ifinfo *igi)
+{
+
+ printf("\t");
+ switch (igi->igi_version) {
+ case IGMP_VERSION_1:
+ case IGMP_VERSION_2:
+ case IGMP_VERSION_3:
+ printf("igmpv%d", igi->igi_version);
+ break;
+ default:
+ printf("igmpv?(%d)", igi->igi_version);
+ break;
+ }
+ printb(" flags", igi->igi_flags, "\020\1SILENT\2LOOPBACK");
+ if (igi->igi_version == IGMP_VERSION_3) {
+ printf(" rv %u qi %u qri %u uri %u",
+ igi->igi_rv, igi->igi_qi, igi->igi_qri, igi->igi_uri);
+ }
+ if (vflag >= 2) {
+ printf(" v1timer %u v2timer %u v3timer %u",
+ igi->igi_v1_timer, igi->igi_v2_timer, igi->igi_v3_timer);
+ }
+ printf("\n");
+}
+
+static const char *inm_modes[] = {
+ "undefined",
+ "include",
+ "exclude",
+};
+
+static const char *
+inm_mode(u_int mode)
+{
+
+ if (mode >= MCAST_UNDEFINED && mode <= MCAST_EXCLUDE)
+ return (inm_modes[mode]);
+ return (NULL);
+}
+
+/*
+ * Retrieve per-group source filter mode and lists via sysctl.
+ */
+static void
+inm_print_sources_sysctl(uint32_t ifindex, struct in_addr gina)
+{
+#define MAX_SYSCTL_TRY 5
+ int mib[7];
+ int ntry = 0;
+ size_t mibsize;
+ size_t len;
+ size_t needed;
+ size_t cnt;
+ int i;
+ char *buf;
+ struct in_addr *pina;
+ uint32_t *p;
+ uint32_t fmode;
+ const char *modestr;
+
+ mibsize = sizeof(mib) / sizeof(mib[0]);
+ if (sysctlnametomib("net.inet.ip.mcast.filters", mib, &mibsize) == -1) {
+ perror("sysctlnametomib");
+ return;
+ }
+
+ needed = 0;
+ mib[5] = ifindex;
+ mib[6] = gina.s_addr; /* 32 bits wide */
+ mibsize = sizeof(mib) / sizeof(mib[0]);
+ do {
+ if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
+ perror("sysctl net.inet.ip.mcast.filters");
+ return;
+ }
+ if ((buf = malloc(needed)) == NULL) {
+ perror("malloc");
+ return;
+ }
+ if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ perror("sysctl");
+ goto out_free;
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ len = needed;
+ if (len < sizeof(uint32_t)) {
+ perror("sysctl");
+ goto out_free;
+ }
+
+ p = (uint32_t *)buf;
+ fmode = *p++;
+ len -= sizeof(uint32_t);
+
+ modestr = inm_mode(fmode);
+ if (modestr)
+ printf(" mode %s", modestr);
+ else
+ printf(" mode (%u)", fmode);
+
+ if (vflag == 0)
+ goto out_free;
+
+ cnt = len / sizeof(struct in_addr);
+ pina = (struct in_addr *)p;
+
+ for (i = 0; i < cnt; i++) {
+ if (i == 0)
+ printf(" srcs ");
+ fprintf(stdout, "%s%s", (i == 0 ? "" : ","),
+ inet_ntoa(*pina++));
+ len -= sizeof(struct in_addr);
+ }
+ if (len > 0) {
+ fprintf(stderr, "warning: %u trailing bytes from %s\n",
+ (unsigned int)len, "net.inet.ip.mcast.filters");
+ }
+
+out_free:
+ free(buf);
+#undef MAX_SYSCTL_TRY
+}
+
+#ifdef INET6
+
+static void
+in6_ifinfo(struct mld_ifinfo *mli)
+{
+
+ printf("\t");
+ switch (mli->mli_version) {
+ case MLD_VERSION_1:
+ case MLD_VERSION_2:
+ printf("mldv%d", mli->mli_version);
+ break;
+ default:
+ printf("mldv?(%d)", mli->mli_version);
+ break;
+ }
+ printb(" flags", mli->mli_flags, "\020\1SILENT");
+ if (mli->mli_version == MLD_VERSION_2) {
+ printf(" rv %u qi %u qri %u uri %u",
+ mli->mli_rv, mli->mli_qi, mli->mli_qri, mli->mli_uri);
+ }
+ if (vflag >= 2) {
+ printf(" v1timer %u v2timer %u", mli->mli_v1_timer,
+ mli->mli_v2_timer);
+ }
+ printf("\n");
+}
+
+/*
+ * Retrieve MLD per-group source filter mode and lists via sysctl.
+ *
+ * Note: The 128-bit IPv6 group addres needs to be segmented into
+ * 32-bit pieces for marshaling to sysctl. So the MIB name ends
+ * up looking like this:
+ * a.b.c.d.e.ifindex.g[0].g[1].g[2].g[3]
+ * Assumes that pgroup originated from the kernel, so its components
+ * are already in network-byte order.
+ */
+static void
+in6m_print_sources_sysctl(uint32_t ifindex, struct in6_addr *pgroup)
+{
+#define MAX_SYSCTL_TRY 5
+ char addrbuf[INET6_ADDRSTRLEN];
+ int mib[10];
+ int ntry = 0;
+ int *pi;
+ size_t mibsize;
+ size_t len;
+ size_t needed;
+ size_t cnt;
+ int i;
+ char *buf;
+ struct in6_addr *pina;
+ uint32_t *p;
+ uint32_t fmode;
+ const char *modestr;
+
+ mibsize = sizeof(mib) / sizeof(mib[0]);
+ if (sysctlnametomib("net.inet6.ip6.mcast.filters", mib,
+ &mibsize) == -1) {
+ perror("sysctlnametomib");
+ return;
+ }
+
+ needed = 0;
+ mib[5] = ifindex;
+ pi = (int *)pgroup;
+ for (i = 0; i < 4; i++)
+ mib[6 + i] = *pi++;
+
+ mibsize = sizeof(mib) / sizeof(mib[0]);
+ do {
+ if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
+ perror("sysctl net.inet6.ip6.mcast.filters");
+ return;
+ }
+ if ((buf = malloc(needed)) == NULL) {
+ perror("malloc");
+ return;
+ }
+ if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ perror("sysctl");
+ goto out_free;
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ len = needed;
+ if (len < sizeof(uint32_t)) {
+ perror("sysctl");
+ goto out_free;
+ }
+
+ p = (uint32_t *)buf;
+ fmode = *p++;
+ len -= sizeof(uint32_t);
+
+ modestr = inm_mode(fmode);
+ if (modestr)
+ printf(" mode %s", modestr);
+ else
+ printf(" mode (%u)", fmode);
+
+ if (vflag == 0)
+ goto out_free;
+
+ cnt = len / sizeof(struct in6_addr);
+ pina = (struct in6_addr *)p;
+
+ for (i = 0; i < cnt; i++) {
+ if (i == 0)
+ printf(" srcs ");
+ inet_ntop(AF_INET6, (const char *)pina++, addrbuf,
+ INET6_ADDRSTRLEN);
+ fprintf(stdout, "%s%s", (i == 0 ? "" : ","), addrbuf);
+ len -= sizeof(struct in6_addr);
+ }
+ if (len > 0) {
+ fprintf(stderr, "warning: %u trailing bytes from %s\n",
+ (unsigned int)len, "net.inet6.ip6.mcast.filters");
+ }
+
+out_free:
+ free(buf);
+#undef MAX_SYSCTL_TRY
+}
+
+static const char *
+inet6_n2a(struct in6_addr *p)
+{
+ static char buf[NI_MAXHOST];
+ struct sockaddr_in6 sin6;
+ u_int32_t scopeid;
+ const int niflags = NI_NUMERICHOST;
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_addr = *p;
+ if (IN6_IS_ADDR_LINKLOCAL(p) || IN6_IS_ADDR_MC_LINKLOCAL(p) ||
+ IN6_IS_ADDR_MC_NODELOCAL(p)) {
+ scopeid = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
+ if (scopeid) {
+ sin6.sin6_scope_id = scopeid;
+ sin6.sin6_addr.s6_addr[2] = 0;
+ sin6.sin6_addr.s6_addr[3] = 0;
+ }
+ }
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ buf, sizeof(buf), NULL, 0, niflags) == 0) {
+ return (buf);
+ } else {
+ return ("(invalid)");
+ }
+}
+#endif /* INET6 */
+
+/*
+ * Print a value a la the %b format of the kernel's printf
+ */
+void
+printb(const char *s, unsigned int v, const char *bits)
+{
+ int i, any = 0;
+ char c;
+
+ if (bits && *bits == 8)
+ printf("%s=%o", s, v);
+ else
+ printf("%s=%x", s, v);
+ bits++;
+ if (bits) {
+ putchar('<');
+ while ((i = *bits++) != '\0') {
+ if (v & (1 << (i-1))) {
+ if (any)
+ putchar(',');
+ any = 1;
+ for (; (c = *bits) > 32; bits++)
+ putchar(c);
+ } else
+ for (; *bits > 32; bits++)
+ ;
+ }
+ putchar('>');
+ }
+}
+
+/*
+ * convert hardware address to hex string for logging errors.
+ */
+static const char *
+sdl_addr_to_hex(const struct sockaddr_dl *sdl, char *orig_buf, int buflen)
+{
+ char *buf = orig_buf;
+ int i;
+ const u_char *lladdr;
+ int maxbytes = buflen / 3;
+
+ lladdr = (u_char *)(size_t)sdl->sdl_data + sdl->sdl_nlen;
+
+ if (maxbytes > sdl->sdl_alen) {
+ maxbytes = sdl->sdl_alen;
+ }
+ *buf = '\0';
+ for (i = 0; i < maxbytes; i++) {
+ snprintf(buf, 3, "%02x", lladdr[i]);
+ buf += 2;
+ *buf = (i == maxbytes - 1) ? '\0' : ':';
+ buf++;
+ }
+ return (orig_buf);
+}
+
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
len = CONFIG_MAXVIFS * sizeof(struct vif);
if (sysctlbyname("net.inet.ip.viftable", viftable, &len, 0, 0) == -1) {
- printf("No IPv4 multicast routing compiled into this system.\n");
+ //printf("No IPv4 multicast routing compiled into this system.\n");
return;
}
printf("\nVirtual Interface Table is empty\n");
if (sysctlbyname("net.inet.ip.mfctable", 0, &len, 0, 0) == -1) {
- printf("No IPv4 multicast routing compiled into this system.\n");
+ //printf("No IPv4 multicast routing compiled into this system.\n");
return;
}
mfctable = malloc(len);
if (mfctable == 0)
return;
if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, 0, 0) == -1) {
- printf("No IPv4 multicast routing compiled into this system.\n");
+ //printf("No IPv4 multicast routing compiled into this system.\n");
return;
}
banner_printed = 0;
size_t len = sizeof(struct mrtstat);
if(sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, 0, 0) == -1) {
- printf("No IPv4 multicast routing compiled into this system.\n");
+ //printf("No IPv4 multicast routing compiled into this system.\n");
return;
}
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
void
mroute6pr(void)
{
+#if 0
struct mf6c **mf6ctable = 0, *mfcp;
struct mif6 mif6table[MAXMIFS];
struct mf6c mfc;
len = sizeof(mif6table);
if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len, 0, 9) == -1) {
- printf("No IPv6 multicast routing compiled into this system.\n");
+ //printf("No IPv6 multicast routing compiled into this system.\n");
return;
}
if (mf6ctable == 0)
return;
if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len, 0, 0) == -1) {
- printf("No IPv6 multicast routing compiled into this system.\n");
+ //printf("No IPv6 multicast routing compiled into this system.\n");
free(mf6ctable);
return;
}
nflag = saved_nflag;
free(mf6ctable);
+#endif
}
void
len = sizeof(mrtstat);
if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len, 0, 0) == -1) {
- printf("No IPv6 multicast routing compiled into this system\n");
+ //printf("No IPv6 multicast routing compiled into this system\n");
return;
}
printf("IPv6 multicast forwarding:\n");
.Op Fl f Ar address_family | Fl p Ar protocol
.Nm
.Op Fl gilns
+.Op Fl v
.Op Fl f Ar address_family
+.Op Fl I Ar interface
.Nm
.Fl i | I Ar interface
.Op Fl w Ar wait
-.Op Fl abdgt
+.Op Fl abdgRt
.Nm
.Fl s Op Fl s
.Op Fl f Ar address_family | Fl p Ar protocol
for
.Dv AF_UNIX .
.It Fl g
-Show information related to multicast (group address) routing. By default, show the
-IP Multicast virtual-interface and routing tables. If the
+Show information related to multicast (group address) membership. If the
.Fl s
-option is also present, show multicast routing statistics.
+option is also present, show extended interface group management statistics. If the
+.Fl v
+option is specified, show link-layer memberships; they are suppressed by default.
+Source lists for each group will also be printed. Specifiying
+.Fl v
+twice will print the control plane timers for each interface and the source list counters
+for each group. If the
+.Fl i
+is specified, only that interface will be shown. If the
+.Fl f
+is specified, only information for the address family will be displayed.
.It Fl I Ar interface
Show information about the specified interface; used with a
.Ar wait
assumes more columns are there and the maximum transmission unit
.Pq Dq mtu
are also displayed.
+.It Fl R
+Show reachability information. Use with
+.Fl i
+to show link-layer reachability information for a given interface.
.It Fl s
Show per-protocol statistics. If this option is repeated, counters with a value of
zero are suppressed.
+.It Fl v
+Increase verbosity level.
.It Fl W
In certain displays, avoid truncating addresses even if this causes some fields to
overflow.
.Xr fstat 1 ,
.Xr nfsstat 1 ,
.Xr ps 1 ,
-.Xr sockstat 1 ,
.Xr inet 4 ,
.Xr unix 4 ,
.Xr hosts 5 ,
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
extern int Lflag; /* show size of listen queues */
extern int mflag; /* show memory stats */
extern int nflag; /* show addresses numerically */
+extern int Rflag; /* show reachability information */
extern int rflag; /* show routing tables (or routing stats) */
extern int sflag; /* show protocol statistics */
extern int prioflag; /* show packet priority statistics */
extern int tflag; /* show i/f watchdog timers */
+extern int vflag; /* more verbose */
extern int Wflag; /* wide display */
extern int interval; /* repeat interval for i/f stats */
extern void mbpr(void);
extern void intpr(void (*)(char *));
+extern void intpr_ri(void (*)(char *));
extern void intervalpr(void (*)(uint32_t, char *, int), uint32_t,
char *, int);
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* sin6_scope_id field of SA should be set in the future.
*/
if (IN6_IS_ADDR_LINKLOCAL(in6) ||
+ IN6_IS_ADDR_MC_NODELOCAL(in6) ||
IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
/* XXX: override is ok? */
sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
sdl->sdl_slen == 0) {
- (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
+ (void) snprintf(workbuf, sizeof(workbuf), "link#%d", sdl->sdl_index);
} else {
switch (sdl->sdl_type) {
cplim = "";
for (i = 0; i < sdl->sdl_alen; i++, lla++) {
- cp += sprintf(cp, "%s%x", cplim, *lla);
+ cp += snprintf(cp, sizeof(workbuf) - (cp - workbuf), "%s%x", cplim, *lla);
cplim = ":";
}
cp = workbuf;
slim = sa->sa_len + (u_char *) sa;
cplim = cp + sizeof(workbuf) - 6;
- cp += sprintf(cp, "(%d)", sa->sa_family);
+ cp += snprintf(cp, sizeof(workbuf) - (cp - workbuf), "(%d)", sa->sa_family);
while (s < slim && cp < cplim) {
- cp += sprintf(cp, " %02x", *s++);
+ cp += snprintf(cp, sizeof(workbuf) - (cp - workbuf), " %02x", *s++);
if (s < slim)
- cp += sprintf(cp, "%02x", *s++);
+ cp += snprintf(cp, sizeof(workbuf) - (cp - workbuf), "%02x", *s++);
}
cp = workbuf;
}
} else {
#define C(x) ((x) & 0xff)
in = ntohl(in);
- sprintf(line, "%u.%u.%u.%u",
+ snprintf(line, sizeof(line), "%u.%u.%u.%u",
C(in >> 24), C(in >> 16), C(in >> 8), C(in));
}
return (line);
break;
}
if (i == -1)
- sprintf(dst, "&0x%x", mask);
+ snprintf(dst, sizeof(dst), "&0x%x", mask);
else
- sprintf(dst, "/%d", 32-i);
+ snprintf(dst, sizeof(dst), "/%d", 32-i);
}
/*
switch (dmask) {
case IN_CLASSA_NET:
if ((i & IN_CLASSA_HOST) == 0) {
- sprintf(line, "%u", C(i >> 24));
+ snprintf(line, sizeof(line), "%u", C(i >> 24));
break;
}
/* FALLTHROUGH */
case IN_CLASSB_NET:
if ((i & IN_CLASSB_HOST) == 0) {
- sprintf(line, "%u.%u",
+ snprintf(line, sizeof(line), "%u.%u",
C(i >> 24), C(i >> 16));
break;
}
/* FALLTHROUGH */
case IN_CLASSC_NET:
if ((i & IN_CLASSC_HOST) == 0) {
- sprintf(line, "%u.%u.%u",
+ snprintf(line, sizeof(line), "%u.%u.%u",
C(i >> 24), C(i >> 16), C(i >> 8));
break;
}
/* FALLTHROUGH */
default:
- sprintf(line, "%u.%u.%u.%u",
+ snprintf(line, sizeof(line), "%u.%u.%u.%u",
C(i >> 24), C(i >> 16), C(i >> 8), C(i));
break;
}
NULL, 0, flag);
if (nflag)
- sprintf(&line[strlen(line)], "/%d", masklen);
+ snprintf(&line[strlen(line)], sizeof(line) - strlen(line), "/%d", masklen);
return line;
}
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
#if !TARGET_OS_EMBEDDED
- sprintf(mibvar, "net.local.%s.pcblist64", socktype[type]);
+ snprintf(mibvar, sizeof(mibvar), "net.local.%s.pcblist64", socktype[type]);
#else
- sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+ snprintf(mibvar, sizeof(mibvar), "net.local.%s.pcblist", socktype[type]);
#endif
len = 0;
if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
03B2DBD1100BE626005349BC /* PBXTargetDependency */,
034E4469100BDD00009CA3DC /* PBXTargetDependency */,
03B2DBC5100BE332005349BC /* PBXTargetDependency */,
+ 690D97BC12DE7151004323A7 /* PBXTargetDependency */,
034E4475100BDEC6009CA3DC /* PBXTargetDependency */,
034E447B100BDF0D009CA3DC /* PBXTargetDependency */,
03B2DBD3100BE645005349BC /* PBXTargetDependency */,
buildPhases = (
);
dependencies = (
+ 4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */,
726121470EE8717B00AFED1B /* PBXTargetDependency */,
726121490EE8717B00AFED1B /* PBXTargetDependency */,
7261217D0EE8896800AFED1B /* PBXTargetDependency */,
724DAB790EE88EA6008900D0 /* PBXTargetDependency */,
724DAB9A0EE88F5D008900D0 /* PBXTargetDependency */,
724DABC30EE890A6008900D0 /* PBXTargetDependency */,
+ 690D97BE12DE7166004323A7 /* PBXTargetDependency */,
724DABEC0EE891DF008900D0 /* PBXTargetDependency */,
724DAC240EE89525008900D0 /* PBXTargetDependency */,
7216D2670EE8978F00AE70E4 /* PBXTargetDependency */,
72ABD0A41083D818008C721C /* PBXTargetDependency */,
72ABD0881083D750008C721C /* PBXTargetDependency */,
72ABD08A1083D753008C721C /* PBXTargetDependency */,
+ 690D97BA12DE7130004323A7 /* PBXTargetDependency */,
72ABD08C1083D75D008C721C /* PBXTargetDependency */,
72ABD08E1083D75F008C721C /* PBXTargetDependency */,
72ABD0901083D762008C721C /* PBXTargetDependency */,
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 03EB2F9A120A1DDA0007C1A0 /* ip6addrctl.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4D2B04E41208C12F0004A3F3 /* ip6addrctl.8 */; };
+ 4D2B04F81208C21B0004A3F3 /* ip6addrctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2B04E51208C12F0004A3F3 /* ip6addrctl.c */; };
+ 690D97A612DE6F96004323A7 /* mtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 690D979412DE6E6B004323A7 /* mtest.c */; };
+ 690D97AE12DE70AE004323A7 /* mtest.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 690D979512DE6E76004323A7 /* mtest.8 */; };
+ 69C10A7812DF808700BCDF4C /* mtest.plist in Install OSS Plist */ = {isa = PBXBuildFile; fileRef = 69C10A7712DF7F2700BCDF4C /* mtest.plist */; };
7216D24C0EE896F300AE70E4 /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = 7261208B0EE86F4800AFED1B /* data.c */; };
7216D24D0EE896F300AE70E4 /* if.c in Sources */ = {isa = PBXBuildFile; fileRef = 7261208D0EE86F4800AFED1B /* if.c */; };
7216D24E0EE896F300AE70E4 /* inet.c in Sources */ = {isa = PBXBuildFile; fileRef = 7261208E0EE86F4800AFED1B /* inet.c */; };
remoteGlobalIDString = 7294F1290EE8BD280052EC88;
remoteInfo = traceroute6;
};
+ 4D2B05131208C6BB0004A3F3 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D2B04F21208C2040004A3F3;
+ remoteInfo = ip6addrctl;
+ };
+ 690D97B912DE7130004323A7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 690D978012DE6034004323A7;
+ remoteInfo = mtest;
+ };
+ 690D97BB12DE7151004323A7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 690D978012DE6034004323A7;
+ remoteInfo = mtest;
+ };
+ 690D97BD12DE7166004323A7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 690D978012DE6034004323A7;
+ remoteInfo = mtest;
+ };
7216D2660EE8978F00AE70E4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
+ 4D2B05221208CB410004A3F3 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/local/share/man/man8;
+ dstSubfolderSpec = 0;
+ files = (
+ 03EB2F9A120A1DDA0007C1A0 /* ip6addrctl.8 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 690D97AD12DE7074004323A7 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/local/share/man/man8;
+ dstSubfolderSpec = 0;
+ files = (
+ 690D97AE12DE70AE004323A7 /* mtest.8 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 69C10A6312DF7D5300BCDF4C /* Install OSS Plist */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/local/OpenSourceVersions/;
+ dstSubfolderSpec = 0;
+ files = (
+ 69C10A7812DF808700BCDF4C /* mtest.plist in Install OSS Plist */,
+ );
+ name = "Install OSS Plist";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
7216D2750EE8979500AE70E4 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 4D2B04E41208C12F0004A3F3 /* ip6addrctl.8 */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ip6addrctl.8; sourceTree = "<group>"; };
+ 4D2B04E51208C12F0004A3F3 /* ip6addrctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ip6addrctl.c; sourceTree = "<group>"; };
+ 4D2B04E61208C12F0004A3F3 /* ip6addrctl.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6addrctl.conf; sourceTree = "<group>"; };
+ 4D2B04F31208C2040004A3F3 /* ip6addrctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ip6addrctl; sourceTree = BUILT_PRODUCTS_DIR; };
+ 690D978112DE6034004323A7 /* mtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mtest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 690D979412DE6E6B004323A7 /* mtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mtest.c; sourceTree = "<group>"; };
+ 690D979512DE6E76004323A7 /* mtest.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mtest.8; sourceTree = "<group>"; };
+ 69C10A7712DF7F2700BCDF4C /* mtest.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = mtest.plist; sourceTree = "<group>"; };
+ 69C10A7912DF80F200BCDF4C /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
7216D2460EE896C000AE70E4 /* netstat */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = netstat; sourceTree = BUILT_PRODUCTS_DIR; };
7216D27C0EE8980A00AE70E4 /* ping */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ping; sourceTree = BUILT_PRODUCTS_DIR; };
7216D29A0EE898BD00AE70E4 /* ping6 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ping6; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 690D977F12DE6034004323A7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
7216D2440EE896C000AE70E4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 4D2B04E31208C12F0004A3F3 /* ip6addrctl.tproj */ = {
+ isa = PBXGroup;
+ children = (
+ 4D2B04E41208C12F0004A3F3 /* ip6addrctl.8 */,
+ 4D2B04E51208C12F0004A3F3 /* ip6addrctl.c */,
+ 4D2B04E61208C12F0004A3F3 /* ip6addrctl.conf */,
+ );
+ path = ip6addrctl.tproj;
+ sourceTree = "<group>";
+ };
+ 690D973F12DE5A21004323A7 /* mtest.tproj */ = {
+ isa = PBXGroup;
+ children = (
+ 690D979512DE6E76004323A7 /* mtest.8 */,
+ 690D979412DE6E6B004323A7 /* mtest.c */,
+ 69C10A7712DF7F2700BCDF4C /* mtest.plist */,
+ 69C10A7912DF80F200BCDF4C /* COPYING */,
+ );
+ path = mtest.tproj;
+ sourceTree = "<group>";
+ };
7248622F0EE86EB7001D0DE9 = {
isa = PBXGroup;
children = (
+ 690D973F12DE5A21004323A7 /* mtest.tproj */,
+ 4D2B04E31208C12F0004A3F3 /* ip6addrctl.tproj */,
726120380EE86EEB00AFED1B /* alias */,
7261204C0EE86EF900AFED1B /* arp.tproj */,
726120540EE86F0900AFED1B /* ifconfig.tproj */,
7216D3A70EE8A3BB00AE70E4 /* spray */,
7294F0F90EE8BB460052EC88 /* traceroute */,
7294F12A0EE8BD280052EC88 /* traceroute6 */,
+ 4D2B04F31208C2040004A3F3 /* ip6addrctl */,
+ 690D978112DE6034004323A7 /* mtest */,
);
name = Products;
sourceTree = "<group>";
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
+ 4D2B04F21208C2040004A3F3 /* ip6addrctl */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D2B05121208C2300004A3F3 /* Build configuration list for PBXNativeTarget "ip6addrctl" */;
+ buildPhases = (
+ 4D2B04F01208C2040004A3F3 /* Sources */,
+ 4D2B05221208CB410004A3F3 /* CopyFiles */,
+ 039D6A11120A2CF60006B8C8 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ip6addrctl;
+ productName = ip6addrctl;
+ productReference = 4D2B04F31208C2040004A3F3 /* ip6addrctl */;
+ productType = "com.apple.product-type.tool";
+ };
+ 690D978012DE6034004323A7 /* mtest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 690D978612DE6053004323A7 /* Build configuration list for PBXNativeTarget "mtest" */;
+ buildPhases = (
+ 690D977E12DE6034004323A7 /* Sources */,
+ 690D977F12DE6034004323A7 /* Frameworks */,
+ 690D97AD12DE7074004323A7 /* CopyFiles */,
+ 69C10A6312DF7D5300BCDF4C /* Install OSS Plist */,
+ 69C10A7612DF7EBB00BCDF4C /* Install OSS License */,
+ 690D97C212DE71CF004323A7 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = mtest;
+ productName = mtest;
+ productReference = 690D978112DE6034004323A7 /* mtest */;
+ productType = "com.apple.product-type.tool";
+ };
7216D2450EE896C000AE70E4 /* netstat */ = {
isa = PBXNativeTarget;
buildConfigurationList = 7216D24B0EE896EC00AE70E4 /* Build configuration list for PBXNativeTarget "netstat" */;
7216D3A60EE8A3BA00AE70E4 /* spray */,
7294F0F80EE8BB460052EC88 /* traceroute */,
7294F1290EE8BD280052EC88 /* traceroute6 */,
+ 4D2B04F21208C2040004A3F3 /* ip6addrctl */,
+ 690D978012DE6034004323A7 /* mtest */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
+ 039D6A11120A2CF60006B8C8 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "/bin/chmod 0444 $DSTROOT/usr/local/share/man/man8/ip6addrctl.8\n";
+ };
+ 690D97C212DE71CF004323A7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "/bin/chmod 0444 $DSTROOT/usr/local/share/man/man8/mtest.8";
+ };
+ 69C10A7612DF7EBB00BCDF4C /* Install OSS License */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/mtest.tproj/COPYING",
+ );
+ name = "Install OSS License";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/mtest.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "cp \"$SRCROOT/mtest.tproj/COPYING\" \"$DERIVED_FILE_DIR/mtest.txt\"\n\nmkdir -p \"$DSTROOT/usr/local/OpenSourceLicenses\"\ncp \"$DERIVED_FILE_DIR/mtest.txt\" \"$DSTROOT/usr/local/OpenSourceLicenses/\"\n\n";
+ };
7216D25F0EE8970100AE70E4 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 4D2B04F01208C2040004A3F3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D2B04F81208C21B0004A3F3 /* ip6addrctl.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 690D977E12DE6034004323A7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 690D97A612DE6F96004323A7 /* mtest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
7216D2430EE896C000AE70E4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
target = 7294F1290EE8BD280052EC88 /* traceroute6 */;
targetProxy = 03B2DBDC100BE6D5005349BC /* PBXContainerItemProxy */;
};
+ 4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D2B04F21208C2040004A3F3 /* ip6addrctl */;
+ targetProxy = 4D2B05131208C6BB0004A3F3 /* PBXContainerItemProxy */;
+ };
+ 690D97BA12DE7130004323A7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 690D978012DE6034004323A7 /* mtest */;
+ targetProxy = 690D97B912DE7130004323A7 /* PBXContainerItemProxy */;
+ };
+ 690D97BC12DE7151004323A7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 690D978012DE6034004323A7 /* mtest */;
+ targetProxy = 690D97BB12DE7151004323A7 /* PBXContainerItemProxy */;
+ };
+ 690D97BE12DE7166004323A7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 690D978012DE6034004323A7 /* mtest */;
+ targetProxy = 690D97BD12DE7166004323A7 /* PBXContainerItemProxy */;
+ };
7216D2670EE8978F00AE70E4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 7216D2450EE896C000AE70E4 /* netstat */;
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(NATIVE_ARCH_ACTUAL)";
COPY_PHASE_STRIP = YES;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
"DEBUG_INFORMATION_FORMAT[sdk=iphoneos*][arch=*]" = dwarf;
- GCC_DYNAMIC_NO_PIC = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
GCC_MODEL_TUNING = G5;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "USE_RFC2292BIS=1",
+ "__APPLE_USE_RFC_3542=1",
+ "__APPLE_API_OBSOLETE=1",
+ );
"GCC_PREPROCESSOR_DEFINITIONS[sdk=iphoneos*][arch=*]" = (
"$(inherited)",
"TARGET_OS_EMBEDDED=1",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
PREBINDING = NO;
- SDKROOT = iphoneos3.1;
+ SDKROOT = "";
"STRIPFLAGS[sdk=iphoneos*]" = "-S";
+ VALID_ARCHS = "armv6 armv7 i386 x86_64";
WARNING_CFLAGS = "-Wall";
ZERO_LINK = NO;
};
03B2DBE6100BE71D005349BC /* Ignore Me */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
IPSEC_DEBUG,
KAME_SCOPEID,
);
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
03B2DBF0100BE71D005349BC /* Ignore Me */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
};
name = "Ignore Me";
};
+ 4D2B04F51208C2050004A3F3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALTERNATE_GROUP = wheel;
+ ALTERNATE_MODE = 0555;
+ ALTERNATE_OWNER = root;
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = 0555;
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ip6addrctl;
+ };
+ name = Debug;
+ };
+ 4D2B04F61208C2050004A3F3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ip6addrctl;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 4D2B04F71208C2050004A3F3 /* Ignore Me */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = ip6addrctl;
+ };
+ name = "Ignore Me";
+ };
+ 690D978312DE6035004323A7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ "DEBUG_INFORMATION_FORMAT[sdk=iphoneos*][arch=*]" = dwarf;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = 0555;
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = mtest;
+ };
+ name = Debug;
+ };
+ 690D978412DE6035004323A7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ "DEBUG_INFORMATION_FORMAT[sdk=iphoneos*][arch=*]" = dwarf;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = 0555;
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = mtest;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 690D978512DE6035004323A7 /* Ignore Me */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ "DEBUG_INFORMATION_FORMAT[sdk=iphoneos*][arch=*]" = dwarf;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = 0555;
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = mtest;
+ };
+ name = "Ignore Me";
+ };
7216D2480EE896C100AE70E4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
7216D29C0EE898BE00AE70E4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
7216D29D0EE898BE00AE70E4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(NATIVE_ARCH_ACTUAL)";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
- GCC_DYNAMIC_NO_PIC = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "USE_RFC2292BIS=1",
+ "__APPLE_USE_RFC_3542=1",
+ "__APPLE_API_OBSOLETE=1",
+ );
"GCC_PREPROCESSOR_DEFINITIONS[sdk=iphoneos*][arch=*]" = (
"$(inherited)",
"TARGET_OS_EMBEDDED=1",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
PREBINDING = NO;
+ SDKROOT = "";
+ VALID_ARCHS = "armv6 armv7 i386 x86_64";
WARNING_CFLAGS = "-Wall";
};
name = Debug;
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(NATIVE_ARCH_ACTUAL)";
COPY_PHASE_STRIP = YES;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
"DEBUG_INFORMATION_FORMAT[sdk=iphoneos*][arch=*]" = dwarf;
- GCC_DYNAMIC_NO_PIC = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
GCC_MODEL_TUNING = G5;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "USE_RFC2292BIS=1",
+ "__APPLE_USE_RFC_3542=1",
+ "__APPLE_API_OBSOLETE=1",
+ );
"GCC_PREPROCESSOR_DEFINITIONS[sdk=iphoneos*][arch=*]" = (
"$(inherited)",
"TARGET_OS_EMBEDDED=1",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
PREBINDING = NO;
+ SDKROOT = "";
"STRIPFLAGS[sdk=iphoneos*]" = "-S";
+ VALID_ARCHS = "armv6 armv7 i386 x86_64";
WARNING_CFLAGS = "-Wall";
ZERO_LINK = NO;
};
IPSEC_DEBUG,
KAME_SCOPEID,
);
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
IPSEC_DEBUG,
KAME_SCOPEID,
);
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
7261212F0EE8710B00AFED1B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
726121300EE8710B00AFED1B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 4D2B05121208C2300004A3F3 /* Build configuration list for PBXNativeTarget "ip6addrctl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D2B04F51208C2050004A3F3 /* Debug */,
+ 4D2B04F61208C2050004A3F3 /* Release */,
+ 4D2B04F71208C2050004A3F3 /* Ignore Me */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 690D978612DE6053004323A7 /* Build configuration list for PBXNativeTarget "mtest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 690D978312DE6035004323A7 /* Debug */,
+ 690D978412DE6035004323A7 /* Release */,
+ 690D978512DE6035004323A7 /* Ignore Me */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
7216D24B0EE896EC00AE70E4 /* Build configuration list for PBXNativeTarget "netstat" */ = {
isa = XCConfigurationList;
buildConfigurations = (
packets to network hosts
.Sh SYNOPSIS
.Nm
-.Op Fl AaDdfnoQqRrv
+.Op Fl AaCDdfnoQqRrv
.Op Fl b Ar boundif
.Op Fl c Ar count
.Op Fl G Ar sweepmaxsize
Bind the socket to interface
.Ar boundif
for sending.
+.It Fl C
+Prohibit the socket from using the cellular network interface.
.It Fl c Ar count
Stop after sending
(and receiving)
.Xr netstat 1 ,
.Xr ifconfig 8 ,
.Xr routed 8 ,
-.Xr traceroute 8
+.Xr traceroute 8 ,
+.Xr ping6 8
.Sh HISTORY
The
.Nm
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
+#include <ifaddrs.h>
#define INADDR_LEN ((int)sizeof(in_addr_t))
#define TIMEVAL_LEN ((int)sizeof(struct tv32))
#if defined(IP_FORCE_OUT_IFP) && TARGET_OS_EMBEDDED
char boundifname[IFNAMSIZ];
#endif /* IP_FORCE_OUT_IFP */
+int nocell;
int how_traffic_class = 0;
int traffic_class = -1;
+int no_dup = 0;
/* counters */
long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
static char *pr_ntime(n_time);
static void pr_icmph(struct icmp *);
static void pr_iph(struct ip *);
-static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *);
+static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *, int);
static void pr_retip(struct ip *);
static void status(int);
static void stopit(int);
u_long alarmtimeout, ultmp;
int almost_done, ch, df, hold, i, icmp_len, mib[4], preload, sockerrno,
tos, ttl;
- char ctrl[CMSG_SPACE(sizeof(struct timeval))];
+ char ctrl[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(int))];
char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
#ifdef IP_OPTIONS
char rspace[MAX_IPOPTLEN]; /* record route space */
outpack = outpackhdr + sizeof(struct ip);
while ((ch = getopt(argc, argv,
- "Aab:c:DdfG:g:h:I:i:k:Ll:M:m:nop:QqRrS:s:T:t:vW:z:"
+ "Aab:Cc:DdfG:g:h:I:i:k:Ll:M:m:nop:QqRrS:s:T:t:vW:z:"
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
"P:"
case 'b':
boundif = optarg;
break;
+ case 'C':
+ nocell++;
+ break;
case 'c':
ultmp = strtoul(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp)
hostname = hnamebuf;
}
+ do {
+ struct ifaddrs *ifa_list, *ifa;
+
+ if (IN_MULTICAST(ntohl(whereto.sin_addr.s_addr)) || whereto.sin_addr.s_addr == INADDR_BROADCAST) {
+ no_dup = 1;
+ break;
+ }
+
+ if (getifaddrs(&ifa_list) == -1)
+ break;
+ for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+ if ((ifa->ifa_flags & IFF_BROADCAST) == 0 || ifa->ifa_broadaddr == NULL)
+ continue;
+ if (whereto.sin_addr.s_addr != ((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr)
+ continue;
+ no_dup = 1;
+ break;
+ }
+
+ freeifaddrs(ifa_list);
+ } while (0);
+
if (options & F_FLOOD && options & F_INTERVAL)
errx(EX_USAGE, "-f and -i: incompatible options");
err(EX_OSERR, "setsockopt(IP_FORCE_OUT_IFP)");
}
#endif /* IP_FORCE_OUT_IFP */
+ if (nocell) {
+ if (setsockopt(s, IPPROTO_IP, IP_NO_IFT_CELLULAR,
+ (char *)&nocell, sizeof (nocell)) != 0)
+ err(EX_OSERR, "setsockopt(IP_NO_IFT_CELLULAR)");
+ }
if (options & F_SO_DEBUG)
(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold,
sizeof(hold));
if (options & F_SO_DONTROUTE)
(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
sizeof(hold));
- if (how_traffic_class == 1) {
+ if (how_traffic_class == 1 && traffic_class > 0) {
(void)setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class,
sizeof(traffic_class));
+ }
+ if (how_traffic_class > 0) {
+ int on = 1;
+ (void)setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS, (void *)&on,
+ sizeof(on));
}
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
struct timeval now, timeout;
fd_set rfds;
int cc, n;
+ int tc = -1;
check_status();
if ((unsigned)s >= FD_SETSIZE)
warn("recvmsg");
continue;
}
-#ifdef SO_TIMESTAMP
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_TIMESTAMP &&
- cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) {
- /* Copy to avoid alignment problems: */
- memcpy(&now, CMSG_DATA(cmsg), sizeof(now));
- tv = &now;
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ #ifdef SO_TIMESTAMP
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_TIMESTAMP &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) {
+ /* Copy to avoid alignment problems: */
+ memcpy(&now, CMSG_DATA(cmsg), sizeof(now));
+ tv = &now;
+ }
+ #endif
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SO_TRAFFIC_CLASS &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+ /* Copy to avoid alignment problems: */
+ memcpy(&tc, CMSG_DATA(cmsg), sizeof(tc));
+ }
}
-#endif
if (tv == NULL) {
(void)gettimeofday(&now, NULL);
tv = &now;
}
- pr_pack((char *)packet, cc, &from, tv);
+ pr_pack((char *)packet, cc, &from, tv, tc);
if ((options & F_ONCE && nreceived) ||
(npackets && nreceived >= npackets))
break;
* program to be run without having intermingled output (or statistics!).
*/
static void
-pr_pack(buf, cc, from, tv)
+pr_pack(buf, cc, from, tv, tc)
char *buf;
int cc;
struct sockaddr_in *from;
struct timeval *tv;
+ int tc;
{
struct in_addr ina;
u_char *cp, *dp;
(void)printf(" ttl=%d", ip->ip_ttl);
if (timing)
(void)printf(" time=%.3f ms", triptime);
- if (dupflag) {
- if (!IN_MULTICAST(ntohl(whereto.sin_addr.s_addr)))
- (void)printf(" (DUP!)");
+ if (tc != -1) {
+ (void)printf(" tc=%d", tc);
+ }
+ if (dupflag && no_dup == 0) {
+ (void)printf(" (DUP!)");
}
if (options & F_AUDIBLE)
(void)write(STDOUT_FILENO, &BBELL, 1);
.Sh SYNOPSIS
.Nm
.\" without ipsec, or new ipsec
-.Op Fl dfHmnNoqtvwW
+.Op Fl CdfHmnNoqtvwW
.\" old ipsec
.\" .Op Fl AdEfmnNqRtvwW
.Bk -words
.Op Fl b Ar bufsiz
.Ek
.Bk -words
+.Op Fl B Ar boundif
+.Ek
+.Bk -words
.Op Fl c Ar count
.Ek
.Bk -words
.El
.It Fl b Ar bufsiz
Set socket buffer size.
+.It Fl B Ar boundif
+Bind the socket to interface
+.Ar boundif
+for sending.
+.It Fl C
+Prohibit the socket from using the cellular network interface.
.It Fl c Ar count
Stop after sending
(and receiving)
Quiet output.
Nothing is displayed except the summary lines at startup time and
when finished.
+.It Fl r
+Audible.
+Include a bell
+.Tn ( ASCII
+0x07)
+character in the output when any packet is received.
+.It Fl R
+Audible.
+Output a bell
+.Tn ( ASCII
+0x07)
+character when no packet is received before the next packet
+is transmitted.
+To cater for round-trip times that are longer than the interval
+between transmissions, further missing packets cause a bell only
+if the maximum number of unreceived packets has increased.
.It Fl S Ar sourceaddr
Specifies the source address of request packets.
The source address must be one of the unicast addresses of the sending node,
The
.Nm
utility returns 0 on success (the host is alive),
-and non-zero if the arguments are incorrect or the host is not responding.
+2 if the transmission was successful but no responses were received,
+any other non-zero value if the arguments are incorrect or
+another error has occured.
.Sh EXAMPLES
Normally,
.Nm
static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
#endif
static const char rcsid[] =
- "$FreeBSD: src/sbin/ping6/ping6.c,v 1.29.2.1 2007/05/22 22:01:44 mtm Exp $";
+ "$FreeBSD$";
#endif /* not lint */
/*
#define F_SUPTYPES 0x80000
#define F_NOMINMTU 0x100000
#define F_ONCE 0x200000
+#define F_AUDIBLE 0x400000
+#define F_MISSED 0x800000
#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
u_int options;
#define SIN6(s) ((struct sockaddr_in6 *)(s))
#define MAXTOS 255
-
/*
* MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
* number of received sequence numbers we can keep track of. Change 128
int s; /* socket file descriptor */
u_char outpack[MAXPACKETLEN];
char BSPACE = '\b'; /* characters written for flood */
+char BBELL = '\a'; /* characters written for AUDIBLE */
char DOT = '.';
char *hostname;
int ident; /* process id to identify our packets */
u_int8_t nonce[8]; /* nonce field for node information */
int hoplimit = -1; /* hoplimit */
int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */
+char *boundif;
+unsigned int ifscope;
+int nocell;
/* counters */
+long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
long npackets; /* max packets to transmit */
long nreceived; /* # of packets we got back */
long nrepeats; /* number of duplicates */
long ntransmitted; /* sequence # for outbound packets = #sent */
-long nmissed; /* # of packet missed */
struct timeval interval = {1, 0}; /* interval between packets */
/* timing */
int rcvtclass = 0;
+int how_so_traffic_class = 0;
+int so_traffic_class = -1;
+
int main(int, char *[]);
void fill(char *, char *);
int get_hoplim(struct msghdr *);
int get_pathmtu(struct msghdr *);
int get_tclass(struct msghdr *);
+int get_so_traffic_class(struct msghdr *);
struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
void onsignal(int);
void retransmit(void);
#endif /*IPSEC_POLICY_IPSEC*/
#endif
while ((ch = getopt(argc, argv,
- "a:b:c:dfHg:h:I:i:l:mnNop:qS:s:tvwWz:" ADDOPTS)) != -1) {
+ "a:b:B:Cc:dfHg:h:I:i:k:l:mnNop:qrRS:s:tvwWz:" ADDOPTS)) != -1) {
#undef ADDOPTS
switch (ch) {
case 'a':
"-b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported");
#endif
break;
+ case 'B':
+ boundif = optarg;
+ break;
+ case 'C':
+ nocell++;
+ break;
case 'c':
npackets = strtol(optarg, &e, 10);
if (npackets <= 0 || *optarg == '\0' || *e != '\0')
}
options |= F_INTERVAL;
break;
+ case 'k':
+ how_so_traffic_class++;
+ so_traffic_class = atoi(optarg);
+ break;
+
case 'l':
if (getuid()) {
errno = EPERM;
case 'q':
options |= F_QUIET;
break;
+ case 'r':
+ options |= F_AUDIBLE;
+ break;
+ case 'R':
+ options |= F_MISSED;
+ break;
case 'S':
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_NUMERICHOST; /* allow hostname? */
}
}
+ if (boundif != NULL && (ifscope = if_nametoindex(boundif)) == 0)
+ errx(1, "bad interface name");
+
argc -= optind;
argv += optind;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET6;
- /* XXX getaddrinfo does like SOCK_DGRAM for IPPROTO_ICMPV6 */
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = IPPROTO_ICMPV6;
res->ai_protocol)) < 0)
err(1, "socket");
+ if (ifscope != 0) {
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_BOUND_IF,
+ (char *)&ifscope, sizeof (ifscope)) != 0)
+ err(1, "setsockopt(IPV6_BOUND_IF)");
+ }
+
+ if (nocell != 0) {
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_NO_IFT_CELLULAR,
+ (char *)&nocell, sizeof (nocell)) != 0)
+ err(1, "setsockopt(IPV6_NO_IFT_CELLULAR)");
+ }
+
/* set the source address if specified. */
if ((options & F_SRCADDR) &&
bind(s, (struct sockaddr *)&src, srclen) != 0) {
err(1, "setsockopt(IPV6_TCLASS)");
}
-/*
+ /*
optval = 1;
if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
if (tclass != -2)
ip6optlen += CMSG_SPACE(sizeof(int));
+ if (how_so_traffic_class == 1 && so_traffic_class > 0) {
+ (void)setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&so_traffic_class,
+ sizeof(so_traffic_class));
+ }
+ if (how_so_traffic_class > 0) {
+ int on = 1;
+ (void)setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS, (void *)&on,
+ sizeof(on));
+ }
+ if (how_so_traffic_class > 1)
+ ip6optlen += CMSG_SPACE(sizeof(int));
+
/* set IP6 packet options */
if (ip6optlen) {
if ((scmsg = (char *)malloc(ip6optlen)) == 0)
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
}
-
+ if (how_so_traffic_class > 1) {
+ scmsgp->cmsg_len = CMSG_LEN(sizeof(int));
+ scmsgp->cmsg_level = SOL_SOCKET;
+ scmsgp->cmsg_type = SO_TRAFFIC_CLASS;
+ *(int *)(CMSG_DATA(scmsgp)) = so_traffic_class;
+
+ scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
+ }
if (!(options & F_SRCADDR)) {
/*
* get the source address. XXX since we revoked the root
if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "UDP socket");
+ if (ifscope != 0) {
+ if (setsockopt(dummy, IPPROTO_IPV6, IPV6_BOUND_IF,
+ (char *)&ifscope, sizeof (ifscope)) != 0)
+ err(1, "setsockopt(IPV6_BOUND_IF)");
+ }
+
+ if (nocell != 0) {
+ if (setsockopt(dummy, IPPROTO_IPV6, IPV6_NO_IFT_CELLULAR,
+ (char *)&nocell, sizeof (nocell)) != 0)
+ err(1, "setsockopt(IPV6_NO_IFT_CELLULAR)");
+ }
+
src.sin6_family = AF_INET6;
src.sin6_addr = dst.sin6_addr;
src.sin6_port = ntohs(DUMMY_PORT);
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval,
sizeof(optval)) < 0)
- warn("setsockopt(IPV6_HOPLIMIT, %d, %u)", optval, sizeof(optval)); /* XXX err? */
+ warn("setsockopt(IPV6_HOPLIMIT, %d, %lu)", optval, sizeof(optval)); /* XXX err? */
#endif
printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
/* signal handling */
if (seenalrm) {
- if (ntransmitted - nreceived > nmissed) {
- nmissed++;
- if (!(options & F_QUIET))
- printf("Request timeout for icmp_seq=%ld\n", ntransmitted - 1);
- }
+ /* last packet sent, timeout reached? */
+ if (npackets && ntransmitted >= npackets)
+ break;
retransmit();
seenalrm = 0;
continue;
if (((options & F_ONCE) != 0 && nreceived > 0) ||
(npackets > 0 && nreceived >= npackets))
break;
+ if (ntransmitted - nreceived - 1 > nmissedmax) {
+ nmissedmax = ntransmitted - nreceived - 1;
+ if (options & F_MISSED)
+ (void)write(STDOUT_FILENO, &BBELL, 1);
+ }
}
summary();
- exit(nreceived == 0);
+ exit(nreceived == 0 ? 2 : 0);
}
void
itimer.it_interval.tv_usec = 0;
itimer.it_value.tv_usec = 0;
- (void)signal(SIGALRM, onint);
+ (void)signal(SIGALRM, onsignal);
(void)setitimer(ITIMER_REAL, &itimer, NULL);
}
int oldfqdn;
u_int16_t seq;
char dnsname[NS_MAXDNAME + 1];
- int tclass;
-
+ int tclass = 0;
+ int sotc = -1;
+
(void)gettimeofday(&tv, NULL);
if (!mhdr || !mhdr->msg_name ||
return;
}
+ if (how_so_traffic_class > 0)
+ sotc = get_so_traffic_class(mhdr);
+
if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {
seq = ntohs(icp->icmp6_seq);
++nreceived;
if (options & F_FLOOD)
(void)write(STDOUT_FILENO, &BSPACE, 1);
else {
+ if (options & F_AUDIBLE)
+ (void)write(STDOUT_FILENO, &BBELL, 1);
(void)printf("%d bytes from %s, icmp_seq=%u", cc,
pr_addr(from, fromlen), seq);
(void)printf(" hlim=%d", hoplim);
if (!IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
(void)printf("(DUP!)");
}
+ if (rcvtclass)
+ (void)printf(" tclass=%d", tclass);
+ if (sotc != -1)
+ (void)printf(" sotc=%d", sotc);
/* check the data */
cp = buf + off + ICMP6ECHOLEN + ICMP6ECHOTMLEN;
dp = outpack + ICMP6ECHOLEN + ICMP6ECHOTMLEN;
return(-1);
}
-
+int
+get_so_traffic_class(struct msghdr *mhdr)
+{
+ struct cmsghdr *cm;
+
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_len == 0)
+ return(-1);
+
+ if (cm->cmsg_level == SOL_SOCKET &&
+ cm->cmsg_type == SO_TRAFFIC_CLASS &&
+ cm->cmsg_len == CMSG_LEN(sizeof(int)))
+ return(*(int *)CMSG_DATA(cm));
+ }
+
+ return(-1);
+}
+
/*
* tvsub --
#ifdef IPV6_USE_MIN_MTU
"m"
#endif
- "nNoqtvwW] "
- "[-a addrtype] [-b bufsiz] [-c count] [-g gateway]\n"
- " [-h hoplimit] [-I interface] [-i wait] [-l preload]"
+ "nNoqrRtvwW] "
+ "[-a addrtype] [-b bufsiz] [-B boundif] [-c count]\n"
+ " [-g gateway] [-h hoplimit] [-I interface] [-i wait] [-l preload]"
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
" [-P policy]"
#endif
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2009 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/* Go through all the minors and find one that isn't in use. */
do {
- (void) sprintf(device, "/dev/bpf%d", n++);
+ (void) snprintf(device, sizeof(device), "/dev/bpf%d", n++);
fd = open(device, O_RDWR);
} while (fd < 0 && errno == EBUSY);
char ipname[9];
static DIR *dd = 0;
- (void) sprintf(ipname, "%08X", addr);
+ (void) snprintf(ipname, sizeof(ipname), "%08X", addr);
/* If directory is already open, rewind it. Otherwise, open it. */
if ((d = dd) != NULL)
rewinddir(d);
.Pp
The following options are available:
.Bl -tag -width indent
+.It Fl d
+Run in debug-only mode, i.e., do not actually modify the routing table.
.It Fl n
Bypass attempts to print host and network names symbolically
when reporting actions. (The process of translating between symbolic
names and numerical equivalents can be quite time consuming, and
may require correct operation of the network; thus it may be expedient
to forget this, especially when attempting to repair networking operations).
+.It Fl t
+Run in test-only mode.
+.Pa /dev/null
+is used instead of a socket.
.It Fl v
(verbose) Print additional details.
.It Fl q
itself may be given, in which case the route remains valid even
if the local or remote addresses change.
.Pp
-For AF_INET, the
+For AF_INET and AF_INET6, the
.Fl ifscope
modifier specifies the additional property of the route related to
the interface scope derived from interface
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
struct rt_metrics rt_metrics;
u_long rtm_inits;
unsigned int ifscope;
+
+static const char *route_strerror(int);
const char *routename(), *netname();
void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
argv += optind;
pid = getpid();
- uid = getuid();
+ uid = geteuid();
if (tflag)
s = open(_PATH_DEVNULL, O_WRONLY, 0);
else
if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
(cp = index(domain, '.'))) {
domain[MAXHOSTNAMELEN] = '\0';
- (void) strcpy(domain, cp + 1);
+ (void) strlcpy(domain, cp + 1, sizeof(domain));
} else
domain[0] = 0;
}
if (sa->sa_len == 0)
- strcpy(line, "default");
+ strlcpy(line, "default", sizeof(line));
else switch (sa->sa_family) {
case AF_INET:
/* XXX - why not inet_ntoa()? */
#define C(x) (unsigned)((x) & 0xff)
in.s_addr = ntohl(in.s_addr);
- (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+ (void) snprintf(line, sizeof(line), "%u.%u.%u.%u", C(in.s_addr >> 24),
C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
}
break;
#ifdef __KAME__
if (sa->sa_len == sizeof(struct sockaddr_in6) &&
(IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
sin6.sin6_scope_id == 0) {
sin6.sin6_scope_id =
default:
{ u_short *s = (u_short *)sa;
u_short *slim = s + ((sa->sa_len + 1) >> 1);
- char *cp = line + sprintf(line, "(%d)", sa->sa_family);
+ char *cp = line + snprintf(line, sizeof(line), "(%d)", sa->sa_family);
char *cpe = line + sizeof(line);
while (++s < slim && cp < cpe) /* start with sa->sa_data */
if (cp)
strncpy(line, cp, sizeof(line));
else if ((in.s_addr & 0xffffff) == 0)
- (void) sprintf(line, "%u", C(in.s_addr >> 24));
+ (void) snprintf(line, sizeof(line), "%u", C(in.s_addr >> 24));
else if ((in.s_addr & 0xffff) == 0)
- (void) sprintf(line, "%u.%u", C(in.s_addr >> 24),
+ (void) snprintf(line, sizeof(line), "%u.%u", C(in.s_addr >> 24),
C(in.s_addr >> 16));
else if ((in.s_addr & 0xff) == 0)
- (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
+ (void) snprintf(line, sizeof(line), "%u.%u.%u", C(in.s_addr >> 24),
C(in.s_addr >> 16), C(in.s_addr >> 8));
else
- (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+ (void) snprintf(line, sizeof(line), "%u.%u.%u.%u", C(in.s_addr >> 24),
C(in.s_addr >> 16), C(in.s_addr >> 8),
C(in.s_addr));
break;
#ifdef __KAME__
if (sa->sa_len == sizeof(struct sockaddr_in6) &&
(IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
sin6.sin6_scope_id == 0) {
sin6.sin6_scope_id =
default:
{ u_short *s = (u_short *)sa->sa_data;
u_short *slim = s + ((sa->sa_len + 1)>>1);
- char *cp = line + sprintf(line, "af %d:", sa->sa_family);
+ char *cp = line + snprintf(line, sizeof(line), "af %d:", sa->sa_family);
char *cpe = line + sizeof(line);
while (s < slim && cp < cpe)
return (line);
}
+static const char *
+route_strerror(int error)
+{
+
+ switch (error) {
+ case ESRCH:
+ return "not in table";
+ case EBUSY:
+ return "entry in use";
+ case ENOBUFS:
+ return "routing table overflow";
+ default:
+ return (strerror(error));
+ }
+}
+
void
set_metric(value, key)
char *value;
int argc;
register char **argv;
{
- char *cmd, *dest = "", *gateway = "", *err;
+ char *cmd, *dest = "", *gateway = "";
int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC;
int key;
struct hostent *hp = 0;
if (ret == 0)
(void) printf("\n");
else {
- switch (oerrno) {
- case ESRCH:
- err = "not in table";
- break;
- case EBUSY:
- err = "entry in use";
- break;
- case ENOBUFS:
- err = "routing table overflow";
- break;
- default:
- err = strerror(oerrno);
- break;
- }
- (void) printf(": %s\n", err);
+ (void)printf(": %s\n", route_strerror(oerrno));
}
}
sin->sin_len = 1 + cp - (char *)sin;
}
+#ifdef INET6
+/*
+ * XXX the function may need more improvement...
+ */
+static int
+inet6_makenetandmask(struct sockaddr_in6 *sin6, const char *plen)
+{
+ struct in6_addr in6;
+
+ if (plen == NULL) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
+ sin6->sin6_scope_id == 0) {
+ plen = "0";
+ } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) {
+ /* aggregatable global unicast - RFC2374 */
+ memset(&in6, 0, sizeof(in6));
+ if (!memcmp(&sin6->sin6_addr.s6_addr[8],
+ &in6.s6_addr[8], 8))
+ plen = "64";
+ }
+ }
+
+ if (plen == NULL || strcmp(plen, "128") == 0)
+ return (1);
+ rtm_addrs |= RTA_NETMASK;
+ prefixlen(plen);
+ return (0);
+}
+#endif
+
/*
* Interpret an argument as a network address of some kind,
* returning 1 if a host address, 0 if a network address.
case RTA_NETMASK:
case RTA_GENMASK:
/* bzero(su, sizeof(*su)); *//* for readability */
+ su->sa.sa_len = 0;
break;
}
return (0);
case AF_INET6:
{
struct addrinfo hints, *res;
+ int ecode;
+ q = NULL;
+ if (which == RTA_DST && (q = strchr(s, '/')) != NULL)
+ *q = '\0';
memset(&hints, 0, sizeof(hints));
hints.ai_family = afamily; /*AF_INET6*/
hints.ai_flags = AI_NUMERICHOST;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- if (getaddrinfo(s, "0", &hints, &res) != 0 ||
- res->ai_family != AF_INET6 ||
+ ecode = getaddrinfo(s, NULL, &hints, &res);
+ if (ecode != 0 || res->ai_family != AF_INET6 ||
res->ai_addrlen != sizeof(su->sin6)) {
- (void) fprintf(stderr, "%s: bad value\n", s);
+ (void) fprintf(stderr, "%s: %s\n", s,
+ gai_strerror(ecode));
exit(1);
}
memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
#ifdef __KAME__
if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) ||
- IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr)) &&
+ IN6_IS_ADDR_MC_NODELOCAL(&su->sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr)) &&
su->sin6.sin6_scope_id) {
*(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] =
htons(su->sin6.sin6_scope_id);
}
#endif
freeaddrinfo(res);
- return (0);
+ if (hints.ai_flags == AI_NUMERICHOST) {
+ if (q != NULL)
+ *q++ = '/';
+ if (which == RTA_DST)
+ return (inet6_makenetandmask(&su->sin6, q));
+ return (0);
+ } else {
+ return (1);
+ }
}
#endif /* INET6 */
if (debugonly)
return (0);
if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
- warn("writing to routing socket");
+ warnx("writing to routing socket: %s", route_strerror(errno));
return (-1);
}
if (cmd == RTM_GET) {
if (rtm->rtm_flags & RTF_IFSCOPE)
(void) printf("ifscope %d, ", rtm->rtm_index);
#ifdef RTF_IFREF
- if (rtm->rtm_flags & RTF_IFREF)
+ if (rtm->rtm_flags & RTF_IFREF)
(void) printf("ifref, ");
#endif /* RTF_IFREF */
- (void) printf("flags:");
+ (void) printf("flags:");
bprintf(stdout, rtm->rtm_flags, routeflags);
pmsg_common(rtm);
}
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/* $KAME: advcap.c,v 1.5 2001/02/01 09:12:08 jinmei Exp $ */
/*
/* p now points to beginning of last field */
if (p[0] != 't' || p[1] != 'c')
return (1);
- strcpy(tcname, p+3);
+ strlcpy(tcname, p+3, sizeof(tcname));
q = tcname;
while (*q && *q != ':')
q++;
for (q = tcbuf; *q++ != ':'; )
;
l = p - holdtbuf + strlen(q);
+
+ /* check length before copying string below */
if (l > BUFSIZ) {
write(2, "Remcap entry too long\n", 23);
q[BUFSIZ - (p-holdtbuf)] = 0;
}
- strcpy(p, q);
+ strlcpy(p, q, p-tbuf);
tbuf = holdtbuf;
return (1);
}
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/* $KAME: config.c,v 1.37 2001/05/25 07:34:00 itojun Exp $ */
/*
#include "if.h"
#include "config.h"
-static void makeentry __P((char *, int, char *, int));
-static void get_prefix __P((struct rainfo *));
-static int getinet6sysctl __P((int));
+static void makeentry (char *, size_t, int, char *, int);
+static void get_prefix (struct rainfo *);
+static int getinet6sysctl (int);
extern struct rainfo *ralist;
void
-getconfig(intface)
- char *intface;
+getconfig(char *intface)
{
int stat, pfxs, i;
+ int rdnss_length;
char tbuf[BUFSIZ];
struct rainfo *tmp;
long val;
memset(tmp, 0, sizeof(*tmp));
tmp->prefix.next = tmp->prefix.prev = &tmp->prefix;
tmp->route.next = tmp->route.prev = &tmp->route;
+ tmp->rdnss_list.next = tmp->rdnss_list.prev = &tmp->rdnss_list;
/* check if we are allowed to forward packets (if not determined) */
if (forwarding < 0) {
pfx->origin = PREFIX_FROM_CONFIG;
- makeentry(entbuf, i, "prefixlen", added);
+ makeentry(entbuf, sizeof(entbuf), i, "prefixlen", added);
MAYHAVE(val, entbuf, 64);
if (val < 0 || val > 128) {
syslog(LOG_ERR,
}
pfx->prefixlen = (int)val;
- makeentry(entbuf, i, "pinfoflags", added);
+ makeentry(entbuf, sizeof(entbuf), i, "pinfoflags", added);
#ifdef MIP6
if (mobileip6)
{
pfx->routeraddr = val & ND_OPT_PI_FLAG_ROUTER;
#endif
- makeentry(entbuf, i, "vltime", added);
+ makeentry(entbuf, sizeof(entbuf), i, "vltime", added);
MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
}
pfx->validlifetime = (u_int32_t)val64;
- makeentry(entbuf, i, "vltimedecr", added);
+ makeentry(entbuf, sizeof(entbuf), i, "vltimedecr", added);
if (agetflag(entbuf)) {
struct timeval now;
gettimeofday(&now, 0);
now.tv_sec + pfx->validlifetime;
}
- makeentry(entbuf, i, "pltime", added);
+ makeentry(entbuf, sizeof(entbuf), i, "pltime", added);
MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
}
pfx->preflifetime = (u_int32_t)val64;
- makeentry(entbuf, i, "pltimedecr", added);
+ makeentry(entbuf, sizeof(entbuf), i, "pltimedecr", added);
if (agetflag(entbuf)) {
struct timeval now;
gettimeofday(&now, 0);
now.tv_sec + pfx->preflifetime;
}
- makeentry(entbuf, i, "addr", added);
+ makeentry(entbuf, sizeof(entbuf), i, "addr", added);
addr = (char *)agetstr(entbuf, &bp);
if (addr == NULL) {
syslog(LOG_ERR,
/* link into chain */
insque(rti, &tmp->route);
- makeentry(entbuf, i, "rtrplen", added);
+ makeentry(entbuf, sizeof(entbuf), i, "rtrplen", added);
MAYHAVE(val, entbuf, 64);
if (val < 0 || val > 128) {
syslog(LOG_ERR,
}
rti->prefixlen = (int)val;
- makeentry(entbuf, i, "rtrflags", added);
+ makeentry(entbuf, sizeof(entbuf), i, "rtrflags", added);
MAYHAVE(val, entbuf, 0);
rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) {
exit(1);
}
- makeentry(entbuf, i, "rtrltime", added);
+ makeentry(entbuf, sizeof(entbuf), i, "rtrltime", added);
/*
* XXX: since default value of route lifetime is not defined in
* draft-draves-route-selection-01.txt, I took the default
}
rti->ltime = (u_int32_t)val64;
- makeentry(entbuf, i, "rtrprefix", added);
+ makeentry(entbuf, sizeof(entbuf), i, "rtrprefix", added);
addr = (char *)agetstr(entbuf, &bp);
if (addr == NULL) {
syslog(LOG_ERR,
#endif
}
+ /* RDNSS option (RFC5006) */
+ MAYHAVE(val, "rdnsslifetime", 2 * tmp->maxinterval);
+ if (val < tmp->maxinterval || val > (2 * tmp->maxinterval)) {
+ syslog(LOG_NOTICE,
+ "<%s> rdnsslifetime (%lu) on %s SHOULD "
+ "be between %u and %u", __FUNCTION__, val,
+ intface, tmp->maxinterval, 2 * tmp->maxinterval);
+ }
+ tmp->rdnss_lifetime = val;
+ if ((rdnss_length = agetnum("rdnssaddrs")) < 0) {
+ tmp->rdnss_length = 0;
+ }
+ else {
+ tmp->rdnss_length = rdnss_length;
+
+ /* traverse in reverse order so that the queue has correct order */
+ for (i = (rdnss_length - 1); i >= 0; i--) {
+ struct rdnss *rdnss;
+ char entbuf[256];
+ int added = (rdnss_length > 1) ? 1 : 0;
+
+ /* allocate memory to store server address information */
+ if ((rdnss = malloc(sizeof(struct rdnss))) == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't allocate enough memory",
+ __FUNCTION__);
+ exit(1);
+ }
+ memset(rdnss, 0, sizeof(*rdnss));
+
+ /* link into chain */
+ insque(rdnss, &tmp->rdnss_list);
+
+ makeentry(entbuf, sizeof(entbuf), i, "rdnssaddr", added);
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL) {
+ syslog(LOG_ERR,
+ "<%s> need %s as a DNS server address for "
+ "interface %s",
+ __FUNCTION__, entbuf, intface);
+ exit(1);
+ }
+
+ if (inet_pton(AF_INET6, addr, &rdnss->addr) != 1) {
+ syslog(LOG_ERR,
+ "<%s> inet_pton failed for %s",
+ __FUNCTION__, addr);
+ exit(1);
+ }
+ if (IN6_IS_ADDR_MULTICAST(&rdnss->addr)) {
+ syslog(LOG_ERR,
+ "<%s> multicast address (%s) must "
+ "not be advertised as recursive DNS server",
+ __FUNCTION__, addr);
+ exit(1);
+ }
+ }
+ }
+
/* okey */
tmp->next = ralist;
ralist = tmp;
}
static void
-makeentry(buf, id, string, add)
- char *buf, *string;
- int id, add;
+makeentry(char *buf, size_t len, int id, char *string, int add)
{
- strcpy(buf, string);
+ strlcpy(buf, string, len);
if (add) {
char *cp;
cp = (char *)index(buf, '\0');
- cp += sprintf(cp, "%d", id);
+ cp += snprintf(cp, len - (cp - buf), "%d", id);
*cp = '\0';
}
}
packlen += sizeof(struct nd_opt_route_info) +
((rti->prefixlen + 0x3f) >> 6) * 8;
#endif
+ if (rainfo->rdnss_length > 0)
+ packlen += 8 + sizeof(struct in6_addr) * rainfo->rdnss_length;
/* allocate memory for the packet */
if ((buf = malloc(packlen)) == NULL) {
}
#endif
+ if (rainfo->rdnss_length > 0) {
+ struct nd_opt_rdnss * ndopt_rdnss;
+ struct rdnss * rdnss;
+
+ ndopt_rdnss = (struct nd_opt_rdnss*) buf;
+ ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
+ ndopt_rdnss->nd_opt_rdnss_len = 1 + (rainfo->rdnss_length * 2);
+ ndopt_rdnss->nd_opt_rdnss_reserved = 0;
+ ndopt_rdnss->nd_opt_rdnss_lifetime = htonl(rainfo->rdnss_lifetime);
+ buf += 8;
+
+ for (rdnss = rainfo->rdnss_list.next;
+ rdnss != &rainfo->rdnss_list;
+ rdnss = rdnss->next)
+ {
+ struct in6_addr* addr6 = (struct in6_addr*) buf;
+ *addr6 = rdnss->addr;
+ buf += sizeof *addr6;
+ }
+ }
+
return;
}
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/* $KAME: dump.c,v 1.16 2001/03/21 17:41:13 jinmei Exp $ */
/*
if (sdl->sdl_alen && sdl->sdl_alen > 5) {
cp = (u_char *)LLADDR(sdl);
- sprintf(ebuf, "%x:%x:%x:%x:%x:%x",
+ snprintf(ebuf, sizeof(ebuf), "%x:%x:%x:%x:%x:%x",
cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
}
else {
- sprintf(ebuf, "NONE");
+ snprintf(ebuf, sizeof(ebuf), "NONE");
}
return(ebuf);
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 17, 1998
+.Dd July 2, 2010
.Dt RTADVD.CONF 5
.Os
.Sh NAME
The default value is 0.
.It Cm \&addrs
(num) Number of prefixes.
-Its default is 0, so it must explicitly be set to positve values
+Its default is 0, so it must explicitly be set to positive values
if you want to specify any prefix information option.
If its value is 0,
.Xr rtadvd 8
.Bl -tag -width indent
.It Cm \&routes
(num) Number of routes.
-Its default is 0, so it must explicitly be set to positve values
+Its default is 0, so it must explicitly be set to positive values
if you want to specify any route information option.
If its value is 0, no route information is sent.
If its value is more than 1, you must specify the index of the routes
See
.Xr termcap 5
for details on the capability.
+.Pp
+The following items are for the ICMPv6 recursive DNS server (RDNSS) option,
+which will be attached to the router advertisement header.
+.Bl -tag -width indent
+.It Cm \&rdnssaddrs
+(num) Number of recursive DNS server addresses.
+Its default is 0, so it must explicitly be set to positive values
+if you want to specify any DNS server address.
+If its value is 0, no DNS server information is sent.
+If its value is more than 1, you must specify the index of the address
+for the
+.Cm rdnssaddr
+item below.
+Indices vary from 0 to N-1, where N is the
+value of
+.Cm rdnssaddrs .
+Each index shall follow the name of
+.Cm rdnssaddr ,
+e.g.,
+.Dq rdnssaddr0 .
+.It Cm \&rdnssaddr
+(str) The IPv6 address of the recursive DNS server.
+Since
+.Dq \&:
+is used for
+.Xr termcap 5
+file format as well as IPv6 numeric address, the field MUST be quoted by
+doublequote character.
+This field cannot be
+omitted if the value of
+.Cm rdnssaddrs
+is more than 0.
+.It Cm \&rdnsslifetime
+(num) The lifetime field in RDNSS option.
+(unit: seconds).
+The default value is 2 * the value of
+.Cm \&maxinterval ,
+which is also the maximum value that should be set. The minimum value is
+.Cm \&maxinterval .
+If you specify a value outside of this range, a message is logged.
+.El
.Sh EXAMPLES
As presented above, all of the advertised parameters have default values
defined in specifications, and hence you usually do not have to set them
Default Router Preferences and More-Specific Routes
.Dc ,
draft-ietf-ipngwg-router-selection-01.txt
+.Pp
+Jeong, J., Park, S., Beloeil, L., and S. Madanapalli,
+.Do
+IPv6 Router Advertisement Option for DNS Configuration
+.Dc ,
+RFC 5006
.Sh HISTORY
The
.Xr rtadvd 8
struct sockaddr_in6 addr;
};
+struct rdnss {
+ struct rdnss *next; /* forward link */
+ struct rdnss *prev; /* previous link */
+
+ struct in6_addr addr;
+};
+
struct rainfo {
/* pointer for list */
struct rainfo *next;
struct rtinfo route; /* route information option (link head) */
int routes; /* number of route information options */
+ /* Recursive DNS Servers RFC5006 */
+ struct rdnss rdnss_list;
+ int rdnss_length;
+ u_int32_t rdnss_lifetime;
+
/* actual RA packet data and its length */
size_t ra_datalen;
u_char *ra_data;
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/* $KAME: dump.c,v 1.8 2000/10/05 22:20:39 itojun Exp $ */
/*
if (days) {
first = 0;
- p += sprintf(p, "%dd", days);
+ p += snprintf(p, sizeof(result) - (p - result), "%dd", days);
}
if (!first || hours) {
first = 0;
- p += sprintf(p, "%dh", hours);
+ p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
}
if (!first || mins) {
first = 0;
- p += sprintf(p, "%dm", mins);
+ p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
}
- sprintf(p, "%ds", secs);
+ snprintf(p, sizeof(result) - (p - result), "%ds", secs);
return(result);
}
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/* $KAME: if.c,v 1.15 2001/05/22 06:04:17 jinmei Exp $ */
/*
continue;
memset(&ifr6, 0, sizeof(ifr6));
- strcpy(ifr6.ifr_name, name);
+ strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
warnmsg(LOG_ERR, __FUNCTION__,
continue;
memset(&ifr6, 0, sizeof(ifr6));
- strcpy(ifr6.ifr_name, name);
+ strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
warnmsg(LOG_ERR, __FUNCTION__,
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/* $KAME: probe.c,v 1.10 2000/08/13 06:14:59 itojun Exp $ */
/*
return(-1);
}
+#ifndef __APPLE__
/* make the socket send-only */
if (shutdown(probesock, 0)) {
warnmsg(LOG_ERR, __FUNCTION__, "shutdown: %s", strerror(errno));
return(-1);
}
+#endif /* __APPLE__ */
/* initialize msghdr for sending packets */
sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
return;
}
bzero(&dr, sizeof(dr));
- strcpy(dr.ifname, "lo0"); /* dummy interface */
+ strlcpy(dr.ifname, "lo0", sizeof(dr.ifname)); /* dummy interface */
if (ioctl(s, SIOCGDRLST_IN6, (caddr_t)&dr) < 0) {
warnmsg(LOG_ERR, __FUNCTION__, "ioctl(SIOCGDRLST_IN6): %s",
strerror(errno));
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 2000
* The Regents of the University of California. All rights reserved.
s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if (s < 0) {
- sprintf(errbuf, "socket: %.128s", strerror(errno));
+ snprintf(errbuf, sizeof(errbuf), "socket: %.128s", strerror(errno));
return (errbuf);
}
cc = write(s, (char *)rp, size);
if (cc < 0) {
- sprintf(errbuf, "write: %.128s", strerror(errno));
+ snprintf(errbuf, sizeof(errbuf), "write: %.128s", strerror(errno));
close(s);
return (errbuf);
}
if (cc != size) {
- sprintf(errbuf, "short write (%d != %d)", cc, size);
+ snprintf(errbuf, sizeof(errbuf), "short write (%d != %d)", cc, size);
close(s);
return (errbuf);
}
memset(rp, 0, size);
cc = read(s, (char *)rp, size);
if (cc < 0) {
- sprintf(errbuf, "read: %.128s", strerror(errno));
+ snprintf(errbuf, sizeof(errbuf), "read: %.128s", strerror(errno));
close(s);
return (errbuf);
}
if (rp->rtm_version != RTM_VERSION) {
- sprintf(errbuf, "bad version %d", rp->rtm_version);
+ snprintf(errbuf, sizeof(errbuf), "bad version %d", rp->rtm_version);
return (errbuf);
}
if (rp->rtm_msglen > cc) {
- sprintf(errbuf, "bad msglen %d > %d", rp->rtm_msglen, cc);
+ snprintf(errbuf, sizeof(errbuf), "bad msglen %d > %d", rp->rtm_msglen, cc);
return (errbuf);
}
if (rp->rtm_errno != 0) {
- sprintf(errbuf, "rtm_errno: %.128s", strerror(rp->rtm_errno));
+ snprintf(errbuf, sizeof(errbuf), "rtm_errno: %.128s", strerror(rp->rtm_errno));
return (errbuf);
}
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1997, 1998, 1999, 2000
* The Regents of the University of California. All rights reserved.
* Return the interface list
*/
int
-ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf)
+ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf, size_t errbuflen)
{
register int fd, nipaddr;
#ifdef HAVE_SOCKADDR_SA_LEN
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
- (void)sprintf(errbuf, "socket: %s", strerror(errno));
+ (void)snprintf(errbuf, errbuflen, "socket: %s", strerror(errno));
return (-1);
}
ifc.ifc_len = sizeof(ibuf);
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
ifc.ifc_len < sizeof(struct ifreq)) {
if (errno == EINVAL)
- (void)sprintf(errbuf,
+ (void)snprintf(errbuf, sizeof(errbuf),
"SIOCGIFCONF: ifreq struct too small (%d bytes)",
(int)sizeof(ibuf));
else
- (void)sprintf(errbuf, "SIOCGIFCONF: %s",
+ (void)snprintf(errbuf, errbuflen, "SIOCGIFCONF: %s",
strerror(errno));
(void)close(fd);
return (-1);
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
if (errno == ENXIO)
continue;
- (void)sprintf(errbuf, "SIOCGIFFLAGS: %.*s: %s",
+ (void)snprintf(errbuf, errbuflen, "SIOCGIFFLAGS: %.*s: %s",
(int)sizeof(ifr.ifr_name), ifr.ifr_name,
strerror(errno));
(void)close(fd);
continue;
#endif
if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
- (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s",
+ (void)snprintf(errbuf, errbuflen, "SIOCGIFADDR: %s: %s",
device, strerror(errno));
(void)close(fd);
return (-1);
}
if (nipaddr >= MAX_IPADDR) {
- (void)sprintf(errbuf, "Too many interfaces (%d)",
+ (void)snprintf(errbuf, errbuflen, "Too many interfaces (%d)",
(int)MAX_IPADDR);
(void)close(fd);
return (-1);
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1997
* The Regents of the University of California. All rights reserved.
char *device;
};
-int ifaddrlist(struct ifaddrlist **, char *);
+int ifaddrlist(struct ifaddrlist **, char *, size_t );
C. Philip Wood, Tim Seaver and Ken Adelman.
.Sh SEE ALSO
.Xr netstat 1 ,
-.Xr ping 8
+.Xr ping 8 ,
+.Xr traceroute6 8
.Sh BUGS
When using protocols other than UDP, functionality is reduced.
In particular, the last packet will often appear to be lost, because
+/*
+ * Copyright (c) 2004-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
* The Regents of the University of California. All rights reserved.
sizeof(on));
/* Get the interface address list */
- n = ifaddrlist(&al, errbuf);
+ n = ifaddrlist(&al, errbuf, sizeof(errbuf));
if (n < 0) {
Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
exit(1);