]> git.saurik.com Git - apple/network_cmds.git/commitdiff
network_cmds-356.8.tar.gz mac-os-x-107 mac-os-x-1071 mac-os-x-1072 mac-os-x-1073 mac-os-x-1074 v356.8
authorApple <opensource@apple.com>
Wed, 30 Mar 2011 23:06:21 +0000 (23:06 +0000)
committerApple <opensource@apple.com>
Wed, 30 Mar 2011 23:06:21 +0000 (23:06 +0000)
61 files changed:
alias/alias_ftp.c
alias/alias_proxy.c
alias/alias_smedia.c
arp.tproj/arp.8
arp.tproj/arp.c
ifconfig.tproj/af_inet.c
ifconfig.tproj/af_inet6.c
ifconfig.tproj/af_link.c
ifconfig.tproj/ifconfig.8
ifconfig.tproj/ifconfig.c
ifconfig.tproj/ifmedia.c
ifconfig.tproj/ifvlan.c
ip6addrctl.tproj/ip6addrctl.8 [new file with mode: 0644]
ip6addrctl.tproj/ip6addrctl.c [new file with mode: 0644]
ip6addrctl.tproj/ip6addrctl.conf [new file with mode: 0644]
ip6fw.tproj/ip6fw.8
ip6fw.tproj/ip6fw.c
ipfw.tproj/ipfw.8
ipfw.tproj/ipfw2.c
kdumpd.tproj/kdumpd.c
mtest.tproj/COPYING [new file with mode: 0644]
mtest.tproj/mtest.8 [new file with mode: 0644]
mtest.tproj/mtest.c [new file with mode: 0644]
mtest.tproj/mtest.plist [new file with mode: 0644]
natd.tproj/natd.8
natd.tproj/natd.c
ndp.tproj/ndp.8
ndp.tproj/ndp.c
netstat.tproj/if.c
netstat.tproj/inet.c
netstat.tproj/inet6.c
netstat.tproj/main.c
netstat.tproj/mbuf.c
netstat.tproj/mcast.c
netstat.tproj/mroute.c
netstat.tproj/mroute6.c
netstat.tproj/netstat.1
netstat.tproj/netstat.h
netstat.tproj/route.c
netstat.tproj/unix.c
network_cmds.xcodeproj/project.pbxproj
ping.tproj/ping.8
ping.tproj/ping.c
ping6.tproj/ping6.8
ping6.tproj/ping6.c
rarpd.tproj/rarpd.c
route.tproj/route.8
route.tproj/route.c
rtadvd.tproj/advcap.c
rtadvd.tproj/config.c
rtadvd.tproj/dump.c
rtadvd.tproj/rtadvd.conf.5
rtadvd.tproj/rtadvd.h
rtsol.tproj/dump.c
rtsol.tproj/if.c
rtsol.tproj/probe.c
traceroute.tproj/findsaddr-socket.c
traceroute.tproj/ifaddrlist.c
traceroute.tproj/ifaddrlist.h
traceroute.tproj/traceroute.8
traceroute.tproj/traceroute.c

index 9c886066e08ce0fc18f7a4760a9c82e636f2ee49..d59fbf322c90b57f35ba6fa359d604d7ba2acf13 100644 (file)
@@ -1,24 +1,31 @@
 /*
- * 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.
@@ -535,23 +542,23 @@ NewFtpMessage(struct ip *pip,
 
                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;
            }
index 3ba958f85641feb11defadd50776c17536dc11b4..a35ba1d5238e1be4349a782f44159eae8778fe0f 100644 (file)
@@ -1,24 +1,31 @@
 /*
- * 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.
@@ -328,11 +335,11 @@ ProxyEncodeTcpStream(struct alias_link *link,
     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;
     }
 
@@ -585,7 +592,7 @@ PacketAliasProxyRule(const char *cmd)
     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);
@@ -661,7 +668,7 @@ PacketAliasProxyRule(const char *cmd)
             break;
 
         case STATE_READ_PORT:
-            strcpy(str_port, token);
+            strlcpy(str_port, token, sizeof(str_port));
             state = STATE_READ_KEYWORD;
             break;
 
index fad6f78cb10985aa4356cec412e33dce2a7c67a7..14d9f5adcaa334fcca6762efba3a8bb54a909dc0 100644 (file)
@@ -1,24 +1,31 @@
 /*
- * 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
  *
@@ -299,7 +306,7 @@ alias_rtsp_out(struct ip *pip,
                                        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)) {
@@ -312,7 +319,7 @@ alias_rtsp_out(struct ip *pip,
                                        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 ';' */
index 6b6247775eaeb79d478abb1a0a9a322e4875f359..ab316013b4259414225b4dc6997fd557a7274653 100644 (file)
@@ -42,6 +42,7 @@
 .Nm
 .Op Fl n
 .Op Fl i Ar interface
+.Op Fl l
 .Fl a
 .Nm
 .Fl d Ar hostname
@@ -115,6 +116,8 @@ entries on
 .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
@@ -208,9 +211,10 @@ character will mark the rest of the line as a comment.
 .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 .
index 0b5c583f234b691429270fa4be4671589c4b52fa..665aa94d140b5a646a2632b80ba5be27e4eb9ae0 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -84,11 +112,16 @@ __FBSDID("$FreeBSD: src/usr.sbin/arp/arp.c,v 1.65.2.1 2008/04/25 16:38:14 sam Ex
 
 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);
@@ -99,6 +132,7 @@ static struct rt_msghdr *rtmsg(int cmd,
 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;
@@ -131,8 +165,10 @@ main(int argc, char *argv[])
        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;
@@ -143,6 +179,9 @@ main(int argc, char *argv[])
                case 'n':
                        nflag = 1;
                        break;
+               case 'l':
+                       lflag = 1;
+                       break;
                case 'S':
                        SETFUNC(F_REPLACE);
                        break;
@@ -167,7 +206,7 @@ main(int argc, char *argv[])
        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
@@ -179,7 +218,15 @@ main(int argc, char *argv[])
                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();
@@ -218,6 +265,8 @@ main(int argc, char *argv[])
                                        usage();
                                }
                        }
+                       if (i > argc)
+                               usage();
                        rtn = delete(argv[0], do_proxy);
                }
                break;
@@ -570,20 +619,23 @@ search(in_addr_t addr, action_fn *action)
 /*
  * 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
  */
@@ -614,7 +666,7 @@ print_entry(struct sockaddr_dl *sdl,
        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 ||
@@ -692,12 +744,18 @@ print_entry(struct sockaddr_dl *sdl,
  */
 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
@@ -705,7 +763,7 @@ usage(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]",
@@ -907,3 +965,148 @@ done:
        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");
+}
index 028951c72a2cbdf815a02b6eb745f2b428a968de..ccac9b02ebc558dcf8464dd5432d2db3e64f120c 100644 (file)
@@ -97,7 +97,9 @@ static struct sockaddr_in *sintab[] = {
 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;
index 54d039a1f66d4dc2d3f120b36916fb1157307e37..cd5e34a7f9c13c417a4fc4715e3fd60203548004 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -412,19 +440,19 @@ sec2str(time_t total)
 
                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);
 }
index ea42ff4ff6dc58e72998ea365f42e0273470a864..b855242f649a43ba9696cd627b20b728e64121e4 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -89,13 +117,14 @@ link_getaddr(const char *addr, int which)
        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);
index 18768283ced0bf64eeed694a2dbaf73957a68a07..5648409c09dcaad552ef2524f6eb90983c620d31 100644 (file)
@@ -120,7 +120,7 @@ slash notation) to include the netmask.
 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
@@ -266,7 +266,6 @@ When an interface is marked
 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
@@ -298,15 +297,15 @@ of the interface to
 .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
@@ -323,6 +322,59 @@ list of available options.
 .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
index 62bfd199827faa300857f2b2266c525c241cfb6c..934635033ce2c01dc997aadd2174efb26194f9c1 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -726,7 +754,7 @@ setifflags(const char *vname, int value, int s, const struct afswtch *afp)
                Perror(vname);
 }
 
-#ifndef __APPLE__
+#ifdef SIOCGIFCAP
 void
 setifcap(const char *vname, int value, int s, const struct afswtch *afp)
 {
@@ -795,11 +823,11 @@ setifname(const char *val, int dummy __unused, int s,
 #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
@@ -839,7 +867,7 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
 #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);
@@ -975,7 +1003,7 @@ ifmaybeload(const char *name)
                }
 
        /* 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);
 
@@ -1012,10 +1040,10 @@ static struct cmd basic_cmds[] = {
        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),
@@ -1039,39 +1067,65 @@ static struct cmd basic_cmds[] = {
        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
index f525154b906949c9fc96599a659e01843e23f212..5c364062e2e7610450b9342a34071418b1be5593 100644 (file)
@@ -402,7 +402,7 @@ static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
 
 #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;
index eec3ef15c2c7566a3411e8c103761f62b858852f..8e78ccb68d497e8977fc0c7348b9db86fbfed2f4 100644 (file)
@@ -181,12 +181,14 @@ static struct cmd vlan_cmds[] = {
        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",
diff --git a/ip6addrctl.tproj/ip6addrctl.8 b/ip6addrctl.tproj/ip6addrctl.8
new file mode 100644 (file)
index 0000000..59154d4
--- /dev/null
@@ -0,0 +1,126 @@
+.\"    $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)
diff --git a/ip6addrctl.tproj/ip6addrctl.c b/ip6addrctl.tproj/ip6addrctl.c
new file mode 100644 (file)
index 0000000..400412a
--- /dev/null
@@ -0,0 +1,467 @@
+/*     $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);
+}
diff --git a/ip6addrctl.tproj/ip6addrctl.conf b/ip6addrctl.tproj/ip6addrctl.conf
new file mode 100644 (file)
index 0000000..a2b3759
--- /dev/null
@@ -0,0 +1,12 @@
+# 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 
index cdbaf6b2074a5c24eca0d914b4a72481aecb96a5..ef3f9a8522bb44d8c04307f4421f4910ab83f112 100644 (file)
@@ -35,7 +35,7 @@
 .Os
 .Sh NAME
 .Nm ip6fw
-.Nd controlling utility for IPv6 firewall
+.Nd controlling utility for IPv6 firewall (DEPRECATED)
 .Sh SYNOPSIS
 .Nm
 .Op Fl q
index 82703ca41be371545cae0474bf34db89d83dec51..baaa620eddc3a98956da7a03eb0ed8e1687780e3 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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
@@ -208,7 +236,7 @@ show_ip6fw(struct ip6_fw *chain)
                {
                        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);
                }
@@ -738,7 +766,7 @@ fill_ip6opt(u_char *set, u_char *reset, char **vp)
 
 void
 fill_icmptypes(types, vp, fw_flg)
-       u_long *types;
+       unsigned *types;
        char **vp;
        u_short *fw_flg;
 {
@@ -760,7 +788,7 @@ fill_icmptypes(types, vp, 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;
        }
 }
@@ -1121,11 +1149,11 @@ badviacombo:
                        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
@@ -1272,7 +1300,7 @@ main(ac, av)
 #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;
@@ -1377,7 +1405,7 @@ main(ac, av)
 
                while (fgets(buf, BUFSIZ, f)) {
                        lineno++;
-                       sprintf(linename, "Line %d", lineno);
+                       snprintf(linename, sizeof(linename), "Line %d", lineno);
                        args[0] = linename;
 
                        if (*buf == '#')
index fc2c3436c47724261a4be686e8e9d8c32493f4a9..4136a3fe994bae78d0f63d38ac8b3ce07c0ca73a 100644 (file)
@@ -7,6 +7,7 @@
 .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
@@ -1560,31 +1566,10 @@ to circumvent firewalls.
 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
@@ -2058,15 +2043,12 @@ the sleep terminates thus restoring the previous situation.
 .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
index 9491dd9e8a1f19fe6ed811c032f764f8a686fdbd..c6c35af933c907d9b38f54d95b301c2cc5baa1fd 100644 (file)
@@ -1,24 +1,31 @@
 /*
- * 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
@@ -624,7 +631,7 @@ fill_newports(ipfw_insn_u16 *cmd, char *av, int proto)
                } 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;
@@ -632,7 +639,7 @@ fill_newports(ipfw_insn_u16 *cmd, char *av, int proto)
        }
        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;
@@ -960,7 +967,7 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
                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);
                }
@@ -970,7 +977,7 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
 #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 {
@@ -1485,17 +1492,17 @@ print_flowset_parms(struct dn_flow_set *fs, char *prefix)
        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),
@@ -1503,7 +1510,7 @@ print_flowset_parms(struct dn_flow_set *fs, char *prefix)
                    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);
@@ -1545,17 +1552,17 @@ list_pipes(void *data, uint nbytes, int ac, char *av[])
                 * 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)
@@ -1573,7 +1580,7 @@ list_pipes(void *data, uint nbytes, int ac, char *av[])
                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);
@@ -1629,13 +1636,13 @@ sets_handler(int ac, char *av[])
                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));
@@ -1651,14 +1658,14 @@ sets_handler(int ac, char *av[])
                } 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));
@@ -1678,7 +1685,7 @@ sets_handler(int ac, char *av[])
                                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;
@@ -1686,12 +1693,12 @@ sets_handler(int ac, char *av[])
                                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];
@@ -1701,7 +1708,7 @@ sets_handler(int ac, char *av[])
                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
@@ -1711,7 +1718,7 @@ sysctl_handler(int ac, char *av[], int which)
        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));
@@ -1728,7 +1735,7 @@ sysctl_handler(int ac, char *av[], int 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);
        }
 }
 
@@ -2045,7 +2052,7 @@ fill_ip(ipfw_insn_ip *cmd, char *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 */
@@ -2068,13 +2075,13 @@ fill_ip(ipfw_insn_ip *cmd, char *av)
 
                        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 */
@@ -2650,7 +2657,8 @@ fill_comment(ipfw_insn *cmd, int ac, char **av)
        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++ = ' ';
        }
@@ -2953,7 +2961,7 @@ add(int ac, char *av[])
                break;
 
        default:
-               errx(EX_DATAERR, "invalid action %s\n", av[-1]);
+               errx(EX_DATAERR, "invalid action %s", av[-1]);
        }
        action = next_cmd(action);
 
@@ -2988,7 +2996,7 @@ add(int ac, char *av[])
 #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') {                      \
@@ -3008,13 +3016,13 @@ add(int ac, char *av[])
                        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++;                                     \
        }
@@ -3163,7 +3171,7 @@ read_options:
 
                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++;
                }
@@ -3172,25 +3180,25 @@ read_options:
                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;
@@ -3482,7 +3490,7 @@ read_options:
                        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;
@@ -3739,6 +3747,8 @@ ipfw_main(int oldac, char **oldav)
        } 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;
 
@@ -3746,13 +3756,14 @@ ipfw_main(int oldac, char **oldav)
                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++;
@@ -4009,11 +4020,11 @@ ipfw_readfile(int ac, char *av[])
        }
 
        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);
index 4133e436098783ed90526069a8cf458f6da613f8..dfbb4bde4ffbad8511a5b806830e2acaafb2b798 100644 (file)
@@ -592,6 +592,9 @@ abort:
        return;
 }
 
+/* update if needed, when adding new errmsgs */
+#define MAXERRMSGLEN   40
+
 struct errmsg {
        int     e_code;
        char    *e_msg;
@@ -646,12 +649,19 @@ nak(error)
                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 *
diff --git a/mtest.tproj/COPYING b/mtest.tproj/COPYING
new file mode 100644 (file)
index 0000000..77bafa4
--- /dev/null
@@ -0,0 +1,27 @@
+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
diff --git a/mtest.tproj/mtest.8 b/mtest.tproj/mtest.8
new file mode 100644 (file)
index 0000000..b618cc0
--- /dev/null
@@ -0,0 +1,175 @@
+.\"
+.\" 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"
diff --git a/mtest.tproj/mtest.c b/mtest.tproj/mtest.c
new file mode 100644 (file)
index 0000000..0401832
--- /dev/null
@@ -0,0 +1,838 @@
+/*-
+ * 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");
+}
+
diff --git a/mtest.tproj/mtest.plist b/mtest.tproj/mtest.plist
new file mode 100644 (file)
index 0000000..8b726f1
--- /dev/null
@@ -0,0 +1,26 @@
+<?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>
index d9f687bc9b6fdbe9a71a765a6966d9afbb7cf6d5..3d88a1201fd6b4dfcad6b01a3713f7d04512e5b9 100644 (file)
@@ -33,6 +33,8 @@
 .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
@@ -462,29 +464,21 @@ This option enables MSS clamping.  The MSS value is derived from the
 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
@@ -512,23 +506,18 @@ The line
 .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
@@ -544,7 +533,7 @@ encouraged to create firewall rules that only allow traffic to and
 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
@@ -554,23 +543,10 @@ packets re-enter the firewall at the rule number following the rule number
 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 ,
index 2ec16213d2bddb5f803000d684eb67a2722e7b55..e47fd1c7c3cfd3f9b90b852ce8163ae3bcba5e95 100644 (file)
@@ -1,24 +1,31 @@
 /*
- * 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.
  *
@@ -829,7 +836,7 @@ static void FlushPacketBuffer (int fd)
                }
                else {
 
-                       sprintf (msgBuf, "failed to write packet back");
+                       snprintf (msgBuf, sizeof(msgBuf), "failed to write packet back");
                        Warn (msgBuf);
                }
        }
@@ -1272,13 +1279,13 @@ static char* FormatPacket (struct ip* ip)
        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,
@@ -1287,7 +1294,7 @@ static char* FormatPacket (struct ip* ip)
 
        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,
@@ -1296,7 +1303,7 @@ static char* FormatPacket (struct ip* ip)
 
        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,
@@ -1304,7 +1311,7 @@ static char* FormatPacket (struct ip* ip)
                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;
        }
 
@@ -2062,7 +2069,7 @@ void SetupPortRedirect (const char* parms)
        int             i;
        struct alias_link *link = NULL;
 
-       strcpy (buf, parms);
+       strlcpy (buf, parms, sizeof(buf));
 /*
  * Extract protocol.
  */
@@ -2193,7 +2200,7 @@ SetupProtoRedirect(const char* parms)
        char*           protoName;
        struct protoent *protoent;
 
-       strcpy (buf, parms);
+       strlcpy (buf, parms, sizeof(buf));
 /*
  * Extract protocol.
  */
@@ -2247,7 +2254,7 @@ void SetupAddressRedirect (const char* parms)
        char*           serverPool;
        struct alias_link *link;
 
-       strcpy (buf, parms);
+       strlcpy (buf, parms, sizeof(buf));
 /*
  * Extract local address.
  */
index 2ff0c346d8edc92aa709880ca9c67d7bd5a49dc8..a030fc5de358d98c66d41fde3ac1c027b40080fd 100644 (file)
@@ -39,7 +39,7 @@
 .Sh SYNOPSIS
 .Nm
 .Fl a
-.Op Fl nt
+.Op Fl lnt
 .Nm
 .Fl A Ar wait
 .Op Fl nt
@@ -136,6 +136,8 @@ turn on or off NUD (Neighbor Unreachability Detection) on the
 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
index 12a1746d7ffd6b886539d3e33c766e79ec217f13..096551b541656e2971b11e753b9626bc187eb9a2 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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 $    */
 
@@ -141,6 +169,7 @@ int set __P((int, char **));
 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 *));
@@ -176,7 +205,7 @@ main(argc, argv)
 {
        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);
@@ -220,7 +249,7 @@ main(argc, argv)
                        file(argv[2]);
                        exit(0);
                case 'l' :
-                       /* obsolete, ignored */
+                       lflag = 1;
                        break;
                case 'r' :
                        rflag = 1;
@@ -254,7 +283,10 @@ main(argc, argv)
        argv += optind;
 
        if (aflag || cflag) {
-               dump(0);
+               if (lflag)
+                       dump_ext(0);
+               else
+                       dump(0);
                exit(0);
        }
        if (dflag) {
@@ -624,6 +656,7 @@ again:;
                } 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)
@@ -748,6 +781,218 @@ again:;
        }
 }
 
+/*
+ * 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;
@@ -783,10 +1028,10 @@ ether_str(sdl)
 
        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);
@@ -814,7 +1059,7 @@ void
 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");
@@ -913,7 +1158,7 @@ ifinfo(argc, argv)
                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);
@@ -1030,9 +1275,12 @@ rtrlist()
                
                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]);
                
@@ -1054,7 +1302,7 @@ rtrlist()
                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);
@@ -1138,13 +1386,19 @@ plist()
                 * 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
@@ -1218,7 +1472,7 @@ plist()
                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);
@@ -1390,7 +1644,7 @@ pfx_flush()
 
        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)");
 }
@@ -1403,7 +1657,7 @@ rtr_flush()
 
        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)");
 
@@ -1418,7 +1672,7 @@ harmonize_rtr()
 
        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)");
 
@@ -1443,7 +1697,7 @@ setdefif(ifname)
        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)
@@ -1462,7 +1716,7 @@ getdefif()
                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)");
@@ -1496,17 +1750,17 @@ sec2str(total)
 
        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);
 }
index 881e8aedb4d8b5fb1c80e41c1bcd12330141519a..962a3ba40934002d514499096c812512882f1563 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -76,6 +76,7 @@ static const char rcsid[] =
 #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>
 
@@ -90,6 +91,7 @@ static const char rcsid[] =
 #include <unistd.h>
 #include <stdlib.h>
 #include <err.h>
+#include <errno.h>
 
 #include "netstat.h"
 
@@ -104,6 +106,8 @@ static const char rcsid[] =
 
 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 *);
@@ -120,10 +124,10 @@ show_stat(const char *fmt, int width, u_int64_t value, short showvalue)
 
        /* 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, "-");
        }
 }
@@ -184,6 +188,7 @@ multipr(int family, char *buf, char *lim)
                                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;
@@ -267,14 +272,25 @@ intpr(void (*pfunc)(char *))
                        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");
@@ -286,6 +302,13 @@ intpr(void (*pfunc)(char *))
     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;
@@ -326,6 +349,48 @@ intpr(void (*pfunc)(char *))
                        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) {
@@ -392,7 +457,7 @@ intpr(void (*pfunc)(char *))
                                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;
                        }
@@ -420,17 +485,33 @@ intpr(void (*pfunc)(char *))
                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) {
@@ -446,6 +527,7 @@ intpr(void (*pfunc)(char *))
                if (aflag) 
                        multipr(sa->sa_family, next, lim);
        }
+       free(buf);
 }
 
 struct iftot {
@@ -517,7 +599,7 @@ sidewaysintpr()
                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);;
                }
        }
@@ -537,7 +619,7 @@ sidewaysintpr()
        (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
@@ -546,13 +628,13 @@ banner:
        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);
@@ -569,7 +651,7 @@ loop:
                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;
@@ -685,7 +767,7 @@ loop:
                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)
@@ -720,7 +802,7 @@ loop:
                        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:
@@ -751,7 +833,7 @@ loop:
                                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);
@@ -762,7 +844,7 @@ loop:
                                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);
@@ -831,3 +913,165 @@ catchalarm(int signo )
 {
        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
+}
index c9660f639ef133f680a6a9699fdc7dfa40628a3d..ffad668e3680f621ebe4a5faf6820594b1133cb1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -22,8 +22,7 @@
  * 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
@@ -104,6 +103,10 @@ static const char rcsid[] =
 #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
@@ -188,24 +191,349 @@ _serv_cache_getservbyport(int port, char *proto)
  * 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;
@@ -218,12 +546,8 @@ protopr(uint32_t proto,            /* for sysctl version we pass proto # */
                        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)
@@ -231,26 +555,14 @@ protopr(uint32_t proto,           /* for sysctl version we pass proto # */
                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) {
@@ -268,37 +580,26 @@ protopr(uint32_t proto,           /* for sysctl version we pass proto # */
                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. */
@@ -343,11 +644,7 @@ protopr(uint32_t proto,            /* for sysctl version we pass proto # */
        "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");
@@ -362,18 +659,9 @@ protopr(uint32_t proto,            /* for sysctl version we pass proto # */
                }
                 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];
@@ -482,6 +770,7 @@ protopr(uint32_t proto,             /* for sysctl version we pass proto # */
        }
        free(buf);
 }
+#endif /* TARGET_OS_EMBEDDED */
 
 /*
  * Dump TCP statistics structure.
@@ -570,6 +859,7 @@ tcp_stats(uint32_t off , char *name, int af )
                "\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");
@@ -715,6 +1005,7 @@ ip_stats(uint32_t off , char *name, int af )
        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);
@@ -825,38 +1116,58 @@ icmp_stats(uint32_t off , char *name, int af )
 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
 }
 
 /*
@@ -870,9 +1181,9 @@ inetprint(struct in_addr *in, int port, char *proto, int numeric_port)
        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_
@@ -881,9 +1192,9 @@ inetprint(struct in_addr *in, int port, char *proto, int numeric_port)
                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);
@@ -923,14 +1234,14 @@ inetname(struct in_addr *inp)
                }
        }
        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);
index 164cb51ce2f64a7a8bf0f7eb5f34d05b4812dc12..0d8396e95f7002b0d3f91b42e723b179d366d1d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -166,7 +166,7 @@ static      char *ip6nh[] = {
        "no next header",       
        "destination option",
        "#61",
-       "#62",
+       "mobility",
        "#63",
        "#64",
        "#65",
@@ -518,7 +518,8 @@ ip6_stats(uint32_t off __unused, char *name, int af __unused)
 
        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);
 
@@ -545,7 +546,7 @@ ip6_ifstats(char *ifname)
                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) {
@@ -715,8 +716,8 @@ static      char *icmp6names[] = {
        "echo",
        "echo reply",   
        "multicast listener query",
-       "multicast listener report",
-       "multicast listener done",
+       "MLDv1 listener report",
+       "MLDv1 listener done",
        "router solicitation",
        "router advertisement",
        "neighbor solicitation",
@@ -727,7 +728,7 @@ static      char *icmp6names[] = {
        "node information reply",
        "inverse neighbor solicitation",
        "inverse neighbor advertisement",
-       "#143",
+       "MLDv2 listener report",
        "#144",
        "#145",
        "#146",
@@ -950,7 +951,7 @@ icmp6_ifstats(char *ifname)
                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) {
@@ -1118,15 +1119,15 @@ inet6print(struct in6_addr *in6, int port, char *proto, int numeric)
        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);
 }
@@ -1153,7 +1154,7 @@ inet6name(struct in6_addr *in6p)
                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;
        }
@@ -1168,7 +1169,7 @@ inet6name(struct in6_addr *in6p)
                }
        }
        if (IN6_IS_ADDR_UNSPECIFIED(in6p))
-               strcpy(line, "*");
+               strlcpy(line, "*", sizeof(line));
        else if (cp)
                strlcpy(line, cp, sizeof(line));
        else {
@@ -1178,6 +1179,7 @@ inet6name(struct in6_addr *in6p)
                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]);
index c30de8223c03927172abcaf8d169b055515fa160..f77b6f32e0b2bf317576ab3566fd887503003d57 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -284,10 +284,12 @@ int       Lflag;          /* show size of listen queues */
 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 */
@@ -307,7 +309,7 @@ main(argc, argv)
 
        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;
@@ -380,6 +382,9 @@ main(argc, argv)
                        }
                        pflag = 1;
                        break;
+               case 'R':
+                       Rflag = 1;
+                       break;
                case 'r':
                        rflag = 1;
                        break;
@@ -392,6 +397,9 @@ main(argc, argv)
                case 'u':
                        af = AF_UNIX;
                        break;
+               case 'v':
+                       vflag++;
+                       break;
                case 'W':
                        Wflag = 1;
                        break;
@@ -423,8 +431,11 @@ main(argc, argv)
                mbpr();
                exit(0);
        }
-       if (iflag && !sflag) {
-               intpr(NULL);
+       if (iflag && !sflag && !gflag) {
+               if (Rflag)
+                       intpr_ri(NULL);
+               else
+                       intpr(NULL);
                exit(0);
        }
        if (rflag) {
@@ -596,7 +607,7 @@ name2protox(char *name)
 #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\
index c5aacfa76d692e1249cc568e4cb3056d08da8c86..e130ef5e83c2bc1dc82f697e091f6e7f4496c431 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -65,6 +65,7 @@
 #include <sys/sysctl.h>
 
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include <errno.h>
 #include "netstat.h"
@@ -101,10 +102,14 @@ bool seen[256];                   /* "have we seen this type yet?" */
 
 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\
@@ -118,6 +123,12 @@ name          count    count    count    count    count    count\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);
@@ -265,6 +276,59 @@ mbpr(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 *
@@ -350,6 +414,44 @@ mbpr_getdata(void)
                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);
@@ -358,8 +460,15 @@ mbpr_getdata(void)
        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);
 }
index dcbfe0d869f9176d49592735a577161109e19768..6ea18bf65421fa540ff7a952762fafdec2316492 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -74,6 +74,8 @@
 #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>
 
@@ -110,14 +112,37 @@ typedef union sockunion sockunion_t;
 #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) : \
@@ -125,172 +150,14 @@ void ifmalist_dump_af(const struct ifmaddrs * const ifmap, int const af);
 #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:
@@ -328,10 +195,7 @@ ifmalist_dump_af(const struct ifmaddrs * const ifmap, int const af)
                        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:
@@ -415,7 +279,609 @@ ifmalist_dump(void)
        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);
+}
+
index 20fccfe5fe27feb1ec3e62ed321377225689bff1..04a9fe56d03bdc23544212d7cbf1bca5deb87fe6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -107,7 +107,7 @@ mroutepr(void)
 
        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;
        }
 
@@ -137,14 +137,14 @@ mroutepr(void)
                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;
@@ -188,7 +188,7 @@ mrt_stats()
        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;
        }
 
index ce0642be27a3a8614d9ad998ea02404476f956f4..549740f452bf867646f4281002843aa4b33c4c89 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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;
@@ -138,7 +139,7 @@ mroute6pr(void)
 
        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;
        }
 
@@ -182,7 +183,7 @@ mroute6pr(void)
        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;
        }
@@ -235,6 +236,7 @@ mroute6pr(void)
        nflag = saved_nflag;
 
        free(mf6ctable);
+#endif
 }
 
 void
@@ -245,7 +247,7 @@ mrt6_stats(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");
index 7fa01d2a27e359d9021845c3918435642f3fa7da..c54ef88b84bd4ba30afca9cfcc1b02062bf5ef16 100644 (file)
 .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
@@ -124,10 +126,19 @@ and
 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
@@ -197,9 +208,15 @@ is also present,
 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.
@@ -345,7 +362,6 @@ option.
 .Xr fstat 1 ,
 .Xr nfsstat 1 ,
 .Xr ps 1 ,
-.Xr sockstat 1 ,
 .Xr inet 4 ,
 .Xr unix 4 ,
 .Xr hosts 5 ,
index b53e5b063a65cbbb916ef9fb46a2b062b418fac8..bcc42145557abaa1df57bd5f02a59d6b981f6fca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -78,10 +78,12 @@ extern int  lflag;  /* show routing table with use and ref */
 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 */
@@ -134,6 +136,7 @@ extern void pfkey_stats(uint32_t, char *, int);
 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);
 
index e7b820581a3b91e4f9e375fefa92e55f27460928..885a19bd86905fa6626d47ccca2c6ca2897e64d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -375,6 +375,7 @@ p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
                 * 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]);
@@ -396,7 +397,7 @@ p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
 
                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) {
 
@@ -407,7 +408,7 @@ p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
 
                                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;
@@ -427,11 +428,11 @@ p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
 
                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;
            }
@@ -481,7 +482,7 @@ routename(uint32_t in)
        } 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);
@@ -524,9 +525,9 @@ domask(char *dst, uint32_t addr, uint32_t mask)
                        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);
 }
 
 /*
@@ -560,26 +561,26 @@ netname(uint32_t in, uint32_t mask)
                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;
                }
@@ -648,7 +649,7 @@ netname6(struct sockaddr_in6 *sa6, struct sockaddr *sam)
                    NULL, 0, flag);
 
        if (nflag)
-               sprintf(&line[strlen(line)], "/%d", masklen);
+               snprintf(&line[strlen(line)], sizeof(line) - strlen(line), "/%d", masklen);
 
        return line;
 }
index 57072661bf1640cccc6f48d2946e00c7cddcdac4..0e4960857459258b9188b2d113f297cc82670a55 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -112,9 +112,9 @@ unixpr()
 
        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) {
index ccf6127126a1f1d22cb71052b48fdc280ba0a67d..ca9bdf623687a7d883fd36938836481e1cd9eead 100644 (file)
@@ -17,6 +17,7 @@
                                03B2DBD1100BE626005349BC /* PBXTargetDependency */,
                                034E4469100BDD00009CA3DC /* PBXTargetDependency */,
                                03B2DBC5100BE332005349BC /* PBXTargetDependency */,
+                               690D97BC12DE7151004323A7 /* PBXTargetDependency */,
                                034E4475100BDEC6009CA3DC /* PBXTargetDependency */,
                                034E447B100BDF0D009CA3DC /* PBXTargetDependency */,
                                03B2DBD3100BE645005349BC /* PBXTargetDependency */,
@@ -34,6 +35,7 @@
                        buildPhases = (
                        );
                        dependencies = (
+                               4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */,
                                726121470EE8717B00AFED1B /* PBXTargetDependency */,
                                726121490EE8717B00AFED1B /* PBXTargetDependency */,
                                7261217D0EE8896800AFED1B /* PBXTargetDependency */,
@@ -41,6 +43,7 @@
                                724DAB790EE88EA6008900D0 /* PBXTargetDependency */,
                                724DAB9A0EE88F5D008900D0 /* PBXTargetDependency */,
                                724DABC30EE890A6008900D0 /* PBXTargetDependency */,
+                               690D97BE12DE7166004323A7 /* PBXTargetDependency */,
                                724DABEC0EE891DF008900D0 /* PBXTargetDependency */,
                                724DAC240EE89525008900D0 /* PBXTargetDependency */,
                                7216D2670EE8978F00AE70E4 /* PBXTargetDependency */,
@@ -66,6 +69,7 @@
                                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 = (
index 1f5478a162178027ceb776dcb4f4a7de9f1dc11a..feb8e7653b59ee9d253e4c0ea11413c2126e0916 100644 (file)
@@ -38,7 +38,7 @@
 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
@@ -118,6 +118,8 @@ if other format options are present.
 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)
@@ -522,7 +524,8 @@ if an error occurred.
 .Xr netstat 1 ,
 .Xr ifconfig 8 ,
 .Xr routed 8 ,
-.Xr traceroute 8
+.Xr traceroute 8 ,
+.Xr ping6 8
 .Sh HISTORY
 The
 .Nm
index b0a8f0d877b9dddc6cdc53c933f207876dcec67b..7227bd42a8c9298cfcc6cd10e9218571d0dda168 100644 (file)
@@ -120,6 +120,7 @@ __FBSDID("$FreeBSD: src/sbin/ping/ping.c,v 1.112 2007/07/01 12:08:06 gnn Exp $")
 #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))
@@ -205,8 +206,10 @@ unsigned int ifscope;
 #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 */
@@ -243,7 +246,7 @@ static char *pr_addr(struct in_addr);
 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);
@@ -274,7 +277,7 @@ main(argc, argv)
        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 */
@@ -304,7 +307,7 @@ main(argc, argv)
 
        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:"
@@ -331,6 +334,9 @@ main(argc, argv)
                case 'b':
                        boundif = optarg;
                        break;
+               case 'C':
+                       nocell++;
+                       break;
                case 'c':
                        ultmp = strtoul(optarg, &ep, 0);
                        if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp)
@@ -641,6 +647,30 @@ main(argc, argv)
                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");
 
@@ -678,15 +708,25 @@ main(argc, argv)
                        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
@@ -899,6 +939,7 @@ main(argc, argv)
                struct timeval now, timeout;
                fd_set rfds;
                int cc, n;
+               int tc = -1;
 
                check_status();
                if ((unsigned)s >= FD_SETSIZE)
@@ -935,20 +976,28 @@ main(argc, argv)
                                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;
@@ -1122,11 +1171,12 @@ pinger(void)
  * 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;
@@ -1213,9 +1263,11 @@ pr_pack(buf, cc, from, tv)
                        (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);
index 82c52ce4066f3c433c348bb35264173a6ac2254c..d6f4cb0328144e3d94e9982b1d2a11ae13421fa6 100644 (file)
@@ -40,7 +40,7 @@ packets to network hosts
 .Sh SYNOPSIS
 .Nm
 .\" without ipsec, or new ipsec
-.Op Fl dfHmnNoqtvwW
+.Op Fl CdfHmnNoqtvwW
 .\" old ipsec
 .\" .Op Fl AdEfmnNqRtvwW
 .Bk -words
@@ -50,6 +50,9 @@ packets to network hosts
 .Op Fl b Ar bufsiz
 .Ek
 .Bk -words
+.Op Fl B Ar boundif
+.Ek
+.Bk -words
 .Op Fl c Ar count
 .Ek
 .Bk -words
@@ -138,6 +141,12 @@ This is an experimental option.
 .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)
@@ -247,6 +256,22 @@ specifies IPsec policy to be used for the probe.
 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,
@@ -414,7 +439,9 @@ option of
 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
index b14564f109d3e96c390de6404d5c9ab3369d7b8b..4892b95a665de1536f48ade082f87d5fe02373c0 100644 (file)
@@ -78,7 +78,7 @@ static const char copyright[] =
 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 */
 
 /*
@@ -193,6 +193,8 @@ struct tv32 {
 #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;
 
@@ -203,7 +205,6 @@ 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
@@ -221,19 +222,23 @@ int datalen = DEFDATALEN;
 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 */
@@ -259,11 +264,15 @@ volatile sig_atomic_t seeninfo;
 
 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);
@@ -356,7 +365,7 @@ main(argc, argv)
 #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':
@@ -416,6 +425,12 @@ main(argc, argv)
 "-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')
@@ -474,6 +489,11 @@ main(argc, argv)
                        }
                        options |= F_INTERVAL;
                        break;
+               case 'k':
+                       how_so_traffic_class++;
+                       so_traffic_class = atoi(optarg);
+                       break;
+                       
                case 'l':
                        if (getuid()) {
                                errno = EPERM;
@@ -507,6 +527,12 @@ main(argc, argv)
                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? */
@@ -591,6 +617,9 @@ main(argc, argv)
                }
        }
 
+       if (boundif != NULL && (ifscope = if_nametoindex(boundif)) == 0)
+               errx(1, "bad interface name");
+
        argc -= optind;
        argv += optind;
 
@@ -626,7 +655,6 @@ main(argc, argv)
        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;
 
@@ -650,6 +678,18 @@ main(argc, argv)
            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) {
@@ -860,7 +900,7 @@ main(argc, argv)
                        err(1, "setsockopt(IPV6_TCLASS)");
        }
 
-/*
+       /*
        optval = 1;
        if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
                if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
@@ -878,6 +918,18 @@ main(argc, argv)
        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)
@@ -976,7 +1028,14 @@ main(argc, argv)
 
                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
@@ -988,6 +1047,18 @@ main(argc, argv)
                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);
@@ -1074,7 +1145,7 @@ main(argc, argv)
 #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()),
@@ -1121,11 +1192,9 @@ main(argc, argv)
 
                /* 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;
@@ -1223,9 +1292,14 @@ main(argc, argv)
                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
@@ -1276,7 +1350,7 @@ retransmit()
        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);
 }
 
@@ -1537,8 +1611,9 @@ pr_pack(buf, cc, mhdr)
        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 ||
@@ -1576,6 +1651,9 @@ pr_pack(buf, cc, mhdr)
                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;
@@ -1609,6 +1687,8 @@ pr_pack(buf, cc, mhdr)
                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);
@@ -1630,6 +1710,10 @@ pr_pack(buf, cc, mhdr)
                                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;
@@ -2279,7 +2363,25 @@ get_tclass(mhdr)
        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 --
@@ -2849,9 +2951,9 @@ usage()
 #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
index 7d365d5c12b3ee58e6522d626eff43351b15b941..d26a1e4582bf36409c05eeb99117f9c529b81ac1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2009 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -288,7 +288,7 @@ bpf_open()
 
        /* 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);
 
@@ -491,7 +491,7 @@ rarp_bootable(addr)
        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);
index 3edd2347ead26ba8b8028c83fa5407872c28a620..74609c9b06931e6714dac27918888ecf572b669e 100644 (file)
@@ -64,12 +64,18 @@ programmatic interface discussed in
 .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
@@ -211,7 +217,7 @@ Alternately, if the interface is point to point the name of the interface
 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
index c43f159bf73776465be62ced55b5d37233062bba..818bdd0fbf7cdf9a0a50c6f12ed2060f88140889 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -125,6 +125,8 @@ int locking, lockrest, debugonly;
 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();
@@ -185,7 +187,7 @@ main(argc, argv)
        argv += optind;
 
        pid = getpid();
-       uid = getuid();
+       uid = geteuid();
        if (tflag)
                s = open(_PATH_DEVNULL, O_WRONLY, 0);
        else
@@ -326,13 +328,13 @@ routename(sa)
                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:
@@ -359,7 +361,7 @@ routename(sa)
                        /* 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;
@@ -381,6 +383,7 @@ routename(sa)
 #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 =
@@ -405,7 +408,7 @@ routename(sa)
        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 */
@@ -469,15 +472,15 @@ netname(sa)
                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;
@@ -499,6 +502,7 @@ netname(sa)
 #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 =
@@ -524,7 +528,7 @@ netname(sa)
        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)
@@ -535,6 +539,22 @@ netname(sa)
        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;
@@ -567,7 +587,7 @@ newroute(argc, argv)
        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;
@@ -770,21 +790,7 @@ newroute(argc, argv)
        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));
        }
 }
 
@@ -833,6 +839,36 @@ inet_makenetandmask(net, sin, bits)
        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.
@@ -925,6 +961,7 @@ getaddr(which, s, hpp)
                case RTA_NETMASK:
                case RTA_GENMASK:
                        /* bzero(su, sizeof(*su)); *//* for readability */
+                       su->sa.sa_len = 0;
                        break;
                }
                return (0);
@@ -934,21 +971,27 @@ getaddr(which, s, hpp)
        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);
@@ -956,7 +999,15 @@ getaddr(which, s, hpp)
                }
 #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 */
 
@@ -1170,7 +1221,7 @@ rtmsg(cmd, flags)
        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) {
@@ -1300,10 +1351,10 @@ print_rtmsg(rtm, msglen)
                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);
        }
index 2a52ff266f09987679898d2892a9fb5eb2812155..cc01ae2a2b03c80b845b5fb83f7aca1b70f2c201 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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 $  */
 
 /*
@@ -206,7 +234,7 @@ tnchktc()
        /* 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++;
@@ -221,11 +249,13 @@ tnchktc()
        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);
 }
index 098f161deba6b1a4d41492af7b6ab8a37c82e263..c2746e9e43b0368557b125bdf7128abf72dfed6f 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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;
@@ -121,6 +149,7 @@ getconfig(intface)
        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) {
@@ -313,7 +342,7 @@ getconfig(intface)
 
                        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,
@@ -323,7 +352,7 @@ getconfig(intface)
                        }
                        pfx->prefixlen = (int)val;
 
-                       makeentry(entbuf, i, "pinfoflags", added);
+                       makeentry(entbuf, sizeof(entbuf), i, "pinfoflags", added);
 #ifdef MIP6
                        if (mobileip6)
                        {
@@ -342,7 +371,7 @@ getconfig(intface)
                        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,
@@ -352,7 +381,7 @@ getconfig(intface)
                        }
                        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);
@@ -360,7 +389,7 @@ getconfig(intface)
                                        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,
@@ -370,7 +399,7 @@ getconfig(intface)
                        }
                        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);
@@ -378,7 +407,7 @@ getconfig(intface)
                                        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,
@@ -457,7 +486,7 @@ getconfig(intface)
                /* 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,
@@ -467,7 +496,7 @@ getconfig(intface)
                }
                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) {
@@ -476,7 +505,7 @@ getconfig(intface)
                        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 
@@ -492,7 +521,7 @@ getconfig(intface)
                }
                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,
@@ -531,6 +560,65 @@ getconfig(intface)
 #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;
@@ -626,16 +714,14 @@ get_prefix(struct rainfo *rai)
 }
 
 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';
        }
 }
@@ -818,6 +904,8 @@ make_packet(struct rainfo *rainfo)
                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) {
@@ -963,6 +1051,27 @@ make_packet(struct rainfo *rainfo)
        }
 #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;
 }
 
index 435830f4d7dd3809cba15f0d7b68f132c0af0786..03f4575ba17649cecfc9a250c8f2b6728f4a60ff 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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 $   */
 
 /*
@@ -89,11 +117,11 @@ ether_str(sdl)
 
        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);
index 89224411333c56421dec8d2abecd438d8d2d653b..c9e9ba31f15392ac2ff75d90d8a0d2fd1ce41088 100644 (file)
@@ -28,7 +28,7 @@
 .\" 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
@@ -159,7 +159,7 @@ for such prefixes.
 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
@@ -275,7 +275,7 @@ These items are optional.
 .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
@@ -320,6 +320,47 @@ capability.
 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
@@ -376,6 +417,12 @@ Richard Draves,
 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
index 8845a2e2518d8010767f161d38ba422bd0a264ee..332b799b7e4fc258b94865dc7ec394a3c9c800a4 100644 (file)
@@ -104,6 +104,13 @@ struct soliciter {
        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;
@@ -146,6 +153,11 @@ struct     rainfo {
        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;
index 7ac8e1f22644004c8ee445bc66d85fe7ae46c65b..c42f8f545d4ec6a8a7f865d966112f4e3b39012e 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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 $    */
 
 /*
@@ -126,17 +154,17 @@ sec2str(total)
 
        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);
 }
index 73d279dd18195f9a4783fabe7df476e14d54ae33..d361c27902a31f249f63df6ba3d2f6400e3ba0df 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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 $     */
 
 /*
@@ -354,7 +382,7 @@ get_llflag(const char *name)
                        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__,
@@ -416,7 +444,7 @@ get_llflag(const char *name)
                        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__,
index 75d3177de4bd1ddccd55e6c2bf9be2fc4dcb57c4..305d0a21c5cc1a92efcf34f15f12f0e24cb66eca 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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 $  */
 
 /*
@@ -82,11 +110,13 @@ probe_init()
                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);
@@ -113,7 +143,7 @@ defrouter_probe(int ifindex)
                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));
index c4ed066e2c366a0e7ed862b439cfd2fa0835435c..88ca8bfe2c72119f3d51b8ab5ba1564bdb06bd8e 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -116,7 +144,7 @@ findsaddr(register const struct sockaddr_in *to,
 
        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);
        }
 
@@ -136,12 +164,12 @@ findsaddr(register const struct sockaddr_in *to,
 
        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);
        }
@@ -151,7 +179,7 @@ findsaddr(register const struct sockaddr_in *to,
                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);
                }
@@ -161,15 +189,15 @@ findsaddr(register const struct sockaddr_in *to,
 
 
        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);
        }
 
index 283491cda3b83ffd492f104e48491adae9e42ac1..ed45494f62b7d54a7d4e19ec2eb2b90c5ee8681b 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -72,7 +100,7 @@ struct rtentry;
  * 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
@@ -89,7 +117,7 @@ ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf)
 
        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);
@@ -98,11 +126,11 @@ ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf)
        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);
@@ -135,7 +163,7 @@ ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf)
                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);
@@ -155,14 +183,14 @@ ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf)
                        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);
index 8b7dc99637b6fe105f95de330e5a0fade15ec26f..53d91d9da985aadff2679a58d9b2c69cc989b196 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -26,4 +54,4 @@ struct ifaddrlist {
        char *device;
 };
 
-int    ifaddrlist(struct ifaddrlist **, char *);
+int    ifaddrlist(struct ifaddrlist **, char *, size_t );
index ca1a5f33c58514e1ec33e822fe4f4dc700cd9eda..c726d7ac93e148ce86c10e46db70d28e7b131bb0 100644 (file)
@@ -422,7 +422,8 @@ by a cast of thousands with particularly cogent suggestions or fixes from
 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
index d74246004c3280436f7246f0384ad209820e306e..ec6b9587f91eb940b1751e17af760911c4ebed8e 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * 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.
@@ -849,7 +877,7 @@ main(int argc, char **argv)
                    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);