]> git.saurik.com Git - apple/network_cmds.git/commitdiff
network_cmds-511.tar.gz macos-1012 macos-10121 macos-10122 macos-10123 os-x-1012 v511
authorApple <opensource@apple.com>
Sat, 11 Jun 2016 02:35:45 +0000 (02:35 +0000)
committerApple <opensource@apple.com>
Sat, 11 Jun 2016 02:35:45 +0000 (02:35 +0000)
25 files changed:
frame_delay/frame_delay.8 [new file with mode: 0644]
frame_delay/frame_delay.c [new file with mode: 0644]
ifconfig.tproj/af_inet6.c
ifconfig.tproj/ifconfig.8
ifconfig.tproj/ifconfig.c
ip6fw.tproj/ip6fw.8 [deleted file]
ip6fw.tproj/ip6fw.c [deleted file]
ipfw.tproj/ipfw.8 [deleted file]
ipfw.tproj/ipfw2.c [deleted file]
kdumpd.tproj/kdumpd.c
ndp.tproj/ndp.8
ndp.tproj/ndp.c
netstat.tproj/if.c
netstat.tproj/inet.c
netstat.tproj/inet6.c
netstat.tproj/mptcp.c
netstat.tproj/systm.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
pktmnglr/packet_mangler.c
route.tproj/route.c

diff --git a/frame_delay/frame_delay.8 b/frame_delay/frame_delay.8
new file mode 100644 (file)
index 0000000..0f454d5
--- /dev/null
@@ -0,0 +1,45 @@
+.Dd October 12, 2015
+.Dt FRAME_DELAY 8
+.Os Darwin
+.Sh NAME
+.Nm frame_delay
+.Nd Utility to measure TCP/UDP frame delay
+
+.Sh DESCRIPTION
+.Pp
+The
+.Nm
+utility is designed to measure the effect of latency on
+delivery of evenly spaced TCP/UDP frames. This can be latency induced
+due to buffering or protocol stack or network drivers.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl m
+Server/Client mode. Should be "server" or "client".
+.It Fl t
+TCP/UDP frame. Should be either "tcp" or "udp".
+.It Fl i
+(Client Only) Server ip address.
+.It Fl p
+Port number.
+.It Fl n
+Number of frames.
+.It Fl f
+Frame size.
+.It Fl d
+(Client only) Delay traffic class. Pick one from {BK_SYS, BK, BE, RD, QAM, AV, RV, VI, VO, CTL}.
+.El
+
+.Sh EXAMPLES
+.Pp
+Setup TCP server:
+.Dl "frame_delay -m server -t tcp -p 10010 -n 10 -f 1000"
+.Pp
+Setup corresponding TCP client:
+.Dl "frame_delay -m client -t tcp -i 127.0.0.1 -p 10010 -n 10 -f 1000 -d 2000  -k RD"
+
+.Sh AUTHORS
+.An Padma Bhooma ,
+.An Kang Sun ,
+.An Vincent Lubet .
\ No newline at end of file
diff --git a/frame_delay/frame_delay.c b/frame_delay/frame_delay.c
new file mode 100644 (file)
index 0000000..37a58b7
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2009-2015 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@
+ */
+
+/*
+ * Usage for frame_delay
+ *
+ * Server
+ *     ./frame_delay -m server -t <tcp/udp> -p <port> -n <num_frames> -f <frame_size>
+ *
+ * Client
+ *     ./frame_delay -m client -t <tcp/udp> -i <srv_ipv4_add> -p <srv_port> -n <num_frames> -f <frame_size> -d <delay_ms>  -k <traffic_class>
+ */
+
+/*
+ * TODO list :
+ *                             1. UDP fragmentation and reassembly
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+
+/* Server Static variable */
+static int so, srv_so;
+static int srv_port = 0;
+static struct sockaddr_in laddr, dst_addr;
+/* Client Static variable */
+static struct sockaddr_in srv_addr;
+static uint32_t tc = 0;
+/* Usage */
+void ErrorUsage(void);
+/* str2svc */
+uint32_t str2svc(const char *str);
+/* Show Stastics */
+void ShowStastics(int64_t *DiffsBuf, int num_frames);
+/* Returns difference between two timevals in microseconds */
+int64_t time_diff(struct timeval *b, struct timeval *a);
+/* tcp server */
+void tcpServer(int frame_size, int num_frames, char *buf, int64_t *DiffsBuf);
+/* udp server */
+void udpServer(int frame_size, int num_frames, char *buf, int64_t *DiffsBuf);
+/* tcp server */
+void tcpClient(int num_frames, int frame_size,
+                          const char *buf, struct timespec sleep_time);
+/* udp server */
+void udpClient(int num_frames, int frame_size,
+                          const char *buf, struct timespec sleep_time);
+
+/* Main function */
+int
+main(int argc, char *argv[])
+{
+       int num_frames = 0, frame_size = 0, delay_ms = 0, rc = 0;
+       char *buf = NULL, ch, *type = NULL, *mode = NULL, *ip_addr = NULL;
+       int64_t *DiffsBuf;
+       struct timespec sleep_time;
+
+       while ((ch = getopt(argc, argv, "m:p:f:n:t:d:i:k:")) != -1) {
+               switch (ch) {
+                       case 'm': {
+                               mode = optarg;
+                               break;
+                       }
+                       case 'p': {
+                               srv_port = atoi(optarg);
+                               break;
+                       }
+                       case 'f' : {
+                               frame_size = atoi(optarg);
+                               break;
+                       }
+                       case 'n' : {
+                               num_frames = atoi(optarg);
+                               break;
+                       }
+                       case 'i': {
+                               ip_addr = optarg;
+                               bzero(&srv_addr, sizeof(srv_addr));
+                               rc = inet_aton(optarg, &srv_addr.sin_addr);
+                               if (rc == 0) {
+                                       perror("inet_ntoa failed");
+                                       exit(1);
+                               }
+                       }
+                       case 'd': {
+                               delay_ms = atoi(optarg);
+                               break;
+                       }
+                       case 't' : {
+                               type = optarg;
+                               break;
+                       }
+                       case 'k': {
+                               tc = str2svc(optarg);
+                               break;
+                       }
+                       default: {
+                               printf("Invalid option: %c\n", ch);
+                               ErrorUsage();
+                       }
+               }
+       }
+       /* General check for both server and client */
+       if (srv_port <= 0 || frame_size <= 0 || num_frames <= 0 || !mode || !type) {
+               ErrorUsage();
+       }
+       if ( strcmp(type, "tcp") != 0 && strcmp(type, "udp") != 0 ) {
+               ErrorUsage();
+       }
+       /* Allocate memory for buf */
+       buf = calloc(1, frame_size);
+       if (buf == NULL) {
+               printf("malloc failed\n");
+               exit(1);
+       }
+       if ( strcmp(mode, "server") == 0 ) {
+               /* Server */
+               printf("<LOG>   :   Start %s server on port %d with expected frame size of %d\n",
+                          type, srv_port, frame_size);
+               DiffsBuf = (int64_t *)calloc(num_frames, sizeof(int64_t));
+               if (DiffsBuf == NULL) {
+                       printf("malloc failed\n");
+                       exit(1);
+               }
+               if( strcmp(type, "tcp") == 0) {
+                       /* tcpServer */
+                       tcpServer(frame_size, num_frames, buf, DiffsBuf);
+               } else {
+                       /* updServer */
+                       udpServer(frame_size, num_frames, buf, DiffsBuf);
+               }
+       }
+       else if ( strcmp(mode, "client") == 0 ){
+               if ( !ip_addr || (tc > 0 && (tc < SO_TC_BK_SYS || tc > SO_TC_CTL)) ){
+                       ErrorUsage();
+                }
+               /* Client */
+               printf("<LOG>   :   Start sending %d %s frames to %s:%d with a frame size of %d\n",
+                          num_frames, type, ip_addr, srv_port, frame_size);
+               /* Resolving sleep time bug : delay_ms should just be calculated once */
+               bzero(&sleep_time, sizeof(sleep_time));
+               while (delay_ms >= 1000) {
+                       sleep_time.tv_sec++;
+                       delay_ms -= 1000;
+               }
+               sleep_time.tv_nsec = delay_ms * 1000 * 1000;
+               if( strcmp(type, "tcp") == 0) {
+                       /* Call TCP client */
+                       tcpClient(num_frames, frame_size, buf, sleep_time);
+               } else {
+                       /* Call UDP client */
+                       udpClient(num_frames, frame_size, buf, sleep_time);
+               }
+       } else {
+               ErrorUsage();
+       }
+}
+
+/* Error usage */
+void
+ErrorUsage(void) {
+       printf("Correct Usage");
+       printf("Server : frame_delay -m server -t <tcp/udp> -p <port> -n <num_frames> -f <frame_size>\n");
+       printf("Client : frame_delay -m client -t <tcp/udp> -i <srv_ipv4_add> -p <srv_port> -n <num_frames> -f <frame_size> -d <delay_ms>  -k <traffic_class>\n");
+       exit(1);
+}
+
+/* str2svc */
+uint32_t
+str2svc(const char *str)
+{
+       uint32_t svc;
+       char *endptr;
+
+       if (str == NULL || *str == '\0')
+               svc = UINT32_MAX;
+       else if (strcasecmp(str, "BK_SYS") == 0)
+               return SO_TC_BK_SYS;
+       else if (strcasecmp(str, "BK") == 0)
+               return SO_TC_BK;
+       else if (strcasecmp(str, "BE") == 0)
+               return SO_TC_BE;
+       else if (strcasecmp(str, "RD") == 0)
+               return SO_TC_RD;
+       else if (strcasecmp(str, "OAM") == 0)
+               return SO_TC_OAM;
+       else if (strcasecmp(str, "AV") == 0)
+               return SO_TC_AV;
+       else if (strcasecmp(str, "RV") == 0)
+               return SO_TC_RV;
+       else if (strcasecmp(str, "VI") == 0)
+               return SO_TC_VI;
+       else if (strcasecmp(str, "VO") == 0)
+               return SO_TC_VO;
+       else if (strcasecmp(str, "CTL") == 0)
+               return SO_TC_CTL;
+       else {
+               svc = (uint32_t)strtoul(str, &endptr, 0);
+               if (*endptr != '\0')
+                       svc = UINT32_MAX;
+       }
+       return (svc);
+}
+
+/* Show Stastics */
+void
+ShowStastics(int64_t *DiffsBuf, int num_frames) {
+       int i = 0;
+       int64_t sum = 0, mean = 0;
+
+       /* Mean */
+       while(i < num_frames)
+               sum += DiffsBuf[i++];
+       mean = sum / num_frames;
+       printf("<LOG>   :   Mean: %.2f usecs\n", sum / (double)num_frames);
+       /* Popular Standard Deviation */
+       i = 0;
+       sum = 0;
+       while(i < num_frames) {
+               sum += (DiffsBuf[i]-mean)*(DiffsBuf[i]-mean);
+               i++;
+       }
+       printf("<LOG>   :   Popular Standard Deviation: %.2f usecs\n",
+                  sqrt(sum/(double)num_frames));
+}
+
+/* Returns difference between two timevals in microseconds */
+int64_t
+time_diff(struct timeval *b, struct timeval *a)
+{
+       int64_t usecs;
+       usecs = (a->tv_sec - b->tv_sec) * 1000 * 1000;
+       usecs += (int64_t)(a->tv_usec - b->tv_usec);
+       return(usecs);
+}
+
+/* Server */
+
+/* tcp server */
+void
+tcpServer(int frame_size, int num_frames, char *buf, int64_t *DiffsBuf) {
+       int rc = 0, i = 0, ignore_count = 0;
+       uint32_t dst_len = 0;
+       struct timeval before, after;
+       ssize_t bytes;
+       int64_t usecs;
+       /* New change from Padama */
+       uint64_t prev_frame_ts = 0, prev_recv = 0, frame_ts = 0, cur_recv = 0;
+       uint64_t min_variation = 0, max_variation = 0, avg_variation = 0;
+
+       printf("<LOG>   :   TCP Server\n");
+       so = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (so == -1) {
+               perror("failed to create socket");
+               exit(1);
+       }
+       bzero(&laddr, sizeof(laddr));
+       laddr.sin_family = AF_INET;
+       laddr.sin_port = htons(srv_port);
+       rc = bind(so, (const struct sockaddr *)&laddr, sizeof(laddr));
+       if (rc != 0) {
+               perror("failed to bind");
+               exit(1);
+       }
+       rc = listen(so, 10);
+       if (rc != 0) {
+               perror("failed to listen");
+               exit(1);
+       }
+       srv_so = accept(so, (struct sockaddr *)&dst_addr, &dst_len);
+       if (srv_so == -1) {
+               perror("failed to accept");
+               exit(1);
+       }
+       while (1) {
+               if ( i == num_frames ) {
+                       printf("<LOG>   :   Completed\n");
+                       break;
+               }
+               printf("<LOG>   :   Waiting for receiving\n");
+               bzero(&before, sizeof(before));
+               bzero(&after, sizeof(after));
+               rc = gettimeofday(&before, NULL);
+               if (rc == -1) {
+                       perror("gettimeofday failed");
+                       exit(1);
+               }
+               bytes = recv(srv_so, buf, frame_size, MSG_WAITALL);
+               if (bytes == -1) {
+                       perror("recv failed");
+                       exit(1);
+               }
+               else if (bytes > 0 && bytes != frame_size) {
+                       printf("Client exited\n");
+                       printf("Didn't recv the complete frame, bytes %ld\n",
+                                  bytes);
+                       exit(1);
+               }
+               else if (bytes == 0) {
+                       break;
+               }
+               rc = gettimeofday(&after, NULL);
+               if (rc == -1) {
+                       perror("gettimeofday failed");
+                       exit(1);
+               }
+               cur_recv = after.tv_sec * 1000 * 1000 + after.tv_usec;
+               memcpy((void *)&frame_ts, buf, sizeof(frame_ts));
+               if (prev_frame_ts > 0) {
+                       int64_t d_variation = 0;
+                       d_variation = (int64_t)((cur_recv - prev_recv) -
+                                                                       (frame_ts - prev_frame_ts));
+                       /* printf("Frame %u ts %llu d_variation %lld usecs\n",
+                        i, frame_ts, d_variation);*/
+                       if (d_variation > 0) {
+                               if (min_variation == 0)
+                                       min_variation = d_variation;
+                               else
+                                       min_variation = ((min_variation <= d_variation) ?
+                                                                        min_variation : d_variation);
+                               max_variation = ((max_variation >= d_variation) ?
+                                                                max_variation : d_variation);
+                               avg_variation += d_variation;
+                       } else {
+                               ignore_count++;
+                       }
+               }
+               prev_recv = cur_recv;
+               prev_frame_ts = frame_ts;
+               ++i;
+               /* Compute the time differenc */
+               usecs = time_diff(&before, &after);
+               DiffsBuf[i] = usecs;
+               printf("<LOG>   :   Frame %d received after %lld usecs\n", i, usecs);
+       }
+       if (i != ignore_count)
+               avg_variation = avg_variation / (i - ignore_count);
+       else
+               avg_variation = 0;
+
+       printf("<LOG>   :   Received frames: %u\n", i);
+       printf("<LOG>   :   Ignored frames: %u\n", ignore_count);
+       printf("<LOG>   :   Minimum delay variation: %llu usecs\n", min_variation);
+       printf("<LOG>   :   Maximum delay variation: %llu usecs\n", max_variation);
+       printf("<LOG>   :   Average delay variation: %llu usecs\n", avg_variation);
+       ShowStastics(DiffsBuf, num_frames);
+}
+
+/* udp server */
+void
+udpServer(int frame_size, int num_frames, char *buf, int64_t *DiffsBuf) {
+       int rc = 0, i = 0, ignore_count = 0;
+       uint32_t dst_len = 0;
+       ssize_t bytes;
+       struct timeval before, after;
+       int64_t usecs;
+       /* New change from Padama */
+       uint64_t prev_frame_ts = 0, prev_recv = 0, frame_ts = 0, cur_recv = 0;
+       uint64_t min_variation = 0, max_variation = 0, avg_variation = 0;
+
+       printf("<LOG>   :   UDP Server\n");
+       so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (so == -1) {
+               perror("failed to create socket");
+               exit(1);
+       }
+       bzero(&laddr,sizeof(laddr));
+       laddr.sin_family = AF_INET;
+       laddr.sin_addr.s_addr=htonl(INADDR_ANY);
+       laddr.sin_port=htons(srv_port);
+       rc = bind(so, (struct sockaddr *)&laddr,sizeof(laddr));
+       if (rc != 0) {
+               perror("failed to bind");
+               exit(1);
+       }
+       while (1) {
+               if ( i == num_frames ) {
+                       printf("<LOG>   :   Completed\n");
+                       break;
+               }
+               printf("<LOG>   :   Waiting for receiving\n");
+               bzero(&before, sizeof(before));
+               bzero(&after, sizeof(after));
+               rc = gettimeofday(&before, NULL);
+               if (rc == -1) {
+                       perror("gettimeofday failed");
+                       exit(1);
+               }
+               bytes = recvfrom(so, buf, frame_size, 0, (struct sockaddr *)&dst_addr, &dst_len);
+               if (bytes == -1) {
+                       perror("recv failed");
+                       exit(1);
+               }
+               else if (bytes > 0 && bytes != frame_size) {
+                       printf("Client exited\n");
+                       printf("Didn't recv the complete frame, bytes %ld\n",
+                                  bytes);
+                       exit(1);
+               }
+               else if (bytes == 0) {
+                       break;
+               }
+               rc = gettimeofday(&after, NULL);
+               if (rc == -1) {
+                       perror("gettimeofday failed");
+                       exit(1);
+               }
+               cur_recv = after.tv_sec * 1000 * 1000 + after.tv_usec;
+               memcpy((void *)&frame_ts, buf, sizeof(frame_ts));
+               if (prev_frame_ts > 0) {
+                       int64_t d_variation = 0;
+
+                       d_variation = (int64_t)((cur_recv - prev_recv) -
+                                                                       (frame_ts - prev_frame_ts));
+                       /* printf("Frame %u ts %llu d_variation %lld usecs\n",
+                        i, frame_ts, d_variation);*/
+                       if (d_variation > 0) {
+                               if (min_variation == 0)
+                                       min_variation = d_variation;
+                               else
+                                       min_variation = ((min_variation <= d_variation) ?
+                                                                        min_variation : d_variation);
+                               max_variation = ((max_variation >= d_variation) ?
+                                                                max_variation : d_variation);
+                               avg_variation += d_variation;
+                       } else {
+                               ignore_count++;
+                       }
+               }
+               prev_recv = cur_recv;
+               prev_frame_ts = frame_ts;
+               ++i;
+               /* Compute the time differenc */
+               usecs = time_diff(&before, &after);
+               DiffsBuf[i] = usecs;
+               printf("<LOG>   :   Frame %d received after %lld usecs\n", i, usecs);
+       }
+       if (i != ignore_count)
+               avg_variation = avg_variation / (i - ignore_count);
+       else
+               avg_variation = 0;
+       printf("<LOG>   :   Received frames: %u\n", i);
+       printf("<LOG>   :   Ignored frames: %u\n", ignore_count);
+       printf("<LOG>   :   Minimum delay variation: %llu usecs\n", min_variation);
+       printf("<LOG>   :   Maximum delay variation: %llu usecs\n", max_variation);
+       printf("<LOG>   :   Average delay variation: %llu usecs\n", avg_variation);
+       ShowStastics(DiffsBuf, num_frames);
+}
+
+/* Client */
+void
+tcpClient(int num_frames, int frame_size,
+                          const char *buf, struct timespec sleep_time){
+       int rc = 0, i = 0;
+       ssize_t bytes;
+
+       printf("<LOG>   :   TCP Client\n");
+       so = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+       if (so <= 0) {
+               perror("creating socket failed");
+               exit(1);
+       }
+       srv_addr.sin_port = htons(srv_port);
+       srv_addr.sin_len = sizeof(srv_addr);
+       srv_addr.sin_family = AF_INET;
+       rc = connect(so, (const struct sockaddr *)&srv_addr,
+                                sizeof(srv_addr));
+       if (rc != 0) {
+               perror("connect failed");
+               exit(1);
+       }
+       if (tc > 0) {
+               rc = setsockopt(so, SOL_SOCKET, SO_TRAFFIC_CLASS, &tc,
+                                               sizeof(tc));
+               if (rc == -1) {
+                       perror("failed to set traffic class");
+                       exit(1);
+               }
+       }
+       for (i = 0; i < num_frames; ++i) {
+               struct timeval fts;
+               uint64_t frame_ts;
+               /* Add a timestamp to the frame */
+               rc = gettimeofday(&fts, NULL);
+               if (rc == -1) {
+                       perror("faile to get time of day");
+                       exit(1);
+               }
+               frame_ts = fts.tv_sec * 1000 * 1000 + fts.tv_usec;
+               memcpy((void *)buf, (const void *)&frame_ts, sizeof(frame_ts));
+               bytes = send(so, buf, frame_size, 0);
+               if (bytes == -1) {
+                       perror("send failed \n");
+                       exit(1);
+               }
+               if (bytes != frame_size) {
+                       printf("failed to send all bytes, sent %ld\n", bytes);
+                       exit (1);
+               }
+               rc = nanosleep(&sleep_time, NULL);
+               if (rc == -1) {
+                       perror("sleep failed");
+                       exit(1);
+               }
+               printf("<LOG>   :   Sent %u frames as a whole\n", (i + 1));
+       }
+}
+
+void
+udpClient(int num_frames, int frame_size,
+                          const char *buf, struct timespec sleep_time){
+       int rc = 0, i = 0;
+       ssize_t bytes;
+
+       printf("<LOG>   :   UDP Client\n");
+       so = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (so <= 0) {
+               perror("creating socket failed");
+               exit(1);
+       }
+       srv_addr.sin_port = htons(srv_port);
+       srv_addr.sin_len = sizeof(srv_addr);
+       srv_addr.sin_family = AF_INET;
+       if (tc > 0) {
+               rc = setsockopt(so, SOL_SOCKET, SO_TRAFFIC_CLASS, &tc,
+                                               sizeof(tc));
+               if (rc == -1) {
+                       perror("failed to set traffic class");
+                       exit(1);
+               }
+       }
+       for (i = 0; i < num_frames; ++i) {
+               struct timeval fts;
+               uint64_t frame_ts;
+               /* Add a timestamp to the frame */
+               rc = gettimeofday(&fts, NULL);
+               if (rc == -1) {
+                       perror("faile to get time of day");
+                       exit(1);
+               }
+               frame_ts = fts.tv_sec * 1000 * 1000 + fts.tv_usec;
+               memcpy((void *)buf, (const void *)&frame_ts, sizeof(frame_ts));
+               bytes = sendto(so, buf, frame_size, 0, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
+               if (bytes == -1) {
+                       perror("send failed \n");
+                       exit(1);
+               }
+               if (bytes != frame_size) {
+                       printf("failed to send all bytes, sent %ld\n", bytes);
+                       exit (1);
+               }
+               rc = nanosleep(&sleep_time, NULL);
+               if (rc == -1) {
+                       perror("sleep failed");
+                       exit(1);
+               }
+               printf("<LOG>   :   Sent %u frames as a whole\n", (i + 1));
+       }
+}
+
+
index 4a9c8fa28ee013e4602ea22de29366e7ea929bb0..d2a5b1be14338926af99fe28edb1c04ac0afb459 100644 (file)
@@ -83,7 +83,7 @@
 
 #define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
        "\004IFDISABLED\005DONT_SET_IFROUTE\006PROXY_PREFIXES" \
-       "\007IGNORE_NA\010INSECURE"
+       "\007IGNORE_NA\010INSECURE\011REPLICATED\012DAD"
 
 static struct in6_ifreq in6_ridreq;
 static struct in6_aliasreq in6_addreq = 
@@ -607,8 +607,8 @@ static struct cmd inet6_cmds[] = {
        DEF_CMD("-nud",         -ND6_IFF_PERFORMNUD,    setnd6flags),
        DEF_CMD("ifdisabled",   ND6_IFF_IFDISABLED,     setnd6flags),
        DEF_CMD("-ifdisabled",  -ND6_IFF_IFDISABLED,    setnd6flags),
-       DEF_CMD("ignore_na",    ND6_IFF_IGNORE_NA,      setnd6flags),
-       DEF_CMD("-ignore_na",   -ND6_IFF_IGNORE_NA,     setnd6flags),
+       DEF_CMD("replicated",   ND6_IFF_REPLICATED,     setnd6flags),
+       DEF_CMD("-replicated",  -ND6_IFF_REPLICATED,    setnd6flags),
        DEF_CMD("proxy_prefixes", ND6_IFF_PROXY_PREFIXES,       setnd6flags),
        DEF_CMD("-proxy_prefixes", -ND6_IFF_PROXY_PREFIXES,     setnd6flags),
        DEF_CMD("insecure",     ND6_IFF_INSECURE,       setnd6flags),
@@ -618,6 +618,8 @@ static struct cmd inet6_cmds[] = {
        DEF_CMD("eui64",        0,                      setip6eui64),
        DEF_CMD("secured",      IN6_IFF_SECURED,        setip6flags),
        DEF_CMD("-secured",     -IN6_IFF_SECURED,       setip6flags),
+       DEF_CMD("dad",          ND6_IFF_DAD,            setnd6flags),
+       DEF_CMD("-dad",         -ND6_IFF_DAD,           setnd6flags),
 };
 
 static struct afswtch af_inet6 = {
index 6a7ea05bb0b51d8ad882f656c13238e40c2e9420..9b06f04fe70d5337d0f2c088e8b9ff3484f64209 100644 (file)
@@ -558,6 +558,16 @@ Do not disable all IPv6 communication on the interface.
 Disable the processing of Secure Neighbor Discovery (SEND).
 .It Cm -insecure
 Do not disabled the processing of Secure Neighbor Discovery (SEND).
+.It Cm dad
+Perform duplicate address detection (DAD).
+.It Cm -dad
+Do not perform duplicate address detection (DAD).
+.It Cm replicated
+Modify duplicate address detection (DAD) protocol to expect that interface
+configuration is replicated at a network sleep proxy. Ignores certain NA
+messages and disables optimistic DAD.
+.It Cm -replicated
+Do not use modified duplicated address detection (DAD) protocol.
 .El
 .Pp
 The following parameters are specific to link aggregate interfaces:
index 1a708da087ed54f47bd612e910b3d98d417a8b3a..d20a2f7b84831dae01ec6a9ec68ffd6a35007cba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2015 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -98,6 +98,7 @@ __unused static const char copyright[] =
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sysexits.h>
 
 #include "ifconfig.h"
 
@@ -762,7 +763,6 @@ setifflags(const char *vname, int value, int s, const struct afswtch *afp)
                Perror(vname);
 }
 
-#ifdef SIOCGIFCAP
 void
 setifcap(const char *vname, int value, int s, const struct afswtch *afp)
 {
@@ -783,7 +783,6 @@ setifcap(const char *vname, int value, int s, const struct afswtch *afp)
        if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
                Perror(vname);
 }
-#endif
 
 static void
 setifmetric(const char *val, int dummy __unused, int s, 
@@ -940,6 +939,33 @@ setthrottle(const char *val, int dummy __unused, int s,
        }
 }
 
+static void
+setdisableoutput(const char *val, int dummy __unused, int s,
+    const struct afswtch *afp)
+{
+       struct ifreq ifr;
+       char *cp;
+       errno = 0;
+       bzero(&ifr, sizeof (ifr));
+       strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+
+       ifr.ifr_ifru.ifru_disable_output = strtold(val, &cp);
+       if (val == cp || errno != 0) {
+               warn("Invalid value '%s'", val);
+               return;
+       }
+
+       if (ioctl(s, SIOCSIFDISABLEOUTPUT, &ifr) < 0 && errno != ENXIO) {
+               warn("ioctl set disable output");
+       } else if (errno == ENXIO) {
+               printf("output thread can not be disabled on %s\n", name);
+       } else {
+               printf("output %s on %s\n",
+                   ((ifr.ifr_ifru.ifru_disable_output == 0) ? "enabled" : "disabled"),
+                   name);
+       }
+}
+
 static void
 setlog(const char *val, int dummy __unused, int s,
     const struct afswtch *afp)
@@ -981,6 +1007,19 @@ setexpensive(const char *vname, int value, int s, const struct afswtch *afp)
                Perror(vname);
 }
 
+void
+settimestamp(const char *vname, int value, int s, const struct afswtch *afp)
+{
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       
+       if (value == 0) {
+               if (ioctl(s, SIOCSIFTIMESTAMPDISABLE, (caddr_t)&ifr) < 0)
+                       Perror(vname);
+       } else {
+               if (ioctl(s, SIOCSIFTIMESTAMPENABLE, (caddr_t)&ifr) < 0)
+                       Perror(vname);
+       }
+}
 
 void
 setecnmode(const char *val, int dummy __unused, int s,
@@ -1008,6 +1047,137 @@ setecnmode(const char *val, int dummy __unused, int s,
                Perror("ioctl(SIOCSECNMODE)");
 }
 
+#if defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED)
+
+void
+setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+       u_long ioc;
+
+#if (DEBUG | DEVELOPMENT)
+       printf("%s(%s, %s)\n", __func__, cmd, arg);
+#endif /* (DEBUG | DEVELOPMENT) */
+       
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       
+       if (strcmp(cmd, "mode") == 0) {
+               ioc = SIOCSQOSMARKINGMODE;
+               
+               if (strcmp(arg, "fastlane") == 0)
+                       ifr.ifr_qosmarking_mode = IFRTYPE_QOSMARKING_FASTLANE;
+               else if (strcasecmp(arg, "none") == 0 || strcasecmp(arg, "off") == 0)
+                       ifr.ifr_qosmarking_mode = IFRTYPE_QOSMARKING_MODE_NONE;
+               else
+                       err(EX_USAGE, "bad value for qosmarking mode: %s", arg);
+       } else if (strcmp(cmd, "enabled") == 0) {
+               ioc = SIOCSQOSMARKINGENABLED;
+               if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+                   strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+                       ifr.ifr_qosmarking_enabled = 1;
+               else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+                        strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+                       ifr.ifr_qosmarking_enabled = 0;
+               else
+                       err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
+       } else {
+               err(EX_USAGE, "qosmarking takes mode or enabled");
+       }
+       
+       if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
+               err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
+}
+
+void
+setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       
+       warnx("### fastlane is obsolete, use qosmarking ###");
+       
+       if (strcmp(cmd, "capable") == 0) {
+               if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+                   strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+                       setqosmarking("mode", "fastlane", s, afp);
+               else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+                        strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+                       setqosmarking("mode", "off", s, afp);
+               else
+                       err(EX_USAGE, "bad value for fastlane %s", cmd);
+       } else if (strcmp(cmd, "enable") == 0) {
+               if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+                   strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+                       setqosmarking("enabled", "1", s, afp);
+               else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+                        strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+                       setqosmarking("enabled", "0", s, afp);
+               else
+                       err(EX_USAGE, "bad value for fastlane %s", cmd);
+       } else {
+               err(EX_USAGE, "fastlane takes capable or enable");
+       }
+}
+
+#else /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
+
+void
+setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+       int value;
+       u_long ioc;
+       
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       
+       if (strcmp(cmd, "capable") == 0)
+               ioc = SIOCSFASTLANECAPABLE;
+       else if (strcmp(cmd, "enable") == 0)
+               ioc = SIOCSFASTLEENABLED;
+       else
+               err(EX_USAGE, "fastlane takes capable or enabled");
+       
+       if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+           strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+               value = 1;
+       else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+                strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+               value = 0;
+       else
+               err(EX_USAGE, "bad value for fastlane %s", cmd);
+       
+       if (ioc == SIOCSFASTLANECAPABLE)
+               ifr.ifr_fastlane_capable = value;
+       else
+               ifr.ifr_fastlane_enabled = value;
+       
+       if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
+               err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
+}
+
+
+void
+setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+       if (strcmp(cmd, "mode") == 0) {
+               if (strcmp(arg, "fastlane") == 0)
+                       setfastlane("capable", "on", s, afp);
+               else if (strcmp(arg, "none") == 0)
+                       setfastlane("capable", "off", s, afp);
+               else
+                       err(EX_USAGE, "bad value for qosmarking mode: %s", arg);
+       } else if (strcmp(cmd, "enabled") == 0) {
+               if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+                   strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+                       setfastlane("enable", "on", s, afp);
+               else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+                        strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+                       setfastlane("enable", "off", s, afp);
+               else
+                       err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
+       } else {
+               err(EX_USAGE, "qosmarking takes mode or enabled");
+       }
+}
+
+#endif /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
 
 #define        IFFBITS \
 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
@@ -1015,14 +1185,15 @@ setecnmode(const char *val, int dummy __unused, int s,
 "\20MULTICAST"
 
 #define        IFEFBITS \
-"\020\1AUTOCONFIGURING\6IPV6_DISABLED\7ACCEPT_RTADV\10TXSTART\11RXPOLL" \
+"\020\1AUTOCONFIGURING\5FASTLN_CAP\6IPV6_DISABLED\7ACCEPT_RTADV\10TXSTART\11RXPOLL" \
 "\12VLAN\13BOND\14ARPLL\15NOWINDOWSCALE\16NOAUTOIPV6LL\17EXPENSIVE\20ROUTER4" \
 "\21ROUTER6\22LOCALNET_PRIVATE\23ND6ALT\24RESTRICTED_RECV\25AWDL\26NOACKPRI" \
-"\27AWDL_RESTRICTED\30CL2K\31ECN_ENABLE\32ECN_DISABLE\35SENDLIST\36DIRECTLINK\40UPDOWNCHANGE"
+"\27AWDL_RESTRICTED\30CL2K\31ECN_ENABLE\32ECN_DISABLE\34CA\35SENDLIST\36DIRECTLINK" \
+"\37FASTLN_ON\40UPDOWNCHANGE"
 
 #define        IFCAPBITS \
 "\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \
-"\6TSO4\7TSO6\10LRO\11AV\12TXSTATUS"
+"\6TSO4\7TSO6\10LRO\11AV\12TXSTATUS\14HW_TIMESTAMP\15SW_TIMESTAMP"
 
 #define        IFRLOGF_BITS \
 "\020\1DLIL\21FAMILY\31DRIVER\35FIRMWARE"
@@ -1044,7 +1215,8 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
        struct ifmibdata_supplemental ifmsupp;
        size_t miblen = sizeof(struct ifmibdata_supplemental);
        u_int64_t eflags = 0;
-
+       int curcap = 0;
+       
        if (afp == NULL) {
                allfamilies = 1;
                afp = af_getbyname("inet");
@@ -1067,11 +1239,11 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
                printf(" mtu %d", ifr.ifr_mtu);
        if (showrtref && ioctl(s, SIOCGIFGETRTREFCNT, &ifr) != -1)
                printf(" rtref %d", ifr.ifr_route_refcnt);
-    if (verbose) {
-        unsigned int ifindex = if_nametoindex(ifa->ifa_name);
-        if (ifindex != 0)
-            printf(" index %u", ifindex);
-    }
+       if (verbose) {
+               unsigned int ifindex = if_nametoindex(ifa->ifa_name);
+               if (ifindex != 0)
+                       printf(" index %u", ifindex);
+       }
        putchar('\n');
 
        if (verbose && ioctl(s, SIOCGIFEFLAGS, (caddr_t)&ifr) != -1 &&
@@ -1080,9 +1252,9 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
                putchar('\n');
        }
 
-#ifdef SIOCGIFCAP      
        if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
                if (ifr.ifr_curcap != 0) {
+                       curcap = ifr.ifr_curcap;
                        printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
                        putchar('\n');
                }
@@ -1091,7 +1263,6 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
                        putchar('\n');
                }
        }
-#endif
        
        tunnel_status(s);
 
@@ -1402,7 +1573,7 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
                        printf("\teffective interface: %s\n", delegatedif);
        }
 
-       if(ioctl(s, SIOCGSTARTDELAY, &ifr) != -1) {
+       if (ioctl(s, SIOCGSTARTDELAY, &ifr) != -1) {
                if (ifr.ifr_start_delay_qlen > 0 &&
                    ifr.ifr_start_delay_timeout > 0) {
                        printf("\ttxstart qlen: %u packets "
@@ -1411,7 +1582,32 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
                            ifr.ifr_start_delay_timeout/1000);
                }
        }
-
+#if defined(IFCAP_HW_TIMESTAMP) && defined(IFCAP_SW_TIMESTAMP)
+       if ((curcap & (IFCAP_HW_TIMESTAMP | IFCAP_SW_TIMESTAMP)) &&
+           ioctl(s, SIOCGIFTIMESTAMPENABLED, &ifr) != -1) {
+               printf("\ttimestamp: %s\n",
+                      (ifr.ifr_intval != 0) ? "enabled" : "disabled");
+       }
+#endif
+#if defined(SIOCGQOSMARKINGENABLED) && defined(SIOCGQOSMARKINGMODE)
+       if (ioctl(s, SIOCGQOSMARKINGENABLED, &ifr) != -1) {
+               printf("\tqosmarking enabled: %s mode: ",
+                      ifr.ifr_qosmarking_enabled ? "yes" : "no");
+               if (ioctl(s, SIOCGQOSMARKINGMODE, &ifr) != -1) {
+                       switch (ifr.ifr_qosmarking_mode) {
+                               case IFRTYPE_QOSMARKING_FASTLANE:
+                                       printf("fastlane\n");
+                                       break;
+                               case IFRTYPE_QOSMARKING_MODE_NONE:
+                                       printf("none\n");
+                                       break;
+                               default:
+                                       printf("unknown (%u)\n", ifr.ifr_qosmarking_mode);
+                                       break;
+                       }
+               }
+       }
+#endif /* defined(SIOCGQOSMARKINGENABLED) && defined(SIOCGQOSMARKINGMODE) */
 done:
        close(s);
        return;
@@ -1715,7 +1911,12 @@ static struct cmd basic_cmds[] = {
        DEF_CMD("-cl2k",        0,              setcl2k),
        DEF_CMD("expensive",    1,              setexpensive),
        DEF_CMD("-expensive",   0,              setexpensive),
+       DEF_CMD("timestamp",    1,              settimestamp),
+       DEF_CMD("-timestamp",   0,              settimestamp),
        DEF_CMD_ARG("ecn",                      setecnmode),
+       DEF_CMD_ARG2("fastlane",                setfastlane),
+       DEF_CMD_ARG2("qosmarking",              setqosmarking),
+       DEF_CMD_ARG("disable_output",           setdisableoutput),
 };
 
 static __constructor void
diff --git a/ip6fw.tproj/ip6fw.8 b/ip6fw.tproj/ip6fw.8
deleted file mode 100644 (file)
index 9915ea7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-.Dd September 27, 2012
-.Dt IP6FW 8
-.Os Darwin
-.Sh NAME
-.Nm ip6fw
-.Sh DESCRIPTION
-This utility is
-.Cm DEPRECATED.
-Please use
-.Xr pfctl 8
-instead.
diff --git a/ip6fw.tproj/ip6fw.c b/ip6fw.tproj/ip6fw.c
deleted file mode 100644 (file)
index baaa620..0000000
+++ /dev/null
@@ -1,1446 +0,0 @@
-/*
- * 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
- *
- * Idea and grammar partially left from:
- * Copyright (c) 1993 Daniel Boulet
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- *
- * NEW command line interface for IP firewall facility
- *
- * $Id: ip6fw.c,v 1.3 2006/02/07 06:22:17 lindak Exp $
- * $FreeBSD: src/sbin/ip6fw/ip6fw.c,v 1.1.2.6 2001/08/01 06:52:18 obrien Exp $
- */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <limits.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <sysexits.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <netinet6/ip6_fw.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-
-int            lineno = -1;
-
-int            s;                              /* main RAW socket         */
-int            do_resolv=0;                    /* Would try to resolv all */
-int            do_acct=0;                      /* Show packet/byte count  */
-int            do_time=0;                      /* Show time stamps        */
-int            do_quiet=0;                     /* Be quiet in add and flush  */
-int            do_force=0;                     /* Don't ask for confirmation */
-
-struct icmpcode {
-       int     code;
-       char    *str;
-};
-
-static struct icmpcode icmp6codes[] = {
-      { ICMP6_DST_UNREACH_NOROUTE,     "noroute" },
-      { ICMP6_DST_UNREACH_ADMIN,       "admin" },
-      { ICMP6_DST_UNREACH_NOTNEIGHBOR, "notneighbor" },
-      { ICMP6_DST_UNREACH_ADDR,                "addr" },
-      { ICMP6_DST_UNREACH_NOPORT,      "noport" },
-      { 0, NULL }
-};
-
-static char ntop_buf[INET6_ADDRSTRLEN];
-
-static void show_usage(const char *fmt, ...);
-
-static int
-mask_bits(u_char *m_ad, int m_len)
-{
-       int h_num = 0,i;
-
-       for (i = 0; i < m_len; i++, m_ad++) {
-               if (*m_ad != 0xff)
-                       break;
-               h_num += 8;
-       }
-       if (i < m_len) {
-               switch (*m_ad) {
-#define        MASKLEN(m, l)   case m: h_num += l; break
-               MASKLEN(0xfe, 7);
-               MASKLEN(0xfc, 6);
-               MASKLEN(0xf8, 5);
-               MASKLEN(0xf0, 4);
-               MASKLEN(0xe0, 3);
-               MASKLEN(0xc0, 2);
-               MASKLEN(0x80, 1);
-#undef MASKLEN
-               }
-       }
-       return h_num;
-}
-
-static int pl2m[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
-
-struct in6_addr *plen2mask(int n)
-{
-       static struct in6_addr ia;
-       u_char  *p;
-       int     i;
-
-       memset(&ia, 0, sizeof(struct in6_addr));
-       p = (u_char *)&ia;
-       for (i = 0; i < 16; i++, p++, n -= 8) {
-               if (n >= 8) {
-                       *p = 0xff;
-                       continue;
-               }
-               *p = pl2m[n];
-               break;
-       }
-       return &ia;
-}
-
-void
-print_port(prot, port, comma)
-       u_char  prot;
-       u_short port;
-       const char *comma;
-{
-       struct servent *se;
-       struct protoent *pe;
-       const char *protocol;
-       int printed = 0;
-
-       if (do_resolv) {
-               pe = getprotobynumber(prot);
-               if (pe)
-                       protocol = pe->p_name;
-               else
-                       protocol = NULL;
-
-               se = getservbyport(htons(port), protocol);
-               if (se) {
-                       printf("%s%s", comma, se->s_name);
-                       printed = 1;
-               }
-       }
-       if (!printed)
-               printf("%s%d",comma,port);
-}
-
-static void
-print_iface(char *key, union ip6_fw_if *un, int byname)
-{
-       char ifnb[IP6FW_IFNLEN+1];
-
-       if (byname) {
-               strncpy(ifnb, un->fu_via_if.name, IP6FW_IFNLEN);
-               ifnb[IP6FW_IFNLEN]='\0';
-               if (un->fu_via_if.unit == -1)
-                       printf(" %s %s*", key, ifnb);
-               else
-                       printf(" %s %s%d", key, ifnb, un->fu_via_if.unit);
-       } else if (!IN6_IS_ADDR_UNSPECIFIED(&un->fu_via_ip6)) {
-               printf(" %s %s", key, inet_ntop(AF_INET6,&un->fu_via_ip6,ntop_buf,sizeof(ntop_buf)));
-       } else
-               printf(" %s any", key);
-}
-
-static void
-print_reject_code(int code)
-{
-       struct icmpcode *ic;
-
-       for (ic = icmp6codes; ic->str; ic++)
-               if (ic->code == code) {
-                       printf("%s", ic->str);
-                       return;
-               }
-       printf("%u", code);
-}
-
-static void
-show_ip6fw(struct ip6_fw *chain)
-{
-       char *comma;
-       struct hostent *he;
-       struct protoent *pe;
-       int i, mb;
-       int nsp = IPV6_FW_GETNSRCP(chain);
-       int ndp = IPV6_FW_GETNDSTP(chain);
-
-       if (do_resolv)
-               setservent(1/*stayopen*/);
-
-       printf("%05u ", chain->fw_number);
-
-       if (do_acct)
-               printf("%10u %10u ",chain->fw_pcnt,chain->fw_bcnt);
-
-       if (do_time)
-       {
-               if (chain->timestamp)
-               {
-                       char timestr[30];
-
-                       strlcpy(timestr, ctime((time_t *)&chain->timestamp), sizeof(timestr));
-                       *strchr(timestr, '\n') = '\0';
-                       printf("%s ", timestr);
-               }
-               else
-                       printf("                         ");
-       }
-
-       switch (chain->fw_flg & IPV6_FW_F_COMMAND)
-       {
-               case IPV6_FW_F_ACCEPT:
-                       printf("allow");
-                       break;
-               case IPV6_FW_F_DENY:
-                       printf("deny");
-                       break;
-               case IPV6_FW_F_COUNT:
-                       printf("count");
-                       break;
-               case IPV6_FW_F_DIVERT:
-                       printf("divert %u", chain->fw_divert_port);
-                       break;
-               case IPV6_FW_F_TEE:
-                       printf("tee %u", chain->fw_divert_port);
-                       break;
-               case IPV6_FW_F_SKIPTO:
-                       printf("skipto %u", chain->fw_skipto_rule);
-                       break;
-               case IPV6_FW_F_REJECT:
-                       if (chain->fw_reject_code == IPV6_FW_REJECT_RST)
-                               printf("reset");
-                       else {
-                               printf("unreach ");
-                               print_reject_code(chain->fw_reject_code);
-                       }
-                       break;
-               default:
-                       errx(EX_OSERR, "impossible");
-       }
-
-       if (chain->fw_flg & IPV6_FW_F_PRN)
-               printf(" log");
-
-       pe = getprotobynumber(chain->fw_prot);
-       if (pe)
-               printf(" %s", pe->p_name);
-       else
-               printf(" %u", chain->fw_prot);
-
-       printf(" from %s", chain->fw_flg & IPV6_FW_F_INVSRC ? "not " : "");
-
-       mb=mask_bits((u_char *)&chain->fw_smsk,sizeof(chain->fw_smsk));
-       if (mb==128 && do_resolv) {
-               he=gethostbyaddr((char *)&(chain->fw_src),sizeof(chain->fw_src),AF_INET6);
-               if (he==NULL) {
-                       printf("%s", inet_ntop(AF_INET6,&chain->fw_src,ntop_buf,sizeof(ntop_buf)));
-               } else
-                       printf("%s",he->h_name);
-       } else {
-               if (mb!=128) {
-                       if (mb == 0) {
-                               printf("any");
-                       } else {
-                               printf("%s", inet_ntop(AF_INET6,&chain->fw_src,ntop_buf,sizeof(ntop_buf)));
-                               printf("/%d",mb);
-                       }
-               } else
-                       printf("%s", inet_ntop(AF_INET6,&chain->fw_src,ntop_buf,sizeof(ntop_buf)));
-       }
-
-       if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) {
-               comma = " ";
-               for (i = 0; i < nsp; i++) {
-                       print_port(chain->fw_prot, chain->fw_pts[i], comma);
-                       if (i==0 && (chain->fw_flg & IPV6_FW_F_SRNG))
-                               comma = "-";
-                       else
-                               comma = ",";
-               }
-       }
-
-       printf(" to %s", chain->fw_flg & IPV6_FW_F_INVDST ? "not " : "");
-
-       mb=mask_bits((u_char *)&chain->fw_dmsk,sizeof(chain->fw_dmsk));
-       if (mb==128 && do_resolv) {
-               he=gethostbyaddr((char *)&(chain->fw_dst),sizeof(chain->fw_dst),AF_INET);
-               if (he==NULL) {
-                       printf("%s", inet_ntop(AF_INET6,&chain->fw_dst,ntop_buf,sizeof(ntop_buf)));
-               } else
-                       printf("%s",he->h_name);
-       } else {
-               if (mb!=128) {
-                       if (mb == 0) {
-                               printf("any");
-                       } else {
-                               printf("%s", inet_ntop(AF_INET6,&chain->fw_dst,ntop_buf,sizeof(ntop_buf)));
-                               printf("/%d",mb);
-                       }
-               } else
-                       printf("%s", inet_ntop(AF_INET6,&chain->fw_dst,ntop_buf,sizeof(ntop_buf)));
-       }
-
-       if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) {
-               comma = " ";
-               for (i = 0; i < ndp; i++) {
-                       print_port(chain->fw_prot, chain->fw_pts[nsp+i], comma);
-                       if (i==0 && (chain->fw_flg & IPV6_FW_F_DRNG))
-                               comma = "-";
-                       else
-                               comma = ",";
-               }
-       }
-
-       /* Direction */
-       if ((chain->fw_flg & IPV6_FW_F_IN) && !(chain->fw_flg & IPV6_FW_F_OUT))
-               printf(" in");
-       if (!(chain->fw_flg & IPV6_FW_F_IN) && (chain->fw_flg & IPV6_FW_F_OUT))
-               printf(" out");
-
-       /* Handle hack for "via" backwards compatibility */
-       if ((chain->fw_flg & IF6_FW_F_VIAHACK) == IF6_FW_F_VIAHACK) {
-               print_iface("via",
-                   &chain->fw_in_if, chain->fw_flg & IPV6_FW_F_IIFNAME);
-       } else {
-               /* Receive interface specified */
-               if (chain->fw_flg & IPV6_FW_F_IIFACE)
-                       print_iface("recv", &chain->fw_in_if,
-                           chain->fw_flg & IPV6_FW_F_IIFNAME);
-               /* Transmit interface specified */
-               if (chain->fw_flg & IPV6_FW_F_OIFACE)
-                       print_iface("xmit", &chain->fw_out_if,
-                           chain->fw_flg & IPV6_FW_F_OIFNAME);
-       }
-
-       if (chain->fw_flg & IPV6_FW_F_FRAG)
-               printf(" frag");
-
-       if (chain->fw_ip6opt || chain->fw_ip6nopt) {
-               int     _opt_printed = 0;
-#define        PRINTOPT(x)     {if (_opt_printed) printf(",");\
-                       printf(x); _opt_printed = 1;}
-
-               printf(" ip6opt ");
-               if (chain->fw_ip6opt  & IPV6_FW_IP6OPT_HOPOPT) PRINTOPT("hopopt");
-               if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_HOPOPT) PRINTOPT("!hopopt");
-               if (chain->fw_ip6opt  & IPV6_FW_IP6OPT_ROUTE)  PRINTOPT("route");
-               if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_ROUTE)  PRINTOPT("!route");
-               if (chain->fw_ip6opt  & IPV6_FW_IP6OPT_FRAG)  PRINTOPT("frag");
-               if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_FRAG)  PRINTOPT("!frag");
-               if (chain->fw_ip6opt  & IPV6_FW_IP6OPT_ESP)    PRINTOPT("esp");
-               if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_ESP)    PRINTOPT("!esp");
-               if (chain->fw_ip6opt  & IPV6_FW_IP6OPT_AH)     PRINTOPT("ah");
-               if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_AH)     PRINTOPT("!ah");
-               if (chain->fw_ip6opt  & IPV6_FW_IP6OPT_NONXT)  PRINTOPT("nonxt");
-               if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_NONXT)  PRINTOPT("!nonxt");
-               if (chain->fw_ip6opt  & IPV6_FW_IP6OPT_OPTS)   PRINTOPT("opts");
-               if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_OPTS)   PRINTOPT("!opts");
-       }
-
-       if (chain->fw_ipflg & IPV6_FW_IF_TCPEST)
-               printf(" established");
-       else if (chain->fw_tcpf == IPV6_FW_TCPF_SYN &&
-           chain->fw_tcpnf == IPV6_FW_TCPF_ACK)
-               printf(" setup");
-       else if (chain->fw_tcpf || chain->fw_tcpnf) {
-               int     _flg_printed = 0;
-#define        PRINTFLG(x)     {if (_flg_printed) printf(",");\
-                       printf(x); _flg_printed = 1;}
-
-               printf(" tcpflg ");
-               if (chain->fw_tcpf  & IPV6_FW_TCPF_FIN)  PRINTFLG("fin");
-               if (chain->fw_tcpnf & IPV6_FW_TCPF_FIN)  PRINTFLG("!fin");
-               if (chain->fw_tcpf  & IPV6_FW_TCPF_SYN)  PRINTFLG("syn");
-               if (chain->fw_tcpnf & IPV6_FW_TCPF_SYN)  PRINTFLG("!syn");
-               if (chain->fw_tcpf  & IPV6_FW_TCPF_RST)  PRINTFLG("rst");
-               if (chain->fw_tcpnf & IPV6_FW_TCPF_RST)  PRINTFLG("!rst");
-               if (chain->fw_tcpf  & IPV6_FW_TCPF_PSH)  PRINTFLG("psh");
-               if (chain->fw_tcpnf & IPV6_FW_TCPF_PSH)  PRINTFLG("!psh");
-               if (chain->fw_tcpf  & IPV6_FW_TCPF_ACK)  PRINTFLG("ack");
-               if (chain->fw_tcpnf & IPV6_FW_TCPF_ACK)  PRINTFLG("!ack");
-               if (chain->fw_tcpf  & IPV6_FW_TCPF_URG)  PRINTFLG("urg");
-               if (chain->fw_tcpnf & IPV6_FW_TCPF_URG)  PRINTFLG("!urg");
-       }
-       if (chain->fw_flg & IPV6_FW_F_ICMPBIT) {
-               int type_index;
-               int first = 1;
-
-               printf(" icmptype");
-
-               for (type_index = 0; type_index < IPV6_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8; ++type_index)
-                       if (chain->fw_icmp6types[type_index / (sizeof(unsigned) * 8)] &
-                               (1U << (type_index % (sizeof(unsigned) * 8)))) {
-                               printf("%c%d", first == 1 ? ' ' : ',', type_index);
-                               first = 0;
-                       }
-       }
-       printf("\n");
-       if (do_resolv)
-               endservent();
-}
-
-void
-list(ac, av)
-       int     ac;
-       char    **av;
-{
-       struct ip6_fw *r, *rules;
-       int l,i;
-       unsigned long rulenum;
-       int nalloc, maxbytes;
-       socklen_t bytes;
-
-       /* extract rules from kernel, resizing array as necessary */
-       rules = NULL;
-       nalloc = sizeof *rules;
-       bytes = nalloc;
-       maxbytes = 65536 * sizeof *rules;
-       while (bytes >= nalloc) {
-               nalloc = nalloc * 2 + 200;
-               bytes = nalloc;
-               if ((rules = realloc(rules, bytes)) == NULL)
-                       err(EX_OSERR, "realloc");
-               memset(rules, 0, sizeof *rules);
-               rules->version = IPV6_FW_CURRENT_API_VERSION;
-               i = getsockopt(s, IPPROTO_IPV6, IPV6_FW_GET, rules, &bytes);
-               if ((i < 0 && errno != EINVAL) || nalloc > maxbytes)
-                       err(EX_OSERR, "getsockopt(IPV6_FW_GET)");
-       }
-       if (!ac) {
-               /* display all rules */
-               for (r = rules, l = bytes; l >= sizeof rules[0];
-                        r++, l-=sizeof rules[0])
-                       show_ip6fw(r);
-       }
-       else {
-               /* display specific rules requested on command line */
-               int exitval = 0;
-
-               while (ac--) {
-                       char *endptr;
-                       int seen;
-
-                       /* convert command line rule # */
-                       rulenum = strtoul(*av++, &endptr, 10);
-                       if (*endptr) {
-                               exitval = 1;
-                               warn("invalid rule number: %s", av[-1]);
-                               continue;
-                       }
-                       seen = 0;
-                       for (r = rules, l = bytes;
-                                l >= sizeof rules[0] && r->fw_number <= rulenum;
-                                r++, l-=sizeof rules[0])
-                               if (rulenum == r->fw_number) {
-                                       show_ip6fw(r);
-                                       seen = 1;
-                               }
-                       if (!seen) {
-                               exitval = 1;
-                               warnx("rule %lu does not exist", rulenum);
-                       }
-               }
-               if (exitval != 0)
-                       exit(exitval);
-       }
-}
-
-static void
-show_usage(const char *fmt, ...)
-{
-       if (fmt) {
-               char buf[100];
-               va_list args;
-
-               va_start(args, fmt);
-               vsnprintf(buf, sizeof(buf), fmt, args);
-               va_end(args);
-               warnx("error: %s", buf);
-       }
-       fprintf(stderr, "usage: ip6fw [options]\n"
-"    flush\n"
-"    add [number] rule\n"
-"    delete number ...\n"
-"    list [number ...]\n"
-"    show [number ...]\n"
-"    zero [number ...]\n"
-"  rule:  action proto src dst extras...\n"
-"    action:\n"
-"      {allow|permit|accept|pass|deny|drop|reject|unreach code|\n"
-"       reset|count|skipto num} [log]\n"
-"    proto: {ipv6|tcp|udp|ipv6-icmp|<number>}\n"
-"    src: from [not] {any|ipv6[/prefixlen]} [{port|port-port},[port],...]\n"
-"    dst: to [not] {any|ipv6[/prefixlen]} [{port|port-port},[port],...]\n"
-"  extras:\n"
-"    fragment     (may not be used with ports or tcpflags)\n"
-"    in\n"
-"    out\n"
-"    {xmit|recv|via} {iface|ipv6|any}\n"
-"    {established|setup}\n"
-"    tcpflags [!]{syn|fin|rst|ack|psh|urg},...\n"
-"    ipv6options [!]{hopopt|route|frag|esp|ah|nonxt|opts},...\n"
-"    icmptypes {type[,type]}...\n");
-
-       exit(1);
-}
-
-static int
-lookup_host (host, addr, family)
-       char *host;
-       u_char *addr;
-{
-       struct hostent *he = gethostbyname2(host, family);
-
-       if (!he)
-               return(-1);
-
-       memcpy(addr, he->h_addr_list[0], he->h_length);
-
-       return(0);
-}
-
-void
-fill_ip6(ipno, mask, acp, avp)
-       struct in6_addr *ipno, *mask;
-       int *acp;
-       char ***avp;
-{
-       int ac = *acp;
-       char **av = *avp;
-       char *p = 0, md = 0;
-       int i;
-
-       if (ac && !strncmp(*av,"any",strlen(*av))) {
-               *ipno = *mask = in6addr_any; av++; ac--;
-       } else {
-               p = strchr(*av, '/');
-               if (p) {
-                       md = *p;
-                       *p++ = '\0';
-               }
-
-               if (lookup_host(*av, (u_char *)ipno, AF_INET6) != 0)
-                       show_usage("hostname ``%s'' unknown", *av);
-               switch (md) {
-                       case '/':
-                               if (atoi(p) == 0) {
-                                       *mask = in6addr_any;
-                               } else if (atoi(p) > 128) {
-                                       show_usage("bad width ``%s''", p);
-                               } else {
-                                       *mask = *(plen2mask(atoi(p)));
-                               }
-                               break;
-                       default:
-                               *mask = *(plen2mask(128));
-                               break;
-               }
-               for (i = 0; i < sizeof(*ipno); i++)
-                       ipno->s6_addr[i] &= mask->s6_addr[i];
-               av++;
-               ac--;
-       }
-       *acp = ac;
-       *avp = av;
-}
-
-static void
-fill_reject_code6(u_short *codep, char *str)
-{
-       struct icmpcode *ic;
-       u_long val;
-       char *s;
-
-       val = strtoul(str, &s, 0);
-       if (s != str && *s == '\0' && val < 0x100) {
-               *codep = val;
-               return;
-       }
-       for (ic = icmp6codes; ic->str; ic++)
-               if (!strcasecmp(str, ic->str)) {
-                       *codep = ic->code;
-                       return;
-               }
-       show_usage("unknown ICMP6 unreachable code ``%s''", str);
-}
-
-static void
-add_port(cnt, ptr, off, port)
-       u_short *cnt, *ptr, off, port;
-{
-       if (off + *cnt >= IPV6_FW_MAX_PORTS)
-               errx(1, "too many ports (max is %d)", IPV6_FW_MAX_PORTS);
-       ptr[off+*cnt] = port;
-       (*cnt)++;
-}
-
-static int
-lookup_port(const char *arg, int test, int nodash)
-{
-       int             val;
-       char            *earg, buf[32];
-       struct servent  *s;
-
-       snprintf(buf, sizeof(buf), "%s", arg);
-       buf[strcspn(arg, nodash ? "-," : ",")] = 0;
-       val = (int) strtoul(buf, &earg, 0);
-       if (!*buf || *earg) {
-               setservent(1);
-               if ((s = getservbyname(buf, NULL))) {
-                       val = htons(s->s_port);
-               } else {
-                       if (!test) {
-                               errx(1, "unknown port ``%s''", arg);
-                       }
-                       val = -1;
-               }
-       } else {
-               if (val < 0 || val > 0xffff) {
-                       if (!test) {
-                               errx(1, "port ``%s'' out of range", arg);
-                       }
-                       val = -1;
-               }
-       }
-       return(val);
-}
-
-int
-fill_port(cnt, ptr, off, arg)
-       u_short *cnt, *ptr, off;
-       char *arg;
-{
-       char *s;
-       int initial_range = 0;
-
-       s = arg + strcspn(arg, "-,");   /* first port name can't have a dash */
-       if (*s == '-') {
-               *s++ = '\0';
-               if (strchr(arg, ','))
-                       errx(1, "port range must be first in list");
-               add_port(cnt, ptr, off, *arg ? lookup_port(arg, 0, 0) : 0x0000);
-               arg = s;
-               s = strchr(arg,',');
-               if (s)
-                       *s++ = '\0';
-               add_port(cnt, ptr, off, *arg ? lookup_port(arg, 0, 0) : 0xffff);
-               arg = s;
-               initial_range = 1;
-       }
-       while (arg != NULL) {
-               s = strchr(arg,',');
-               if (s)
-                       *s++ = '\0';
-               add_port(cnt, ptr, off, lookup_port(arg, 0, 0));
-               arg = s;
-       }
-       return initial_range;
-}
-
-void
-fill_tcpflag(set, reset, vp)
-       u_char *set, *reset;
-       char **vp;
-{
-       char *p = *vp,*q;
-       u_char *d;
-
-       while (p && *p) {
-               struct tpcflags {
-                       char * name;
-                       u_char value;
-               } flags[] = {
-                       { "syn", IPV6_FW_TCPF_SYN },
-                       { "fin", IPV6_FW_TCPF_FIN },
-                       { "ack", IPV6_FW_TCPF_ACK },
-                       { "psh", IPV6_FW_TCPF_PSH },
-                       { "rst", IPV6_FW_TCPF_RST },
-                       { "urg", IPV6_FW_TCPF_URG }
-               };
-               int i;
-
-               if (*p == '!') {
-                       p++;
-                       d = reset;
-               } else {
-                       d = set;
-               }
-               q = strchr(p, ',');
-               if (q)
-                       *q++ = '\0';
-               for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i)
-                       if (!strncmp(p, flags[i].name, strlen(p))) {
-                               *d |= flags[i].value;
-                               break;
-                       }
-               if (i == sizeof(flags) / sizeof(flags[0]))
-                       show_usage("invalid tcp flag ``%s''", p);
-               p = q;
-       }
-}
-
-static void
-fill_ip6opt(u_char *set, u_char *reset, char **vp)
-{
-       char *p = *vp,*q;
-       u_char *d;
-
-       while (p && *p) {
-               if (*p == '!') {
-                       p++;
-                       d = reset;
-               } else {
-                       d = set;
-               }
-               q = strchr(p, ',');
-               if (q)
-                       *q++ = '\0';
-               if (!strncmp(p,"hopopt",strlen(p))) *d |= IPV6_FW_IP6OPT_HOPOPT;
-               if (!strncmp(p,"route",strlen(p)))  *d |= IPV6_FW_IP6OPT_ROUTE;
-               if (!strncmp(p,"frag",strlen(p)))   *d |= IPV6_FW_IP6OPT_FRAG;
-               if (!strncmp(p,"esp",strlen(p)))    *d |= IPV6_FW_IP6OPT_ESP;
-               if (!strncmp(p,"ah",strlen(p)))     *d |= IPV6_FW_IP6OPT_AH;
-               if (!strncmp(p,"nonxt",strlen(p)))  *d |= IPV6_FW_IP6OPT_NONXT;
-               if (!strncmp(p,"opts",strlen(p)))   *d |= IPV6_FW_IP6OPT_OPTS;
-               p = q;
-       }
-}
-
-void
-fill_icmptypes(types, vp, fw_flg)
-       unsigned *types;
-       char **vp;
-       u_short *fw_flg;
-{
-       char *c = *vp;
-
-       while (*c)
-       {
-               unsigned long icmptype;
-
-               if ( *c == ',' )
-                       ++c;
-
-               icmptype = strtoul(c, &c, 0);
-
-               if ( *c != ',' && *c != '\0' )
-                       show_usage("invalid ICMP6 type");
-
-               if (icmptype >= IPV6_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8)
-                       show_usage("ICMP6 type out of range");
-
-               types[icmptype / (sizeof(unsigned) * 8)] |=
-                       1U << (icmptype % (sizeof(unsigned) * 8));
-               *fw_flg |= IPV6_FW_F_ICMPBIT;
-       }
-}
-
-void
-delete(ac,av)
-       int ac;
-       char **av;
-{
-       struct ip6_fw rule;
-       int i;
-       int exitval = 0;
-
-       memset(&rule, 0, sizeof rule);
-       rule.version = IPV6_FW_CURRENT_API_VERSION;
-
-       av++; ac--;
-
-       /* Rule number */
-       while (ac && isdigit(**av)) {
-               rule.fw_number = atoi(*av); av++; ac--;
-               i = setsockopt(s, IPPROTO_IPV6, IPV6_FW_DEL, &rule, sizeof rule);
-               if (i) {
-                       exitval = 1;
-                       warn("rule %u: setsockopt(%s)", rule.fw_number, "IPV6_FW_DEL");
-               }
-       }
-       if (exitval != 0)
-               exit(exitval);
-}
-
-static void
-verify_interface(union ip6_fw_if *ifu)
-{
-       struct ifreq ifr;
-
-       /*
-        *      If a unit was specified, check for that exact interface.
-        *      If a wildcard was specified, check for unit 0.
-        */
-       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
-                        ifu->fu_via_if.name,
-                        ifu->fu_via_if.unit == -1 ? 0 : ifu->fu_via_if.unit);
-
-       if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
-               warnx("warning: interface ``%s'' does not exist", ifr.ifr_name);
-}
-
-static void
-fill_iface(char *which, union ip6_fw_if *ifu, int *byname, int ac, char *arg)
-{
-       if (!ac)
-           show_usage("missing argument for ``%s''", which);
-
-       /* Parse the interface or address */
-       if (!strcmp(arg, "any")) {
-               ifu->fu_via_ip6 = in6addr_any;
-               *byname = 0;
-       } else if (!isdigit(*arg)) {
-               char *q;
-
-               *byname = 1;
-               strncpy(ifu->fu_via_if.name, arg, sizeof(ifu->fu_via_if.name));
-               ifu->fu_via_if.name[sizeof(ifu->fu_via_if.name) - 1] = '\0';
-               for (q = ifu->fu_via_if.name;
-                   *q && !isdigit(*q) && *q != '*'; q++)
-                       continue;
-               ifu->fu_via_if.unit = (*q == '*') ? -1 : atoi(q);
-               *q = '\0';
-               verify_interface(ifu);
-       } else if (inet_pton(AF_INET6, arg, &ifu->fu_via_ip6) != 1) {
-               show_usage("bad ip6 address ``%s''", arg);
-       } else
-               *byname = 0;
-}
-
-static void
-add(ac,av)
-       int ac;
-       char **av;
-{
-       struct ip6_fw rule;
-       int i;
-       u_char proto;
-       struct protoent *pe;
-       int saw_xmrc = 0, saw_via = 0;
-
-       memset(&rule, 0, sizeof rule);
-       rule.version = IPV6_FW_CURRENT_API_VERSION;
-
-       av++; ac--;
-
-       /* Rule number */
-       if (ac && isdigit(**av)) {
-               rule.fw_number = atoi(*av); av++; ac--;
-       }
-
-       /* Action */
-       if (ac == 0)
-               show_usage("missing action");
-       if (!strncmp(*av,"accept",strlen(*av))
-                   || !strncmp(*av,"pass",strlen(*av))
-                   || !strncmp(*av,"allow",strlen(*av))
-                   || !strncmp(*av,"permit",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_ACCEPT; av++; ac--;
-       } else if (!strncmp(*av,"count",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_COUNT; av++; ac--;
-       }
-#if 0
-       else if (!strncmp(*av,"divert",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_DIVERT; av++; ac--;
-               if (!ac)
-                       show_usage("missing divert port");
-               rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
-               if (rule.fw_divert_port == 0) {
-                       struct servent *s;
-                       setservent(1);
-                       s = getservbyname(av[-1], "divert");
-                       if (s != NULL)
-                               rule.fw_divert_port = ntohs(s->s_port);
-                       else
-                               show_usage("illegal divert port");
-               }
-       } else if (!strncmp(*av,"tee",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_TEE; av++; ac--;
-               if (!ac)
-                       show_usage("missing divert port");
-               rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--;
-               if (rule.fw_divert_port == 0) {
-                       struct servent *s;
-                       setservent(1);
-                       s = getservbyname(av[-1], "divert");
-                       if (s != NULL)
-                               rule.fw_divert_port = ntohs(s->s_port);
-                       else
-                               show_usage("illegal divert port");
-               }
-       }
-#endif
-       else if (!strncmp(*av,"skipto",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_SKIPTO; av++; ac--;
-               if (!ac)
-                       show_usage("missing skipto rule number");
-               rule.fw_skipto_rule = strtoul(*av, NULL, 0); av++; ac--;
-       } else if ((!strncmp(*av,"deny",strlen(*av))
-                   || !strncmp(*av,"drop",strlen(*av)))) {
-               rule.fw_flg |= IPV6_FW_F_DENY; av++; ac--;
-       } else if (!strncmp(*av,"reject",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_REJECT; av++; ac--;
-               rule.fw_reject_code = ICMP6_DST_UNREACH_NOROUTE;
-       } else if (!strncmp(*av,"reset",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_REJECT; av++; ac--;
-               rule.fw_reject_code = IPV6_FW_REJECT_RST;       /* check TCP later */
-       } else if (!strncmp(*av,"unreach",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_REJECT; av++; ac--;
-               fill_reject_code6(&rule.fw_reject_code, *av); av++; ac--;
-       } else {
-               show_usage("invalid action ``%s''", *av);
-       }
-
-       /* [log] */
-       if (ac && !strncmp(*av,"log",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_PRN; av++; ac--;
-       }
-
-       /* protocol */
-       if (ac == 0)
-               show_usage("missing protocol");
-       if ((proto = atoi(*av)) > 0) {
-               rule.fw_prot = proto; av++; ac--;
-       } else if (!strncmp(*av,"all",strlen(*av))) {
-               rule.fw_prot = IPPROTO_IPV6; av++; ac--;
-       } else if ((pe = getprotobyname(*av)) != NULL) {
-               rule.fw_prot = pe->p_proto; av++; ac--;
-       } else {
-               show_usage("invalid protocol ``%s''", *av);
-       }
-
-       if (rule.fw_prot != IPPROTO_TCP
-           && (rule.fw_flg & IPV6_FW_F_COMMAND) == IPV6_FW_F_REJECT
-           && rule.fw_reject_code == IPV6_FW_REJECT_RST)
-               show_usage("``reset'' is only valid for tcp packets");
-
-       /* from */
-       if (ac && !strncmp(*av,"from",strlen(*av))) { av++; ac--; }
-       else
-               show_usage("missing ``from''");
-
-       if (ac && !strncmp(*av,"not",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_INVSRC;
-               av++; ac--;
-       }
-       if (!ac)
-               show_usage("missing arguments");
-
-       fill_ip6(&rule.fw_src, &rule.fw_smsk, &ac, &av);
-
-       if (ac && (isdigit(**av) || lookup_port(*av, 1, 1) >= 0)) {
-               u_short nports = 0;
-
-               if (fill_port(&nports, rule.fw_pts, 0, *av))
-                       rule.fw_flg |= IPV6_FW_F_SRNG;
-               IPV6_FW_SETNSRCP(&rule, nports);
-               av++; ac--;
-       }
-
-       /* to */
-       if (ac && !strncmp(*av,"to",strlen(*av))) { av++; ac--; }
-       else
-               show_usage("missing ``to''");
-
-       if (ac && !strncmp(*av,"not",strlen(*av))) {
-               rule.fw_flg |= IPV6_FW_F_INVDST;
-               av++; ac--;
-       }
-       if (!ac)
-               show_usage("missing arguments");
-
-       fill_ip6(&rule.fw_dst, &rule.fw_dmsk, &ac, &av);
-
-       if (ac && (isdigit(**av) || lookup_port(*av, 1, 1) >= 0)) {
-               u_short nports = 0;
-
-               if (fill_port(&nports,
-                   rule.fw_pts, IPV6_FW_GETNSRCP(&rule), *av))
-                       rule.fw_flg |= IPV6_FW_F_DRNG;
-               IPV6_FW_SETNDSTP(&rule, nports);
-               av++; ac--;
-       }
-
-       if ((rule.fw_prot != IPPROTO_TCP) && (rule.fw_prot != IPPROTO_UDP)
-           && (IPV6_FW_GETNSRCP(&rule) || IPV6_FW_GETNDSTP(&rule))) {
-               show_usage("only TCP and UDP protocols are valid"
-                   " with port specifications");
-       }
-
-       while (ac) {
-               if (!strncmp(*av,"in",strlen(*av))) {
-                       rule.fw_flg |= IPV6_FW_F_IN;
-                       av++; ac--; continue;
-               }
-               if (!strncmp(*av,"out",strlen(*av))) {
-                       rule.fw_flg |= IPV6_FW_F_OUT;
-                       av++; ac--; continue;
-               }
-               if (ac && !strncmp(*av,"xmit",strlen(*av))) {
-                       union ip6_fw_if ifu;
-                       int byname;
-
-                       if (saw_via) {
-badviacombo:
-                               show_usage("``via'' is incompatible"
-                                   " with ``xmit'' and ``recv''");
-                       }
-                       saw_xmrc = 1;
-                       av++; ac--;
-                       fill_iface("xmit", &ifu, &byname, ac, *av);
-                       rule.fw_out_if = ifu;
-                       rule.fw_flg |= IPV6_FW_F_OIFACE;
-                       if (byname)
-                               rule.fw_flg |= IPV6_FW_F_OIFNAME;
-                       av++; ac--; continue;
-               }
-               if (ac && !strncmp(*av,"recv",strlen(*av))) {
-                       union ip6_fw_if ifu;
-                       int byname;
-
-                       if (saw_via)
-                               goto badviacombo;
-                       saw_xmrc = 1;
-                       av++; ac--;
-                       fill_iface("recv", &ifu, &byname, ac, *av);
-                       rule.fw_in_if = ifu;
-                       rule.fw_flg |= IPV6_FW_F_IIFACE;
-                       if (byname)
-                               rule.fw_flg |= IPV6_FW_F_IIFNAME;
-                       av++; ac--; continue;
-               }
-               if (ac && !strncmp(*av,"via",strlen(*av))) {
-                       union ip6_fw_if ifu;
-                       int byname = 0;
-
-                       if (saw_xmrc)
-                               goto badviacombo;
-                       saw_via = 1;
-                       av++; ac--;
-                       fill_iface("via", &ifu, &byname, ac, *av);
-                       rule.fw_out_if = rule.fw_in_if = ifu;
-                       if (byname)
-                               rule.fw_flg |=
-                                   (IPV6_FW_F_IIFNAME | IPV6_FW_F_OIFNAME);
-                       av++; ac--; continue;
-               }
-               if (!strncmp(*av,"fragment",strlen(*av))) {
-                       rule.fw_flg |= IPV6_FW_F_FRAG;
-                       av++; ac--; continue;
-               }
-               if (!strncmp(*av,"ipv6options",strlen(*av))) {
-                       av++; ac--;
-                       if (!ac)
-                               show_usage("missing argument"
-                                   " for ``ipv6options''");
-                       fill_ip6opt(&rule.fw_ip6opt, &rule.fw_ip6nopt, av);
-                       av++; ac--; continue;
-               }
-               if (rule.fw_prot == IPPROTO_TCP) {
-                       if (!strncmp(*av,"established",strlen(*av))) {
-                               rule.fw_ipflg |= IPV6_FW_IF_TCPEST;
-                               av++; ac--; continue;
-                       }
-                       if (!strncmp(*av,"setup",strlen(*av))) {
-                               rule.fw_tcpf  |= IPV6_FW_TCPF_SYN;
-                               rule.fw_tcpnf  |= IPV6_FW_TCPF_ACK;
-                               av++; ac--; continue;
-                       }
-                       if (!strncmp(*av,"tcpflags",strlen(*av))) {
-                               av++; ac--;
-                               if (!ac)
-                                       show_usage("missing argument"
-                                           " for ``tcpflags''");
-                               fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av);
-                               av++; ac--; continue;
-                       }
-               }
-               if (rule.fw_prot == IPPROTO_ICMPV6) {
-                       if (!strncmp(*av,"icmptypes",strlen(*av))) {
-                               av++; ac--;
-                               if (!ac)
-                                       show_usage("missing argument"
-                                           " for ``icmptypes''");
-                               fill_icmptypes(rule.fw_icmp6types,
-                                   av, &rule.fw_flg);
-                               av++; ac--; continue;
-                       }
-               }
-               show_usage("unknown argument ``%s''", *av);
-       }
-
-       /* No direction specified -> do both directions */
-       if (!(rule.fw_flg & (IPV6_FW_F_OUT|IPV6_FW_F_IN)))
-               rule.fw_flg |= (IPV6_FW_F_OUT|IPV6_FW_F_IN);
-
-       /* Sanity check interface check, but handle "via" case separately */
-       if (saw_via) {
-               if (rule.fw_flg & IPV6_FW_F_IN)
-                       rule.fw_flg |= IPV6_FW_F_IIFACE;
-               if (rule.fw_flg & IPV6_FW_F_OUT)
-                       rule.fw_flg |= IPV6_FW_F_OIFACE;
-       } else if ((rule.fw_flg & IPV6_FW_F_OIFACE) && (rule.fw_flg & IPV6_FW_F_IN))
-               show_usage("can't check xmit interface of incoming packets");
-
-       /* frag may not be used in conjunction with ports or TCP flags */
-       if (rule.fw_flg & IPV6_FW_F_FRAG) {
-               if (rule.fw_tcpf || rule.fw_tcpnf)
-                       show_usage("can't mix 'frag' and tcpflags");
-
-               if (rule.fw_nports)
-                       show_usage("can't mix 'frag' and port specifications");
-       }
-
-       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
-zero (ac, av)
-       int ac;
-       char **av;
-{
-       struct ip6_fw rule;
-
-       av++; ac--;
-       memset(&rule, 0, sizeof rule);
-       rule.version = IPV6_FW_CURRENT_API_VERSION;
-
-       if (!ac) {
-               /* clear all entries */
-               if (setsockopt(s, IPPROTO_IPV6, IPV6_FW_ZERO, &rule, sizeof rule) < 0)
-                       err(EX_UNAVAILABLE, "setsockopt(%s)", "IPV6_FW_ZERO");
-               if (!do_quiet)
-                       printf("Accounting cleared.\n");
-       } else {
-               int failed = 0;
-
-               while (ac) {
-                       /* Rule number */
-                       if (isdigit(**av)) {
-                               rule.fw_number = atoi(*av); av++; ac--;
-                               if (setsockopt(s, IPPROTO_IPV6,
-                                   IPV6_FW_ZERO, &rule, sizeof rule)) {
-                                       warn("rule %u: setsockopt(%s)", rule.fw_number,
-                                                "IPV6_FW_ZERO");
-                                       failed = 1;
-                               }
-                               else if (!do_quiet)
-                                       printf("Entry %d cleared\n",
-                                           rule.fw_number);
-                       } else
-                               show_usage("invalid rule number ``%s''", *av);
-               }
-               if (failed != 0)
-                       exit(failed);
-       }
-}
-
-int
-ip6fw_main(ac,av)
-       int     ac;
-       char    **av;
-{
-       int             ch;
-       extern int      optind;
-
-       /* init optind to 1 */
-       optind = 1;
-
-       if ( ac == 1 ) {
-               show_usage(NULL);
-       }
-
-       /* Set the force flag for non-interactive processes */
-       do_force = !isatty(STDIN_FILENO);
-
-       while ((ch = getopt(ac, av ,"afqtN")) != -1)
-       switch(ch) {
-               case 'a':
-                       do_acct=1;
-                       break;
-               case 'f':
-                       do_force=1;
-                       break;
-               case 'q':
-                       do_quiet=1;
-                       break;
-               case 't':
-                       do_time=1;
-                       break;
-               case 'N':
-                       do_resolv=1;
-                       break;
-               default:
-                       show_usage(NULL);
-       }
-
-       ac -= optind;
-       if (*(av+=optind)==NULL) {
-                show_usage("Bad arguments");
-       }
-
-       if (!strncmp(*av, "add", strlen(*av))) {
-               add(ac,av);
-       } else if (!strncmp(*av, "delete", strlen(*av))) {
-               delete(ac,av);
-       } else if (!strncmp(*av, "flush", strlen(*av))) {
-               int do_flush = 0;
-
-               if ( do_force || do_quiet )
-                       do_flush = 1;
-               else {
-                       int c;
-
-                       /* Ask the user */
-                       printf("Are you sure? [yn] ");
-                       do {
-                               fflush(stdout);
-                               c = toupper(getc(stdin));
-                               while (c != '\n' && getc(stdin) != '\n')
-                                       if (feof(stdin))
-                                               return (0);
-                       } while (c != 'Y' && c != 'N');
-                       printf("\n");
-                       if (c == 'Y')
-                               do_flush = 1;
-               }
-               if ( do_flush ) {
-                       struct ip6_fw rule;
-
-                       memset(&rule, 0, sizeof rule);
-                       rule.version = IPV6_FW_CURRENT_API_VERSION;
-                       if (setsockopt(s, IPPROTO_IPV6, IPV6_FW_FLUSH, &rule, sizeof rule) < 0)
-                               err(EX_UNAVAILABLE, "setsockopt(%s)", "IPV6_FW_FLUSH");
-                       if (!do_quiet)
-                               printf("Flushed all rules.\n");
-               }
-       } else if (!strncmp(*av, "zero", strlen(*av))) {
-               zero(ac,av);
-       } else if (!strncmp(*av, "print", strlen(*av))) {
-               list(--ac,++av);
-       } else if (!strncmp(*av, "list", strlen(*av))) {
-               list(--ac,++av);
-       } else if (!strncmp(*av, "show", strlen(*av))) {
-               do_acct++;
-               list(--ac,++av);
-       } else {
-               show_usage("Bad arguments");
-       }
-       return 0;
-}
-
-int
-main(ac, av)
-       int     ac;
-       char    **av;
-{
-#define        MAX_ARGS        32
-#define        WHITESP         " \t\f\v\n\r"
-       char    buf[BUFSIZ];
-       char    *a, *p, *args[MAX_ARGS], *cmd = NULL;
-       char    linename[16];
-       int     i, c, lineno, qflag, pflag, status;
-       FILE    *f = NULL;
-       pid_t   preproc = 0;
-
-       s = socket( AF_INET6, SOCK_RAW, IPPROTO_RAW );
-       if ( s < 0 )
-               err(EX_UNAVAILABLE, "socket");
-
-       setbuf(stdout,0);
-
-       /*
-        * Only interpret the last command line argument as a file to
-        * be preprocessed if it is specified as an absolute pathname.
-        */
-
-       if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0) {
-               qflag = pflag = i = 0;
-               lineno = 0;
-
-               while ((c = getopt(ac, av, "D:U:p:q")) != -1)
-                       switch(c) {
-                       case 'D':
-                               if (!pflag)
-                                       errx(EX_USAGE, "-D requires -p");
-                               if (i > MAX_ARGS - 2)
-                                       errx(EX_USAGE,
-                                            "too many -D or -U options");
-                               args[i++] = "-D";
-                               args[i++] = optarg;
-                               break;
-
-                       case 'U':
-                               if (!pflag)
-                                       errx(EX_USAGE, "-U requires -p");
-                               if (i > MAX_ARGS - 2)
-                                       errx(EX_USAGE,
-                                            "too many -D or -U options");
-                               args[i++] = "-U";
-                               args[i++] = optarg;
-                               break;
-
-                       case 'p':
-                               pflag = 1;
-                               cmd = optarg;
-                               args[0] = cmd;
-                               i = 1;
-                               break;
-
-                       case 'q':
-                               qflag = 1;
-                               break;
-
-                       default:
-                               show_usage(NULL);
-                       }
-
-               av += optind;
-               ac -= optind;
-               if (ac != 1)
-                       show_usage("extraneous filename arguments");
-
-               if ((f = fopen(av[0], "r")) == NULL)
-                       err(EX_UNAVAILABLE, "fopen: %s", av[0]);
-
-               if (pflag) {
-                       /* pipe through preprocessor (cpp or m4) */
-                       int pipedes[2];
-
-                       args[i] = 0;
-
-                       if (pipe(pipedes) == -1)
-                               err(EX_OSERR, "cannot create pipe");
-
-                       switch((preproc = fork())) {
-                       case -1:
-                               err(EX_OSERR, "cannot fork");
-
-                       case 0:
-                               /* child */
-                               if (dup2(fileno(f), 0) == -1 ||
-                                   dup2(pipedes[1], 1) == -1)
-                                       err(EX_OSERR, "dup2()");
-                               fclose(f);
-                               close(pipedes[1]);
-                               close(pipedes[0]);
-                               execvp(cmd, args);
-                               err(EX_OSERR, "execvp(%s) failed", cmd);
-
-                       default:
-                               /* parent */
-                               fclose(f);
-                               close(pipedes[1]);
-                               if ((f = fdopen(pipedes[0], "r")) == NULL) {
-                                       int savederrno = errno;
-
-                                       (void)kill(preproc, SIGTERM);
-                                       errno = savederrno;
-                                       err(EX_OSERR, "fdopen()");
-                               }
-                       }
-               }
-
-               while (fgets(buf, BUFSIZ, f)) {
-                       lineno++;
-                       snprintf(linename, sizeof(linename), "Line %d", lineno);
-                       args[0] = linename;
-
-                       if (*buf == '#')
-                               continue;
-                       if ((p = strchr(buf, '#')) != NULL)
-                               *p = '\0';
-                       i=1;
-                       if (qflag) args[i++]="-q";
-                       for (a = strtok(buf, WHITESP);
-                           a && i < MAX_ARGS; a = strtok(NULL, WHITESP), i++)
-                               args[i] = a;
-                       if (i == (qflag? 2: 1))
-                               continue;
-                       if (i == MAX_ARGS)
-                               errx(EX_USAGE, "%s: too many arguments", linename);
-                       args[i] = NULL;
-
-                       ip6fw_main(i, args);
-               }
-               fclose(f);
-               if (pflag) {
-                       if (waitpid(preproc, &status, 0) != -1) {
-                               if (WIFEXITED(status)) {
-                                       if (WEXITSTATUS(status) != EX_OK)
-                                               errx(EX_UNAVAILABLE,
-                                                    "preprocessor exited with status %d",
-                                                    WEXITSTATUS(status));
-                               } else if (WIFSIGNALED(status)) {
-                                       errx(EX_UNAVAILABLE,
-                                            "preprocessor exited with signal %d",
-                                            WTERMSIG(status));
-                               }
-                       }
-               }
-       } else
-               ip6fw_main(ac,av);
-       return 0;
-}
diff --git a/ipfw.tproj/ipfw.8 b/ipfw.tproj/ipfw.8
deleted file mode 100644 (file)
index 71e3aed..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-.Dd September 27, 2012
-.Dt IPFW 8
-.Os Darwin
-.Sh NAME
-.Nm ipfw
-.Sh DESCRIPTION
-This utility is
-.Cm DEPRECATED.
-Please use
-.Xr pfctl 8
-instead.
diff --git a/ipfw.tproj/ipfw2.c b/ipfw.tproj/ipfw2.c
deleted file mode 100644 (file)
index c6c35af..0000000
+++ /dev/null
@@ -1,4064 +0,0 @@
-/*
- * Copyright (c) 2002-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) 2002-2003 Luigi Rizzo
- * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
- * Copyright (c) 1994 Ugen J.S.Antsilevich
- *
- * Idea and grammar partially left from:
- * Copyright (c) 1993 Daniel Boulet
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- *
- * NEW command line interface for IP firewall facility
- *
- * $FreeBSD: /repoman/r/ncvs/src/sbin/ipfw/ipfw2.c,v 1.4.2.18 2003/09/15 10:27:03 luigi Exp $
- */
-
-#include <sys/param.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <grp.h>
-#include <limits.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <sysexits.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#define IPFW2
-#include <netinet/ip_fw.h>
-#undef IPFW2
-#include <net/route.h> /* def. of struct route */
-#include <netinet/ip_dummynet.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-
-int
-               do_resolv,              /* Would try to resolve all */
-               do_time,                /* Show time stamps */
-               do_quiet,               /* Be quiet in add and flush */
-               do_pipe,                /* this cmd refers to a pipe */
-               do_sort,                /* field to sort results (0 = no) */
-               do_dynamic,             /* display dynamic rules */
-               do_expired,             /* display expired dynamic rules */
-               do_compact,             /* show rules in compact mode */
-               show_sets,              /* display rule sets */
-               test_only,              /* only check syntax */
-               verbose;
-
-#define        IP_MASK_ALL     0xffffffff
-
-/*
- * _s_x is a structure that stores a string <-> token pairs, used in
- * various places in the parser. Entries are stored in arrays,
- * with an entry with s=NULL as terminator.
- * The search routines are match_token() and match_value().
- * Often, an element with x=0 contains an error string.
- *
- */
-struct _s_x {
-       char const *s;
-       int x;
-};
-
-static struct _s_x f_tcpflags[] = {
-       { "syn", TH_SYN },
-       { "fin", TH_FIN },
-       { "ack", TH_ACK },
-       { "psh", TH_PUSH },
-       { "rst", TH_RST },
-       { "urg", TH_URG },
-       { "tcp flag", 0 },
-       { NULL, 0 }
-};
-
-static struct _s_x f_tcpopts[] = {
-       { "mss",        IP_FW_TCPOPT_MSS },
-       { "maxseg",     IP_FW_TCPOPT_MSS },
-       { "window",     IP_FW_TCPOPT_WINDOW },
-       { "sack",       IP_FW_TCPOPT_SACK },
-       { "ts",         IP_FW_TCPOPT_TS },
-       { "timestamp",  IP_FW_TCPOPT_TS },
-       { "cc",         IP_FW_TCPOPT_CC },
-       { "tcp option", 0 },
-       { NULL, 0 }
-};
-
-/*
- * IP options span the range 0 to 255 so we need to remap them
- * (though in fact only the low 5 bits are significant).
- */
-static struct _s_x f_ipopts[] = {
-       { "ssrr",       IP_FW_IPOPT_SSRR},
-       { "lsrr",       IP_FW_IPOPT_LSRR},
-       { "rr",         IP_FW_IPOPT_RR},
-       { "ts",         IP_FW_IPOPT_TS},
-       { "ip option",  0 },
-       { NULL, 0 }
-};
-
-static struct _s_x f_iptos[] = {
-       { "lowdelay",   IPTOS_LOWDELAY},
-       { "throughput", IPTOS_THROUGHPUT},
-       { "reliability", IPTOS_RELIABILITY},
-       { "mincost",    IPTOS_MINCOST},
-       { "congestion", IPTOS_CE},
-       { "ecntransport", IPTOS_ECT},
-       { "ip tos option", 0},
-       { NULL, 0 }
-};
-
-static struct _s_x limit_masks[] = {
-       {"all",         DYN_SRC_ADDR|DYN_SRC_PORT|DYN_DST_ADDR|DYN_DST_PORT},
-       {"src-addr",    DYN_SRC_ADDR},
-       {"src-port",    DYN_SRC_PORT},
-       {"dst-addr",    DYN_DST_ADDR},
-       {"dst-port",    DYN_DST_PORT},
-       {NULL,          0}
-};
-
-/*
- * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
- * This is only used in this code.
- */
-#define IPPROTO_ETHERTYPE      0x1000
-static struct _s_x ether_types[] = {
-    /*
-     * Note, we cannot use "-:&/" in the names because they are field
-     * separators in the type specifications. Also, we use s = NULL as
-     * end-delimiter, because a type of 0 can be legal.
-     */
-       { "ip",         0x0800 },
-       { "ipv4",       0x0800 },
-       { "ipv6",       0x86dd },
-       { "arp",        0x0806 },
-       { "rarp",       0x8035 },
-       { "vlan",       0x8100 },
-       { "loop",       0x9000 },
-       { "trail",      0x1000 },
-       { "at",         0x809b },
-       { "atalk",      0x809b },
-       { "aarp",       0x80f3 },
-       { "pppoe_disc", 0x8863 },
-       { "pppoe_sess", 0x8864 },
-       { "ipx_8022",   0x00E0 },
-       { "ipx_8023",   0x0000 },
-       { "ipx_ii",     0x8137 },
-       { "ipx_snap",   0x8137 },
-       { "ipx",        0x8137 },
-       { "ns",         0x0600 },
-       { NULL,         0 }
-};
-
-static struct _s_x exception_types[] = {
-       { "to",         1},
-       { "dst",        2},
-       { "in",         3},
-       { "out",        4},
-       { "xmit",       5},
-       { "recv",       6},
-       { "via",        7},
-       { "src",        8},
-       { NULL,         0}
-};
-
-static void show_usage(void);
-
-enum tokens {
-       TOK_NULL=0,
-
-       TOK_OR,
-       TOK_NOT,
-       TOK_STARTBRACE,
-       TOK_ENDBRACE,
-
-       TOK_ACCEPT,
-       TOK_COUNT,
-       TOK_PIPE,
-       TOK_QUEUE,
-       TOK_DIVERT,
-       TOK_TEE,
-       TOK_FORWARD,
-       TOK_SKIPTO,
-       TOK_DENY,
-       TOK_REJECT,
-       TOK_RESET,
-       TOK_UNREACH,
-       TOK_CHECKSTATE,
-
-       TOK_UID,
-       TOK_GID,
-       TOK_IN,
-       TOK_LIMIT,
-       TOK_KEEPSTATE,
-       TOK_LAYER2,
-       TOK_OUT,
-       TOK_XMIT,
-       TOK_RECV,
-       TOK_VIA,
-       TOK_FRAG,
-       TOK_IPOPTS,
-       TOK_IPLEN,
-       TOK_IPID,
-       TOK_IPPRECEDENCE,
-       TOK_IPTOS,
-       TOK_IPTTL,
-       TOK_IPVER,
-       TOK_ESTAB,
-       TOK_SETUP,
-       TOK_TCPFLAGS,
-       TOK_TCPOPTS,
-       TOK_TCPSEQ,
-       TOK_TCPACK,
-       TOK_TCPWIN,
-       TOK_ICMPTYPES,
-       TOK_MAC,
-       TOK_MACTYPE,
-       TOK_VERREVPATH,
-       TOK_IPSEC,
-       TOK_COMMENT,
-
-       TOK_PLR,
-       TOK_NOERROR,
-       TOK_BUCKETS,
-       TOK_DSTIP,
-       TOK_SRCIP,
-       TOK_DSTPORT,
-       TOK_SRCPORT,
-       TOK_ALL,
-       TOK_MASK,
-       TOK_BW,
-       TOK_DELAY,
-       TOK_RED,
-       TOK_GRED,
-       TOK_DROPTAIL,
-       TOK_PROTO,
-       TOK_WEIGHT,
-};
-
-struct _s_x dummynet_params[] = {
-       { "plr",                TOK_PLR },
-       { "noerror",            TOK_NOERROR },
-       { "buckets",            TOK_BUCKETS },
-       { "dst-ip",             TOK_DSTIP },
-       { "src-ip",             TOK_SRCIP },
-       { "dst-port",           TOK_DSTPORT },
-       { "src-port",           TOK_SRCPORT },
-       { "proto",              TOK_PROTO },
-       { "weight",             TOK_WEIGHT },
-       { "all",                TOK_ALL },
-       { "mask",               TOK_MASK },
-       { "droptail",           TOK_DROPTAIL },
-       { "red",                TOK_RED },
-       { "gred",               TOK_GRED },
-       { "bw",                 TOK_BW },
-       { "bandwidth",          TOK_BW },
-       { "delay",              TOK_DELAY },
-       { "pipe",               TOK_PIPE },
-       { "queue",              TOK_QUEUE },
-       { "dummynet-params",    TOK_NULL },
-       { NULL, 0 }     /* terminator */
-};
-
-struct _s_x rule_actions[] = {
-       { "accept",             TOK_ACCEPT },
-       { "pass",               TOK_ACCEPT },
-       { "allow",              TOK_ACCEPT },
-       { "permit",             TOK_ACCEPT },
-       { "count",              TOK_COUNT },
-       { "pipe",               TOK_PIPE },
-       { "queue",              TOK_QUEUE },
-       { "divert",             TOK_DIVERT },
-       { "tee",                TOK_TEE },
-       { "fwd",                TOK_FORWARD },
-       { "forward",            TOK_FORWARD },
-       { "skipto",             TOK_SKIPTO },
-       { "deny",               TOK_DENY },
-       { "drop",               TOK_DENY },
-       { "reject",             TOK_REJECT },
-       { "reset",              TOK_RESET },
-       { "unreach",            TOK_UNREACH },
-       { "check-state",        TOK_CHECKSTATE },
-       { "//",                 TOK_COMMENT },
-       { NULL, 0 }     /* terminator */
-};
-
-struct _s_x rule_options[] = {
-       { "uid",                TOK_UID },
-       { "gid",                TOK_GID },
-       { "in",                 TOK_IN },
-       { "limit",              TOK_LIMIT },
-       { "keep-state",         TOK_KEEPSTATE },
-       { "bridged",            TOK_LAYER2 },
-       { "layer2",             TOK_LAYER2 },
-       { "out",                TOK_OUT },
-       { "xmit",               TOK_XMIT },
-       { "recv",               TOK_RECV },
-       { "via",                TOK_VIA },
-       { "fragment",           TOK_FRAG },
-       { "frag",               TOK_FRAG },
-       { "ipoptions",          TOK_IPOPTS },
-       { "ipopts",             TOK_IPOPTS },
-       { "iplen",              TOK_IPLEN },
-       { "ipid",               TOK_IPID },
-       { "ipprecedence",       TOK_IPPRECEDENCE },
-       { "iptos",              TOK_IPTOS },
-       { "ipttl",              TOK_IPTTL },
-       { "ipversion",          TOK_IPVER },
-       { "ipver",              TOK_IPVER },
-       { "estab",              TOK_ESTAB },
-       { "established",        TOK_ESTAB },
-       { "setup",              TOK_SETUP },
-       { "tcpflags",           TOK_TCPFLAGS },
-       { "tcpflgs",            TOK_TCPFLAGS },
-       { "tcpoptions",         TOK_TCPOPTS },
-       { "tcpopts",            TOK_TCPOPTS },
-       { "tcpseq",             TOK_TCPSEQ },
-       { "tcpack",             TOK_TCPACK },
-       { "tcpwin",             TOK_TCPWIN },
-       { "icmptype",           TOK_ICMPTYPES },
-       { "icmptypes",          TOK_ICMPTYPES },
-       { "dst-ip",             TOK_DSTIP },
-       { "src-ip",             TOK_SRCIP },
-       { "dst-port",           TOK_DSTPORT },
-       { "src-port",           TOK_SRCPORT },
-       { "proto",              TOK_PROTO },
-       { "MAC",                TOK_MAC },
-       { "mac",                TOK_MAC },
-       { "mac-type",           TOK_MACTYPE },
-       { "verrevpath",         TOK_VERREVPATH },
-       { "ipsec",              TOK_IPSEC },
-       { "//",                 TOK_COMMENT },
-
-       { "not",                TOK_NOT },              /* pseudo option */
-       { "!", /* escape ? */   TOK_NOT },              /* pseudo option */
-       { "or",                 TOK_OR },               /* pseudo option */
-       { "|", /* escape */     TOK_OR },               /* pseudo option */
-       { "{",                  TOK_STARTBRACE },       /* pseudo option */
-       { "(",                  TOK_STARTBRACE },       /* pseudo option */
-       { "}",                  TOK_ENDBRACE },         /* pseudo option */
-       { ")",                  TOK_ENDBRACE },         /* pseudo option */
-       { NULL, 0 }     /* terminator */
-};
-
-static __inline uint64_t
-align_uint64(uint64_t *pll) {
-       uint64_t ret;
-
-       bcopy (pll, &ret, sizeof(ret));
-       return ret;
-};
-
-/*
- * conditionally runs the command.
- */
-static int
-do_cmd(int optname, void *optval, uintptr_t optlen)
-{
-       static int s = -1;      /* the socket */
-       int i;
-
-       if (test_only)
-               return 0;
-
-       if (s == -1)
-               s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-       if (s < 0)
-               err(EX_UNAVAILABLE, "socket");
-       
-       switch (optname) {
-               case IP_FW_GET:
-               case IP_FW_FLUSH:
-               case IP_FW_ADD:
-               case IP_FW_DEL:
-               case IP_FW_ZERO:
-               case IP_FW_RESETLOG:
-                       ((struct ip_fw *)optval)->version = IP_FW_CURRENT_API_VERSION;
-               default:
-                       break;
-       }
-
-       if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
-           optname == IP_FW_ADD)
-               i = getsockopt(s, IPPROTO_IP, optname, optval,
-                       (socklen_t *)optlen);
-       else
-               i = setsockopt(s, IPPROTO_IP, optname, optval, optlen);
-       return i;
-}
-
-/**
- * match_token takes a table and a string, returns the value associated
- * with the string (-1 in case of failure).
- */
-static int
-match_token(struct _s_x *table, char *string)
-{
-       struct _s_x *pt;
-       uint i = strlen(string);
-
-       for (pt = table ; i && pt->s != NULL ; pt++)
-               if (strlen(pt->s) == i && !bcmp(string, pt->s, i))
-                       return pt->x;
-       return -1;
-};
-
-/**
- * match_value takes a table and a value, returns the string associated
- * with the value (NULL in case of failure).
- */
-static char const *
-match_value(struct _s_x *p, int value)
-{
-       for (; p->s != NULL; p++)
-               if (p->x == value)
-                       return p->s;
-       return NULL;
-}
-
-/*
- * prints one port, symbolic or numeric
- */
-static void
-print_port(int proto, uint16_t port)
-{
-
-       if (proto == IPPROTO_ETHERTYPE) {
-               char const *s;
-
-               if (do_resolv && (s = match_value(ether_types, port)) )
-                       printf("%s", s);
-               else
-                       printf("0x%04x", port);
-       } else {
-               struct servent *se = NULL;
-               if (do_resolv) {
-                       struct protoent *pe = getprotobynumber(proto);
-
-                       se = getservbyport(htons(port), pe ? pe->p_name : NULL);
-               }
-               if (se)
-                       printf("%s", se->s_name);
-               else
-                       printf("%d", port);
-       }
-}
-
-struct _s_x _port_name[] = {
-       {"dst-port",    O_IP_DSTPORT},
-       {"src-port",    O_IP_SRCPORT},
-       {"ipid",        O_IPID},
-       {"iplen",       O_IPLEN},
-       {"ipttl",       O_IPTTL},
-       {"mac-type",    O_MAC_TYPE},
-       {NULL,          0}
-};
-
-/*
- * Print the values in a list 16-bit items of the types above.
- * XXX todo: add support for mask.
- */
-static void
-print_newports(ipfw_insn_u16 *cmd, int proto, int opcode)
-{
-       uint16_t *p = cmd->ports;
-       int i;
-       char const *sep;
-
-       if (cmd->o.len & F_NOT)
-               printf(" not");
-       if (opcode != 0) {
-               sep = match_value(_port_name, opcode);
-               if (sep == NULL)
-                       sep = "???";
-               printf (" %s", sep);
-       }
-       sep = " ";
-       for (i = F_LEN((ipfw_insn *)cmd) - 1; i > 0; i--, p += 2) {
-               printf("%s", sep);
-               print_port(proto, p[0]);
-               if (p[0] != p[1]) {
-                       printf("-");
-                       print_port(proto, p[1]);
-               }
-               sep = ",";
-       }
-}
-
-/*
- * Like strtol, but also translates service names into port numbers
- * for some protocols.
- * In particular:
- *     proto == -1 disables the protocol check;
- *     proto == IPPROTO_ETHERTYPE looks up an internal table
- *     proto == <some value in /etc/protocols> matches the values there.
- * Returns *end == s in case the parameter is not found.
- */
-static int
-strtoport(char *s, char **end, int base, int proto)
-{
-       char *p, *buf;
-       char *s1;
-       int i;
-
-       *end = s;               /* default - not found */
-       if (*s == '\0')
-               return 0;       /* not found */
-
-       if (isdigit(*s))
-               return strtol(s, end, base);
-
-       /*
-        * find separator. '\\' escapes the next char.
-        */
-       for (s1 = s; *s1 && (isalnum(*s1) || *s1 == '\\') ; s1++)
-               if (*s1 == '\\' && s1[1] != '\0')
-                       s1++;
-
-       buf = malloc(s1 - s + 1);
-       if (buf == NULL)
-               return 0;
-
-       /*
-        * copy into a buffer skipping backslashes
-        */
-       for (p = s, i = 0; p != s1 ; p++)
-               if (*p != '\\')
-                       buf[i++] = *p;
-       buf[i++] = '\0';
-
-       if ( match_token( exception_types, buf) != -1 ){
-               free(buf);
-               return 0;
-       }
-
-       if (proto == IPPROTO_ETHERTYPE) {
-               i = match_token(ether_types, buf);
-               free(buf);
-               if (i != -1) {  /* found */
-                       *end = s1;
-                       return i;
-               }
-       } else {
-               struct protoent *pe = NULL;
-               struct servent *se;
-
-               if (proto != 0)
-                       pe = getprotobynumber(proto);
-               setservent(1);
-               se = getservbyname(buf, pe ? pe->p_name : NULL);
-               free(buf);
-               if (se != NULL) {
-                       *end = s1;
-                       return ntohs(se->s_port);
-               }
-       }
-       return 0;       /* not found */
-}
-
-/*
- * Fill the body of the command with the list of port ranges.
- */
-static int
-fill_newports(ipfw_insn_u16 *cmd, char *av, int proto)
-{
-       uint16_t a, b, *p = cmd->ports;
-       int i = 0;
-       char *s = av;
-
-       while (*s) {
-               a = strtoport(av, &s, 0, proto);
-               if (s == av) /* no parameter */
-                       break;
-               if (*s == '-') { /* a range */
-                       av = s+1;
-                       b = strtoport(av, &s, 0, proto);
-                       if (s == av) /* no parameter */
-                               break;
-                       p[0] = a;
-                       p[1] = b;
-               } else if (*s == ',' || *s == '\0' )
-                       p[0] = p[1] = a;
-               else    /* invalid separator */
-                       errx(EX_DATAERR, "invalid separator <%c> in <%s>",
-                               *s, av);
-               i++;
-               p += 2;
-               av = s+1;
-       }
-       if (i > 0) {
-               if (i+1 > F_LEN_MASK)
-                       errx(EX_DATAERR, "too many ports/ranges");
-               cmd->o.len |= i+1; /* leave F_NOT and F_OR untouched */
-       }
-       return i;
-}
-
-static struct _s_x icmpcodes[] = {
-      { "net",                 ICMP_UNREACH_NET },
-      { "host",                        ICMP_UNREACH_HOST },
-      { "protocol",            ICMP_UNREACH_PROTOCOL },
-      { "port",                        ICMP_UNREACH_PORT },
-      { "needfrag",            ICMP_UNREACH_NEEDFRAG },
-      { "srcfail",             ICMP_UNREACH_SRCFAIL },
-      { "net-unknown",         ICMP_UNREACH_NET_UNKNOWN },
-      { "host-unknown",                ICMP_UNREACH_HOST_UNKNOWN },
-      { "isolated",            ICMP_UNREACH_ISOLATED },
-      { "net-prohib",          ICMP_UNREACH_NET_PROHIB },
-      { "host-prohib",         ICMP_UNREACH_HOST_PROHIB },
-      { "tosnet",              ICMP_UNREACH_TOSNET },
-      { "toshost",             ICMP_UNREACH_TOSHOST },
-      { "filter-prohib",       ICMP_UNREACH_FILTER_PROHIB },
-      { "host-precedence",     ICMP_UNREACH_HOST_PRECEDENCE },
-      { "precedence-cutoff",   ICMP_UNREACH_PRECEDENCE_CUTOFF },
-      { NULL, 0 }
-};
-
-static void
-fill_reject_code(u_short *codep, char *str)
-{
-       int val;
-       char *s;
-
-       val = strtoul(str, &s, 0);
-       if (s == str || *s != '\0' || val >= 0x100)
-               val = match_token(icmpcodes, str);
-       if (val < 0)
-               errx(EX_DATAERR, "unknown ICMP unreachable code ``%s''", str);
-       *codep = val;
-       return;
-}
-
-static void
-print_reject_code(uint16_t code)
-{
-       char const *s = match_value(icmpcodes, code);
-
-       if (s != NULL)
-               printf("unreach %s", s);
-       else
-               printf("unreach %u", code);
-}
-
-/*
- * Returns the number of bits set (from left) in a contiguous bitmask,
- * or -1 if the mask is not contiguous.
- * XXX this needs a proper fix.
- * This effectively works on masks in big-endian (network) format.
- * when compiled on little endian architectures.
- *
- * First bit is bit 7 of the first byte -- note, for MAC addresses,
- * the first bit on the wire is bit 0 of the first byte.
- * len is the max length in bits.
- */
-static int
-contigmask(uint8_t *p, int len)
-{
-       int i, n;
-
-       for (i=0; i<len ; i++)
-               if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */
-                       break;
-       for (n=i+1; n < len; n++)
-               if ( (p[n/8] & (1 << (7 - (n%8)))) != 0)
-                       return -1; /* mask not contiguous */
-       return i;
-}
-
-/*
- * print flags set/clear in the two bitmasks passed as parameters.
- * There is a specialized check for f_tcpflags.
- */
-static void
-print_flags(char const *name, ipfw_insn *cmd, struct _s_x *list)
-{
-       char const *comma = "";
-       int i;
-       uint8_t set = cmd->arg1 & 0xff;
-       uint8_t clear = (cmd->arg1 >> 8) & 0xff;
-
-       if (list == f_tcpflags && set == TH_SYN && clear == TH_ACK) {
-               printf(" setup");
-               return;
-       }
-
-       printf(" %s ", name);
-       for (i=0; list[i].x != 0; i++) {
-               if (set & list[i].x) {
-                       set &= ~list[i].x;
-                       printf("%s%s", comma, list[i].s);
-                       comma = ",";
-               }
-               if (clear & list[i].x) {
-                       clear &= ~list[i].x;
-                       printf("%s!%s", comma, list[i].s);
-                       comma = ",";
-               }
-       }
-}
-
-/*
- * Print the ip address contained in a command.
- */
-static void
-print_ip(ipfw_insn_ip *cmd, char const *s)
-{
-       struct hostent *he = NULL;
-       int len = F_LEN((ipfw_insn *)cmd);
-       uint32_t *a = ((ipfw_insn_u32 *)cmd)->d;
-
-       printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s);
-
-       if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) {
-               printf("me");
-               return;
-       }
-       if (cmd->o.opcode == O_IP_SRC_SET || cmd->o.opcode == O_IP_DST_SET) {
-               uint32_t x, *map = (uint32_t *)&(cmd->mask);
-               int i, j;
-               char comma = '{';
-
-               x = cmd->o.arg1 - 1;
-               x = htonl( ~x );
-               cmd->addr.s_addr = htonl(cmd->addr.s_addr);
-               printf("%s/%d", inet_ntoa(cmd->addr),
-                       contigmask((uint8_t *)&x, 32));
-               x = cmd->addr.s_addr = htonl(cmd->addr.s_addr);
-               x &= 0xff; /* base */
-               /*
-                * Print bits and ranges.
-                * Locate first bit set (i), then locate first bit unset (j).
-                * If we have 3+ consecutive bits set, then print them as a
-                * range, otherwise only print the initial bit and rescan.
-                */
-               for (i=0; i < cmd->o.arg1; i++)
-                       if (map[i/32] & (1<<(i & 31))) {
-                               for (j=i+1; j < cmd->o.arg1; j++)
-                                       if (!(map[ j/32] & (1<<(j & 31))))
-                                               break;
-                               printf("%c%d", comma, i+x);
-                               if (j>i+2) { /* range has at least 3 elements */
-                                       printf("-%d", j-1+x);
-                                       i = j-1;
-                               }
-                               comma = ',';
-                       }
-               printf("}");
-               return;
-       }
-       /*
-        * len == 2 indicates a single IP, whereas lists of 1 or more
-        * addr/mask pairs have len = (2n+1). We convert len to n so we
-        * use that to count the number of entries.
-        */
-    for (len = len / 2; len > 0; len--, a += 2) {
-       int mb =        /* mask length */
-           (cmd->o.opcode == O_IP_SRC || cmd->o.opcode == O_IP_DST) ?
-               32 : contigmask((uint8_t *)&(a[1]), 32);
-       if (mb == 32 && do_resolv)
-               he = gethostbyaddr((char *)&(a[0]), sizeof(in_addr_t), AF_INET);
-       if (he != NULL)         /* resolved to name */
-               printf("%s", he->h_name);
-       else if (mb == 0)       /* any */
-               printf("any");
-       else {          /* numeric IP followed by some kind of mask */
-               printf("%s", inet_ntoa( *((struct in_addr *)&a[0]) ) );
-               if (mb < 0)
-                       printf(":%s", inet_ntoa( *((struct in_addr *)&a[1]) ) );
-               else if (mb < 32)
-                       printf("/%d", mb);
-       }
-       if (len > 1)
-               printf(",");
-    }
-}
-
-/*
- * prints a MAC address/mask pair
- */
-static void
-print_mac(uint8_t *addr, uint8_t *mask)
-{
-       int l = contigmask(mask, 48);
-
-       if (l == 0)
-               printf(" any");
-       else {
-               printf(" %02x:%02x:%02x:%02x:%02x:%02x",
-                   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
-               if (l == -1)
-                       printf("&%02x:%02x:%02x:%02x:%02x:%02x",
-                           mask[0], mask[1], mask[2],
-                           mask[3], mask[4], mask[5]);
-               else if (l < 48)
-                       printf("/%d", l);
-       }
-}
-
-static void
-fill_icmptypes(ipfw_insn_u32 *cmd, char *av)
-{
-       uint8_t type;
-
-       cmd->d[0] = 0;
-       while (*av) {
-               if (*av == ',')
-                       av++;
-
-               type = strtoul(av, &av, 0);
-
-               if (*av != ',' && *av != '\0')
-                       errx(EX_DATAERR, "invalid ICMP type");
-
-               if (type > 31)
-                       errx(EX_DATAERR, "ICMP type out of range");
-
-               cmd->d[0] |= 1 << type;
-       }
-       cmd->o.opcode = O_ICMPTYPE;
-       cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
-}
-
-static void
-print_icmptypes(ipfw_insn_u32 *cmd)
-{
-       int i;
-       char sep= ' ';
-
-       printf(" icmptypes");
-       for (i = 0; i < 32; i++) {
-               if ( (cmd->d[0] & (1 << (i))) == 0)
-                       continue;
-               printf("%c%d", sep, i);
-               sep = ',';
-       }
-}
-
-/*
- * show_ipfw() prints the body of an ipfw rule.
- * Because the standard rule has at least proto src_ip dst_ip, we use
- * a helper function to produce these entries if not provided explicitly.
- * The first argument is the list of fields we have, the second is
- * the list of fields we want to be printed.
- *
- * Special cases if we have provided a MAC header:
- *   + if the rule does not contain IP addresses/ports, do not print them;
- *   + if the rule does not contain an IP proto, print "all" instead of "ip";
- *
- * Once we have 'have_options', IP header fields are printed as options.
- */
-#define        HAVE_PROTO      0x0001
-#define        HAVE_SRCIP      0x0002
-#define        HAVE_DSTIP      0x0004
-#define        HAVE_MAC        0x0008
-#define        HAVE_MACTYPE    0x0010
-#define        HAVE_OPTIONS    0x8000
-
-#define        HAVE_IP         (HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP)
-static void
-show_prerequisites(int *flags, int want, int cmd)
-{
-       if ( (*flags & HAVE_IP) == HAVE_IP)
-               *flags |= HAVE_OPTIONS;
-
-       if ( (*flags & (HAVE_MAC|HAVE_MACTYPE|HAVE_OPTIONS)) == HAVE_MAC &&
-            cmd != O_MAC_TYPE) {
-               /*
-                * mac-type was optimized out by the compiler,
-                * restore it
-                */
-               printf(" any");
-               *flags |= HAVE_MACTYPE | HAVE_OPTIONS;
-               return;
-       }
-       if ( !(*flags & HAVE_OPTIONS)) {
-               if ( !(*flags & HAVE_PROTO) && (want & HAVE_PROTO))
-                       printf(" ip");
-               if ( !(*flags & HAVE_SRCIP) && (want & HAVE_SRCIP))
-                       printf(" from any");
-               if ( !(*flags & HAVE_DSTIP) && (want & HAVE_DSTIP))
-                       printf(" to any");
-       }
-       *flags |= want;
-}
-
-static void
-show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
-{
-       static int twidth = 0;
-       int l;
-       ipfw_insn *cmd;
-       char *comment = NULL;   /* ptr to comment if we have one */
-       int proto = 0;          /* default */
-       int flags = 0;  /* prerequisites */
-       ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */
-       int or_block = 0;       /* we are in an or block */
-       uint32_t set_disable;
-
-       bcopy(&rule->next_rule, &set_disable, sizeof(set_disable));
-
-       if (set_disable & (1 << rule->set)) { /* disabled */
-               if (!show_sets)
-                       return;
-               else
-                       printf("# DISABLED ");
-       }
-       printf("%05u ", rule->rulenum);
-
-       if (pcwidth>0 || bcwidth>0)
-               printf("%*llu %*llu ", pcwidth, align_uint64(&rule->pcnt),
-                   bcwidth, align_uint64(&rule->bcnt));
-
-       if (do_time == 2)
-               printf("%10u ", rule->timestamp);
-       else if (do_time == 1) {
-               char timestr[30];
-               time_t t = (time_t)0;
-
-               if (twidth == 0) {
-                       strlcpy(timestr, ctime(&t), sizeof(timestr));
-                       *strchr(timestr, '\n') = '\0';
-                       twidth = strlen(timestr);
-               }
-               if (rule->timestamp) {
-#if _FreeBSD_version < 500000 /* XXX check */
-#define        _long_to_time(x)        (time_t)(x)
-#endif
-                       t = _long_to_time(rule->timestamp);
-
-                       strlcpy(timestr, ctime(&t), sizeof(timestr));
-                       *strchr(timestr, '\n') = '\0';
-                       printf("%s ", timestr);
-               } else {
-                       printf("%*s", twidth, " ");
-               }
-       }
-
-       if (show_sets)
-               printf("set %d ", rule->set);
-
-       /*
-        * print the optional "match probability"
-        */
-       if (rule->cmd_len > 0) {
-               cmd = rule->cmd ;
-               if (cmd->opcode == O_PROB) {
-                       ipfw_insn_u32 *p = (ipfw_insn_u32 *)cmd;
-                       double d = 1.0 * p->d[0];
-
-                       d = (d / 0x7fffffff);
-                       printf("prob %f ", d);
-               }
-       }
-
-       /*
-        * first print actions
-        */
-        for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule);
-                       l > 0 ; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
-               switch(cmd->opcode) {
-               case O_CHECK_STATE:
-                       printf("check-state");
-                       flags = HAVE_IP; /* avoid printing anything else */
-                       break;
-
-               case O_ACCEPT:
-                       printf("allow");
-                       break;
-
-               case O_COUNT:
-                       printf("count");
-                       break;
-
-               case O_DENY:
-                       printf("deny");
-                       break;
-
-               case O_REJECT:
-                       if (cmd->arg1 == ICMP_REJECT_RST)
-                               printf("reset");
-                       else if (cmd->arg1 == ICMP_UNREACH_HOST)
-                               printf("reject");
-                       else
-                               print_reject_code(cmd->arg1);
-                       break;
-
-               case O_SKIPTO:
-                       printf("skipto %u", cmd->arg1);
-                       break;
-
-               case O_PIPE:
-                       printf("pipe %u", cmd->arg1);
-                       break;
-
-               case O_QUEUE:
-                       printf("queue %u", cmd->arg1);
-                       break;
-
-               case O_DIVERT:
-                       printf("divert %u", cmd->arg1);
-                       break;
-
-               case O_TEE:
-                       printf("tee %u", cmd->arg1);
-                       break;
-
-               case O_FORWARD_IP:
-                   {
-                       ipfw_insn_sa *s = (ipfw_insn_sa *)cmd;
-
-                       printf("fwd %s", inet_ntoa(s->sa.sin_addr));
-                       if (s->sa.sin_port)
-                               printf(",%d", s->sa.sin_port);
-                   }
-                       break;
-
-               case O_LOG: /* O_LOG is printed last */
-                       logptr = (ipfw_insn_log *)cmd;
-                       break;
-
-               default:
-                       printf("** unrecognized action %d len %d",
-                               cmd->opcode, cmd->len);
-               }
-       }
-       if (logptr) {
-               if (logptr->max_log > 0)
-                       printf(" log logamount %d", logptr->max_log);
-               else
-                       printf(" log");
-       }
-
-       /*
-        * then print the body.
-        */
-       if (rule->_pad & 1) {   /* empty rules before options */
-               if (!do_compact)
-                       printf(" ip from any to any");
-               flags |= HAVE_IP | HAVE_OPTIONS;
-       }
-
-        for (l = rule->act_ofs, cmd = rule->cmd ;
-                       l > 0 ; l -= F_LEN(cmd) , cmd += F_LEN(cmd)) {
-               /* useful alias */
-               ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
-
-               show_prerequisites(&flags, 0, cmd->opcode);
-
-               switch(cmd->opcode) {
-               case O_PROB:
-                       break;  /* done already */
-
-               case O_PROBE_STATE:
-                       break; /* no need to print anything here */
-
-               case O_MACADDR2: {
-                       ipfw_insn_mac *m = (ipfw_insn_mac *)cmd;
-
-                       if ((cmd->len & F_OR) && !or_block)
-                               printf(" {");
-                       if (cmd->len & F_NOT)
-                               printf(" not");
-                       printf(" MAC");
-                       flags |= HAVE_MAC;
-                       print_mac(m->addr, m->mask);
-                       print_mac(m->addr + 6, m->mask + 6);
-                       }
-                       break;
-
-               case O_MAC_TYPE:
-                       if ((cmd->len & F_OR) && !or_block)
-                               printf(" {");
-                       print_newports((ipfw_insn_u16 *)cmd, IPPROTO_ETHERTYPE,
-                               (flags & HAVE_OPTIONS) ? cmd->opcode : 0);
-                       flags |= HAVE_MAC | HAVE_MACTYPE | HAVE_OPTIONS;
-                       break;
-
-               case O_IP_SRC:
-               case O_IP_SRC_MASK:
-               case O_IP_SRC_ME:
-               case O_IP_SRC_SET:
-                       show_prerequisites(&flags, HAVE_PROTO, 0);
-                       if (!(flags & HAVE_SRCIP))
-                               printf(" from");
-                       if ((cmd->len & F_OR) && !or_block)
-                               printf(" {");
-                       print_ip((ipfw_insn_ip *)cmd,
-                               (flags & HAVE_OPTIONS) ? " src-ip" : "");
-                       flags |= HAVE_SRCIP;
-                       break;
-
-               case O_IP_DST:
-               case O_IP_DST_MASK:
-               case O_IP_DST_ME:
-               case O_IP_DST_SET:
-                       show_prerequisites(&flags, HAVE_PROTO|HAVE_SRCIP, 0);
-                       if (!(flags & HAVE_DSTIP))
-                               printf(" to");
-                       if ((cmd->len & F_OR) && !or_block)
-                               printf(" {");
-                       print_ip((ipfw_insn_ip *)cmd,
-                               (flags & HAVE_OPTIONS) ? " dst-ip" : "");
-                       flags |= HAVE_DSTIP;
-                       break;
-
-               case O_IP_DSTPORT:
-                       show_prerequisites(&flags, HAVE_IP, 0);
-               case O_IP_SRCPORT:
-                       show_prerequisites(&flags, HAVE_PROTO|HAVE_SRCIP, 0);
-                       if ((cmd->len & F_OR) && !or_block)
-                               printf(" {");
-                       print_newports((ipfw_insn_u16 *)cmd, proto,
-                               (flags & HAVE_OPTIONS) ? cmd->opcode : 0);
-                       break;
-
-               case O_PROTO: {
-                       struct protoent *pe;
-
-                       if ((cmd->len & F_OR) && !or_block)
-                               printf(" {");
-                       if (cmd->len & F_NOT)
-                               printf(" not");
-                       proto = cmd->arg1;
-                       pe = getprotobynumber(cmd->arg1);
-                       if (flags & HAVE_OPTIONS)
-                               printf(" proto");
-                       if (pe)
-                               printf(" %s", pe->p_name);
-                       else
-                               printf(" %u", cmd->arg1);
-                       }
-                       flags |= HAVE_PROTO;
-                       break;
-
-               default: /*options ... */
-                       show_prerequisites(&flags, HAVE_IP | HAVE_OPTIONS, 0);
-                       if ((cmd->len & F_OR) && !or_block)
-                               printf(" {");
-                       if (cmd->len & F_NOT && cmd->opcode != O_IN)
-                               printf(" not");
-                       switch(cmd->opcode) {
-                       case O_FRAG:
-                               printf(" frag");
-                               break;
-
-                       case O_IN:
-                               printf(cmd->len & F_NOT ? " out" : " in");
-                               break;
-
-                       case O_LAYER2:
-                               printf(" layer2");
-                               break;
-                       case O_XMIT:
-                       case O_RECV:
-                       case O_VIA: {
-                               char const *s;
-                               ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd;
-
-                               if (cmd->opcode == O_XMIT)
-                                       s = "xmit";
-                               else if (cmd->opcode == O_RECV)
-                                       s = "recv";
-                               else /* if (cmd->opcode == O_VIA) */
-                                       s = "via";
-                               if (cmdif->name[0] == '\0')
-                                       printf(" %s %s", s,
-                                           inet_ntoa(cmdif->p.ip));
-                               else if (cmdif->p.unit == -1)
-                                       printf(" %s %s*", s, cmdif->name);
-                               else
-                                       printf(" %s %s%d", s, cmdif->name,
-                                           cmdif->p.unit);
-                               }
-                               break;
-
-                       case O_IPID:
-                               if (F_LEN(cmd) == 1)
-                                   printf(" ipid %u", cmd->arg1 );
-                               else
-                                   print_newports((ipfw_insn_u16 *)cmd, 0,
-                                       O_IPID);
-                               break;
-
-                       case O_IPTTL:
-                               if (F_LEN(cmd) == 1)
-                                   printf(" ipttl %u", cmd->arg1 );
-                               else
-                                   print_newports((ipfw_insn_u16 *)cmd, 0,
-                                       O_IPTTL);
-                               break;
-
-                       case O_IPVER:
-                               printf(" ipver %u", cmd->arg1 );
-                               break;
-
-                       case O_IPPRECEDENCE:
-                               printf(" ipprecedence %u", (cmd->arg1) >> 5 );
-                               break;
-
-                       case O_IPLEN:
-                               if (F_LEN(cmd) == 1)
-                                   printf(" iplen %u", cmd->arg1 );
-                               else
-                                   print_newports((ipfw_insn_u16 *)cmd, 0,
-                                       O_IPLEN);
-                               break;
-
-                       case O_IPOPT:
-                               print_flags("ipoptions", cmd, f_ipopts);
-                               break;
-
-                       case O_IPTOS:
-                               print_flags("iptos", cmd, f_iptos);
-                               break;
-
-                       case O_ICMPTYPE:
-                               print_icmptypes((ipfw_insn_u32 *)cmd);
-                               break;
-
-                       case O_ESTAB:
-                               printf(" established");
-                               break;
-
-                       case O_TCPFLAGS:
-                               print_flags("tcpflags", cmd, f_tcpflags);
-                               break;
-
-                       case O_TCPOPTS:
-                               print_flags("tcpoptions", cmd, f_tcpopts);
-                               break;
-
-                       case O_TCPWIN:
-                               printf(" tcpwin %d", ntohs(cmd->arg1));
-                               break;
-
-                       case O_TCPACK:
-                               printf(" tcpack %d", ntohl(cmd32->d[0]));
-                               break;
-
-                       case O_TCPSEQ:
-                               printf(" tcpseq %d", ntohl(cmd32->d[0]));
-                               break;
-
-                       case O_UID:
-                           {
-                               struct passwd *pwd = getpwuid(cmd32->d[0]);
-
-                               if (pwd)
-                                       printf(" uid %s", pwd->pw_name);
-                               else
-                                       printf(" uid %u", cmd32->d[0]);
-                           }
-                               break;
-
-                       case O_GID:
-                           {
-                               struct group *grp = getgrgid(cmd32->d[0]);
-
-                               if (grp)
-                                       printf(" gid %s", grp->gr_name);
-                               else
-                                       printf(" gid %u", cmd32->d[0]);
-                           }
-                               break;
-
-                       case O_VERREVPATH:
-                               printf(" verrevpath");
-                               break;
-
-                       case O_IPSEC:
-                               printf(" ipsec");
-                               break;
-
-                       case O_NOP:
-                               comment = (char *)(cmd + 1);
-                               break;
-
-                       case O_KEEP_STATE:
-                               printf(" keep-state");
-                               break;
-
-                       case O_LIMIT:
-                           {
-                               struct _s_x *p = limit_masks;
-                               ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
-                               uint8_t x = c->limit_mask;
-                               char const *comma = " ";
-
-                               printf(" limit");
-                               for (; p->x != 0 ; p++)
-                                       if ((x & p->x) == p->x) {
-                                               x &= ~p->x;
-                                               printf("%s%s", comma, p->s);
-                                               comma = ",";
-                                       }
-                               printf(" %d", c->conn_limit);
-                           }
-                               break;
-
-                       default:
-                               printf(" [opcode %d len %d]",
-                                   cmd->opcode, cmd->len);
-                       }
-               }
-               if (cmd->len & F_OR) {
-                       printf(" or");
-                       or_block = 1;
-               } else if (or_block) {
-                       printf(" }");
-                       or_block = 0;
-               }
-       }
-       show_prerequisites(&flags, HAVE_IP, 0);
-       if (comment)
-               printf(" // %s", comment);
-       printf("\n");
-}
-
-static void
-show_dyn_ipfw(ipfw_dyn_rule *d, int pcwidth, int bcwidth)
-{
-       struct protoent *pe;
-       struct in_addr a;
-       uint16_t rulenum;
-
-       if (!do_expired) {
-               if (!d->expire && !(d->dyn_type == O_LIMIT_PARENT))
-                       return;
-       }
-       bcopy(&d->rule, &rulenum, sizeof(rulenum));
-       printf("%05d", rulenum);
-       if (pcwidth>0 || bcwidth>0)
-           printf(" %*llu %*llu (%ds)", pcwidth,
-               align_uint64(&d->pcnt), bcwidth,
-               align_uint64(&d->bcnt), d->expire);
-       switch (d->dyn_type) {
-       case O_LIMIT_PARENT:
-               printf(" PARENT %d", d->count);
-               break;
-       case O_LIMIT:
-               printf(" LIMIT");
-               break;
-       case O_KEEP_STATE: /* bidir, no mask */
-               printf(" STATE");
-               break;
-       }
-
-       if ((pe = getprotobynumber(d->id.proto)) != NULL)
-               printf(" %s", pe->p_name);
-       else
-               printf(" proto %u", d->id.proto);
-
-       a.s_addr = htonl(d->id.src_ip);
-       printf(" %s %d", inet_ntoa(a), d->id.src_port);
-
-       a.s_addr = htonl(d->id.dst_ip);
-       printf(" <-> %s %d", inet_ntoa(a), d->id.dst_port);
-       printf("\n");
-}
-
-static int
-sort_q(const void *pa, const void *pb)
-{
-       int rev = (do_sort < 0);
-       int field = rev ? -do_sort : do_sort;
-       long long res = 0;
-       const struct dn_flow_queue *a = pa;
-       const struct dn_flow_queue *b = pb;
-
-       switch (field) {
-       case 1: /* pkts */
-               res = a->len - b->len;
-               break;
-       case 2: /* bytes */
-               res = a->len_bytes - b->len_bytes;
-               break;
-
-       case 3: /* tot pkts */
-               res = a->tot_pkts - b->tot_pkts;
-               break;
-
-       case 4: /* tot bytes */
-               res = a->tot_bytes - b->tot_bytes;
-               break;
-       }
-       if (res < 0)
-               res = -1;
-       if (res > 0)
-               res = 1;
-       return (int)(rev ? res : -res);
-}
-
-static void
-list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q)
-{
-       int l;
-
-       printf("    mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
-           fs->flow_mask.proto,
-           fs->flow_mask.src_ip, fs->flow_mask.src_port,
-           fs->flow_mask.dst_ip, fs->flow_mask.dst_port);
-       if (fs->rq_elements == 0)
-               return;
-
-       printf("BKT Prot ___Source IP/port____ "
-           "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
-       if (do_sort != 0)
-               heapsort(q, fs->rq_elements, sizeof *q, sort_q);
-       for (l = 0; l < fs->rq_elements; l++) {
-               struct in_addr ina;
-               struct protoent *pe;
-
-               ina.s_addr = htonl(q[l].id.src_ip);
-               printf("%3d ", q[l].hash_slot);
-               pe = getprotobynumber(q[l].id.proto);
-               if (pe)
-                       printf("%-4s ", pe->p_name);
-               else
-                       printf("%4u ", q[l].id.proto);
-               printf("%15s/%-5d ",
-                   inet_ntoa(ina), q[l].id.src_port);
-               ina.s_addr = htonl(q[l].id.dst_ip);
-               printf("%15s/%-5d ",
-                   inet_ntoa(ina), q[l].id.dst_port);
-               printf("%4qu %8qu %2u %4u %3u\n",
-                   q[l].tot_pkts, q[l].tot_bytes,
-                   q[l].len, q[l].len_bytes, q[l].drops);
-               if (verbose)
-                       printf("   S %20qd  F %20qd\n",
-                           q[l].S, q[l].F);
-       }
-}
-
-static void
-print_flowset_parms(struct dn_flow_set *fs, char *prefix)
-{
-       int l;
-       char qs[30];
-       char plr[30];
-       char red[90];   /* Display RED parameters */
-
-       l = fs->qsize;
-       if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
-               if (l >= 8192)
-                       snprintf(qs, sizeof(qs), "%d KB", l / 1024);
-               else
-                       snprintf(qs, sizeof(qs), "%d B", l);
-       } else
-               snprintf(qs, sizeof(qs), "%3d sl.", l);
-       if (fs->plr)
-               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 */
-               snprintf(red, sizeof(red),
-                   "\n\t  %cRED w_q %f min_th %d max_th %d max_p %f",
-                   (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
-                   1.0 * fs->w_q / (double)(1 << SCALE_RED),
-                   SCALE_VAL(fs->min_th),
-                   SCALE_VAL(fs->max_th),
-                   1.0 * fs->max_p / (double)(1 << SCALE_RED));
-       else
-               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);
-}
-
-static void
-list_pipes(void *data, uint nbytes, int ac, char *av[])
-{
-       int rulenum;
-       void *next = data;
-       struct dn_pipe *p = (struct dn_pipe *) data;
-       struct dn_flow_set *fs;
-       struct dn_flow_queue *q;
-       int l;
-
-       if (ac > 0)
-               rulenum = strtoul(*av++, NULL, 10);
-       else
-               rulenum = 0;
-       for (; nbytes >= sizeof *p; p = (struct dn_pipe *)next) {
-               double b = p->bandwidth;
-               char buf[30];
-               char prefix[80];
-
-               if (p->next.sle_next != (struct dn_pipe *)DN_IS_PIPE)
-                       break;  /* done with pipes, now queues */
-
-               /*
-                * compute length, as pipe have variable size
-                */
-               l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
-               next = (char *)p + l;
-               nbytes -= l;
-
-               if (rulenum != 0 && rulenum != p->pipe_nr)
-                       continue;
-
-               /*
-                * Print rate (or clocking interface)
-                */
-               if (p->if_name[0] != '\0')
-                       snprintf(buf, sizeof(buf), "%s", p->if_name);
-               else if (b == 0)
-                       snprintf(buf, sizeof(buf), "unlimited");
-               else if (b >= 1000000)
-                       snprintf(buf, sizeof(buf), "%7.3f Mbit/s", b/1000000);
-               else if (b >= 1000)
-                       snprintf(buf, sizeof(buf), "%7.3f Kbit/s", b/1000);
-               else
-                       snprintf(buf, sizeof(buf), "%7.3f bit/s ", b);
-
-               snprintf(prefix, sizeof(prefix), "%05d: %s %4d ms ",
-                   p->pipe_nr, buf, p->delay);
-               print_flowset_parms(&(p->fs), prefix);
-               if (verbose)
-                       printf("   V %20qd\n", p->V >> MY_M);
-
-               q = (struct dn_flow_queue *)(p+1);
-               list_queues(&(p->fs), q);
-       }
-       for (fs = next; nbytes >= sizeof *fs; fs = next) {
-               char prefix[80];
-
-               if (fs->next.sle_next != (struct dn_flow_set *)DN_IS_QUEUE)
-                       break;
-               l = sizeof(*fs) + fs->rq_elements * sizeof(*q);
-               next = (char *)fs + l;
-               nbytes -= l;
-               q = (struct dn_flow_queue *)(fs+1);
-               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);
-       }
-}
-
-/*
- * This one handles all set-related commands
- *     ipfw set { show | enable | disable }
- *     ipfw set swap X Y
- *     ipfw set move X to Y
- *     ipfw set move rule X to Y
- */
-static void
-sets_handler(int ac, char *av[])
-{
-       uint32_t set_disable, masks[2];
-       int i, nbytes;
-       uint16_t rulenum;
-       uint8_t cmd, new_set;
-
-       ac--;
-       av++;
-
-       if (!ac)
-               errx(EX_USAGE, "set needs command");
-       if (!strncmp(*av, "show", strlen(*av)) ) {
-               void *data;
-               char const *msg;
-
-               nbytes = sizeof(struct ip_fw);
-               if ((data = calloc(1, nbytes)) == NULL)
-                       err(EX_OSERR, "calloc");
-               
-               if (do_cmd(IP_FW_GET, data, (uintptr_t)&nbytes) < 0)
-                       err(EX_OSERR, "getsockopt(IP_FW_GET)");
-               bcopy(&((struct ip_fw *)data)->next_rule,
-                       &set_disable, sizeof(set_disable));
-
-               for (i = 0, msg = "disable" ; i < RESVD_SET; i++)
-                       if ((set_disable & (1<<i))) {
-                               printf("%s %d", msg, i);
-                               msg = "";
-                       }
-               msg = (set_disable) ? " enable" : "enable";
-               for (i = 0; i < RESVD_SET; i++)
-                       if (!(set_disable & (1<<i))) {
-                               printf("%s %d", msg, i);
-                               msg = "";
-                       }
-               printf("\n");
-       } else if (!strncmp(*av, "swap", strlen(*av))) {
-               struct ip_fw    rule;
-               ac--; av++;
-               if (ac != 2)
-                       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", av[0]);
-               if (!isdigit(*(av[1])) || new_set > RESVD_SET)
-                       errx(EX_DATAERR, "invalid set number %s", av[1]);
-               masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
-               
-               bzero(&rule, sizeof(rule));
-               rule.set_masks[0] = masks[0];
-               
-               i = do_cmd(IP_FW_DEL, &rule, sizeof(rule));
-       } else if (!strncmp(*av, "move", strlen(*av))) {
-               struct ip_fw    rule;
-               ac--; av++;
-               if (ac && !strncmp(*av, "rule", strlen(*av))) {
-                       cmd = 2;
-                       ac--; av++;
-               } else
-                       cmd = 3;
-               if (ac != 3 || strncmp(av[1], "to", strlen(*av)))
-                       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", av[0]);
-               if (!isdigit(*(av[2])) || new_set > RESVD_SET)
-                       errx(EX_DATAERR, "invalid dest. set %s", av[1]);
-               masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
-               
-               bzero(&rule, sizeof(rule));
-               rule.set_masks[0] = masks[0];
-               
-               i = do_cmd(IP_FW_DEL, &rule, sizeof(rule));
-       } else if (!strncmp(*av, "disable", strlen(*av)) ||
-                  !strncmp(*av, "enable",  strlen(*av)) ) {
-               int which = !strncmp(*av, "enable",  strlen(*av)) ? 1 : 0;
-               struct ip_fw    rule;
-
-               ac--; av++;
-               masks[0] = masks[1] = 0;
-
-               while (ac) {
-                       if (isdigit(**av)) {
-                               i = atoi(*av);
-                               if (i < 0 || i > RESVD_SET)
-                                       errx(EX_DATAERR,
-                                           "invalid set number %d", i);
-                               masks[which] |= (1<<i);
-                       } else if (!strncmp(*av, "disable", strlen(*av)))
-                               which = 0;
-                       else if (!strncmp(*av, "enable", strlen(*av)))
-                               which = 1;
-                       else
-                               errx(EX_DATAERR,
-                                       "invalid set command %s", *av);
-                       av++; ac--;
-               }
-               if ( (masks[0] & masks[1]) != 0 )
-                       errx(EX_DATAERR,
-                           "cannot enable and disable the same set");
-               
-               bzero(&rule, sizeof(rule));
-               rule.set_masks[0] = masks[0];
-               rule.set_masks[1] = masks[1];
-               
-               i = do_cmd(IP_FW_DEL, &rule, sizeof(rule));
-               if (i)
-                       warn("set enable/disable: setsockopt(IP_FW_DEL)");
-       } else
-               errx(EX_USAGE, "invalid set command %s", *av);
-}
-
-static void
-sysctl_handler(int ac, char *av[], int which)
-{
-       ac--;
-       av++;
-
-       if (ac == 0) {
-               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));
-       } else if (strncmp(*av, "one_pass", strlen(*av)) == 0) {
-               sysctlbyname("net.inet.ip.fw.one_pass", NULL, 0,
-                   &which, sizeof(which));
-       } else if (strncmp(*av, "debug", strlen(*av)) == 0) {
-               sysctlbyname("net.inet.ip.fw.debug", NULL, 0,
-                   &which, sizeof(which));
-       } else if (strncmp(*av, "verbose", strlen(*av)) == 0) {
-               sysctlbyname("net.inet.ip.fw.verbose", NULL, 0,
-                   &which, sizeof(which));
-       } else if (strncmp(*av, "dyn_keepalive", strlen(*av)) == 0) {
-               sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0,
-                   &which, sizeof(which));
-       } else {
-               warnx("unrecognize enable/disable keyword: %s", *av);
-       }
-}
-
-static void
-list(int ac, char *av[], int show_counters)
-{
-       struct ip_fw *r;
-       ipfw_dyn_rule *dynrules, *d;
-
-#define NEXT(r)        ((struct ip_fw *)((char *)r + RULESIZE(r)))
-       char *lim;
-       void *data = NULL;
-       int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
-       int exitval = EX_OK;
-       int lac;
-       char **lav;
-       u_long rnum, last;
-       char *endptr;
-       int seen = 0;
-
-       const int ocmd = do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
-       int nalloc = 1024;      /* start somewhere... */
-
-       if (test_only) {
-               fprintf(stderr, "Testing only, list disabled\n");
-               return;
-       }
-
-       ac--;
-       av++;
-
-       /* get rules or pipes from kernel, resizing array as necessary */
-       nbytes = nalloc;
-
-       while (nbytes >= nalloc) {
-               nalloc = nalloc * 2 + 200;
-               nbytes = nalloc;
-               if ((data = realloc(data, nbytes)) == NULL)
-                       err(EX_OSERR, "realloc");
-               
-               if (do_cmd(ocmd, data, (uintptr_t)&nbytes) < 0)
-                       err(EX_OSERR, "getsockopt(IP_%s_GET)",
-                               do_pipe ? "DUMMYNET" : "FW");
-       }
-
-       if (do_pipe) {
-               list_pipes(data, nbytes, ac, av);
-               goto done;
-       }
-
-       /*
-        * Count static rules. They have variable size so we
-        * need to scan the list to count them.
-        */
-       for (nstat = 1, r = data, lim = (char *)data + nbytes;
-                   r->rulenum < 65535 && (char *)r < lim;
-                   ++nstat, r = NEXT(r) )
-               ; /* nothing */
-
-       /*
-        * Count dynamic rules. This is easier as they have
-        * fixed size.
-        */
-       r = NEXT(r);
-       dynrules = (ipfw_dyn_rule *)r ;
-       n = (char *)r - (char *)data;
-       ndyn = (nbytes - n) / sizeof *dynrules;
-
-       /* if showing stats, figure out column widths ahead of time */
-       bcwidth = pcwidth = 0;
-       if (show_counters) {
-               for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) {
-                       /* packet counter */
-                       width = snprintf(NULL, 0, "%llu",
-                           align_uint64(&r->pcnt));
-                       if (width > pcwidth)
-                               pcwidth = width;
-
-                       /* byte counter */
-                       width = snprintf(NULL, 0, "%llu",
-                           align_uint64(&r->bcnt));
-                       if (width > bcwidth)
-                               bcwidth = width;
-               }
-       }
-       if (do_dynamic && ndyn) {
-               for (n = 0, d = dynrules; n < ndyn; n++, d++) {
-                       width = snprintf(NULL, 0, "%llu",
-                           align_uint64(&d->pcnt));
-                       if (width > pcwidth)
-                               pcwidth = width;
-
-                       width = snprintf(NULL, 0, "%llu",
-                           align_uint64(&d->bcnt));
-                       if (width > bcwidth)
-                               bcwidth = width;
-               }
-       }
-       /* if no rule numbers were specified, list all rules */
-       if (ac == 0) {
-               for (n = 0, r = data; n < nstat; n++, r = NEXT(r) )
-                       show_ipfw(r, pcwidth, bcwidth);
-
-               if (do_dynamic && ndyn) {
-                       printf("## Dynamic rules (%d):\n", ndyn);
-                       for (n = 0, d = dynrules; n < ndyn; n++, d++)
-                               show_dyn_ipfw(d, pcwidth, bcwidth);
-               }
-               goto done;
-       }
-
-       /* display specific rules requested on command line */
-
-       for (lac = ac, lav = av; lac != 0; lac--) {
-               /* convert command line rule # */
-               last = rnum = strtoul(*lav++, &endptr, 10);
-               if (*endptr == '-')
-                       last = strtoul(endptr+1, &endptr, 10);
-               if (*endptr) {
-                       exitval = EX_USAGE;
-                       warnx("invalid rule number: %s", *(lav - 1));
-                       continue;
-               }
-               for (n = seen = 0, r = data; n < nstat; n++, r = NEXT(r) ) {
-                       if (r->rulenum > last)
-                               break;
-                       if (r->rulenum >= rnum && r->rulenum <= last) {
-                               show_ipfw(r, pcwidth, bcwidth);
-                               seen = 1;
-                       }
-               }
-               if (!seen) {
-                       /* give precedence to other error(s) */
-                       if (exitval == EX_OK)
-                               exitval = EX_UNAVAILABLE;
-                       warnx("rule %lu does not exist", rnum);
-               }
-       }
-
-       if (do_dynamic && ndyn) {
-               printf("## Dynamic rules:\n");
-               for (lac = ac, lav = av; lac != 0; lac--) {
-                       rnum = strtoul(*lav++, &endptr, 10);
-                       if (*endptr == '-')
-                               last = strtoul(endptr+1, &endptr, 10);
-                       if (*endptr)
-                               /* already warned */
-                               continue;
-                       for (n = 0, d = dynrules; n < ndyn; n++, d++) {
-                               uint16_t rulenum;
-
-                               bcopy(&d->rule, &rulenum, sizeof(rulenum));
-                               if (rulenum > rnum)
-                                       break;
-                               if (r->rulenum >= rnum && r->rulenum <= last)
-                                       show_dyn_ipfw(d, pcwidth, bcwidth);
-                       }
-               }
-       }
-
-       ac = 0;
-
-done:
-       free(data);
-
-       if (exitval != EX_OK)
-               exit(exitval);
-#undef NEXT
-}
-
-static void
-show_usage(void)
-{
-       fprintf(stderr, "usage: ipfw [options]\n"
-"do \"ipfw -h\" or see ipfw manpage for details\n"
-);
-       exit(EX_USAGE);
-}
-
-static void
-help(void)
-{
-       fprintf(stderr,
-"ipfw syntax summary (but please do read the ipfw(8) manpage):\n"
-"ipfw [-acdeftTnNpqS] <command> where <command> is one of:\n"
-"add [num] [set N] [prob x] RULE-BODY\n"
-"{pipe|queue} N config PIPE-BODY\n"
-"[pipe|queue] {zero|delete|show} [N{,N}]\n"
-"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
-"\n"
-"RULE-BODY:    check-state [LOG] | ACTION [LOG] ADDR [OPTION_LIST]\n"
-"ACTION:       check-state | allow | count | deny | reject | skipto N |\n"
-"              {divert|tee} PORT | forward ADDR | pipe N | queue N\n"
-"ADDR:         [ MAC dst src ether_type ] \n"
-"              [ from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
-"IPADDR:       [not] { any | me | ip/bits{x,y,z} | IPLIST }\n"
-"IPLIST:       { ip | ip/bits | ip:mask }[,IPLIST]\n"
-"OPTION_LIST:  OPTION [OPTION_LIST]\n"
-"OPTION:       bridged | {dst-ip|src-ip} ADDR | {dst-port|src-port} LIST |\n"
-"      estab | frag | {gid|uid} N | icmptypes LIST | in | out | ipid LIST |\n"
-"      iplen LIST | ipoptions SPEC | ipprecedence | ipsec | iptos SPEC |\n"
-"      ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
-"      mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
-"      setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
-"      verrevpath\n"
-);
-exit(0);
-}
-
-
-static int
-lookup_host (char *host, struct in_addr *ipaddr)
-{
-       struct hostent *he;
-
-       if (!inet_aton(host, ipaddr)) {
-               if ((he = gethostbyname(host)) == NULL)
-                       return(-1);
-               *ipaddr = *(struct in_addr *)he->h_addr_list[0];
-       }
-       return(0);
-}
-
-/*
- * fills the addr and mask fields in the instruction as appropriate from av.
- * Update length as appropriate.
- * The following formats are allowed:
- *     any     matches any IP. Actually returns an empty instruction.
- *     me      returns O_IP_*_ME
- *     1.2.3.4         single IP address
- *     1.2.3.4:5.6.7.8 address:mask
- *     1.2.3.4/24      address/mask
- *     1.2.3.4/26{1,6,5,4,23}  set of addresses in a subnet
- * We can have multiple comma-separated address/mask entries.
- */
-static void
-fill_ip(ipfw_insn_ip *cmd, char *av)
-{
-       int len = 0;
-       uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
-
-       cmd->o.len &= ~F_LEN_MASK;      /* zero len */
-
-       if (!strncmp(av, "any", strlen(av)))
-               return;
-
-       if (!strncmp(av, "me", strlen(av))) {
-               cmd->o.len |= F_INSN_SIZE(ipfw_insn);
-               return;
-       }
-
-    while (av) {
-       /*
-        * After the address we can have '/' or ':' indicating a mask,
-        * ',' indicating another address follows, '{' indicating a
-        * set of addresses of unspecified size.
-        */
-       char *p = strpbrk(av, "/:,{");
-       int masklen;
-       char md;
-
-       if (p) {
-               md = *p;
-               *p++ = '\0';
-       } else
-               md = '\0';
-
-       if (lookup_host(av, (struct in_addr *)&d[0]) != 0)
-               errx(EX_NOHOST, "hostname ``%s'' unknown", av);
-       switch (md) {
-       case ':':
-               if (!inet_aton(p, (struct in_addr *)&d[1]))
-                       errx(EX_DATAERR, "bad netmask ``%s''", p);
-               break;
-       case '/':
-               masklen = atoi(p);
-               if (masklen == 0)
-                       d[1] = htonl(0);        /* mask */
-               else if (masklen > 32)
-                       errx(EX_DATAERR, "bad width ``%s''", p);
-               else
-                       d[1] = htonl(~0 << (32 - masklen));
-               break;
-       case '{':       /* no mask, assume /24 and put back the '{' */
-               d[1] = htonl(~0 << (32 - 24));
-               *(--p) = md;
-               break;
-
-       case ',':       /* single address plus continuation */
-               *(--p) = md;
-               /* FALLTHROUGH */
-       case 0:         /* initialization value */
-       default:
-               d[1] = htonl(~0);       /* force /32 */
-               break;
-       }
-       d[0] &= d[1];           /* mask base address with mask */
-       /* find next separator */
-       if (p)
-               p = strpbrk(p, ",{");
-       if (p && *p == '{') {
-               /*
-                * We have a set of addresses. They are stored as follows:
-                *   arg1       is the set size (powers of 2, 2..256)
-                *   addr       is the base address IN HOST FORMAT
-                *   mask..     is an array of arg1 bits (rounded up to
-                *              the next multiple of 32) with bits set
-                *              for each host in the map.
-                */
-               uint32_t *map = (uint32_t *)&cmd->mask;
-               int low, high;
-               int i = contigmask((uint8_t *)&(d[1]), 32);
-
-               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", 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 */
-               cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + (cmd->o.arg1+31)/32;
-               for (i = 0; i < (cmd->o.arg1+31)/32 ; i++)
-                       map[i] = 0;     /* clear map */
-
-               av = p + 1;
-               low = d[0] & 0xff;
-               high = low + cmd->o.arg1 - 1;
-               /*
-                * Here, i stores the previous value when we specify a range
-                * of addresses within a mask, e.g. 45-63. i = -1 means we
-                * have no previous value.
-                */
-               i = -1; /* previous value in a range */
-               while (isdigit(*av)) {
-                       char *s;
-                       int a = strtol(av, &s, 0);
-
-                       if (s == av) { /* no parameter */
-                           if (*av != '}')
-                               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]",
-                               a, low, high);
-                       a -= low;
-                       if (i == -1)    /* no previous in range */
-                           i = a;
-                       else {          /* check that range is valid */
-                           if (i > a)
-                               errx(EX_DATAERR, "invalid range %d-%d",
-                                       i+low, a+low);
-                           if (*s == '-')
-                               errx(EX_DATAERR, "double '-' in range");
-                       }
-                       for (; i <= a; i++)
-                           map[i/32] |= 1<<(i & 31);
-                       i = -1;
-                       if (*s == '-')
-                           i = a;
-                       else if (*s == '}')
-                           break;
-                       av = s+1;
-               }
-               return;
-       }
-       av = p;
-       if (av)                 /* then *av must be a ',' */
-               av++;
-
-       /* Check this entry */
-       if (d[1] == 0) { /* "any", specified as x.x.x.x/0 */
-               /*
-                * 'any' turns the entire list into a NOP.
-                * 'not any' never matches, so it is removed from the
-                * list unless it is the only item, in which case we
-                * report an error.
-                */
-               if (cmd->o.len & F_NOT) {       /* "not any" never matches */
-                       if (av == NULL && len == 0) /* only this entry */
-                               errx(EX_DATAERR, "not any never matches");
-               }
-               /* else do nothing and return */
-               return;
-       }
-       /* A single IP can be stored in an optimized format */
-       if (d[1] == IP_MASK_ALL && av == NULL && len == 0) {
-               cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
-               return;
-       }
-       len += 2;       /* two words... */
-       d += 2;
-    } /* end while */
-    cmd->o.len |= len+1;
-}
-
-
-/*
- * helper function to process a set of flags and set bits in the
- * appropriate masks.
- */
-static void
-fill_flags(ipfw_insn *cmd, enum ipfw_opcodes opcode,
-       struct _s_x *flags, char *p)
-{
-       uint8_t set=0, clear=0;
-
-       while (p && *p) {
-               char *q;        /* points to the separator */
-               int val;
-               uint8_t *which; /* mask we are working on */
-
-               if (*p == '!') {
-                       p++;
-                       which = &clear;
-               } else
-                       which = &set;
-               q = strchr(p, ',');
-               if (q)
-                       *q++ = '\0';
-               val = match_token(flags, p);
-               if (val <= 0)
-                       errx(EX_DATAERR, "invalid flag %s", p);
-               *which |= (uint8_t)val;
-               p = q;
-       }
-        cmd->opcode = opcode;
-        cmd->len =  (cmd->len & (F_NOT | F_OR)) | 1;
-        cmd->arg1 = (set & 0xff) | ( (clear & 0xff) << 8);
-}
-
-
-static void
-delete(int ac, char *av[])
-{
-       struct ip_fw rule;
-       struct dn_pipe p;
-       int i;
-       int exitval = EX_OK;
-       int do_set = 0;
-
-       memset(&p, 0, sizeof p);
-
-       av++; ac--;
-       if (ac > 0 && !strncmp(*av, "set", strlen(*av))) {
-               do_set = 1;     /* delete set */
-               ac--; av++;
-       }
-
-       /* Rule number */
-       while (ac && isdigit(**av)) {
-               i = atoi(*av); av++; ac--;
-               if (do_pipe) {
-                       if (do_pipe == 1)
-                               p.pipe_nr = i;
-                       else
-                               p.fs.fs_nr = i;
-                       i = do_cmd(IP_DUMMYNET_DEL, &p, sizeof p);
-                       if (i) {
-                               exitval = 1;
-                               warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
-                                   do_pipe == 1 ? p.pipe_nr : p.fs.fs_nr);
-                       }
-               } else {
-                       bzero(&rule, sizeof(rule));
-                       if (do_set) {
-                               rule.set_masks[0] = (i & 0xffff) | (do_set << 24);
-                       }
-                       else {
-                               rule.rulenum = i;
-                       }
-                       i = do_cmd(IP_FW_DEL, &rule, sizeof(rule));
-                       if (i) {
-                               exitval = EX_UNAVAILABLE;
-                               warn("rule %u: setsockopt(IP_FW_DEL)",
-                                   rule.rulenum);
-                       }
-               }
-       }
-       if (exitval != EX_OK)
-               exit(exitval);
-}
-
-
-/*
- * fill the interface structure. We do not check the name as we can
- * create interfaces dynamically, so checking them at insert time
- * makes relatively little sense.
- * A '*' following the name means any unit.
- */
-static void
-fill_iface(ipfw_insn_if *cmd, char *arg)
-{
-       cmd->name[0] = '\0';
-       cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
-
-       /* Parse the interface or address */
-       if (!strcmp(arg, "any"))
-               cmd->o.len = 0;         /* effectively ignore this command */
-       else if (!isdigit(*arg)) {
-               char *q;
-
-               strncpy(cmd->name, arg, sizeof(cmd->name));
-               cmd->name[sizeof(cmd->name) - 1] = '\0';
-               /* find first digit or wildcard */
-               for (q = cmd->name; *q && !isdigit(*q) && *q != '*'; q++)
-                       continue;
-               cmd->p.unit = (*q == '*') ? -1 : atoi(q);
-               *q = '\0';
-       } else if (!inet_aton(arg, &cmd->p.ip))
-               errx(EX_DATAERR, "bad ip address ``%s''", arg);
-}
-
-/*
- * the following macro returns an error message if we run out of
- * arguments.
- */
-#define        NEED1(msg)      {if (!ac) errx(EX_USAGE, msg);}
-
-static void
-config_pipe(int ac, char **av)
-{
-       struct dn_pipe p;
-       int i;
-       char *end;
-       uint32_t a;
-       void *par = NULL;
-
-       memset(&p, 0, sizeof p);
-
-       av++; ac--;
-       /* Pipe number */
-       if (ac && isdigit(**av)) {
-               i = atoi(*av); av++; ac--;
-               if (do_pipe == 1)
-                       p.pipe_nr = i;
-               else
-                       p.fs.fs_nr = i;
-       }
-       while (ac > 0) {
-               double d;
-               int tok = match_token(dummynet_params, *av);
-               ac--; av++;
-
-               switch(tok) {
-               case TOK_NOERROR:
-                       p.fs.flags_fs |= DN_NOERROR;
-                       break;
-
-               case TOK_PLR:
-                       NEED1("plr needs argument 0..1\n");
-                       d = strtod(av[0], NULL);
-                       if (d > 1)
-                               d = 1;
-                       else if (d < 0)
-                               d = 0;
-                       p.fs.plr = (int)(d*0x7fffffff);
-                       ac--; av++;
-                       break;
-
-               case TOK_QUEUE:
-                       NEED1("queue needs queue size\n");
-                       end = NULL;
-                       p.fs.qsize = strtoul(av[0], &end, 0);
-                       if (*end == 'K' || *end == 'k') {
-                               p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
-                               p.fs.qsize *= 1024;
-                       } else if (*end == 'B' || !strncmp(end, "by", 2)) {
-                               p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
-                       }
-                       ac--; av++;
-                       break;
-
-               case TOK_BUCKETS:
-                       NEED1("buckets needs argument\n");
-                       p.fs.rq_size = strtoul(av[0], NULL, 0);
-                       ac--; av++;
-                       break;
-
-               case TOK_MASK:
-                       NEED1("mask needs mask specifier\n");
-                       /*
-                        * per-flow queue, mask is dst_ip, dst_port,
-                        * src_ip, src_port, proto measured in bits
-                        */
-                       par = NULL;
-
-                       p.fs.flow_mask.dst_ip = 0;
-                       p.fs.flow_mask.src_ip = 0;
-                       p.fs.flow_mask.dst_port = 0;
-                       p.fs.flow_mask.src_port = 0;
-                       p.fs.flow_mask.proto = 0;
-                       end = NULL;
-
-                       while (ac >= 1) {
-                           uint32_t *p32 = NULL;
-                           uint16_t *p16 = NULL;
-
-                           tok = match_token(dummynet_params, *av);
-                           ac--; av++;
-                           switch(tok) {
-                           case TOK_ALL:
-                                   /*
-                                    * special case, all bits significant
-                                    */
-                                   p.fs.flow_mask.dst_ip = ~0;
-                                   p.fs.flow_mask.src_ip = ~0;
-                                   p.fs.flow_mask.dst_port = ~0;
-                                   p.fs.flow_mask.src_port = ~0;
-                                   p.fs.flow_mask.proto = ~0;
-                                   p.fs.flags_fs |= DN_HAVE_FLOW_MASK;
-                                   goto end_mask;
-
-                           case TOK_DSTIP:
-                                   p32 = &p.fs.flow_mask.dst_ip;
-                                   break;
-
-                           case TOK_SRCIP:
-                                   p32 = &p.fs.flow_mask.src_ip;
-                                   break;
-
-                           case TOK_DSTPORT:
-                                   p16 = &p.fs.flow_mask.dst_port;
-                                   break;
-
-                           case TOK_SRCPORT:
-                                   p16 = &p.fs.flow_mask.src_port;
-                                   break;
-
-                           case TOK_PROTO:
-                                   break;
-
-                           default:
-                                   ac++; av--; /* backtrack */
-                                   goto end_mask;
-                           }
-                           if (ac < 1)
-                                   errx(EX_USAGE, "mask: value missing");
-                           if (*av[0] == '/') {
-                                   a = strtoul(av[0]+1, &end, 0);
-                                   a = (a == 32) ? ~0 : (1 << a) - 1;
-                           } else
-                                   a = strtoul(av[0], &end, 0);
-                           if (p32 != NULL)
-                                   *p32 = a;
-                           else if (p16 != NULL) {
-                                   if (a > 65535)
-                                           errx(EX_DATAERR,
-                                               "mask: must be 16 bit");
-                                   *p16 = (uint16_t)a;
-                           } else {
-                                   if (a > 255)
-                                           errx(EX_DATAERR,
-                                               "mask: must be 8 bit");
-                                   p.fs.flow_mask.proto = (uint8_t)a;
-                           }
-                           if (a != 0)
-                                   p.fs.flags_fs |= DN_HAVE_FLOW_MASK;
-                           ac--; av++;
-                       } /* end while, config masks */
-end_mask:
-                       break;
-
-               case TOK_RED:
-               case TOK_GRED:
-                       NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
-                       p.fs.flags_fs |= DN_IS_RED;
-                       if (tok == TOK_GRED)
-                               p.fs.flags_fs |= DN_IS_GENTLE_RED;
-                       /*
-                        * the format for parameters is w_q/min_th/max_th/max_p
-                        */
-                       if ((end = strsep(&av[0], "/"))) {
-                           double w_q = strtod(end, NULL);
-                           if (w_q > 1 || w_q <= 0)
-                               errx(EX_DATAERR, "0 < w_q <= 1");
-                           p.fs.w_q = (int) (w_q * (1 << SCALE_RED));
-                       }
-                       if ((end = strsep(&av[0], "/"))) {
-                           p.fs.min_th = strtoul(end, &end, 0);
-                           if (*end == 'K' || *end == 'k')
-                               p.fs.min_th *= 1024;
-                       }
-                       if ((end = strsep(&av[0], "/"))) {
-                           p.fs.max_th = strtoul(end, &end, 0);
-                           if (*end == 'K' || *end == 'k')
-                               p.fs.max_th *= 1024;
-                       }
-                       if ((end = strsep(&av[0], "/"))) {
-                           double max_p = strtod(end, NULL);
-                           if (max_p > 1 || max_p <= 0)
-                               errx(EX_DATAERR, "0 < max_p <= 1");
-                           p.fs.max_p = (int)(max_p * (1 << SCALE_RED));
-                       }
-                       ac--; av++;
-                       break;
-
-               case TOK_DROPTAIL:
-                       p.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
-                       break;
-
-               case TOK_BW:
-                       NEED1("bw needs bandwidth or interface\n");
-                       if (do_pipe != 1)
-                           errx(EX_DATAERR, "bandwidth only valid for pipes");
-                       /*
-                        * set clocking interface or bandwidth value
-                        */
-                       if (av[0][0] >= 'a' && av[0][0] <= 'z') {
-                           int l = sizeof(p.if_name)-1;
-                           /* interface name */
-                           strncpy(p.if_name, av[0], l);
-                           p.if_name[l] = '\0';
-                           p.bandwidth = 0;
-                       } else {
-                           p.if_name[0] = '\0';
-                           p.bandwidth = strtoul(av[0], &end, 0);
-                           if (*end == 'K' || *end == 'k') {
-                               end++;
-                               p.bandwidth *= 1000;
-                           } else if (*end == 'M') {
-                               end++;
-                               p.bandwidth *= 1000000;
-                           }
-                           if (*end == 'B' || !strncmp(end, "by", 2))
-                               p.bandwidth *= 8;
-                           if (p.bandwidth < 0)
-                               errx(EX_DATAERR, "bandwidth too large");
-                       }
-                       ac--; av++;
-                       break;
-
-               case TOK_DELAY:
-                       if (do_pipe != 1)
-                               errx(EX_DATAERR, "delay only valid for pipes");
-                       NEED1("delay needs argument 0..10000ms\n");
-                       p.delay = strtoul(av[0], NULL, 0);
-                       ac--; av++;
-                       break;
-
-               case TOK_WEIGHT:
-                       if (do_pipe == 1)
-                               errx(EX_DATAERR,"weight only valid for queues");
-                       NEED1("weight needs argument 0..100\n");
-                       p.fs.weight = strtoul(av[0], &end, 0);
-                       ac--; av++;
-                       break;
-
-               case TOK_PIPE:
-                       if (do_pipe == 1)
-                               errx(EX_DATAERR,"pipe only valid for queues");
-                       NEED1("pipe needs pipe_number\n");
-                       p.fs.parent_nr = strtoul(av[0], &end, 0);
-                       ac--; av++;
-                       break;
-
-               default:
-                       errx(EX_DATAERR, "unrecognised option ``%s''", *(--av));
-               }
-       }
-       if (do_pipe == 1) {
-               if (p.pipe_nr == 0)
-                       errx(EX_DATAERR, "pipe_nr must be > 0");
-               if (p.delay > 10000)
-                       errx(EX_DATAERR, "delay must be < 10000");
-       } else { /* do_pipe == 2, queue */
-               if (p.fs.parent_nr == 0)
-                       errx(EX_DATAERR, "pipe must be > 0");
-               if (p.fs.weight >100)
-                       errx(EX_DATAERR, "weight must be <= 100");
-       }
-       if (p.fs.flags_fs & DN_QSIZE_IS_BYTES) {
-               if (p.fs.qsize > 1024*1024)
-                       errx(EX_DATAERR, "queue size must be < 1MB");
-       } else {
-               if (p.fs.qsize > 100)
-                       errx(EX_DATAERR, "2 <= queue size <= 100");
-       }
-       if (p.fs.flags_fs & DN_IS_RED) {
-               size_t len;
-               int lookup_depth, avg_pkt_size;
-               double s, idle, weight, w_q;
-               struct clockinfo ck;
-               int t;
-
-               if (p.fs.min_th >= p.fs.max_th)
-                   errx(EX_DATAERR, "min_th %d must be < than max_th %d",
-                       p.fs.min_th, p.fs.max_th);
-               if (p.fs.max_th == 0)
-                   errx(EX_DATAERR, "max_th must be > 0");
-
-               len = sizeof(int);
-               if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
-                       &lookup_depth, &len, NULL, 0) == -1)
-
-                   errx(1, "sysctlbyname(\"%s\")",
-                       "net.inet.ip.dummynet.red_lookup_depth");
-               if (lookup_depth == 0)
-                   errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
-                       " must be greater than zero");
-
-               len = sizeof(int);
-               if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
-                       &avg_pkt_size, &len, NULL, 0) == -1)
-
-                   errx(1, "sysctlbyname(\"%s\")",
-                       "net.inet.ip.dummynet.red_avg_pkt_size");
-               if (avg_pkt_size == 0)
-                       errx(EX_DATAERR,
-                           "net.inet.ip.dummynet.red_avg_pkt_size must"
-                           " be greater than zero");
-
-               len = sizeof(struct clockinfo);
-               if (sysctlbyname("kern.clockrate", &ck, &len, NULL, 0) == -1)
-                       errx(1, "sysctlbyname(\"%s\")", "kern.clockrate");
-
-               /*
-                * Ticks needed for sending a medium-sized packet.
-                * Unfortunately, when we are configuring a WF2Q+ queue, we
-                * do not have bandwidth information, because that is stored
-                * in the parent pipe, and also we have multiple queues
-                * competing for it. So we set s=0, which is not very
-                * correct. But on the other hand, why do we want RED with
-                * WF2Q+ ?
-                */
-               if (p.bandwidth==0) /* this is a WF2Q+ queue */
-                       s = 0;
-               else
-                       s = ck.hz * avg_pkt_size * 8 / p.bandwidth;
-
-               /*
-                * max idle time (in ticks) before avg queue size becomes 0.
-                * NOTA:  (3/w_q) is approx the value x so that
-                * (1-w_q)^x < 10^-3.
-                */
-               w_q = ((double)p.fs.w_q) / (1 << SCALE_RED);
-               idle = s * 3. / w_q;
-               p.fs.lookup_step = (int)idle / lookup_depth;
-               if (!p.fs.lookup_step)
-                       p.fs.lookup_step = 1;
-               weight = 1 - w_q;
-               for (t = p.fs.lookup_step; t > 0; --t)
-                       weight *= weight;
-               p.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
-       }
-       i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, sizeof p);
-       if (i)
-               err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
-}
-
-static void
-get_mac_addr_mask(char *p, uint8_t *addr, uint8_t *mask)
-{
-       int i, l;
-
-       for (i=0; i<6; i++)
-               addr[i] = mask[i] = 0;
-       if (!strcmp(p, "any"))
-               return;
-
-       for (i=0; *p && i<6;i++, p++) {
-               addr[i] = strtol(p, &p, 16);
-               if (*p != ':') /* we start with the mask */
-                       break;
-       }
-       if (*p == '/') { /* mask len */
-               l = strtol(p+1, &p, 0);
-               for (i=0; l>0; l -=8, i++)
-                       mask[i] = (l >=8) ? 0xff : (~0) << (8-l);
-       } else if (*p == '&') { /* mask */
-               for (i=0, p++; *p && i<6;i++, p++) {
-                       mask[i] = strtol(p, &p, 16);
-                       if (*p != ':')
-                               break;
-               }
-       } else if (*p == '\0') {
-               for (i=0; i<6; i++)
-                       mask[i] = 0xff;
-       }
-       for (i=0; i<6; i++)
-               addr[i] &= mask[i];
-}
-
-/*
- * helper function, updates the pointer to cmd with the length
- * of the current command, and also cleans up the first word of
- * the new command in case it has been clobbered before.
- */
-static ipfw_insn *
-next_cmd(ipfw_insn *cmd)
-{
-       cmd += F_LEN(cmd);
-       bzero(cmd, sizeof(*cmd));
-       return cmd;
-}
-
-/*
- * Takes arguments and copies them into a comment
- */
-static void
-fill_comment(ipfw_insn *cmd, int ac, char **av)
-{
-       int i, l;
-       char *p = (char *)(cmd + 1);
-
-       cmd->opcode = O_NOP;
-       cmd->len =  (cmd->len & (F_NOT | F_OR));
-
-       /* Compute length of comment string. */
-       for (i = 0, l = 0; i < ac; i++)
-               l += strlen(av[i]) + 1;
-       if (l == 0)
-               return;
-       if (l > 84)
-               errx(EX_DATAERR,
-                   "comment too long (max 80 chars)");
-       l = 1 + (l+3)/4;
-       cmd->len =  (cmd->len & (F_NOT | F_OR)) | l;
-       for (i = 0; i < ac; i++) {
-               /* length being checked above (max 80 chars) */
-               strlcpy(p, av[i], 80);
-               p += strlen(av[i]);
-               *p++ = ' ';
-       }
-       *(--p) = '\0';
-}
-
-/*
- * A function to fill simple commands of size 1.
- * Existing flags are preserved.
- */
-static void
-fill_cmd(ipfw_insn *cmd, enum ipfw_opcodes opcode, int flags, uint16_t arg)
-{
-       cmd->opcode = opcode;
-       cmd->len =  ((cmd->len | flags) & (F_NOT | F_OR)) | 1;
-       cmd->arg1 = arg;
-}
-
-/*
- * Fetch and add the MAC address and type, with masks. This generates one or
- * two microinstructions, and returns the pointer to the last one.
- */
-static ipfw_insn *
-add_mac(ipfw_insn *cmd, int ac, char *av[])
-{
-       ipfw_insn_mac *mac;
-
-       if (ac < 2)
-               errx(EX_DATAERR, "MAC dst src");
-
-       cmd->opcode = O_MACADDR2;
-       cmd->len = (cmd->len & (F_NOT | F_OR)) | F_INSN_SIZE(ipfw_insn_mac);
-
-       mac = (ipfw_insn_mac *)cmd;
-       get_mac_addr_mask(av[0], mac->addr, mac->mask); /* dst */
-       get_mac_addr_mask(av[1], &(mac->addr[6]), &(mac->mask[6])); /* src */
-       return cmd;
-}
-
-static ipfw_insn *
-add_mactype(ipfw_insn *cmd, int ac, char *av)
-{
-       if (ac < 1)
-               errx(EX_DATAERR, "missing MAC type");
-       if (strcmp(av, "any") != 0) { /* we have a non-null type */
-               fill_newports((ipfw_insn_u16 *)cmd, av, IPPROTO_ETHERTYPE);
-               cmd->opcode = O_MAC_TYPE;
-               return cmd;
-       } else
-               return NULL;
-}
-
-static ipfw_insn *
-add_proto(ipfw_insn *cmd, char *av)
-{
-       struct protoent *pe;
-       u_char proto = 0;
-
-       if (!strncmp(av, "all", strlen(av)))
-               ; /* same as "ip" */
-       else if ((proto = atoi(av)) > 0)
-               ; /* all done! */
-       else if ((pe = getprotobyname(av)) != NULL)
-               proto = pe->p_proto;
-       else
-               return NULL;
-       if (proto != IPPROTO_IP)
-               fill_cmd(cmd, O_PROTO, 0, proto);
-       return cmd;
-}
-
-static ipfw_insn *
-add_srcip(ipfw_insn *cmd, char *av)
-{
-       fill_ip((ipfw_insn_ip *)cmd, av);
-       if (cmd->opcode == O_IP_DST_SET)                        /* set */
-               cmd->opcode = O_IP_SRC_SET;
-       else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn))          /* me */
-               cmd->opcode = O_IP_SRC_ME;
-       else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32))      /* one IP */
-               cmd->opcode = O_IP_SRC;
-       else                                                    /* addr/mask */
-               cmd->opcode = O_IP_SRC_MASK;
-       return cmd;
-}
-
-static ipfw_insn *
-add_dstip(ipfw_insn *cmd, char *av)
-{
-       fill_ip((ipfw_insn_ip *)cmd, av);
-       if (cmd->opcode == O_IP_DST_SET)                        /* set */
-               ;
-       else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn))          /* me */
-               cmd->opcode = O_IP_DST_ME;
-       else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32))      /* one IP */
-               cmd->opcode = O_IP_DST;
-       else                                                    /* addr/mask */
-               cmd->opcode = O_IP_DST_MASK;
-       return cmd;
-}
-
-static ipfw_insn *
-add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode)
-{
-       if (!strncmp(av, "any", strlen(av))) {
-               return NULL;
-       } else if (fill_newports((ipfw_insn_u16 *)cmd, av, proto)) {
-               /* XXX todo: check that we have a protocol with ports */
-               cmd->opcode = opcode;
-               return cmd;
-       }
-       return NULL;
-}
-
-/*
- * Parse arguments and assemble the microinstructions which make up a rule.
- * Rules are added into the 'rulebuf' and then copied in the correct order
- * into the actual rule.
- *
- * The syntax for a rule starts with the action, followed by an
- * optional log action, and the various match patterns.
- * In the assembled microcode, the first opcode must be an O_PROBE_STATE
- * (generated if the rule includes a keep-state option), then the
- * various match patterns, the "log" action, and the actual action.
- *
- */
-static void
-add(int ac, char *av[])
-{
-       /*
-        * rules are added into the 'rulebuf' and then copied in
-        * the correct order into the actual rule.
-        * Some things that need to go out of order (prob, action etc.)
-        * go into actbuf[].
-        */
-       static uint32_t rulebuf[255], actbuf[255], cmdbuf[255];
-
-       ipfw_insn *src, *dst, *cmd, *action, *prev=NULL;
-       ipfw_insn *first_cmd;   /* first match pattern */
-
-       struct ip_fw *rule;
-
-       /*
-        * various flags used to record that we entered some fields.
-        */
-       ipfw_insn *have_state = NULL;   /* check-state or keep-state */
-
-       int i;
-
-       int open_par = 0;       /* open parenthesis ( */
-
-       /* proto is here because it is used to fetch ports */
-       u_char proto = IPPROTO_IP;      /* default protocol */
-
-       double match_prob = 1; /* match probability, default is always match */
-
-       bzero(actbuf, sizeof(actbuf));          /* actions go here */
-       bzero(cmdbuf, sizeof(cmdbuf));
-       bzero(rulebuf, sizeof(rulebuf));
-
-       rule = (struct ip_fw *)rulebuf;
-       cmd = (ipfw_insn *)cmdbuf;
-       action = (ipfw_insn *)actbuf;
-
-       av++; ac--;
-
-       /* [rule N]     -- Rule number optional */
-       if (ac && isdigit(**av)) {
-               rule->rulenum = atoi(*av);
-               av++;
-               ac--;
-       }
-
-       /* [set N]      -- set number (0..RESVD_SET), optional */
-       if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
-               int set = strtoul(av[1], NULL, 10);
-               if (set < 0 || set > RESVD_SET)
-                       errx(EX_DATAERR, "illegal set %s", av[1]);
-               rule->set = set;
-               av += 2; ac -= 2;
-       }
-
-       /* [prob D]     -- match probability, optional */
-       if (ac > 1 && !strncmp(*av, "prob", strlen(*av))) {
-               match_prob = strtod(av[1], NULL);
-
-               if (match_prob <= 0 || match_prob > 1)
-                       errx(EX_DATAERR, "illegal match prob. %s", av[1]);
-               av += 2; ac -= 2;
-       }
-
-       /* action       -- mandatory */
-       NEED1("missing action");
-       i = match_token(rule_actions, *av);
-       ac--; av++;
-       action->len = 1;        /* default */
-       switch(i) {
-       case TOK_CHECKSTATE:
-               have_state = action;
-               action->opcode = O_CHECK_STATE;
-               break;
-
-       case TOK_ACCEPT:
-               action->opcode = O_ACCEPT;
-               break;
-
-       case TOK_DENY:
-               action->opcode = O_DENY;
-               action->arg1 = 0;
-               break;
-
-       case TOK_REJECT:
-               action->opcode = O_REJECT;
-               action->arg1 = ICMP_UNREACH_HOST;
-               break;
-
-       case TOK_RESET:
-               action->opcode = O_REJECT;
-               action->arg1 = ICMP_REJECT_RST;
-               break;
-
-       case TOK_UNREACH:
-               action->opcode = O_REJECT;
-               NEED1("missing reject code");
-               fill_reject_code(&action->arg1, *av);
-               ac--; av++;
-               break;
-
-       case TOK_COUNT:
-               action->opcode = O_COUNT;
-               break;
-
-       case TOK_QUEUE:
-       case TOK_PIPE:
-               action->len = F_INSN_SIZE(ipfw_insn_pipe);
-       case TOK_SKIPTO:
-               if (i == TOK_QUEUE)
-                       action->opcode = O_QUEUE;
-               else if (i == TOK_PIPE)
-                       action->opcode = O_PIPE;
-               else if (i == TOK_SKIPTO)
-                       action->opcode = O_SKIPTO;
-               NEED1("missing skipto/pipe/queue number");
-               action->arg1 = strtoul(*av, NULL, 10);
-               av++; ac--;
-               break;
-
-       case TOK_DIVERT:
-       case TOK_TEE:
-               action->opcode = (i == TOK_DIVERT) ? O_DIVERT : O_TEE;
-               NEED1("missing divert/tee port");
-               action->arg1 = strtoul(*av, NULL, 0);
-               if (action->arg1 == 0) {
-                       struct servent *s;
-                       setservent(1);
-                       s = getservbyname(av[0], "divert");
-                       if (s != NULL)
-                               action->arg1 = ntohs(s->s_port);
-                       else
-                               errx(EX_DATAERR, "illegal divert/tee port");
-               }
-               ac--; av++;
-               break;
-
-       case TOK_FORWARD: {
-               ipfw_insn_sa *p = (ipfw_insn_sa *)action;
-               char *s, *end;
-
-               NEED1("missing forward address[:port]");
-
-               action->opcode = O_FORWARD_IP;
-               action->len = F_INSN_SIZE(ipfw_insn_sa);
-
-               p->sa.sin_len = sizeof(struct sockaddr_in);
-               p->sa.sin_family = AF_INET;
-               p->sa.sin_port = 0;
-               /*
-                * locate the address-port separator (':' or ',')
-                */
-               s = strchr(*av, ':');
-               if (s == NULL)
-                       s = strchr(*av, ',');
-               if (s != NULL) {
-                       *(s++) = '\0';
-                       i = strtoport(s, &end, 0 /* base */, 0 /* proto */);
-                       if (s == end)
-                               errx(EX_DATAERR,
-                                   "illegal forwarding port ``%s''", s);
-                       p->sa.sin_port = (u_short)i;
-               }
-               lookup_host(*av, &(p->sa.sin_addr));
-               }
-               ac--; av++;
-               break;
-
-       case TOK_COMMENT:
-               /* pretend it is a 'count' rule followed by the comment */
-               action->opcode = O_COUNT;
-               ac++; av--;     /* go back... */
-               break;
-
-       default:
-               errx(EX_DATAERR, "invalid action %s", av[-1]);
-       }
-       action = next_cmd(action);
-
-       /*
-        * [log [logamount N]]  -- log, optional
-        *
-        * If exists, it goes first in the cmdbuf, but then it is
-        * skipped in the copy section to the end of the buffer.
-        */
-       if (ac && !strncmp(*av, "log", strlen(*av))) {
-               ipfw_insn_log *c = (ipfw_insn_log *)cmd;
-               int l;
-
-               cmd->len = F_INSN_SIZE(ipfw_insn_log);
-               cmd->opcode = O_LOG;
-               av++; ac--;
-               if (ac && !strncmp(*av, "logamount", strlen(*av))) {
-                       ac--; av++;
-                       NEED1("logamount requires argument");
-                       l = atoi(*av);
-                       if (l < 0)
-                               errx(EX_DATAERR, "logamount must be positive");
-                       c->max_log = l;
-                       ac--; av++;
-               }
-               cmd = next_cmd(cmd);
-       }
-
-       if (have_state) /* must be a check-state, we are done */
-               goto done;
-
-#define OR_START(target)                                       \
-       if (ac && (*av[0] == '(' || *av[0] == '{')) {           \
-               if (open_par)                                   \
-                       errx(EX_USAGE, "nested \"(\" not allowed"); \
-               prev = NULL;                                    \
-               open_par = 1;                                   \
-               if ( (av[0])[1] == '\0') {                      \
-                       ac--; av++;                             \
-               } else                                          \
-                       (*av)++;                                \
-       }                                                       \
-       target:                                                 \
-
-
-#define        CLOSE_PAR                                               \
-       if (open_par) {                                         \
-               if (ac && (                                     \
-                   !strncmp(*av, ")", strlen(*av)) ||          \
-                   !strncmp(*av, "}", strlen(*av)) )) {        \
-                       prev = NULL;                            \
-                       open_par = 0;                           \
-                       ac--; av++;                             \
-               } else                                          \
-                       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"); \
-               cmd->len |= F_NOT;                              \
-               ac--; av++;                                     \
-       }
-
-#define OR_BLOCK(target)                                       \
-       if (ac && !strncmp(*av, "or", strlen(*av))) {           \
-               if (prev == NULL || open_par == 0)              \
-                       errx(EX_DATAERR, "invalid OR block");   \
-               prev->len |= F_OR;                              \
-               ac--; av++;                                     \
-               goto target;                                    \
-       }                                                       \
-       CLOSE_PAR;
-
-       first_cmd = cmd;
-
-#if 0
-       /*
-        * MAC addresses, optional.
-        * If we have this, we skip the part "proto from src to dst"
-        * and jump straight to the option parsing.
-        */
-       NOT_BLOCK;
-       NEED1("missing protocol");
-       if (!strncmp(*av, "MAC", strlen(*av)) ||
-           !strncmp(*av, "mac", strlen(*av))) {
-               ac--; av++;     /* the "MAC" keyword */
-               add_mac(cmd, ac, av); /* exits in case of errors */
-               cmd = next_cmd(cmd);
-               ac -= 2; av += 2;       /* dst-mac and src-mac */
-               NOT_BLOCK;
-               NEED1("missing mac type");
-               if (add_mactype(cmd, ac, av[0]))
-                       cmd = next_cmd(cmd);
-               ac--; av++;     /* any or mac-type */
-               goto read_options;
-       }
-#endif
-
-       /*
-        * protocol, mandatory
-        */
-    OR_START(get_proto);
-       NOT_BLOCK;
-       NEED1("missing protocol");
-       if (add_proto(cmd, *av)) {
-               av++; ac--;
-               if (F_LEN(cmd) == 0)    /* plain IP */
-                       proto = 0;
-               else {
-                       proto = cmd->arg1;
-                       prev = cmd;
-                       cmd = next_cmd(cmd);
-               }
-       } else if (first_cmd != cmd) {
-               errx(EX_DATAERR, "invalid protocol ``%s''", *av);
-       } else
-               goto read_options;
-    OR_BLOCK(get_proto);
-
-       /*
-        * "from", mandatory
-        */
-       if (!ac || strncmp(*av, "from", strlen(*av)))
-               errx(EX_USAGE, "missing ``from''");
-       ac--; av++;
-
-       /*
-        * source IP, mandatory
-        */
-    OR_START(source_ip);
-       NOT_BLOCK;      /* optional "not" */
-       NEED1("missing source address");
-       if (add_srcip(cmd, *av)) {
-               ac--; av++;
-               if (F_LEN(cmd) != 0) {  /* ! any */
-                       prev = cmd;
-                       cmd = next_cmd(cmd);
-               }
-       }
-    OR_BLOCK(source_ip);
-
-       /*
-        * source ports, optional
-        */
-       NOT_BLOCK;      /* optional "not" */
-       if (ac) {
-               if (!strncmp(*av, "any", strlen(*av)) ||
-                   add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
-                       ac--; av++;
-                       if (F_LEN(cmd) != 0)
-                               cmd = next_cmd(cmd);
-               }
-       }
-
-       /*
-        * "to", mandatory
-        */
-       if (!ac || strncmp(*av, "to", strlen(*av)))
-               errx(EX_USAGE, "missing ``to''");
-       av++; ac--;
-
-       /*
-        * destination, mandatory
-        */
-    OR_START(dest_ip);
-       NOT_BLOCK;      /* optional "not" */
-       NEED1("missing dst address");
-       if (add_dstip(cmd, *av)) {
-               ac--; av++;
-               if (F_LEN(cmd) != 0) {  /* ! any */
-                       prev = cmd;
-                       cmd = next_cmd(cmd);
-               }
-       }
-    OR_BLOCK(dest_ip);
-
-       /*
-        * dest. ports, optional
-        */
-       NOT_BLOCK;      /* optional "not" */
-       if (ac) {
-               if (!strncmp(*av, "any", strlen(*av)) ||
-                   add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
-                       ac--; av++;
-                       if (F_LEN(cmd) != 0)
-                               cmd = next_cmd(cmd);
-               }
-       }
-
-read_options:
-       if (ac && first_cmd == cmd) {
-               /*
-                * nothing specified so far, store in the rule to ease
-                * printout later.
-                */
-                rule->_pad = 1;
-       }
-       prev = NULL;
-       while (ac) {
-               char *s;
-               ipfw_insn_u32 *cmd32;   /* alias for cmd */
-
-               s = *av;
-               cmd32 = (ipfw_insn_u32 *)cmd;
-
-               if (*s == '!') {        /* alternate syntax for NOT */
-                       if (cmd->len & F_NOT)
-                               errx(EX_USAGE, "double \"not\" not allowed");
-                       cmd->len = F_NOT;
-                       s++;
-               }
-               i = match_token(rule_options, s);
-               ac--; av++;
-               switch(i) {
-               case TOK_NOT:
-                       if (cmd->len & F_NOT)
-                               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");
-                       prev->len |= F_OR;
-                       break;
-
-               case TOK_STARTBRACE:
-                       if (open_par)
-                               errx(EX_USAGE, "+nested \"(\" not allowed");
-                       open_par = 1;
-                       break;
-
-               case TOK_ENDBRACE:
-                       if (!open_par)
-                               errx(EX_USAGE, "+missing \")\"");
-                       open_par = 0;
-                       prev = NULL;
-                       break;
-
-               case TOK_IN:
-                       fill_cmd(cmd, O_IN, 0, 0);
-                       break;
-
-               case TOK_OUT:
-                       cmd->len ^= F_NOT; /* toggle F_NOT */
-                       fill_cmd(cmd, O_IN, 0, 0);
-                       break;
-
-               case TOK_FRAG:
-                       fill_cmd(cmd, O_FRAG, 0, 0);
-                       break;
-
-               case TOK_LAYER2:
-                       fill_cmd(cmd, O_LAYER2, 0, 0);
-                       break;
-
-               case TOK_XMIT:
-               case TOK_RECV:
-               case TOK_VIA:
-                       NEED1("recv, xmit, via require interface name"
-                               " or address");
-                       fill_iface((ipfw_insn_if *)cmd, av[0]);
-                       ac--; av++;
-                       if (F_LEN(cmd) == 0)    /* not a valid address */
-                               break;
-                       if (i == TOK_XMIT)
-                               cmd->opcode = O_XMIT;
-                       else if (i == TOK_RECV)
-                               cmd->opcode = O_RECV;
-                       else if (i == TOK_VIA)
-                               cmd->opcode = O_VIA;
-                       break;
-
-               case TOK_ICMPTYPES:
-                       NEED1("icmptypes requires list of types");
-                       fill_icmptypes((ipfw_insn_u32 *)cmd, *av);
-                       av++; ac--;
-                       break;
-
-               case TOK_IPTTL:
-                       NEED1("ipttl requires TTL");
-                       if (strpbrk(*av, "-,")) {
-                           if (!add_ports(cmd, *av, 0, O_IPTTL))
-                               errx(EX_DATAERR, "invalid ipttl %s", *av);
-                       } else
-                           fill_cmd(cmd, O_IPTTL, 0, strtoul(*av, NULL, 0));
-                       ac--; av++;
-                       break;
-
-               case TOK_IPID:
-                       NEED1("ipid requires id");
-                       if (strpbrk(*av, "-,")) {
-                           if (!add_ports(cmd, *av, 0, O_IPID))
-                               errx(EX_DATAERR, "invalid ipid %s", *av);
-                       } else
-                           fill_cmd(cmd, O_IPID, 0, strtoul(*av, NULL, 0));
-                       ac--; av++;
-                       break;
-
-               case TOK_IPLEN:
-                       NEED1("iplen requires length");
-                       if (strpbrk(*av, "-,")) {
-                           if (!add_ports(cmd, *av, 0, O_IPLEN))
-                               errx(EX_DATAERR, "invalid ip len %s", *av);
-                       } else
-                           fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0));
-                       ac--; av++;
-                       break;
-
-               case TOK_IPVER:
-                       NEED1("ipver requires version");
-                       fill_cmd(cmd, O_IPVER, 0, strtoul(*av, NULL, 0));
-                       ac--; av++;
-                       break;
-
-               case TOK_IPPRECEDENCE:
-                       NEED1("ipprecedence requires value");
-                       fill_cmd(cmd, O_IPPRECEDENCE, 0,
-                           (strtoul(*av, NULL, 0) & 7) << 5);
-                       ac--; av++;
-                       break;
-
-               case TOK_IPOPTS:
-                       NEED1("missing argument for ipoptions");
-                       fill_flags(cmd, O_IPOPT, f_ipopts, *av);
-                       ac--; av++;
-                       break;
-
-               case TOK_IPTOS:
-                       NEED1("missing argument for iptos");
-                       fill_flags(cmd, O_IPTOS, f_iptos, *av);
-                       ac--; av++;
-                       break;
-
-               case TOK_UID:
-                       NEED1("uid requires argument");
-                   {
-                       char *end;
-                       uid_t uid;
-                       struct passwd *pwd;
-
-                       cmd->opcode = O_UID;
-                       uid = strtoul(*av, &end, 0);
-                       pwd = (*end == '\0') ? getpwuid(uid) : getpwnam(*av);
-                       if (pwd == NULL)
-                               errx(EX_DATAERR, "uid \"%s\" nonexistent", *av);
-                       cmd32->d[0] = pwd->pw_uid;
-                       cmd->len = F_INSN_SIZE(ipfw_insn_u32);
-                       ac--; av++;
-                   }
-                       break;
-
-               case TOK_GID:
-                       NEED1("gid requires argument");
-                   {
-                       char *end;
-                       gid_t gid;
-                       struct group *grp;
-
-                       cmd->opcode = O_GID;
-                       gid = strtoul(*av, &end, 0);
-                       grp = (*end == '\0') ? getgrgid(gid) : getgrnam(*av);
-                       if (grp == NULL)
-                               errx(EX_DATAERR, "gid \"%s\" nonexistent", *av);
-                       cmd32->d[0] = grp->gr_gid;
-                       cmd->len = F_INSN_SIZE(ipfw_insn_u32);
-                       ac--; av++;
-                   }
-                       break;
-
-               case TOK_ESTAB:
-                       fill_cmd(cmd, O_ESTAB, 0, 0);
-                       break;
-
-               case TOK_SETUP:
-                       fill_cmd(cmd, O_TCPFLAGS, 0,
-                               (TH_SYN) | ( (TH_ACK) & 0xff) <<8 );
-                       break;
-
-               case TOK_TCPOPTS:
-                       NEED1("missing argument for tcpoptions");
-                       fill_flags(cmd, O_TCPOPTS, f_tcpopts, *av);
-                       ac--; av++;
-                       break;
-
-               case TOK_TCPSEQ:
-               case TOK_TCPACK:
-                       NEED1("tcpseq/tcpack requires argument");
-                       cmd->len = F_INSN_SIZE(ipfw_insn_u32);
-                       cmd->opcode = (i == TOK_TCPSEQ) ? O_TCPSEQ : O_TCPACK;
-                       cmd32->d[0] = htonl(strtoul(*av, NULL, 0));
-                       ac--; av++;
-                       break;
-
-               case TOK_TCPWIN:
-                       NEED1("tcpwin requires length");
-                       fill_cmd(cmd, O_TCPWIN, 0,
-                           htons(strtoul(*av, NULL, 0)));
-                       ac--; av++;
-                       break;
-
-               case TOK_TCPFLAGS:
-                       NEED1("missing argument for tcpflags");
-                       cmd->opcode = O_TCPFLAGS;
-                       fill_flags(cmd, O_TCPFLAGS, f_tcpflags, *av);
-                       ac--; av++;
-                       break;
-
-               case TOK_KEEPSTATE:
-                       if (open_par)
-                               errx(EX_USAGE, "keep-state cannot be part "
-                                   "of an or block");
-                       if (have_state)
-                               errx(EX_USAGE, "only one of keep-state "
-                                       "and limit is allowed");
-                       have_state = cmd;
-                       fill_cmd(cmd, O_KEEP_STATE, 0, 0);
-                       break;
-
-               case TOK_LIMIT:
-                       if (open_par)
-                               errx(EX_USAGE, "limit cannot be part "
-                                   "of an or block");
-                       if (have_state)
-                               errx(EX_USAGE, "only one of keep-state "
-                                       "and limit is allowed");
-                       NEED1("limit needs mask and # of connections");
-                       have_state = cmd;
-                   {
-                       ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
-
-                       cmd->len = F_INSN_SIZE(ipfw_insn_limit);
-                       cmd->opcode = O_LIMIT;
-                       c->limit_mask = 0;
-                       c->conn_limit = 0;
-                       for (; ac >1 ;) {
-                               int val;
-
-                               val = match_token(limit_masks, *av);
-                               if (val <= 0)
-                                       break;
-                               c->limit_mask |= val;
-                               ac--; av++;
-                       }
-                       c->conn_limit = atoi(*av);
-                       if (c->conn_limit == 0)
-                               errx(EX_USAGE, "limit: limit must be >0");
-                       if (c->limit_mask == 0)
-                               errx(EX_USAGE, "missing limit mask");
-                       ac--; av++;
-                   }
-                       break;
-
-               case TOK_PROTO:
-                       NEED1("missing protocol");
-                       if (add_proto(cmd, *av)) {
-                               proto = cmd->arg1;
-                               ac--; av++;
-                       } else
-                               errx(EX_DATAERR, "invalid protocol ``%s''",
-                                   *av);
-                       break;
-
-               case TOK_SRCIP:
-                       NEED1("missing source IP");
-                       if (add_srcip(cmd, *av)) {
-                               ac--; av++;
-                       }
-                       break;
-
-               case TOK_DSTIP:
-                       NEED1("missing destination IP");
-                       if (add_dstip(cmd, *av)) {
-                               ac--; av++;
-                       }
-                       break;
-
-               case TOK_SRCPORT:
-                       NEED1("missing source port");
-                       if (!strncmp(*av, "any", strlen(*av)) ||
-                           add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
-                               ac--; av++;
-                       } else
-                               errx(EX_DATAERR, "invalid source port %s", *av);
-                       break;
-
-               case TOK_DSTPORT:
-                       NEED1("missing destination port");
-                       if (!strncmp(*av, "any", strlen(*av)) ||
-                           add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
-                               ac--; av++;
-                       } else
-                               errx(EX_DATAERR, "invalid destination port %s",
-                                   *av);
-                       break;
-
-               case TOK_MAC:
-                       if (ac < 2)
-                               errx(EX_USAGE, "MAC dst-mac src-mac");
-                       if (add_mac(cmd, ac, av)) {
-                               ac -= 2; av += 2;
-                       }
-                       break;
-
-               case TOK_MACTYPE:
-                       NEED1("missing mac type");
-                       if (!add_mactype(cmd, ac, *av))
-                               errx(EX_DATAERR, "invalid mac type %s", *av);
-                       ac--; av++;
-                       break;
-
-               case TOK_VERREVPATH:
-                       fill_cmd(cmd, O_VERREVPATH, 0, 0);
-                       break;
-
-               case TOK_IPSEC:
-                       fill_cmd(cmd, O_IPSEC, 0, 0);
-                       break;
-
-               case TOK_COMMENT:
-                       fill_comment(cmd, ac, av);
-                       av += ac;
-                       ac = 0;
-                       break;
-
-               default:
-                       errx(EX_USAGE, "unrecognised option [%d] %s", i, s);
-               }
-               if (F_LEN(cmd) > 0) {   /* prepare to advance */
-                       prev = cmd;
-                       cmd = next_cmd(cmd);
-               }
-       }
-
-done:
-       /*
-        * Now copy stuff into the rule.
-        * If we have a keep-state option, the first instruction
-        * must be a PROBE_STATE (which is generated here).
-        * If we have a LOG option, it was stored as the first command,
-        * and now must be moved to the top of the action part.
-        */
-       dst = (ipfw_insn *)rule->cmd;
-
-       /*
-        * First thing to write into the command stream is the match probability.
-        */
-       if (match_prob != 1) { /* 1 means always match */
-               dst->opcode = O_PROB;
-               dst->len = 2;
-               *((int32_t *)(dst+1)) = (int32_t)(match_prob * 0x7fffffff);
-               dst += dst->len;
-       }
-
-       /*
-        * generate O_PROBE_STATE if necessary
-        */
-       if (have_state && have_state->opcode != O_CHECK_STATE) {
-               fill_cmd(dst, O_PROBE_STATE, 0, 0);
-               dst = next_cmd(dst);
-       }
-       /*
-        * copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT
-        */
-       for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
-               i = F_LEN(src);
-
-               switch (src->opcode) {
-               case O_LOG:
-               case O_KEEP_STATE:
-               case O_LIMIT:
-                       break;
-               default:
-                       bcopy(src, dst, i * sizeof(uint32_t));
-                       dst += i;
-               }
-       }
-
-       /*
-        * put back the have_state command as last opcode
-        */
-       if (have_state && have_state->opcode != O_CHECK_STATE) {
-               i = F_LEN(have_state);
-               bcopy(have_state, dst, i * sizeof(uint32_t));
-               dst += i;
-       }
-       /*
-        * start action section
-        */
-       rule->act_ofs = dst - rule->cmd;
-
-       /*
-        * put back O_LOG if necessary
-        */
-       src = (ipfw_insn *)cmdbuf;
-       if (src->opcode == O_LOG) {
-               i = F_LEN(src);
-               bcopy(src, dst, i * sizeof(uint32_t));
-               dst += i;
-       }
-       /*
-        * copy all other actions
-        */
-       for (src = (ipfw_insn *)actbuf; src != action; src += i) {
-               i = F_LEN(src);
-               bcopy(src, dst, i * sizeof(uint32_t));
-               dst += i;
-       }
-
-       rule->cmd_len = (uint32_t *)dst - (uint32_t *)(rule->cmd);
-       i = (char *)dst - (char *)rule;
-       
-       if (do_cmd(IP_FW_ADD, rule, (uintptr_t)&i) == -1)
-               err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
-       if (!do_quiet)
-               show_ipfw(rule, 0, 0);
-}
-
-static void
-zero(int ac, char *av[], int optname /* IP_FW_ZERO or IP_FW_RESETLOG */)
-{
-       struct ip_fw    rule;
-       int rulenum;
-       int failed = EX_OK;
-       char const *name = optname == IP_FW_ZERO ?  "ZERO" : "RESETLOG";
-
-       av++; ac--;
-       bzero(&rule, sizeof(rule));
-
-       if (!ac) {
-               /* clear all entries - send empty rule */
-               if (do_cmd(optname, &rule, sizeof(rule)) < 0)
-                       err(EX_UNAVAILABLE, "setsockopt(IP_FW_%s)", name);
-               if (!do_quiet)
-                       printf("%s.\n", optname == IP_FW_ZERO ?
-                           "Accounting cleared":"Logging counts reset");
-
-               return;
-       }
-
-       while (ac) {
-               /* Rule number */
-               if (isdigit(**av)) {
-                       rulenum = atoi(*av);
-                       av++;
-                       ac--;
-                       rule.rulenum = rulenum;
-                       if (do_cmd(optname, &rule, sizeof(rule))) {
-                               warn("rule %u: setsockopt(IP_FW_%s)",
-                                   rulenum, name);
-                               failed = EX_UNAVAILABLE;
-                       } else if (!do_quiet)
-                               printf("Entry %d %s.\n", rulenum,
-                                   optname == IP_FW_ZERO ?
-                                       "cleared" : "logging count reset");
-               } else {
-                       errx(EX_USAGE, "invalid rule number ``%s''", *av);
-               }
-       }
-       if (failed != EX_OK)
-               exit(failed);
-}
-
-static void
-flush(int force)
-{
-       int cmd = do_pipe ? IP_DUMMYNET_FLUSH : IP_FW_FLUSH;
-       struct ip_fw    rule;
-
-       if (!force && !do_quiet) { /* need to ask user */
-               int c;
-
-               printf("Are you sure? [yn] ");
-               fflush(stdout);
-               do {
-                       c = toupper(getc(stdin));
-                       while (c != '\n' && getc(stdin) != '\n')
-                               if (feof(stdin))
-                                       return; /* and do not flush */
-               } while (c != 'Y' && c != 'N');
-               printf("\n");
-               if (c == 'N')   /* user said no */
-                       return;
-       }
-       
-       if (cmd == IP_FW_FLUSH) {
-               /* send empty rule */
-               bzero(&rule, sizeof(rule));
-               if (do_cmd(cmd, &rule, sizeof(rule)) < 0)
-                       err(EX_UNAVAILABLE, "setsockopt(IP_FW_FLUSH)");
-       }
-       else {
-               if (do_cmd(cmd, NULL, 0) < 0)
-                       err(EX_UNAVAILABLE, "setsockopt(IP_DUMMYNET_FLUSH)");
-       }
-       if (!do_quiet)
-               printf("Flushed all %s.\n", do_pipe ? "pipes" : "rules");
-}
-
-/*
- * Free a the (locally allocated) copy of command line arguments.
- */
-static void
-free_args(int ac, char **av)
-{
-       int i;
-
-       for (i=0; i < ac; i++)
-               free(av[i]);
-       free(av);
-}
-
-/*
- * Called with the arguments (excluding program name).
- * Returns 0 if successful, 1 if empty command, errx() in case of errors.
- */
-static int
-ipfw_main(int oldac, char **oldav)
-{
-       int ch, ac, save_ac;
-       char **av, **save_av;
-       int do_acct = 0;                /* Show packet/byte count */
-       int do_force = 0;               /* Don't ask for confirmation */
-
-#define WHITESP                " \t\f\v\n\r"
-       if (oldac == 0)
-               return 1;
-       else if (oldac == 1) {
-               /*
-                * If we are called with a single string, try to split it into
-                * arguments for subsequent parsing.
-                * But first, remove spaces after a ',', by copying the string
-                * in-place.
-                */
-               char *arg = oldav[0];   /* The string... */
-               int l = strlen(arg);
-               int copy = 0;           /* 1 if we need to copy, 0 otherwise */
-               int i, j;
-               for (i = j = 0; i < l; i++) {
-                       if (arg[i] == '#')      /* comment marker */
-                               break;
-                       if (copy) {
-                               arg[j++] = arg[i];
-                               copy = !index("," WHITESP, arg[i]);
-                       } else {
-                               copy = !index(WHITESP, arg[i]);
-                               if (copy)
-                                       arg[j++] = arg[i];
-                       }
-               }
-               if (!copy && j > 0)     /* last char was a 'blank', remove it */
-                       j--;
-               l = j;                  /* the new argument length */
-               arg[j++] = '\0';
-               if (l == 0)             /* empty string! */
-                       return 1;
-
-               /*
-                * First, count number of arguments. Because of the previous
-                * processing, this is just the number of blanks plus 1.
-                */
-               for (i = 0, ac = 1; i < l; i++)
-                       if (index(WHITESP, arg[i]) != NULL)
-                               ac++;
-
-               av = calloc(ac, sizeof(char *));
-
-               /*
-                * Second, copy arguments from cmd[] to av[]. For each one,
-                * j is the initial character, i is the one past the end.
-                */
-               for (ac = 0, i = j = 0; i < l; i++)
-                       if (index(WHITESP, arg[i]) != NULL || i == l-1) {
-                               if (i == l-1)
-                                       i++;
-                               av[ac] = calloc(i-j+1, 1);
-                               bcopy(arg+j, av[ac], i-j);
-                               ac++;
-                               j = i + 1;
-                       }
-       } 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;
-
-               av = calloc(oldac, sizeof(char *));
-               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++) {
-                                       strlcat(av[ac]+l, oldav[first], buflen-l);
-                                       l += strlen(oldav[first]);
-                               }
-                               ac++;
-                               l = 0;
-                               first = i+1;
-                       }
-               }
-       }
-
-       /* Set the force flag for non-interactive processes */
-       do_force = !isatty(STDIN_FILENO);
-
-       /* Save arguments for final freeing of memory. */
-       save_ac = ac;
-       save_av = av;
-
-       optind = optreset = 0;
-       while ((ch = getopt(ac, av, "acdefhnNqs:STtv")) != -1)
-               switch (ch) {
-               case 'a':
-                       do_acct = 1;
-                       break;
-
-               case 'c':
-                       do_compact = 1;
-                       break;
-
-               case 'd':
-                       do_dynamic = 1;
-                       break;
-
-               case 'e':
-                       do_expired = 1;
-                       break;
-
-               case 'f':
-                       do_force = 1;
-                       break;
-
-               case 'h': /* help */
-                       free_args(save_ac, save_av);
-                       help();
-                       break;  /* NOTREACHED */
-
-               case 'n':
-                       test_only = 1;
-                       break;
-
-               case 'N':
-                       do_resolv = 1;
-                       break;
-
-               case 'q':
-                       do_quiet = 1;
-                       break;
-
-               case 's': /* sort */
-                       do_sort = atoi(optarg);
-                       break;
-
-               case 'S':
-                       show_sets = 1;
-                       break;
-
-               case 't':
-                       do_time = 1;
-                       break;
-
-               case 'T':
-                       do_time = 2;    /* numeric timestamp */
-                       break;
-
-               case 'v': /* verbose */
-                       verbose = 1;
-                       break;
-
-               default:
-                       free_args(save_ac, save_av);
-                       return 1;
-               }
-
-       ac -= optind;
-       av += optind;
-       NEED1("bad arguments, for usage summary ``ipfw''");
-
-       /*
-        * An undocumented behaviour of ipfw1 was to allow rule numbers first,
-        * e.g. "100 add allow ..." instead of "add 100 allow ...".
-        * In case, swap first and second argument to get the normal form.
-        */
-       if (ac > 1 && isdigit(*av[0])) {
-               char *p = av[0];
-
-               av[0] = av[1];
-               av[1] = p;
-       }
-
-       /*
-        * optional: pipe or queue
-        */
-       do_pipe = 0;
-       if (!strncmp(*av, "pipe", strlen(*av)))
-               do_pipe = 1;
-       else if (!strncmp(*av, "queue", strlen(*av)))
-               do_pipe = 2;
-       if (do_pipe) {
-               ac--;
-               av++;
-       }
-       NEED1("missing command");
-
-       /*
-        * For pipes and queues we normally say 'pipe NN config'
-        * but the code is easier to parse as 'pipe config NN'
-        * so we swap the two arguments.
-        */
-       if (do_pipe > 0 && ac > 1 && isdigit(*av[0])) {
-               char *p = av[0];
-
-               av[0] = av[1];
-               av[1] = p;
-       }
-
-       if (!strncmp(*av, "add", strlen(*av)))
-               add(ac, av);
-       else if (do_pipe && !strncmp(*av, "config", strlen(*av)))
-               config_pipe(ac, av);
-       else if (!strncmp(*av, "delete", strlen(*av)))
-               delete(ac, av);
-       else if (!strncmp(*av, "flush", strlen(*av)))
-               flush(do_force);
-       else if (!strncmp(*av, "zero", strlen(*av)))
-               zero(ac, av, IP_FW_ZERO);
-       else if (!strncmp(*av, "resetlog", strlen(*av)))
-               zero(ac, av, IP_FW_RESETLOG);
-       else if (!strncmp(*av, "print", strlen(*av)) ||
-                !strncmp(*av, "list", strlen(*av)))
-               list(ac, av, do_acct);
-       else if (!strncmp(*av, "set", strlen(*av)))
-               sets_handler(ac, av);
-       else if (!strncmp(*av, "enable", strlen(*av)))
-               sysctl_handler(ac, av, 1);
-       else if (!strncmp(*av, "disable", strlen(*av)))
-               sysctl_handler(ac, av, 0);
-       else if (!strncmp(*av, "show", strlen(*av)))
-               list(ac, av, 1 /* show counters */);
-       else
-               errx(EX_USAGE, "bad command `%s'", *av);
-
-       /* Free memory allocated in the argument parsing. */
-       free_args(save_ac, save_av);
-       return 0;
-}
-
-
-static void
-ipfw_readfile(int ac, char *av[])
-{
-#define MAX_ARGS       32
-       char    buf[BUFSIZ];
-       char    *cmd = NULL, *filename = av[ac-1];
-       int     c, lineno=0;
-       FILE    *f = NULL;
-       pid_t   preproc = 0;
-
-       filename = av[ac-1];
-
-       while ((c = getopt(ac, av, "cNnp:qS")) != -1) {
-               switch(c) {
-               case 'c':
-                       do_compact = 1;
-                       break;
-
-               case 'N':
-                       do_resolv = 1;
-                       break;
-
-               case 'n':
-                       test_only = 1;
-                       break;
-
-               case 'p':
-                       cmd = optarg;
-                       /*
-                        * Skip previous args and delete last one, so we
-                        * pass all but the last argument to the preprocessor
-                        * via av[optind-1]
-                        */
-                       av += optind - 1;
-                       ac -= optind - 1;
-                       av[ac-1] = NULL;
-                       fprintf(stderr, "command is %s\n", av[0]);
-                       break;
-
-               case 'q':
-                       do_quiet = 1;
-                       break;
-
-               case 'S':
-                       show_sets = 1;
-                       break;
-
-               default:
-                       errx(EX_USAGE, "bad arguments, for usage"
-                            " summary ``ipfw''");
-               }
-
-               if (cmd != NULL)
-                       break;
-       }
-
-       if (cmd == NULL && ac != optind + 1) {
-               fprintf(stderr, "ac %d, optind %d\n", ac, optind);
-               errx(EX_USAGE, "extraneous filename arguments");
-       }
-
-       if ((f = fopen(filename, "r")) == NULL)
-               err(EX_UNAVAILABLE, "fopen: %s", filename);
-
-       if (cmd != NULL) {                      /* pipe through preprocessor */
-               int pipedes[2];
-
-               if (pipe(pipedes) == -1)
-                       err(EX_OSERR, "cannot create pipe");
-
-               preproc = fork();
-               if (preproc == -1)
-                       err(EX_OSERR, "cannot fork");
-
-               if (preproc == 0) {
-                       /*
-                        * Child, will run the preprocessor with the
-                        * file on stdin and the pipe on stdout.
-                        */
-                       if (dup2(fileno(f), 0) == -1
-                           || dup2(pipedes[1], 1) == -1)
-                               err(EX_OSERR, "dup2()");
-                       fclose(f);
-                       close(pipedes[1]);
-                       close(pipedes[0]);
-                       execvp(cmd, av);
-                       err(EX_OSERR, "execvp(%s) failed", cmd);
-               } else { /* parent, will reopen f as the pipe */
-                       fclose(f);
-                       close(pipedes[1]);
-                       if ((f = fdopen(pipedes[0], "r")) == NULL) {
-                               int savederrno = errno;
-
-                               (void)kill(preproc, SIGTERM);
-                               errno = savederrno;
-                               err(EX_OSERR, "fdopen()");
-                       }
-               }
-       }
-
-       while (fgets(buf, BUFSIZ, f)) {         /* read commands */
-               char linename[16];
-               char *args[1];
-
-               lineno++;
-               snprintf(linename, sizeof(linename), "Line %d", lineno);
-               setprogname(linename); /* XXX */
-               args[0] = buf;
-               ipfw_main(1, args);
-       }
-       fclose(f);
-       if (cmd != NULL) {
-               int status;
-
-               if (waitpid(preproc, &status, 0) == -1)
-                       errx(EX_OSERR, "waitpid()");
-               if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
-                       errx(EX_UNAVAILABLE,
-                           "preprocessor exited with status %d",
-                           WEXITSTATUS(status));
-               else if (WIFSIGNALED(status))
-                       errx(EX_UNAVAILABLE,
-                           "preprocessor exited with signal %d",
-                           WTERMSIG(status));
-       }
-}
-
-int
-main(int ac, char *av[])
-{
-       /*
-        * If the last argument is an absolute pathname, interpret it
-        * as a file to be preprocessed.
-        */
-
-       if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
-               ipfw_readfile(ac, av);
-       else {
-               if (ipfw_main(ac-1, av+1))
-                       show_usage();
-       }
-       return EX_OK;
-}
index 040def3346a057b5b325ab3acf3954a952cd0aab..61762fe4e8f5421aa7409d26cc28d7b4172d0a50 100644 (file)
@@ -63,6 +63,7 @@ __unused static const char copyright[] =
 #include "kdump.h"
 #include <arpa/inet.h>
 
+#include <assert.h>
 #include <stdint.h>
 #include <ctype.h>
 #include <errno.h>
@@ -80,6 +81,7 @@ __unused static const char copyright[] =
 
 #include "kdumpsubs.h"
 
+#define DEFAULT_KDUMPD_PORTNO (1069)
 #define        TIMEOUT         2
 
 int    peer;
@@ -110,6 +112,7 @@ static struct dirlist {
 static int     suppress_naks;
 static int     logging = 1;
 static int     ipchroot;
+static int  server_mode = 1;
 
 static char *errtomsg __P((int));
 static void  nak __P((int));
@@ -137,7 +140,7 @@ main(argc, argv)
        char *chuser = "nobody";
 
        openlog("kdumpd", LOG_PID | LOG_NDELAY, LOG_FTP);
-       while ((ch = getopt(argc, argv, "cClns:u:")) != -1) {
+       while ((ch = getopt(argc, argv, "cClns:u:w")) != -1) {
                switch (ch) {
                case 'c':
                        ipchroot = 1;
@@ -157,6 +160,9 @@ main(argc, argv)
                case 'u':
                        chuser = optarg;
                        break;
+               case 'w':
+                       server_mode = 0;
+                       break;
                default:
                        syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
                }
@@ -184,67 +190,70 @@ main(argc, argv)
                exit(1);
        }
 
-       on = 1;
-       if (ioctl(0, FIONBIO, &on) < 0) {
-               syslog(LOG_ERR, "ioctl(FIONBIO): %m");
-               exit(1);
-       }
-       fromlen = sizeof (from);
-       n = recvfrom(0, buf, sizeof (buf), 0,
-           (struct sockaddr *)&from, &fromlen);
-       if (n < 0) {
-               syslog(LOG_ERR, "recvfrom: %m");
-               exit(1);
-       }
-       /*
-        * Now that we have read the message out of the UDP
-        * socket, we fork and exit.  Thus, inetd will go back
-        * to listening to the kdump port, and the next request
-        * to come in will start up a new instance of kdumpd.
-        *
-        * We do this so that inetd can run kdumpd in "wait" mode.
-        * The problem with kdumpd running in "nowait" mode is that
-        * inetd may get one or more successful "selects" on the
-        * kdump port before we do our receive, so more than one
-        * instance of kdumpd may be started up.  Worse, if kdumpd
-        * breaks before doing the above "recvfrom", inetd would
-        * spawn endless instances, clogging the system.
-        */
-       {
-               int pid;
-               int i;
-               socklen_t j;
-
-               for (i = 1; i < 20; i++) {
-                   pid = fork();
-                   if (pid < 0) {
-                               sleep(i);
-                               /*
-                                * flush out to most recently sent request.
-                                *
-                                * This may drop some requests, but those
-                                * will be resent by the clients when
-                                * they timeout.  The positive effect of
-                                * this flush is to (try to) prevent more
-                                * than one kdumpd being started up to service
-                                * a single request from a single client.
-                                */
-                               j = sizeof from;
-                               i = recvfrom(0, buf, sizeof (buf), 0,
-                                   (struct sockaddr *)&from, &j);
-                               if (i > 0) {
-                                       n = i;
-                                       fromlen = j;
-                               }
-                   } else {
-                               break;
-                   }
+       /* If we are not in server mode, skip the whole 'inetd' logic below. */
+       if (server_mode) {
+               on = 1;
+               if (ioctl(0, FIONBIO, &on) < 0) {
+                       syslog(LOG_ERR, "ioctl(FIONBIO): %m");
+                       exit(1);
                }
-               if (pid < 0) {
-                       syslog(LOG_ERR, "fork: %m");
+               fromlen = sizeof (from);
+               n = recvfrom(0, buf, sizeof (buf), 0,
+                       (struct sockaddr *)&from, &fromlen);
+               if (n < 0) {
+                       syslog(LOG_ERR, "recvfrom: %m");
                        exit(1);
-               } else if (pid != 0) {
-                       exit(0);
+               }
+               /*
+                * Now that we have read the message out of the UDP
+                * socket, we fork and exit.  Thus, inetd will go back
+                * to listening to the kdump port, and the next request
+                * to come in will start up a new instance of kdumpd.
+                *
+                * We do this so that inetd can run kdumpd in "wait" mode.
+                * The problem with kdumpd running in "nowait" mode is that
+                * inetd may get one or more successful "selects" on the
+                * kdump port before we do our receive, so more than one
+                * instance of kdumpd may be started up.  Worse, if kdumpd
+                * breaks before doing the above "recvfrom", inetd would
+                * spawn endless instances, clogging the system.
+                */
+               {
+                       int pid;
+                       int i;
+                       socklen_t j;
+
+                       for (i = 1; i < 20; i++) {
+                               pid = fork();
+                               if (pid < 0) {
+                                       sleep(i);
+                                       /*
+                                        * flush out to most recently sent request.
+                                        *
+                                        * This may drop some requests, but those
+                                        * will be resent by the clients when
+                                        * they timeout.  The positive effect of
+                                        * this flush is to (try to) prevent more
+                                        * than one kdumpd being started up to service
+                                        * a single request from a single client.
+                                        */
+                                       j = sizeof from;
+                                       i = recvfrom(0, buf, sizeof (buf), 0,
+                                               (struct sockaddr *)&from, &j);
+                                       if (i > 0) {
+                                               n = i;
+                                               fromlen = j;
+                                       }
+                               } else {
+                                       break;
+                               }
+                       }
+                       if (pid < 0) {
+                               syslog(LOG_ERR, "fork: %m");
+                               exit(1);
+                       } else if (pid != 0) {
+                               exit(0);
+                       }
                }
        }
 
@@ -278,10 +287,9 @@ main(argc, argv)
                }
                chdir( "/" );
                setuid(nobody->pw_uid);
-       }
-       else
-         if (0 !=  chdir(dirs->name))
+       } else if (0 !=  chdir(dirs->name)) {
            syslog(LOG_ERR, "chdir%s: %m", dirs->name);
+       }
 
        from.sin_family = AF_INET;
        alarm(0);
@@ -294,10 +302,32 @@ main(argc, argv)
        }
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
+
+       if (!server_mode) {
+               sin.sin_addr.s_addr = htonl(INADDR_ANY);
+               sin.sin_port = htons((uint16_t) DEFAULT_KDUMPD_PORTNO);
+       }
+
        if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
                syslog(LOG_ERR, "bind: %m");
                exit(1);
        }
+
+       if (!server_mode) {
+               /*
+                * Wait for an incoming message from a remote peer, note that we need to
+                * populate n since kdump() expect the first message to be in buf
+                * already.
+                */
+               socklen_t slen = sizeof(from);
+               n = recvfrom(peer, buf, sizeof(buf), 0,
+                       (struct sockaddr *) &from, &slen);
+               if (n <= 0) {
+                       syslog(LOG_ERR, "recvfrom: %m");
+                       exit(1);
+               }
+       }
+
        if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {
                syslog(LOG_ERR, "connect: %m");
                exit(1);
index a96e169f3a0475f8d5ae852d7f3d3aeff1afd7a9..b1217ebe51af076cf3baa6dc98af94993cdfa576 100644 (file)
@@ -170,13 +170,16 @@ another device on the network is using the same link-local address.
 the interface is enabled to proxy neighbor discovery for global scope prefixes
 matching those on link at other interfaces.
 .It Xo
-.Ic ignore_na
-.Xc
-ignore neighbor advertisements received on this interface.
-.It Xo
 .Ic insecure
 do not use cryptographically generated addresses (CGA) on this interface.
 .Xc
+.It Xo
+.Ic replicated
+Address autoconfiguration proceeds under the assumption that interface
+configuration is replicated by a sleep proxy at another node on the link.
+Disables optimistic DAD and sends unsolicited NA with O=1 when DAD completes.
+Ignores DAD failures from other hardware addresses.
+.Xc
 .El
 .It Fl l
 Show link-layer reachability information.
index 2afce5dc12a8331ba7783962a4e919100d2a26d8..01d64aa77a9ca26a0b101cb7d2e7390b83de506b 100644 (file)
@@ -1205,9 +1205,9 @@ ifinfo(int argc, char **argv)
        } while (0)
                SETFLAG("nud", ND6_IFF_PERFORMNUD);
                SETFLAG("proxy_prefixes", ND6_IFF_PROXY_PREFIXES);
-               SETFLAG("ignore_na", ND6_IFF_IGNORE_NA);
                SETFLAG("disabled", ND6_IFF_IFDISABLED);
                SETFLAG("insecure", ND6_IFF_INSECURE);
+               SETFLAG("replicated", ND6_IFF_REPLICATED);
 
                ND.flags = newflags;
                if (ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd) < 0) {
@@ -1248,17 +1248,19 @@ ifinfo(int argc, char **argv)
                }
        }
        if (ND.flags) {
-               printf("\nFlags: ");
+               printf("\nFlags: 0x%x ", ND.flags);
                if ((ND.flags & ND6_IFF_IFDISABLED) != 0)
                        printf("IFDISABLED ");
-               if ((ND.flags & ND6_IFF_IGNORE_NA) != 0)
-                       printf("IGNORE_NA ");
                if ((ND.flags & ND6_IFF_INSECURE) != 0)
                        printf("INSECURE ");
                if ((ND.flags & ND6_IFF_PERFORMNUD) != 0)
                        printf("PERFORMNUD ");
                if ((ND.flags & ND6_IFF_PROXY_PREFIXES) != 0)
                        printf("PROXY_PREFIXES ");
+               if ((ND.flags & ND6_IFF_REPLICATED) != 0)
+                       printf("REPLICATED ");
+               if ((ND.flags & ND6_IFF_DAD) != 0)
+                       printf("DAD ");
        }
        putc('\n', stdout);
 #undef ND
index 714e6511ba168efb42674bc9fbe8d1d2d9b578cd..a0ef208bfa5741973e1be66a83d86d9ab1306678 100644 (file)
@@ -115,6 +115,7 @@ static char *qid2str(unsigned int);
 static char *qstate2str(unsigned int);
 static char *tcqslot2str(unsigned int);
 static char *rate2str(long double);
+static char *pri2str(unsigned int i);
 
 #define AVGN_MAX       8
 
@@ -142,6 +143,8 @@ static void print_qfqstats(int slot, struct qfq_classstats *,
     struct queue_stats *);
 static void print_sfbstats(struct sfb_stats *);
 static void update_avg(struct if_ifclassq_stats *, struct queue_stats *);
+static void print_fq_codel_stats(int slot, struct fq_codel_classstats *,
+    struct queue_stats *);
 
 struct queue_stats qstats[IFCQ_SC_MAX];
 
@@ -1064,6 +1067,8 @@ loop:
                                    sum->ift_fb - total->ift_fb);
                }
                *total = *sum;
+               
+               free(ifmsuppall);
        }
        if (!first)
                putchar('\n');
@@ -1468,6 +1473,11 @@ loop:
                                print_qfqstats(n, &ifcqs->ifqs_qfq_stats,
                                    &qstats[n]);
                                break;
+                       case PKTSCHEDT_FQ_CODEL:
+                               print_fq_codel_stats(n,
+                                   &ifcqs->ifqs_fq_codel_stats,
+                                   &qstats[n]);
+                               break;
                        case PKTSCHEDT_NONE:
                        default:
                                break;
@@ -1699,6 +1709,35 @@ print_qfqstats(int slot, struct qfq_classstats *cs, struct queue_stats *qs)
        }
 }
 
+static void
+print_fq_codel_stats(int pri, struct fq_codel_classstats *fqst,
+    struct queue_stats *qs)
+{
+       printf("     [ pri: %s (%d)\tsrv_cl: 0x%x\tquantum: %d\tdrr_max: %d ]\n",
+           pri2str(fqst->fcls_pri), fqst->fcls_pri,
+           fqst->fcls_service_class, fqst->fcls_quantum,
+           fqst->fcls_drr_max);
+       printf("     [ budget: %lld\t\ttarget qdelay: %14s ]\n",
+           fqst->fcls_budget, nsec_to_str(fqst->fcls_target_qdelay));
+       printf("     [ flow control: %u\tfeedback: %u\tstalls: %u\tfailed: %u ]\n",
+           fqst->fcls_flow_control, fqst->fcls_flow_feedback,
+           fqst->fcls_dequeue_stall, fqst->fcls_flow_control_fail);
+       printf("     [ drop overflow: %llu\tearly: %llu\tmemfail: %u\tduprexmt:%u ]\n",
+           fqst->fcls_drop_overflow, fqst->fcls_drop_early,
+           fqst->fcls_drop_memfailure, fqst->fcls_dup_rexmts);
+       printf("     [ flows total: %u\tnew: %u\told: %u ]\n",
+           fqst->fcls_flows_cnt,
+           fqst->fcls_newflows_cnt, fqst->fcls_oldflows_cnt);
+       printf("     [ queued pkts: %llu\tbytes: %llu ]\n",
+           fqst->fcls_pkt_cnt, fqst->fcls_byte_cnt);
+       printf("     [ dequeued pkts: %llu\tbytes: %llu ]\n",
+           fqst->fcls_dequeue, fqst->fcls_dequeue_bytes);
+       printf("     [ throttle on: %u\toff: %u\tdrop: %u ]\n",
+           fqst->fcls_throttle_on, fqst->fcls_throttle_off,
+           fqst->fcls_throttle_drops);
+       printf("=====================================================\n");
+}
+
 static void
 print_sfbstats(struct sfb_stats *sfb)
 {
@@ -1808,6 +1847,10 @@ update_avg(struct if_ifclassq_stats *ifcqs, struct queue_stats *qs)
                b = ifcqs->ifqs_qfq_stats.xmitcnt.bytes;
                p = ifcqs->ifqs_qfq_stats.xmitcnt.packets;
                break;
+       case PKTSCHEDT_FQ_CODEL:
+               b = ifcqs->ifqs_fq_codel_stats.fcls_dequeue_bytes;
+               p = ifcqs->ifqs_fq_codel_stats.fcls_dequeue;
+               break;
        default:
                b = 0;
                p = 0;
@@ -1868,8 +1911,8 @@ qtype2str(classq_type_t t)
 }
 
 #define NSEC_PER_SEC    1000000000      /* nanoseconds per second */
-#define USEC_PER_SEC    1000000                /* nanoseconds per second */
-#define MSEC_PER_SEC    1000           /* nanoseconds per second */
+#define USEC_PER_SEC    1000000                /* microseconds per second */
+#define MSEC_PER_SEC    1000           /* milliseconds per second */
 
 static char *
 nsec_to_str(unsigned long long nsec)
@@ -1923,6 +1966,9 @@ sched2str(unsigned int s)
        case PKTSCHEDT_QFQ:
                c = "QFQ";
                break;
+       case PKTSCHEDT_FQ_CODEL:
+               c = "FQ_CODEL";
+               break;
        default:
                c = "UNKNOWN";
                break;
@@ -2007,6 +2053,48 @@ tcqslot2str(unsigned int s)
        return (c);
 }
 
+static char *
+pri2str(unsigned int i)
+{
+       char *c;
+       switch (i) {
+       case 9:
+               c = "BK_SYS";
+               break;
+       case 8:
+               c = "BK";
+               break;
+       case 7:
+               c = "BE";
+               break;
+       case 6:
+               c = "RD";
+               break;
+       case 5:
+               c = "OAM";
+               break;
+       case 4:
+               c = "AV";
+               break;
+       case 3:
+               c = "RV";
+               break;
+       case 2:
+               c = "VI";
+               break;
+       case 1:
+               c = "VO";
+               break;
+       case 0:
+               c = "CTL";
+               break;
+       default:
+               c = "?";
+               break;
+       }
+       return (c);
+}
+
 static char *
 qstate2str(unsigned int s)
 {
@@ -2295,8 +2383,8 @@ rem_nstat_src(int fd, nstat_src_ref_t sref)
        }
 
        if (remrsp->srcref != sref) {
-               fprintf(stderr, "%s: received invalid srcref, received %u "
-                       "expected %u\n", __func__, remrsp->srcref, sref);
+               fprintf(stderr, "%s: received invalid srcref, received %llu "
+                       "expected %llu\n", __func__, remrsp->srcref, sref);
        }
        return 0;
 }
@@ -2352,7 +2440,7 @@ get_src_decsription(int fd, nstat_src_ref_t srcref,
        if (drsp->srcref != srcref)
        {
                fprintf(stderr, "%s: received message for wrong source, "
-                       "received 0x%x expected 0x%x\n",
+                       "received 0x%llx expected 0x%llx\n",
                        __func__, drsp->srcref, srcref);
                return -1;
        }
@@ -2427,7 +2515,7 @@ print_wifi_status(nstat_ifnet_desc_wifi_status *status)
 static void
 print_cellular_status(nstat_ifnet_desc_cellular_status *status)
 {
-       int tmp;
+       int tmp, tmp_mss;
 #define val(x, f)      \
        ((status->valid_bitmask & NSTAT_IFNET_DESC_CELL_ ## f ## _VALID) ?\
         status->x : -1)
@@ -2439,6 +2527,12 @@ print_cellular_status(nstat_ifnet_desc_cellular_status *status)
        ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_MEDIUM) ? "(medium)" : \
        ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_HIGH) ? "(high)" : \
        "(?)")))))
+#define pretxtm(n, un) \
+       (((tmp_mss = val(n,un)) == -1) ? "(not valid)" : \
+       ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_NONE) ? "(none)" : \
+       ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_MEDIUM) ? "(medium)" : \
+       ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_LOW) ? "(low)" : \
+       "(?)"))))
 
        printf("\ncellular status:\n");
        printf(
@@ -2456,7 +2550,8 @@ print_cellular_status(nstat_ifnet_desc_cellular_status *status)
            "\t%s:\t%d\n"
            "\t%s:\t%d\n"
            "\t%s:\t%d\n"
-           "\t%s:\t%d\n",
+           "\t%s:\t%d\n"
+           "\t%s:\t%d %s\n",
            parg(link_quality_metric, LINK_QUALITY_METRIC),
            parg(ul_effective_bandwidth, UL_EFFECTIVE_BANDWIDTH),
            parg(ul_max_bandwidth, UL_MAX_BANDWIDTH),
@@ -2472,7 +2567,9 @@ print_cellular_status(nstat_ifnet_desc_cellular_status *status)
            parg(dl_effective_bandwidth, DL_EFFECTIVE_BANDWIDTH),
            parg(dl_max_bandwidth, DL_MAX_BANDWIDTH),
            parg(config_inactivity_time, CONFIG_INACTIVITY_TIME),
-           parg(config_backoff_time, CONFIG_BACKOFF_TIME)
+           parg(config_backoff_time, CONFIG_BACKOFF_TIME),
+           parg(mss_recommended, MSS_RECOMMENDED),
+           pretxtm(mss_recommended, MSS_RECOMMENDED)
            );
 #undef pretxtl
 #undef parg
index 47eeaea9c86efc7ab9489e28a34acc245bf466cf..d614aecd6dc791c0fdd2e147fb6cc5fcca80f8d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -697,6 +697,9 @@ tcp_stats(uint32_t off , char *name, int af)
        p(tcps_ecn_conn_plnoce, "\t\t%u connection%s using ECN have seen packet loss but no CE\n");
        p(tcps_ecn_conn_pl_ce, "\t\t%u connection%s using ECN have seen packet loss and CE\n");
        p(tcps_ecn_conn_nopl_ce, "\t\t%u connection%s using ECN received CE but no packet loss\n");
+       p(tcps_ecn_fallback_synloss, "\t\t%u connection%s fell back to non-ECN due to SYN-loss\n");
+       p(tcps_ecn_fallback_reorder, "\t\t%u connection%s fell back to non-ECN due to reordering\n");
+       p(tcps_ecn_fallback_ce, "\t\t%u connection%s fell back to non-ECN due to excessive CE-markings\n");
        p(tcps_detect_reordering, "\t%u time%s packet reordering was detected on a connection\n");
        p(tcps_reordered_pkts, "\t\t%u time%s transmitted packets were reordered\n");
        p(tcps_delay_recovery, "\t\t%u time%s fast recovery was delayed to handle reordering\n");
@@ -721,6 +724,9 @@ tcp_stats(uint32_t off , char *name, int af)
        p(tcps_tfo_syn_data_acked,"\t\t%u time%s our SYN with data has been acknowledged\n");
        p(tcps_tfo_syn_loss,"\t%u time%s a connection-attempt with TFO fell back to regular TCP\n");
        p(tcps_tfo_blackhole,"\t%u time%s a TFO-connection blackhole'd\n");
+       p(tcps_mss_to_default,"\t%u time%s maximum segment size was changed to default\n");
+       p(tcps_mss_to_medium,"\t%u time%s maximum segment size was changed to medium\n");
+       p(tcps_mss_to_low,"\t%u time%s maximum segment size was changed to low\n");
 
        if (interval > 0) {
                bcopy(&tcpstat, &ptcpstat, len);
@@ -791,10 +797,10 @@ mptcp_stats(uint32_t off , char *name, int af)
        p(tcps_mp_badcsum, "\t%u bad DSS checksum%s\n");
        p(tcps_mp_oodata, "\t%u time%s received out of order data \n");
        p3(tcps_mp_switches, "\t%u subflow switch%s\n");
-       p3(tcps_mp_sel_symtomsd, "\t%u subflow switche%s due to advisory\n");
-       p3(tcps_mp_sel_rtt, "\t%u subflow switche%s due to rtt\n");
-       p3(tcps_mp_sel_rto, "\t%u subflow switche%s due to rto\n");
-       p3(tcps_mp_sel_peer, "\t%u subflow switche%s due to peer\n");
+       p3(tcps_mp_sel_symtomsd, "\t%u subflow switch%s due to advisory\n");
+       p3(tcps_mp_sel_rtt, "\t%u subflow switch%s due to rtt\n");
+       p3(tcps_mp_sel_rto, "\t%u subflow switch%s due to rto\n");
+       p3(tcps_mp_sel_peer, "\t%u subflow switch%s due to peer\n");
        p3(tcps_mp_num_probes, "\t%u number of subflow probe%s\n");
 
        if (interval > 0) {
@@ -1079,8 +1085,11 @@ arp_stats(uint32_t off, char *name, int af)
     printf(m, ARPDIFF(f), plural(ARPDIFF(f)))
 #define        p2(f, m) if (ARPDIFF(f) || sflag <= 1) \
     printf(m, ARPDIFF(f), pluralies(ARPDIFF(f)))
+#define        p3(f, m) if (ARPDIFF(f) || sflag <= 1) \
+    printf(m, ARPDIFF(f), plural(ARPDIFF(f)), pluralies(ARPDIFF(f)))
 
-       p(txrequests, "\t%u ARP request%s sent\n");
+       p(txrequests, "\t%u broadast ARP request%s sent\n");
+       p(txurequests, "\t%u unicast ARP request%s sent\n");
        p2(txreplies, "\t%u ARP repl%s sent\n");
        p(txannounces, "\t%u ARP announcement%s sent\n");
        p(rxrequests, "\t%u ARP request%s received\n");
@@ -1089,6 +1098,7 @@ arp_stats(uint32_t off, char *name, int af)
        p(txconflicts, "\t%u ARP conflict probe%s sent\n");
        p(invalidreqs, "\t%u invalid ARP resolve request%s\n");
        p(reqnobufs, "\t%u total packet%s dropped due to lack of memory\n");
+       p3(held, "\t%u total packet%s held awaiting ARP repl%s\n");
        p(dropped, "\t%u total packet%s dropped due to no ARP entry\n");
        p(purged, "\t%u total packet%s dropped during ARP entry removal\n");
        p2(timeouts, "\t%u ARP entr%s timed out\n");
index a741196571c1c58d8cc0c8d0ffd8dc657268c6cd..6e81df7d1581edeeaa7cf71f9e2042623fe1a49a 100644 (file)
@@ -436,6 +436,7 @@ ip6_stats(uint32_t off __unused, char *name, int af __unused)
        p1a(ip6s_fragtimeout, "\t\t\t%llu dropped after timeout\n");
        p1a(ip6s_fragoverflow, "\t\t\t%llu exceeded limit\n");
        p1a(ip6s_reassembled, "\t\t\t%llu reassembled ok\n");
+       p1a(ip6s_atmfrag_rcvd, "\t\t\t%llu atomic fragments received\n");
        p(ip6s_delivered, "\t\t%llu packet%s for this host\n");
        p(ip6s_forward, "\t\t%llu packet%s forwarded\n");
        p(ip6s_cantforward, "\t\t%llu packet%s not forwardable\n");
@@ -616,7 +617,7 @@ ip6_stats(uint32_t off __unused, char *name, int af __unused)
        for (first = 1, i = 0; i < IP6S_SRCRULE_COUNT; i++) {
                if (IP6DIFF(ip6s_sources_rule[i]) || 1) {
                        if (first) {
-                               printf("\t\tsource addresse selection\n");
+                               printf("\t\tsource address selection\n");
                                first = 0;
                        }
                        PRINT_SRCRULESTAT(ip6s_sources_rule[i], i);
@@ -624,8 +625,10 @@ ip6_stats(uint32_t off __unused, char *name, int af __unused)
        }
        
        p(ip6s_dad_collide, "\t\t%llu duplicate address detection collision%s\n");
+       
+       p(ip6s_dad_loopcount, "\t\t%llu duplicate address detection NS loop%s\n");
 
-       p(ip6s_sources_skip_expensive_secondary_if, "\t\t%llu times%s ignored source on secondary expensive I/F\n");
+       p(ip6s_sources_skip_expensive_secondary_if, "\t\t%llu time%s ignored source on secondary expensive I/F\n");
 
        if (interval > 0) {
                bcopy(&ip6stat, &pip6stat, len);
@@ -684,6 +687,7 @@ ip6_ifstats(char *ifname)
        p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n");
        p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
        p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
+       p(ifs6_atmfrag_rcvd, "\t%llu atomic fragments%s received\n");
        p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n");
        p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
        p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
@@ -1039,6 +1043,7 @@ icmp6_stats(uint32_t off __unused, char *name, int af __unused)
        p(icp6s_badra, "\t%qu bad router advertisement message%s\n");
        p(icp6s_badredirect, "\t%qu bad redirect message%s\n");
        p(icp6s_pmtuchg, "\t%llu path MTU change%s\n");
+       p(icp6s_rfc6980_drop, "\t%qu dropped fragmented NDP message%s\n");
 
        if (interval > 0)
                bcopy(&icmp6stat, &picmp6stat, len);
@@ -1145,7 +1150,7 @@ rip6_stats(uint32_t off __unused, char *name, int af __unused)
 #define        p(f, m) if (RIP6DIFF(f) || sflag <= 1) \
     printf(m, (unsigned long long)RIP6DIFF(f), plural(RIP6DIFF(f)))
        p(rip6s_ipackets, "\t%llu message%s received\n");
-       p(rip6s_isum, "\t%llu checksum calcuration%s on inbound\n");
+       p(rip6s_isum, "\t%llu checksum calculation%s on inbound\n");
        p(rip6s_badsum, "\t%llu message%s with bad checksum\n");
        p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n");
        p(rip6s_nosockmcast,
@@ -1208,7 +1213,7 @@ inet6print(struct in6_addr *in6, int port, char *proto, int numeric)
        if (!numeric && port)
                GETSERVBYPORT6(port, proto, sp);
        if (sp || port == 0)
-               snprintf(cp, sizeof(line) - (cp - line), "%.8s", sp ? sp->s_name : "*");
+               snprintf(cp, sizeof(line) - (cp - line), "%.15s", sp ? sp->s_name : "*");
        else
                snprintf(cp, sizeof(line) - (cp - line), "%d", ntohs((u_short)port));
        width = lflag ? 45 : Aflag ? 18 : 22;
index 4d6977070d5345da2b8fabbab4400a78849c8251..b3e13ffc0f80db477716fcde80d2d4f854219c76 100644 (file)
@@ -57,7 +57,7 @@ static const char *tcpstates[] = {
 
 static const char *mptcpstates[] = {
        "CLOSED", "LISTEN", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1",
-       "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", "FASTCLOSE_WAIT"
+       "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", "TERMINATE"
 };
 
 int mptcp_done = 0;
index a3c170e1caeb60b6de059640611cde94ac5b7560..d94dec0c49b6e11c716d7df08f3b015156abca46 100644 (file)
@@ -377,7 +377,7 @@ kevt_stats(uint32_t off __unused, char *name, int af __unused)
 {
        static struct kevtstat pkevtstat;
        struct kevtstat kevtstat;
-       size_t len = sizeof(struct kctlstat);
+       size_t len = sizeof(struct kevtstat);
        const char *mibvar = "net.systm.kevt.stats";
        
        if (sysctlbyname(mibvar, &kevtstat, &len, 0, 0) < 0) {
index 215480947e68b852e4d3d3f17f8852551d5f53f9..2c7b2efcd141bc4bd4312e5b73fe0b5b04c21fdf 100644 (file)
@@ -86,7 +86,7 @@ static        void unixdomainpr __P((struct xunpcb *, struct xsocket *));
 #endif
 
 static const char *const socktype[] =
-    { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
+    { "#0", "stream", "dgram", "raw" };
 
 void
 unixpr()
@@ -105,7 +105,7 @@ unixpr()
        char mibvar[sizeof "net.local.seqpacket.pcblist"];
 #endif
 
-       for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
+       for (type = SOCK_STREAM; type <= SOCK_RAW; type++) {
 #if !TARGET_OS_EMBEDDED
                snprintf(mibvar, sizeof(mibvar), "net.local.%s.pcblist64", socktype[type]);
 #else
index d7b9d4c1753aeba5f1fc6b5df6dc43b1e7abb8b6..511810c66a3585140f8b3eb0c63ce89f7bb2359a 100755 (executable)
@@ -17,6 +17,7 @@
                                72B732EB1899B19A0060E6D4 /* PBXTargetDependency */,
                                72179EAE146233390098FB3E /* PBXTargetDependency */,
                                7282BA571AFBDEAD005DE836 /* PBXTargetDependency */,
+                               72946F4C1BBF063800087E35 /* PBXTargetDependency */,
                                034E4469100BDD00009CA3DC /* PBXTargetDependency */,
                                565825AF13392239003E5FA5 /* PBXTargetDependency */,
                                72311F4D194A34F500EB4788 /* PBXTargetDependency */,
@@ -46,6 +47,7 @@
                                72B732E91899B18F0060E6D4 /* PBXTargetDependency */,
                                723C7074142BB003007C87E9 /* PBXTargetDependency */,
                                7282BA5B1AFBDED3005DE836 /* PBXTargetDependency */,
+                               7263724B1BCC709900E4B026 /* PBXTargetDependency */,
                                7261217D0EE8896800AFED1B /* PBXTargetDependency */,
                                4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */,
                                724DABC30EE890A6008900D0 /* PBXTargetDependency */,
@@ -79,6 +81,7 @@
                                72ABD0A41083D818008C721C /* PBXTargetDependency */,
                                72ABD0881083D750008C721C /* PBXTargetDependency */,
                                7282BA591AFBDEC2005DE836 /* PBXTargetDependency */,
+                               72946F4E1BBF063F00087E35 /* PBXTargetDependency */,
                                565825B113392242003E5FA5 /* PBXTargetDependency */,
                                72311F4F194A34FE00EB4788 /* PBXTargetDependency */,
                                690D97BA12DE7130004323A7 /* PBXTargetDependency */,
                72311F55194A354F00EB4788 /* mptcp_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72311F53194A354F00EB4788 /* mptcp_client.c */; };
                72311F56194A76DA00EB4788 /* mptcp_client.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72311F52194A354F00EB4788 /* mptcp_client.1 */; };
                724753E7144905E300F6A941 /* dnctl.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 724753E61448E1EF00F6A941 /* dnctl.8 */; };
+               724769371CE2B1FF00AAB5F0 /* gmt2local.c in Sources */ = {isa = PBXBuildFile; fileRef = 7282BA3C1AFAD58E005DE836 /* gmt2local.c */; };
+               724769381CE2C1E400AAB5F0 /* gmt2local.c in Sources */ = {isa = PBXBuildFile; fileRef = 7282BA3C1AFAD58E005DE836 /* gmt2local.c */; };
                7247B83616165EDC00873B3C /* pktapctl.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7247B83516165EDC00873B3C /* pktapctl.8 */; };
                7247B83C16165F0100873B3C /* pktapctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 7247B83B16165F0100873B3C /* pktapctl.c */; };
-               724DAB640EE88E63008900D0 /* ipfw2.c in Sources */ = {isa = PBXBuildFile; fileRef = 726121000EE8701100AFED1B /* ipfw2.c */; };
-               724DAB680EE88E78008900D0 /* ipfw.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120FF0EE8701100AFED1B /* ipfw.8 */; };
-               724DAB860EE88F0D008900D0 /* ip6fw.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120690EE86F2300AFED1B /* ip6fw.c */; };
-               724DAB8A0EE88F24008900D0 /* ip6fw.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120680EE86F2300AFED1B /* ip6fw.8 */; };
                724DABA60EE88FED008900D0 /* kdumpd.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120710EE86F2D00AFED1B /* kdumpd.c */; };
                724DABA70EE88FED008900D0 /* kdumpsubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120720EE86F2D00AFED1B /* kdumpsubs.c */; };
                724DABAB0EE89006008900D0 /* kdumpd.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120700EE86F2D00AFED1B /* kdumpd.8 */; };
                7282BA521AFAD58E005DE836 /* session.c in Sources */ = {isa = PBXBuildFile; fileRef = 7282BA451AFAD58E005DE836 /* session.c */; };
                7282BA531AFAD58E005DE836 /* support.c in Sources */ = {isa = PBXBuildFile; fileRef = 7282BA471AFAD58E005DE836 /* support.c */; };
                7282BA551AFBCA66005DE836 /* libpcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7282BA541AFBCA66005DE836 /* libpcap.dylib */; };
+               72946F501BBF07FF00087E35 /* frame_delay.c in Sources */ = {isa = PBXBuildFile; fileRef = 72946F4F1BBF07FF00087E35 /* frame_delay.c */; };
                7294F0DF0EE8BA730052EC88 /* spray.x in Sources */ = {isa = PBXBuildFile; fileRef = 726120E10EE86F9D00AFED1B /* spray.x */; };
                7294F1000EE8BB990052EC88 /* as.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120E50EE86FA700AFED1B /* as.c */; };
                7294F1010EE8BB990052EC88 /* findsaddr-socket.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120E70EE86FA700AFED1B /* findsaddr-socket.c */; };
                        remoteGlobalIDString = 726121530EE8881700AFED1B;
                        remoteInfo = ifconfig;
                };
+               7263724A1BCC709900E4B026 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 72946F421BBF055700087E35;
+                       remoteInfo = frame_delay;
+               };
                7282BA561AFBDEAD005DE836 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
                        remoteGlobalIDString = 7282BA0B1AFAD4C9005DE836;
                        remoteInfo = ecnprobe;
                };
+               72946F4B1BBF063800087E35 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 72946F421BBF055700087E35;
+                       remoteInfo = frame_delay;
+               };
+               72946F4D1BBF063F00087E35 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 72946F421BBF055700087E35;
+                       remoteInfo = frame_delay;
+               };
                7294F0E90EE8BAC80052EC88 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
-               724DAB760EE88E9C008900D0 /* CopyFiles */ = {
-                       isa = PBXCopyFilesBuildPhase;
-                       buildActionMask = 8;
-                       dstPath = /usr/share/man/man8;
-                       dstSubfolderSpec = 0;
-                       files = (
-                               724DAB680EE88E78008900D0 /* ipfw.8 in CopyFiles */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 1;
-               };
-               724DAB970EE88F56008900D0 /* CopyFiles */ = {
-                       isa = PBXCopyFilesBuildPhase;
-                       buildActionMask = 8;
-                       dstPath = /usr/share/man/man8;
-                       dstSubfolderSpec = 0;
-                       files = (
-                               724DAB8A0EE88F24008900D0 /* ip6fw.8 in CopyFiles */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 1;
-               };
                724DABB70EE89035008900D0 /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
+               72946F411BBF055700087E35 /* CopyFiles */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = /usr/share/man/man1/;
+                       dstSubfolderSpec = 0;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
                7294F11A0EE8BC0C0052EC88 /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
                7247B83116165EDC00873B3C /* pktapctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pktapctl; sourceTree = BUILT_PRODUCTS_DIR; };
                7247B83516165EDC00873B3C /* pktapctl.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = pktapctl.8; sourceTree = "<group>"; };
                7247B83B16165F0100873B3C /* pktapctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pktapctl.c; sourceTree = "<group>"; };
-               724DAB5F0EE88E2A008900D0 /* ipfw */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ipfw; sourceTree = BUILT_PRODUCTS_DIR; };
-               724DAB820EE88EFA008900D0 /* ip6fw */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ip6fw; sourceTree = BUILT_PRODUCTS_DIR; };
                724DABA20EE88FE3008900D0 /* kdumpd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = kdumpd; sourceTree = BUILT_PRODUCTS_DIR; };
                724DABDB0EE8912D008900D0 /* natd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = natd; sourceTree = BUILT_PRODUCTS_DIR; };
                724DAC0D0EE8940D008900D0 /* ndp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ndp; sourceTree = BUILT_PRODUCTS_DIR; };
                726120580EE86F0900AFED1B /* ifconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ifconfig.h; sourceTree = "<group>"; };
                726120590EE86F0900AFED1B /* ifmedia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifmedia.c; sourceTree = "<group>"; };
                7261205A0EE86F0900AFED1B /* ifvlan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifvlan.c; sourceTree = "<group>"; };
-               726120680EE86F2300AFED1B /* ip6fw.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6fw.8; sourceTree = "<group>"; };
-               726120690EE86F2300AFED1B /* ip6fw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ip6fw.c; sourceTree = "<group>"; };
                7261206E0EE86F2D00AFED1B /* com.apple.kdumpd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.kdumpd.plist; sourceTree = "<group>"; };
                7261206F0EE86F2D00AFED1B /* kdump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kdump.h; sourceTree = "<group>"; };
                726120700EE86F2D00AFED1B /* kdumpd.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = kdumpd.8; sourceTree = "<group>"; };
                7261209B0EE86F4800AFED1B /* unix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unix.c; sourceTree = "<group>"; };
                726120A00EE86F5000AFED1B /* ping.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ping.8; sourceTree = "<group>"; };
                726120A10EE86F5000AFED1B /* ping.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ping.c; sourceTree = "<group>"; };
-               726120A50EE86F5C00AFED1B /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
                726120A60EE86F5C00AFED1B /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = md5.c; sourceTree = "<group>"; };
                726120A70EE86F5C00AFED1B /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = "<group>"; };
                726120A80EE86F5C00AFED1B /* ping6.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ping6.8; sourceTree = "<group>"; };
                726120F10EE86FA700AFED1B /* traceroute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = traceroute.c; sourceTree = "<group>"; };
                726120F20EE86FA700AFED1B /* traceroute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = traceroute.h; sourceTree = "<group>"; };
                726120F30EE86FA700AFED1B /* version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = version.c; sourceTree = "<group>"; };
-               726120F90EE86FB500AFED1B /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
                726120FA0EE86FB500AFED1B /* traceroute6.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = traceroute6.8; sourceTree = "<group>"; };
                726120FB0EE86FB500AFED1B /* traceroute6.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = traceroute6.c; sourceTree = "<group>"; };
-               726120FF0EE8701100AFED1B /* ipfw.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ipfw.8; sourceTree = "<group>"; };
-               726121000EE8701100AFED1B /* ipfw2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ipfw2.c; sourceTree = "<group>"; };
                7261210C0EE8707500AFED1B /* libalias.A.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libalias.A.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
                726121220EE870D400AFED1B /* alias_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alias_local.h; sourceTree = "<group>"; };
                726121230EE870D400AFED1B /* alias.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alias.h; sourceTree = "<group>"; };
                726121240EE870D400AFED1B /* libalias.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = libalias.3; sourceTree = "<group>"; };
                7261212D0EE8710B00AFED1B /* arp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = arp; sourceTree = BUILT_PRODUCTS_DIR; };
                726121540EE8881700AFED1B /* ifconfig */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ifconfig; sourceTree = BUILT_PRODUCTS_DIR; };
+               7263724C1BCC718B00E4B026 /* frame_delay.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = frame_delay.8; sourceTree = "<group>"; };
                7282BA0C1AFAD4C9005DE836 /* ecnprobe */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ecnprobe; sourceTree = BUILT_PRODUCTS_DIR; };
                7282BA341AFAD58E005DE836 /* base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base.h; sourceTree = "<group>"; };
                7282BA351AFAD58E005DE836 /* capture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = capture.c; sourceTree = "<group>"; };
                7282BA481AFAD58E005DE836 /* support.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = support.h; sourceTree = "<group>"; };
                7282BA541AFBCA66005DE836 /* libpcap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpcap.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib/libpcap.dylib; sourceTree = DEVELOPER_DIR; };
                7282BA5C1AFBED07005DE836 /* ecnprobe.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = ecnprobe.1; sourceTree = "<group>"; };
+               72946F431BBF055700087E35 /* frame_delay */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = frame_delay; sourceTree = BUILT_PRODUCTS_DIR; };
+               72946F4F1BBF07FF00087E35 /* frame_delay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = frame_delay.c; sourceTree = "<group>"; };
                7294F0F90EE8BB460052EC88 /* traceroute */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = traceroute; sourceTree = BUILT_PRODUCTS_DIR; };
                7294F12A0EE8BD280052EC88 /* traceroute6 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = traceroute6; sourceTree = BUILT_PRODUCTS_DIR; };
                72B732DA1899B0380060E6D4 /* cfilutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cfilutil; sourceTree = BUILT_PRODUCTS_DIR; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               724DAB5D0EE88E2A008900D0 /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               724DAB800EE88EFA008900D0 /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                724DABA00EE88FE3008900D0 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               72946F401BBF055700087E35 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                7294F0F70EE8BB460052EC88 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                72B732DB1899B0380060E6D4 /* cfilutil */,
                                723C706A142BAFEA007C87E9 /* dnctl */,
                                7282BA0D1AFAD4C9005DE836 /* ecnprobe */,
+                               72946F441BBF055700087E35 /* frame_delay */,
                                726120540EE86F0900AFED1B /* ifconfig.tproj */,
                                4D2B04E31208C12F0004A3F3 /* ip6addrctl.tproj */,
-                               726120670EE86F2300AFED1B /* ip6fw.tproj */,
-                               726120FE0EE8701100AFED1B /* ipfw.tproj */,
                                7261206D0EE86F2D00AFED1B /* kdumpd.tproj */,
                                56582591133920B5003E5FA5 /* mnc.tproj */,
                                72311F43194A349100EB4788 /* mptcp_client */,
                        path = ifconfig.tproj;
                        sourceTree = "<group>";
                };
-               726120670EE86F2300AFED1B /* ip6fw.tproj */ = {
-                       isa = PBXGroup;
-                       children = (
-                               726120680EE86F2300AFED1B /* ip6fw.8 */,
-                               726120690EE86F2300AFED1B /* ip6fw.c */,
-                       );
-                       path = ip6fw.tproj;
-                       sourceTree = "<group>";
-               };
                7261206D0EE86F2D00AFED1B /* kdumpd.tproj */ = {
                        isa = PBXGroup;
                        children = (
                726120A40EE86F5C00AFED1B /* ping6.tproj */ = {
                        isa = PBXGroup;
                        children = (
-                               726120A50EE86F5C00AFED1B /* Makefile */,
                                726120A60EE86F5C00AFED1B /* md5.c */,
                                726120A70EE86F5C00AFED1B /* md5.h */,
                                726120A80EE86F5C00AFED1B /* ping6.8 */,
                726120F80EE86FB500AFED1B /* traceroute6.tproj */ = {
                        isa = PBXGroup;
                        children = (
-                               726120F90EE86FB500AFED1B /* Makefile */,
                                726120FA0EE86FB500AFED1B /* traceroute6.8 */,
                                726120FB0EE86FB500AFED1B /* traceroute6.c */,
                        );
                        path = traceroute6.tproj;
                        sourceTree = "<group>";
                };
-               726120FE0EE8701100AFED1B /* ipfw.tproj */ = {
-                       isa = PBXGroup;
-                       children = (
-                               726120FF0EE8701100AFED1B /* ipfw.8 */,
-                               726121000EE8701100AFED1B /* ipfw2.c */,
-                       );
-                       path = ipfw.tproj;
-                       sourceTree = "<group>";
-               };
                7261210D0EE8707500AFED1B /* Products */ = {
                        isa = PBXGroup;
                        children = (
                                7261210C0EE8707500AFED1B /* libalias.A.dylib */,
                                7261212D0EE8710B00AFED1B /* arp */,
                                726121540EE8881700AFED1B /* ifconfig */,
-                               724DAB5F0EE88E2A008900D0 /* ipfw */,
-                               724DAB820EE88EFA008900D0 /* ip6fw */,
                                724DABA20EE88FE3008900D0 /* kdumpd */,
                                724DABDB0EE8912D008900D0 /* natd */,
                                724DAC0D0EE8940D008900D0 /* ndp */,
                                7200F2FA1958A34D0033E22C /* pktmnglr */,
                                713297681A93C743002359CF /* unbound */,
                                7282BA0C1AFAD4C9005DE836 /* ecnprobe */,
+                               72946F431BBF055700087E35 /* frame_delay */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                        path = ecnprobe;
                        sourceTree = "<group>";
                };
+               72946F441BBF055700087E35 /* frame_delay */ = {
+                       isa = PBXGroup;
+                       children = (
+                               72946F4F1BBF07FF00087E35 /* frame_delay.c */,
+                               7263724C1BCC718B00E4B026 /* frame_delay.8 */,
+                       );
+                       path = frame_delay;
+                       sourceTree = "<group>";
+               };
                72B732DB1899B0380060E6D4 /* cfilutil */ = {
                        isa = PBXGroup;
                        children = (
                        productReference = 7247B83116165EDC00873B3C /* pktapctl */;
                        productType = "com.apple.product-type.tool";
                };
-               724DAB5E0EE88E2A008900D0 /* ipfw */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 724DAB770EE88E9C008900D0 /* Build configuration list for PBXNativeTarget "ipfw" */;
-                       buildPhases = (
-                               724DAB5C0EE88E2A008900D0 /* Sources */,
-                               724DAB5D0EE88E2A008900D0 /* Frameworks */,
-                               724DAB760EE88E9C008900D0 /* CopyFiles */,
-                               72CD1DB00EE8C551005F825D /* ShellScript */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = ipfw;
-                       productName = ipfw;
-                       productReference = 724DAB5F0EE88E2A008900D0 /* ipfw */;
-                       productType = "com.apple.product-type.tool";
-               };
-               724DAB810EE88EFA008900D0 /* ip6fw */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = 724DAB980EE88F56008900D0 /* Build configuration list for PBXNativeTarget "ip6fw" */;
-                       buildPhases = (
-                               724DAB7F0EE88EFA008900D0 /* Sources */,
-                               724DAB800EE88EFA008900D0 /* Frameworks */,
-                               724DAB970EE88F56008900D0 /* CopyFiles */,
-                               724DAC1B0EE89440008900D0 /* ShellScript */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = ip6fw;
-                       productName = ip6fw;
-                       productReference = 724DAB820EE88EFA008900D0 /* ip6fw */;
-                       productType = "com.apple.product-type.tool";
-               };
                724DABA10EE88FE3008900D0 /* kdumpd */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = 724DABB80EE89035008900D0 /* Build configuration list for PBXNativeTarget "kdumpd" */;
                        productReference = 7282BA0C1AFAD4C9005DE836 /* ecnprobe */;
                        productType = "com.apple.product-type.tool";
                };
+               72946F421BBF055700087E35 /* frame_delay */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 72946F4A1BBF055700087E35 /* Build configuration list for PBXNativeTarget "frame_delay" */;
+                       buildPhases = (
+                               72946F3F1BBF055700087E35 /* Sources */,
+                               72946F401BBF055700087E35 /* Frameworks */,
+                               72946F411BBF055700087E35 /* CopyFiles */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = frame_delay;
+                       productName = frame_delay;
+                       productReference = 72946F431BBF055700087E35 /* frame_delay */;
+                       productType = "com.apple.product-type.tool";
+               };
                7294F0F80EE8BB460052EC88 /* traceroute */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = 7294F0FD0EE8BB550052EC88 /* Build configuration list for PBXNativeTarget "traceroute" */;
                724862310EE86EB7001D0DE9 /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0500;
+                               LastUpgradeCheck = 0800;
                                TargetAttributes = {
                                        713297671A93C743002359CF = {
                                                CreatedOnToolsVersion = 6.3;
                                        7282BA0B1AFAD4C9005DE836 = {
                                                CreatedOnToolsVersion = 7.0;
                                        };
+                                       72946F421BBF055700087E35 = {
+                                               CreatedOnToolsVersion = 6.3;
+                                       };
                                };
                        };
                        buildConfigurationList = 724862340EE86EB7001D0DE9 /* Build configuration list for PBXProject "network_cmds" */;
                                72B732D91899B0380060E6D4 /* cfilutil */,
                                723C7067142BAFEA007C87E9 /* dnctl */,
                                7282BA0B1AFAD4C9005DE836 /* ecnprobe */,
+                               72946F421BBF055700087E35 /* frame_delay */,
                                726121530EE8881700AFED1B /* ifconfig */,
                                4D2B04F21208C2040004A3F3 /* ip6addrctl */,
-                               724DAB810EE88EFA008900D0 /* ip6fw */,
-                               724DAB5E0EE88E2A008900D0 /* ipfw */,
                                724DABA10EE88FE3008900D0 /* kdumpd */,
                                5658259E1339218F003E5FA5 /* mnc */,
                                72311F41194A349000EB4788 /* mptcp_client */,
                        shellPath = /bin/sh;
                        shellScript = "/bin/chmod 0444 $DSTROOT/usr/share/man/man8/natd.8\t";
                };
-               724DAC1B0EE89440008900D0 /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 8;
-                       files = (
-                       );
-                       inputPaths = (
-                       );
-                       outputPaths = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 1;
-                       shellPath = /bin/sh;
-                       shellScript = "/bin/chmod 0444 $DSTROOT/usr/share/man/man8/ip6fw.8\t";
-               };
                724DAC440EE89562008900D0 /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 8;
                        shellPath = /bin/sh;
                        shellScript = "/bin/chmod 0444 $DSTROOT/usr/share/man/man8/ifconfig.8\t";
                };
-               72CD1DB00EE8C551005F825D /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 8;
-                       files = (
-                       );
-                       inputPaths = (
-                       );
-                       outputPaths = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 1;
-                       shellPath = /bin/sh;
-                       shellScript = "/bin/chmod 0444 $DSTROOT/usr/share/man/man8/ipfw.8\n";
-               };
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               724769381CE2C1E400AAB5F0 /* gmt2local.c in Sources */,
                                7216D2800EE8981C00AE70E4 /* ping.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               724769371CE2B1FF00AAB5F0 /* gmt2local.c in Sources */,
                                7216D2A00EE898DF00AE70E4 /* md5.c in Sources */,
                                7216D2A10EE898DF00AE70E4 /* ping6.c in Sources */,
                        );
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               724DAB5C0EE88E2A008900D0 /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               724DAB640EE88E63008900D0 /* ipfw2.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               724DAB7F0EE88EFA008900D0 /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               724DAB860EE88F0D008900D0 /* ip6fw.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                724DAB9F0EE88FE3008900D0 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               72946F3F1BBF055700087E35 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               72946F501BBF07FF00087E35 /* frame_delay.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                7294F0F60EE8BB460052EC88 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        target = 726121530EE8881700AFED1B /* ifconfig */;
                        targetProxy = 7261217C0EE8896800AFED1B /* PBXContainerItemProxy */;
                };
+               7263724B1BCC709900E4B026 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 72946F421BBF055700087E35 /* frame_delay */;
+                       targetProxy = 7263724A1BCC709900E4B026 /* PBXContainerItemProxy */;
+               };
                7282BA571AFBDEAD005DE836 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 7282BA0B1AFAD4C9005DE836 /* ecnprobe */;
                        target = 7282BA0B1AFAD4C9005DE836 /* ecnprobe */;
                        targetProxy = 7282BA5A1AFBDED3005DE836 /* PBXContainerItemProxy */;
                };
+               72946F4C1BBF063800087E35 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 72946F421BBF055700087E35 /* frame_delay */;
+                       targetProxy = 72946F4B1BBF063800087E35 /* PBXContainerItemProxy */;
+               };
+               72946F4E1BBF063F00087E35 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 72946F421BBF055700087E35 /* frame_delay */;
+                       targetProxy = 72946F4D1BBF063F00087E35 /* PBXContainerItemProxy */;
+               };
                7294F0EA0EE8BAC80052EC88 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 7216D3A60EE8A3BA00AE70E4 /* spray */;
                        };
                        name = "Ignore Me";
                };
-               03B2DBE9100BE71D005349BC /* Ignore Me */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "$(inherited)",
-                                       IP_FW_PRIVATE,
-                               );
-                               HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
-                               INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = 0555;
-                               INSTALL_OWNER = root;
-                               INSTALL_PATH = /sbin;
-                               PRODUCT_NAME = ipfw;
-                       };
-                       name = "Ignore Me";
-               };
-               03B2DBEA100BE71D005349BC /* Ignore Me */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "$(inherited)",
-                                       IP_FW_PRIVATE,
-                               );
-                               HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
-                               INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = 0555;
-                               INSTALL_OWNER = root;
-                               INSTALL_PATH = /sbin;
-                               PRODUCT_NAME = ip6fw;
-                       };
-                       name = "Ignore Me";
-               };
                03B2DBEB100BE71D005349BC /* Ignore Me */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                INSTALL_OWNER = root;
                                INSTALL_PATH = /sbin;
                                PRODUCT_NAME = ping;
-                               SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
                        };
                        name = "Ignore Me";
                };
                                HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
                                MACOSX_DEPLOYMENT_TARGET = 10.10;
                                METAL_ENABLE_DEBUG_INFO = YES;
-                               ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                        };
                        name = Debug;
                        buildSettings = {
                                CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/network-client-server-entitlements.plist";
                                CODE_SIGN_IDENTITY = "-";
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "USE_RFC2292BIS=1",
+                                       "__APPLE_USE_RFC_3542=1",
+                                       "__APPLE_API_OBSOLETE=1",
+                                       "DEBUG=1",
+                               );
                                HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
                                INSTALL_GROUP = wheel;
                                INSTALL_MODE_FLAG = 0555;
                                INSTALL_OWNER = root;
                                INSTALL_PATH = /sbin;
                                PRODUCT_NAME = ping;
-                               SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
                        };
                        name = Debug;
                };
                                INSTALL_OWNER = root;
                                INSTALL_PATH = /sbin;
                                PRODUCT_NAME = ping;
-                               SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
                        };
                        name = Release;
                };
                                HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
                                MACOSX_DEPLOYMENT_TARGET = 10.10;
                                METAL_ENABLE_DEBUG_INFO = YES;
-                               ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                        };
                        name = Debug;
                                HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
                                MACOSX_DEPLOYMENT_TARGET = 10.10;
                                METAL_ENABLE_DEBUG_INFO = NO;
-                               ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                        };
                        name = Release;
                                HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
                                MACOSX_DEPLOYMENT_TARGET = 10.10;
                                METAL_ENABLE_DEBUG_INFO = NO;
-                               ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                        };
                        name = "Ignore Me";
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               ASSETCATALOG_COMPRESSION = lossless;
                                COPY_PHASE_STRIP = NO;
                                DEAD_CODE_STRIPPING = YES;
+                               ENABLE_TESTABILITY = YES;
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_MODEL_TUNING = G5;
                                );
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
                                GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
-                               ONLY_ACTIVE_ARCH = YES;
                                PREBINDING = NO;
                                SDKROOT = macosx.internal;
                                SUPPORTED_PLATFORMS = "macosx iphoneos";
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               ASSETCATALOG_COMPRESSION = "respect-asset-catalog";
                                COPY_PHASE_STRIP = YES;
                                DEAD_CODE_STRIPPING = YES;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                        };
                        name = Release;
                };
-               724DAB610EE88E2B008900D0 /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "$(inherited)",
-                                       IP_FW_PRIVATE,
-                               );
-                               HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
-                               INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = 0555;
-                               INSTALL_OWNER = root;
-                               INSTALL_PATH = /sbin;
-                               PRODUCT_NAME = ipfw;
-                       };
-                       name = Debug;
-               };
-               724DAB620EE88E2B008900D0 /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "$(inherited)",
-                                       IP_FW_PRIVATE,
-                               );
-                               HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
-                               INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = 0555;
-                               INSTALL_OWNER = root;
-                               INSTALL_PATH = /sbin;
-                               PRODUCT_NAME = ipfw;
-                       };
-                       name = Release;
-               };
-               724DAB840EE88EFA008900D0 /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "$(inherited)",
-                                       IP_FW_PRIVATE,
-                               );
-                               HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
-                               INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = 0555;
-                               INSTALL_OWNER = root;
-                               INSTALL_PATH = /sbin;
-                               PRODUCT_NAME = ip6fw;
-                       };
-                       name = Debug;
-               };
-               724DAB850EE88EFA008900D0 /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "$(inherited)",
-                                       IP_FW_PRIVATE,
-                               );
-                               HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
-                               INSTALL_GROUP = wheel;
-                               INSTALL_MODE_FLAG = 0555;
-                               INSTALL_OWNER = root;
-                               INSTALL_PATH = /sbin;
-                               PRODUCT_NAME = ip6fw;
-                       };
-                       name = Release;
-               };
                724DABA40EE88FE3008900D0 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = "Ignore Me";
                };
+               72946F471BBF055700087E35 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/network-client-server-entitlements.plist";
+                               CODE_SIGN_IDENTITY = "-";
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.11.xctoolchain/usr/include,
+                                       /System/Library/Frameworks/System.framework/PrivateHeaders,
+                               );
+                               MACOSX_DEPLOYMENT_TARGET = 10.10;
+                               MTL_ENABLE_DEBUG_INFO = YES;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               72946F481BBF055700087E35 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/network-client-server-entitlements.plist";
+                               CODE_SIGN_IDENTITY = "-";
+                               COPY_PHASE_STRIP = NO;
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.11.xctoolchain/usr/include,
+                                       /System/Library/Frameworks/System.framework/PrivateHeaders,
+                               );
+                               MACOSX_DEPLOYMENT_TARGET = 10.10;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               72946F491BBF055700087E35 /* Ignore Me */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/network-client-server-entitlements.plist";
+                               CODE_SIGN_IDENTITY = "-";
+                               COPY_PHASE_STRIP = NO;
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.11.xctoolchain/usr/include,
+                                       /System/Library/Frameworks/System.framework/PrivateHeaders,
+                               );
+                               MACOSX_DEPLOYMENT_TARGET = 10.10;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = "Ignore Me";
+               };
                7294F0FB0EE8BB460052EC88 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               724DAB770EE88E9C008900D0 /* Build configuration list for PBXNativeTarget "ipfw" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               724DAB610EE88E2B008900D0 /* Debug */,
-                               724DAB620EE88E2B008900D0 /* Release */,
-                               03B2DBE9100BE71D005349BC /* Ignore Me */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               724DAB980EE88F56008900D0 /* Build configuration list for PBXNativeTarget "ip6fw" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               724DAB840EE88EFA008900D0 /* Debug */,
-                               724DAB850EE88EFA008900D0 /* Release */,
-                               03B2DBEA100BE71D005349BC /* Ignore Me */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
                724DABB80EE89035008900D0 /* Build configuration list for PBXNativeTarget "kdumpd" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               72946F4A1BBF055700087E35 /* Build configuration list for PBXNativeTarget "frame_delay" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               72946F471BBF055700087E35 /* Debug */,
+                               72946F481BBF055700087E35 /* Release */,
+                               72946F491BBF055700087E35 /* Ignore Me */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                7294F0FD0EE8BB550052EC88 /* Build configuration list for PBXNativeTarget "traceroute" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
index 6c60deeed4aa417bb426c019a8f3c00e76965f6d..defb856241f5c94e87ae916983e855b3d021247f 100644 (file)
@@ -71,6 +71,7 @@ packets to network hosts
 .Op Fl h Ar sweepincrsize
 .Op Fl i Ar wait
 .Op Fl k Ar trafficclass
+.Op Fl K Ar netservicetype
 .Op Fl l Ar preload
 .Op Fl M Cm mask | time
 .Op Fl m Ar ttl
@@ -81,6 +82,8 @@ packets to network hosts
 .Op Fl t Ar timeout
 .Op Fl W Ar waittime
 .Op Fl z Ar tos
+.Op Fl Fl apple-connect
+.Op Fl Fl apple-print
 .Ar host
 .Nm
 .Op Fl AaDdfLnoQqRrv
@@ -89,6 +92,7 @@ packets to network hosts
 .Op Fl I Ar iface
 .Op Fl i Ar wait
 .Op Fl k Ar trafficclass
+.Op Fl K Ar netservicetype
 .Op Fl l Ar preload
 .Op Fl M Cm mask | time
 .Op Fl m Ar ttl
@@ -100,6 +104,8 @@ packets to network hosts
 .Op Fl t Ar timeout
 .Op Fl W Ar waittime
 .Op Fl z Ar tos
+.Op Fl Fl apple-connect
+.Op Fl Fl apple-print
 .Ar mcast-group
 .Sh DESCRIPTION
 The
@@ -145,8 +151,10 @@ if other format options are present.
 Bind the socket to interface
 .Ar boundif
 for sending.
+This option is an Apple addition.
 .It Fl C
 Prohibit the socket from using the cellular network interface.
+This option is an Apple addition.
 .It Fl c Ar count
 Stop after sending
 (and receiving)
@@ -212,13 +220,19 @@ values less than 0.1 second.
 This option is incompatible with the
 .Fl f
 option.
-.It Fl k Ar trafficlass
+.It Fl k Ar trafficclass
 Specifies the traffic class to use for sending ICMP packets.
 The supported traffic classes are
 BK_SYS, BK, BE, RD, OAM, AV, RV, VI, VO and CTL.
 By default 
 .Nm
 uses the control traffic class (CTL).
+This option is an Apple addition.
+.It Fl K Ar netservicetype
+Specifies the network service type to use for sending ICMP packets.
+The supported network service type are BK_SYS, BK, BE, RV, AV, RD, OAM, VI, SIG and VO.
+Note this overrides the default traffic class (-k can still be specified after -K to use both).
+This option is an Apple addition.
 .It Fl L
 Suppress loopback of multicast packets.
 This flag only applies if the ping destination is a multicast address.
@@ -355,6 +369,12 @@ If a reply arrives later, the packet is not printed as replied, but
 considered as replied when calculating statistics.
 .It Fl z Ar tos
 Use the specified type of service.
+.It Fl Fl apple-connect
+Connects the socket to the destination address.
+This option is an Apple addition.
+.It Fl Fl apple-print
+Prints the time a packet was received.
+This option is an Apple addition.
 .El
 .Pp
 When using
index fa79b60c58e089cb1d15f953b6c39ff60891675c..ad5ea7a535139aaafa6b4cb7c0c139ec95ad9b29 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -107,12 +107,14 @@ __unused static const char copyright[] =
 #include <math.h>
 #include <netdb.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
 #include <ifaddrs.h>
+#include <getopt.h>
 
 #define        INADDR_LEN      ((int)sizeof(in_addr_t))
 #define        TIMEVAL_LEN     ((int)sizeof(struct tv32))
@@ -167,6 +169,8 @@ int options;
 #define        F_TIME          0x100000
 #define        F_SWEEP         0x200000
 #define        F_WAITTIME      0x400000
+#define        F_CONNECT       0x800000
+#define F_PRTIME       0x1000000
 
 /*
  * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -195,12 +199,11 @@ int phdr_len = 0;
 int send_len;
 char *boundif;
 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 use_sendmsg = 0;
+int use_recvmsg = 0;
 int traffic_class = SO_TC_CTL; /* use control class, by default */
+int net_service_type = -1;
 int no_dup = 0;
 
 /* counters */
@@ -244,9 +247,26 @@ static void pr_retip(struct ip *);
 static void status(int);
 static void stopit(int);
 static void tvsub(struct timeval *, const struct timeval *);
-static uint32_t str2svc(const char *);
+static int str2sotc(const char *, bool *);
+static int str2netservicetype(const char *, bool *);
+static u_int8_t str2tos(const char *, bool *);
 static void usage(void) __dead2;
 
+int32_t thiszone;              /* seconds offset from gmt to local time */
+extern int32_t gmt2local(time_t);
+static void pr_currenttime(void);
+
+static int longopt_flag = 0;
+
+#define        LOF_CONNECT     0x01
+#define        LOF_PRTIME      0x02
+
+static const struct option longopts[] = {
+       { "apple-connect", no_argument, &longopt_flag, LOF_CONNECT },
+       { "apple-time", no_argument, &longopt_flag, LOF_PRTIME },
+       { NULL, 0, NULL, 0 }
+};
+
 int
 main(int argc, char *const *argv)
 {
@@ -280,6 +300,7 @@ main(int argc, char *const *argv)
 #ifdef IPSEC_POLICY_IPSEC
        policy_in = policy_out = NULL;
 #endif
+       bool valid;
 
        /*
         * Do the stuff that we need root priv's for *first*, and
@@ -299,17 +320,9 @@ main(int argc, char *const *argv)
        alarmtimeout = df = preload = tos = 0;
 
        outpack = outpackhdr + sizeof(struct ip);
-       while ((ch = getopt(argc, argv,
-               "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:"
-#endif /*IPSEC_POLICY_IPSEC*/
-#endif /*IPSEC*/
-#if defined(IP_FORCE_OUT_IFP) && TARGET_OS_EMBEDDED
-               "B:"
-#endif /* IP_FORCE_OUT_IFP */
-               )) != -1)
+       while ((ch = getopt_long(argc, argv,
+           "AaB:b:Cc:DdfG:g:h:I:i:k:K:Ll:M:m:noP:p:QqRrS:s:T:t:vW:z:",
+           longopts, NULL)) != -1)
        {
                switch(ch) {
                case 'A':
@@ -318,12 +331,7 @@ main(int argc, char *const *argv)
                case 'a':
                        options |= F_AUDIBLE;
                        break;
-#if defined(IP_FORCE_OUT_IFP) && TARGET_OS_EMBEDDED
                case 'B':
-                       (void) snprintf(boundifname, sizeof (boundifname),
-                           "%s", optarg);
-                       break;
-#endif /* IP_FORCE_OUT_IFP */
                case 'b':
                        boundif = optarg;
                        break;
@@ -421,12 +429,31 @@ main(int argc, char *const *argv)
                        }
                        break;
                case 'k':
-                       how_traffic_class++;
-                       traffic_class = str2svc(optarg);
-                       if (traffic_class == UINT32_MAX)
+                       if (strcasecmp(optarg, "sendmsg") == 0) {
+                               use_sendmsg++;
+                               break;
+                       }
+                       if (strcasecmp(optarg, "recvmsg") == 0) {
+                               use_recvmsg++;
+                               break;
+                       }
+                       traffic_class = str2sotc(optarg, &valid);
+                       if (valid == false)
                                errx(EX_USAGE, "bad traffic class: `%s'",
                                     optarg);
                        break;
+               case 'K':
+                       if (strcasecmp(optarg, "sendmsg") == 0) {
+                               use_sendmsg++;
+                               break;
+                       }
+                       net_service_type = str2netservicetype(optarg, &valid);
+                       if (valid == false)
+                               errx(EX_USAGE, "bad network service type: `%s'",
+                                    optarg);
+                       /* suppress default traffic class (-k can still be specified after -K) */
+                       traffic_class = -1;
+                       break;
                case 'L':
                        options |= F_NOLOOP;
                        loop = 0;
@@ -470,9 +497,9 @@ main(int argc, char *const *argv)
                case 'o':
                        options |= F_ONCE;
                        break;
+               case 'P':
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
-               case 'P':
                        options |= F_POLICY;
                        if (!strncmp("in", optarg, 2))
                                policy_in = strdup(optarg);
@@ -480,9 +507,9 @@ main(int argc, char *const *argv)
                                policy_out = strdup(optarg);
                        else
                                errx(1, "invalid security policy");
-                       break;
 #endif /*IPSEC_POLICY_IPSEC*/
 #endif /*IPSEC*/
+                       break;
                case 'p':               /* fill buffer with user pattern */
                        options |= F_PINGFILLED;
                        payload = optarg;
@@ -548,10 +575,23 @@ main(int argc, char *const *argv)
                        break;
                case 'z':
                        options |= F_HDRINCL;
-                       ultmp = strtoul(optarg, &ep, 0);
-                       if (*ep || ep == optarg || ultmp > MAXTOS)
+                       tos = str2tos(optarg, &valid);
+                       if (valid == false)
                                errx(EX_USAGE, "invalid TOS: `%s'", optarg);
-                       tos = ultmp;
+                       break;
+               case 0:
+                       switch (longopt_flag) {
+                               case LOF_CONNECT:
+                                       options |= F_CONNECT;
+                                       break;
+                               case LOF_PRTIME:
+                                       options |= F_PRTIME;
+                                       thiszone = gmt2local(0);
+                                       break;
+                               default:
+                                       break;
+                       }
+                       longopt_flag = 0;
                        break;
                default:
                        usage();
@@ -620,7 +660,11 @@ main(int argc, char *const *argv)
                        shostname = snamebuf;
                }
                if (bind(s, (struct sockaddr *)&sock_in, sizeof sock_in) == -1)
+#if (DEBUG || DEVELOPMENT)
+                       options |= F_HDRINCL;
+#else
                        err(1, "bind");
+#endif /* DEBUG || DEVELOPMENT */
        }
 
        bzero(&whereto, sizeof(whereto));
@@ -678,9 +722,6 @@ main(int argc, char *const *argv)
                errx(EX_USAGE,
                    "-I, -L, -T flags cannot be used with unicast destination");
 
-       if (datalen >= TIMEVAL_LEN)     /* can we time transfer */
-               timing = 1;
-
        if (!(options & F_PINGFILLED))
                for (i = TIMEVAL_LEN; i < MAX(datalen, sweepmax); ++i)
                        *datap++ = i;
@@ -699,13 +740,6 @@ main(int argc, char *const *argv)
                    (char *)&ifscope, sizeof (ifscope)) != 0)
                        err(EX_OSERR, "setsockopt(IP_BOUND_IF)");
        }
-#if defined(IP_FORCE_OUT_IFP) && TARGET_OS_EMBEDDED
-       else if (boundifname[0] != 0) {
-               if (setsockopt(s, IPPROTO_IP, IP_FORCE_OUT_IFP, boundifname,
-                   sizeof (boundifname)) != 0)
-                       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)
@@ -717,11 +751,19 @@ main(int argc, char *const *argv)
        if (options & F_SO_DONTROUTE)
                (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
                    sizeof(hold));
-       if (how_traffic_class < 2 && traffic_class >= 0) {
-               (void) setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS,
-                   (void *)&traffic_class, sizeof (traffic_class));
+       if (use_sendmsg == 0) {
+               if (net_service_type != -1)
+                       if (setsockopt(s, SOL_SOCKET, SO_NET_SERVICE_TYPE,
+                                      (void *)&net_service_type, sizeof (net_service_type)) != 0)
+                               warn("setsockopt(SO_NET_SERVICE_TYPE");
+               if (traffic_class != -1) {
+                       if (setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS,
+                                      (void *)&traffic_class, sizeof (traffic_class)) != 0)
+                               warn("setsockopt(SO_TRAFFIC_CLASS");
+                       
+               }
        }
-       if (how_traffic_class > 0) {
+       if (use_recvmsg > 0) {
                int on = 1;
                (void) setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS,
                    (void *)&on, sizeof (on));
@@ -824,6 +866,12 @@ main(int argc, char *const *argv)
                err(EX_OSERR, "setsockopt SO_TIMESTAMP");
        }
 #endif
+
+       if ((options & F_CONNECT)) {
+               if (connect(s, (struct sockaddr *)&whereto, sizeof whereto) == -1)
+                       err(EX_OSERR, "connect");
+       }
+
        if (sweepmax) {
                if (sweepmin >= sweepmax)
                        errx(EX_USAGE, "Maximum packet size must be greater than the minimum packet size");
@@ -880,6 +928,16 @@ main(int argc, char *const *argv)
                        (void)printf("PING %s: %d data bytes\n", hostname, datalen);
        }
 
+       /*
+        * rdar://25829310
+        *
+        * Clear blocked signals inherited from the parent
+        */
+       sigset_t newset;
+       sigemptyset(&newset);
+       if (sigprocmask(SIG_SETMASK, &newset, NULL) != 0)
+               err(EX_OSERR, "sigprocmask(newset)");
+
        /*
         * Use sigaction() instead of signal() to get unambiguous semantics,
         * in particular with SA_RESTART not set.
@@ -967,7 +1025,7 @@ main(int argc, char *const *argv)
                if (n == 1) {
                        struct timeval *tv = NULL;
 #ifdef SO_TIMESTAMP
-                       struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl;
+                       struct cmsghdr *cmsg;
 
                        msg.msg_controllen = sizeof(ctrl);
 #endif
@@ -1094,6 +1152,11 @@ pinger(void)
 
        CLR(ntransmitted % mx_dup_ck);
 
+       if (datalen >= TIMEVAL_LEN)     /* can we time transfer */
+               timing = 1;
+       else
+               timing = 0;
+       
        if ((options & F_TIME) || timing) {
                (void)gettimeofday(&now, NULL);
 
@@ -1120,34 +1183,55 @@ pinger(void)
                ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
                packet = outpackhdr;
        }
-       if (how_traffic_class > 1 && traffic_class >= 0) {
+       if (use_sendmsg > 0) {
                struct msghdr msg;
                struct iovec iov;
-               char *cmbuf[CMSG_SPACE(sizeof(int))];
+               char cmbuf[2 * CMSG_SPACE(sizeof(int))];
                struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
 
+               if ((options & F_CONNECT)) {
+                       msg.msg_name = NULL;
+                       msg.msg_namelen = 0;
+               } else {
                msg.msg_name = &whereto;
                msg.msg_namelen = sizeof(whereto);
-
+               }
                iov.iov_base = packet;
                iov.iov_len = cc;
                msg.msg_iov = &iov;
                msg.msg_iovlen = 1;
 
-               cm->cmsg_len = CMSG_LEN(sizeof(int));
-               cm->cmsg_level = SOL_SOCKET;
-               cm->cmsg_type = SO_TRAFFIC_CLASS;
-               *(int *)CMSG_DATA(cm) = traffic_class;
-               msg.msg_control = cm;
-               msg.msg_controllen = CMSG_SPACE(sizeof(int));
+               msg.msg_controllen = 0;
+               msg.msg_control = NULL;
+               
+               if (traffic_class >= 0) {
+                       cm->cmsg_len = CMSG_LEN(sizeof(int));
+                       cm->cmsg_level = SOL_SOCKET;
+                       cm->cmsg_type = SO_TRAFFIC_CLASS;
+                       *(int *)CMSG_DATA(cm) = traffic_class;
+                       msg.msg_controllen += CMSG_SPACE(sizeof(int));
+                       cm = (struct cmsghdr *)(((char *)cm) + CMSG_SPACE(sizeof(int)));
+               }
+               if (net_service_type >= 0) {
+                       cm->cmsg_len = CMSG_LEN(sizeof(int));
+                       cm->cmsg_level = SOL_SOCKET;
+                       cm->cmsg_type = SO_NET_SERVICE_TYPE;
+                       msg.msg_controllen += CMSG_SPACE(sizeof(int));
+                       *(int *)CMSG_DATA(cm) = net_service_type;
+               }
+               msg.msg_control = cmbuf;
 
                msg.msg_flags = 0;
 
                i = sendmsg(s, &msg, 0);
        } else {
+               if ((options & F_CONNECT)) {
+                       i = send(s, (char *)packet, cc, 0);
+               } else {
                i = sendto(s, (char *)packet, cc, 0, (struct sockaddr *)&whereto,
                        sizeof(whereto));
        }
+       }
        if (i < 0 || i != cc)  {
                if (i < 0) {
                        if (options & F_FLOOD && errno == ENOBUFS) {
@@ -1267,6 +1351,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv,
                                seq_datalen = sweepmin + (seq / snpackets) * sweepincr;
                                seq_sent_len = icmp_len + seq_datalen;
                        }
+                       if (options & F_PRTIME)
+                               pr_currenttime();
                        (void)printf("%d bytes from %s: icmp_seq=%u", cc,
                           inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
                           seq);
@@ -1353,6 +1439,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv,
                     (oip->ip_p == IPPROTO_ICMP) &&
                     (oicmp->icmp_type == ICMP_ECHO) &&
                     (oicmp->icmp_id == ident))) {
+                   if (options & F_PRTIME)
+                           pr_currenttime();
                    (void)printf("%d bytes from %s: ", cc,
                        pr_addr(from->sin_addr));
                    pr_icmph(icp);
@@ -1862,14 +1950,16 @@ fill(char *bp, char *patp)
        }
 }
 
-uint32_t
-str2svc(const char *str)
+int
+str2sotc(const char *str, bool *valid)
 {
-       uint32_t svc;
+       int sotc = -1;
        char *endptr;
        
+       *valid = true;
+       
        if (str == NULL || *str == '\0')
-               svc = UINT32_MAX;
+               *valid = false;
        else if (strcasecmp(str, "BK_SYS") == 0)
                return SO_TC_BK_SYS;
        else if (strcasecmp(str, "BK") == 0)
@@ -1891,13 +1981,132 @@ str2svc(const char *str)
        else if (strcasecmp(str, "CTL") == 0)
                return SO_TC_CTL;
        else {
-               svc = strtoul(str, &endptr, 0);
+               sotc = (int)strtol(str, &endptr, 0);
                if (*endptr != '\0')
-                       svc = UINT32_MAX;
+                       *valid = false;
+       }
+       return (sotc);
+}
+
+int
+str2netservicetype(const char *str, bool *valid)
+{
+       int svc = -1;
+       char *endptr;
+       
+       *valid = true;
+       
+       if (str == NULL || *str == '\0')
+               *valid = false;
+       else if (strcasecmp(str, "BK") == 0)
+               return NET_SERVICE_TYPE_BK;
+       else if (strcasecmp(str, "BE") == 0)
+               return NET_SERVICE_TYPE_BE;
+       else if (strcasecmp(str, "VI") == 0)
+               return NET_SERVICE_TYPE_VI;
+       else if (strcasecmp(str, "SIG") == 0)
+               return NET_SERVICE_TYPE_SIG;
+       else if (strcasecmp(str, "VO") == 0)
+               return NET_SERVICE_TYPE_VO;
+       else if (strcasecmp(str, "RV") == 0)
+               return NET_SERVICE_TYPE_RV;
+       else if (strcasecmp(str, "AV") == 0)
+               return NET_SERVICE_TYPE_AV;
+       else if (strcasecmp(str, "OAM") == 0)
+               return NET_SERVICE_TYPE_OAM;
+       else if (strcasecmp(str, "RD") == 0)
+               return NET_SERVICE_TYPE_RD;
+       else {
+               svc = (int)strtol(str, &endptr, 0);
+               if (*endptr != '\0')
+                       *valid = false;
        }
        return (svc);
 }
 
+u_int8_t
+str2tos(const char *str, bool *valid)
+{
+       u_int8_t dscp = -1;
+       char *endptr;
+       
+       *valid = true;
+       
+       if (str == NULL || *str == '\0')
+               *valid = false;
+       else if (strcasecmp(str, "DF") == 0)
+               dscp = _DSCP_DF;
+       else if (strcasecmp(str, "EF") == 0)
+               dscp = _DSCP_EF;
+       else if (strcasecmp(str, "VA") == 0)
+               dscp = _DSCP_VA;
+       
+       else if (strcasecmp(str, "CS0") == 0)
+               dscp = _DSCP_CS0;
+       else if (strcasecmp(str, "CS1") == 0)
+               dscp = _DSCP_CS1;
+       else if (strcasecmp(str, "CS2") == 0)
+               dscp = _DSCP_CS2;
+       else if (strcasecmp(str, "CS3") == 0)
+               dscp = _DSCP_CS3;
+       else if (strcasecmp(str, "CS4") == 0)
+               dscp = _DSCP_CS4;
+       else if (strcasecmp(str, "CS5") == 0)
+               dscp = _DSCP_CS5;
+       else if (strcasecmp(str, "CS6") == 0)
+               dscp = _DSCP_CS6;
+       else if (strcasecmp(str, "CS7") == 0)
+               dscp = _DSCP_CS7;
+       
+       else if (strcasecmp(str, "AF11") == 0)
+               dscp = _DSCP_AF11;
+       else if (strcasecmp(str, "AF12") == 0)
+               dscp = _DSCP_AF12;
+       else if (strcasecmp(str, "AF13") == 0)
+               dscp = _DSCP_AF13;
+       else if (strcasecmp(str, "AF21") == 0)
+               dscp = _DSCP_AF21;
+       else if (strcasecmp(str, "AF22") == 0)
+               dscp = _DSCP_AF22;
+       else if (strcasecmp(str, "AF23") == 0)
+               dscp = _DSCP_AF23;
+       else if (strcasecmp(str, "AF31") == 0)
+               dscp = _DSCP_AF31;
+       else if (strcasecmp(str, "AF32") == 0)
+               dscp = _DSCP_AF32;
+       else if (strcasecmp(str, "AF33") == 0)
+               dscp = _DSCP_AF33;
+       else if (strcasecmp(str, "AF41") == 0)
+               dscp = _DSCP_AF41;
+       else if (strcasecmp(str, "AF42") == 0)
+               dscp = _DSCP_AF42;
+       else if (strcasecmp(str, "AF43") == 0)
+               dscp = _DSCP_AF43;
+       
+       else {
+               unsigned long val = strtoul(str, &endptr, 0);
+               if (*endptr != '\0' || val > 255)
+                       *valid = false;
+               else
+                       return ((u_int8_t)val);
+       }
+       /* DSCP occupies the 6 upper bits of the TOS field */
+       return (dscp << 2);
+}
+
+void
+pr_currenttime(void)
+{
+       int s;
+       struct timeval tv;
+       
+       gettimeofday(&tv, NULL);
+       
+       s = (tv.tv_sec + thiszone) % 86400;
+       printf("%02d:%02d:%02d.%06u ", s / 3600, (s % 3600) / 60, s % 60,
+              (u_int32_t)tv.tv_usec);
+}
+
 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
 #define        SECOPT          " [-P policy]"
 #else
@@ -1908,14 +2117,20 @@ usage(void)
 {
 
        (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-"usage: ping [-AaDdfnoQqRrv] [-b boundif] [-c count] [-G sweepmaxsize]",
-"            [-g sweepminsize] [-h sweepincrsize] [-i wait] [−k trafficclass]",
+"usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize]",
+"            [-g sweepminsize] [-h sweepincrsize] [-i wait]",
 "            [-l preload] [-M mask | time] [-m ttl]" SECOPT " [-p pattern]",
-"            [-S src_addr] [-s packetsize] [-t timeout][-W waittime] [-z tos]",
-"            host",
-"       ping [-AaDdfLnoQqRrv] [-b boundif] [-c count] [-I iface] [-i wait]",
-"            [−k trafficclass] [-l preload] [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]",
+"            [-S src_addr] [-s packetsize] [-t timeout][-W waittime]",
+"            [-z tos] host",
+"       ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait]",
+"            [-l preload] [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]",
 "            [-s packetsize] [-T ttl] [-t timeout] [-W waittime]",
 "            [-z tos] mcast-group");
+       (void)fprintf(stderr, "Apple specific options (to be specified before mcast-group or host like all options)\n");
+       (void)fprintf(stderr, "            -b boundif           # bind the socket to the interface\n");
+       (void)fprintf(stderr, "            -k traffic_class     # set traffic class socket option\n");
+       (void)fprintf(stderr, "            -K net_service_type  # set traffic class socket options\n");
+       (void)fprintf(stderr, "            -apple-connect       # call connect(2) in the socket\n");
+       (void)fprintf(stderr, "            -apple-time          # display current time\n");
        exit(EX_USAGE);
 }
index 716668cf6529ed705027247b6df784a4a1891269..e19b066ebc8d39a7acae307f7ceeca12cd9fe5fb 100644 (file)
@@ -79,9 +79,15 @@ packets to network hosts
 .Op Fl c Ar count
 .Ek
 .Bk -words
+.Op Fl G Ar sweepmaxsize[,sweepminsize[,sweepincrsize]]
+.Ek
+.Bk -words
 .Op Fl g Ar gateway
 .Ek
 .Bk -words
+.Op Fl G Ar sweep
+.Ek
+.Bk -words
 .Op Fl h Ar hoplimit
 .Ek
 .Bk -words
@@ -94,6 +100,9 @@ packets to network hosts
 .Op Fl k Ar trafficclass
 .Ek
 .Bk -words
+.Op Fl K Ar netservicetype
+.Ek
+.Bk -words
 .Op Fl l Ar preload
 .Ek
 .Bk -words
@@ -113,6 +122,12 @@ packets to network hosts
 .Op Fl z Ar tclass
 .Ek
 .Bk -words
+.Op Fl Fl apple-connect
+.Ek
+.Bk -words
+.Op Fl Fl apple-print
+.Ek
+.Bk -words
 .Op Ar hops ...
 .Ek
 .Bk -words
@@ -169,6 +184,7 @@ This is an experimental option.
 Set socket buffer size.
 .It Fl B Ar boundif
 Bind the socket to interface
+This option is an Apple addition.
 .Ar boundif
 for sending.
 .It Fl C
@@ -179,6 +195,10 @@ Stop after sending
 .Ar count
 .Tn ECHO_RESPONSE
 packets.
+If this option is specified in conjunction with ping sweeps,
+each sweep will consist of
+.Ar count
+packets.
 .It Fl D
 Disable IPv6 fragmentation.
 .It Fl d
@@ -204,6 +224,18 @@ Only the super-user may use this option.
 .Bf -emphasis
 This can be very hard on a network and should be used with caution.
 .Ef
+.It Fl G Ar sweepmaxsize[,sweepminsize[,sweepincrsize]]
+.Ar sweepmaxsize
+specifies the maximum size of the payload when sending sweeping
+pings and is required for sweeps.
+.Ar sweepminsize
+specifies the size of the payload to start with when sending
+sweeping pings -- the default value is 0.
+.Ar sweepincrsize
+specifies the number of bytes to increment the size of the payload
+after each sweep when sending sweeping pings -- the default value
+is 1.
+This option is an Apple addition.
 .It Fl g Ar gateway
 Specifies to use
 .Ar gateway
@@ -231,13 +263,19 @@ values less than 0.1 second.
 This option is incompatible with the
 .Fl f
 option.
-.It Fl k Ar trafficlass
+.It Fl k Ar trafficclass
 Specifies the traffic class to use for sending ICMPv6 packets.
 The supported traffic classes are
 BK_SYS, BK, BE, RD, OAM, AV, RV, VI, VO and CTL.
 By default 
 .Nm
 uses the control traffic class (CTL).
+This option is an Apple addition.
+.It Fl K Ar netservicetype
+Specifies the network service type to use for sending ICMPv6 packets.
+The supported network service type are BK_SYS, BK, BE, RV, AV, RD, OAM, VI, SIG and VO.
+Note this overrides the default traffic class (-k can still be specified after -K to use both).
+This option is an Apple addition.
 .It Fl l Ar preload
 If
 .Ar preload
@@ -354,6 +392,12 @@ has no effect if
 is specified.
 .It Fl z Ar tclass
 Use the specified traffic class.
+.It Fl Fl apple-connect
+Connects the socket to the destination address.
+This option is an Apple addition.
+.It Fl Fl apple-print
+Prints the time a packet was received.
+This option is an Apple addition.
 .It Ar hops
 IPv6 addresses for intermediate nodes,
 which will be put into type 0 routing header.
index 90da21a9f726341617dccd6f5e8315d2304124bf..c5b0785cdef74e86471d4e84fb1c49f3ed9a365b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -143,6 +143,7 @@ __unused static const char copyright[] =
 #include <fcntl.h>
 #include <math.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -151,6 +152,7 @@ __unused static const char copyright[] =
 #include <poll.h>
 #endif
 #include <sysexits.h>
+#include <getopt.h>
 
 #ifdef IPSEC
 #include <netinet6/ah.h>
@@ -189,6 +191,7 @@ struct tv32 {
 #define        F_QUIET         0x0010
 #define        F_RROUTE        0x0020
 #define        F_SO_DEBUG      0x0040
+#define        F_PRTIME        0x0080
 #define        F_VERBOSE       0x0100
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
@@ -211,9 +214,23 @@ struct tv32 {
 #define F_AUDIBLE      0x400000
 #define F_MISSED       0x800000
 #define F_DONTFRAG     0x1000000
+#define        F_SWEEP         0x2000000
+#define F_CONNECT      0x4000000
 #define F_NOUSERDATA   (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
 u_int options;
 
+static int longopt_flag = 0;
+
+#define        LOF_CONNECT     0x01
+#define LOF_PRTIME     0x02
+
+static const struct option longopts[] = {
+       { "apple-connect", no_argument, &longopt_flag, LOF_CONNECT },
+       { "apple-time", no_argument, &longopt_flag, LOF_PRTIME },
+       { NULL, 0, NULL, 0 }
+};
+
+
 #define IN6LEN         sizeof(struct in6_addr)
 #define SA6LEN         sizeof(struct sockaddr_in6)
 #define DUMMY_PORT     10101
@@ -264,6 +281,11 @@ long nreceived;                    /* # of packets we got back */
 long nrepeats;                 /* number of duplicates */
 long ntransmitted;             /* sequence # for outbound packets = #sent */
 struct timeval interval = {1, 0}; /* interval between packets */
+long snpackets = 0;            /* max packets to transmit in one sweep */
+long sntransmitted = 0;                /* # of packets we sent in this sweep */
+int sweepmax = 0;              /* max value of payload in sweep */
+int sweepmin = 0;              /* start value of payload in sweep */
+int sweepincr = 1;             /* payload increment in sweep */
 
 /* timing */
 int timing;                    /* flag to do timing */
@@ -277,7 +299,7 @@ u_short naflags;
 
 /* for ancillary data(advanced API) */
 struct msghdr smsghdr;
-struct iovec smsgiov;
+struct iovec smsgiov[2];
 char *scmsg = NULL;
 
 volatile sig_atomic_t seenalrm;
@@ -288,8 +310,14 @@ volatile sig_atomic_t seeninfo;
 
 int rcvtclass = 0;
 
-int how_so_traffic_class = 0;
+int use_sendmsg = 0;
+int use_recvmsg = 0;
 int so_traffic_class = SO_TC_CTL;      /* use control class, by default */
+int net_service_type = -1;
+
+int32_t thiszone;              /* seconds offset from gmt to local time */
+extern int32_t gmt2local(time_t);
+static void pr_currenttime(void);
 
 int     main(int, char *[]);
 void    fill(char *, char *);
@@ -322,7 +350,9 @@ void         summary(void);
 void    tvsub(struct timeval *, struct timeval *);
 int     setpolicy(int, char *);
 char   *nigroup(char *);
-static uint32_t str2svc(const char *);
+static int str2sotc(const char *, bool *);
+static int str2netservicetype(const char *, bool *);
+static u_int8_t str2tclass(const char *, bool *);
 void    usage(void);
 
 int
@@ -365,6 +395,8 @@ main(int argc, char *argv[])
 #endif
        /* T_CLASS value -1 means default, so -2 means do not bother */
        int tclass = -2;
+       bool valid;
+       struct timeval intvl;
 
        /* just to be sure */
        memset(&smsghdr, 0, sizeof(smsghdr));
@@ -381,8 +413,9 @@ main(int argc, char *argv[])
 #define ADDOPTS        "AE"
 #endif /*IPSEC_POLICY_IPSEC*/
 #endif
-       while ((ch = getopt(argc, argv,
-           "a:b:B:Cc:DdfHg:h:I:i:k:l:mnNop:qrRS:s:tvwWz:" ADDOPTS)) != -1) {
+       while ((ch = getopt_long(argc, argv,
+           "a:b:B:Cc:DdfHG:g:h:I:i:k:K:l:mnNop:qrRS:s:tvwWz:" ADDOPTS,
+           longopts, NULL)) != -1) {
 #undef ADDOPTS
                switch (ch) {
                case 'a':
@@ -471,6 +504,66 @@ main(int argc, char *argv[])
                case 'g':
                        gateway = optarg;
                        break;
+               case 'G': {
+                       char *ptr ;
+                       char *tofree;
+                       unsigned long ultmp;
+
+                       tofree = strdup(optarg);
+                       if (tofree == NULL)
+                               errx(1, "### strdup() failed");
+                       ptr = tofree;
+                       do {
+                               char *str;
+                               char *ep;
+                               
+                               if ((str = strsep(&ptr, ",")) == NULL)
+                                       errx(1, "-G requires maximum packet size");
+                               ultmp = strtoul(str, &ep, 0);
+                               if (*ep || ep == optarg)
+                                       errx(EX_USAGE, "option -G invalid maximum packet size: `%s'",
+                                            str);
+                               options |= F_SWEEP;
+                               sweepmax = ultmp;
+                               if (sweepmax < 1 || sweepmax > MAXDATALEN) {
+                                       errx(1,
+                                            "-G invalid maximum packet size, needs to be between 1 and %d",
+                                            MAXDATALEN);
+                               }
+
+                               if ((str = strsep(&ptr, ",")) == NULL)
+                                       break;
+                               if (*str != 0) {
+                                       ultmp = strtoul(str, &ep, 0);
+                                       if (*ep || ep == optarg)
+                                               errx(EX_USAGE, "option -G invalid minimum packet size: `%s'",
+                                                    str);
+                                       sweepmin = ultmp;
+                                       if (sweepmin < 0 || sweepmin > MAXDATALEN) {
+                                               errx(1,
+                                                    "-G invalid minimum packet size, needs to be between 0 and %d",
+                                                    MAXDATALEN);
+                                       }
+                               }
+                               
+                               if ((str = strsep(&ptr, ",")) == NULL)
+                                       break;
+                               if (*str == 0)
+                                       break;
+                               ultmp = strtoul(str, &ep, 0);
+                               if (*ep || ep == optarg)
+                                       errx(EX_USAGE, "option -G invalid sweep increment size: `%s'",
+                                            str);
+                               sweepincr = ultmp;
+                               if (sweepincr < 1 || sweepincr > MAXDATALEN) {
+                                       errx(1,
+                                            "-G invalid sweep increment size, needs to be between 1 and %d",
+                                            MAXDATALEN);
+                               }
+                       } while (0);
+                       free(tofree);
+                       break;
+               }
                case 'H':
                        options |= F_HOSTNAME;
                        break;
@@ -510,13 +603,31 @@ main(int argc, char *argv[])
                        options |= F_INTERVAL;
                        break;
                case 'k':
-                       how_so_traffic_class++;
-                       so_traffic_class = str2svc(optarg);
-                       if (so_traffic_class == UINT32_MAX)
+                       if (strcasecmp(optarg, "sendmsg") == 0) {
+                               use_sendmsg++;
+                               break;
+                       }
+                       if (strcasecmp(optarg, "recvmsg") == 0) {
+                               use_recvmsg++;
+                               break;
+                       }
+                       so_traffic_class = str2sotc(optarg, &valid);
+                       if (valid == false)
                                errx(EX_USAGE, "bad traffic class: `%s'",
                                     optarg);
                        break;
-
+               case 'K':
+                       if (strcasecmp(optarg, "sendmsg") == 0) {
+                               use_sendmsg++;
+                               break;
+                       }
+                       net_service_type = str2netservicetype(optarg, &valid);
+                       if (valid == false)
+                               errx(EX_USAGE, "bad network service type: `%s'",
+                                    optarg);
+                       /* suppress default traffic class (-k can still be specified after -K) */
+                       so_traffic_class = -1;
+                       break;
                case 'l':
                        if (getuid()) {
                                errno = EPERM;
@@ -546,7 +657,7 @@ main(int argc, char *argv[])
                case 'p':               /* fill buffer with user pattern */
                        options |= F_PINGFILLED;
                        fill((char *)datap, optarg);
-                               break;
+                       break;
                case 'q':
                        options |= F_QUIET;
                        break;
@@ -604,13 +715,9 @@ main(int argc, char *argv[])
                        options |= F_FQDNOLD;
                        break;
                case 'z':
-                       tclass = (int)strtol(optarg, &e, 10);
-                       if (tclass < -1 || *optarg == '\0' || *e != '\0')
+                       tclass = str2tclass(optarg, &valid);
+                       if (valid == false)
                                errx(1, "illegal TOS value -- %s", optarg);
-                       if (tclass > MAXTOS)
-                               errx(1,
-                                   "TOS value too large, maximum is %d",
-                                   MAXTOS);
                        rcvtclass = 1;
                        break;
 #ifdef IPSEC
@@ -635,6 +742,20 @@ main(int argc, char *argv[])
                        break;
 #endif /*IPSEC_POLICY_IPSEC*/
 #endif /*IPSEC*/
+               case 0:
+                       switch (longopt_flag) {
+                               case LOF_CONNECT:
+                                       options |= F_CONNECT;
+                                       break;
+                               case LOF_PRTIME:
+                                       options |= F_PRTIME;
+                                       thiszone = gmt2local(0);
+                                       break;
+                               default:
+                                       break;
+                       }
+                       longopt_flag = 0;
+                       break;
                default:
                        usage();
                        /*NOTREACHED*/
@@ -644,6 +765,12 @@ main(int argc, char *argv[])
        if (boundif != NULL && (ifscope = if_nametoindex(boundif)) == 0)
                errx(1, "bad interface name");
 
+       if ((options & F_SWEEP) && !sweepmax)
+               errx(EX_USAGE, "Maximum sweep size must be specified");
+
+       if ((options & F_SWEEP) && (options & F_NOUSERDATA))
+               errx(EX_USAGE, "Option -G incompatible with -t, -w and -W");
+       
        argc -= optind;
        argv += optind;
 
@@ -787,17 +914,32 @@ main(int argc, char *argv[])
        if ((options & F_FLOOD) && (options & F_INTERVAL))
                errx(1, "-f and -i incompatible options");
 
-       if ((options & F_NOUSERDATA) == 0) {
-               if (datalen >= sizeof(struct tv32)) {
-                       /* we can time transfer */
-                       timing = 1;
+       if ((options & F_CONNECT)) {
+               if (connect(s, (struct sockaddr *)&dst, sizeof(dst)) == -1)
+                       err(EX_OSERR, "connect");
+       }
+       
+       if (sweepmax) {
+               if (sweepmin >= sweepmax)
+                       errx(EX_USAGE, "Maximum packet size must be greater than the minimum packet size");
+               
+               if (datalen != DEFDATALEN)
+                       errx(EX_USAGE, "Packet size and ping sweep are mutually exclusive");
+               
+               if (npackets > 0) {
+                       snpackets = npackets;
+                       npackets = 0;
                } else
-                       timing = 0;
+                       snpackets = 1;
+               datalen = sweepmin;
+       }
+       
+       if ((options & F_NOUSERDATA) == 0) {
                /* in F_VERBOSE case, we may get non-echoreply packets*/
                if (options & F_VERBOSE)
-                       packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
+                       packlen = MAX(2048, sweepmax) + IP6LEN + ICMP6ECHOLEN + EXTRA;
                else
-                       packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA;
+                       packlen = MAX(datalen, sweepmax) + IP6LEN + ICMP6ECHOLEN + EXTRA;
        } else {
                /* suppress timing for node information query */
                timing = 0;
@@ -805,10 +947,10 @@ main(int argc, char *argv[])
                packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
        }
 
-       if (!(packet = (u_char *)malloc((u_int)packlen)))
+       if (!(packet = (u_char *)malloc((u_int)MAX(datalen, sweepmax))))
                err(1, "Unable to allocate packet");
        if (!(options & F_PINGFILLED))
-               for (i = ICMP6ECHOLEN; i < packlen; ++i)
+               for (i = ICMP6ECHOLEN; i < MAX(datalen, sweepmax); ++i)
                        *datap++ = i;
 
        ident = getpid() & 0xFFFF;
@@ -959,17 +1101,29 @@ main(int argc, char *argv[])
        if (tclass != -2)
                ip6optlen += CMSG_SPACE(sizeof(int));
 
-       if (how_so_traffic_class < 2 && so_traffic_class >= 0) {
-               (void) setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS,
-                   (void *)&so_traffic_class, sizeof (so_traffic_class));
+       if (use_sendmsg == 0) {
+               if (net_service_type != -1)
+                       if (setsockopt(s, SOL_SOCKET, SO_NET_SERVICE_TYPE,
+                                      (void *)&net_service_type, sizeof (net_service_type)) != 0)
+                               warn("setsockopt(SO_NET_SERVICE_TYPE");
+               if (so_traffic_class != -1) {
+                       if (setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS,
+                           (void *)&so_traffic_class, sizeof (so_traffic_class)) != 0)
+                               warn("setsockopt(SO_TRAFFIC_CLASS");
+                       
+               }
+       } else {
+               if (net_service_type != -1)
+                       ip6optlen += CMSG_SPACE(sizeof(int));
+               if (so_traffic_class != -1)
+                       ip6optlen += CMSG_SPACE(sizeof(int));
        }
-       if (how_so_traffic_class > 0) {
+       if (use_recvmsg > 0) {
                int on = 1;
-               (void) setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS,
-                   (void *)&on, sizeof (on));
+               if (setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS,
+                   (void *)&on, sizeof (on)) != 0)
+                       warn("setsockopt(SO_RECV_TRAFFIC_CLASS");
        }
-       if (how_so_traffic_class > 1)
-               ip6optlen += CMSG_SPACE(sizeof(int));
 
        /* set IP6 packet options */
        if (ip6optlen) {
@@ -1082,13 +1236,21 @@ main(int argc, char *argv[])
 
                scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
        }
-       if (how_so_traffic_class > 1 && so_traffic_class >= 0) {
-               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;
+       if (use_sendmsg != 0) {
+               if (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);
+                       scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
+               }
+               if (net_service_type != -1) {
+                       scmsgp->cmsg_len = CMSG_LEN(sizeof(int));
+                       scmsgp->cmsg_level = SOL_SOCKET;
+                       scmsgp->cmsg_type = SO_NET_SERVICE_TYPE;
+                       *(int *)(CMSG_DATA(scmsgp)) = net_service_type;
+               }
        }
        if (!(options & F_SRCADDR)) {
                /*
@@ -1156,7 +1318,7 @@ main(int argc, char *argv[])
 
 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
        if (sockbufsize) {
-               if (datalen > sockbufsize)
+               if (MAX(datalen, sweepmax) > sockbufsize)
                        warnx("you need -b to increase socket buffer size");
                if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
                    sizeof(sockbufsize)) < 0)
@@ -1166,7 +1328,7 @@ main(int argc, char *argv[])
                        err(1, "setsockopt(SO_RCVBUF)");
        }
        else {
-               if (datalen > 8 * 1024) /*XXX*/
+               if (MAX(datalen, sweepmax) > 8 * 1024)  /*XXX*/
                        warnx("you need -b to increase socket buffer size");
                /*
                 * When pinging the broadcast address, you can get a lot of
@@ -1203,21 +1365,42 @@ main(int argc, char *argv[])
                    optval, sizeof(optval)); /* XXX err? */
 #endif
 
-       printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
-           (unsigned long)(pingerlen() - 8));
+       if (sweepmax)
+               printf("PING6(40+8+[%lu...%lu] bytes) ",
+                      (unsigned long)(sweepmin),
+                      (unsigned long)(sweepmax));
+       else
+               printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
+                       (unsigned long)(pingerlen() - 8));
        printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
        printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
 
        while (preload--)               /* Fire off them quickies. */
                (void)pinger();
 
+       /*
+        * rdar://25829310
+        *
+        * Clear blocked signals inherited from the parent
+        */
+       sigset_t newset;
+       sigemptyset(&newset);
+       if (sigprocmask(SIG_SETMASK, &newset, NULL) != 0)
+               err(EX_OSERR, "sigprocmask(newset)");
+       
+       seenalrm = seenint = 0;
+#ifdef SIGINFO
+       seeninfo = 0;
+#endif
+       
        (void)signal(SIGINT, onsignal);
 #ifdef SIGINFO
        (void)signal(SIGINFO, onsignal);
 #endif
 
        if ((options & F_FLOOD) == 0) {
-               (void)signal(SIGALRM, onsignal);
+               if (signal(SIGALRM, onsignal) == SIG_ERR)
+                       warn("signal(SIGALRM)");
                itimer.it_interval = interval;
                itimer.it_value = interval;
                (void)setitimer(ITIMER_REAL, &itimer, NULL);
@@ -1225,17 +1408,20 @@ main(int argc, char *argv[])
                        retransmit();
        }
 
+       if (options & F_FLOOD) {
+               intvl.tv_sec = 0;
+               intvl.tv_usec = 10000;
+       } else {
+               intvl.tv_sec = interval.tv_sec;
+               intvl.tv_usec = interval.tv_usec;
+       }
+       
 #ifndef HAVE_POLL_H
        fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);
        if ((fdmaskp = malloc(fdmasks)) == NULL)
                err(1, "malloc");
 #endif
 
-       seenalrm = seenint = 0;
-#ifdef SIGINFO
-       seeninfo = 0;
-#endif
-
        /* For control (ancillary) data received from recvmsg() */
        cm = (struct cmsghdr *)malloc(CONTROLLEN);
        if (cm == NULL)
@@ -1247,28 +1433,32 @@ main(int argc, char *argv[])
 
                /* signal handling */
                if (seenalrm) {
+                       seenalrm = 0;
                        /* last packet sent, timeout reached? */
                        if (npackets && ntransmitted >= npackets)
                                break;
+                       /* sweep done ? */
+                       if (sweepmax && datalen > sweepmax)
+                               break;
                        retransmit();
-                       seenalrm = 0;
                        continue;
                }
                if (seenint) {
-                       onint(SIGINT);
                        seenint = 0;
+                       onint(SIGINT);
                        continue;
                }
 #ifdef SIGINFO
                if (seeninfo) {
-                       summary();
                        seeninfo = 0;
+                       summary();
                        continue;
                }
 #endif
 
                if (options & F_FLOOD) {
-                       (void)pinger();
+                       if (pinger() != 0)
+                               break;
 #ifdef HAVE_POLL_H
                        timeout = 10;
 #else
@@ -1302,9 +1492,9 @@ main(int argc, char *argv[])
                                sleep(1);
                        }
                        continue;
-               } else if (cc == 0)
+               } else if (cc == 0) {
                        continue;
-
+               }
                m.msg_name = (caddr_t)&from;
                m.msg_namelen = sizeof(from);
                memset(&iov, 0, sizeof(iov));
@@ -1378,7 +1568,8 @@ main(int argc, char *argv[])
 void
 onsignal(int sig)
 {
-
+       fflush(stdout);
+       
        switch (sig) {
        case SIGALRM:
                seenalrm++;
@@ -1403,9 +1594,9 @@ retransmit(void)
 {
        struct itimerval itimer;
 
-       if (pinger() == 0)
+       if (pinger() == 0) {
                return;
-
+       }
        /*
         * If we're not transmitting any more packets, change the timer
         * to wait two round-trip times if we've received any packets or
@@ -1457,7 +1648,6 @@ int
 pinger(void)
 {
        struct icmp6_hdr *icp;
-       struct iovec iov[2];
        int i, cc;
        struct icmp6_nodeinfo *nip;
        int seq;
@@ -1465,6 +1655,13 @@ pinger(void)
        if (npackets && ntransmitted >= npackets)
                return(-1);     /* no more transmission */
 
+       if (sweepmax && sntransmitted == snpackets) {
+               datalen += sweepincr;
+               if (datalen > sweepmax)
+                       return(-1);     /* no more transmission */
+               sntransmitted = 0;
+       }
+
        icp = (struct icmp6_hdr *)outpack;
        nip = (struct icmp6_nodeinfo *)outpack;
        memset(icp, 0, sizeof(*icp));
@@ -1530,6 +1727,11 @@ pinger(void)
                icp->icmp6_code = 0;
                icp->icmp6_id = htons(ident);
                icp->icmp6_seq = ntohs(seq);
+               if (datalen >= sizeof(struct tv32)) {
+                       /* we can time transfer */
+                       timing = 1;
+               } else
+                       timing = 0;
                if (timing) {
                        struct timeval tv;
                        struct tv32 *tv32;
@@ -1546,12 +1748,17 @@ pinger(void)
                errx(1, "internal error; length mismatch");
 #endif
 
+       if ((options & F_CONNECT)) {
+               smsghdr.msg_name = NULL;
+               smsghdr.msg_namelen = 0;
+       } else {
        smsghdr.msg_name = (caddr_t)&dst;
        smsghdr.msg_namelen = sizeof(dst);
-       memset(&iov, 0, sizeof(iov));
-       iov[0].iov_base = (caddr_t)outpack;
-       iov[0].iov_len = cc;
-       smsghdr.msg_iov = iov;
+       }
+       memset(&smsgiov, 0, sizeof(smsgiov));
+       smsgiov[0].iov_base = (caddr_t)outpack;
+       smsgiov[0].iov_len = cc;
+       smsghdr.msg_iov = smsgiov;
        smsghdr.msg_iovlen = 1;
 
        i = sendmsg(s, &smsghdr, 0);
@@ -1562,6 +1769,7 @@ pinger(void)
                (void)printf("ping6: wrote %s %d chars, ret=%d\n",
                    hostname, cc, i);
        }
+       sntransmitted++;
        if (!(options & F_QUIET) && options & F_FLOOD)
                (void)write(STDOUT_FILENO, &DOT, 1);
 
@@ -1593,7 +1801,7 @@ dnsdecode(const u_char **sp, const u_char *ep, const u_char *base, char *buf,
     size_t bufsiz)
        /*base for compressed name*/
 {
-       int i;
+       int i = 0;
        const u_char *cp;
        char cresult[NS_MAXDNAME + 1];
        const u_char *comp;
@@ -1715,7 +1923,7 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
                return;
        }
 
-       if (how_so_traffic_class > 0)
+       if (use_recvmsg > 0)
                sotc = get_so_traffic_class(mhdr);
 
        if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {
@@ -1753,6 +1961,8 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
                else {
                        if (options & F_AUDIBLE)
                                (void)write(STDOUT_FILENO, &BBELL, 1);
+                       if (options & F_PRTIME)
+                               pr_currenttime();
                        (void)printf("%d bytes from %s, icmp_seq=%u", cc,
                            pr_addr(from, fromlen), seq);
                        (void)printf(" hlim=%d", hoplim);
@@ -1796,15 +2006,15 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
                if (TST(seq % mx_dup_ck)) {
                        ++nrepeats;
                        --nreceived;
-                       dupflag = 1;
                } else {
                        SET(seq % mx_dup_ck);
-                       dupflag = 0;
                }
 
                if (options & F_QUIET)
                        return;
 
+               if (options & F_PRTIME)
+                       pr_currenttime();
                (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
 
                switch (ntohs(ni->ni_code)) {
@@ -1941,6 +2151,8 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
                /* We've got something other than an ECHOREPLY */
                if (!(options & F_VERBOSE))
                        return;
+               if (options & F_PRTIME)
+                       pr_currenttime();
                (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
                pr_icmph(icp, end);
        }
@@ -1961,7 +2173,6 @@ pr_exthdrs(struct msghdr *mhdr)
        void    *bufp;
        struct cmsghdr *cm;
 
-       bufsize = 0;
        bufp = mhdr->msg_control;
        for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
             cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
@@ -1998,7 +2209,7 @@ pr_ip6opt(void *extbuf, size_t bufsize)
        struct ip6_hbh *ext;
        int currentlen;
        u_int8_t type;
-       socklen_t extlen, len, origextlen;
+       socklen_t extlen, len;
        void *databuf;
        size_t offset;
        u_int16_t value2;
@@ -2014,7 +2225,6 @@ pr_ip6opt(void *extbuf, size_t bufsize)
         *     subtract the size of a cmsg structure from the buffer size.
         */
        if (bufsize < (extlen  + CMSG_SPACE(0))) {
-               origextlen = extlen;
                extlen = bufsize - CMSG_SPACE(0);
                warnx("options truncated, showing only %u (total=%u)",
                    (unsigned int)(extlen / 8 - 1),
@@ -2034,14 +2244,14 @@ pr_ip6opt(void *extbuf, size_t bufsize)
                 */
                case IP6OPT_JUMBO:
                        offset = 0;
-                       offset = inet6_opt_get_val(databuf, offset,
+                       (void) inet6_opt_get_val(databuf, offset,
                            &value4, sizeof(value4));
                        printf("    Jumbo Payload Opt: Length %u\n",
                            (u_int32_t)ntohl(value4));
                        break;
                case IP6OPT_ROUTER_ALERT:
                        offset = 0;
-                       offset = inet6_opt_get_val(databuf, offset,
+                       (void)inet6_opt_get_val(databuf, offset,
                                                   &value2, sizeof(value2));
                        printf("    Router Alert Opt: Type %u\n",
                            ntohs(value2));
@@ -2187,7 +2397,7 @@ pr_suptypes(struct icmp6_nodeinfo *ni, size_t nilen)
        struct cbit {
                u_int16_t words;        /*32bit count*/
                u_int16_t skip;
-       } cbit;
+       } cbit = { 0, 0 };
 #define MAXQTYPES      (1 << 16)
        size_t off;
        int b;
@@ -2995,14 +3205,16 @@ nigroup(char *name)
        return strdup(hbuf);
 }
 
-uint32_t
-str2svc(const char *str)
+int
+str2sotc(const char *str, bool *valid)
 {
-       uint32_t svc;
+       int sotc = -1;
        char *endptr;
        
+       *valid = true;
+       
        if (str == NULL || *str == '\0')
-               svc = UINT32_MAX;
+               *valid = false;
        else if (strcasecmp(str, "BK_SYS") == 0)
                return SO_TC_BK_SYS;
        else if (strcasecmp(str, "BK") == 0)
@@ -3024,13 +3236,132 @@ str2svc(const char *str)
        else if (strcasecmp(str, "CTL") == 0)
                return SO_TC_CTL;
        else {
-               svc = strtoul(str, &endptr, 0);
+               sotc = (int)strtol(str, &endptr, 0);
                if (*endptr != '\0')
-                       svc = UINT32_MAX;
+                       *valid = false;
+       }
+       return (sotc);
+}
+
+int
+str2netservicetype(const char *str, bool *valid)
+{
+       int svc = -1;
+       char *endptr;
+       
+       *valid = true;
+       
+       if (str == NULL || *str == '\0')
+               *valid = false;
+       else if (strcasecmp(str, "BK") == 0)
+               return NET_SERVICE_TYPE_BK;
+       else if (strcasecmp(str, "BE") == 0)
+               return NET_SERVICE_TYPE_BE;
+       else if (strcasecmp(str, "VI") == 0)
+               return NET_SERVICE_TYPE_VI;
+       else if (strcasecmp(str, "SIG") == 0)
+               return NET_SERVICE_TYPE_SIG;
+       else if (strcasecmp(str, "VO") == 0)
+               return NET_SERVICE_TYPE_VO;
+       else if (strcasecmp(str, "RV") == 0)
+               return NET_SERVICE_TYPE_RV;
+       else if (strcasecmp(str, "AV") == 0)
+               return NET_SERVICE_TYPE_AV;
+       else if (strcasecmp(str, "OAM") == 0)
+               return NET_SERVICE_TYPE_OAM;
+       else if (strcasecmp(str, "RD") == 0)
+               return NET_SERVICE_TYPE_RD;
+       else {
+               svc = (int)strtol(str, &endptr, 0);
+               if (*endptr != '\0')
+                       *valid = false;
        }
        return (svc);
 }
 
+u_int8_t
+str2tclass(const char *str, bool *valid)
+{
+       u_int8_t dscp = -1;
+       char *endptr;
+       
+       *valid = true;
+       
+       if (str == NULL || *str == '\0')
+               *valid = false;
+       else if (strcasecmp(str, "DF") == 0)
+               dscp = _DSCP_DF;
+       else if (strcasecmp(str, "EF") == 0)
+               dscp = _DSCP_EF;
+       else if (strcasecmp(str, "VA") == 0)
+               dscp = _DSCP_VA;
+       
+       else if (strcasecmp(str, "CS0") == 0)
+               dscp = _DSCP_CS0;
+       else if (strcasecmp(str, "CS1") == 0)
+               dscp = _DSCP_CS1;
+       else if (strcasecmp(str, "CS2") == 0)
+               dscp = _DSCP_CS2;
+       else if (strcasecmp(str, "CS3") == 0)
+               dscp = _DSCP_CS3;
+       else if (strcasecmp(str, "CS4") == 0)
+               dscp = _DSCP_CS4;
+       else if (strcasecmp(str, "CS5") == 0)
+               dscp = _DSCP_CS5;
+       else if (strcasecmp(str, "CS6") == 0)
+               dscp = _DSCP_CS6;
+       else if (strcasecmp(str, "CS7") == 0)
+               dscp = _DSCP_CS7;
+       
+       else if (strcasecmp(str, "AF11") == 0)
+               dscp = _DSCP_AF11;
+       else if (strcasecmp(str, "AF12") == 0)
+               dscp = _DSCP_AF12;
+       else if (strcasecmp(str, "AF13") == 0)
+               dscp = _DSCP_AF13;
+       else if (strcasecmp(str, "AF21") == 0)
+               dscp = _DSCP_AF21;
+       else if (strcasecmp(str, "AF22") == 0)
+               dscp = _DSCP_AF22;
+       else if (strcasecmp(str, "AF23") == 0)
+               dscp = _DSCP_AF23;
+       else if (strcasecmp(str, "AF31") == 0)
+               dscp = _DSCP_AF31;
+       else if (strcasecmp(str, "AF32") == 0)
+               dscp = _DSCP_AF32;
+       else if (strcasecmp(str, "AF33") == 0)
+               dscp = _DSCP_AF33;
+       else if (strcasecmp(str, "AF41") == 0)
+               dscp = _DSCP_AF41;
+       else if (strcasecmp(str, "AF42") == 0)
+               dscp = _DSCP_AF42;
+       else if (strcasecmp(str, "AF43") == 0)
+               dscp = _DSCP_AF43;
+       
+       else {
+               unsigned long val = strtoul(str, &endptr, 0);
+               if (*endptr != '\0' || val > 255)
+                       *valid = false;
+               else
+                       return ((u_int8_t)val);
+       }
+       /* DSCP occupies the 6 upper bits of the traffic class field */
+       return (dscp << 2);
+}
+
+void
+pr_currenttime(void)
+{
+       int s;
+       struct timeval tv;
+       
+       gettimeofday(&tv, NULL);
+       
+       s = (tv.tv_sec + thiszone) % 86400;
+       printf("%02d:%02d:%02d.%06u ", s / 3600, (s % 3600) / 60, s % 60,
+              (u_int32_t)tv.tv_usec);
+}
+
 void
 usage(void)
 {
@@ -3048,13 +3379,21 @@ usage(void)
            "m"
 #endif
            "nNoqrRtvwW] "
-           "[-a addrtype] [-b bufsiz] [-B boundif] [-c count]\n"
+           "[-a addrtype] [-b bufsiz] [-c count]\n"
            "             [-g gateway] [-h hoplimit] [-I interface] [-i wait] [-l preload]"
 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
            " [-P policy]"
 #endif
            "\n"
            "             [-p pattern] [-S sourceaddr] [-s packetsize] [-z tclass] "
+           "[-k traffic_class] [-K net_service_type] "
            "[hops ...] host\n");
+       (void)fprintf(stderr, "Apple specific options (to be specified before hops or host like all options)\n");
+       (void)fprintf(stderr, "            -b boundif           # bind the socket to the interface\n");
+       (void)fprintf(stderr, "            -k traffic_class     # set traffic class socket option\n");
+       (void)fprintf(stderr, "            -K net_service_type  # set traffic class socket options\n");
+       (void)fprintf(stderr, "            -apple-connect       # call connect(2) in the socket\n");
+       (void)fprintf(stderr, "            -apple-time          # display current time\n");
+       (void)fprintf(stderr, "            -apple-progress      # show progress for debugging\n");
        exit(1);
 }
index fab5ce90d81dcd4e98458abf1ddb00a0146b9f60..8ce0f8fc2875e1d32f30d92c9da1aed01ca4555f 100644 (file)
@@ -145,7 +145,7 @@ main(int argc, char * const argv[]) {
         exit(0);
     }
     
-    while ((ch = getopt(argc, argv, "hf:l:r:t:p:m:M:L:R")) != -1) {
+    while ((ch = getopt(argc, argv, "hf:l:r:t:p:m:M:L:R:")) != -1) {
         switch (ch) {
             case 'h':
                 usage(argv[0]);
index c2508bdef7e2140610dc5eea9437b2a32af1a103..69ee7e1773487ae91fd9a3ecf4bbea5760fdeb3d 100644 (file)
@@ -127,6 +127,10 @@ int        getaddr(), rtmsg(), x25_makemask();
 int    prefixlen();
 extern char *iso_ntoa();
 
+static void
+inet_makenetandmask(in_addr_t net, struct sockaddr_in *sin,
+    struct sockaddr_in *sin_mask, in_addr_t bits);
+
 void usage __P((const char *)) __dead2;
 
 void
@@ -414,71 +418,49 @@ routename(sa)
 
 /*
  * Return the name of the network whose address is given.
- * The address is assumed to be that of a net or subnet, not a host.
+ * The address is assumed to be that of a net, not a host.
  */
 const char *
 netname(sa)
        struct sockaddr *sa;
 {
-       char *cp = 0;
+       char *cp = NULL;
        static char line[MAXHOSTNAMELEN + 1];
-       struct netent *np = 0;
-       in_addr_t net, mask;
+       struct netent *np = NULL;
        register in_addr_t i;
-       int subnetshift;
 
        switch (sa->sa_family) {
 
-       case AF_INET:
-           {   struct in_addr in;
-               in = ((struct sockaddr_in *)sa)->sin_addr;
-
-               i = in.s_addr = ntohl(in.s_addr);
-               if (in.s_addr == 0)
-                       cp = "default";
-               else if (!nflag) {
-                       if (IN_CLASSA(i)) {
-                               mask = IN_CLASSA_NET;
-                               subnetshift = 8;
-                       } else if (IN_CLASSB(i)) {
-                               mask = IN_CLASSB_NET;
-                               subnetshift = 8;
-                       } else {
-                               mask = IN_CLASSC_NET;
-                               subnetshift = 4;
-                       }
-                       /*
-                        * If there are more bits than the standard mask
-                        * would suggest, subnets must be in use.
-                        * Guess at the subnet mask, assuming reasonable
-                        * width subnet fields.
-                        */
-                       while (in.s_addr &~ mask)
-                               mask = mask >> subnetshift;
-                       net = in.s_addr & mask;
-                       while ((mask & 1) == 0)
-                               mask >>= 1, net >>= 1;
-                       np = getnetbyaddr(net, AF_INET);
-                       if (np)
-                               cp = np->n_name;
-               }
-               if (cp)
-                       strncpy(line, cp, sizeof(line));
-               else if ((in.s_addr & 0xffffff) == 0)
-                       (void) snprintf(line, sizeof(line), "%u", C(in.s_addr >> 24));
-               else if ((in.s_addr & 0xffff) == 0)
-                       (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) snprintf(line, sizeof(line), "%u.%u.%u", C(in.s_addr >> 24),
-                           C(in.s_addr >> 16), C(in.s_addr >> 8));
-               else
-                       (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;
-           }
-
+               case AF_INET:
+                  {   struct in_addr in;
+                      in = ((struct sockaddr_in *)sa)->sin_addr;
+
+                      i = in.s_addr = ntohl(in.s_addr);
+                      if (in.s_addr == 0)
+                              cp = "default";
+                      else if (!nflag) {
+                              np = getnetbyaddr(i, AF_INET);
+                              if (np != NULL)
+                                      cp = np->n_name;
+                      }
+#define C(x)    (unsigned)((x) & 0xff)
+                      if (cp != NULL)
+                              strncpy(line, cp, sizeof(line));
+                      else if ((in.s_addr & 0xffffff) == 0)
+                              (void) sprintf(line, "%u", C(in.s_addr >> 24));
+                      else if ((in.s_addr & 0xffff) == 0)
+                              (void) sprintf(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),
+                                              C(in.s_addr >> 16), C(in.s_addr >> 8));
+                      else
+                              (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+                                              C(in.s_addr >> 16), C(in.s_addr >> 8),
+                                              C(in.s_addr));
+#undef C
+                      break;
+                  }
 #ifdef INET6
        case AF_INET6:
        {
@@ -787,49 +769,43 @@ newroute(argc, argv)
        }
 }
 
-void
-inet_makenetandmask(net, sin, bits)
-       in_addr_t net, bits;
-       register struct sockaddr_in *sin;
+static void
+inet_makenetandmask(in_addr_t net, struct sockaddr_in *sin,
+    struct sockaddr_in *sin_mask, in_addr_t bits)
 {
-       in_addr_t addr, mask = 0;
-       register char *cp;
-
+       in_addr_t mask = 0;
+       
        rtm_addrs |= RTA_NETMASK;
-       if (bits) {
-               addr = net;
-               mask = 0xffffffff << (32 - bits);
-       } else if (net == 0)
-               mask = addr = 0;
-       else if (net < 128) {
-               addr = net << IN_CLASSA_NSHIFT;
-               mask = IN_CLASSA_NET;
-       } else if (net < 65536) {
-               addr = net << IN_CLASSB_NSHIFT;
-               mask = IN_CLASSB_NET;
-       } else if (net < 16777216L) {
-               addr = net << IN_CLASSC_NSHIFT;
-               mask = IN_CLASSC_NET;
-       } else {
-               addr = net;
-               if ((addr & IN_CLASSA_HOST) == 0)
-                       mask =  IN_CLASSA_NET;
-               else if ((addr & IN_CLASSB_HOST) == 0)
-                       mask =  IN_CLASSB_NET;
-               else if ((addr & IN_CLASSC_HOST) == 0)
-                       mask =  IN_CLASSC_NET;
-               else
-                       mask = -1;
+       /*
+        * MSB of net should be meaningful. 0/0 is exception.
+        */
+       if (net > 0)
+               while ((net & 0xff000000) == 0)
+                       net <<= 8;
+
+       /*
+        * If no /xx was specified we must calculate the
+        * CIDR address.
+        */
+       if ((bits == 0) && (net != 0)) {
+               u_long i, j;
+
+               for(i = 0, j = 0xff; i < 4; i++)  {
+                       if (net & j) {
+                               break;
+                       }
+                       j <<= 8;
+               }
+               /* i holds the first non zero bit */
+               bits = 32 - (i*8);      
        }
-       sin->sin_addr.s_addr = htonl(addr);
-       sin = &so_mask.sin;
-       sin->sin_addr.s_addr = htonl(mask);
-       sin->sin_len = 0;
-       sin->sin_family = 0;
-       cp = (char *)(&sin->sin_addr + 1);
-       while (*--cp == 0 && cp > (char *)sin)
-               ;
-       sin->sin_len = 1 + cp - (char *)sin;
+       if (bits != 0)
+               mask = 0xffffffff << (32 - bits);
+
+       sin->sin_addr.s_addr = htonl(net);
+       sin_mask->sin_addr.s_addr = htonl(mask);
+       sin_mask->sin_len = sizeof(struct sockaddr_in);
+       sin_mask->sin_family = AF_INET;
 }
 
 #ifdef INET6
@@ -1026,17 +1002,18 @@ getaddr(which, s, hpp)
        q = strchr(s,'/');
        if (q && which == RTA_DST) {
                *q = '\0';
-               if ((val = inet_addr(s)) != INADDR_NONE) {
+               if ((val = inet_network(s)) != INADDR_NONE) {
                        inet_makenetandmask(
-                               ntohl(val), &su->sin, strtoul(q+1, 0, 0));
+                               val, &su->sin, (struct sockaddr_in *)&so_mask,
+                               strtoul(q+1, 0, 0));
                        return (0);
                }
                *q = '/';
        }
        if ((which != RTA_DST || forcenet == 0) &&
-           (val = inet_addr(s)) != INADDR_NONE) {
-               su->sin.sin_addr.s_addr = val;
-               if (which != RTA_DST ||
+           inet_aton(s, &su->sin.sin_addr)) {
+               val = su->sin.sin_addr.s_addr;
+               if (which != RTA_DST || forcehost ||
                    inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
                        return (1);
                else {
@@ -1048,7 +1025,7 @@ getaddr(which, s, hpp)
            ((val = inet_network(s)) != INADDR_NONE ||
            ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0))) {
 netdone:
-               inet_makenetandmask(val, &su->sin, 0);
+               inet_makenetandmask(val, &su->sin, (struct sockaddr_in *)&so_mask, 0);
                return (0);
        }
        hp = gethostbyname(s);