--- /dev/null
+.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
--- /dev/null
+/*
+ * 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));
+ }
+}
+
+
#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 =
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),
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 = {
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:
/*
- * Copyright (c) 2009-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2015 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sysexits.h>
#include "ifconfig.h"
Perror(vname);
}
-#ifdef SIOCGIFCAP
void
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,
}
}
+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)
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,
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" \
"\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"
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");
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 &&
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');
}
putchar('\n');
}
}
-#endif
tunnel_status(s);
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 "
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;
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
+++ /dev/null
-.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.
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-.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.
+++ /dev/null
-/*
- * 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;
-}
#include "kdump.h"
#include <arpa/inet.h>
+#include <assert.h>
#include <stdint.h>
#include <ctype.h>
#include <errno.h>
#include "kdumpsubs.h"
+#define DEFAULT_KDUMPD_PORTNO (1069)
#define TIMEOUT 2
int peer;
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));
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;
case 'u':
chuser = optarg;
break;
+ case 'w':
+ server_mode = 0;
+ break;
default:
syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
}
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);
+ }
}
}
}
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);
}
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);
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.
} 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) {
}
}
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
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
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];
sum->ift_fb - total->ift_fb);
}
*total = *sum;
+
+ free(ifmsuppall);
}
if (!first)
putchar('\n');
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;
}
}
+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)
{
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;
}
#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)
case PKTSCHEDT_QFQ:
c = "QFQ";
break;
+ case PKTSCHEDT_FQ_CODEL:
+ c = "FQ_CODEL";
+ break;
default:
c = "UNKNOWN";
break;
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)
{
}
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;
}
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;
}
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)
((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(
"\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),
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
/*
- * Copyright (c) 2008-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
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");
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);
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) {
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");
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");
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");
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);
}
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);
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");
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);
#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,
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;
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;
{
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) {
#endif
static const char *const socktype[] =
- { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
+ { "#0", "stream", "dgram", "raw" };
void
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
72B732EB1899B19A0060E6D4 /* PBXTargetDependency */,
72179EAE146233390098FB3E /* PBXTargetDependency */,
7282BA571AFBDEAD005DE836 /* PBXTargetDependency */,
+ 72946F4C1BBF063800087E35 /* PBXTargetDependency */,
034E4469100BDD00009CA3DC /* PBXTargetDependency */,
565825AF13392239003E5FA5 /* PBXTargetDependency */,
72311F4D194A34F500EB4788 /* PBXTargetDependency */,
72B732E91899B18F0060E6D4 /* PBXTargetDependency */,
723C7074142BB003007C87E9 /* PBXTargetDependency */,
7282BA5B1AFBDED3005DE836 /* PBXTargetDependency */,
+ 7263724B1BCC709900E4B026 /* PBXTargetDependency */,
7261217D0EE8896800AFED1B /* PBXTargetDependency */,
4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */,
724DABC30EE890A6008900D0 /* PBXTargetDependency */,
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 = (
.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
.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
.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
.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
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)
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.
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
/*
- * Copyright (c) 1999-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#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))
#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
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 */
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)
{
#ifdef IPSEC_POLICY_IPSEC
policy_in = policy_out = NULL;
#endif
+ bool valid;
/*
* Do the stuff that we need root priv's for *first*, and
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':
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;
}
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;
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);
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;
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();
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));
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;
(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)
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));
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");
(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.
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
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);
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) {
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);
(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);
}
}
-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)
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
{
(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);
}
.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
.Op Fl k Ar trafficclass
.Ek
.Bk -words
+.Op Fl K Ar netservicetype
+.Ek
+.Bk -words
.Op Fl l Ar preload
.Ek
.Bk -words
.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
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
.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
.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
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
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.
/*
- * Copyright (c) 2002-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <fcntl.h>
#include <math.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#endif
#include <sysexits.h>
+#include <getopt.h>
#ifdef IPSEC
#include <netinet6/ah.h>
#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
#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
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 */
/* for ancillary data(advanced API) */
struct msghdr smsghdr;
-struct iovec smsgiov;
+struct iovec smsgiov[2];
char *scmsg = NULL;
volatile sig_atomic_t seenalrm;
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 *);
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
#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));
#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':
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;
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;
case 'p': /* fill buffer with user pattern */
options |= F_PINGFILLED;
fill((char *)datap, optarg);
- break;
+ break;
case 'q':
options |= F_QUIET;
break;
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
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*/
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;
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;
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;
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) {
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)) {
/*
#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)
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
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);
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)
/* 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
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));
void
onsignal(int sig)
{
-
+ fflush(stdout);
+
switch (sig) {
case SIGALRM:
seenalrm++;
{
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
pinger(void)
{
struct icmp6_hdr *icp;
- struct iovec iov[2];
int i, cc;
struct icmp6_nodeinfo *nip;
int seq;
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));
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;
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);
(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);
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;
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)) {
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);
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)) {
/* 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);
}
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)) {
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;
* 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),
*/
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));
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;
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)
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)
{
"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);
}
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]);
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
/*
* 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:
{
}
}
-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
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 {
((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);