+.\" Copyright (c) 2012 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) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
A
.Ql #
character will mark the rest of the line as a comment.
+.It Fl x
+Show extended link-layer reachability information in addition to that shown by
+the
+.Fl l
+flag.
.El
.Sh SEE ALSO
.Xr inet 3 ,
/*
- * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
static char *sec2str(time_t);
static int nflag; /* no reverse dns lookups */
+static int xflag; /* extended link-layer reachability information */
static char *rifname;
static int expire_time, flags, doing_proxy, proxy_only;
int lflag = 0;
uint32_t ifindex = 0;
- while ((ch = getopt(argc, argv, "andflsSi:")) != -1)
+ while ((ch = getopt(argc, argv, "andflsSi:x")) != -1)
switch((char)ch) {
case 'a':
aflag = 1;
case 'i':
rifname = optarg;
break;
+ case 'x':
+ xflag = 1;
+ lflag = 1;
+ break;
case '?':
default:
usage();
usage();
if (lflag) {
printf("%-23s %-17s %-9.9s %-9.9s %8.8s %4s "
- "%4s\n", "Neighbor", "Linklayer Address",
- "Expire(O)", "Expire(I)", "Netif", "Refs",
- "Prbs");
+ "%4s", "Neighbor",
+ "Linklayer Address", "Expire(O)",
+ "Expire(I)", "Netif", "Refs", "Prbs");
+ if (xflag)
+ printf(" %-7.7s %-7.7s %-7.7s",
+ "RSSI", "LQM", "NPM");
+ printf("\n");
search_ext(0, print_entry_ext);
} else {
search(0, print_entry);
printf(" %4d", ertm->rtm_ri.ri_refcnt);
if (ertm->rtm_ri.ri_probes)
printf(" %4d", ertm->rtm_ri.ri_probes);
+
+ if (xflag) {
+ if (!ertm->rtm_ri.ri_probes)
+ printf(" %-4.4s", "none");
+
+ if (ertm->rtm_ri.ri_rssi != IFNET_RSSI_UNKNOWN)
+ printf(" %7d", ertm->rtm_ri.ri_rssi);
+ else
+ printf(" %-7.7s", "unknown");
+
+ switch (ertm->rtm_ri.ri_lqm)
+ {
+ case IFNET_LQM_THRESH_OFF:
+ printf(" %-7.7s", "off");
+ break;
+ case IFNET_LQM_THRESH_UNKNOWN:
+ printf(" %-7.7s", "unknown");
+ break;
+ case IFNET_LQM_THRESH_POOR:
+ printf(" %-7.7s", "poor");
+ break;
+ case IFNET_LQM_THRESH_GOOD:
+ printf(" %-7.7s", "good");
+ break;
+ default:
+ printf(" %7d", ertm->rtm_ri.ri_lqm);
+ break;
+ }
+
+ switch (ertm->rtm_ri.ri_npm)
+ {
+ case IFNET_NPM_THRESH_UNKNOWN:
+ printf(" %-7.7s", "unknown");
+ break;
+ case IFNET_NPM_THRESH_NEAR:
+ printf(" %-7.7s", "near");
+ break;
+ case IFNET_NPM_THRESH_GENERAL:
+ printf(" %-7.7s", "general");
+ break;
+ case IFNET_NPM_THRESH_FAR:
+ printf(" %-7.7s", "far");
+ break;
+ default:
+ printf(" %7d", ertm->rtm_ri.ri_npm);
+ break;
+ }
+ }
}
printf("\n");
}
--- /dev/null
+.\"
+.\" $FreeBSD: /repoman/r/ncvs/src/sbin/ipfw/ipfw.8,v 1.63.2.38 2003/07/28 07:15:13 luigi Exp $
+.\"
+.Dd August 13, 2002
+.Dt DNCTL 8
+.Os Darwin
+.Sh NAME
+.Nm dnctl
+.Nd Traffic shaper control program
+.Sh SYNOPSIS
+.Nm
+.Op Fl anqs
+.Brq Cm list | show
+.Nm
+.Op Fl f | q
+.Cm flush
+.Nm
+.Op Fl q
+.Brq Cm delete
+.Op Ar number ...
+.Nm
+.Brq Cm pipe | queue
+.Ar number
+.Cm config
+.Ar config-options
+.Nm
+.Op Fl s Op Ar field
+.Brq Cm pipe | queue
+.Brq Cm delete | list | show
+.Op Ar number ...
+.Nm
+.Op Fl nq
+.Oo
+.Fl p Ar preproc
+.Oo
+.Ar preproc-flags
+.Oc
+.Oc
+.Ar pathname
+.Sh DESCRIPTION
+.Pp
+The
+.Nm
+utility is the user interface for controlling the
+.Xr dummynet 4
+traffic shaper.
+.Pp
+.Nm dummynet
+operates by first using a packet filter to classify packets and divide them into
+.Em flows ,
+using any match pattern that can be used in
+.Nm
+rules.
+Depending on local policies, a flow can contain packets for a single
+TCP connection, or from/to a given host, or entire subnet, or a
+protocol type, etc.
+.Pp
+Packets belonging to the same flow are then passed to either of two
+different objects, which implement the traffic regulation:
+.Bl -hang -offset XXXX
+.It Em pipe
+A pipe emulates a link with given bandwidth, propagation delay,
+queue size and packet loss rate.
+Packets are queued in front of the pipe as they come out from the classifier,
+and then transferred to the pipe according to the pipe's parameters.
+.Pp
+.It Em queue
+A queue
+is an abstraction used to implement the WF2Q+
+(Worst-case Fair Weighted Fair Queueing) policy, which is
+an efficient variant of the WFQ policy.
+.br
+The queue associates a
+.Em weight
+and a reference pipe to each flow, and then all backlogged (i.e.,
+with packets queued) flows linked to the same pipe share the pipe's
+bandwidth proportionally to their weights.
+Note that weights are not priorities; a flow with a lower weight
+is still guaranteed to get its fraction of the bandwidth even if a
+flow with a higher weight is permanently backlogged.
+.Pp
+.El
+In practice,
+.Em pipes
+can be used to set hard limits to the bandwidth that a flow can use, whereas
+.Em queues
+can be used to determine how different flow share the available bandwidth.
+.Pp
+The
+.Em pipe
+and
+.Em queue
+configuration commands are the following:
+.Bd -ragged -offset indent
+.Cm pipe Ar number Cm config Ar pipe-configuration
+.Pp
+.Cm queue Ar number Cm config Ar queue-configuration
+.Ed
+.Pp
+The following parameters can be configured for a pipe:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm bw Ar bandwidth | device
+Bandwidth, measured in
+.Sm off
+.Op Cm K | M
+.Brq Cm bit/s | Byte/s .
+.Sm on
+.Pp
+A value of 0 (default) means unlimited bandwidth.
+The unit must immediately follow the number, as in
+.Pp
+.Dl "dnctl pipe 1 config bw 300Kbit/s"
+.Pp
+If a device name is specified instead of a numeric value, as in
+.Pp
+.Dl "dnctl pipe 1 config bw tun0"
+.Pp
+then the transmit clock is supplied by the specified device.
+At the moment no
+device supports this
+functionality.
+.Pp
+.It Cm delay Ar ms-delay
+Propagation delay, measured in milliseconds.
+The value is rounded to the next multiple of the clock tick
+(typically 10ms, but it is a good practice to run kernels
+with
+.Dq "options HZ=1000"
+to reduce
+the granularity to 1ms or less).
+Default value is 0, meaning no delay.
+.El
+.Pp
+The following parameters can be configured for a queue:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm pipe Ar pipe_nr
+Connects a queue to the specified pipe.
+Multiple queues (with the same or different weights) can be connected to
+the same pipe, which specifies the aggregate rate for the set of queues.
+.Pp
+.It Cm weight Ar weight
+Specifies the weight to be used for flows matching this queue.
+The weight must be in the range 1..100, and defaults to 1.
+.El
+.Pp
+Finally, the following parameters can be configured for both
+pipes and queues:
+.Pp
+.Bl -tag -width XXXX -compact
+.It Cm buckets Ar hash-table-size
+Specifies the size of the hash table used for storing the
+various queues.
+Default value is 64 controlled by the
+.Xr sysctl 8
+variable
+.Em net.inet.ip.dummynet.hash_size ,
+allowed range is 16 to 65536.
+.Pp
+.It Cm mask Ar mask-specifier
+Packets sent to a given pipe or queue by an
+.Nm
+rule can be further classified into multiple flows, each of which is then
+sent to a different
+.Em dynamic
+pipe or queue.
+A flow identifier is constructed by masking the IP addresses,
+ports and protocol types as specified with the
+.Cm mask
+options in the configuration of the pipe or queue.
+For each different flow identifier, a new pipe or queue is created
+with the same parameters as the original object, and matching packets
+are sent to it.
+.Pp
+Thus, when
+.Em dynamic pipes
+are used, each flow will get the same bandwidth as defined by the pipe,
+whereas when
+.Em dynamic queues
+are used, each flow will share the parent's pipe bandwidth evenly
+with other flows generated by the same queue (note that other queues
+with different weights might be connected to the same pipe).
+.br
+Available mask specifiers are a combination of one or more of the following:
+.Pp
+.Cm dst-ip Ar mask ,
+.Cm dst-ip6 Ar mask ,
+.Cm src-ip Ar mask ,
+.Cm src-ip6 Ar mask ,
+.Cm dst-port Ar mask ,
+.Cm src-port Ar mask ,
+.Cm proto Ar mask
+or
+.Cm all ,
+.Pp
+where the latter means all bits in all fields are significant.
+.Pp
+.It Cm noerror
+When a packet is dropped by a dummynet queue or pipe, the error
+is normally reported to the caller routine in the kernel, in the
+same way as it happens when a device queue fills up. Setting this
+option reports the packet as successfully delivered, which can be
+needed for some experimental setups where you want to simulate
+loss or congestion at a remote router.
+.Pp
+.It Cm plr Ar packet-loss-rate
+Packet loss rate.
+Argument
+.Ar packet-loss-rate
+is a floating-point number between 0 and 1, with 0 meaning no
+loss, 1 meaning 100% loss.
+The loss rate is internally represented on 31 bits.
+.Pp
+.It Cm queue Brq Ar slots | size Ns Cm Kbytes
+Queue size, in
+.Ar slots
+or
+.Cm KBytes .
+Default value is 50 slots, which
+is the typical queue size for Ethernet devices.
+Note that for slow speed links you should keep the queue
+size short or your traffic might be affected by a significant
+queueing delay.
+E.g., 50 max-sized ethernet packets (1500 bytes) mean 600Kbit
+or 20s of queue on a 30Kbit/s pipe.
+Even worse effect can result if you get packets from an
+interface with a much larger MTU, e.g. the loopback interface
+with its 16KB packets.
+.Pp
+.It Cm red | gred Ar w_q Ns / Ns Ar min_th Ns / Ns Ar max_th Ns / Ns Ar max_p
+Make use of the RED (Random Early Detection) queue management algorithm.
+.Ar w_q
+and
+.Ar max_p
+are floating
+point numbers between 0 and 1 (0 not included), while
+.Ar min_th
+and
+.Ar max_th
+are integer numbers specifying thresholds for queue management
+(thresholds are computed in bytes if the queue has been defined
+in bytes, in slots otherwise).
+The
+.Xr dummynet 4
+also supports the gentle RED variant (gred).
+.Pp
+Three
+.Xr sysctl 8
+variables can be used to control the RED behaviour:
+.Bl -tag -width indent
+.It Em net.inet.ip.dummynet.red_lookup_depth
+specifies the accuracy in computing the average queue
+when the link is idle (defaults to 256, must be greater than zero)
+.It Em net.inet.ip.dummynet.red_avg_pkt_size
+specifies the expected average packet size (defaults to 512, must be
+greater than zero)
+.It Em net.inet.ip.dummynet.red_max_pkt_size
+specifies the expected maximum packet size, only used when queue
+thresholds are in bytes (defaults to 1500, must be greater than zero).
+.El
+.El
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+While listing, show counter values.
+The
+.Cm show
+command just implies this option.
+.It Fl f
+Don't ask for confirmation for commands that can cause problems
+if misused,
+.No i.e. Cm flush .
+If there is no tty associated with the process, this is implied.
+.It Fl h
+Displays a short help.
+.It Fl n
+Only check syntax of the command strings, without actually passing
+them to the kernel.
+.It Fl q
+While
+.Cm add Ns ing ,
+.Cm zero Ns ing ,
+.Cm resetlog Ns ging
+or
+.Cm flush Ns ing ,
+be quiet about actions
+(implies
+.Fl f ) .
+This is useful for adjusting rules by executing multiple
+.Nm
+commands in a script
+or by processing a file of many
+.Nm
+rules across a remote login session.
+If a
+.Cm flush
+is performed in normal (verbose) mode (with the default kernel
+configuration), it prints a message.
+Because all rules are flushed, the message might not be delivered
+to the login session, causing the remote login session to be closed
+and the remainder of the ruleset to not be processed.
+Access to the console would then be required to recover.
+.It Fl s Op Ar field
+While listing pipes, sort according to one of the four
+counters (total or current packets or bytes).
+.It Fl v
+Be verbose.
+.El
+.Pp
+To ease configuration, rules can be put into a file which is
+processed using
+.Nm
+as shown in the last synopsis line.
+An absolute
+.Ar pathname
+must be used.
+The file will be read line by line and applied as arguments to the
+.Nm
+utility.
+.Pp
+Optionally, a preprocessor can be specified using
+.Fl p Ar preproc
+where
+.Ar pathname
+is to be piped through.
+Useful preprocessors include
+.Xr cpp 1
+and
+.Xr m4 1 .
+If
+.Ar preproc
+doesn't start with a slash
+.Pq Ql /
+as its first character, the usual
+.Ev PATH
+name search is performed.
+Care should be taken with this in environments where not all
+file systems are mounted (yet) by the time
+.Nm
+is being run (e.g. when they are mounted over NFS).
+Once
+.Fl p
+has been specified, any additional arguments as passed on to the preprocessor
+for interpretation.
+This allows for flexible configuration files (like conditionalizing
+them on the local hostname) and the use of macros to centralize
+frequently required arguments like IP addresses.
+.El
+.Sh CHECKLIST
+Here are some important points to consider when designing your
+rules:
+.Bl -bullet
+.It
+Remember that you filter both packets going
+.Cm in
+and
+.Cm out .
+Most connections need packets going in both directions.
+.It
+Remember to test very carefully.
+It is a good idea to be near the console when doing this.
+If you cannot be near the console,
+use an auto-recovery script such as the one in
+.Pa /usr/share/examples/ipfw/change_rules.sh .
+.It
+Don't forget the loopback interface.
+.El
+.Sh SYSCTL VARIABLES
+A set of
+.Xr sysctl 8
+variables controls the behaviour of the
+.Nm dummynet
+module.
+These are shown below together with their default value
+(but always check with the
+.Xr sysctl 8
+command what value is actually in use) and meaning:
+.Bl -tag -width indent
+.It Em net.inet.ip.dummynet.expire : No 1
+Lazily delete dynamic pipes/queue once they have no pending traffic.
+You can disable this by setting the variable to 0, in which case
+the pipes/queues will only be deleted when the threshold is reached.
+.It Em net.inet.ip.dummynet.hash_size : No 64
+Default size of the hash table used for dynamic pipes/queues.
+This value is used when no
+.Cm buckets
+option is specified when configuring a pipe/queue.
+.It Em net.inet.ip.dummynet.max_chain_len : No 16
+Target value for the maximum number of pipes/queues in a hash bucket.
+The product
+.Cm max_chain_len*hash_size
+is used to determine the threshold over which empty pipes/queues
+will be expired even when
+.Cm net.inet.ip.dummynet.expire=0 .
+.It Em net.inet.ip.dummynet.red_lookup_depth : No 256
+.It Em net.inet.ip.dummynet.red_avg_pkt_size : No 512
+.It Em net.inet.ip.dummynet.red_max_pkt_size : No 1500
+Parameters used in the computations of the drop probability
+for the RED algorithm.
+.El
+.Sh EXAMPLES
+The following rules show some of the applications of
+.Xr dummynet 4
+for simulations and the like. The examples use the obsolete
+.Nm ipfw
+command for illustration only as the use of
+.Nm ipfw
+is discouraged.
+.Pp
+This rule drops random incoming packets with a probability
+of 5%:
+.Pp
+.Dl "ipfw add pipe 10 ip from any to any"
+.Dl "dnctl pipe 10 config plr 0.05"
+.Pp
+We can use pipes to artificially limit bandwidth, e.g. on a
+machine acting as a router, if we want to limit traffic from
+local clients on 192.168.2.0/24 we do:
+.Pp
+.Dl "ipfw add pipe 1 ip from 192.168.2.0/24 to any out"
+.Dl "dnctl pipe 1 config bw 300Kbit/s queue 50KBytes"
+.Pp
+note that we use the
+.Cm out
+modifier so that the rule is not used twice.
+Remember in fact that
+.Nm
+rules are checked both on incoming and outgoing packets.
+.Pp
+Should we want to simulate a bidirectional link with bandwidth
+limitations, the correct way is the following:
+.Pp
+.Dl "ipfw add pipe 1 ip from any to any out"
+.Dl "ipfw add pipe 2 ip from any to any in"
+.Dl "dnctl pipe 1 config bw 64Kbit/s queue 10Kbytes"
+.Dl "dnctl pipe 2 config bw 64Kbit/s queue 10Kbytes"
+.Pp
+The above can be very useful, e.g. if you want to see how
+your fancy Web page will look for a residential user who
+is connected only through a slow link.
+You should not use only one pipe for both directions, unless
+you want to simulate a half-duplex medium (e.g. AppleTalk,
+Ethernet, IRDA).
+It is not necessary that both pipes have the same configuration,
+so we can also simulate asymmetric links.
+.Pp
+Should we want to verify network performance with the RED queue
+management algorithm:
+.Pp
+.Dl "ipfw add pipe 1 ip from any to any"
+.Dl "dnctl pipe 1 config bw 500Kbit/s queue 100 red 0.002/30/80/0.1"
+.Pp
+Another typical application of the traffic shaper is to
+introduce some delay in the communication.
+This can significantly affect applications which do a lot of Remote
+Procedure Calls, and where the round-trip-time of the
+connection often becomes a limiting factor much more than
+bandwidth:
+.Pp
+.Dl "ipfw add pipe 1 ip from any to any out"
+.Dl "ipfw add pipe 2 ip from any to any in"
+.Dl "dnctl pipe 1 config delay 250ms bw 1Mbit/s"
+.Dl "dnctl pipe 2 config delay 250ms bw 1Mbit/s"
+.Pp
+Per-flow queueing can be useful for a variety of purposes.
+A very simple one is counting traffic:
+.Pp
+.Dl "ipfw add pipe 1 tcp from any to any"
+.Dl "ipfw add pipe 1 udp from any to any"
+.Dl "ipfw add pipe 1 ip from any to any"
+.Dl "dnctl pipe 1 config mask all"
+.Pp
+The above set of rules will create queues (and collect
+statistics) for all traffic.
+Because the pipes have no limitations, the only effect is
+collecting statistics.
+Note that we need 3 rules, not just the last one, because
+when
+.Nm
+tries to match IP packets it will not consider ports, so we
+would not see connections on separate ports as different
+ones.
+.Pp
+A more sophisticated example is limiting the outbound traffic
+on a net with per-host limits, rather than per-network limits:
+.Pp
+.Dl "ipfw add pipe 1 ip from 192.168.2.0/24 to any out"
+.Dl "ipfw add pipe 2 ip from any to 192.168.2.0/24 in"
+.Dl "dnctl pipe 1 config mask src-ip 0x000000ff bw 200Kbit/s queue 20Kbytes"
+.Dl "dnctl pipe 2 config mask dst-ip 0x000000ff bw 200Kbit/s queue 20Kbytes"
+.Ss SETS OF RULES
+To add a set of rules atomically, e.g. set 18:
+.Pp
+.Dl "ipfw set disable 18"
+.Dl "ipfw add NN set 18 ... # repeat as needed"
+.Dl "ipfw set enable 18"
+.Pp
+To delete a set of rules atomically the command is simply:
+.Pp
+.Dl "ipfw delete set 18"
+.Pp
+To test a ruleset and disable it and regain control if something goes wrong:
+.Pp
+.Dl "ipfw set disable 18"
+.Dl "ipfw add NN set 18 ... # repeat as needed"
+.Dl "ipfw set enable 18; echo done; sleep 30 && ipfw set disable 18"
+.Pp
+Here if everything goes well, you press control-C before the "sleep"
+terminates, and your ruleset will be left active. Otherwise, e.g. if
+you cannot access your box, the ruleset will be disabled after
+the sleep terminates thus restoring the previous situation.
+.Sh SEE ALSO
+.Xr cpp 1 ,
+.Xr m4 1 ,
+.Xr dummynet 4 ,
+.Xr ip 4 ,
+.Xr ipfirewall 4 ,
+.Xr protocols 5 ,
+.Xr services 5 ,
+.Xr sysctl 8
+.Sh AUTHORS
+.An Ugen J. S. Antsilevich ,
+.An Poul-Henning Kamp ,
+.An Alex Nash ,
+.An Archie Cobbs ,
+.An Luigi Rizzo .
+.Pp
+.An -nosplit
+API based upon code written by
+.An Daniel Boulet
+for BSDI.
+.Pp
+Work on
+.Xr dummynet 4
+traffic shaper supported by Akamba Corp.
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 2.0 .
+.Xr dummynet 4
+was introduced in
+.Fx 2.2.8 .
+Stateful extensions were introduced in
+.Fx 4.0 .
+.Nm ipfw2
+was introduced in Summer 2002.
--- /dev/null
+/*
+ * Copyright (c) 2002-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * Ripped off ipfw2.c
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.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/ip.h>
+#include <netinet/ip_dummynet.h>
+#include <arpa/inet.h>
+
+
+int
+do_quiet, /* Be quiet in add and flush */
+do_pipe, /* this cmd refers to a pipe */
+do_sort, /* field to sort results (0 = no) */
+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;
+};
+
+enum tokens {
+ TOK_NULL=0,
+
+ TOK_ACCEPT,
+ TOK_COUNT,
+ TOK_PIPE,
+ TOK_QUEUE,
+
+ 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,
+
+ TOK_DSTIP6,
+ TOK_SRCIP6,
+};
+
+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 },
+ { "dst-ipv6", TOK_DSTIP6},
+ { "dst-ip6", TOK_DSTIP6},
+ { "src-ipv6", TOK_SRCIP6},
+ { "src-ip6", TOK_SRCIP6},
+ { "dummynet-params", TOK_NULL },
+ { NULL, 0 } /* terminator */
+};
+
+static void show_usage(void);
+
+
+void n2mask(struct in6_addr *, int );
+unsigned long long align_uint64(const uint64_t *);
+
+/* n2mask sets n bits of the mask */
+void
+n2mask(struct in6_addr *mask, int n)
+{
+ static int minimask[9] =
+ { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+ u_char *p;
+
+ memset(mask, 0, sizeof(struct in6_addr));
+ p = (u_char *) mask;
+ for (; n > 0; p++, n -= 8) {
+ if (n >= 8)
+ *p = 0xff;
+ else
+ *p = minimask[n];
+ }
+ return;
+}
+
+/*
+ * The following is used to generate a printable argument for
+ * 64-bit numbers, irrespective of platform alignment and bit size.
+ * Because all the printf in this program use %llu as a format,
+ * we just return an unsigned long long, which is larger than
+ * we need in certain cases, but saves the hassle of using
+ * PRIu64 as a format specifier.
+ * We don't care about inlining, this is not performance critical code.
+ */
+unsigned long long
+align_uint64(const 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, socklen_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");
+
+ if (optname == IP_DUMMYNET_GET)
+ i = getsockopt(s, IPPROTO_IP, optname, optval, optlen);
+ else
+ i = setsockopt(s, IPPROTO_IP, optname, optval, optlen ? *optlen : 0);
+ 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;
+ size_t 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;
+};
+
+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;
+ int index_printed, indexes = 0;
+ char buff[255];
+ struct protoent *pe;
+
+ 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(struct dn_flow_queue), sort_q);
+
+ /* Print IPv4 flows */
+ for (l = 0; l < fs->rq_elements; l++) {
+ struct in_addr ina;
+
+ /* XXX: Should check for IPv4 flows */
+ if (IS_IP6_FLOW_ID(&(q[l].id)))
+ continue;
+
+ if (!index_printed) {
+ index_printed = 1;
+ if (indexes > 0) /* currently a no-op */
+ printf("\n");
+ indexes++;
+ 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);
+
+ printf("BKT Prot ___Source IP/port____ "
+ "____Dest. IP/port____ "
+ "Tot_pkt/bytes Pkt/Byte Drp\n");
+ }
+
+ 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);
+ ina.s_addr = htonl(q[l].id.src_ip);
+ 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("%4llu %8llu %2u %4u %3u\n",
+ align_uint64(&q[l].tot_pkts),
+ align_uint64(&q[l].tot_bytes),
+ q[l].len, q[l].len_bytes, q[l].drops);
+ if (verbose)
+ printf(" S %20llu F %20llu\n",
+ align_uint64(&q[l].S), align_uint64(&q[l].F));
+ }
+
+ /* Print IPv6 flows */
+ index_printed = 0;
+ for (l = 0; l < fs->rq_elements; l++) {
+ if (!IS_IP6_FLOW_ID(&(q[l].id)))
+ continue;
+
+ if (!index_printed) {
+ index_printed = 1;
+ if (indexes > 0)
+ printf("\n");
+ indexes++;
+ printf("\n mask: proto: 0x%02x, flow_id: 0x%08x, ",
+ fs->flow_mask.proto, fs->flow_mask.flow_id6);
+ inet_ntop(AF_INET6, &(fs->flow_mask.src_ip6),
+ buff, sizeof(buff));
+ printf("%s/0x%04x -> ", buff, fs->flow_mask.src_port);
+ inet_ntop( AF_INET6, &(fs->flow_mask.dst_ip6),
+ buff, sizeof(buff) );
+ printf("%s/0x%04x\n", buff, fs->flow_mask.dst_port);
+
+ printf("BKT ___Prot___ _flow-id_ "
+ "______________Source IPv6/port_______________ "
+ "_______________Dest. IPv6/port_______________ "
+ "Tot_pkt/bytes Pkt/Byte Drp\n");
+ }
+ printf("%3d ", q[l].hash_slot);
+ pe = getprotobynumber(q[l].id.proto);
+ if (pe != NULL)
+ printf("%9s ", pe->p_name);
+ else
+ printf("%9u ", q[l].id.proto);
+ printf("%7d %39s/%-5d ", q[l].id.flow_id6,
+ inet_ntop(AF_INET6, &(q[l].id.src_ip6), buff, sizeof(buff)),
+ q[l].id.src_port);
+ printf(" %39s/%-5d ",
+ inet_ntop(AF_INET6, &(q[l].id.dst_ip6), buff, sizeof(buff)),
+ q[l].id.dst_port);
+ printf(" %4llu %8llu %2u %4u %3u\n",
+ align_uint64(&q[l].tot_pkts),
+ align_uint64(&q[l].tot_bytes),
+ q[l].len, q[l].len_bytes, q[l].drops);
+ if (verbose)
+ printf(" S %20llu F %20llu\n",
+ align_uint64(&q[l].S),
+ align_uint64(&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, size_t nbytes, int ac, char *av[])
+{
+ unsigned int rulenum;
+ void *next = data;
+ struct dn_pipe *p = (struct dn_pipe *) data;
+ struct dn_flow_set *fs;
+ struct dn_flow_queue *q;
+ size_t l;
+
+ if (ac > 0)
+ rulenum = (unsigned int)strtoul(*av++, NULL, 10);
+ else
+ rulenum = 0;
+ for (; nbytes >= sizeof(struct dn_pipe); 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(struct dn_pipe) + p->fs.rq_elements * sizeof(struct dn_flow_queue);
+ 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(struct dn_flow_set) + fs->rq_elements * sizeof(struct dn_flow_queue);
+ 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);
+ }
+}
+
+static void
+list(int ac, char *av[], int show_counters)
+{
+ void *data = NULL;
+ socklen_t nbytes;
+ int exitval = EX_OK;
+
+ 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(IP_DUMMYNET_GET, data, &nbytes) < 0) {
+ if (errno == ENOBUFS) {
+ nbytes = 0;
+ break;
+ }
+ err(EX_OSERR, "getsockopt(IP_DUMMYNET_GET)");
+
+ }
+ }
+
+ list_pipes(data, nbytes, ac, av);
+
+ free(data);
+
+ if (exitval != EX_OK)
+ exit(exitval);
+}
+
+static void
+show_usage(void)
+{
+ fprintf(stderr, "usage: dnctl [options]\n"
+ "do \"dnctl -h\" or see dnctl manpage for details\n"
+ );
+ exit(EX_USAGE);
+}
+
+static void
+help(void)
+{
+ fprintf(stderr,
+ "dnclt [-acdeftTnNpqS] <command> where <command> is one of:\n"
+ "{pipe|queue} N config PIPE-BODY\n"
+ "[pipe|queue] {zero|delete|show} [N{,N}]\n"
+ );
+ exit(0);
+}
+
+static void
+delete(int ac, char *av[])
+{
+ struct dn_pipe p;
+ int i;
+ int exitval = EX_OK;
+ socklen_t len;
+
+ memset(&p, 0, sizeof(struct dn_pipe));
+
+ av++; ac--;
+
+ while (ac && isdigit(**av)) {
+ i = atoi(*av); av++; ac--;
+
+ if (do_pipe == 1)
+ p.pipe_nr = i;
+ else
+ p.fs.fs_nr = i;
+ len = sizeof(struct dn_pipe);
+ i = do_cmd(IP_DUMMYNET_DEL, &p, &len);
+ if (i) {
+ exitval = 1;
+ warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
+ do_pipe == 1 ? p.pipe_nr : p.fs.fs_nr);
+ }
+ }
+ if (exitval != EX_OK)
+ exit(exitval);
+}
+
+/*
+ * 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;
+ void *par = NULL;
+ socklen_t len;
+
+ memset(&p, 0, sizeof(struct dn_pipe));
+
+ 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 = (int)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 = (int)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;
+ struct in6_addr *pa6 = NULL;
+ uint32_t a;
+
+ 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;
+ n2mask(&(p.fs.flow_mask.dst_ip6), 128);
+ n2mask(&(p.fs.flow_mask.src_ip6), 128);
+ 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_DSTIP6:
+ pa6 = &(p.fs.flow_mask.dst_ip6);
+ break;
+
+ case TOK_SRCIP6:
+ pa6 = &(p.fs.flow_mask.src_ip6);
+ 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 = (int)strtoul(av[0]+1, &end, 0);
+ if (pa6 == NULL)
+ a = (a == 32) ? ~0 : (1 << a) - 1;
+ } else
+ a = (int)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 (pa6 != NULL) {
+ if (a > 128)
+ errx(EX_DATAERR,
+ "in6addr invalid mask len");
+ else
+ n2mask(pa6, 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 = (int)strtoul(end, &end, 0);
+ if (*end == 'K' || *end == 'k')
+ p.fs.min_th *= 1024;
+ }
+ if ((end = strsep(&av[0], "/"))) {
+ p.fs.max_th = (int)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 = (int)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 = (int)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 = (int)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));
+ }
+ len = sizeof(struct dn_pipe);
+ i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, &len);
+ if (i)
+ err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
+}
+
+static void
+flush(int force)
+{
+ 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 (do_cmd(IP_DUMMYNET_FLUSH, NULL, 0) < 0)
+ err(EX_UNAVAILABLE, "setsockopt(IP_DUMMYNET_FLUSH)");
+
+ if (!do_quiet)
+ printf("Flushed all pipes.\n");
+}
+
+/*
+ * 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
+parse_args(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... */
+ size_t 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;
+ size_t l;
+
+ av = calloc(oldac, sizeof(char *));
+ for (first = i = ac = 0, l = 0; i < oldac; i++) {
+ char *arg = oldav[i];
+ size_t k = strlen(arg);
+
+ l += k;
+ if (arg[k-1] != ',' || i == oldac-1) {
+ size_t 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, "afhnqsv")) != -1)
+ switch (ch) {
+ case 'a':
+ do_acct = 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 'q':
+ do_quiet = 1;
+ break;
+
+ case 's': /* sort */
+ do_sort = atoi(optarg);
+ 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 ``dnctl''");
+
+ /*
+ * An undocumented behaviour of dnctl1 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 (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, "print", strlen(*av)) ||
+ !strncmp(*av, "list", strlen(*av)))
+ list(ac, av, do_acct);
+ 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
+dnctl_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;
+
+ while ((c = getopt(ac, av, "np:q")) != -1) {
+ switch(c) {
+ 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;
+
+ default:
+ errx(EX_USAGE, "bad arguments, for usage"
+ " summary ``dnctl''");
+ }
+
+ 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;
+ parse_args(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)
+ dnctl_readfile(ac, av);
+ else {
+ if (parse_args(ac-1, av+1))
+ show_usage();
+ }
+ return EX_OK;
+}
+/*
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
warn("SIOCSIFPHYADDR");
}
+static void
+in_set_router(int s, int enable)
+{
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof (ifr));
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+ ifr.ifr_intval = enable;
+
+ if (ioctl(s, SIOCSETROUTERMODE, &ifr) < 0)
+ warn("SIOCSETROUTERMODE");
+}
+
static struct afswtch af_inet = {
.af_name = "inet",
.af_af = AF_INET,
.af_getaddr = in_getaddr,
.af_status_tunnel = in_status_tunnel,
.af_settunnel = in_set_tunnel,
+ .af_setrouter = in_set_router,
.af_difaddr = SIOCDIFADDR,
.af_aifaddr = SIOCAIFADDR,
.af_ridreq = &in_ridreq,
/*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
printf("anycast ");
if ((flags6 & IN6_IFF_TENTATIVE) != 0)
printf("tentative ");
+ if ((flags6 & IN6_IFF_OPTIMISTIC) != 0)
+ printf("optimistic ");
if ((flags6 & IN6_IFF_DUPLICATED) != 0)
printf("duplicated ");
if ((flags6 & IN6_IFF_DETACHED) != 0)
warn("SIOCSIFPHYADDR_IN6");
}
+static void
+in6_set_router(int s, int enable)
+{
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof (ifr));
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+ ifr.ifr_intval = enable;
+
+ if (ioctl(s, SIOCSETROUTERMODE_IN6, &ifr) < 0)
+ warn("SIOCSETROUTERMODE_IN6");
+}
+
static struct cmd inet6_cmds[] = {
DEF_CMD_ARG("prefixlen", setifprefixlen),
DEF_CMD("anycast", IN6_IFF_ANYCAST, setip6flags),
DEF_CMD("tentative", IN6_IFF_TENTATIVE, setip6flags),
DEF_CMD("-tentative", -IN6_IFF_TENTATIVE, setip6flags),
+ /* RFC 4429, section 3.1, says:
+ * "Optimistic DAD SHOULD NOT be used for manually entered
+ * addresses."
+ *
+ * DEF_CMD("optimistic", IN6_IFF_OPTIMISTIC, setip6flags),
+ * DEF_CMD("-optimistic", -IN6_IFF_OPTIMISTIC, setip6flags),
+ */
DEF_CMD("deprecated", IN6_IFF_DEPRECATED, setip6flags),
DEF_CMD("-deprecated", -IN6_IFF_DEPRECATED, setip6flags),
DEF_CMD("autoconf", IN6_IFF_AUTOCONF, setip6flags),
.af_postproc = in6_postproc,
.af_status_tunnel = in6_status_tunnel,
.af_settunnel = in6_set_tunnel,
+ .af_setrouter = in6_set_router,
.af_difaddr = SIOCDIFADDR_IN6,
.af_aifaddr = SIOCAIFADDR_IN6,
- .af_ridreq = &in6_addreq,
+ .af_ridreq = &in6_ridreq,
.af_addreq = &in6_addreq,
};
/*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_types.h>
+#include <net/if_mib.h>
#include <net/route.h>
+#include <net/pktsched/pktsched.h>
/* IP */
#include <netinet/in.h>
int doalias;
int clearaddr;
int newaddr = 1;
-int verbose;
int noload;
int all;
int bond_details = 0;
int supmedia = 0;
+#if TARGET_OS_EMBEDDED
+int verbose = 1;
+int showrtref = 1;
+#else /* !TARGET_OS_EMBEDDED */
+int verbose = 0;
int showrtref = 0;
+#endif /* !TARGET_OS_EMBEDDED */
int printkeys = 0; /* Print keying material for interfaces. */
static int ifconfig(int argc, char *const *argv, int iscreate,
const struct afswtch *afp);
static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
struct ifaddrs *ifa);
+static char *bps_to_str(unsigned long long rate);
static void tunnel_status(int s);
static void usage(void);
+static char *sched2str(unsigned int s);
+static char *tl2str(unsigned int s);
static struct afswtch *af_getbyname(const char *name);
static struct afswtch *af_getbyfamily(int af);
struct option *p;
size_t iflen;
- all = downonly = uponly = namesonly = noload = verbose = 0;
+ all = downonly = uponly = namesonly = noload = 0;
/* Parse leading line options */
#ifndef __APPLE__
argc -= optind;
argv += optind;
- /* -l cannot be used with -a or -r or -m or -b */
- if (namesonly && (all || supmedia || showrtref || bond_details))
+ /* -l cannot be used with -a or -q or -r or -m or -b */
+ if (namesonly &&
+#ifdef TARGET_OS_EMBEDDED
+ (all || supmedia || bond_details))
+#else /* TARGET_OS_EMBEDDED */
+ (all || supmedia || showrtref || bond_details))
+#endif /* !TARGET_OS_EMBEDDED */
usage();
/* nonsense.. */
}
#endif
+static void
+setrouter(const char *vname, int value, int s, const struct afswtch *afp)
+{
+ if (afp->af_setrouter == NULL) {
+ warn("address family %s does not support router mode",
+ afp->af_name);
+ return;
+ }
+
+ afp->af_setrouter(s, value);
+}
+
+static void
+setifdesc(const char *val, int dummy __unused, int s, const struct afswtch *afp)
+{
+ struct if_descreq ifdr;
+
+ bzero(&ifdr, sizeof (ifdr));
+ strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name));
+ ifdr.ifdr_len = strlen(val);
+ strncpy((char *)ifdr.ifdr_desc, val, sizeof (ifdr.ifdr_desc));
+
+ if (ioctl(s, SIOCSIFDESC, (caddr_t)&ifdr) < 0) {
+ warn("ioctl (set desc)");
+ }
+}
+
+static void
+settbr(const char *val, int dummy __unused, int s, const struct afswtch *afp)
+{
+ struct if_linkparamsreq iflpr;
+ long double bps;
+ u_int64_t rate;
+ u_int32_t percent = 0;
+ char *cp;
+
+ errno = 0;
+ bzero(&iflpr, sizeof (iflpr));
+ strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name));
+
+ bps = strtold(val, &cp);
+ if (val == cp || errno != 0) {
+ warn("Invalid value '%s'", val);
+ return;
+ }
+ rate = (u_int64_t)bps;
+ if (cp != NULL) {
+ if (!strcmp(cp, "b") || !strcmp(cp, "bps")) {
+ ; /* nothing */
+ } else if (!strcmp(cp, "Kb") || !strcmp(cp, "Kbps")) {
+ rate *= 1000;
+ } else if (!strcmp(cp, "Mb") || !strcmp(cp, "Mbps")) {
+ rate *= 1000 * 1000;
+ } else if (!strcmp(cp, "Gb") || !strcmp(cp, "Gbps")) {
+ rate *= 1000 * 1000 * 1000;
+ } else if (!strcmp(cp, "%")) {
+ percent = rate;
+ if (percent == 0 || percent > 100) {
+ printf("Value out of range '%s'", val);
+ return;
+ }
+ } else if (*cp != '\0') {
+ printf("Unknown unit '%s'", cp);
+ return;
+ }
+ }
+ iflpr.iflpr_output_tbr_rate = rate;
+ iflpr.iflpr_output_tbr_percent = percent;
+ if (ioctl(s, SIOCSIFLINKPARAMS, &iflpr) < 0 &&
+ errno != ENOENT && errno != ENXIO && errno != ENODEV) {
+ warn("ioctl (set link params)");
+ } else if (errno == ENXIO) {
+ printf("TBR cannot be set on %s\n", name);
+ } else if (errno == ENOENT || rate == 0) {
+ printf("%s: TBR is now disabled\n", name);
+ } else if (errno == ENODEV) {
+ printf("%s: requires absolute TBR rate\n", name);
+ } else if (percent != 0) {
+ printf("%s: TBR rate set to %u%% of effective link rate\n",
+ name, percent);
+ } else {
+ printf("%s: TBR rate set to %s\n", name, bps_to_str(rate));
+ }
+}
+
+static void
+setthrottle(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ struct if_throttlereq iftr;
+ char *cp;
+
+ errno = 0;
+ bzero(&iftr, sizeof (iftr));
+ strncpy(iftr.ifthr_name, name, sizeof (iftr.ifthr_name));
+
+ iftr.ifthr_level = strtold(val, &cp);
+ if (val == cp || errno != 0) {
+ warn("Invalid value '%s'", val);
+ return;
+ }
+
+ if (ioctl(s, SIOCSIFTHROTTLE, &iftr) < 0 && errno != ENXIO) {
+ warn("ioctl (set throttling level)");
+ } else if (errno == ENXIO) {
+ printf("throttling level cannot be set on %s\n", name);
+ } else {
+ printf("%s: throttling level set to %d\n", name,
+ iftr.ifthr_level);
+ }
+}
+
#define IFFBITS \
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
"\20MULTICAST"
+#define IFEFBITS \
+"\020\1AUTOCONFIGURING\7ACCEPT_RTADV\10TXSTART\11RXPOLL\12VLAN\13BOND\14ARPLL" \
+"\15NOWINDOWSCALE\16NOAUTOIPV6LL\20ROUTER4\21ROUTER6" \
+"\22LOCALNET_PRIVATE\23ND6ALT\24RESTRICTED_RECV\25AWDL\26NOACKPRI\35SENDLIST"
+
#define IFCAPBITS \
"\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \
"\6TSO4\7TSO6\10LRO\11AV"
struct ifaddrs *ift;
int allfamilies, s;
struct ifstat ifs;
+ struct if_descreq ifdr;
+ struct if_linkparamsreq iflpr;
+ int mib[6];
+ struct ifmibdata_supplemental ifmsupp;
+ size_t miblen = sizeof(struct ifmibdata_supplemental);
+ u_int64_t eflags = 0;
if (afp == NULL) {
allfamilies = 1;
printf(" metric %d", ifr.ifr_metric);
if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
printf(" mtu %d", ifr.ifr_mtu);
-#ifdef SIOCGIFGETRTREFCNT
if (showrtref && ioctl(s, SIOCGIFGETRTREFCNT, &ifr) != -1)
printf(" rtref %d", ifr.ifr_route_refcnt);
-#endif
+ 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 &&
+ (eflags = ifr.ifr_eflags) != 0) {
+ printb("\teflags", eflags, IFEFBITS);
+ putchar('\n');
+ }
+
#ifdef SIOCGIFCAP
if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
if (ifr.ifr_curcap != 0) {
if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
printf("%s", ifs.ascii);
+ /* The rest is for when verbose is set; if not set, we're done */
+ if (!verbose)
+ goto done;
+
+ if (ioctl(s, SIOCGIFLINKQUALITYMETRIC, &ifr) != -1) {
+ int lqm = ifr.ifr_link_quality_metric;
+ if (verbose > 1) {
+ printf("\tlink quality: %d ", lqm);
+ if (lqm == IFNET_LQM_THRESH_OFF) {
+ printf("(off)");
+ } else if (lqm == IFNET_LQM_THRESH_UNKNOWN) {
+ printf("(unknown)");
+ } else if (lqm > IFNET_LQM_THRESH_UNKNOWN &&
+ lqm <= IFNET_LQM_THRESH_POOR)
+ printf("(poor)");
+ else if (lqm > IFNET_LQM_THRESH_POOR &&
+ lqm <= IFNET_LQM_THRESH_GOOD)
+ printf("(good)");
+ else
+ printf("(?)");
+ printf("\n");
+ } else if (lqm > IFNET_LQM_THRESH_UNKNOWN) {
+ printf("\tlink quality: %d ", lqm);
+ if (lqm <= IFNET_LQM_THRESH_POOR)
+ printf("(poor)");
+ else if (lqm > IFNET_LQM_THRESH_POOR &&
+ lqm <= IFNET_LQM_THRESH_GOOD)
+ printf("(good)");
+ else
+ printf("(?)");
+ printf("\n");
+ }
+ }
+
+ bzero(&iflpr, sizeof (iflpr));
+ strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name));
+ if (ioctl(s, SIOCGIFLINKPARAMS, &iflpr) != -1) {
+ u_int64_t ibw_max = iflpr.iflpr_input_bw.max_bw;
+ u_int64_t ibw_eff = iflpr.iflpr_input_bw.eff_bw;
+ u_int64_t obw_max = iflpr.iflpr_output_bw.max_bw;
+ u_int64_t obw_eff = iflpr.iflpr_output_bw.eff_bw;
+ u_int64_t obw_tbr = iflpr.iflpr_output_tbr_rate;
+ u_int32_t obw_pct = iflpr.iflpr_output_tbr_percent;
+
+ if (eflags & IFEF_TXSTART) {
+ u_int32_t flags = iflpr.iflpr_flags;
+ u_int32_t sched = iflpr.iflpr_output_sched;
+ struct if_throttlereq iftr;
+
+ printf("\tscheduler: %s%s ",
+ (flags & IFLPRF_ALTQ) ? "ALTQ_" : "",
+ sched2str(sched));
+ if (flags & IFLPRF_DRVMANAGED)
+ printf("(driver managed)");
+ printf("\n");
+
+ bzero(&iftr, sizeof (iftr));
+ strncpy(iftr.ifthr_name, name,
+ sizeof (iftr.ifthr_name));
+ if (ioctl(s, SIOCGIFTHROTTLE, &iftr) != -1 &&
+ iftr.ifthr_level != IFNET_THROTTLE_OFF)
+ printf("\tthrottling: level %d (%s)\n",
+ iftr.ifthr_level, tl2str(iftr.ifthr_level));
+ }
+
+ if (obw_tbr != 0 && obw_eff > obw_tbr)
+ obw_eff = obw_tbr;
+
+ if (ibw_max != 0 || obw_max != 0) {
+ if (ibw_max == obw_max && ibw_eff == obw_eff &&
+ ibw_max == ibw_eff && obw_tbr == 0) {
+ printf("\tlink rate: %s\n",
+ bps_to_str(ibw_max));
+ } else {
+ printf("\tuplink rate: %s [eff] / ",
+ bps_to_str(obw_eff));
+ if (obw_tbr != 0) {
+ if (obw_pct == 0)
+ printf("%s [tbr] / ",
+ bps_to_str(obw_tbr));
+ else
+ printf("%s [tbr %u%%] / ",
+ bps_to_str(obw_tbr),
+ obw_pct);
+ }
+ printf("%s", bps_to_str(obw_max));
+ if (obw_tbr != 0)
+ printf(" [max]");
+ printf("\n");
+ if (ibw_eff == ibw_max) {
+ printf("\tdownlink rate: %s\n",
+ bps_to_str(ibw_max));
+ } else {
+ printf("\tdownlink rate: "
+ "%s [eff] / ", bps_to_str(ibw_eff));
+ printf("%s [max]\n",
+ bps_to_str(ibw_max));
+ }
+ }
+ } else if (obw_tbr != 0) {
+ printf("\tuplink rate: %s [tbr]\n",
+ bps_to_str(obw_tbr));
+ }
+ }
+
+ /* Common OID prefix */
+ mib[0] = CTL_NET;
+ mib[1] = PF_LINK;
+ mib[2] = NETLINK_GENERIC;
+ mib[3] = IFMIB_IFDATA;
+ mib[4] = if_nametoindex(name);
+ mib[5] = IFDATA_SUPPLEMENTAL;
+ if (sysctl(mib, 6, &ifmsupp, &miblen, (void *)0, 0) == -1)
+ err(1, "sysctl IFDATA_SUPPLEMENTAL");
+
+ if (ifmsupp.ifmd_data_extended.ifi_alignerrs != 0) {
+ printf("\tunaligned pkts: %lld\n",
+ ifmsupp.ifmd_data_extended.ifi_alignerrs);
+ }
+
+ bzero(&ifdr, sizeof (ifdr));
+ strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name));
+ if (ioctl(s, SIOCGIFDESC, &ifdr) != -1 && ifdr.ifdr_len) {
+ printf("\tdesc: %s\n", ifdr.ifdr_desc);
+ }
+
+done:
close(s);
return;
}
+#define GIGABIT_PER_SEC 1000000000 /* gigabit per second */
+#define MEGABIT_PER_SEC 1000000 /* megabit per second */
+#define KILOBIT_PER_SEC 1000 /* kilobit per second */
+
+static char *
+bps_to_str(unsigned long long rate)
+{
+ static char buf[32];
+ const char *u;
+ long double n = rate, t;
+
+ if (rate >= GIGABIT_PER_SEC) {
+ t = n / GIGABIT_PER_SEC;
+ u = "Gbps";
+ } else if (n >= MEGABIT_PER_SEC) {
+ t = n / MEGABIT_PER_SEC;
+ u = "Mbps";
+ } else if (n >= KILOBIT_PER_SEC) {
+ t = n / KILOBIT_PER_SEC;
+ u = "Kbps";
+ } else {
+ t = n;
+ u = "bps ";
+ }
+
+ snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
+ return (buf);
+}
+
static void
tunnel_status(int s)
{
DEF_CMD("av", IFCAP_AV, setifcap),
DEF_CMD("-av", -IFCAP_AV, setifcap),
#endif /* IFCAP_AV */
+ DEF_CMD("router", 1, setrouter),
+ DEF_CMD("-router", 0, setrouter),
+ DEF_CMD_ARG("desc", setifdesc),
+ DEF_CMD_ARG("tbr", settbr),
+ DEF_CMD_ARG("throttle", setthrottle),
};
static __constructor void
cmd_register(&basic_cmds[i]);
#undef N
}
+
+static char *
+sched2str(unsigned int s)
+{
+ char *c;
+
+ switch (s) {
+ case PKTSCHEDT_NONE:
+ c = "NONE";
+ break;
+ case PKTSCHEDT_CBQ:
+ c = "CBQ";
+ break;
+ case PKTSCHEDT_HFSC:
+ c = "HFSC";
+ break;
+ case PKTSCHEDT_PRIQ:
+ c = "PRIQ";
+ break;
+ case PKTSCHEDT_FAIRQ:
+ c = "FAIRQ";
+ break;
+ case PKTSCHEDT_TCQ:
+ c = "TCQ";
+ break;
+ case PKTSCHEDT_QFQ:
+ c = "QFQ";
+ break;
+ default:
+ c = "UNKNOWN";
+ break;
+ }
+
+ return (c);
+}
+
+static char *
+tl2str(unsigned int s)
+{
+ char *c;
+
+ switch (s) {
+ case IFNET_THROTTLE_OFF:
+ c = "off";
+ break;
+ case IFNET_THROTTLE_OPPORTUNISTIC:
+ c = "opportunistic";
+ break;
+ default:
+ c = "unknown";
+ break;
+ }
+
+ return (c);
+}
+/*
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
/*
* Copyright (c) 1997 Peter Wemm.
* All rights reserved.
void (*af_status_tunnel)(int);
void (*af_settunnel)(int s, struct addrinfo *srcres,
struct addrinfo *dstres);
+
+ void (*af_setrouter)(int, int);
};
void af_register(struct afswtch *);
+++ /dev/null
-# 6to4.conf
-# Configuration file for 6to4 tunnel
-#
-
-$in_if=""; # Inside (usually ethernet) interface - for local network
-
-$v6_net="1"; # 2002:x:x:v6_net::
-$v6_innernet="2"; # 2002:x:x:v6_innernet::
-$v6_prefixlen=16; # Change for more
-$hostbits6=":1"; # should be determined via MAC of $in_if
-
-# Possible remote 6to4 routers:
-# Anycast is default per RFC 3068, but can select another if desired
-
-$peer="6to4-anycast"; # RFC 3068 magic value
-#$peer="6to4.ipv6.fh-regensburg.de"; # Germany, Europe
-#$peer="asterix.ipv6.bt.com"; # Great Britain, Europe
-#$peer="6to4.kfu.com"; # USA, West coast
-#$peer="6to4.ipv6.microsoft.com"; # USA, West coast
-#$peer="ipv6-router.cisco.com"; # USA, West coast; register at http://www.cisco.com/ipv6/
+++ /dev/null
-.Dd May 23, 2002
-.Dt ip6 8
-.Os
-.Sh NAME
-.Nm ip6
-.Nd Enable or disable IPv6 on active interfaces
-.Sh SYNOPSIS
-.Nm
-.Op Fl ax
-.Op Fl ud interface
-.Sh DESCRIPTION
-.Nm
-can be used to start up or shut down IPv6 on active interfaces.
-When IPv6 is enabled on an interface the protocol is attached to the
-interface, at which point the default settings in the kernel allow it
-to acquire a link-local address and accept router advertisements.
-Disabling detaches the protocol from the interface.
-.Pp
-Possible options are:
-.Bl -tag -width xxx
-.It Fl a
-Start IPv6 on all interfaces.
-.It Fl x
-Stop IPv6 on all interfaces.
-.It Fl u [interface]
-Start IPv6 on interface.
-.It Fl d [interface]
-Stop IPv6 on interface.
-.El
-.Pp
-.Sh REQUIREMENTS
-You need support for IPv6 in your kernel. This is provided beginning
-with Darwin Kernel Version 6.0.
-.Pp
-.Sh CONFIGURATION
-The default IPv6 configuration for an interface assigns a link-local
-address to it and sets the interface to receive router advertisements.
-No further configuration is necessary for basic functionality.
-However, various settings can be modified by using sysctl.
-Pp
-.Sh SEE ALSO
-.Xr stf 4 ,
-IPv6 Documentation at
-.Pa http://www.netbsd.org/Documentation/network/ipv6/ ,
-RFC 3068.
+++ /dev/null
-#!/usr/bin/perl
-#
-# Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
-#
-# @APPLE_LICENSE_HEADER_START@
-#
-# "Portions Copyright (c) 2002 Apple Computer, Inc. All Rights
-# Reserved. 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 1.0 (the 'License'). You may not use this file
-# except in compliance with the License. Please obtain a copy of the
-# License at http://www.apple.com/publicsource and read it before using
-# this file.
-#
-# The Original Code and all software distributed under the License are
-# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-# License for the specific language governing rights and limitations
-# under the License."
-#
-# @APPLE_LICENSE_HEADER_END@
-#
-# Setup IPv6 for Darwin
-# - Startup/shutdown IPv6 on the given interface
-# - Startup/shutdown 6to4 on the given interface
-# - Start/stop router advertisement.
-#
-# Setup 6to4 IPv6, for NetBSD (and maybe others)
-#
-# (c) Copyright 2000 Hubert Feyrer <hubert@feyrer.de>
-#
-
-
-# Directory for conf file
-$etcdir="/private/etc";
-require "$etcdir/6to4.conf";
-
-use Getopt::Std;
-
-###########################################################################
-sub do_6to4_setup
-{
- #
- # Some sanity checks - check for link-local address and stf
- #
- if (`ifconfig -a | grep fe80: | wc -l` <= 0 or
- `ifconfig -a | grep stf | wc -l` <= 0) {
- die "$0: It seems your kernel does not support IPv6 or 6to4 (stf).\n";
- }
-
- #
- # Take the requested interface from the user
- # Figure out addressing, etc.
- #
- $localadr4 = `ifconfig $ARGV[1] inet | grep inet | grep -v "10.*.*.*"| \
- grep -v "172.[^16-31].*.*" | grep -v "192.168.*.*" | \
- grep -v "169.254.*.*" | grep -v alias`;
- $localadr4 =~ s/^.*inet\s*//;
- $localadr4 =~ s/\s.*$//;
- chomp($localadr4);
-
- @l4c = split('\.', $localadr4);
- $prefix = sprintf("2002:%02x%02x:%02x%02x", @l4c[0..3]);
-
- $localadr6 = sprintf("$prefix:%04x", $v6_net);
-
- #
- # Anycast is default in 6to4.conf file
- #
- if ($peer eq "6to4-anycast") {
- # magic values from rfc 3068
- $remoteadr4 = "192.88.99.1";
- $remoteadr6 = "2002:c058:6301::";
- }
- else {
- chomp($remoteadr4 = `host $peer`);
- $remoteadr4 =~ s/^.*address //;
-
- chomp($remoteadr6 = `host -t AAAA $peer`);
- $remoteadr6 =~ s/^.*address //;
- }
-
-}
-
-###########################################################################
-sub do_usage
-{
- print "Usage: $0 \n";
- print " start-v6 all | stop-v6 all\n";
- print " start-v6 [interface] | stop-v6 [interface]\n";
- print " start-stf [interface] | stop-stf\n";
- print " start-rtadvd | stop-rtadvd\n";
-}
-###########################################################################
-
-#
-# Process options - just help for now
-#
-getopts('h');
-
-if ($opt_h) {
- do_usage;
- exit 0;
-}
-
-#
-# Handle commands
-#
-
-# Start IPv6
-if ($ARGV[0] eq "start-v6" or $ARGV[0] eq "v6-start") {
- if ($ARGV[1] eq "all") {
- print "Starting IPv6 on all interfaces.\n";
- system "ip6 -a";
- }
- else {
- print "Starting IPv6 on $ARGV[1].\n";
- system "ip6 -u $ARGV[1]";
- }
-}
-
-# Stop IPv6
-elsif ($ARGV[0] eq "stop-v6" or $ARGV[0] eq "v6-stop") {
- if ($ARGV[1] eq "all") {
- print "Stopping IPv6 on all interfaces.\n";
- system "ip6 -x";
- }
- else {
- print "Stopping IPv6 on $ARGV[1].\n";
- system "ip6 -d $ARGV[1]";
- }
-}
-
-# Start 6to4
-elsif ($ARGV[0] eq "start-stf" or $ARGV[0] eq "stf-start") {
- do_6to4_setup;
- print "Starting 6to4 on $ARGV[1].\n";
- system "ifconfig stf0 inet6 $localadr6:$hostbits6 prefixlen $v6_prefixlen alias";
- system "route add -inet6 default $remoteadr6";
- if ($in_if ne "") {
- system "ifconfig $in_if inet6 $prefix:$v6_innernet:$hostbits6";
- }
-}
-
-# Stop 6to4
-elsif ($ARGV[0] eq "stop-stf" or $ARGV[0] eq "stf-stop") {
- print "Stopping 6to4.\n";
- system "ifconfig stf0 down";
- $cmd="ifconfig stf0 inet6 " .
- "| grep inet6 " .
- "| sed -e 's/inet6//' " .
- "-e 's/prefix.*//g' " .
- "-e 's/^[ ]*//' " .
- "-e 's/[ ]*\$//'";
- foreach $ip ( split('\s+', `$cmd`)) {
- system "ifconfig stf0 inet6 -alias $ip";
- }
- system "route delete -inet6 default";
-}
-
-# Start router advertisement
-elsif ($ARGV[0] eq "rtadvd-start" or $ARGV[0] eq "start-rtadvd") {
- print "WARNING: Setting up router advertisement should be done with great care\n";
- print "because of a number of security issues. You should make sure this is\n";
- print "allowed on your network and possibly fine-tune rtadvd.conf.\n";
- print "\n";
- print "Are you sure you want to start router advertisement (yes/no) ?: ";
- while (<STDIN>) {
- chomp;
- if ($_ eq "yes" or $_ eq "y") {
- if ( -f "/var/run/rtadvd.pid" ) {
- print "rtadvd already running!\n";
- } else {
- print "Starting router advertisement.\n";
- system "sysctl -w net.inet6.ip6.forwarding=1";
- system "sysctl -w net.inet6.ip6.accept_rtadv=0";
- shift @ARGV;
- system "rtadvd @ARGV";
- }
- last;
- }
- elsif ($_ eq "no" or $_ eq "n") {
- print "Router advertisement startup aborted.\n";
- last;
- }
- else {
- print "Invalid entry! Try again.\n";
- print "Are you sure you want to start router advertisement? (yes/no): ";
- }
- }
-}
-
-# Stop router advertisement
-elsif ($ARGV[0] eq "rtadvd-stop" or $ARGV[0] eq "stop-rtadvd") {
- if ( -f "/var/run/rtadvd.pid" ) {
- print "Stopping router advertisement.\n";
- $pid = `cat /var/run/rtadvd.pid`;
- system "kill -TERM $pid";
- system "rm -f /var/run/rtadvd.pid";
- system "rm -f /var/run/6to4-rtadvd.conf.$pid";
- } else {
- print "no rtadvd running!\n";
- }
-}
-else {
- do_usage;
-}
+++ /dev/null
-.\" $NetBSD: 6to4.8,v 1.5 2001/12/03 19:03:21 wiz Exp $
-.Dd May 21, 2002
-.Dt ip6config 8
-.Os
-.Sh NAME
-.Nm ip6config
-.Nd Configure IPv6 and 6to4 IPv6 tunnelling
-.Sh SYNOPSIS
-.Nm
-.Op Fl h
-.Ar command interface
-.Sh DESCRIPTION
-The
-.Nm
-script can be used to start up or shut down IPv6 on active interfaces. It
-can also be used to configure a 6to4 tunnel and start or stop router
-advertisement.
-.Pp
-When IPv6 is enabled on an interface the protocol is attached to the
-interface, at which point the default settings in the kernel allow it
-to acquire a link-local address and listen for router advertisements.
-.Pp
-6to4 is a mechanism by which your IPv6 address(es) are derived from an
-assigned IPv4 address, and which involves automatic tunnelling to one or
-more remove 6to4 hubs, which will then forward your v6 packets on the
-6bone etc. Replies are routed back to you over IPv4 via (possibly) other
-6to4 capable remote gateways. As such, IPv6-in-IPv4-encapsulated
-packets are accepted from all v4-hosts.
-.Pp
-From your (single) IPv4 address, you get a whole IPv6 /48 network,
-which allows you to split your network in 2^16 subnets, with 2^64
-hosts each. You need to setup routing for your internal network
-properly, help is provided for setting up the border router here.
-.Pp
-This script takes the burden to calculate your IPv6 address from
-existing IPv4 address and runs the commands to setup (and tear down)
-automatic 6to4 IPv6 tunnelling.
-.Pp
-Finally, router advertisement for an internal network can be started
-and stopped. This uses sysctl to set net.inet6.ip6.forwarding and
-net.inet6.ip6.accept_rtadv to the proper values for routing.
-.Pp
-Possible options are:
-.Bl -tag -width xxx
-.It Fl h
-Show usage.
-.El
-.Pp
-Possible commands are:
-.Bl -tag -width start-rtadvd
-.It Sy start-v6
-Start IPv6 on given interface using default kernel settings. Attaches
-protocol to the interface. If interface is "all", all valid interfaces
-will be configured.
-.It Sy stop-v6
-Stop IPv6 on given interface. Detaches protocol from the interface. If
-interface is "all", all valid interfaces will be configured.
-.It Sy start-stf
-Configure 6to4 IPv6. The
-.Xr stf 4
-interface is configured, and a default route to a remote 6to4
-gateway is established. In addition, the internal
-network interface is assigned an address.
-.It Sy stop-stf
-Stops 6to4 IPv6. All addresses are removed from the
-.Xr stf 4
-device, and the default route is removed.
-.It Sy start-rtadvd
-Starts router advertizement and IPv6 packet forwarding,
-turning the machine into a IPv6 router.
-.Xr rtadvd 8
-is invoked with a custom config file created under
-.Pa /var/run .
-Clients just need to be told to accept router advertizements, i.e.
-the
-.Sq net.inet6.ip6.accept_rtadv
-sysctl needs to be set to
-.Sq 1 .
-You can arrange that by setting
-.Dq ip6mode=autohost
-in
-.Pa /etc/rc.conf .
-.It Sy stop-rtadvd
-Stops router advertizement and IPv6 packet forwarding.
-.Xr rtadvd 8
-is stopped, and the
-.Xr rtadvd.conf 5
-config file is removed from
-.Pa /var/run .
-.El
-.Sh REQUIREMENTS
-Besides IPv4 connectivity, you need support for IPv6 and the
-.Xr stf 4
-device in your kernel. This is provided beginning with Darwin
-Kernel Version 6.0.
-.Pp
-No special values are needed in
-.Pa /etc/rc.conf
-to run this script, but see comment on setting up IPv6-clients
-.Sq behind
-your 6to4 router for the
-.Sy rtadvd-start
-command!
-.Sh CONFIGURATION
-The default IPv6 configuration for an interface assigns a link-local
-address to it and sets the interface to receive router advertisements.
-No further configuration is necessary for basic functionality.
-However, various settings can be modified by using sysctl.
-.Pp
-The
-.Nm
-script reads its 6to4 configuration from a config file named
-.Pa 6to4.conf .
-The
-.Pa 6to4.conf
-file is in
-.Xr perl 1
-syntax, and contains several
-variables that can be tuned to adjust your setup.
-.Bl -tag -width start-rtadvd
-.It Sy in_if
-The inside interface. If non-empty, this interface is
-assigned the IPv6 address
-2002:x:x:v6_innernet:hostbits6, see below.
-This is only useful on machines that
-have more than one network interface, e.g. with a modem and a
-local ethernet.
-.It Sy v6_net
-The subnet address you want to use on the address of
-your outbound interface. Defaults to
-.Dq 1 .
-.It Sy v6_innernet
-The subnet address you want to use on the address of
-your inbound interface. Defaults to
-.Dq 2 .
-.It Sy hostbits6
-The lower 64 bits of both the inbound and outbound interface's
-addresses.
-.It Sy peer
-Name of the remote 6to4 server that'll take our
-IPv6-in-IPv4 encapsulated packets and route them on
-via IPv6. A special value of
-.Dq 6to4-anycast
-can be used for the anycast service defined in RFC 3068.
-Other possible values are given in the example config file.
-.El
-.Sh SEE ALSO
-.Xr stf 4 ,
-.Dq 6to4 IPv6 Explained
-at
-.Pa http://www.feyrer.de/NetBSD/6to4.html ,
-.Nx
-IPv6 Documentation at
-.Pa http://www.netbsd.org/Documentation/network/ipv6/ ,
-RFC 3068.
-.Sh HISTORY
-The
-.Nm
-6to4 utility and manpage portions were written by
-Hubert Feyrer <hubert@feyrer.de> for NetBSD.
+++ /dev/null
-/* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
-*
-* @APPLE_LICENSE_HEADER_START@
-*
-* "Portions Copyright (c) 2002 Apple Computer, Inc. All Rights
-* Reserved. 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 1.0 (the 'License'). You may not use this file
-* except in compliance with the License. Please obtain a copy of the
-* License at http://www.apple.com/publicsource and read it before using
-* this file.
-*
-* The Original Code and all software distributed under the License are
-* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-* License for the specific language governing rights and limitations
-* under the License."
-*
-* @APPLE_LICENSE_HEADER_END@
-*
-*/
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/errno.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <netinet6/in6_var.h>
-#include <ifaddrs.h>
-
-/* From netinet6/in6_var.h */
-#ifndef SIOCPROTOATTACH_IN6
-#define SIOCPROTOATTACH_IN6 _IOWR('i', 110, struct in6_aliasreq) /* attach proto to interface */
-#endif
-#ifndef SIOCPROTODETACH_IN6
-#define SIOCPROTODETACH_IN6 _IOWR('i', 111, struct in6_ifreq) /* detach proto from interface */
-#endif
-#ifndef SIOCLL_START
-#define SIOCLL_START _IOWR('i', 130, struct in6_aliasreq) /* start aquiring linklocal on interface */
-#endif
-#ifndef SIOCLL_STOP
-#define SIOCLL_STOP _IOWR('i', 131, struct in6_ifreq) /* deconfigure linklocal from interface */
-#endif
-
-/* options */
-#define IPv6_STARTUP 1
-#define IPv6_SHUTDOWN 2
-#define IPv6_STARTUP_ALL 3
-#define IPv6_SHUTDOWN_ALL 4
-
-const char *if_exceptions[] = {"lo0", "gif0", "faith0", "stf0"};
-
-extern char *optarg;
-
-void do_usage(void);
-int do_protoattach(int s, char *name);
-int do_protodetach(int s, char *name);
-void do_protoattach_all(int s);
-void do_protodetach_all(int s);
-
-
-int
-main(int argc, char **argv)
-{
- int s,
- ch,
- option = 0,
- err;
- char *interface = NULL;
-
- if ((ch = getopt(argc, argv, "u:d:ax")) != -1) {
- switch (ch) {
- case 'u':
- /* option -u: start up proto */
- option = IPv6_STARTUP;
- interface = optarg;
- break;
- case 'd':
- /* option -d: shut down proto */
- option = IPv6_SHUTDOWN;
- interface = optarg;
- break;
- case 'a':
- /* option -a: start up proto on all interfaces */
- option = IPv6_STARTUP_ALL;
- break;
- case 'x':
- /* option -x: shut down proto on all interfaces */
- option = IPv6_SHUTDOWN_ALL;
- break;
- default:
- break;
- }
- }
-
- if (!option) {
- do_usage();
- return 0;
- }
-
- if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- err = s;
- printf("%s: Error %d creating socket.\n", argv[0], err);
- return 0;
- }
-
- switch (option) {
- case IPv6_STARTUP:
- err = do_protoattach(s, interface);
- if (err < 0)
- printf("%s: Error %d encountered attaching interface %s.\n", argv[0], err, interface);
-
- break;
- case IPv6_SHUTDOWN:
- err = do_protodetach(s, interface);
- if (err < 0)
- printf("%s: Error %d encountered detaching interface %s.\n", argv[0], err, interface);
-
- break;
- case IPv6_STARTUP_ALL:
- do_protoattach_all(s);
-
- break;
- case IPv6_SHUTDOWN_ALL:
- do_protodetach_all(s);
-
- break;
- default:
- break;
- }
-
- close(s);
-
- return 0;
-}
-
-void
-do_usage(void)
-{
- printf("Usage: \n\
- Start up IPv6 on ALL interfaces: -a\n\
- Shut down IPv6 on ALL interfaces: -x\n\
- Start up IPv6 on given interface: -u [interface]\n\
- Shut down IPv6 on given interface: -d [interface].\n");
-}
-
-int
-do_protoattach(int s, char *name)
-{
- struct in6_aliasreq ifr;
- int err;
-
- bzero(&ifr, sizeof(ifr));
- strncpy(ifr.ifra_name, name, sizeof(ifr.ifra_name));
-
- if ((err = ioctl(s, SIOCPROTOATTACH_IN6, &ifr)) != 0)
- return (err);
-
- return (ioctl(s, SIOCLL_START, &ifr));
-}
-
-int
-do_protodetach(int s, char *name)
-{
- struct in6_ifreq ifr;
- int err;
-
- bzero(&ifr, sizeof(ifr));
- strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
-
- if ((err = ioctl(s, SIOCLL_STOP, &ifr)) != 0)
- return (err);
-
- return (ioctl(s, SIOCPROTODETACH_IN6, &ifr));
-}
-
-void
-do_protoattach_all(int s)
-{
- struct ifaddrs *ifaddrs, *ifa;
-
- if (getifaddrs(&ifaddrs)) {
- printf("ip6: getifaddrs returned error (%s)", strerror(errno));
- }
-
- for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
- /* skip over invalid interfaces */
- if ((strcmp(ifa->ifa_name, if_exceptions[0])))
- if (strcmp(ifa->ifa_name, if_exceptions[1]))
- if (strcmp(ifa->ifa_name, if_exceptions[2]))
- if (strcmp(ifa->ifa_name, if_exceptions[3])) {
- /* this is a valid interface */
- if (do_protoattach(s, ifa->ifa_name)) {
- printf("ip6: error attaching %s\n", ifa->ifa_name);
- }
-
- while (ifa->ifa_next != NULL &&
- !(strcmp(ifa->ifa_name, ifa->ifa_next->ifa_name))) {
- /* skip multiple entries for same interface */
- ifa = ifa->ifa_next;
- }
- }
- }
-
- freeifaddrs(ifaddrs);
-
- return;
-}
-
-void
-do_protodetach_all(int s)
-{
- struct ifaddrs *ifaddrs, *ifa;
-
- if (getifaddrs(&ifaddrs)) {
- printf("ip6: getifaddrs returned error (%s)", strerror(errno));
- }
-
- for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
- /* skip over invalid interfaces */
- if ((strcmp(ifa->ifa_name, if_exceptions[0])))
- if (strcmp(ifa->ifa_name, if_exceptions[1]))
- if (strcmp(ifa->ifa_name, if_exceptions[2]))
- if (strcmp(ifa->ifa_name, if_exceptions[3])) {
- /* this is a valid interface */
- if (do_protodetach(s, ifa->ifa_name)) {
- printf("ip6: error detaching %s\n", ifa->ifa_name);
- }
-
- while (ifa->ifa_next != NULL &&
- !(strcmp(ifa->ifa_name, ifa->ifa_next->ifa_name))) {
- /* skip multiple entries for same interface */
- ifa = ifa->ifa_next;
- }
- }
- }
-
- freeifaddrs(ifaddrs);
-
- return;
-}
.Op via Ar name | ipv6no
.Op Ar options
.Sh DESCRIPTION
+Note that use of this utility is
+.Cm DEPRECATED.
+Please use
+.Xr pfctl 8
+instead.
+.Pp
To ease configuration, rules can be put into a file which is
processed using
.Nm
--- /dev/null
+/*
+ * Colm MacCarthaigh, <colm@apache.org>
+ *
+ * Copyright (c) 2007, Colm MacCarthaigh.
+ * Copyright (c) 2004 - 2006, HEAnet Ltd.
+ *
+ * This software is an open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the HEAnet Ltd. nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
--- /dev/null
+ MNC - Multicast NetCat
+ ------------------------
+
+1. Introduction
+
+mnc is a simple, one-direction-at-a-time, "netcat"-like application using
+multicast. The aim is to provide a tool for easy debugging and testing when
+setting up a multicast network or host. MNC supports IPv4 and IPv6
+any-source-multicast and single-source-multicast, but depending on your
+platform some of those features may not be available:
+
+ L = Listen (Implies IGMP/MLD mupport)
+ S = Send
+
+ +----------+----------+----------+----------+----------+
+ | Platform | IPv4 ASM | IPv4 SSM | IPv6 ASM | IPv6 SSM |
+ +----------+----------+----------+----------+----------+
+ | *nix | L + S | L + S | L + S | L + S |
+ +----------+----------+----------+----------+----------+
+ | Win2k | L + S | S | None | None |
+ +----------+----------+----------+----------+----------+
+ | WinXP | L + S | L + S | S | S |
+ +----------+----------+----------+----------+----------+
+ | Win2k3 | L + S | L + S | S | S |
+ +----------+----------+----------+----------+----------+
+
+man doc/mnc.1 for information and help on how to run multicast.
+
+2. Supported platforms
+
+As of September 2004, mnc has been compiled and tested with Linux 2.6.8
+kernels, the BSD KAME stack and Windows XP Profesional. Currently automatic
+interface selection does not work on a KAME-based host and you will need to
+specify the interface when in listening mode.
+
+3. Installing mnc from source on UNIX:
+
+ ./configure ; make ; make install
+
+4. Compiling from source on Windows:
+
+nmc is compilable with free utilities available from Microsoft. You need to
+download and install the free (as in beer) MS Visual C++ command-line tools
+from:
+
+ http://msdn.microsoft.com/visualc/vctoolkit2003/
+
+and the SDK relevant to your platform from:
+
+ http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+
+You can run a Visual C++ command-line session, and use:
+
+ cl /DWINDOWS=1 /TC /c *.c
+ link /fixed /out:mnc.exe *.obj ws2_32.lib
+
+to compile a working mnc.exe. The Windows version of MNC does not yet fully
+support IPv6 due to underlying limitation in the Operating System.
+
+5. Reporting problems
+
+Any problems, bugs or suggested features should be mailed to colm
+at apache.org.
--- /dev/null
+.\"
+.\" mnc.1 -- mnc manual
+.\"
+.\" Colm MacCárthaigh, <colm@apache.org>
+.\"
+.\" Copyright (c) 2007 Coolm MacCarthaigh.
+.\" Copyright (c) 2004-2006 HEAnet Ltd.
+.\"
+.\" This software is an open source.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" Redistributions of source code must retain the above copyright notice,
+.\" this list of conditions and the following disclaimer.
+.\"
+.\" Redistributions in binary form must reproduce the above copyright notice,
+.\" this list of conditions and the following disclaimer in the documentation
+.\" and/or other materials provided with the distribution.
+.\"
+.\" Neither the name of the HEAnet Ltd. nor the names of its contributors may
+.\" be used to endorse or promote products derived from this software without
+.\" specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.TH mnc 1 "17 September 2004" "mnc"
+.SH NAME
+mnc \- Multicast NetCat
+.SH SYNOPSIS
+.BR mnc
+[ -l ] [ -i interface ] [ -p port ] group-id [ source-address ]
+.SH DESCRIPTION
+.B mnc
+is designed for simple multicast debugging and testing. It supports
+IPv4 and IPv6 any-source multicast and source-specific multicast.
+In standard mode it will multicast the standard-input verbatim.
+In listening mode it recieves the content and displays it on the
+standard output.
+.PP
+When given the optional source-address, mnc will attempt to use
+source-specific multicast. You may also specify this address
+in standard mode and mnc will use this source-address for
+outgoing packets.
+.PP
+.SH OPTIONS
+.IP \-l
+Listen for multicast packets. Default is to send.
+.IP \-i\ "interface"
+When listening for multicast packets, use the specified interface.
+.IP \-p\ "port"
+Specify a UDP port to use for sending or receiving packets. Default is to use port 1234.
+.SH "SEE ALSO"
+.BR nc (1)
+.PP
+.SH EXAMPLES
+To send IPv4 packets to an ASM group-id:
+.PP
+.RS
+mnc 233.1.2.3
+.RE
+.PP
+To receive IPv4 ASM packets from the same group-id, using eth0 as
+the listening interface:
+.PP
+.RS
+mnc -l -i eth0 233.1.2.3
+.RE
+.PP
+To receive IPv4 packets from an SSM group-id, using eth1 as the
+listening interface and 193.1.219.90 as the permitted source:
+.PP
+.RS
+mnc -l -i eth1 232.0.0.1 193.1.219.90
+.RE
+.PP
+To receive IPv6 packets from an SSM group-id, using eth1 as the
+listening interface and 2001:770:18:2::90 as the permitted source:
+.PP
+.RS
+mnc -l -i eth1 ff31::12 2001:770:18:2::90
+.RE
+.PP
+.SH CREDITS
+mnc is by Colm MacCárthaigh <colm@apache.org> and is available from:
+.PP
+http://people.apache.org/~colm/mnc/
+.PP
+Additional multicast development and support provided by John Lyons
+<john.lyons@heanet.ie> and Eoin Kenny <eoin.kenny@heanet.ie>
--- /dev/null
+/*
+ * $Id: mnc.h,v 1.4 2004/09/22 14:07:10 colmmacc Exp $
+ *
+ * mnc.h -- Multicast NetCat
+ *
+ * Colm MacCarthaigh, <colm@apache.org>
+ *
+ * Copyright (c) 2007, Colm MacCarthaigh.
+ * Copyright (c) 2004 - 2006, HEAnet Ltd.
+ *
+ * This software is an open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the HEAnet Ltd. nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _MNC_H_
+#define _MNC_H_
+
+#ifndef WINDOWS
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#else
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#endif
+
+/* The UDP port MNC will use by default */
+#define MNC_DEFAULT_PORT "1234"
+
+struct mnc_configuration
+{
+ /* Are we sending or recieving ? */
+ enum {SENDER, LISTENER} mode;
+
+ /* What UDP port are we using ? */
+ char * port;
+
+ /* The group-id */
+ struct addrinfo * group;
+
+ /* The source */
+ struct addrinfo * source;
+
+ /* An interface index for listening */
+ char * iface;
+};
+
+
+/* Functions in mnc_opts.c */
+void usage(void);
+struct mnc_configuration * parse_arguments(int argc, char **argv);
+
+/* Functions in mnc_multicast.c */
+int multicast_setup_listen(int, struct addrinfo *, struct addrinfo *, char *);
+int multicast_setup_send(int, struct addrinfo *, struct addrinfo *);
+
+/* Functions in mnc_error.c */
+void mnc_warning(char * string, ...);
+void mnc_error(char * string, ...);
+
+#endif /* _MNC_H_ */
--- /dev/null
+/*
+ * $Id: mnc_error.c,v 1.2 2004/09/22 16:02:26 colmmacc Exp $
+ *
+ * mnc_multicast.c -- Multicast NetCat
+ *
+ * Colm MacCarthaigh, <colm@apache.org>
+ *
+ * Copyright (c) 2007, Colm MacCarthaigh.
+ * Copyright (c) 2004 - 2006, HEAnet Ltd.
+ *
+ * This software is an open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the HEAnet Ltd. nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "mnc.h"
+
+void mnc_warning(char * string, ...)
+{
+ va_list ap;
+
+ /* Do the vararg stuff */
+ va_start(ap, string);
+
+ /* Output our name */
+ if (fprintf(stderr, "mnc: ") < 0)
+ {
+ exit(2);
+ }
+
+ /* Output our error */
+ if (vfprintf(stderr, string, ap) < 0)
+ {
+ exit(2);
+ }
+
+ /* End the vararg stuff */
+ va_end(ap);
+}
+
+void mnc_error(char * string, ...)
+{
+ va_list ap;
+
+ /* Do the vararg stuff */
+ va_start(ap, string);
+
+ /* Output our name */
+ if (fprintf(stderr, "mnc: ") < 0)
+ {
+ exit(2);
+ }
+
+ /* Output our error */
+ if (vfprintf(stderr, string, ap) < 0)
+ {
+ exit(2);
+ }
+
+ /* End the vararg stuff */
+ va_end(ap);
+
+ /* Die! */
+ exit(1);
+}
--- /dev/null
+/*
+ * $Id: mnc_main.c,v 1.12 2004/09/22 19:14:23 colmmacc Exp $
+ *
+ * mnc_main.c -- Multicast NetCat
+ *
+ * Colm MacCarthaigh, <colm@apache.org>
+ *
+ * Copyright (c) 2007, Colm MacCarthaigh.
+ * Copyright (c) 2004 - 2006, HEAnet Ltd.
+ *
+ * This software is an open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the HEAnet Ltd. nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WINDOWS
+
+/* Non-windows includes */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#else
+
+/* Windows-specific includes */
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#endif /* WINDOWS */
+
+#include "mnc.h"
+
+int main(int argc, char **argv)
+{
+ /* Utility variables */
+ int sock,
+ len;
+ char buffer[1024];
+
+ /* Our main configuration */
+ struct mnc_configuration * config;
+
+#ifdef WINDOWS
+ WSADATA wsaData;
+
+ if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
+ {
+ mnc_error("This operating system is not supported\n");
+ }
+#endif
+
+ /* Parse the command line */
+ config = parse_arguments(argc, argv);
+
+ /* Create a socket */
+ if ((sock = socket(config->group->ai_family, config->group->ai_socktype,
+ config->group->ai_protocol)) < 0)
+ {
+ mnc_error("Could not create socket\n");
+ }
+
+ /* Are we supposed to listen? */
+ if (config->mode == LISTENER)
+ {
+ /* Set up the socket for listening */
+ if (multicast_setup_listen(sock, config->group, config->source,
+ config->iface) < 0)
+ {
+ mnc_error("Can not listen for multicast packets.\n");
+ }
+
+ /* Recieve the packets */
+ while ((len = recvfrom(sock, buffer, sizeof(buffer),
+ 0, NULL, NULL)) >= 0)
+ {
+ write(STDOUT_FILENO, buffer, len);
+ }
+ }
+ else /* Assume MODE == SENDER */
+ {
+ /* Set up the socket for sending */
+ if (multicast_setup_send(sock, config->group, config->source)
+ < 0)
+ {
+ mnc_error("Can not send multicast packets\n");
+ }
+
+ /* Send the packets */
+ while((len = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0)
+ {
+ sendto(sock, buffer, len, 0, config->group->ai_addr,
+ config->group->ai_addrlen);
+ }
+ }
+
+ /* Close the socket */
+ close(sock);
+
+ return 0;
+}
--- /dev/null
+/*
+ * $Id: mnc_multicast.c,v 1.8 2004/09/22 19:14:23 colmmacc Exp $
+ *
+ * mnc_multicast.c -- Multicast NetCat
+ *
+ * Colm MacCarthaigh, <colm@apache.org>
+ *
+ * copyright (c) 2007, Colm MacCarthaigh.
+ * Copyright (c) 2004 - 2006, HEAnet Ltd.
+ *
+ * This software is an open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the HEAnet Ltd. nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef WINDOWS
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <string.h>
+#include <netdb.h>
+#include <errno.h>
+
+#else
+
+#include <sys/types.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <stdlib.h>
+
+#endif
+
+#include "mnc.h"
+
+#ifndef MCAST_JOIN_GROUP
+
+#ifdef IP_ADD_SOURCE_MEMBERSHIP
+int mnc_join_ipv4_ssm(int socket, struct addrinfo * group,
+ struct addrinfo * source, char * iface)
+{
+ struct ip_mreq_source multicast_request;
+
+ if (iface != NULL)
+ {
+ /* See if interface is a literal IPv4 address */
+ if ((multicast_request.imr_interface.s_addr =
+ inet_addr(iface)) == INADDR_NONE)
+ {
+ mnc_warning("Invalid interface address\n");
+ return -1;
+ }
+ }
+ else
+ {
+ /* set the interface to the default */
+ multicast_request.imr_interface.s_addr = htonl(INADDR_ANY);
+ }
+
+ multicast_request.imr_multiaddr.s_addr =
+ ((struct sockaddr_in *)group->ai_addr)->sin_addr.s_addr;
+
+ multicast_request.imr_sourceaddr.s_addr =
+ ((struct sockaddr_in *)source->ai_addr)->sin_addr.s_addr;
+
+ /* Set the socket option */
+ if (setsockopt(socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
+ (char *) &multicast_request,
+ sizeof(multicast_request)) != 0)
+ {
+ mnc_warning("Could not join the multicast group: %s\n",
+ strerror(errno));
+
+ return -1;
+ }
+
+ return 0;
+}
+#else
+
+int mnc_join_ipv4_ssm(int socket, struct addrinfo * group,
+ struct addrinfo * source, char * iface)
+{
+ mnc_warning("Sorry, No support for IPv4 source-specific multicast in this build\n");
+
+ return -1;
+}
+#endif
+
+int mnc_join_ipv6_ssm(int socket, struct addrinfo * group,
+ struct addrinfo * source, char * iface)
+{
+ mnc_warning("Sorry, No support for IPv6 source-specific multicast in this build\n");
+
+ return -1;
+}
+#else /* if MCAST_JOIN_GROUP .. */
+
+#define mnc_join_ipv6_asm(a, b, c) mnc_join_ip_asm((a), (b), (c))
+#define mnc_join_ipv4_asm(a, b, c) mnc_join_ip_asm((a), (b), (c))
+
+int mnc_join_ip_asm(int socket, struct addrinfo * group, char * iface)
+{
+ struct group_req multicast_request;
+ int ip_proto;
+
+ if (group->ai_family == AF_INET6)
+ {
+ ip_proto = IPPROTO_IPV6;
+ }
+ else
+ {
+ ip_proto = IPPROTO_IP;
+ }
+
+ if (iface != NULL)
+ {
+ if ((multicast_request.gr_interface = if_nametoindex(iface))
+ == 0)
+ {
+ mnc_warning("Ignoring unknown interface: %s\n", iface);
+ }
+ }
+ else
+ {
+ multicast_request.gr_interface = 0;
+ }
+
+ memcpy(&multicast_request.gr_group, group->ai_addr, group->ai_addrlen);
+
+ /* Set the socket option */
+ if (setsockopt(socket, ip_proto, MCAST_JOIN_GROUP, (char *)
+ &multicast_request, sizeof(multicast_request)) != 0)
+ {
+ mnc_warning("Could not join the multicast group: %s\n",
+ strerror(errno));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* MCAST_JOIN_GROUP */
+
+#ifndef MCAST_JOIN_SOURCE_GROUP
+int mnc_join_ipv4_asm(int socket, struct addrinfo * group, char * iface)
+{
+ struct ip_mreq multicast_request;
+
+ if (iface != NULL)
+ {
+ /* See if interface is a literal IPv4 address */
+ if ((multicast_request.imr_interface.s_addr =
+ inet_addr(iface)) == INADDR_NONE)
+ {
+ mnc_warning("Invalid interface address\n");
+ return -1;
+ }
+ }
+ else
+ {
+ /* Set the interface to the default */
+ multicast_request.imr_interface.s_addr = htonl(INADDR_ANY);
+ }
+
+ multicast_request.imr_multiaddr.s_addr =
+ ((struct sockaddr_in *)group->ai_addr)->sin_addr.s_addr;
+
+ /* Set the socket option */
+ if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *) &multicast_request,
+ sizeof(multicast_request)) != 0)
+ {
+ mnc_warning("Could not join the multicast group: %s\n",
+ strerror(errno));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int mnc_join_ipv6_asm(int socket, struct addrinfo * group, char * iface)
+{
+ mnc_warning("Sorry, No support for IPv6 any-source multicast in this build\n");
+
+ return -1;
+}
+#else /* if MCAST_JOIN_SOURCE_GROUP ... */
+
+#define mnc_join_ipv4_ssm(a, b, c, d) mnc_join_ip_ssm((a), (b), (c), (d))
+#define mnc_join_ipv6_ssm(a, b, c, d) mnc_join_ip_ssm((a), (b), (c), (d))
+
+int mnc_join_ip_ssm(int socket, struct addrinfo * group,
+ struct addrinfo * source,
+ char * iface)
+{
+ struct group_source_req multicast_request;
+ int ip_proto;
+
+ if (group->ai_family == AF_INET6)
+ {
+ ip_proto = IPPROTO_IPV6;
+ }
+ else
+ {
+ ip_proto = IPPROTO_IP;
+ }
+
+ if (iface != NULL)
+ {
+ if ((multicast_request.gsr_interface = if_nametoindex(iface))
+ == 0)
+ {
+ mnc_warning("Ignoring unknown interface: %s\n", iface);
+ }
+ }
+ else
+ {
+ multicast_request.gsr_interface = 0;
+ }
+
+ memcpy(&multicast_request.gsr_group, group->ai_addr, group->ai_addrlen);
+ memcpy(&multicast_request.gsr_source, source->ai_addr,
+ source->ai_addrlen);
+
+ /* Set the socket option */
+ if (setsockopt(socket, ip_proto, MCAST_JOIN_SOURCE_GROUP,
+ (char *) &multicast_request,
+ sizeof(multicast_request)) != 0)
+ {
+ mnc_warning("Could not join the multicast group: %s\n",
+ strerror(errno));
+
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* MCAST_JOIN_SOURCE_GROUP */
+
+int multicast_setup_listen(int socket, struct addrinfo * group,
+ struct addrinfo * source, char * iface)
+{
+ size_t rcvbuf;
+
+#ifndef WINDOWS
+ /* bind to the group address before anything */
+ if (bind(socket, group->ai_addr, group->ai_addrlen) != 0)
+ {
+ mnc_warning("Could not bind to group-id\n");
+ return -1;
+ }
+#else
+ if (group->ai_family == AF_INET)
+ {
+ struct sockaddr_in sin;
+
+ sin.sin_family = group->ai_family;
+ sin.sin_port = group->ai_port;
+ sin.sin_addr = INADDR_ANY;
+
+ if (bind(socket, (struct sockaddr *) sin,
+ sizeof(sin)) != 0)
+ {
+ mnc_warning("Could not bind to ::\n");
+ return -1;
+ }
+ }
+ else if (group->ai_family == AF_INET6)
+ {
+ struct sockaddr_in6 sin6;
+
+ sin6.sin6_family = group->ai_family;
+ sin6.sin6_port = group->ai_port;
+ sin6.sin6_addr = in6addr_any;
+
+ if (bind(socket, (struct sockaddr *) sin6,
+ sizeof(sin6)) != 0)
+ {
+ mnc_warning("Could not bind to ::\n");
+ return -1;
+ }
+ }
+#endif
+
+ /* Set a receive buffer size of 64k */
+ rcvbuf = 1 << 15;
+ if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &rcvbuf,
+ sizeof(rcvbuf)) < 0) {
+ mnc_warning("Could not set receive buffer to 64k\n");
+ }
+
+ if (source != NULL)
+ {
+ if (group->ai_family == AF_INET6)
+ {
+ /* Use whatever IPv6 API is appropriate */
+ return
+ mnc_join_ipv6_ssm(socket, group, source, iface);
+ }
+ else if (group->ai_family == AF_INET)
+ {
+ /* Use the fully portable IPv4 API */
+ return
+ mnc_join_ipv4_ssm(socket, group, source, iface);
+ }
+ else
+ {
+ mnc_warning("Only IPv4 and IPv6 are supported\n");
+ return -1;
+ }
+ }
+ else
+ {
+ if (group->ai_family == AF_INET6)
+ {
+ /* Use the fully portable IPv4 API */
+ return
+ mnc_join_ipv6_asm(socket, group, iface);
+ }
+ else if (group->ai_family == AF_INET)
+ {
+ /* Use the fully portable IPv4 API */
+ return
+ mnc_join_ipv4_asm(socket, group, iface);
+ }
+ else
+ {
+ mnc_warning("Only IPv4 and IPv6 are supported\n");
+ return -1;
+ }
+ }
+
+ /* We should never get here */
+ return -1;
+}
+
+
+int multicast_setup_send(int socket, struct addrinfo * group,
+ struct addrinfo * source)
+{
+ int ttl = 255;
+
+ if (source != NULL)
+ {
+ /* bind to the address before anything */
+ if (bind(socket, source->ai_addr, source->ai_addrlen) != 0)
+ {
+ mnc_warning("Could not bind to source-address\n");
+ return -1;
+ }
+ }
+
+ if (group->ai_family == AF_INET)
+ {
+ if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)
+ &ttl, sizeof(ttl)) != 0)
+ {
+ mnc_warning("Could not increase the TTL\n");
+ return -1;
+ }
+ }
+ else if (group->ai_family == AF_INET6)
+ {
+ if (setsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ (char *) &ttl, sizeof(ttl)) != 0)
+ {
+ mnc_warning("Could not increase the hop-count\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * $Id: mnc_opts.c,v 1.3 2004/09/22 16:02:26 colmmacc Exp $
+ *
+ * mnc_opts.c -- Multicast NetCat
+ *
+ * Colm MacCarthaigh, <colm@apache.org>
+ *
+ * Copyright (c) 2007, Colm MacCarthaigh.
+ * Copyright (c) 2004 - 2006, HEAnet Ltd.
+ *
+ * This software is an open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the HEAnet Ltd. nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef WINDOWS
+
+/* UNIX-y includes */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#else
+
+/* WINDOWS-y includes */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#include "mnc.h"
+
+/* Display a usage statement */
+void usage(void)
+{
+ fprintf(stderr,
+ "Usage: mnc [-l] [-i interface] [-p port] group-id "
+ "[source-address]\n\n"
+ "-l : listen mode\n"
+ "-i : specify interface to listen\n"
+ "-p : specify port to listen/send on\n\n");
+ exit(1);
+}
+
+struct mnc_configuration * parse_arguments(int argc, char **argv)
+{
+ /* Utility variables */
+ int optind,
+ errorcode;
+ struct addrinfo hints;
+
+ /* Our persisting configuration */
+ static struct mnc_configuration config;
+
+ /* Set some defaults */
+ config.mode = SENDER;
+ config.port = MNC_DEFAULT_PORT;
+ config.iface = NULL;
+ config.source = NULL;
+
+ /* Loop through the arguments */
+ for (optind = 1; optind < (argc - 1); optind++)
+ {
+ if ( (argv[optind][0] == '-') || (argv[optind][0] == '/') )
+ {
+ switch(argv[optind][1])
+ {
+ /* Set listening mode */
+ case 'l': config.mode = LISTENER;
+ break;
+
+ /* Set port */
+ case 'p': config.port = argv[++optind];
+ break;
+
+ /* Set an interface */
+ case 'i': config.iface = argv[++optind];
+ break;
+
+ /* Unrecognised option */
+ default: usage();
+ break;
+ }
+ }
+ else
+ {
+ /* assume we've ran out of options */
+ break;
+ }
+ }
+
+ /* There's a chance we were passed one option */
+ if (optind >= argc || argv[optind][0] == '-')
+ {
+ usage();
+ }
+
+ /* Now make sure we have either exactly 1 or 2 more arguments */
+ if ( (argc - optind) != 1 && (argc - optind) != 2 )
+ {
+ /* We have not been given the right ammount of
+ arguments */
+ usage();
+ }
+
+ /* You can't have an interface without also listening */
+ if (config.mode == SENDER && config.iface != NULL)
+ {
+ mnc_error("You may only specify the interface when in"
+ " listening mode\n");
+ }
+
+ /* Set some hints for getaddrinfo */
+ memset(&hints, 0, sizeof(hints));
+
+ /* We want a UDP socket */
+ hints.ai_socktype = SOCK_DGRAM;
+
+ /* Don't do any name-lookups */
+ hints.ai_flags = AI_NUMERICHOST;
+
+ /* Get the group-id information */
+ if ( (errorcode =
+ getaddrinfo(argv[optind], config.port, &hints, &config.group)) != 0)
+ {
+ mnc_error("Error getting group-id address information: %s\n",
+ gai_strerror(errorcode));
+ }
+
+ /* Move on to next argument */
+ optind++;
+
+ /* Get the source information */
+ if ( (argc - optind) == 1)
+ {
+
+ if ( (errorcode =
+ getaddrinfo(argv[optind], config.port, &hints, &config.source))
+ != 0)
+ {
+ mnc_error("Error getting source-address information: %s\n",
+ gai_strerror(errorcode));
+ }
+
+ /* Confirm that the source and group are in the same Address Family */
+ if ( config.source->ai_family != config.group->ai_family )
+ {
+ mnc_error("Group ID and Source address are not of "
+ "the same type\n");
+ }
+ }
+
+ return &config;
+}
void *optval;
uint32_t fmode, ifindex;
socklen_t optlen;
- int af, error, i, level, n, optname;
+ int af, error, i, level, n = 0, optname;
#ifndef __APPLE__
int f, flags;
#endif /* __APPLE__ */
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<array>
- <dict>
- <key>OpenSourceProject</key>
- <string>mtest</string>
- <key>OpenSouceVersion</key>
- <string>1.11</string>
- <key>OpenSourceWebsiteURL</key>
- <string>http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/</string>
- <key>OpenSourceURL</key>
- <string>http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/</string>
- <key>OpenSourceSHA1</key>
- <string></string>
- <key>OpenSourceMD5</key>
- <string></string>
- <key>OpenSourceImportDate</key>
- <string>2011-01-13</string>
- <key>OpenSourceLicense</key>
- <string>Other</string>
- <key>OpenSourceLicenseFile</key>
- <string>mtest.txt</string>
- </dict>
-</array>
-</plist>
+.\" Copyright (c) 2012 Apple Inc. All rights reserved.
+.\"
+.\" @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+.\"
+.\" This file contains Original Code and/or Modifications of Original Code
+.\" as defined in and that are subject to the Apple Public Source License
+.\" Version 2.0 (the 'License'). You may not use this file except in
+.\" compliance with the License. The rights granted to you under the License
+.\" may not be used to create, or enable the creation or redistribution of,
+.\" unlawful or unlicensed copies of an Apple operating system, or to
+.\" circumvent, violate, or enable the circumvention or violation of, any
+.\" terms of an Apple operating system software license agreement.
+.\"
+.\" Please obtain a copy of the License at
+.\" http://www.opensource.apple.com/apsl/ and read it before using this file.
+.\"
+.\" The Original Code and all software distributed under the License are
+.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+.\" Please see the License for the specific language governing rights and
+.\" limitations under the License.
+.\"
+.\" @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+.\"
.\" $FreeBSD: src/usr.sbin/ndp/ndp.8,v 1.1.2.6 2001/08/16 15:56:09 ru Exp $
.\" $KAME: ndp.8,v 1.15 2001/02/08 07:17:03 itojun Exp $
.\"
.Xr tcpdump 1 .
Most useful when used with
.Fl A .
+.It Fl x
+Show extended link-layer reachability information in addition to that shown by
+the
+.Fl l
+flag.
.El
.\"
.Sh RETURN VALUES
/*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
void get __P((char *));
int delete __P((char *));
void dump __P((struct in6_addr *));
-void dump_ext __P((struct in6_addr *));
+void dump_ext __P((struct in6_addr *, int));
static struct in6_nbrinfo *getnbrinfo __P((struct in6_addr *addr,
int ifindex, int));
static char *ether_str __P((struct sockaddr_dl *));
{
int ch;
int aflag = 0, dflag = 0, sflag = 0, Hflag = 0,
- pflag = 0, rflag = 0, Pflag = 0, Rflag = 0, lflag = 0;
+ pflag = 0, rflag = 0, Pflag = 0, Rflag = 0, lflag = 0,
+ xflag = 0;
pid = getpid();
// thiszone = gmt2local(0);
- while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != -1)
+ while ((ch = getopt(argc, argv, "acndfIilprstA:HPRx")) != -1)
switch ((char)ch) {
case 'a':
aflag = 1;
case 'R':
Rflag = 1;
break;
+ case 'x':
+ xflag = 1;
+ lflag = 1;
+ break;
default:
usage();
}
if (aflag || cflag) {
if (lflag)
- dump_ext(0);
+ dump_ext(0, xflag);
else
dump(0);
exit(0);
struct rt_msghdr *rtm;
struct sockaddr_in6 *sin;
struct sockaddr_dl *sdl;
- extern int h_errno;
struct in6_nbrinfo *nbi;
struct timeval time;
int addrwidth;
* Dump the entire neighbor cache (extended)
*/
void
-dump_ext(addr)
+dump_ext(addr, xflag)
struct in6_addr *addr;
+ int xflag;
{
int mib[6];
size_t needed;
struct rt_msghdr_ext *ertm;
struct sockaddr_in6 *sin;
struct sockaddr_dl *sdl;
- extern int h_errno;
struct in6_nbrinfo *nbi;
struct timeval time;
int addrwidth;
char *ifname;
/* Print header */
- if (!tflag && !cflag)
- printf("%-*.*s %-*.*s %*.*s %-9.9s %-9.9s %2s %4s %4s\n",
+ if (!tflag && !cflag) {
+ printf("%-*.*s %-*.*s %*.*s %-9.9s %-9.9s %2s %4s %4s",
W_ADDR, W_ADDR, "Neighbor", W_LL, W_LL, "Linklayer Address",
W_IF, W_IF, "Netif", "Expire(O)", "Expire(I)", "St",
"Flgs", "Prbs");
+ if (xflag)
+ printf(" %-7.7s %-7.7s %-7.7s", "RSSI", "LQM", "NPM");
+ printf("\n");
+ }
again:;
mib[0] = CTL_NET;
if (prbs)
printf(" %4d", prbs);
+ if (xflag) {
+ if (!prbs)
+ printf(" %-4.4s", "none");
+
+ if (ertm->rtm_ri.ri_rssi != IFNET_RSSI_UNKNOWN)
+ printf(" %7d", ertm->rtm_ri.ri_rssi);
+ else
+ printf(" %-7.7s", "unknown");
+
+ switch (ertm->rtm_ri.ri_lqm)
+ {
+ case IFNET_LQM_THRESH_OFF:
+ printf(" %-7.7s", "off");
+ break;
+ case IFNET_LQM_THRESH_UNKNOWN:
+ printf(" %-7.7s", "unknown");
+ break;
+ case IFNET_LQM_THRESH_POOR:
+ printf(" %-7.7s", "poor");
+ break;
+ case IFNET_LQM_THRESH_GOOD:
+ printf(" %-7.7s", "good");
+ break;
+ default:
+ printf(" %7d", ertm->rtm_ri.ri_lqm);
+ break;
+ }
+
+ switch (ertm->rtm_ri.ri_npm)
+ {
+ case IFNET_NPM_THRESH_UNKNOWN:
+ printf(" %-7.7s", "unknown");
+ break;
+ case IFNET_NPM_THRESH_NEAR:
+ printf(" %-7.7s", "near");
+ break;
+ case IFNET_NPM_THRESH_GENERAL:
+ printf(" %-7.7s", "general");
+ break;
+ case IFNET_NPM_THRESH_FAR:
+ printf(" %-7.7s", "far");
+ break;
+ default:
+ printf(" %7d", ertm->rtm_ri.ri_npm);
+ break;
+ }
+ }
+
printf("\n");
}
if (buf != NULL)
}\
} while (0)
SETFLAG("nud", ND6_IFF_PERFORMNUD);
+ SETFLAG("proxy_prefixes", ND6_IFF_PROXY_PREFIXES);
+ SETFLAG("ignore_na", ND6_IFF_IGNORE_NA);
ND.flags = newflags;
if (ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd) < 0) {
printf("\nFlags: ");
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_IFDISABLED) != 0)
+ printf("IFDISABLED ");
+ if ((ND.flags & ND6_IFF_IGNORE_NA) != 0)
+ printf("IGNORE_NA ");
}
putc('\n', stdout);
#undef ND
* meaning of fields, especially flags, is very different
* by origin. notify the difference to the users.
*/
- printf("flags=%s%s%s%s%s%s%s",
+ printf("flags=%s%s%s%s%s%s%s%s",
p->raflags.onlink ? "L" : "",
p->raflags.autonomous ? "A" : "",
(p->flags & NDPRF_ONLINK) != 0 ? "O" : "",
(p->flags & NDPRF_DETACHED) != 0 ? "D" : "",
(p->flags & NDPRF_IFSCOPE) != 0 ? "I" : "",
+ (p->flags & NDPRF_PRPROXY) != 0 ? "Y" : "",
#ifdef NDPRF_HOME
(p->flags & NDPRF_HOME) != 0 ? "H" : "",
#else
/*
- * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
+#include <sys/ioctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/route.h>
+#include <net/pktsched/pktsched.h>
+#include <net/classq/if_classq.h>
+
#include <netinet/in.h>
#include <netinet/in_var.h>
static void catchalarm (int);
static char *sec2str(time_t);
static void llreach_sysctl(uint32_t);
+static char *nsec_to_str(unsigned long long);
+static char *qtype2str(classq_type_t);
+static char *sched2str(unsigned int);
+static char *qid2str(unsigned int);
+static char *qstate2str(unsigned int);
+static char *tcqslot2str(unsigned int);
+static char *rate2str(long double);
+
+#define AVGN_MAX 8
+
+struct queue_stats {
+ int avgn;
+ double avg_bytes;
+ double avg_packets;
+ u_int64_t prev_bytes;
+ u_int64_t prev_packets;
+ unsigned int printed;
+ unsigned int handle;
+};
+
+static void print_cbqstats(int slot, struct cbq_classstats *,
+ struct queue_stats *);
+static void print_priqstats(int slot, struct priq_classstats *,
+ struct queue_stats *);
+static void print_hfscstats(int slot, struct hfsc_classstats *,
+ struct queue_stats *);
+static void print_fairqstats(int slot, struct fairq_classstats *,
+ struct queue_stats *);
+static void print_tcqstats(int slot, struct tcq_classstats *,
+ struct queue_stats *);
+static void print_qfqstats(int slot, struct qfq_classstats *,
+ struct queue_stats *);
+static void print_sfbstats(struct sfb_stats *);
+static void update_avg(struct if_ifclassq_stats *, struct queue_stats *);
+
+struct queue_stats qstats[IFCQ_SC_MAX];
#ifdef INET6
char *netname6 (struct sockaddr_in6 *, struct sockaddr *);
printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
"Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
if (prioflag >= 0)
- printf(" %8.8s", "Itcpkts");
+ printf(" %8.8s %8.8s", "Itcpkts", "Ipvpkts");
if (bflag) {
printf(" %10.10s","Ibytes");
if (prioflag >= 0)
- printf(" %10.10s", "Itcbytes");
+ printf(" %8.8s %8.8s", "Itcbytes", "Ipvbytes");
}
printf(" %8.8s %5.5s", "Opkts", "Oerrs");
if (prioflag >= 0)
- printf(" %8.8s", "Otcpkts");
+ printf(" %8.8s %8.8s", "Otcpkts", "Opvpkts");
if (bflag) {
printf(" %10.10s","Obytes");
if (prioflag >= 0)
- printf(" %10.10s", "Otcbytes");
+ printf(" %8.8s %8.8s", "Otcbytes", "Opvbytes");
}
printf(" %5s", "Coll");
if (tflag)
u_int64_t ift_itcb = 0; /* input tc bytes */
u_int64_t ift_otcp = 0; /* output tc packets */
u_int64_t ift_otcb = 0; /* output tc bytes */
-
+ u_int64_t ift_ipvp = 0; /* input priv tc packets */
+ u_int64_t ift_ipvb = 0; /* input priv tc bytes */
+ u_int64_t ift_opvp = 0; /* output priv tc packets */
+ u_int64_t ift_opvb = 0; /* output priv tc bytes */
+
bzero(&ifmsupp, sizeof(struct ifmibdata_supplemental));
network_layer = 0;
err(1, "sysctl IFDATA_SUPPLEMENTAL");
switch (prioflag) {
+ case SO_TC_BE:
+ ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibepackets;
+ ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibebytes;
+ ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obepackets;
+ ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obebytes;
+ break;
case SO_TC_BK:
ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
ift_itcb = 0;
ift_otcp = 0;
ift_otcb = 0;
+ ift_ipvp = 0;
+ ift_ipvb = 0;
+ ift_opvp = 0;
+ ift_opvb = 0;
break;
}
+ ift_ipvp = ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
+ ift_ipvb = ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
+ ift_opvp = ifmsupp.ifmd_traffic_class.ifi_opvpackets;
+ ift_opvb = ifmsupp.ifmd_traffic_class.ifi_opvbytes;
}
get_rti_info(if2m->ifm_addrs, (struct sockaddr*)(if2m + 1), rti_info);
if (prioflag >= 0) {
show_stat("llu", 8, ift_itcp, link_layer|network_layer);
printf(" ");
+ show_stat("llu", 8, ift_ipvp, link_layer|network_layer);
+ printf(" ");
}
if (bflag) {
show_stat("llu", 10, ibytes, link_layer|network_layer);
if (prioflag >= 0) {
show_stat("llu", 8, ift_itcb, link_layer|network_layer);
printf(" ");
+ show_stat("llu", 8, ift_ipvb, link_layer|network_layer);
+ printf(" ");
}
}
show_stat("llu", 8, opackets, link_layer|network_layer);
if (prioflag >= 0) {
show_stat("llu", 8, ift_otcp, link_layer|network_layer);
printf(" ");
+ show_stat("llu", 8, ift_opvp, link_layer|network_layer);
+ printf(" ");
}
if (bflag) {
show_stat("llu", 10, obytes, link_layer|network_layer);
if (prioflag >= 0) {
show_stat("llu", 8, ift_otcb, link_layer|network_layer);
printf(" ");
+ show_stat("llu", 8, ift_opvb, link_layer|network_layer);
+ printf(" ");
}
}
show_stat("llu", 5, collisions, link_layer);
u_int64_t ift_itcb; /* input tc bytes */
u_int64_t ift_otcp; /* output tc packets */
u_int64_t ift_otcb; /* output tc bytes */
+ u_int64_t ift_ipvp; /* input priv tc packets */
+ u_int64_t ift_ipvb; /* input priv tc bytes */
+ u_int64_t ift_opvp; /* output priv tc packets */
+ u_int64_t ift_opvb; /* output priv tc bytes */
};
u_char signalled; /* set if alarm goes off "early" */
first = 1;
banner:
if (prioflag >= 0)
- printf("%37s %14s %16s", "input",
+ printf("%39s %39s %36s", "input",
interesting ? interesting->ift_name : "(Total)", "output");
else
printf("%17s %14s %16s", "input",
printf("%10s %5s %10s ",
"packets", "errs", "bytes");
if (prioflag >= 0)
- printf(" %10s %10s", "tcpkts", "tcbytes");
+ printf(" %10s %10s %10s %10s", "tcpkts", "tcbytes", "pvpkts", "pvbytes");
printf("%10s %5s %10s %5s",
"packets", "errs", "bytes", "colls");
if (dflag)
printf(" %5.5s", "drops");
if (prioflag >= 0)
- printf(" %10s %10s", "tcpkts", "tcbytes");
+ printf(" %10s %10s %10s %10s", "tcpkts", "tcbytes", "pvpkts", "pvbytes");
putchar('\n');
fflush(stdout);
line = 0;
if (sysctl(name, 6, &ifmsupp, &len, (void *)0, 0) == -1)
err(1, "sysctl IFDATA_SUPPLEMENTAL %d", interesting_row);
}
+
if (!first) {
printf("%10llu %5llu %10llu ",
ifmd.ifmd_data.ifi_ipackets - interesting->ift_ip,
ifmd.ifmd_data.ifi_ierrors - interesting->ift_ie,
ifmd.ifmd_data.ifi_ibytes - interesting->ift_ib);
switch (prioflag) {
+ case SO_TC_BE:
+ printf("%10llu %10llu ",
+ ifmsupp.ifmd_traffic_class.ifi_ibepackets - interesting->ift_itcp,
+ ifmsupp.ifmd_traffic_class.ifi_ibebytes - interesting->ift_itcb);
+ break;
case SO_TC_BK:
printf("%10llu %10llu ",
ifmsupp.ifmd_traffic_class.ifi_ibkpackets - interesting->ift_itcp,
default:
break;
}
+ if (prioflag >= 0) {
+ printf("%10llu %10llu ",
+ ifmsupp.ifmd_traffic_class.ifi_ipvpackets - interesting->ift_ipvp,
+ ifmsupp.ifmd_traffic_class.ifi_ipvbytes - interesting->ift_ipvb);
+ }
printf("%10llu %5llu %10llu %5llu",
ifmd.ifmd_data.ifi_opackets - interesting->ift_op,
ifmd.ifmd_data.ifi_oerrors - interesting->ift_oe,
if (dflag)
printf(" %5llu", ifmd.ifmd_snd_drops - interesting->ift_dr);
switch (prioflag) {
+ case SO_TC_BE:
+ printf(" %10llu %10llu",
+ ifmsupp.ifmd_traffic_class.ifi_obepackets - interesting->ift_otcp,
+ ifmsupp.ifmd_traffic_class.ifi_obebytes - interesting->ift_otcb);
+ break;
case SO_TC_BK:
printf(" %10llu %10llu",
ifmsupp.ifmd_traffic_class.ifi_obkpackets - interesting->ift_otcp,
default:
break;
}
+ if (prioflag >= 0) {
+ printf("%10llu %10llu ",
+ ifmsupp.ifmd_traffic_class.ifi_opvpackets - interesting->ift_opvp,
+ ifmsupp.ifmd_traffic_class.ifi_opvbytes - interesting->ift_opvb);
+ }
}
interesting->ift_ip = ifmd.ifmd_data.ifi_ipackets;
interesting->ift_ie = ifmd.ifmd_data.ifi_ierrors;
interesting->ift_dr = ifmd.ifmd_snd_drops;
/* private counters */
switch (prioflag) {
+ case SO_TC_BE:
+ interesting->ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibepackets;
+ interesting->ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibebytes;
+ interesting->ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obepackets;
+ interesting->ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obebytes;
+ break;
case SO_TC_BK:
interesting->ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
interesting->ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
default:
break;
}
+ if (prioflag >= 0) {
+ interesting->ift_ipvp = ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
+ interesting->ift_ipvb = ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
+ interesting->ift_opvp = ifmsupp.ifmd_traffic_class.ifi_opvpackets;
+ interesting->ift_opvb = ifmsupp.ifmd_traffic_class.ifi_opvbytes;
+ }
} else {
unsigned int latest_ifcount;
struct ifmibdata_supplemental *ifmsuppall = NULL;
sum->ift_itcb = 0;
sum->ift_otcp = 0;
sum->ift_otcb = 0;
+ sum->ift_ipvp = 0;
+ sum->ift_ipvb = 0;
+ sum->ift_opvp = 0;
+ sum->ift_opvb = 0;
for (i = 0; i < ifcount; i++) {
struct ifmibdata *ifmd = ifmdall + i;
if (prioflag >= 0) {
struct ifmibdata_supplemental *ifmsupp = ifmsuppall + i;
switch (prioflag) {
+ case SO_TC_BE:
+ sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibepackets;
+ sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibebytes;
+ sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obepackets;
+ sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obebytes;
+ break;
case SO_TC_BK:
sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibkpackets;
sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibkbytes;
default:
break;
}
+ sum->ift_ipvp += ifmsupp->ifmd_traffic_class.ifi_ipvpackets;
+ sum->ift_ipvb += ifmsupp->ifmd_traffic_class.ifi_ipvbytes;
+ sum->ift_opvp += ifmsupp->ifmd_traffic_class.ifi_opvpackets;
+ sum->ift_opvb += ifmsupp->ifmd_traffic_class.ifi_opvbytes;
}
}
if (!first) {
sum->ift_ie - total->ift_ie,
sum->ift_ib - total->ift_ib);
if (prioflag >= 0)
- printf(" %10llu %10llu",
+ printf(" %10llu %10llu %10llu %10llu",
sum->ift_itcp - total->ift_itcp,
- sum->ift_itcb - total->ift_itcb);
+ sum->ift_itcb - total->ift_itcb,
+ sum->ift_ipvp - total->ift_ipvp,
+ sum->ift_ipvb - total->ift_ipvb);
printf("%10llu %5llu %10llu %5llu",
sum->ift_op - total->ift_op,
sum->ift_oe - total->ift_oe,
if (dflag)
printf(" %5llu", sum->ift_dr - total->ift_dr);
if (prioflag >= 0)
- printf(" %10llu %10llu",
+ printf(" %10llu %10llu %10llu %10llu",
sum->ift_otcp - total->ift_otcp,
- sum->ift_otcb - total->ift_otcb);
+ sum->ift_otcb - total->ift_otcb,
+ sum->ift_opvp - total->ift_opvp,
+ sum->ift_opvb - total->ift_opvb);
}
*total = *sum;
}
return;
}
- printf("%-6s %-17s %8.8s %-9.9s %4s %4s\n",
- "Proto", "Linklayer Address", "Netif", "Expire", "Refs", "Prbs");
+ printf("%-6s %-17s %8.8s %-9.9s %4s %4s",
+ "Proto", "Linklayer Address", "Netif", "Expire", "Refs",
+ "Prbs");
+ if (xflag)
+ printf(" %7s %7s %7s", "RSSI", "LQM", "NPM");
+ printf("\n");
lim = buf + len;
if2m = (struct if_msghdr2 *)buf;
printf(" %4d", lri->lri_refcnt);
if (lri->lri_probes)
printf(" %4d", lri->lri_probes);
+
+ if (xflag) {
+ if (!lri->lri_probes)
+ printf(" %-4.4s", "none");
+
+ if (lri->lri_rssi != IFNET_RSSI_UNKNOWN)
+ printf(" %7d", lri->lri_rssi);
+ else
+ printf(" %-7.7s", "unknown");
+
+ switch (lri->lri_lqm)
+ {
+ case IFNET_LQM_THRESH_OFF:
+ printf(" %-7.7s", "off");
+ break;
+ case IFNET_LQM_THRESH_UNKNOWN:
+ printf(" %-7.7s", "unknown");
+ break;
+ case IFNET_LQM_THRESH_POOR:
+ printf(" %-7.7s", "poor");
+ break;
+ case IFNET_LQM_THRESH_GOOD:
+ printf(" %-7.7s", "good");
+ break;
+ default:
+ printf(" %7d", lri->lri_lqm);
+ break;
+ }
+
+ switch (lri->lri_npm)
+ {
+ case IFNET_NPM_THRESH_UNKNOWN:
+ printf(" %-7.7s", "unknown");
+ break;
+ case IFNET_NPM_THRESH_NEAR:
+ printf(" %-7.7s", "near");
+ break;
+ case IFNET_NPM_THRESH_GENERAL:
+ printf(" %-7.7s", "general");
+ break;
+ case IFNET_NPM_THRESH_FAR:
+ printf(" %-7.7s", "far");
+ break;
+ default:
+ printf(" %7d", lri->lri_npm);
+ break;
+ }
+ }
+
printf("\n");
len -= sizeof (*lri);
}
+
if (len > 0) {
fprintf(stderr, "warning: %u trailing bytes from %s\n",
(unsigned int)len, "net.link.generic.system.llreach_info");
free(buf);
#undef MAX_SYSCTL_TRY
}
+
+void
+aqstatpr(void)
+{
+ unsigned int ifindex;
+ struct itimerval timer_interval;
+ struct if_qstatsreq ifqr;
+ struct if_ifclassq_stats *ifcqs;
+ sigset_t sigset, oldsigset;
+ u_int32_t scheduler;
+ int s, n, tcq = 0;
+
+ if (cq < -1 || cq >= IFCQ_SC_MAX) {
+ fprintf(stderr, "Invalid classq index (range is 0-%d)\n",
+ IFCQ_SC_MAX-1);
+ return;
+ }
+ ifindex = if_nametoindex(interface);
+ if (ifindex == 0) {
+ fprintf(stderr, "Invalid interface name\n");
+ return;
+ }
+
+ ifcqs = malloc(sizeof (*ifcqs));
+ if (ifcqs == NULL) {
+ fprintf(stderr, "Unable to allocate memory\n");
+ return;
+ }
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("Warning: socket(AF_INET)");
+ free(ifcqs);
+ return;
+ }
+
+ bzero(&ifqr, sizeof (ifqr));
+ strlcpy(ifqr.ifqr_name, interface, sizeof (ifqr.ifqr_name));
+ ifqr.ifqr_buf = ifcqs;
+ ifqr.ifqr_len = sizeof (*ifcqs);
+
+loop:
+ if (interval > 0) {
+ /* create a timer that fires repeatedly every interval seconds */
+ timer_interval.it_value.tv_sec = interval;
+ timer_interval.it_value.tv_usec = 0;
+ timer_interval.it_interval.tv_sec = interval;
+ timer_interval.it_interval.tv_usec = 0;
+ (void) signal(SIGALRM, catchalarm);
+ signalled = NO;
+ (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
+ }
+
+ ifqr.ifqr_slot = 0;
+ if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
+ if (errno == ENXIO) {
+ printf("Queue statistics are not available on %s\n",
+ interface);
+ } else {
+ perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
+ }
+ goto done;
+ }
+ scheduler = ifcqs->ifqs_scheduler;
+ tcq = (scheduler == PKTSCHEDT_TCQ);
+
+ printf("%s:\n"
+ "%s [ sched: %9s %sqlength: %3d/%3d ]\n",
+ interface, tcq ? " " : "", sched2str(ifcqs->ifqs_scheduler),
+ tcq ? "" : " ", ifcqs->ifqs_len, ifcqs->ifqs_maxlen);
+ printf("%s [ pkts: %10llu %sbytes: %10llu "
+ "%sdropped pkts: %6llu bytes: %6llu ]\n",
+ (scheduler != PKTSCHEDT_TCQ) ? "" : " ",
+ ifcqs->ifqs_xmitcnt.packets, tcq ? "" : " ",
+ ifcqs->ifqs_xmitcnt.bytes, tcq ? "" : " ",
+ ifcqs->ifqs_dropcnt.packets, ifcqs->ifqs_dropcnt.bytes);
+
+ for (n = 0; n < IFCQ_SC_MAX; n++) {
+ qstats[n].printed = 0;
+ if (!tcq)
+ continue;
+ ifqr.ifqr_slot = n;
+ if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
+ perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
+ goto done;
+ }
+ qstats[n].handle = ifcqs->ifqs_tcq_stats.class_handle;
+ }
+
+ for (n = 0; n < IFCQ_SC_MAX && scheduler != PKTSCHEDT_NONE; n++) {
+ if (cq >= 0 && cq != n)
+ continue;
+
+ ifqr.ifqr_slot = n;
+ if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
+ perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
+ goto done;
+ }
+
+ update_avg(ifcqs, &qstats[n]);
+
+ switch (scheduler) {
+ case PKTSCHEDT_CBQ:
+ print_cbqstats(n, &ifcqs->ifqs_cbq_stats,
+ &qstats[n]);
+ break;
+ case PKTSCHEDT_HFSC:
+ print_hfscstats(n, &ifcqs->ifqs_hfsc_stats,
+ &qstats[n]);
+ break;
+ case PKTSCHEDT_PRIQ:
+ print_priqstats(n, &ifcqs->ifqs_priq_stats,
+ &qstats[n]);
+ break;
+ case PKTSCHEDT_FAIRQ:
+ print_fairqstats(n, &ifcqs->ifqs_fairq_stats,
+ &qstats[n]);
+ break;
+ case PKTSCHEDT_TCQ:
+ print_tcqstats(n, &ifcqs->ifqs_tcq_stats,
+ &qstats[n]);
+ break;
+ case PKTSCHEDT_QFQ:
+ print_qfqstats(n, &ifcqs->ifqs_qfq_stats,
+ &qstats[n]);
+ break;
+ case PKTSCHEDT_NONE:
+ default:
+ break;
+ }
+ }
+
+ fflush(stdout);
+
+ if (interval > 0) {
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGALRM);
+ (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
+ if (!signalled) {
+ sigemptyset(&sigset);
+ sigsuspend(&sigset);
+ }
+ (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
+
+ signalled = NO;
+ goto loop;
+ }
+
+done:
+ free(ifcqs);
+ close(s);
+}
+
+static void
+print_cbqstats(int slot, struct cbq_classstats *cs, struct queue_stats *qs)
+{
+ printf(" %2d: [ pkts: %10llu bytes: %10llu "
+ "dropped pkts: %6llu bytes: %6llu ]\n", slot,
+ (unsigned long long)cs->xmit_cnt.packets,
+ (unsigned long long)cs->xmit_cnt.bytes,
+ (unsigned long long)cs->drop_cnt.packets,
+ (unsigned long long)cs->drop_cnt.bytes);
+ printf(" [ qlength: %3d/%3d borrows: %6u "
+ "suspends: %6u qalg: %s ]\n", cs->qcnt, cs->qmax,
+ cs->borrows, cs->delays, qtype2str(cs->qtype));
+ printf(" [ service class: %5s ]\n", qid2str(cs->handle));
+
+ if (qs->avgn >= 2) {
+ printf(" [ measured: %7.1f packets/s, %s/s ]\n",
+ qs->avg_packets / interval,
+ rate2str((8 * qs->avg_bytes) / interval));
+ }
+
+ if (qflag < 2)
+ return;
+
+ switch (cs->qtype) {
+ case Q_SFB:
+ print_sfbstats(&cs->sfb);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+print_priqstats(int slot, struct priq_classstats *cs, struct queue_stats *qs)
+{
+ printf(" %2d: [ pkts: %10llu bytes: %10llu "
+ "dropped pkts: %6llu bytes: %6llu ]\n", slot,
+ (unsigned long long)cs->xmitcnt.packets,
+ (unsigned long long)cs->xmitcnt.bytes,
+ (unsigned long long)cs->dropcnt.packets,
+ (unsigned long long)cs->dropcnt.bytes);
+ printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n",
+ cs->qlength, cs->qlimit, qtype2str(cs->qtype),
+ qid2str(cs->class_handle));
+
+ if (qs->avgn >= 2) {
+ printf(" [ measured: %7.1f packets/s, %s/s ]\n",
+ qs->avg_packets / interval,
+ rate2str((8 * qs->avg_bytes) / interval));
+ }
+
+ if (qflag < 2)
+ return;
+
+ switch (cs->qtype) {
+ case Q_SFB:
+ print_sfbstats(&cs->sfb);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+print_hfscstats(int slot, struct hfsc_classstats *cs, struct queue_stats *qs)
+{
+ printf(" %2d: [ pkts: %10llu bytes: %10llu "
+ "dropped pkts: %6llu bytes: %6llu ]\n", slot,
+ (unsigned long long)cs->xmit_cnt.packets,
+ (unsigned long long)cs->xmit_cnt.bytes,
+ (unsigned long long)cs->drop_cnt.packets,
+ (unsigned long long)cs->drop_cnt.bytes);
+ printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n",
+ cs->qlength, cs->qlimit, qtype2str(cs->qtype),
+ qid2str(cs->class_handle));
+
+ if (qs->avgn >= 2) {
+ printf(" [ measured: %7.1f packets/s, %s/s ]\n",
+ qs->avg_packets / interval,
+ rate2str((8 * qs->avg_bytes) / interval));
+ }
+
+ if (qflag < 2)
+ return;
+
+ switch (cs->qtype) {
+ case Q_SFB:
+ print_sfbstats(&cs->sfb);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+print_fairqstats(int slot, struct fairq_classstats *cs, struct queue_stats *qs)
+{
+ printf(" %2d: [ pkts: %10llu bytes: %10llu "
+ "dropped pkts: %6llu bytes: %6llu ]\n", slot,
+ (unsigned long long)cs->xmit_cnt.packets,
+ (unsigned long long)cs->xmit_cnt.bytes,
+ (unsigned long long)cs->drop_cnt.packets,
+ (unsigned long long)cs->drop_cnt.bytes);
+ printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]]\n",
+ cs->qlength, cs->qlimit, qtype2str(cs->qtype),
+ qid2str(cs->class_handle));
+
+ if (qs->avgn >= 2) {
+ printf(" [ measured: %7.1f packets/s, %s/s ]\n",
+ qs->avg_packets / interval,
+ rate2str((8 * qs->avg_bytes) / interval));
+ }
+
+ if (qflag < 2)
+ return;
+
+ switch (cs->qtype) {
+ case Q_SFB:
+ print_sfbstats(&cs->sfb);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+print_tcqstats(int slot, struct tcq_classstats *cs, struct queue_stats *qs)
+{
+ int n;
+
+ if (qs->printed)
+ return;
+
+ qs->handle = cs->class_handle;
+ qs->printed++;
+
+ for (n = 0; n < IFCQ_SC_MAX; n++) {
+ if (&qstats[n] != qs && qstats[n].handle == qs->handle)
+ qstats[n].printed++;
+ }
+
+ printf("%5s: [ pkts: %10llu bytes: %10llu "
+ "dropped pkts: %6llu bytes: %6llu ]\n", tcqslot2str(slot),
+ (unsigned long long)cs->xmitcnt.packets,
+ (unsigned long long)cs->xmitcnt.bytes,
+ (unsigned long long)cs->dropcnt.packets,
+ (unsigned long long)cs->dropcnt.bytes);
+ printf(" [ qlength: %3d/%3d qalg: %11s "
+ "svc class: %9s %-13s ]\n", cs->qlength, cs->qlimit,
+ qtype2str(cs->qtype), qid2str(cs->class_handle),
+ qstate2str(cs->qstate));
+
+ if (qs->avgn >= 2) {
+ printf(" [ measured: %7.1f packets/s, %s/s ]\n",
+ qs->avg_packets / interval,
+ rate2str((8 * qs->avg_bytes) / interval));
+ }
+
+ if (qflag < 2)
+ return;
+
+ switch (cs->qtype) {
+ case Q_SFB:
+ print_sfbstats(&cs->sfb);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+print_qfqstats(int slot, struct qfq_classstats *cs, struct queue_stats *qs)
+{
+ printf(" %2d: [ pkts: %10llu bytes: %10llu "
+ "dropped pkts: %6llu bytes: %6llu ]\n", slot,
+ (unsigned long long)cs->xmitcnt.packets,
+ (unsigned long long)cs->xmitcnt.bytes,
+ (unsigned long long)cs->dropcnt.packets,
+ (unsigned long long)cs->dropcnt.bytes);
+ printf(" [ qlength: %3d/%3d index: %10u weight: %12u "
+ "lmax: %7u ]\n", cs->qlength, cs->qlimit, cs->index,
+ cs->weight, cs->lmax);
+ printf(" [ qalg: %10s svc class: %6s %-35s ]\n",
+ qtype2str(cs->qtype), qid2str(cs->class_handle),
+ qstate2str(cs->qstate));
+
+ if (qs->avgn >= 2) {
+ printf(" [ measured: %7.1f packets/s, %s/s ]\n",
+ qs->avg_packets / interval,
+ rate2str((8 * qs->avg_bytes) / interval));
+ }
+
+ if (qflag < 2)
+ return;
+
+ switch (cs->qtype) {
+ case Q_SFB:
+ print_sfbstats(&cs->sfb);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+print_sfbstats(struct sfb_stats *sfb)
+{
+ struct sfbstats *sp = &sfb->sfbstats;
+ int i, j, cur = sfb->current;
+
+ printf("\n");
+ printf(" [ early drop: %12llu rlimit drop: %11llu "
+ "marked: %11llu ]\n",
+ sp->drop_early, sp->drop_pbox, sp->marked_packets);
+ printf(" [ penalized: %13llu rehash cnt: %12llu "
+ "current: %10u ]\n", sp->pbox_packets, sp->num_rehash, cur);
+ printf(" [ deque avg: %13s ", nsec_to_str(sp->dequeue_avg));
+ printf("rehash intvl: %11s]\n", nsec_to_str(sp->rehash_intval));
+ printf(" [ holdtime: %14s ", nsec_to_str(sp->hold_time));
+ printf("pboxtime: %14s ]\n", nsec_to_str(sp->pbox_time));
+ printf(" [ allocation: %12u drop thresh: %11u ]\n",
+ sfb->allocation, sfb->dropthresh);
+ printf(" [ flow controlled: %7llu adv feedback: %10llu ]\n",
+ sp->flow_controlled, sp->flow_feedback);
+
+ printf("\n\t\t\t\tCurrent bins (set %d)", cur);
+ for (i = 0; i < SFB_LEVELS; ++i) {
+ unsigned int q;
+ double p;
+
+ printf("\n\tLevel: %d\n", i);
+ for (j = 0; j < SFB_BINS; ++j) {
+ if ((j % 4) == 0)
+ printf("\t%6d:\t", j + 1);
+ p = sfb->binstats[cur].stats[i][j].pmark;
+ q = sfb->binstats[cur].stats[i][j].pkts;
+ if (p > 0) {
+ p /= (1 << SFB_FP_SHIFT);
+ printf("[%1.4f %4u]", p, q);
+ } else {
+ printf("[ ]");
+ }
+ if (j > 0 && ((j + 1) % 4) == 0)
+ printf("\n");
+ }
+ }
+
+ cur ^= 1;
+ printf("\n\t\t\t\tWarm up bins (set %d)", cur);
+ for (i = 0; i < SFB_LEVELS; ++i) {
+ unsigned int q;
+ double p;
+
+ printf("\n\tLevel: %d\n", i);
+ for (j = 0; j < SFB_BINS; ++j) {
+ if ((j % 4) == 0)
+ printf("\t%6d:\t", j + 1);
+ p = sfb->binstats[cur].stats[i][j].pmark;
+ q = sfb->binstats[cur].stats[i][j].pkts;
+ if (p > 0) {
+ p /= (1 << SFB_FP_SHIFT);
+ printf("[%1.4f %4u]", p, q);
+ } else {
+ printf("[ ]");
+ }
+ if (j > 0 && ((j + 1) % 4) == 0)
+ printf("\n");
+ }
+ }
+ printf("\n");
+}
+
+static void
+update_avg(struct if_ifclassq_stats *ifcqs, struct queue_stats *qs)
+{
+ u_int64_t b, p;
+ int n;
+
+ n = qs->avgn;
+
+ switch (ifcqs->ifqs_scheduler) {
+ case PKTSCHEDT_CBQ:
+ b = ifcqs->ifqs_cbq_stats.xmit_cnt.bytes;
+ p = ifcqs->ifqs_cbq_stats.xmit_cnt.packets;
+ break;
+ case PKTSCHEDT_PRIQ:
+ b = ifcqs->ifqs_priq_stats.xmitcnt.bytes;
+ p = ifcqs->ifqs_priq_stats.xmitcnt.packets;
+ break;
+ case PKTSCHEDT_HFSC:
+ b = ifcqs->ifqs_hfsc_stats.xmit_cnt.bytes;
+ p = ifcqs->ifqs_hfsc_stats.xmit_cnt.packets;
+ break;
+ case PKTSCHEDT_FAIRQ:
+ b = ifcqs->ifqs_fairq_stats.xmit_cnt.bytes;
+ p = ifcqs->ifqs_fairq_stats.xmit_cnt.packets;
+ break;
+ case PKTSCHEDT_TCQ:
+ b = ifcqs->ifqs_tcq_stats.xmitcnt.bytes;
+ p = ifcqs->ifqs_tcq_stats.xmitcnt.packets;
+ break;
+ case PKTSCHEDT_QFQ:
+ b = ifcqs->ifqs_qfq_stats.xmitcnt.bytes;
+ p = ifcqs->ifqs_qfq_stats.xmitcnt.packets;
+ break;
+ default:
+ b = 0;
+ p = 0;
+ break;
+ }
+
+ if (n == 0) {
+ qs->prev_bytes = b;
+ qs->prev_packets = p;
+ qs->avgn++;
+ return;
+ }
+
+ if (b >= qs->prev_bytes)
+ qs->avg_bytes = ((qs->avg_bytes * (n - 1)) +
+ (b - qs->prev_bytes)) / n;
+
+ if (p >= qs->prev_packets)
+ qs->avg_packets = ((qs->avg_packets * (n - 1)) +
+ (p - qs->prev_packets)) / n;
+
+ qs->prev_bytes = b;
+ qs->prev_packets = p;
+ if (n < AVGN_MAX)
+ qs->avgn++;
+}
+
+static char *
+qtype2str(classq_type_t t)
+{
+ char *c;
+
+ switch (t) {
+ case Q_DROPHEAD:
+ c = "DROPHEAD";
+ break;
+ case Q_DROPTAIL:
+ c = "DROPTAIL";
+ break;
+ case Q_RED:
+ c = "RED";
+ break;
+ case Q_RIO:
+ c = "RIO";
+ break;
+ case Q_BLUE:
+ c = "BLUE";
+ break;
+ case Q_SFB:
+ c = "SFB";
+ break;
+ default:
+ c = "UNKNOWN";
+ break;
+ }
+
+ return (c);
+}
+
+#define NSEC_PER_SEC 1000000000 /* nanoseconds per second */
+#define USEC_PER_SEC 1000000 /* nanoseconds per second */
+#define MSEC_PER_SEC 1000 /* nanoseconds per second */
+
+static char *
+nsec_to_str(unsigned long long nsec)
+{
+ static char buf[32];
+ const char *u;
+ long double n = nsec, t;
+
+ if (nsec >= NSEC_PER_SEC) {
+ t = n / NSEC_PER_SEC;
+ u = "sec ";
+ } else if (n >= USEC_PER_SEC) {
+ t = n / USEC_PER_SEC;
+ u = "msec";
+ } else if (n >= MSEC_PER_SEC) {
+ t = n / MSEC_PER_SEC;
+ u = "usec";
+ } else {
+ t = n;
+ u = "nsec";
+ }
+
+ snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
+ return (buf);
+}
+
+static char *
+sched2str(unsigned int s)
+{
+ char *c;
+
+ switch (s) {
+ case PKTSCHEDT_NONE:
+ c = "NONE";
+ break;
+ case PKTSCHEDT_CBQ:
+ c = "CBQ";
+ break;
+ case PKTSCHEDT_HFSC:
+ c = "HFSC";
+ break;
+ case PKTSCHEDT_PRIQ:
+ c = "PRIQ";
+ break;
+ case PKTSCHEDT_FAIRQ:
+ c = "FAIRQ";
+ break;
+ case PKTSCHEDT_TCQ:
+ c = "TCQ";
+ break;
+ case PKTSCHEDT_QFQ:
+ c = "QFQ";
+ break;
+ default:
+ c = "UNKNOWN";
+ break;
+ }
+
+ return (c);
+}
+
+static char *
+qid2str(unsigned int s)
+{
+ char *c;
+
+ switch (s) {
+ case 0:
+ c = "BE";
+ break;
+ case 1:
+ c = "BK_SYS";
+ break;
+ case 2:
+ c = "BK";
+ break;
+ case 3:
+ c = "RD";
+ break;
+ case 4:
+ c = "OAM";
+ break;
+ case 5:
+ c = "AV";
+ break;
+ case 6:
+ c = "RV";
+ break;
+ case 7:
+ c = "VI";
+ break;
+ case 8:
+ c = "VO";
+ break;
+ case 9:
+ c = "CTL";
+ break;
+ default:
+ c = "UNKNOWN";
+ break;
+ }
+
+ return (c);
+}
+
+static char *
+tcqslot2str(unsigned int s)
+{
+ char *c;
+
+ switch (s) {
+ case 0:
+ case 3:
+ case 4:
+ c = "0,3,4";
+ break;
+ case 1:
+ case 2:
+ c = "1,2";
+ break;
+ case 5:
+ case 6:
+ case 7:
+ c = "5-7";
+ break;
+ case 8:
+ case 9:
+ c = "8,9";
+ break;
+ default:
+ c = "?";
+ break;
+ }
+
+ return (c);
+}
+
+static char *
+qstate2str(unsigned int s)
+{
+ char *c;
+
+ switch (s) {
+ case QS_RUNNING:
+ c = "(RUNNING)";
+ break;
+ case QS_SUSPENDED:
+ c = "(SUSPENDED)";
+ break;
+ default:
+ c = "(UNKNOWN)";
+ break;
+ }
+
+ return (c);
+}
+
+#define R2S_BUFS 8
+#define RATESTR_MAX 16
+
+static char *
+rate2str(long double rate)
+{
+ char *buf;
+ static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */
+ static int idx = 0;
+ int i;
+ static const char unit[] = " KMG";
+
+ buf = r2sbuf[idx++];
+ if (idx == R2S_BUFS)
+ idx = 0;
+
+ for (i = 0; rate >= 1000 && i <= 3; i++)
+ rate /= 1000;
+
+ if ((int)(rate * 100) % 100)
+ snprintf(buf, RATESTR_MAX, "%.2Lf%cb", rate, unit[i]);
+ else
+ snprintf(buf, RATESTR_MAX, "%lld%cb", (int64_t)rate, unit[i]);
+
+ return (buf);
+}
+
+void
+rxpollstatpr(void)
+{
+ struct ifmibdata_supplemental ifmsupp;
+ size_t miblen = sizeof (ifmsupp);
+ struct itimerval timer_interval;
+ struct if_rxpoll_stats *sp;
+ sigset_t sigset, oldsigset;
+ unsigned int ifindex;
+ int name[6];
+
+ ifindex = if_nametoindex(interface);
+ if (ifindex == 0) {
+ fprintf(stderr, "Invalid interface name\n");
+ return;
+ }
+
+ bzero(&ifmsupp, sizeof (struct ifmibdata_supplemental));
+
+loop:
+ if (interval > 0) {
+ /* create a timer that fires repeatedly every interval seconds */
+ timer_interval.it_value.tv_sec = interval;
+ timer_interval.it_value.tv_usec = 0;
+ timer_interval.it_interval.tv_sec = interval;
+ timer_interval.it_interval.tv_usec = 0;
+ (void) signal(SIGALRM, catchalarm);
+ signalled = NO;
+ (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
+ }
+
+ /* Common OID prefix */
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_IFDATA;
+ name[4] = ifindex;
+ name[5] = IFDATA_SUPPLEMENTAL;
+ if (sysctl(name, 6, &ifmsupp, &miblen, NULL, 0) == -1)
+ err(1, "sysctl IFDATA_SUPPLEMENTAL");
+
+ sp = &ifmsupp.ifmd_rxpoll_stats;
+
+ printf("%-4s [ poll on requests: %15u errors: %27u ]\n",
+ interface, sp->ifi_poll_on_req, sp->ifi_poll_on_err);
+ printf(" [ poll off requests: %15u errors: %27u ]\n",
+ sp->ifi_poll_off_req, sp->ifi_poll_off_err);
+ printf(" [ polled packets: %18llu polled bytes: %21llu ]\n",
+ sp->ifi_poll_packets, sp->ifi_poll_bytes);
+ printf(" [ sampled packets avg/min/max: %12u / %12u / %12u ]\n",
+ sp->ifi_poll_packets_avg, sp->ifi_poll_packets_min,
+ sp->ifi_poll_packets_max);
+ printf(" [ sampled bytes avg/min/max: %12u / %12u / %12u ]\n",
+ sp->ifi_poll_bytes_avg, sp->ifi_poll_bytes_min,
+ sp->ifi_poll_bytes_max);
+ printf(" [ sampled wakeups avg: %12u ]\n",
+ sp->ifi_poll_wakeups_avg);
+ printf(" [ packets lowat/hiwat threshold: %10u / %10u ]\n",
+ sp->ifi_poll_packets_lowat, sp->ifi_poll_packets_hiwat);
+ printf(" [ bytes lowat/hiwat threshold: %10u / %10u ]\n",
+ sp->ifi_poll_bytes_lowat, sp->ifi_poll_bytes_hiwat);
+ printf(" [ wakeups lowat/hiwat threshold: %10u / %10u ]\n",
+ sp->ifi_poll_wakeups_lowat, sp->ifi_poll_wakeups_hiwat);
+
+ fflush(stdout);
+
+ if (interval > 0) {
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGALRM);
+ (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
+ if (!signalled) {
+ sigemptyset(&sigset);
+ sigsuspend(&sigset);
+ }
+ (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
+
+ signalled = NO;
+ goto loop;
+ }
+}
/*
- * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
return &s;
}
-#endif SRVCACHE
+#endif /* SRVCACHE */
/*
* Print a summary of connections related to an Internet
* Listening processes (aflag) are suppressed unless the
* -a (all) flag is specified.
*/
-#if !TARGET_OS_EMBEDDED
struct xgen_n {
u_int32_t xgn_len; /* length of this structure */
printf(
"Current listen queue sizes (qlen/incqlen/maxqlen)");
putchar('\n');
- if (Aflag)
+ if (Aflag) {
#if !TARGET_OS_EMBEDDED
printf("%-16.16s ", "Socket");
#else
- printf("%-8.8s ", "Socket");
+ printf("%-8.8s ", "Socket");
#endif
+ printf("%-9.9s", "Flowhash");
+ }
if (Lflag)
printf("%-14.14s %-22.22s\n",
"Listen", "Local Address");
#else
printf("%8lx ", (u_long)so->so_pcb);
#endif
+ printf("%8x ", inp->inp_flowhash);
}
if (Lflag) {
char buf[15];
free(buf);
}
-#else /* TARGET_OS_EMBEDDED */
-
-void
-protopr(uint32_t proto, /* for sysctl version we pass proto # */
- char *name, int af)
-{
- int istcp;
- static int first = 1;
- char *buf;
- const char *mibvar;
- struct xinpgen *xig, *oxig;
- struct tcpcb *tp = NULL;
- struct inpcb *inp;
- struct xsocket *so;
- size_t len;
-
- istcp = 0;
- switch (proto) {
- case IPPROTO_TCP:
-#ifdef INET6
- if (tcp_done != 0)
- return;
- else
- tcp_done = 1;
-#endif
- istcp = 1;
- mibvar = "net.inet.tcp.pcblist";
- break;
- case IPPROTO_UDP:
-#ifdef INET6
- if (udp_done != 0)
- return;
- else
- udp_done = 1;
-#endif
- mibvar = "net.inet.udp.pcblist";
- break;
- case IPPROTO_DIVERT:
- mibvar = "net.inet.divert.pcblist";
- break;
- default:
- mibvar = "net.inet.raw.pcblist";
- break;
- }
- len = 0;
- if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
- if (errno != ENOENT)
- warn("sysctl: %s", mibvar);
- return;
- }
- if ((buf = malloc(len)) == 0) {
- warn("malloc %lu bytes", (u_long)len);
- return;
- }
- if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
- warn("sysctl: %s", mibvar);
- free(buf);
- return;
- }
-
- /*
- * Bail-out to avoid logic error in the loop below when
- * there is in fact no more control block to process
- */
- if (len <= sizeof(struct xinpgen)) {
- free(buf);
- return;
- }
-
- oxig = xig = (struct xinpgen *)buf;
- for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
- xig->xig_len > sizeof(struct xinpgen);
- xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
- if (istcp) {
- tp = &((struct xtcpcb *)xig)->xt_tp;
- inp = &((struct xtcpcb *)xig)->xt_inp;
- so = &((struct xtcpcb *)xig)->xt_socket;
- } else {
- inp = &((struct xinpcb *)xig)->xi_inp;
- so = &((struct xinpcb *)xig)->xi_socket;
- }
-
- /* Ignore sockets for protocols other than the desired one. */
- if (so->xso_protocol != (int)proto)
- continue;
-
- /* Ignore PCBs which were freed during copyout. */
- if (inp->inp_gencnt > oxig->xig_gen)
- continue;
-
- if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
-#ifdef INET6
- || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
-#endif /* INET6 */
- || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
-#ifdef INET6
- && (inp->inp_vflag &
- INP_IPV6) == 0
-#endif /* INET6 */
- ))
- )
- continue;
-
- /*
- * Local address is not an indication of listening socket or
- * server sockey but just rather the socket has been bound.
- * That why many UDP sockets were not displayed in the original code.
- */
- if (!aflag && istcp && tp->t_state <= TCPS_LISTEN)
- continue;
-
- if (Lflag && !so->so_qlimit)
- continue;
-
- if (first) {
- if (!Lflag) {
- printf("Active Internet connections");
- if (aflag)
- printf(" (including servers)");
- } else
- printf(
- "Current listen queue sizes (qlen/incqlen/maxqlen)");
- putchar('\n');
- if (Aflag)
- printf("%-8.8s ", "Socket");
- if (Lflag)
- printf("%-14.14s %-22.22s\n",
- "Listen", "Local Address");
- else
- printf((Aflag && !Wflag) ?
- "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
- "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
- "Proto", "Recv-Q", "Send-Q",
- "Local Address", "Foreign Address",
- "(state)");
- first = 0;
- }
- if (Aflag) {
- if (istcp)
- printf("%8lx ", (u_long)inp->inp_ppcb);
- else
- printf("%8lx ", (u_long)so->so_pcb);
- }
- if (Lflag) {
- char buf[15];
-
- snprintf(buf, 15, "%d/%d/%d", so->so_qlen,
- so->so_incqlen, so->so_qlimit);
- printf("%-14.14s ", buf);
- }
- else {
- const char *vchar;
-
-#ifdef INET6
- if ((inp->inp_vflag & INP_IPV6) != 0)
- vchar = ((inp->inp_vflag & INP_IPV4) != 0)
- ? "46" : "6 ";
- else
-#endif
- vchar = ((inp->inp_vflag & INP_IPV4) != 0)
- ? "4 " : " ";
-
- printf("%-3.3s%-2.2s %6u %6u ", name, vchar,
- so->so_rcv.sb_cc,
- so->so_snd.sb_cc);
- }
- if (nflag) {
- if (inp->inp_vflag & INP_IPV4) {
- inetprint(&inp->inp_laddr, (int)inp->inp_lport,
- name, 1);
- if (!Lflag)
- inetprint(&inp->inp_faddr,
- (int)inp->inp_fport, name, 1);
- }
-#ifdef INET6
- else if (inp->inp_vflag & INP_IPV6) {
- inet6print(&inp->in6p_laddr,
- (int)inp->inp_lport, name, 1);
- if (!Lflag)
- inet6print(&inp->in6p_faddr,
- (int)inp->inp_fport, name, 1);
- } /* else nothing printed now */
-#endif /* INET6 */
- } else if (inp->inp_flags & INP_ANONPORT) {
- if (inp->inp_vflag & INP_IPV4) {
- inetprint(&inp->inp_laddr, (int)inp->inp_lport,
- name, 1);
- if (!Lflag)
- inetprint(&inp->inp_faddr,
- (int)inp->inp_fport, name, 0);
- }
-#ifdef INET6
- else if (inp->inp_vflag & INP_IPV6) {
- inet6print(&inp->in6p_laddr,
- (int)inp->inp_lport, name, 1);
- if (!Lflag)
- inet6print(&inp->in6p_faddr,
- (int)inp->inp_fport, name, 0);
- } /* else nothing printed now */
-#endif /* INET6 */
- } else {
- if (inp->inp_vflag & INP_IPV4) {
- inetprint(&inp->inp_laddr, (int)inp->inp_lport,
- name, 0);
- if (!Lflag)
- inetprint(&inp->inp_faddr,
- (int)inp->inp_fport, name,
- inp->inp_lport !=
- inp->inp_fport);
- }
-#ifdef INET6
- else if (inp->inp_vflag & INP_IPV6) {
- inet6print(&inp->in6p_laddr,
- (int)inp->inp_lport, name, 0);
- if (!Lflag)
- inet6print(&inp->in6p_faddr,
- (int)inp->inp_fport, name,
- inp->inp_lport !=
- inp->inp_fport);
- } /* else nothing printed now */
-#endif /* INET6 */
- }
- if (istcp && !Lflag) {
- if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
- printf("%d", tp->t_state);
- else {
- printf("%s", tcpstates[tp->t_state]);
-#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
- /* Show T/TCP `hidden state' */
- if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
- putchar('*');
-#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
- }
- }
- putchar('\n');
- }
- if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
- if (oxig->xig_count > xig->xig_count) {
- printf("Some %s sockets may have been deleted.\n",
- name);
- } else if (oxig->xig_count < xig->xig_count) {
- printf("Some %s sockets may have been created.\n",
- name);
- } else {
- printf("Some %s sockets may have been created or deleted",
- name);
- }
- }
- free(buf);
-}
-#endif /* TARGET_OS_EMBEDDED */
-
/*
* Dump TCP statistics structure.
*/
p(tcps_sndprobe, "\t\t%u window probe packet%s\n");
p(tcps_sndwinup, "\t\t%u window update packet%s\n");
p(tcps_sndctrl, "\t\t%u control packet%s\n");
+ p(tcps_fcholdpacket, "\t\t%u data packet%s sent after flow control\n");
p(tcps_rcvtotal, "\t%u packet%s received\n");
p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %u byte%s)\n");
p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n");
/*
- * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
int Aflag; /* show addresses of protocol control block */
int aflag; /* show all sockets (including servers) */
int bflag; /* show i/f total bytes in/out */
+int cflag; /* show specific classq */
int dflag; /* show i/f dropped packets */
#if defined(__APPLE__)
int gflag; /* show group (multicast) routing or stats */
int tflag; /* show i/f watchdog timers */
int vflag; /* more verbose */
int Wflag; /* wide display */
+int qflag; /* classq stats display */
+int Qflag; /* opportunistic polling stats display */
+int xflag; /* show extended link-layer reachability information */
+int cq = -1; /* send classq index (-1 for all) */
int interval; /* repeat interval for i/f stats */
char *interface; /* desired i/f for stats, or NULL for all i/fs */
af = AF_UNSPEC;
- while ((ch = getopt(argc, argv, "Aabdf:gI:iLlmnP:p:rRstuvWw:")) != -1)
+ while ((ch = getopt(argc, argv, "Aabc:df:gI:iLlmnP:p:qQrRstuvWw:x")) != -1)
switch(ch) {
case 'A':
Aflag = 1;
case 'b':
bflag = 1;
break;
+ case 'c':
+ cflag = 1;
+ cq = atoi(optarg);
+ break;
case 'd':
dflag = 1;
break;
}
pflag = 1;
break;
+ case 'q':
+ qflag++;
+ break;
+ case 'Q':
+ Qflag++;
+ break;
case 'R':
Rflag = 1;
break;
interval = atoi(optarg);
iflag = 1;
break;
+ case 'x':
+ xflag = 1;
+ Rflag = 1;
+ break;
case '?':
default:
usage();
mbpr();
exit(0);
}
- if (iflag && !sflag && !gflag) {
+ if (iflag && !sflag && !gflag && !qflag && !Qflag) {
if (Rflag)
intpr_ri(NULL);
else
routepr(nl[N_RTREE].n_value);
exit(0);
}
+ if (qflag || Qflag) {
+ if (interface == NULL) {
+ fprintf(stderr, "%s statistics option "
+ "requires interface name\n", qflag ? "Queue" :
+ "Polling");
+ } else if (qflag) {
+ aqstatpr();
+ } else {
+ rxpollstatpr();
+ }
+ exit(0);
+ }
+
#if defined(__APPLE__)
if (gflag) {
#if !TARGET_OS_EMBEDDED
+.\" Copyright (c) 2012 Apple Inc. All rights reserved.
+.\"
+.\" @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+.\"
+.\" This file contains Original Code and/or Modifications of Original Code
+.\" as defined in and that are subject to the Apple Public Source License
+.\" Version 2.0 (the 'License'). You may not use this file except in
+.\" compliance with the License. The rights granted to you under the License
+.\" may not be used to create, or enable the creation or redistribution of,
+.\" unlawful or unlicensed copies of an Apple operating system, or to
+.\" circumvent, violate, or enable the circumvention or violation of, any
+.\" terms of an Apple operating system software license agreement.
+.\"
+.\" Please obtain a copy of the License at
+.\" http://www.opensource.apple.com/apsl/ and read it before using this file.
+.\"
+.\" The Original Code and all software distributed under the License are
+.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+.\" Please see the License for the specific language governing rights and
+.\" limitations under the License.
+.\"
+.\" @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+.\"
.\" Copyright (c) 1983, 1990, 1992, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.Nm
.Fl i | I Ar interface
.Op Fl w Ar wait
-.Op Fl abdgRt
+.Op Fl c Ar queue
+.Op Fl abdgqRt
.Nm
.Fl s Op Fl s
.Op Fl f Ar address_family | Fl p Ar protocol
.Bl -tag -width flag
.It Fl A
With the default display, show the address of any protocol control blocks associated with
-sockets; used for debugging.
+sockets and the flow hash; used for debugging.
.It Fl a
With the default display, show the state of all sockets; normally sockets used by server
processes are not shown. With the routing table display (option
With the interface display (option
.Fl i ,
as described below), show the number of bytes in and out.
+.It Fl c Ar queue
+With the queue statistics (option
+.Fl q ,
+as described below), show only those for the specified
+.Ar queue .
.It Fl d
With either interface display (option
.Fl i
no interesting numbers to report. The program will complain if
.Ar protocol
is unknown or if there is no statistics routine for it.
+.It Fl q
+Show network interface send queue statistics. By default all queues are displayed, unless
+specified with
+.Fl c .
+This option requires specifying an interface with
+.Fl I
+option. More detailed information about the queues, which includes their queueing algorithm related statistics, can be obtained by using
+.Fl qq
+or
+.Fl q
+.Fl q
+option.
.It Fl r
Show the routing tables. Use with
.Fl a
Show network interface or protocol statistics at intervals of
.Ar wait
seconds.
+.It Fl x
+Show extended link-layer reachability information in addition to that shown by
+the
+.Fl R
+flag.
.El
.Pp
.\"-------------------------------------------------------------------------------
M RTF_MODIFIED Modified dynamically (by redirect)
m RTF_MULTICAST The route represents a multicast address
R RTF_REJECT Host or net unreachable
+r RTF_ROUTER Host is a default router
S RTF_STATIC Manually added
U RTF_UP Route usable
W RTF_WASCLONED Route was generated as a result of cloning
X RTF_XRESOLVE External daemon translates proto to link address
+Y RTF_PROXY Proxying; cloned routes will not be scoped
.El
.Pp
Direct routes are created for each interface attached to the local host;
provides a count of the number of packets sent using that route. The
interface entry indicates the network interface utilized for the route.
A route which is marked with the RTF_IFSCOPE flag is instantiated for
-the corresponding interface.
+the corresponding interface. A cloning route which is marked with the
+RTF_PROXY flag will not generate new routes that are associated
+with its interface scope.
.Pp
When
.Nm netstat
/*
- * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
extern int Aflag; /* show addresses of protocol control block */
extern int aflag; /* show all sockets (including servers) */
extern int bflag; /* show i/f total bytes in/out */
+extern int cflag; /* show specific classq */
extern int dflag; /* show i/f dropped packets */
#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
extern int gflag; /* show group (multicast) routing or stats */
extern int tflag; /* show i/f watchdog timers */
extern int vflag; /* more verbose */
extern int Wflag; /* wide display */
+extern int qflag; /* Display ifclassq stats */
+extern int Qflag; /* Display opportunistic polling stats */
+extern int xflag; /* show extended link-layer reachability information */
+extern int cq; /* send classq index (-1 for all) */
extern int interval; /* repeat interval for i/f stats */
extern char *interface; /* desired i/f for stats, or NULL for all i/fs */
extern void routepr(uint32_t);
extern void unixpr(void);
+extern void aqstatpr(void);
+extern void rxpollstatpr(void);
#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
extern void mroutepr(void);
/*
- * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
{ RTF_BLACKHOLE,'B' },
{ RTF_BROADCAST,'b' },
{ RTF_IFSCOPE, 'I' },
-#ifdef RTF_IFREF
{ RTF_IFREF, 'i' },
-#endif /* RTF_IFREF */
+ { RTF_PROXY, 'Y' },
+ { RTF_ROUTER, 'r' },
{ 0 }
};
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+ <dict>
+ <key>OpenSourceProject</key>
+ <string>mtest</string>
+ <key>OpenSourceVersion</key>
+ <string>1.11</string>
+ <key>OpenSourceWebsiteURL</key>
+ <string>http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/</string>
+ <key>OpenSourceURL</key>
+ <string>http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/usr.sbin/mtest/mtest.c?rev=1.11;content-type=text%2Fplain</string>
+ <key>OpenSourceSHA1</key>
+ <string></string>
+ <key>OpenSourceMD5</key>
+ <string></string>
+ <key>OpenSourceImportDate</key>
+ <string>2011-01-13</string>
+ <key>OpenSourceLicense</key>
+ <string>Other</string>
+ <key>OpenSourceLicenseFile</key>
+ <string>network_cmds.txt</string>
+ </dict>
+</array>
+</plist>
);
dependencies = (
034E4464100BDCA3009CA3DC /* PBXTargetDependency */,
- 03B2DBD1100BE626005349BC /* PBXTargetDependency */,
+ 72179EAE146233390098FB3E /* PBXTargetDependency */,
034E4469100BDD00009CA3DC /* PBXTargetDependency */,
- 03B2DBC5100BE332005349BC /* PBXTargetDependency */,
+ 565825AF13392239003E5FA5 /* PBXTargetDependency */,
690D97BC12DE7151004323A7 /* PBXTargetDependency */,
+ 03B2DBD1100BE626005349BC /* PBXTargetDependency */,
034E4475100BDEC6009CA3DC /* PBXTargetDependency */,
034E447B100BDF0D009CA3DC /* PBXTargetDependency */,
03B2DBD3100BE645005349BC /* PBXTargetDependency */,
+ 18515B85133D1DBF000148A4 /* PBXTargetDependency */,
034E447F100BDF54009CA3DC /* PBXTargetDependency */,
03B2DBDB100BE6D2005349BC /* PBXTargetDependency */,
034E4485100BE15F009CA3DC /* PBXTargetDependency */,
buildPhases = (
);
dependencies = (
- 4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */,
- 726121470EE8717B00AFED1B /* PBXTargetDependency */,
726121490EE8717B00AFED1B /* PBXTargetDependency */,
+ 723C7074142BB003007C87E9 /* PBXTargetDependency */,
7261217D0EE8896800AFED1B /* PBXTargetDependency */,
- 726121B30EE88B7900AFED1B /* PBXTargetDependency */,
- 724DAB790EE88EA6008900D0 /* PBXTargetDependency */,
+ 4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */,
724DAB9A0EE88F5D008900D0 /* PBXTargetDependency */,
+ 724DAB790EE88EA6008900D0 /* PBXTargetDependency */,
724DABC30EE890A6008900D0 /* PBXTargetDependency */,
+ 565825AD13392232003E5FA5 /* PBXTargetDependency */,
690D97BE12DE7166004323A7 /* PBXTargetDependency */,
724DABEC0EE891DF008900D0 /* PBXTargetDependency */,
724DAC240EE89525008900D0 /* PBXTargetDependency */,
dependencies = (
72ABD0A41083D818008C721C /* PBXTargetDependency */,
72ABD0881083D750008C721C /* PBXTargetDependency */,
- 72ABD08A1083D753008C721C /* PBXTargetDependency */,
690D97BA12DE7130004323A7 /* PBXTargetDependency */,
+ 565825B113392242003E5FA5 /* PBXTargetDependency */,
72ABD08C1083D75D008C721C /* PBXTargetDependency */,
72ABD08E1083D75F008C721C /* PBXTargetDependency */,
72ABD0901083D762008C721C /* PBXTargetDependency */,
name = "All-EmbeddedOther";
productName = "All-EmbeddedOther";
};
+ 72C77D3A1484199C002D2577 /* network_cmds_libs */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 72C77D671484199C002D2577 /* Build configuration list for PBXAggregateTarget "network_cmds_libs" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 72C77D3B1484199C002D2577 /* PBXTargetDependency */,
+ );
+ name = network_cmds_libs;
+ productName = "network_cmds (Aggregate)";
+ };
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
03EB2F9A120A1DDA0007C1A0 /* ip6addrctl.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4D2B04E41208C12F0004A3F3 /* ip6addrctl.8 */; };
+ 03EB2F9D120A1E690007C1A0 /* ip6addrctl.conf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4D2B04E61208C12F0004A3F3 /* ip6addrctl.conf */; };
4D2B04F81208C21B0004A3F3 /* ip6addrctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2B04E51208C12F0004A3F3 /* ip6addrctl.c */; };
+ 565825A4133921A3003E5FA5 /* mnc_error.c in Sources */ = {isa = PBXBuildFile; fileRef = 565825961339217B003E5FA5 /* mnc_error.c */; };
+ 565825A5133921A3003E5FA5 /* mnc_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 565825971339217B003E5FA5 /* mnc_main.c */; };
+ 565825A6133921A3003E5FA5 /* mnc_multicast.c in Sources */ = {isa = PBXBuildFile; fileRef = 565825981339217B003E5FA5 /* mnc_multicast.c */; };
+ 565825A7133921A3003E5FA5 /* mnc_opts.c in Sources */ = {isa = PBXBuildFile; fileRef = 565825991339217B003E5FA5 /* mnc_opts.c */; };
+ 565825A9133921CF003E5FA5 /* mnc.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 565825941339217B003E5FA5 /* mnc.1 */; };
690D97A612DE6F96004323A7 /* mtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 690D979412DE6E6B004323A7 /* mtest.c */; };
690D97AE12DE70AE004323A7 /* mtest.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 690D979512DE6E76004323A7 /* mtest.8 */; };
- 69C10A7812DF808700BCDF4C /* mtest.plist in Install OSS Plist */ = {isa = PBXBuildFile; fileRef = 69C10A7712DF7F2700BCDF4C /* mtest.plist */; };
7216D24C0EE896F300AE70E4 /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = 7261208B0EE86F4800AFED1B /* data.c */; };
7216D24D0EE896F300AE70E4 /* if.c in Sources */ = {isa = PBXBuildFile; fileRef = 7261208D0EE86F4800AFED1B /* if.c */; };
7216D24E0EE896F300AE70E4 /* inet.c in Sources */ = {isa = PBXBuildFile; fileRef = 7261208E0EE86F4800AFED1B /* inet.c */; };
7216D3700EE8A05B00AE70E4 /* rtsol.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120D70EE86F9100AFED1B /* rtsol.8 */; };
7216D3AB0EE8A3C400AE70E4 /* spray.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120E00EE86F9D00AFED1B /* spray.c */; };
7216D3AF0EE8A3D800AE70E4 /* spray.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120DF0EE86F9D00AFED1B /* spray.8 */; };
+ 724753E7144905E300F6A941 /* dnctl.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 724753E61448E1EF00F6A941 /* dnctl.8 */; };
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 */; };
7261215C0EE8883900AFED1B /* ifmedia.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120590EE86F0900AFED1B /* ifmedia.c */; };
7261215D0EE8883900AFED1B /* ifvlan.c in Sources */ = {isa = PBXBuildFile; fileRef = 7261205A0EE86F0900AFED1B /* ifvlan.c */; };
726121610EE8885400AFED1B /* ifconfig.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120560EE86F0900AFED1B /* ifconfig.8 */; };
- 726121890EE889C100AFED1B /* ip6tool.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120630EE86F1A00AFED1B /* ip6tool.c */; };
- 7261219A0EE88AB500AFED1B /* ip6.8 in Copy Files man */ = {isa = PBXBuildFile; fileRef = 726120600EE86F1A00AFED1B /* ip6.8 */; };
- 7261219B0EE88AB500AFED1B /* ip6config.8 in Copy Files man */ = {isa = PBXBuildFile; fileRef = 726120620EE86F1A00AFED1B /* ip6config.8 */; };
- 7261219F0EE88ADD00AFED1B /* 6to4.conf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7261205F0EE86F1A00AFED1B /* 6to4.conf */; };
- 726121AA0EE88B2700AFED1B /* ip6config in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120610EE86F1A00AFED1B /* ip6config */; };
7263A9630EEE31C800164D5D /* libipsec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 72CD1DB50EE8C619005F825D /* libipsec.dylib */; };
7294F0DF0EE8BA730052EC88 /* spray.x in Sources */ = {isa = PBXBuildFile; fileRef = 726120E10EE86F9D00AFED1B /* spray.x */; };
7294F1000EE8BB990052EC88 /* as.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120E50EE86FA700AFED1B /* as.c */; };
7294F12E0EE8BD2F0052EC88 /* traceroute6.c in Sources */ = {isa = PBXBuildFile; fileRef = 726120FB0EE86FB500AFED1B /* traceroute6.c */; };
7294F1320EE8BD430052EC88 /* traceroute6.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 726120FA0EE86FB500AFED1B /* traceroute6.8 */; };
72B894EC0EEDB17C00C218D6 /* libipsec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 72CD1DB50EE8C619005F825D /* libipsec.dylib */; };
+ 72D000C4142BB11100151981 /* dnctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D000C3142BB11100151981 /* dnctl.c */; };
+ 72E42BA314B7CF3D003AAE28 /* network_cmds.plist in Install OSS Plist */ = {isa = PBXBuildFile; fileRef = 72E42BA214B7CF37003AAE28 /* network_cmds.plist */; };
72E650A7107BF2F000AAF325 /* af_inet.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E650A2107BF2F000AAF325 /* af_inet.c */; };
72E650A8107BF2F000AAF325 /* af_inet6.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E650A3107BF2F000AAF325 /* af_inet6.c */; };
72E650A9107BF2F000AAF325 /* af_link.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E650A4107BF2F000AAF325 /* af_link.c */; };
72E650AA107BF2F000AAF325 /* ifbridge.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E650A5107BF2F000AAF325 /* ifbridge.c */; };
72E650AB107BF2F000AAF325 /* ifclone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E650A6107BF2F000AAF325 /* ifclone.c */; };
+ E01AB0901368880F008C66FF /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E01AB08F1368880F008C66FF /* libutil.dylib */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
remoteGlobalIDString = 7294F0F80EE8BB460052EC88;
remoteInfo = traceroute;
};
- 03B2DBC4100BE332005349BC /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 726121820EE8897C00AFED1B;
- remoteInfo = ip6conf;
- };
03B2DBD0100BE626005349BC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
remoteGlobalIDString = 7294F1290EE8BD280052EC88;
remoteInfo = traceroute6;
};
+ 18515B84133D1DBF000148A4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7216D3130EE89E9E00AE70E4;
+ remoteInfo = rtadvd;
+ };
4D2B05131208C6BB0004A3F3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
remoteGlobalIDString = 4D2B04F21208C2040004A3F3;
remoteInfo = ip6addrctl;
};
+ 565825AC13392232003E5FA5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 5658259E1339218F003E5FA5;
+ remoteInfo = mnc;
+ };
+ 565825AE13392239003E5FA5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 5658259E1339218F003E5FA5;
+ remoteInfo = mnc;
+ };
+ 565825B013392242003E5FA5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 5658259E1339218F003E5FA5;
+ remoteInfo = mnc;
+ };
690D97B912DE7130004323A7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
remoteGlobalIDString = 7216D3580EE8A02200AE70E4;
remoteInfo = rtsol;
};
+ 72179EAD146233390098FB3E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 723C7067142BAFEA007C87E9;
+ remoteInfo = dnctl;
+ };
+ 723C7073142BB003007C87E9 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 723C7067142BAFEA007C87E9;
+ remoteInfo = dnctl;
+ };
724DAB780EE88EA6008900D0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
remoteGlobalIDString = 724DAC0C0EE8940D008900D0;
remoteInfo = ndp;
};
- 726121460EE8717B00AFED1B /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 7261210B0EE8707500AFED1B;
- remoteInfo = alias;
- };
726121480EE8717B00AFED1B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
remoteGlobalIDString = 726121530EE8881700AFED1B;
remoteInfo = ifconfig;
};
- 726121B20EE88B7900AFED1B /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 726121820EE8897C00AFED1B;
- remoteInfo = ip6conf;
- };
7294F0E90EE8BAC80052EC88 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
remoteGlobalIDString = 726121530EE8881700AFED1B;
remoteInfo = ifconfig;
};
- 72ABD0891083D753008C721C /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 726121820EE8897C00AFED1B;
- remoteInfo = ip6conf;
- };
72ABD08B1083D75D008C721C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
remoteGlobalIDString = 7261212C0EE8710B00AFED1B;
remoteInfo = arp;
};
+ 72C77D3C1484199C002D2577 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7261210B0EE8707500AFED1B;
+ remoteInfo = alias;
+ };
72CD1D9B0EE8C47C005F825D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 724862310EE86EB7001D0DE9 /* Project object */;
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
+ 03EB2FB6120A1E740007C1A0 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /private/etc;
+ dstSubfolderSpec = 0;
+ files = (
+ 03EB2F9D120A1E690007C1A0 /* ip6addrctl.conf in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
4D2B05221208CB410004A3F3 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
- dstPath = /usr/local/share/man/man8;
+ dstPath = /usr/share/man/man8;
dstSubfolderSpec = 0;
files = (
03EB2F9A120A1DDA0007C1A0 /* ip6addrctl.8 in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
+ 565825AA133921ED003E5FA5 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/local/share/man/man1;
+ dstSubfolderSpec = 0;
+ files = (
+ 565825A9133921CF003E5FA5 /* mnc.1 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
690D97AD12DE7074004323A7 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/local/OpenSourceVersions/;
dstSubfolderSpec = 0;
files = (
- 69C10A7812DF808700BCDF4C /* mtest.plist in Install OSS Plist */,
+ 72E42BA314B7CF3D003AAE28 /* network_cmds.plist in Install OSS Plist */,
);
name = "Install OSS Plist";
runOnlyForDeploymentPostprocessing = 1;
);
runOnlyForDeploymentPostprocessing = 1;
};
+ 723C7066142BAFEA007C87E9 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/local/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 724753E7144905E300F6A941 /* dnctl.8 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
724DAB760EE88E9C008900D0 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
);
runOnlyForDeploymentPostprocessing = 1;
};
- 726121A50EE88AF300AFED1B /* Copy Files man */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 8;
- dstPath = /usr/share/man/man8;
- dstSubfolderSpec = 0;
- files = (
- 7261219A0EE88AB500AFED1B /* ip6.8 in Copy Files man */,
- 7261219B0EE88AB500AFED1B /* ip6config.8 in Copy Files man */,
- );
- name = "Copy Files man";
- runOnlyForDeploymentPostprocessing = 1;
- };
- 726121A60EE88AF300AFED1B /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 8;
- dstPath = /private/etc;
- dstSubfolderSpec = 0;
- files = (
- 7261219F0EE88ADD00AFED1B /* 6to4.conf in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 1;
- };
- 726121AE0EE88B4200AFED1B /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 8;
- dstPath = /usr/sbin;
- dstSubfolderSpec = 0;
- files = (
- 726121AA0EE88B2700AFED1B /* ip6config in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 1;
- };
7294F11A0EE8BC0C0052EC88 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
4D2B04E51208C12F0004A3F3 /* ip6addrctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ip6addrctl.c; sourceTree = "<group>"; };
4D2B04E61208C12F0004A3F3 /* ip6addrctl.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6addrctl.conf; sourceTree = "<group>"; };
4D2B04F31208C2040004A3F3 /* ip6addrctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ip6addrctl; sourceTree = BUILT_PRODUCTS_DIR; };
+ 565825941339217B003E5FA5 /* mnc.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = mnc.1; sourceTree = "<group>"; };
+ 565825951339217B003E5FA5 /* LICENCE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENCE; sourceTree = "<group>"; };
+ 565825961339217B003E5FA5 /* mnc_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_error.c; sourceTree = "<group>"; };
+ 565825971339217B003E5FA5 /* mnc_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_main.c; sourceTree = "<group>"; };
+ 565825981339217B003E5FA5 /* mnc_multicast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_multicast.c; sourceTree = "<group>"; };
+ 565825991339217B003E5FA5 /* mnc_opts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_opts.c; sourceTree = "<group>"; };
+ 5658259A1339217B003E5FA5 /* mnc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mnc.h; sourceTree = "<group>"; };
+ 5658259B1339217B003E5FA5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
+ 5658259F1339218F003E5FA5 /* mnc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mnc; sourceTree = BUILT_PRODUCTS_DIR; };
690D978112DE6034004323A7 /* mtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mtest; sourceTree = BUILT_PRODUCTS_DIR; };
690D979412DE6E6B004323A7 /* mtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mtest.c; sourceTree = "<group>"; };
690D979512DE6E76004323A7 /* mtest.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mtest.8; sourceTree = "<group>"; };
- 69C10A7712DF7F2700BCDF4C /* mtest.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = mtest.plist; sourceTree = "<group>"; };
69C10A7912DF80F200BCDF4C /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
7216D2460EE896C000AE70E4 /* netstat */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = netstat; sourceTree = BUILT_PRODUCTS_DIR; };
7216D27C0EE8980A00AE70E4 /* ping */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ping; sourceTree = BUILT_PRODUCTS_DIR; };
7216D3140EE89E9E00AE70E4 /* rtadvd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rtadvd; sourceTree = BUILT_PRODUCTS_DIR; };
7216D3590EE8A02200AE70E4 /* rtsol */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rtsol; sourceTree = BUILT_PRODUCTS_DIR; };
7216D3A70EE8A3BB00AE70E4 /* spray */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = spray; sourceTree = BUILT_PRODUCTS_DIR; };
+ 723C7068142BAFEA007C87E9 /* dnctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnctl; sourceTree = BUILT_PRODUCTS_DIR; };
+ 724753E61448E1EF00F6A941 /* dnctl.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = dnctl.8; 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; };
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>"; };
- 7261205F0EE86F1A00AFED1B /* 6to4.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 6to4.conf; sourceTree = "<group>"; };
- 726120600EE86F1A00AFED1B /* ip6.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6.8; sourceTree = "<group>"; };
- 726120610EE86F1A00AFED1B /* ip6config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = ip6config; sourceTree = "<group>"; };
- 726120620EE86F1A00AFED1B /* ip6config.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6config.8; sourceTree = "<group>"; };
- 726120630EE86F1A00AFED1B /* ip6tool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ip6tool.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>"; };
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; };
- 726121830EE8897C00AFED1B /* ip6 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ip6; sourceTree = BUILT_PRODUCTS_DIR; };
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; };
72CD1DB50EE8C619005F825D /* libipsec.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libipsec.dylib; path = /usr/lib/libipsec.dylib; sourceTree = "<absolute>"; };
+ 72D000C3142BB11100151981 /* dnctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dnctl.c; sourceTree = "<group>"; };
+ 72E42BA214B7CF37003AAE28 /* network_cmds.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = network_cmds.plist; sourceTree = "<group>"; };
72E650A2107BF2F000AAF325 /* af_inet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = af_inet.c; sourceTree = "<group>"; };
72E650A3107BF2F000AAF325 /* af_inet6.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = af_inet6.c; sourceTree = "<group>"; };
72E650A4107BF2F000AAF325 /* af_link.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = af_link.c; sourceTree = "<group>"; };
72E650A5107BF2F000AAF325 /* ifbridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifbridge.c; sourceTree = "<group>"; };
72E650A6107BF2F000AAF325 /* ifclone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifclone.c; sourceTree = "<group>"; };
+ E01AB08F1368880F008C66FF /* libutil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libutil.dylib; path = $SDKROOT/usr/lib/libutil.dylib; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 5658259D1339218F003E5FA5 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
690D977F12DE6034004323A7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ E01AB0901368880F008C66FF /* libutil.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 723C7065142BAFEA007C87E9 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
724DAB5D0EE88E2A008900D0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
- 726121810EE8897C00AFED1B /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
7294F0F70EE8BB460052EC88 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
path = ip6addrctl.tproj;
sourceTree = "<group>";
};
+ 56582591133920B5003E5FA5 /* mnc.tproj */ = {
+ isa = PBXGroup;
+ children = (
+ 565825941339217B003E5FA5 /* mnc.1 */,
+ 565825951339217B003E5FA5 /* LICENCE */,
+ 565825961339217B003E5FA5 /* mnc_error.c */,
+ 565825971339217B003E5FA5 /* mnc_main.c */,
+ 565825981339217B003E5FA5 /* mnc_multicast.c */,
+ 565825991339217B003E5FA5 /* mnc_opts.c */,
+ 5658259A1339217B003E5FA5 /* mnc.h */,
+ 5658259B1339217B003E5FA5 /* README */,
+ );
+ path = mnc.tproj;
+ sourceTree = "<group>";
+ };
690D973F12DE5A21004323A7 /* mtest.tproj */ = {
isa = PBXGroup;
children = (
690D979512DE6E76004323A7 /* mtest.8 */,
690D979412DE6E6B004323A7 /* mtest.c */,
- 69C10A7712DF7F2700BCDF4C /* mtest.plist */,
69C10A7912DF80F200BCDF4C /* COPYING */,
);
path = mtest.tproj;
sourceTree = "<group>";
};
+ 723C706A142BAFEA007C87E9 /* dnctl */ = {
+ isa = PBXGroup;
+ children = (
+ 724753E61448E1EF00F6A941 /* dnctl.8 */,
+ 72D000C3142BB11100151981 /* dnctl.c */,
+ );
+ path = dnctl;
+ sourceTree = "<group>";
+ };
7248622F0EE86EB7001D0DE9 = {
isa = PBXGroup;
children = (
- 690D973F12DE5A21004323A7 /* mtest.tproj */,
- 4D2B04E31208C12F0004A3F3 /* ip6addrctl.tproj */,
+ 72E42BA214B7CF37003AAE28 /* network_cmds.plist */,
+ E01AB08F1368880F008C66FF /* libutil.dylib */,
726120380EE86EEB00AFED1B /* alias */,
7261204C0EE86EF900AFED1B /* arp.tproj */,
+ 723C706A142BAFEA007C87E9 /* dnctl */,
726120540EE86F0900AFED1B /* ifconfig.tproj */,
- 7261205E0EE86F1A00AFED1B /* ip6conf.tproj */,
- 726120FE0EE8701100AFED1B /* ipfw.tproj */,
+ 4D2B04E31208C12F0004A3F3 /* ip6addrctl.tproj */,
726120670EE86F2300AFED1B /* ip6fw.tproj */,
+ 726120FE0EE8701100AFED1B /* ipfw.tproj */,
7261206D0EE86F2D00AFED1B /* kdumpd.tproj */,
+ 56582591133920B5003E5FA5 /* mnc.tproj */,
+ 690D973F12DE5A21004323A7 /* mtest.tproj */,
726120770EE86F3600AFED1B /* natd.tproj */,
726120830EE86F4000AFED1B /* ndp.tproj */,
7261208A0EE86F4800AFED1B /* netstat.tproj */,
path = ifconfig.tproj;
sourceTree = "<group>";
};
- 7261205E0EE86F1A00AFED1B /* ip6conf.tproj */ = {
- isa = PBXGroup;
- children = (
- 7261205F0EE86F1A00AFED1B /* 6to4.conf */,
- 726120600EE86F1A00AFED1B /* ip6.8 */,
- 726120610EE86F1A00AFED1B /* ip6config */,
- 726120620EE86F1A00AFED1B /* ip6config.8 */,
- 726120630EE86F1A00AFED1B /* ip6tool.c */,
- );
- path = ip6conf.tproj;
- sourceTree = "<group>";
- };
726120670EE86F2300AFED1B /* ip6fw.tproj */ = {
isa = PBXGroup;
children = (
7261210C0EE8707500AFED1B /* libalias.A.dylib */,
7261212D0EE8710B00AFED1B /* arp */,
726121540EE8881700AFED1B /* ifconfig */,
- 726121830EE8897C00AFED1B /* ip6 */,
724DAB5F0EE88E2A008900D0 /* ipfw */,
724DAB820EE88EFA008900D0 /* ip6fw */,
724DABA20EE88FE3008900D0 /* kdumpd */,
7294F12A0EE8BD280052EC88 /* traceroute6 */,
4D2B04F31208C2040004A3F3 /* ip6addrctl */,
690D978112DE6034004323A7 /* mtest */,
+ 5658259F1339218F003E5FA5 /* mnc */,
+ 723C7068142BAFEA007C87E9 /* dnctl */,
);
name = Products;
sourceTree = "<group>";
buildPhases = (
4D2B04F01208C2040004A3F3 /* Sources */,
4D2B05221208CB410004A3F3 /* CopyFiles */,
+ 03EB2FB6120A1E740007C1A0 /* CopyFiles */,
039D6A11120A2CF60006B8C8 /* ShellScript */,
);
buildRules = (
productReference = 4D2B04F31208C2040004A3F3 /* ip6addrctl */;
productType = "com.apple.product-type.tool";
};
+ 5658259E1339218F003E5FA5 /* mnc */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 565825AB133921ED003E5FA5 /* Build configuration list for PBXNativeTarget "mnc" */;
+ buildPhases = (
+ 5658259C1339218F003E5FA5 /* Sources */,
+ 5658259D1339218F003E5FA5 /* Frameworks */,
+ 565825AA133921ED003E5FA5 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = mnc;
+ productName = mnc;
+ productReference = 5658259F1339218F003E5FA5 /* mnc */;
+ productType = "com.apple.product-type.tool";
+ };
690D978012DE6034004323A7 /* mtest */ = {
isa = PBXNativeTarget;
buildConfigurationList = 690D978612DE6053004323A7 /* Build configuration list for PBXNativeTarget "mtest" */;
productReference = 7216D3A70EE8A3BB00AE70E4 /* spray */;
productType = "com.apple.product-type.tool";
};
+ 723C7067142BAFEA007C87E9 /* dnctl */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 723C706F142BAFEA007C87E9 /* Build configuration list for PBXNativeTarget "dnctl" */;
+ buildPhases = (
+ 723C7064142BAFEA007C87E9 /* Sources */,
+ 723C7065142BAFEA007C87E9 /* Frameworks */,
+ 723C7066142BAFEA007C87E9 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = dnctl;
+ productName = dnctl;
+ productReference = 723C7068142BAFEA007C87E9 /* dnctl */;
+ productType = "com.apple.product-type.tool";
+ };
724DAB5E0EE88E2A008900D0 /* ipfw */ = {
isa = PBXNativeTarget;
buildConfigurationList = 724DAB770EE88E9C008900D0 /* Build configuration list for PBXNativeTarget "ipfw" */;
productReference = 726121540EE8881700AFED1B /* ifconfig */;
productType = "com.apple.product-type.tool";
};
- 726121820EE8897C00AFED1B /* ip6conf */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 726121870EE8898B00AFED1B /* Build configuration list for PBXNativeTarget "ip6conf" */;
- buildPhases = (
- 726121800EE8897C00AFED1B /* Sources */,
- 726121810EE8897C00AFED1B /* Frameworks */,
- 726121A50EE88AF300AFED1B /* Copy Files man */,
- 726121A60EE88AF300AFED1B /* CopyFiles */,
- 726121AE0EE88B4200AFED1B /* CopyFiles */,
- 726121BB0EE88BB300AFED1B /* ShellScript */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = ip6conf;
- productName = ip6conf;
- productReference = 726121830EE8897C00AFED1B /* ip6 */;
- productType = "com.apple.product-type.tool";
- };
7294F0F80EE8BB460052EC88 /* traceroute */ = {
isa = PBXNativeTarget;
buildConfigurationList = 7294F0FD0EE8BB550052EC88 /* Build configuration list for PBXNativeTarget "traceroute" */;
726121430EE8717500AFED1B /* All */,
72570DA20EE8EBF3000F4CFB /* All-Embedded */,
72ABD0811083D742008C721C /* All-EmbeddedOther */,
+ 72C77D3A1484199C002D2577 /* network_cmds_libs */,
7261210B0EE8707500AFED1B /* alias */,
7261212C0EE8710B00AFED1B /* arp */,
+ 723C7067142BAFEA007C87E9 /* dnctl */,
726121530EE8881700AFED1B /* ifconfig */,
- 726121820EE8897C00AFED1B /* ip6conf */,
- 724DAB5E0EE88E2A008900D0 /* ipfw */,
+ 4D2B04F21208C2040004A3F3 /* ip6addrctl */,
724DAB810EE88EFA008900D0 /* ip6fw */,
+ 724DAB5E0EE88E2A008900D0 /* ipfw */,
724DABA10EE88FE3008900D0 /* kdumpd */,
+ 5658259E1339218F003E5FA5 /* mnc */,
+ 690D978012DE6034004323A7 /* mtest */,
724DABDA0EE8912D008900D0 /* natd */,
724DAC0C0EE8940D008900D0 /* ndp */,
7216D2450EE896C000AE70E4 /* netstat */,
7216D3A60EE8A3BA00AE70E4 /* spray */,
7294F0F80EE8BB460052EC88 /* traceroute */,
7294F1290EE8BD280052EC88 /* traceroute6 */,
- 4D2B04F21208C2040004A3F3 /* ip6addrctl */,
- 690D978012DE6034004323A7 /* mtest */,
);
};
/* End PBXProject section */
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
- shellScript = "/bin/chmod 0444 $DSTROOT/usr/local/share/man/man8/ip6addrctl.8\n";
+ shellScript = "/bin/chmod 0444 $DSTROOT/usr/share/man/man8/ip6addrctl.8\n/bin/chmod 0644 $DSTROOT/private/etc/ip6addrctl.conf";
};
690D97C212DE71CF004323A7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
);
name = "Install OSS License";
outputPaths = (
- "$(DERIVED_FILE_DIR)/mtest.txt",
+ "$(DERIVED_FILE_DIR)/network_cmds.txt",
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
- shellScript = "cp \"$SRCROOT/mtest.tproj/COPYING\" \"$DERIVED_FILE_DIR/mtest.txt\"\n\nmkdir -p \"$DSTROOT/usr/local/OpenSourceLicenses\"\ncp \"$DERIVED_FILE_DIR/mtest.txt\" \"$DSTROOT/usr/local/OpenSourceLicenses/\"\n\n";
+ shellScript = "cp \"$SRCROOT/mtest.tproj/COPYING\" \"$DERIVED_FILE_DIR/network_cmds.txt\"\n\nmkdir -p \"$DSTROOT/usr/local/OpenSourceLicenses\"\ncp \"$DERIVED_FILE_DIR/network_cmds.txt\" \"$DSTROOT/usr/local/OpenSourceLicenses/\"\n\n";
};
7216D25F0EE8970100AE70E4 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
shellPath = /bin/sh;
shellScript = "/bin/chmod 0444 $DSTROOT/usr/share/man/man8/ndp.8\t";
};
- 726121BB0EE88BB300AFED1B /* ShellScript */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 8;
- files = (
- );
- inputPaths = (
- );
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 1;
- shellPath = /bin/sh;
- shellScript = "/bin/chmod 0644 $DSTROOT/private/etc/6to4.conf\n/bin/chmod 0555 $DSTROOT/usr/sbin/ip6config\n/bin/chmod 0444 $DSTROOT/usr/share/man/man8/ip6.8\n/bin/chmod 0444 $DSTROOT/usr/share/man/man8/ip6config.8\n";
- };
7294F10C0EE8BBB60052EC88 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 5658259C1339218F003E5FA5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 565825A4133921A3003E5FA5 /* mnc_error.c in Sources */,
+ 565825A5133921A3003E5FA5 /* mnc_main.c in Sources */,
+ 565825A6133921A3003E5FA5 /* mnc_multicast.c in Sources */,
+ 565825A7133921A3003E5FA5 /* mnc_opts.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
690D977E12DE6034004323A7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 723C7064142BAFEA007C87E9 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72D000C4142BB11100151981 /* dnctl.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
724DAB5C0EE88E2A008900D0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
- 726121800EE8897C00AFED1B /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 726121890EE889C100AFED1B /* ip6tool.c in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
7294F0F60EE8BB460052EC88 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
target = 7294F0F80EE8BB460052EC88 /* traceroute */;
targetProxy = 034E4484100BE15F009CA3DC /* PBXContainerItemProxy */;
};
- 03B2DBC5100BE332005349BC /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 726121820EE8897C00AFED1B /* ip6conf */;
- targetProxy = 03B2DBC4100BE332005349BC /* PBXContainerItemProxy */;
- };
03B2DBD1100BE626005349BC /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 724DAC0C0EE8940D008900D0 /* ndp */;
target = 7294F1290EE8BD280052EC88 /* traceroute6 */;
targetProxy = 03B2DBDC100BE6D5005349BC /* PBXContainerItemProxy */;
};
+ 18515B85133D1DBF000148A4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7216D3130EE89E9E00AE70E4 /* rtadvd */;
+ targetProxy = 18515B84133D1DBF000148A4 /* PBXContainerItemProxy */;
+ };
4D2B05141208C6BB0004A3F3 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4D2B04F21208C2040004A3F3 /* ip6addrctl */;
targetProxy = 4D2B05131208C6BB0004A3F3 /* PBXContainerItemProxy */;
};
+ 565825AD13392232003E5FA5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 5658259E1339218F003E5FA5 /* mnc */;
+ targetProxy = 565825AC13392232003E5FA5 /* PBXContainerItemProxy */;
+ };
+ 565825AF13392239003E5FA5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 5658259E1339218F003E5FA5 /* mnc */;
+ targetProxy = 565825AE13392239003E5FA5 /* PBXContainerItemProxy */;
+ };
+ 565825B113392242003E5FA5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 5658259E1339218F003E5FA5 /* mnc */;
+ targetProxy = 565825B013392242003E5FA5 /* PBXContainerItemProxy */;
+ };
690D97BA12DE7130004323A7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 690D978012DE6034004323A7 /* mtest */;
target = 7216D3580EE8A02200AE70E4 /* rtsol */;
targetProxy = 7216D37E0EE8A0B300AE70E4 /* PBXContainerItemProxy */;
};
+ 72179EAE146233390098FB3E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 723C7067142BAFEA007C87E9 /* dnctl */;
+ targetProxy = 72179EAD146233390098FB3E /* PBXContainerItemProxy */;
+ };
+ 723C7074142BB003007C87E9 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 723C7067142BAFEA007C87E9 /* dnctl */;
+ targetProxy = 723C7073142BB003007C87E9 /* PBXContainerItemProxy */;
+ };
724DAB790EE88EA6008900D0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 724DAB5E0EE88E2A008900D0 /* ipfw */;
target = 724DAC0C0EE8940D008900D0 /* ndp */;
targetProxy = 724DAC230EE89525008900D0 /* PBXContainerItemProxy */;
};
- 726121470EE8717B00AFED1B /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 7261210B0EE8707500AFED1B /* alias */;
- targetProxy = 726121460EE8717B00AFED1B /* PBXContainerItemProxy */;
- };
726121490EE8717B00AFED1B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 7261212C0EE8710B00AFED1B /* arp */;
target = 726121530EE8881700AFED1B /* ifconfig */;
targetProxy = 7261217C0EE8896800AFED1B /* PBXContainerItemProxy */;
};
- 726121B30EE88B7900AFED1B /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 726121820EE8897C00AFED1B /* ip6conf */;
- targetProxy = 726121B20EE88B7900AFED1B /* PBXContainerItemProxy */;
- };
7294F0EA0EE8BAC80052EC88 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 7216D3A60EE8A3BA00AE70E4 /* spray */;
target = 726121530EE8881700AFED1B /* ifconfig */;
targetProxy = 72ABD0871083D750008C721C /* PBXContainerItemProxy */;
};
- 72ABD08A1083D753008C721C /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 726121820EE8897C00AFED1B /* ip6conf */;
- targetProxy = 72ABD0891083D753008C721C /* PBXContainerItemProxy */;
- };
72ABD08C1083D75D008C721C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 724DAC0C0EE8940D008900D0 /* ndp */;
target = 7261212C0EE8710B00AFED1B /* arp */;
targetProxy = 72ABD0A31083D818008C721C /* PBXContainerItemProxy */;
};
+ 72C77D3B1484199C002D2577 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7261210B0EE8707500AFED1B /* alias */;
+ targetProxy = 72C77D3C1484199C002D2577 /* PBXContainerItemProxy */;
+ };
72CD1D9C0EE8C47C005F825D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 7294F1290EE8BD280052EC88 /* traceroute6 */;
PREBINDING = NO;
SDKROOT = "";
"STRIPFLAGS[sdk=iphoneos*]" = "-S";
- VALID_ARCHS = "armv6 armv7 i386 x86_64";
WARNING_CFLAGS = "-Wall";
ZERO_LINK = NO;
};
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_MODEL_TUNING = G5;
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
};
name = "Ignore Me";
};
- 03B2DBE8100BE71D005349BC /* Ignore Me */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
- INSTALL_GROUP = wheel;
- INSTALL_MODE_FLAG = 0555;
- INSTALL_OWNER = root;
- INSTALL_PATH = /usr/sbin;
- PRODUCT_NAME = ip6;
- };
- name = "Ignore Me";
- };
03B2DBE9100BE71D005349BC /* Ignore Me */ = {
isa = XCBuildConfiguration;
buildSettings = {
"$(inherited)",
IP_FW_PRIVATE,
);
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
};
name = "Ignore Me";
};
+ 565825A11339218F003E5FA5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = mnc;
+ };
+ name = Debug;
+ };
+ 565825A21339218F003E5FA5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = mnc;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 565825A31339218F003E5FA5 /* Ignore Me */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = mnc;
+ };
+ name = "Ignore Me";
+ };
690D978312DE6035004323A7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Release;
};
+ 723C7070142BAFEA007C87E9 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = 0555;
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 723C7071142BAFEA007C87E9 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = 0555;
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 723C7072142BAFEA007C87E9 /* Ignore Me */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = 0555;
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = "Ignore Me";
+ };
724862320EE86EB7001D0DE9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
PREBINDING = NO;
SDKROOT = "";
- VALID_ARCHS = "armv6 armv7 i386 x86_64";
WARNING_CFLAGS = "-Wall";
};
name = Debug;
PREBINDING = NO;
SDKROOT = "";
"STRIPFLAGS[sdk=iphoneos*]" = "-S";
- VALID_ARCHS = "armv6 armv7 i386 x86_64";
WARNING_CFLAGS = "-Wall";
ZERO_LINK = NO;
};
"$(inherited)",
IP_FW_PRIVATE,
);
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
"$(inherited)",
IP_FW_PRIVATE,
);
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_MODEL_TUNING = G5;
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_GROUP = wheel;
INSTALL_MODE_FLAG = 0555;
INSTALL_OWNER = root;
};
name = Release;
};
- 726121850EE8897C00AFED1B /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
- INSTALL_GROUP = wheel;
- INSTALL_MODE_FLAG = 0555;
- INSTALL_OWNER = root;
- INSTALL_PATH = /usr/sbin;
- PRODUCT_NAME = ip6;
- };
- name = Debug;
- };
- 726121860EE8897C00AFED1B /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
- INSTALL_GROUP = wheel;
- INSTALL_MODE_FLAG = 0555;
- INSTALL_OWNER = root;
- INSTALL_PATH = /usr/sbin;
- PRODUCT_NAME = ip6;
- };
- name = Release;
- };
7294F0FB0EE8BB460052EC88 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = "Ignore Me";
};
+ 72C77D681484199C002D2577 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ PRODUCT_NAME = network_cmds_libs;
+ };
+ name = Debug;
+ };
+ 72C77D691484199C002D2577 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ PRODUCT_NAME = network_cmds_libs;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 72C77D6A1484199C002D2577 /* Ignore Me */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ PRODUCT_NAME = network_cmds_libs;
+ ZERO_LINK = NO;
+ };
+ name = "Ignore Me";
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 565825AB133921ED003E5FA5 /* Build configuration list for PBXNativeTarget "mnc" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 565825A11339218F003E5FA5 /* Debug */,
+ 565825A21339218F003E5FA5 /* Release */,
+ 565825A31339218F003E5FA5 /* Ignore Me */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
690D978612DE6053004323A7 /* Build configuration list for PBXNativeTarget "mtest" */ = {
isa = XCConfigurationList;
buildConfigurations = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 723C706F142BAFEA007C87E9 /* Build configuration list for PBXNativeTarget "dnctl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 723C7070142BAFEA007C87E9 /* Debug */,
+ 723C7071142BAFEA007C87E9 /* Release */,
+ 723C7072142BAFEA007C87E9 /* Ignore Me */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
724862340EE86EB7001D0DE9 /* Build configuration list for PBXProject "network_cmds" */ = {
isa = XCConfigurationList;
buildConfigurations = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 726121870EE8898B00AFED1B /* Build configuration list for PBXNativeTarget "ip6conf" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 726121850EE8897C00AFED1B /* Debug */,
- 726121860EE8897C00AFED1B /* Release */,
- 03B2DBE8100BE71D005349BC /* Ignore Me */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
7294F0FD0EE8BB550052EC88 /* Build configuration list for PBXNativeTarget "traceroute" */ = {
isa = XCConfigurationList;
buildConfigurations = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 72C77D671484199C002D2577 /* Build configuration list for PBXAggregateTarget "network_cmds_libs" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72C77D681484199C002D2577 /* Debug */,
+ 72C77D691484199C002D2577 /* Release */,
+ 72C77D6A1484199C002D2577 /* Ignore Me */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
};
rootObject = 724862310EE86EB7001D0DE9 /* Project object */;
or if the program is terminated with a
.Dv SIGINT ,
a brief summary is displayed, showing the number of packets sent and
-received, and the minimum, mean, maximum, and standard deviation of
-the round-trip times.
+received, and the minimum, mean, maximum, and the population standard
+deviation of the round-trip times.
.Pp
If
.Nm
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#endif /* IP_FORCE_OUT_IFP */
int nocell;
int how_traffic_class = 0;
-int traffic_class = -1;
+int traffic_class = SO_TC_CTL; /* use control class, by default */
int no_dup = 0;
/* counters */
if (options & F_SO_DONTROUTE)
(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
sizeof(hold));
- if (how_traffic_class == 1 && traffic_class > 0) {
- (void)setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class,
- sizeof(traffic_class));
- }
+ if (how_traffic_class < 2 && traffic_class >= 0) {
+ (void) setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS,
+ (void *)&traffic_class, sizeof (traffic_class));
+ }
if (how_traffic_class > 0) {
int on = 1;
- (void)setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS, (void *)&on,
- sizeof(on));
+ (void) setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS,
+ (void *)&on, sizeof (on));
}
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
packet = outpackhdr;
}
- if (how_traffic_class == 2) {
+ if (how_traffic_class > 1 && traffic_class >= 0) {
struct msghdr msg;
struct iovec iov;
char *cmbuf[CMSG_SPACE(sizeof(int))];
int rcvtclass = 0;
int how_so_traffic_class = 0;
-int so_traffic_class = -1;
+int so_traffic_class = SO_TC_CTL; /* use control class, by default */
int main(int, char *[]);
void fill(char *, char *);
how_so_traffic_class++;
so_traffic_class = atoi(optarg);
break;
-
+
case 'l':
if (getuid()) {
errno = EPERM;
if (tclass != -2)
ip6optlen += CMSG_SPACE(sizeof(int));
- if (how_so_traffic_class == 1 && so_traffic_class > 0) {
- (void)setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&so_traffic_class,
- sizeof(so_traffic_class));
- }
+ if (how_so_traffic_class < 2 && so_traffic_class >= 0) {
+ (void) setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS,
+ (void *)&so_traffic_class, sizeof (so_traffic_class));
+ }
if (how_so_traffic_class > 0) {
int on = 1;
- (void)setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS, (void *)&on,
- sizeof(on));
+ (void) setsockopt(s, SOL_SOCKET, SO_RECV_TRAFFIC_CLASS,
+ (void *)&on, sizeof (on));
}
if (how_so_traffic_class > 1)
ip6optlen += CMSG_SPACE(sizeof(int));
-
+
/* set IP6 packet options */
if (ip6optlen) {
if ((scmsg = (char *)malloc(ip6optlen)) == 0)
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
}
- if (how_so_traffic_class > 1) {
+ 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;
-
+
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
}
if (!(options & F_SRCADDR)) {
warnx("failed to get receiving traffic class");
return;
}
-
+
if (how_so_traffic_class > 0)
sotc = get_so_traffic_class(mhdr);
-
+
if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {
seq = ntohs(icp->icmp6_seq);
++nreceived;
int op, pid, devnull, f;
char *ifname, *hostname, *name;
- extern char *optarg;
extern int optind, opterr;
if ((name = strrchr(argv[0], '/')) != NULL)
/*
- * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016"
"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024b024"
"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\031IFSCOPE\032CONDEMNED"
-"\033IFREF";
+"\033IFREF\034PROXY\035ROUTER";
char ifnetflags[] =
"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
(long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
if (rtm->rtm_flags & RTF_IFSCOPE)
(void) printf("ifscope %d, ", rtm->rtm_index);
-#ifdef RTF_IFREF
if (rtm->rtm_flags & RTF_IFREF)
(void) printf("ifref, ");
-#endif /* RTF_IFREF */
(void) printf("flags:");
bprintf(stdout, rtm->rtm_flags, routeflags);
pmsg_common(rtm);
register char *cp;
register int i;
- (void) printf(" route to: %s\n", routename(&so_dst));
+ (void) printf(" route to: %s\n", routename(&so_dst.sa));
if (rtm->rtm_version != RTM_VERSION) {
warnx("routing message version %d not understood",
rtm->rtm_version);
/*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-/* $KAME: advcap.c,v 1.5 2001/02/01 09:12:08 jinmei Exp $ */
+/* $KAME: advcap.c,v 1.11 2003/05/19 09:46:50 keiichi Exp $ */
/*
* Copyright (c) 1983 The Regents of the University of California.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/advcap.c,v 1.1.2.2 2001/07/03 11:02:13 ume Exp $
*/
/*
extern char *conffile;
-int tgetent __P((char *, char *));
-int getent __P((char *, char *, char *));
-int tnchktc __P((void));
-int tnamatch __P((char *));
-static char *tskip __P((char *));
-long long tgetnum __P((char *));
-int tgetflag __P((char *));
-char *tgetstr __P((char *, char **));
-static char *tdecode __P((char *, char **));
+int tgetent(char *, char *);
+int getent(char *, char *, char *);
+int tnchktc(void);
+int tnamatch(char *);
+static char *tskip(char *);
+int64_t tgetnum(char *);
+int tgetflag(char *);
+char *tgetstr(char *, char **);
+static char *tdecode(char *, char **);
/*
* Get an entry for terminal name in buffer bp,
getent(bp, name, cp)
char *bp, *name, *cp;
{
- register int c;
- register int i = 0, cnt = 0;
+ int c;
+ int i = 0, cnt = 0;
char ibuf[BUFSIZ];
int tf;
}
if (tf < 0) {
syslog(LOG_INFO,
- "<%s> open: %s", __FUNCTION__, strerror(errno));
+ "<%s> open: %s", __func__, strerror(errno));
return (-2);
}
for (;;) {
}
break;
}
- if (cp >= bp+BUFSIZ) {
- write(2,"Remcap entry too long\n", 23);
+ if (cp >= bp + BUFSIZ) {
+ write(STDERR_FILENO, "Remcap entry too long\n",
+ 23);
break;
} else
*cp++ = c;
int
tnchktc()
{
- register char *p, *q;
+ char *p, *q;
char tcname[16]; /* name of similar terminal */
char tcbuf[BUFSIZ];
char *holdtbuf = tbuf;
p = tbuf + strlen(tbuf) - 2; /* before the last colon */
while (*--p != ':')
- if (p<tbuf) {
- write(2, "Bad remcap entry\n", 18);
+ if (p < tbuf) {
+ write(STDERR_FILENO, "Bad remcap entry\n", 18);
return (0);
}
p++;
/* p now points to beginning of last field */
if (p[0] != 't' || p[1] != 'c')
return (1);
- strlcpy(tcname, p+3, sizeof(tcname));
+ strlcpy(tcname, p + 3, sizeof tcname);
q = tcname;
while (*q && *q != ':')
q++;
*q = 0;
if (++hopcount > MAXHOP) {
- write(2, "Infinite tc= loop\n", 18);
+ write(STDERR_FILENO, "Infinite tc= loop\n", 18);
return (0);
}
if (getent(tcbuf, tcname, remotefile) != 1) {
/* check length before copying string below */
if (l > BUFSIZ) {
- write(2, "Remcap entry too long\n", 23);
+ write(STDERR_FILENO, "Remcap entry too long\n", 23);
q[BUFSIZ - (p-holdtbuf)] = 0;
}
strlcpy(p, q, p-tbuf);
tnamatch(np)
char *np;
{
- register char *Np, *Bp;
+ char *Np, *Bp;
Bp = tbuf;
if (*Bp == '#')
*/
static char *
tskip(bp)
- register char *bp;
+ char *bp;
{
int dquote;
* a # character. If the option is not found we return -1.
* Note that we handle octal numbers beginning with 0.
*/
-long long
+int64_t
tgetnum(id)
char *id;
{
- register long long i;
- register int base;
- register char *bp = tbuf;
+ int64_t i;
+ int base;
+ char *bp = tbuf;
for (;;) {
bp = tskip(bp);
tgetflag(id)
char *id;
{
- register char *bp = tbuf;
+ char *bp = tbuf;
for (;;) {
bp = tskip(bp);
tgetstr(id, area)
char *id, **area;
{
- register char *bp = tbuf;
+ char *bp = tbuf;
for (;;) {
bp = tskip(bp);
*/
static char *
tdecode(str, area)
- register char *str;
+ char *str;
char **area;
{
- register char *cp;
- register int c;
- register char *dp;
+ char *cp;
+ int c;
+ char *dp;
int i;
char term;
-/* $KAME: advcap.h,v 1.3 2001/02/01 09:12:08 jinmei Exp $ */
+/* $KAME: advcap.h,v 1.5 2003/06/09 05:40:54 t-momose Exp $ */
/*
* Copyright (C) 1994,1995 by Andrey A. Chernov, Moscow, Russia.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/advcap.h,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
/* Based on Id: termcap.h,v 1.8 1996/09/10 12:42:10 peter Exp */
__BEGIN_DECLS
-extern int agetent __P((char *, const char *));
-extern int agetflag __P((const char *));
-extern long long agetnum __P((const char *));
-extern char *agetstr __P((const char *, char **));
+extern int agetent(char *, const char *);
+extern int agetflag(const char *);
+extern int64_t agetnum(const char *);
+extern char *agetstr(const char *, char **);
__END_DECLS
/*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-/* $KAME: config.c,v 1.37 2001/05/25 07:34:00 itojun Exp $ */
+/* $KAME: config.c,v 1.84 2003/08/05 12:34:23 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/config.c,v 1.3.2.3 2001/07/03 11:02:14 ume Exp $
*/
#include <sys/param.h>
#include <sys/sysctl.h>
#include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
-#endif /* __FreeBSD__ >= 3 */
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
-#ifdef MIP6
-#include <netinet6/mip6.h>
-#endif
+#include <netinet6/nd6.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <errno.h>
#include <string.h>
-#include <stdlib.h>
-#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
#include <search.h>
-#endif
+#include <stdlib.h>
#include <unistd.h>
#include <ifaddrs.h>
+#include <stddef.h>
#include "rtadvd.h"
#include "advcap.h"
#include "if.h"
#include "config.h"
-static void makeentry (char *, size_t, int, char *, int);
-static void get_prefix (struct rainfo *);
-static int getinet6sysctl (int);
-
+static time_t prefix_timo = (60 * 120); /* 2 hours.
+ * XXX: should be configurable. */
extern struct rainfo *ralist;
+static struct rtadvd_timer *prefix_timeout(void *);
+static void makeentry(char *, size_t, int, char *);
+static int getinet6sysctl(int);
+static int encode_domain(char *, u_char *);
+
void
-getconfig(char *intface)
+getconfig(intface)
+ char *intface;
{
- int stat, pfxs, i;
+ int stat, i;
int rdnss_length;
+ int dnssl_length;
char tbuf[BUFSIZ];
struct rainfo *tmp;
long val;
- long long val64;
+ int64_t val64;
char buf[BUFSIZ];
char *bp = buf;
- char *addr;
+ char *addr, *flagstr;
static int forwarding = -1;
#define MUSTHAVE(var, cap) \
do { \
- int t; \
+ int64_t t; \
if ((t = agetnum(cap)) < 0) { \
fprintf(stderr, "rtadvd: need %s for interface %s\n", \
cap, intface); \
"<%s> %s isn't defined in the configuration file"
" or the configuration file doesn't exist."
" Treat it as default",
- __FUNCTION__, intface);
+ __func__, intface);
}
tmp = (struct rainfo *)malloc(sizeof(*ralist));
+ if (tmp == NULL) {
+ syslog(LOG_INFO, "<%s> %s: can't allocate enough memory",
+ __func__, intface);
+ exit(1);
+ }
memset(tmp, 0, sizeof(*tmp));
tmp->prefix.next = tmp->prefix.prev = &tmp->prefix;
+#ifdef ROUTEINFO
tmp->route.next = tmp->route.prev = &tmp->route;
+#endif
tmp->rdnss_list.next = tmp->rdnss_list.prev = &tmp->rdnss_list;
+ tmp->dnssl_list.next = tmp->dnssl_list.prev = &tmp->dnssl_list;
/* check if we are allowed to forward packets (if not determined) */
if (forwarding < 0) {
if ((tmp->sdl = if_nametosdl(intface)) == NULL) {
syslog(LOG_ERR,
"<%s> can't get information of %s",
- __FUNCTION__, intface);
+ __func__, intface);
exit(1);
}
tmp->ifindex = tmp->sdl->sdl_index;
tmp->phymtu = IPV6_MMTU;
syslog(LOG_WARNING,
"<%s> can't get interface mtu of %s. Treat as %d",
- __FUNCTION__, intface, IPV6_MMTU);
+ __func__, intface, IPV6_MMTU);
}
/*
MAYHAVE(val, "maxinterval", DEF_MAXRTRADVINTERVAL);
if (val < MIN_MAXINTERVAL || val > MAX_MAXINTERVAL) {
syslog(LOG_ERR,
- "<%s> maxinterval must be between %e and %u",
- __FUNCTION__, MIN_MAXINTERVAL, MAX_MAXINTERVAL);
+ "<%s> maxinterval (%ld) on %s is invalid "
+ "(must be between %u and %u)", __func__, val,
+ intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL);
exit(1);
}
tmp->maxinterval = (u_int)val;
MAYHAVE(val, "mininterval", tmp->maxinterval/3);
if (val < MIN_MININTERVAL || val > (tmp->maxinterval * 3) / 4) {
syslog(LOG_ERR,
- "<%s> mininterval must be between %e and %d",
- __FUNCTION__,
- MIN_MININTERVAL,
+ "<%s> mininterval (%ld) on %s is invalid "
+ "(must be between %d and %d)",
+ __func__, val, intface, MIN_MININTERVAL,
(tmp->maxinterval * 3) / 4);
exit(1);
}
MAYHAVE(val, "chlim", DEF_ADVCURHOPLIMIT);
tmp->hoplimit = val & 0xff;
- MAYHAVE(val, "raflags", 0);
+ if ((flagstr = (char *)agetstr("raflags", &bp))) {
+ val = 0;
+ if (strchr(flagstr, 'm'))
+ val |= ND_RA_FLAG_MANAGED;
+ if (strchr(flagstr, 'o'))
+ val |= ND_RA_FLAG_OTHER;
+ if (strchr(flagstr, 'h'))
+ val |= ND_RA_FLAG_RTPREF_HIGH;
+ if (strchr(flagstr, 'l')) {
+ if ((val & ND_RA_FLAG_RTPREF_HIGH)) {
+ syslog(LOG_ERR, "<%s> the \'h\' and \'l\'"
+ " router flags are exclusive", __func__);
+ exit(1);
+ }
+ val |= ND_RA_FLAG_RTPREF_LOW;
+ }
+ } else {
+ MAYHAVE(val, "raflags", 0);
+ }
tmp->managedflg = val & ND_RA_FLAG_MANAGED;
tmp->otherflg = val & ND_RA_FLAG_OTHER;
-#ifdef MIP6
- if (mobileip6)
- tmp->haflg = val & ND_RA_FLAG_HA;
-#endif
#ifndef ND_RA_FLAG_RTPREF_MASK
#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
#endif
tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV) {
- syslog(LOG_ERR, "<%s> invalid router preference on %s",
- __FUNCTION__, intface);
+ syslog(LOG_ERR, "<%s> invalid router preference (%02x) on %s",
+ __func__, tmp->rtpref, intface);
exit(1);
}
MAYHAVE(val, "rltime", tmp->maxinterval * 3);
if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) {
syslog(LOG_ERR,
- "<%s> router lifetime on %s must be 0 or"
- " between %d and %d",
- __FUNCTION__, intface,
- tmp->maxinterval, MAXROUTERLIFETIME);
+ "<%s> router lifetime (%ld) on %s is invalid "
+ "(must be 0 or between %d and %d)",
+ __func__, val, intface,
+ tmp->maxinterval,
+ MAXROUTERLIFETIME);
exit(1);
}
/*
* explicitly set zero. (see also the above section)
*/
if (val && forwarding == 0) {
- syslog(LOG_WARNING,
+ syslog(LOG_ERR,
"<%s> non zero router lifetime is specified for %s, "
- "which must not be allowed for hosts.",
- __FUNCTION__, intface);
+ "which must not be allowed for hosts. you must "
+ "change router lifetime or enable IPv6 forwarding.",
+ __func__, intface);
exit(1);
}
tmp->lifetime = val & 0xffff;
MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
- if (val > MAXREACHABLETIME) {
+ if (val < 0 || val > MAXREACHABLETIME) {
syslog(LOG_ERR,
- "<%s> reachable time must be no greater than %d",
- __FUNCTION__, MAXREACHABLETIME);
+ "<%s> reachable time (%ld) on %s is invalid "
+ "(must be no greater than %d)",
+ __func__, val, intface, MAXREACHABLETIME);
exit(1);
}
tmp->reachabletime = (u_int32_t)val;
MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER);
if (val64 < 0 || val64 > 0xffffffff) {
- syslog(LOG_ERR,
- "<%s> retrans time out of range", __FUNCTION__);
+ syslog(LOG_ERR, "<%s> retrans time (%lld) on %s out of range",
+ __func__, (long long)val64, intface);
exit(1);
}
tmp->retranstimer = (u_int32_t)val64;
-#ifndef MIP6
- if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
+ if (agetnum("hapref") != -1 || agetnum("hatime") != -1) {
syslog(LOG_ERR,
"<%s> mobile-ip6 configuration not supported",
- __FUNCTION__);
+ __func__);
exit(1);
}
-#else
- if (!mobileip6) {
- if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
- syslog(LOG_ERR,
- "<%s> mobile-ip6 configuration without "
- "proper command line option",
- __FUNCTION__);
- exit(1);
- }
- } else {
- tmp->hapref = 0;
- if ((val = agetnum("hapref")) >= 0)
- tmp->hapref = (int16_t)val;
- if (tmp->hapref != 0) {
- tmp->hatime = 0;
- MUSTHAVE(val, "hatime");
- tmp->hatime = (u_int16_t)val;
- if (tmp->hatime <= 0) {
- syslog(LOG_ERR,
- "<%s> home agent lifetime must be greater than 0",
- __FUNCTION__);
- exit(1);
- }
- }
- }
-#endif
-
/* prefix information */
/*
- * This is an implementation specific parameter to consinder
+ * This is an implementation specific parameter to consider
* link propagation delays and poorly synchronized clocks when
* checking consistency of advertised lifetimes.
*/
MAYHAVE(val, "clockskew", 0);
tmp->clockskew = val;
- if ((pfxs = agetnum("addrs")) < 0) {
- /* auto configure prefix information */
- if (agetstr("addr", &bp) || agetstr("addr1", &bp)) {
+ tmp->pfxs = 0;
+ for (i = -1; i < MAXPREFIX; i++) {
+ struct prefix *pfx;
+ char entbuf[256];
+
+ makeentry(entbuf, sizeof(entbuf), i, "addr");
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL)
+ continue;
+
+ /* allocate memory to store prefix information */
+ if ((pfx = malloc(sizeof(struct prefix))) == NULL) {
syslog(LOG_ERR,
- "<%s> conflicting prefix configuration for %s: "
- "automatic and manual config at the same time",
- __FUNCTION__, intface);
+ "<%s> can't allocate enough memory",
+ __func__);
exit(1);
}
- get_prefix(tmp);
- }
- else {
- tmp->pfxs = pfxs;
- for (i = 0; i < pfxs; i++) {
- struct prefix *pfx;
- char entbuf[256];
- int added = (pfxs > 1) ? 1 : 0;
-
- /* allocate memory to store prefix information */
- if ((pfx = malloc(sizeof(struct prefix))) == NULL) {
- syslog(LOG_ERR,
- "<%s> can't allocate enough memory",
- __FUNCTION__);
- exit(1);
- }
- memset(pfx, 0, sizeof(*pfx));
+ memset(pfx, 0, sizeof(*pfx));
- /* link into chain */
- insque(pfx, &tmp->prefix);
+ /* link into chain */
+ insque(pfx, &tmp->prefix);
+ tmp->pfxs++;
+ pfx->rainfo = tmp;
- pfx->origin = PREFIX_FROM_CONFIG;
+ pfx->origin = PREFIX_FROM_CONFIG;
- makeentry(entbuf, sizeof(entbuf), i, "prefixlen", added);
- MAYHAVE(val, entbuf, 64);
- if (val < 0 || val > 128) {
- syslog(LOG_ERR,
- "<%s> prefixlen out of range",
- __FUNCTION__);
- exit(1);
- }
- pfx->prefixlen = (int)val;
-
- makeentry(entbuf, sizeof(entbuf), i, "pinfoflags", added);
-#ifdef MIP6
- if (mobileip6)
- {
- MAYHAVE(val, entbuf,
- (ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO|
- ND_OPT_PI_FLAG_ROUTER));
- } else
-#endif
- {
- MAYHAVE(val, entbuf,
- (ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO));
- }
- pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
- pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
-#ifdef MIP6
- pfx->routeraddr = val & ND_OPT_PI_FLAG_ROUTER;
-#endif
+ if (inet_pton(AF_INET6, addr, &pfx->prefix) != 1) {
+ syslog(LOG_ERR,
+ "<%s> inet_pton failed for %s",
+ __func__, addr);
+ exit(1);
+ }
+ if (IN6_IS_ADDR_MULTICAST(&pfx->prefix)) {
+ syslog(LOG_ERR,
+ "<%s> multicast prefix (%s) must "
+ "not be advertised on %s",
+ __func__, addr, intface);
+ exit(1);
+ }
+ if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix))
+ syslog(LOG_NOTICE,
+ "<%s> link-local prefix (%s) will be"
+ " advertised on %s",
+ __func__, addr, intface);
- makeentry(entbuf, sizeof(entbuf), i, "vltime", added);
- MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
- if (val64 < 0 || val64 > 0xffffffff) {
- syslog(LOG_ERR,
- "<%s> vltime out of range",
- __FUNCTION__);
- exit(1);
- }
- pfx->validlifetime = (u_int32_t)val64;
-
- makeentry(entbuf, sizeof(entbuf), i, "vltimedecr", added);
- if (agetflag(entbuf)) {
- struct timeval now;
- gettimeofday(&now, 0);
- pfx->vltimeexpire =
- now.tv_sec + pfx->validlifetime;
- }
+ makeentry(entbuf, sizeof(entbuf), i, "prefixlen");
+ MAYHAVE(val, entbuf, 64);
+ if (val < 0 || val > 128) {
+ syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s "
+ "on %s out of range",
+ __func__, val, addr, intface);
+ exit(1);
+ }
+ pfx->prefixlen = (int)val;
+
+ makeentry(entbuf, sizeof(entbuf), i, "pinfoflags");
+ if ((flagstr = (char *)agetstr(entbuf, &bp))) {
+ val = 0;
+ if (strchr(flagstr, 'l'))
+ val |= ND_OPT_PI_FLAG_ONLINK;
+ if (strchr(flagstr, 'a'))
+ val |= ND_OPT_PI_FLAG_AUTO;
+ } else {
+ MAYHAVE(val, entbuf,
+ (ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO));
+ }
+ pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
+ pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
- makeentry(entbuf, sizeof(entbuf), i, "pltime", added);
- MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
- if (val64 < 0 || val64 > 0xffffffff) {
- syslog(LOG_ERR,
- "<%s> pltime out of range",
- __FUNCTION__);
- exit(1);
- }
- pfx->preflifetime = (u_int32_t)val64;
-
- makeentry(entbuf, sizeof(entbuf), i, "pltimedecr", added);
- if (agetflag(entbuf)) {
- struct timeval now;
- gettimeofday(&now, 0);
- pfx->pltimeexpire =
- now.tv_sec + pfx->preflifetime;
- }
+ makeentry(entbuf, sizeof(entbuf), i, "vltime");
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
+ syslog(LOG_ERR, "<%s> vltime (%lld) for "
+ "%s/%d on %s is out of range",
+ __func__, (long long)val64,
+ addr, pfx->prefixlen, intface);
+ exit(1);
+ }
+ pfx->validlifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, sizeof(entbuf), i, "vltimedecr");
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->vltimeexpire =
+ now.tv_sec + pfx->validlifetime;
+ }
- makeentry(entbuf, sizeof(entbuf), i, "addr", added);
- addr = (char *)agetstr(entbuf, &bp);
- if (addr == NULL) {
- syslog(LOG_ERR,
- "<%s> need %s as an prefix for "
- "interface %s",
- __FUNCTION__, entbuf, intface);
- exit(1);
- }
- if (inet_pton(AF_INET6, addr,
- &pfx->prefix) != 1) {
- syslog(LOG_ERR,
- "<%s> inet_pton failed for %s",
- __FUNCTION__, addr);
- exit(1);
- }
- if (IN6_IS_ADDR_MULTICAST(&pfx->prefix)) {
- syslog(LOG_ERR,
- "<%s> multicast prefix(%s) must "
- "not be advertised (IF=%s)",
- __FUNCTION__, addr, intface);
- exit(1);
- }
- if (IN6_IS_ADDR_LINKLOCAL(&pfx->prefix))
- syslog(LOG_NOTICE,
- "<%s> link-local prefix(%s) will be"
- " advertised on %s",
- __FUNCTION__, addr, intface);
+ makeentry(entbuf, sizeof(entbuf), i, "pltime");
+ MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
+ syslog(LOG_ERR,
+ "<%s> pltime (%lld) for %s/%d on %s "
+ "is out of range",
+ __func__, (long long)val64,
+ addr, pfx->prefixlen, intface);
+ exit(1);
+ }
+ pfx->preflifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, sizeof(entbuf), i, "pltimedecr");
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->pltimeexpire =
+ now.tv_sec + pfx->preflifetime;
}
}
+ if (tmp->pfxs == 0)
+ get_prefix(tmp);
MAYHAVE(val, "mtu", 0);
if (val < 0 || val > 0xffffffff) {
syslog(LOG_ERR,
- "<%s> mtu out of range", __FUNCTION__);
+ "<%s> mtu (%ld) on %s out of range",
+ __func__, val, intface);
exit(1);
}
tmp->linkmtu = (u_int32_t)val;
}
else if (tmp->linkmtu < IPV6_MMTU || tmp->linkmtu > tmp->phymtu) {
syslog(LOG_ERR,
- "<%s> advertised link mtu must be between"
- " least MTU and physical link MTU",
- __FUNCTION__);
+ "<%s> advertised link mtu (%lu) on %s is invalid (must "
+ "be between least MTU (%d) and physical link MTU (%d)",
+ __func__, (unsigned long)tmp->linkmtu, intface,
+ IPV6_MMTU, tmp->phymtu);
exit(1);
}
- /* route information */
+#ifdef SIOCSIFINFO_IN6
+ {
+ struct in6_ndireq ndi;
+ int s;
- MAYHAVE(val, "routes", 0);
- if (val < 0 || val > 0xffffffff) {
- syslog(LOG_ERR,
- "<%s> number of route information improper", __FUNCTION__);
- exit(1);
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ syslog(LOG_ERR, "<%s> socket: %s", __func__,
+ strerror(errno));
+ exit(1);
+ }
+ memset(&ndi, 0, sizeof(ndi));
+ strncpy(ndi.ifname, intface, IFNAMSIZ);
+ if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&ndi) < 0) {
+ syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s",
+ __func__, intface, strerror(errno));
+ }
+
+ /* reflect the RA info to the host variables in kernel */
+ ndi.ndi.chlim = tmp->hoplimit;
+ ndi.ndi.retrans = tmp->retranstimer;
+ ndi.ndi.basereachable = tmp->reachabletime;
+ if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&ndi) < 0) {
+ syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s",
+ __func__, intface, strerror(errno));
+ }
+ close(s);
}
- tmp->routes = val;
- for (i = 0; i < tmp->routes; i++) {
+#endif
+
+ /* route information */
+#ifdef ROUTEINFO
+ tmp->routes = 0;
+ for (i = -1; i < MAXROUTE; i++) {
struct rtinfo *rti;
- char entbuf[256];
- int added = (tmp->routes > 1) ? 1 : 0;
+ char entbuf[256], oentbuf[256];
+
+ makeentry(entbuf, sizeof(entbuf), i, "rtprefix");
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL) {
+ makeentry(oentbuf, sizeof(oentbuf), i, "rtrprefix");
+ addr = (char *)agetstr(oentbuf, &bp);
+ if (addr) {
+ fprintf(stderr, "%s was obsoleted. Use %s.\n",
+ oentbuf, entbuf);
+ }
+ }
+ if (addr == NULL)
+ continue;
/* allocate memory to store prefix information */
if ((rti = malloc(sizeof(struct rtinfo))) == NULL) {
syslog(LOG_ERR,
"<%s> can't allocate enough memory",
- __FUNCTION__);
+ __func__);
exit(1);
}
memset(rti, 0, sizeof(*rti));
/* link into chain */
insque(rti, &tmp->route);
+ tmp->routes++;
- makeentry(entbuf, sizeof(entbuf), i, "rtrplen", added);
- MAYHAVE(val, entbuf, 64);
- if (val < 0 || val > 128) {
- syslog(LOG_ERR,
- "<%s> prefixlen out of range",
- __FUNCTION__);
- exit(1);
- }
- rti->prefixlen = (int)val;
-
- makeentry(entbuf, sizeof(entbuf), i, "rtrflags", added);
- MAYHAVE(val, entbuf, 0);
- rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
- if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) {
- syslog(LOG_ERR, "<%s> invalid router preference",
- __FUNCTION__);
- exit(1);
- }
-
- makeentry(entbuf, sizeof(entbuf), i, "rtrltime", added);
- /*
- * XXX: since default value of route lifetime is not defined in
- * draft-draves-route-selection-01.txt, I took the default
- * value of valid lifetime of prefix as its default.
- * It need be much considered.
- */
- MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
- if (val64 < 0 || val64 > 0xffffffff) {
- syslog(LOG_ERR,
- "<%s> rtrltime out of range",
- __FUNCTION__);
- exit(1);
- }
- rti->ltime = (u_int32_t)val64;
-
- makeentry(entbuf, sizeof(entbuf), i, "rtrprefix", added);
- addr = (char *)agetstr(entbuf, &bp);
- if (addr == NULL) {
- syslog(LOG_ERR,
- "<%s> need %s as an route for "
- "interface %s",
- __FUNCTION__, entbuf, intface);
- exit(1);
- }
if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) {
- syslog(LOG_ERR,
- "<%s> inet_pton failed for %s",
- __FUNCTION__, addr);
+ syslog(LOG_ERR, "<%s> inet_pton failed for %s",
+ __func__, addr);
exit(1);
}
#if 0
/*
* XXX: currently there's no restriction in route information
- * prefix according to draft-draves-route-selection-01.txt,
- * however I think the similar restriction be necessary.
+ * prefix according to
+ * draft-ietf-ipngwg-router-selection-00.txt.
+ * However, I think the similar restriction be necessary.
*/
MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
if (IN6_IS_ADDR_MULTICAST(&rti->prefix)) {
syslog(LOG_ERR,
"<%s> multicast route (%s) must "
- "not be advertised (IF=%s)",
- __FUNCTION__, addr, intface);
+ "not be advertised on %s",
+ __func__, addr, intface);
exit(1);
}
if (IN6_IS_ADDR_LINKLOCAL(&rti->prefix)) {
syslog(LOG_NOTICE,
- "<%s> link-local route (%s) must "
- "not be advertised on %s",
- __FUNCTION__, addr, intface);
+ "<%s> link-local route (%s) will "
+ "be advertised on %s",
+ __func__, addr, intface);
exit(1);
}
#endif
+
+ makeentry(entbuf, sizeof(entbuf), i, "rtplen");
+ /* XXX: 256 is a magic number for compatibility check. */
+ MAYHAVE(val, entbuf, 256);
+ if (val == 256) {
+ makeentry(oentbuf, sizeof(oentbuf), i, "rtrplen");
+ MAYHAVE(val, oentbuf, 256);
+ if (val != 256) {
+ fprintf(stderr, "%s was obsoleted. Use %s.\n",
+ oentbuf, entbuf);
+ } else
+ val = 64;
+ }
+ if (val < 0 || val > 128) {
+ syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s on %s "
+ "out of range",
+ __func__, val, addr, intface);
+ exit(1);
+ }
+ rti->prefixlen = (int)val;
+
+ makeentry(entbuf, sizeof(entbuf), i, "rtflags");
+ if ((flagstr = (char *)agetstr(entbuf, &bp))) {
+ val = 0;
+ if (strchr(flagstr, 'h'))
+ val |= ND_RA_FLAG_RTPREF_HIGH;
+ if (strchr(flagstr, 'l')) {
+ if ((val & ND_RA_FLAG_RTPREF_HIGH)) {
+ syslog(LOG_ERR,
+ "<%s> the \'h\' and \'l\' route"
+ " preferences are exclusive",
+ __func__);
+ exit(1);
+ }
+ val |= ND_RA_FLAG_RTPREF_LOW;
+ }
+ } else
+ MAYHAVE(val, entbuf, 256); /* XXX */
+ if (val == 256) {
+ makeentry(oentbuf, sizeof(oentbuf), i, "rtrflags");
+ MAYHAVE(val, oentbuf, 256);
+ if (val != 256) {
+ fprintf(stderr, "%s was obsoleted. Use %s.\n",
+ oentbuf, entbuf);
+ } else
+ val = 0;
+ }
+ rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+ if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+ syslog(LOG_ERR, "<%s> invalid route preference (%02x) "
+ "for %s/%d on %s",
+ __func__, rti->rtpref, addr,
+ rti->prefixlen, intface);
+ exit(1);
+ }
+
+ /*
+ * Since the spec does not a default value, we should make
+ * this entry mandatory. However, FreeBSD 4.4 has shipped
+ * with this field being optional, we use the router lifetime
+ * as an ad-hoc default value with a warning message.
+ */
+ makeentry(entbuf, sizeof(entbuf), i, "rtltime");
+ MAYHAVE(val64, entbuf, -1);
+ if (val64 == -1) {
+ makeentry(oentbuf, sizeof(oentbuf), i, "rtrltime");
+ MAYHAVE(val64, oentbuf, -1);
+ if (val64 != -1) {
+ fprintf(stderr, "%s was obsoleted. Use %s.\n",
+ oentbuf, entbuf);
+ } else {
+ fprintf(stderr, "%s should be specified "
+ "for interface %s.\n",
+ entbuf, intface);
+ val64 = tmp->lifetime;
+ }
+ }
+ if (val64 < 0 || val64 > 0xffffffff) {
+ syslog(LOG_ERR, "<%s> route lifetime (%lld) for "
+ "%s/%d on %s out of range", __func__,
+ (long long)val64, addr, rti->prefixlen, intface);
+ exit(1);
+ }
+ rti->ltime = (u_int32_t)val64;
}
+#endif
/* RDNSS option (RFC5006) */
MAYHAVE(val, "rdnsslifetime", 2 * tmp->maxinterval);
if (val < tmp->maxinterval || val > (2 * tmp->maxinterval)) {
syslog(LOG_NOTICE,
"<%s> rdnsslifetime (%lu) on %s SHOULD "
- "be between %u and %u", __FUNCTION__, val,
+ "be between %u and %u", __func__, val,
intface, tmp->maxinterval, 2 * tmp->maxinterval);
}
tmp->rdnss_lifetime = val;
for (i = (rdnss_length - 1); i >= 0; i--) {
struct rdnss *rdnss;
char entbuf[256];
- int added = (rdnss_length > 1) ? 1 : 0;
/* allocate memory to store server address information */
if ((rdnss = malloc(sizeof(struct rdnss))) == NULL) {
syslog(LOG_ERR,
"<%s> can't allocate enough memory",
- __FUNCTION__);
+ __func__);
exit(1);
}
memset(rdnss, 0, sizeof(*rdnss));
/* link into chain */
insque(rdnss, &tmp->rdnss_list);
- makeentry(entbuf, sizeof(entbuf), i, "rdnssaddr", added);
+ makeentry(entbuf, sizeof(entbuf), i, "rdnssaddr");
addr = (char *)agetstr(entbuf, &bp);
+
+ if (addr == NULL && rdnss_length == 1) {
+ makeentry(entbuf, sizeof(entbuf), -1, "rdnssaddr");
+ addr = agetstr(entbuf, &bp);
+ }
+
if (addr == NULL) {
syslog(LOG_ERR,
"<%s> need %s as a DNS server address for "
"interface %s",
- __FUNCTION__, entbuf, intface);
+ __func__, entbuf, intface);
exit(1);
}
if (inet_pton(AF_INET6, addr, &rdnss->addr) != 1) {
syslog(LOG_ERR,
"<%s> inet_pton failed for %s",
- __FUNCTION__, addr);
+ __func__, addr);
exit(1);
}
if (IN6_IS_ADDR_MULTICAST(&rdnss->addr)) {
syslog(LOG_ERR,
"<%s> multicast address (%s) must "
"not be advertised as recursive DNS server",
- __FUNCTION__, addr);
+ __func__, addr);
exit(1);
}
}
}
+ /* DNSSL option (RFC6106) */
+
+ /* Parse the DNSSL lifetime from the config */
+ MAYHAVE(val, "dnssllifetime", 2 * tmp->maxinterval);
+ if (val < tmp->maxinterval || val > (2 * tmp->maxinterval)) {
+ syslog(LOG_NOTICE,
+ "<%s> dnssllifetime (%lu) on %s SHOULD "
+ "be between %u and %u", __func__, val,
+ intface, tmp->maxinterval, 2 * tmp->maxinterval);
+ }
+ tmp->dnssl_lifetime = val;
+ tmp->dnssl_option_length = 8; /* 8 bytes for the option header */
+
+ /* Parse the DNSSL domain list from the config */
+ if ((dnssl_length = agetnum("dnssldomains")) < 0) {
+ tmp->dnssl_length = 0;
+ } else {
+ tmp->dnssl_length = dnssl_length;
+
+ for (i = (tmp->dnssl_length - 1); i >= 0; i--) {
+ unsigned char *dnssl_buf;
+ struct dnssl *dnssl;
+ int dnssl_len;
+ char entbuf[sizeof("dnssldomain") + 20];
+ char *domain;
+ int domain_len;
+
+ makeentry(entbuf, sizeof(entbuf), i, "dnssldomain");
+ domain = agetstr(entbuf, &bp);
+
+ if (domain == NULL && tmp->dnssl_length == 1) {
+ makeentry(entbuf, sizeof(entbuf), -1, "dnssldomain");
+ domain = agetstr(entbuf, &bp);
+ }
+
+ if (domain == NULL) {
+ syslog(LOG_ERR,
+ "<%s> need %s as a DNS search domain for "
+ "interface %s",
+ __func__, entbuf, intface);
+ exit(1);
+ }
+
+ domain_len = strlen(domain);
+
+ /* Trim off leading dots */
+ while (domain_len > 0 && domain[0] == '.') {
+ domain++;
+ domain_len--;
+ }
+
+ /* Trim off trailing dots */
+ while (domain_len > 0 && domain[domain_len-1] == '.') {
+ domain_len--;
+ }
+
+ if (domain_len > 0) {
+ dnssl_len = sizeof(struct dnssl) + domain_len + 1;
+ dnssl_buf = (unsigned char *)malloc(dnssl_len);
+
+ memset(dnssl_buf, 0, dnssl_len);
+
+ dnssl = (struct dnssl *)dnssl_buf;
+ insque(dnssl, &tmp->dnssl_list);
+
+ /* Copy the domain name in at the end of the dnssl struct */
+ memcpy(dnssl_buf + offsetof(struct dnssl, domain), domain,
+ domain_len);
+
+ /* Add 2 for leading length byte and the trailing 0 byte */
+ tmp->dnssl_option_length += domain_len + 2;
+ }
+ }
+
+ /* Round up to the next multiple of 8 */
+ tmp->dnssl_option_length += (8 - (tmp->dnssl_option_length & 0x7));
+ }
+
/* okey */
tmp->next = ralist;
ralist = tmp;
rtadvd_set_timer(&tmp->timer->tm, tmp->timer);
}
-static void
+void
get_prefix(struct rainfo *rai)
{
struct ifaddrs *ifap, *ifa;
struct prefix *pp;
struct in6_addr *a;
u_char *p, *ep, *m, *lim;
- u_char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
if (getifaddrs(&ifap) < 0) {
syslog(LOG_ERR,
"<%s> can't get interface addresses",
- __FUNCTION__);
+ __func__);
exit(1);
}
+
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ int plen;
+
if (strcmp(ifa->ifa_name, rai->ifname) != 0)
continue;
if (ifa->ifa_addr->sa_family != AF_INET6)
a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
if (IN6_IS_ADDR_LINKLOCAL(a))
continue;
+ /* get prefix length */
+ m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
+ lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len;
+ plen = prefixlen(m, lim);
+ if (plen <= 0 || plen > 128) {
+ syslog(LOG_ERR, "<%s> failed to get prefixlen "
+ "or prefix is invalid",
+ __func__);
+ exit(1);
+ }
+ if (plen == 128) /* XXX */
+ continue;
+ if (find_prefix(rai, a, plen)) {
+ /* ignore a duplicated prefix. */
+ continue;
+ }
/* allocate memory to store prefix info. */
if ((pp = malloc(sizeof(*pp))) == NULL) {
syslog(LOG_ERR,
"<%s> can't get allocate buffer for prefix",
- __FUNCTION__);
+ __func__);
exit(1);
}
memset(pp, 0, sizeof(*pp));
- /* set prefix length */
- m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
- lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len;
- pp->prefixlen = prefixlen(m, lim);
- if (pp->prefixlen < 0 || pp->prefixlen > 128) {
- syslog(LOG_ERR,
- "<%s> failed to get prefixlen "
- "or prefix is invalid",
- __FUNCTION__);
- exit(1);
- }
-
/* set prefix, sweep bits outside of prefixlen */
+ pp->prefixlen = plen;
memcpy(&pp->prefix, a, sizeof(*a));
p = (u_char *)&pp->prefix;
ep = (u_char *)(&pp->prefix + 1);
- while (m < lim)
+ while (m < lim && p < ep)
*p++ &= *m++;
while (p < ep)
*p++ = 0x00;
-
- if (!inet_ntop(AF_INET6, &pp->prefix, (char *)ntopbuf,
+ if (!inet_ntop(AF_INET6, &pp->prefix, ntopbuf,
sizeof(ntopbuf))) {
- syslog(LOG_ERR, "<%s> inet_ntop failed", __FUNCTION__);
+ syslog(LOG_ERR, "<%s> inet_ntop failed", __func__);
exit(1);
}
syslog(LOG_DEBUG,
"<%s> add %s/%d to prefix list on %s",
- __FUNCTION__, ntopbuf, pp->prefixlen, rai->ifname);
+ __func__, ntopbuf, pp->prefixlen, rai->ifname);
/* set other fields with protocol defaults */
pp->validlifetime = DEF_ADVVALIDLIFETIME;
pp->onlinkflg = 1;
pp->autoconfflg = 1;
pp->origin = PREFIX_FROM_KERNEL;
+ pp->rainfo = rai;
/* link into chain */
insque(pp, &rai->prefix);
}
static void
-makeentry(char *buf, size_t len, int id, char *string, int add)
+makeentry(buf, len, id, string)
+ char *buf;
+ size_t len;
+ int id;
+ char *string;
{
- strlcpy(buf, string, len);
- if (add) {
- char *cp;
- cp = (char *)index(buf, '\0');
- cp += snprintf(cp, len - (cp - buf), "%d", id);
- *cp = '\0';
- }
+ if (id < 0)
+ strlcpy(buf, string, len);
+ else
+ snprintf(buf, len, "%s%d", string, id);
}
/*
* Add a prefix to the list of specified interface and reconstruct
* the outgoing packet.
* The prefix must not be in the list.
- * XXX: other parameter of the prefix(e.g. lifetime) shoule be
+ * XXX: other parameters of the prefix (e.g. lifetime) should be
* able to be specified.
*/
static void
add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
{
struct prefix *prefix;
- u_char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
if ((prefix = malloc(sizeof(*prefix))) == NULL) {
syslog(LOG_ERR, "<%s> memory allocation failed",
- __FUNCTION__);
+ __func__);
return; /* XXX: error or exit? */
}
memset(prefix, 0, sizeof(*prefix));
prefix->origin = PREFIX_FROM_DYNAMIC;
insque(prefix, &rai->prefix);
+ prefix->rainfo = rai;
syslog(LOG_DEBUG, "<%s> new prefix %s/%d was added on %s",
- __FUNCTION__, inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ __func__, inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr,
+ ntopbuf, INET6_ADDRSTRLEN),
ipr->ipr_plen, rai->ifname);
/* free the previous packet */
/* reconstruct the packet */
rai->pfxs++;
make_packet(rai);
-
- /*
- * reset the timer so that the new prefix will be advertised quickly.
- */
- rai->initcounter = 0;
- ra_timer_update((void *)rai, &rai->timer->tm);
- rtadvd_set_timer(&rai->timer->tm, rai->timer);
}
/*
* The prefix must be in the list.
*/
void
-delete_prefix(struct rainfo *rai, struct prefix *prefix)
+delete_prefix(struct prefix *prefix)
{
- u_char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
+ struct rainfo *rai = prefix->rainfo;
remque(prefix);
syslog(LOG_DEBUG, "<%s> prefix %s/%d was deleted on %s",
- __FUNCTION__, inet_ntop(AF_INET6, &prefix->prefix,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ __func__, inet_ntop(AF_INET6, &prefix->prefix,
+ ntopbuf, INET6_ADDRSTRLEN),
prefix->prefixlen, rai->ifname);
+ if (prefix->timer)
+ rtadvd_remove_timer(&prefix->timer);
free(prefix);
rai->pfxs--;
- make_packet(rai);
+}
+
+void
+invalidate_prefix(struct prefix *prefix)
+{
+ char ntopbuf[INET6_ADDRSTRLEN];
+ struct timeval timo;
+ struct rainfo *rai = prefix->rainfo;
+
+ if (prefix->timer) { /* sanity check */
+ syslog(LOG_ERR,
+ "<%s> assumption failure: timer already exists",
+ __func__);
+ exit(1);
+ }
+
+ syslog(LOG_DEBUG, "<%s> prefix %s/%d was invalidated on %s, "
+ "will expire in %ld seconds", __func__,
+ inet_ntop(AF_INET6, &prefix->prefix, ntopbuf, INET6_ADDRSTRLEN),
+ prefix->prefixlen, rai->ifname, (long)prefix_timo);
+
+ /* set the expiration timer */
+ prefix->timer = rtadvd_add_timer(prefix_timeout, NULL, prefix, NULL);
+ if (prefix->timer == NULL) {
+ syslog(LOG_ERR, "<%s> failed to add a timer for a prefix. "
+ "remove the prefix", __func__);
+ delete_prefix(prefix);
+ }
+ timo.tv_sec = prefix_timo;
+ timo.tv_usec = 0;
+ rtadvd_set_timer(&timo, prefix->timer);
+}
+
+static struct rtadvd_timer *
+prefix_timeout(void *arg)
+{
+ struct prefix *prefix = (struct prefix *)arg;
+
+ delete_prefix(prefix);
+
+ return(NULL);
+}
+
+void
+update_prefix(struct prefix * prefix)
+{
+ char ntopbuf[INET6_ADDRSTRLEN];
+ struct rainfo *rai = prefix->rainfo;
+
+ if (prefix->timer == NULL) { /* sanity check */
+ syslog(LOG_ERR,
+ "<%s> assumption failure: timer does not exist",
+ __func__);
+ exit(1);
+ }
+
+ syslog(LOG_DEBUG, "<%s> prefix %s/%d was re-enabled on %s",
+ __func__, inet_ntop(AF_INET6, &prefix->prefix, ntopbuf,
+ INET6_ADDRSTRLEN), prefix->prefixlen, rai->ifname);
+
+ /* stop the expiration timer */
+ rtadvd_remove_timer(&prefix->timer);
}
/*
static int
init_prefix(struct in6_prefixreq *ipr)
{
+#if 0
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "<%s> socket: %s", __FUNCTION__,
+ syslog(LOG_ERR, "<%s> socket: %s", __func__,
strerror(errno));
exit(1);
}
if (ioctl(s, SIOCGIFPREFIX_IN6, (caddr_t)ipr) < 0) {
- syslog(LOG_INFO, "<%s> ioctl:SIOCGIFPREFIX %s", __FUNCTION__,
+ syslog(LOG_INFO, "<%s> ioctl:SIOCGIFPREFIX %s", __func__,
strerror(errno));
ipr->ipr_vltime = DEF_ADVVALIDLIFETIME;
/* omit other field initialization */
}
else if (ipr->ipr_origin < PR_ORIG_RR) {
- u_char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
syslog(LOG_WARNING, "<%s> Added prefix(%s)'s origin %d is"
"lower than PR_ORIG_RR(router renumbering)."
- "This should not happen if I am router", __FUNCTION__,
- inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr, (char *)ntopbuf,
+ "This should not happen if I am router", __func__,
+ inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr, ntopbuf,
sizeof(ntopbuf)), ipr->ipr_origin);
close(s);
return 1;
close(s);
return 0;
+#else
+ ipr->ipr_vltime = DEF_ADVVALIDLIFETIME;
+ ipr->ipr_pltime = DEF_ADVPREFERREDLIFETIME;
+ ipr->ipr_raf_onlink = 1;
+ ipr->ipr_raf_auto = 1;
+ return 0;
+#endif
}
void
memset(&ipr, 0, sizeof(ipr));
if (if_indextoname(ifindex, ipr.ipr_name) == NULL) {
syslog(LOG_ERR, "<%s> Prefix added interface No.%d doesn't"
- "exist. This should not happen! %s", __FUNCTION__,
+ "exist. This should not happen! %s", __func__,
ifindex, strerror(errno));
exit(1);
}
make_packet(struct rainfo *rainfo)
{
size_t packlen, lladdroptlen = 0;
- char *buf;
+ u_char *buf;
struct nd_router_advert *ra;
struct nd_opt_prefix_info *ndopt_pi;
struct nd_opt_mtu *ndopt_mtu;
-#ifdef MIP6
- struct nd_opt_advinterval *ndopt_advint;
- struct nd_opt_homeagent_info *ndopt_hai;
-#endif
+#ifdef ROUTEINFO
struct nd_opt_route_info *ndopt_rti;
- struct prefix *pfx;
struct rtinfo *rti;
+#endif
+ struct prefix *pfx;
/* calculate total length */
packlen = sizeof(struct nd_router_advert);
if ((lladdroptlen = lladdropt_length(rainfo->sdl)) == 0) {
syslog(LOG_INFO,
"<%s> link-layer address option has"
- " null length on %s."
- " Treat as not included.",
- __FUNCTION__, rainfo->ifname);
+ " null length on %s. Treat as not included.",
+ __func__, rainfo->ifname);
rainfo->advlinkopt = 0;
}
packlen += lladdroptlen;
packlen += sizeof(struct nd_opt_prefix_info) * rainfo->pfxs;
if (rainfo->linkmtu)
packlen += sizeof(struct nd_opt_mtu);
-#ifdef MIP6
- if (mobileip6 && rainfo->maxinterval)
- packlen += sizeof(struct nd_opt_advinterval);
- if (mobileip6 && rainfo->hatime)
- packlen += sizeof(struct nd_opt_homeagent_info);
-#endif
-#ifdef ND_OPT_ROUTE_INFO
+#ifdef ROUTEINFO
for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next)
packlen += sizeof(struct nd_opt_route_info) +
((rti->prefixlen + 0x3f) >> 6) * 8;
if (rainfo->rdnss_length > 0)
packlen += 8 + sizeof(struct in6_addr) * rainfo->rdnss_length;
+ if (rainfo->dnssl_length > 0) {
+ packlen += rainfo->dnssl_option_length;
+ }
+
/* allocate memory for the packet */
if ((buf = malloc(packlen)) == NULL) {
syslog(LOG_ERR,
"<%s> can't get enough memory for an RA packet",
- __FUNCTION__);
+ __func__);
exit(1);
}
if (rainfo->ra_data) {
free(rainfo->ra_data);
rainfo->ra_data = NULL;
}
- rainfo->ra_data = (u_char *)buf;
+ rainfo->ra_data = buf;
/* XXX: what if packlen > 576? */
rainfo->ra_datalen = packlen;
rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0;
ra->nd_ra_flags_reserved |=
rainfo->otherflg ? ND_RA_FLAG_OTHER : 0;
-#ifdef MIP6
- ra->nd_ra_flags_reserved |=
- rainfo->haflg ? ND_RA_FLAG_HA : 0;
-#endif
ra->nd_ra_router_lifetime = htons(rainfo->lifetime);
ra->nd_ra_reachable = htonl(rainfo->reachabletime);
ra->nd_ra_retransmit = htonl(rainfo->retranstimer);
buf += sizeof(struct nd_opt_mtu);
}
-#ifdef MIP6
- if (mobileip6 && rainfo->maxinterval) {
- ndopt_advint = (struct nd_opt_advinterval *)buf;
- ndopt_advint->nd_opt_adv_type = ND_OPT_ADVINTERVAL;
- ndopt_advint->nd_opt_adv_len = 1;
- ndopt_advint->nd_opt_adv_reserved = 0;
- ndopt_advint->nd_opt_adv_interval = htonl(rainfo->maxinterval *
- 1000);
- buf += sizeof(struct nd_opt_advinterval);
- }
-#endif
-
-#ifdef MIP6
- if (rainfo->hatime) {
- ndopt_hai = (struct nd_opt_homeagent_info *)buf;
- ndopt_hai->nd_opt_hai_type = ND_OPT_HOMEAGENT_INFO;
- ndopt_hai->nd_opt_hai_len = 1;
- ndopt_hai->nd_opt_hai_reserved = 0;
- ndopt_hai->nd_opt_hai_preference = htons(rainfo->hapref);
- ndopt_hai->nd_opt_hai_lifetime = htons(rainfo->hatime);
- buf += sizeof(struct nd_opt_homeagent_info);
- }
-#endif
-
for (pfx = rainfo->prefix.next;
pfx != &rainfo->prefix; pfx = pfx->next) {
u_int32_t vltime, pltime;
if (pfx->autoconfflg)
ndopt_pi->nd_opt_pi_flags_reserved |=
ND_OPT_PI_FLAG_AUTO;
-#ifdef MIP6
- if (pfx->routeraddr)
- ndopt_pi->nd_opt_pi_flags_reserved |=
- ND_OPT_PI_FLAG_ROUTER;
-#endif
- if (pfx->vltimeexpire || pfx->pltimeexpire)
- gettimeofday(&now, NULL);
- if (pfx->vltimeexpire == 0)
- vltime = pfx->validlifetime;
- else
- vltime = (pfx->vltimeexpire > now.tv_sec) ?
- pfx->vltimeexpire - now.tv_sec : 0;
- if (pfx->pltimeexpire == 0)
- pltime = pfx->preflifetime;
- else
- pltime = (pfx->pltimeexpire > now.tv_sec) ?
- pfx->pltimeexpire - now.tv_sec : 0;
+ if (pfx->timer)
+ vltime = 0;
+ else {
+ if (pfx->vltimeexpire || pfx->pltimeexpire)
+ gettimeofday(&now, NULL);
+ if (pfx->vltimeexpire == 0)
+ vltime = pfx->validlifetime;
+ else
+ vltime = (pfx->vltimeexpire > now.tv_sec) ?
+ pfx->vltimeexpire - now.tv_sec : 0;
+ }
+ if (pfx->timer)
+ pltime = 0;
+ else {
+ if (pfx->pltimeexpire == 0)
+ pltime = pfx->preflifetime;
+ else
+ pltime = (pfx->pltimeexpire > now.tv_sec) ?
+ pfx->pltimeexpire - now.tv_sec : 0;
+ }
if (vltime < pltime) {
/*
* this can happen if vltime is decrement but pltime
buf += sizeof(struct nd_opt_prefix_info);
}
-#ifdef ND_OPT_ROUTE_INFO
+#ifdef ROUTEINFO
for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) {
u_int8_t psize = (rti->prefixlen + 0x3f) >> 6;
ndopt_rti->nd_opt_rti_len = 1 + psize;
ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen;
ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref;
- ndopt_rti->nd_opt_rti_lifetime = rti->ltime;
+ ndopt_rti->nd_opt_rti_lifetime = htonl(rti->ltime);
memcpy(ndopt_rti + 1, &rti->prefix, psize * 8);
buf += sizeof(struct nd_opt_route_info) + psize * 8;
}
}
}
+ if (rainfo->dnssl_length > 0) {
+ struct nd_opt_dnssl * dnssl_opt;
+ struct dnssl * dnssl;
+ int domains_length = 0;
+ u_char * cursor = buf;
+
+ memset(cursor, 0, rainfo->dnssl_option_length);
+
+ dnssl_opt = (struct nd_opt_dnssl *)cursor;
+ dnssl_opt->nd_opt_dnssl_type = ND_OPT_DNSSL;
+ /*
+ * Length is in units of 8 octets. Divide total byte length
+ * of the option by 8.
+ */
+ dnssl_opt->nd_opt_dnssl_len = rainfo->dnssl_option_length >> 3;
+ dnssl_opt->nd_opt_dnssl_reserved = 0;
+ dnssl_opt->nd_opt_dnssl_lifetime =
+ htonl(rainfo->dnssl_lifetime);
+
+ cursor += offsetof(struct nd_opt_dnssl, nd_opt_dnssl_domains);
+
+ for (dnssl = rainfo->dnssl_list.next;
+ dnssl != &rainfo->dnssl_list;
+ dnssl = dnssl->next)
+ {
+ int encodeLen = encode_domain(dnssl->domain, cursor);
+ cursor += encodeLen;
+ domains_length += encodeLen;
+ }
+
+ buf += rainfo->dnssl_option_length;
+ }
+
return;
}
if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0)
< 0) {
syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s",
- __FUNCTION__, code,
+ __func__, code,
strerror(errno));
return(-1);
}
else
return(value);
}
+
+/*
+ * Encode a domain name into a buffer according to the rules in RFC 1035 section
+ * 3.1. Do not use the compression techniques outlined in section 4.1.4.
+ */
+int
+encode_domain(char *domain, u_char *dst)
+{
+ char *domainCopy = strdup(domain);
+ char *input = domainCopy;
+ char *label;
+ u_char *cursor = dst;
+
+ while ((label = strsep(&input, ".")) != NULL) {
+ int label_len = strlen(label) & 0x3f; /* Max length is 63 */
+ if (label_len > 0) {
+ *cursor = (u_char)label_len;
+ cursor++;
+ memcpy(cursor, label, label_len);
+ cursor += label_len;
+ }
+ }
+ *cursor = 0;
+ cursor++;
+
+ free(domainCopy);
+
+ return (cursor - dst);
+}
-/* $KAME: config.h,v 1.3 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: config.h,v 1.8 2003/06/17 08:26:22 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/config.h,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
-extern void getconfig __P((char *));
-extern void delete_prefix __P((struct rainfo *, struct prefix *));
-extern void make_prefix __P((struct rainfo *, int, struct in6_addr *, int));
-extern void make_packet __P((struct rainfo *));
+extern void getconfig(char *);
+extern void delete_prefix(struct prefix *);
+extern void invalidate_prefix(struct prefix *);
+extern void update_prefix(struct prefix *);
+extern void make_prefix(struct rainfo *, int, struct in6_addr *, int);
+extern void make_packet(struct rainfo *);
+extern void get_prefix(struct rainfo *);
+
+
+/*
+ * it is highly unlikely to have 100 prefix information options,
+ * so it should be okay to limit it
+ */
+#define MAXPREFIX 100
+#define MAXROUTE 100
/*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-/* $KAME: dump.c,v 1.16 2001/03/21 17:41:13 jinmei Exp $ */
+/* $KAME: dump.c,v 1.32 2003/05/19 09:46:50 keiichi Exp $ */
/*
* Copyright (C) 2000 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/dump.c,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
-#endif /* __FreeBSD__ >= 3 */
#include <net/if_dl.h>
#include <netinet/in.h>
extern struct rainfo *ralist;
-static char *ether_str __P((struct sockaddr_dl *));
-static void if_dump __P((void));
-
-#ifdef __FreeBSD__ /* XXX: see PORTABILITY */
-#define LONGLONG "%qu"
-#else
-#define LONGLONG "%llu"
-#endif
+static char *ether_str(struct sockaddr_dl *);
+static void if_dump(void);
static char *rtpref_str[] = {
"medium", /* 00 */
ether_str(sdl)
struct sockaddr_dl *sdl;
{
- static char ebuf[32];
+ static char hbuf[32];
u_char *cp;
if (sdl->sdl_alen && sdl->sdl_alen > 5) {
cp = (u_char *)LLADDR(sdl);
- snprintf(ebuf, sizeof(ebuf), "%x:%x:%x:%x:%x:%x",
+ snprintf(hbuf, sizeof(hbuf), "%x:%x:%x:%x:%x:%x",
cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
- }
- else {
- snprintf(ebuf, sizeof(ebuf), "NONE");
- }
+ } else
+ snprintf(hbuf, sizeof(hbuf), "NONE");
- return(ebuf);
+ return(hbuf);
}
static void
{
struct rainfo *rai;
struct prefix *pfx;
+#ifdef ROUTEINFO
+ struct rtinfo *rti;
+#endif
char prefixbuf[INET6_ADDRSTRLEN];
int first;
struct timeval now;
if (rai->lastsent.tv_sec) {
/* note that ctime() appends CR by itself */
fprintf(fp, " Last RA sent: %s",
- ctime((time_t *)&rai->lastsent.tv_sec));
+ ctime((time_t *)&rai->lastsent.tv_sec));
}
if (rai->timer) {
fprintf(fp, " Next RA will be sent: %s",
- ctime((time_t *)&rai->timer->tm.tv_sec));
+ ctime((time_t *)&rai->timer->tm.tv_sec));
}
else
fprintf(fp, " RA timer is stopped");
rai->waiting, rai->initcounter);
/* statistics */
- fprintf(fp,
- " statistics: RA(out/in/inconsistent): "
- LONGLONG "/" LONGLONG "/" LONGLONG ", ",
- (unsigned long long)rai->raoutput,
- (unsigned long long)rai->rainput,
- (unsigned long long)rai->rainconsistent);
- fprintf(fp, "RS(input): " LONGLONG "\n",
- (unsigned long long)rai->rsinput);
+ fprintf(fp, " statistics: RA(out/in/inconsistent): "
+ "%llu/%llu/%llu, ",
+ (unsigned long long)rai->raoutput,
+ (unsigned long long)rai->rainput,
+ (unsigned long long)rai->rainconsistent);
+ fprintf(fp, "RS(input): %llu\n",
+ (unsigned long long)rai->rsinput);
/* interface information */
if (rai->advlinkopt)
fprintf(fp, " Link-layer address: %s\n",
- ether_str(rai->sdl));
+ ether_str(rai->sdl));
fprintf(fp, " MTU: %d\n", rai->phymtu);
/* Router configuration variables */
- fprintf(fp,
- " DefaultLifetime: %d, MaxAdvInterval: %d, "
- "MinAdvInterval: %d\n",
- rai->lifetime, rai->maxinterval, rai->mininterval);
+ fprintf(fp, " DefaultLifetime: %d, MaxAdvInterval: %d, "
+ "MinAdvInterval: %d\n", rai->lifetime, rai->maxinterval,
+ rai->mininterval);
fprintf(fp, " Flags: %s%s%s, ",
- rai->managedflg ? "M" : "", rai->otherflg ? "O" : "",
-#ifdef MIP6
- rai->haflg ? "H" :
-#endif
- "");
+ rai->managedflg ? "M" : "", rai->otherflg ? "O" : "", "");
fprintf(fp, "Preference: %s, ",
rtpref_str[(rai->rtpref >> 3) & 0xff]);
fprintf(fp, "MTU: %d\n", rai->linkmtu);
fprintf(fp, " ReachableTime: %d, RetransTimer: %d, "
"CurHopLimit: %d\n", rai->reachabletime,
rai->retranstimer, rai->hoplimit);
-#ifdef MIP6
- fprintf(fp, " HAPreference: %d, HALifetime: %d\n",
- rai->hapref, rai->hatime);
-#endif
-
if (rai->clockskew)
fprintf(fp, " Clock skew: %ldsec\n",
- rai->clockskew);
+ rai->clockskew);
for (first = 1, pfx = rai->prefix.next; pfx != &rai->prefix;
pfx = pfx->next) {
if (first) {
first = 0;
}
fprintf(fp, " %s/%d(",
- inet_ntop(AF_INET6, &pfx->prefix,
- prefixbuf, sizeof(prefixbuf)),
- pfx->prefixlen);
- switch(pfx->origin) {
+ inet_ntop(AF_INET6, &pfx->prefix, prefixbuf,
+ sizeof(prefixbuf)), pfx->prefixlen);
+ switch (pfx->origin) {
case PREFIX_FROM_KERNEL:
fprintf(fp, "KERNEL, ");
break;
fprintf(fp, "flags: %s%s%s",
pfx->onlinkflg ? "L" : "",
pfx->autoconfflg ? "A" : "",
-#ifdef MIP6
- pfx->routeraddr ? "R" :
-#endif
"");
+ if (pfx->timer) {
+ struct timeval *rest;
+
+ rest = rtadvd_timer_rest(pfx->timer);
+ if (rest) { /* XXX: what if not? */
+ fprintf(fp, ", expire in: %ld",
+ (long)rest->tv_sec);
+ }
+ }
+ fprintf(fp, ")\n");
+ }
+#ifdef ROUTEINFO
+ for (first = 1, rti = rai->route.next; rti != &rai->route;
+ rti = rti->next) {
+ if (first) {
+ fprintf(fp, " Route Information:\n");
+ first = 0;
+ }
+ fprintf(fp, " %s/%d (",
+ inet_ntop(AF_INET6, &rti->prefix,
+ prefixbuf, sizeof(prefixbuf)),
+ rti->prefixlen);
+ fprintf(fp, "preference: %s, ",
+ rtpref_str[0xff & (rti->rtpref >> 3)]);
+ if (rti->ltime == ND6_INFINITE_LIFETIME)
+ fprintf(fp, "lifetime: infinity");
+ else
+ fprintf(fp, "lifetime: %ld", (long)rti->ltime);
fprintf(fp, ")\n");
}
+#endif
}
}
rtadvd_dump_file(dumpfile)
char *dumpfile;
{
+ syslog(LOG_DEBUG, "<%s> dump current status to %s", __func__,
+ dumpfile);
+
if ((fp = fopen(dumpfile, "w")) == NULL) {
syslog(LOG_WARNING, "<%s> open a dump file(%s)",
- __FUNCTION__, dumpfile);
+ __func__, dumpfile);
return;
}
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/dump.h,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
-extern void rtadvd_dump_file __P((char *));
+extern void rtadvd_dump_file(char *);
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/if.c,v 1.2.2.3 2001/07/03 11:02:14 ume Exp $
*/
#include <sys/param.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_types.h>
-#if defined(__FreeBSD__) || defined (__APPLE__)
-# include <net/ethernet.h>
-#endif
+#include <net/ethernet.h>
#include <ifaddrs.h>
-#ifdef __NetBSD__
-#include <net/if_ether.h>
-#endif
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
-#ifdef __bsdi__
-# include <netinet/if_ether.h>
-#endif
-#ifdef __OpenBSD__
-#include <netinet/if_ether.h>
-#endif
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
size_t ifblock_size;
char *ifblock;
-static void get_iflist __P((char **buf, size_t *size));
-static void parse_iflist __P((struct if_msghdr ***ifmlist_p, char *buf,
- size_t bufsize));
+static void get_iflist(char **buf, size_t *size);
+static void parse_iflist(struct if_msghdr ***ifmlist_p, char *buf,
+ size_t bufsize);
static void
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
size_t len;
struct if_msghdr *ifm;
struct sockaddr *sa, *rti_info[RTAX_MAX];
- struct sockaddr_dl *sdl = NULL, *ret_sdl = NULL;
+ struct sockaddr_dl *sdl = NULL, *ret_sdl;
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
return(NULL);
if ((buf = malloc(len)) == NULL)
return(NULL);
- if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
- goto end;
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ free(buf);
+ return(NULL);
+ }
lim = buf + len;
for (next = buf; next < lim; next += ifm->ifm_msglen) {
}
if (next == lim) {
/* search failed */
- goto end;
+ free(buf);
+ return(NULL);
}
if ((ret_sdl = malloc(sdl->sdl_len)) == NULL)
end:
free(buf);
- return (ret_sdl);
+ return(ret_sdl);
}
int
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "<%s> socket: %s", __FUNCTION__,
+ syslog(LOG_ERR, "<%s> socket: %s", __func__,
strerror(errno));
return (oifflags & ~IFF_UP);
}
if_indextoname(ifindex, ifr.ifr_name);
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
syslog(LOG_ERR, "<%s> ioctl:SIOCGIFFLAGS: failed for %s",
- __FUNCTION__, ifr.ifr_name);
+ __func__, ifr.ifr_name);
close(s);
return (oifflags & ~IFF_UP);
}
int
lladdropt_length(struct sockaddr_dl *sdl)
{
- switch(sdl->sdl_type) {
- case IFT_ETHER:
- return(ROUNDUP8(ETHER_ADDR_LEN + 2));
- default:
- return(0);
+ switch (sdl->sdl_type) {
+ case IFT_ETHER:
+ return(ROUNDUP8(ETHER_ADDR_LEN + 2));
+ default:
+ return(0);
}
}
ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */
- switch(sdl->sdl_type) {
- case IFT_ETHER:
- ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
- addr = (char *)(ndopt + 1);
- memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
- break;
- default:
- syslog(LOG_ERR,
- "<%s> unsupported link type(%d)",
- __FUNCTION__, sdl->sdl_type);
- exit(1);
+ switch (sdl->sdl_type) {
+ case IFT_ETHER:
+ ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
+ addr = (char *)(ndopt + 1);
+ memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
+ break;
+ default:
+ syslog(LOG_ERR, "<%s> unsupported link type(%d)",
+ __func__, sdl->sdl_type);
+ exit(1);
}
return;
/* just for safety */
if (!rtm->rtm_msglen) {
syslog(LOG_WARNING, "<%s> rtm_msglen is 0 "
- "(buf=%p lim=%p rtm=%p)", __FUNCTION__,
+ "(buf=%p lim=%p rtm=%p)", __func__,
buf, lim, rtm);
break;
}
if (sysctl(mib, 6, NULL, size, NULL, 0) < 0) {
syslog(LOG_ERR, "<%s> sysctl: iflist size get failed",
- __FUNCTION__);
+ __func__);
exit(1);
}
if ((*buf = malloc(*size)) == NULL) {
- syslog(LOG_ERR, "<%s> malloc failed", __FUNCTION__);
+ syslog(LOG_ERR, "<%s> malloc failed", __func__);
exit(1);
}
if (sysctl(mib, 6, *buf, size, NULL, 0) < 0) {
syslog(LOG_ERR, "<%s> sysctl: iflist get failed",
- __FUNCTION__);
+ __func__);
exit(1);
}
return;
/* roughly estimate max list size of pointers to each if_msghdr */
malloc_size = (bufsize/iflentry_size) * sizeof(size_t);
if ((*ifmlist_p = (struct if_msghdr **)malloc(malloc_size)) == NULL) {
- syslog(LOG_ERR, "<%s> malloc failed", __FUNCTION__);
+ syslog(LOG_ERR, "<%s> malloc failed", __func__);
exit(1);
}
for (ifm = (struct if_msghdr *)buf; ifm < (struct if_msghdr *)lim;) {
if (ifm->ifm_msglen == 0) {
syslog(LOG_WARNING, "<%s> ifm_msglen is 0 "
- "(buf=%p lim=%p ifm=%p)", __FUNCTION__,
+ "(buf=%p lim=%p ifm=%p)", __func__,
buf, lim, ifm);
return;
}
/* just for safety */
if (!ifam->ifam_msglen) {
syslog(LOG_WARNING, "<%s> ifa_msglen is 0 "
- "(buf=%p lim=%p ifam=%p)", __FUNCTION__,
+ "(buf=%p lim=%p ifam=%p)", __func__,
buf, lim, ifam);
return;
}
-/* $KAME: if.h,v 1.6 2001/01/21 15:37:14 itojun Exp $ */
+/* $KAME: if.h,v 1.10 2003/02/24 11:29:10 ono Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/if.h,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
#define RTADV_TYPE2BITMASK(type) (0x1 << type)
extern char *ifblock;
struct nd_opt_hdr;
-struct sockaddr_dl *if_nametosdl __P((char *));
-int if_getmtu __P((char *));
-int if_getflags __P((int, int));
-int lladdropt_length __P((struct sockaddr_dl *));
-void lladdropt_fill __P((struct sockaddr_dl *, struct nd_opt_hdr *));
-int rtbuf_len __P((void));
-char *get_next_msg __P((char *, char *, int, size_t *, int));
-struct in6_addr *get_addr __P((char *));
-int get_rtm_ifindex __P((char *));
-int get_ifm_ifindex __P((char *));
-int get_ifam_ifindex __P((char *));
-int get_ifm_flags __P((char *));
-int get_prefixlen __P((char *));
-int prefixlen __P((u_char *, u_char *));
-int rtmsg_type __P((char *));
-int ifmsg_type __P((char *));
-int rtmsg_len __P((char *));
-int ifmsg_len __P((char *));
-void init_iflist __P((void));
+struct sockaddr_dl *if_nametosdl(char *);
+int if_getmtu(char *);
+int if_getflags(int, int);
+int lladdropt_length(struct sockaddr_dl *);
+void lladdropt_fill(struct sockaddr_dl *, struct nd_opt_hdr *);
+int rtbuf_len(void);
+char *get_next_msg(char *, char *, int, size_t *, int);
+struct in6_addr *get_addr(char *);
+int get_rtm_ifindex(char *);
+int get_ifm_ifindex(char *);
+int get_ifam_ifindex(char *);
+int get_ifm_flags(char *);
+int get_prefixlen(char *);
+int prefixlen(u_char *, u_char *);
+int rtmsg_type(char *);
+int ifmsg_type(char *);
+int rtmsg_len(char *);
+int ifmsg_len(char *);
+void init_iflist(void);
-/* $KAME: rrenum.c,v 1.10 2001/01/21 15:32:16 itojun Exp $ */
+/* $KAME: rrenum.c,v 1.12 2002/06/10 19:59:47 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/rrenum.c,v 1.2.2.2 2001/07/03 11:02:14 ume Exp $
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
-#endif /* __FreeBSD__ >= 3 */
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
if ((rpm->rpm_len - 3) < 0 || /* must be at least 3 */
(rpm->rpm_len - 3) & 0x3) { /* must be multiple of 4 */
syslog(LOG_WARNING, "<%s> rpm_len %d is not 4N * 3",
- __FUNCTION__, rpm->rpm_len);
+ __func__, rpm->rpm_len);
return 1;
}
/* rpm->rpm_code must be valid value */
- switch(rpm->rpm_code) {
+ switch (rpm->rpm_code) {
case RPM_PCO_ADD:
case RPM_PCO_CHANGE:
case RPM_PCO_SETGLOBAL:
break;
default:
- syslog(LOG_WARNING, "<%s> unknown rpm_code %d", __FUNCTION__,
+ syslog(LOG_WARNING, "<%s> unknown rpm_code %d", __func__,
rpm->rpm_code);
return 1;
}
/* rpm->rpm_matchlen must be 0 to 128 inclusive */
if (rpm->rpm_matchlen > 128) {
syslog(LOG_WARNING, "<%s> rpm_matchlen %d is over 128",
- __FUNCTION__, rpm->rpm_matchlen);
+ __func__, rpm->rpm_matchlen);
return 1;
}
if (checklen > 128) {
syslog(LOG_WARNING, "<%s> sum of rpu_uselen %d and"
" rpu_keeplen %d is %d(over 128)",
- __FUNCTION__, rpu->rpu_uselen,
+ __func__, rpu->rpu_uselen,
rpu->rpu_keeplen,
rpu->rpu_uselen + rpu->rpu_keeplen);
return 1;
irr->irr_useprefix.sin6_addr = in6addr_any;
if (ioctl(s, rrcmd2pco[rpm->rpm_code], (caddr_t)irr) < 0 &&
errno != EADDRNOTAVAIL)
- syslog(LOG_ERR, "<%s> ioctl: %s", __FUNCTION__,
+ syslog(LOG_ERR, "<%s> ioctl: %s", __func__,
strerror(errno));
return;
}
irr->irr_u_uselen = rpu->rpu_uselen;
irr->irr_u_keeplen = rpu->rpu_keeplen;
irr->irr_raf_mask_onlink =
- (rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK) == 0 ? 0 : 1;
+ !!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK);
irr->irr_raf_mask_auto =
- (rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? 0 : 1;
+ !!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_AUTO);
irr->irr_vltime = ntohl(rpu->rpu_vltime);
irr->irr_pltime = ntohl(rpu->rpu_pltime);
irr->irr_raf_onlink =
if (ioctl(s, rrcmd2pco[rpm->rpm_code], (caddr_t)irr) < 0 &&
errno != EADDRNOTAVAIL)
- syslog(LOG_ERR, "<%s> ioctl: %s", __FUNCTION__,
+ syslog(LOG_ERR, "<%s> ioctl: %s", __func__,
strerror(errno));
/* very adhoc: should be rewritten */
return 1;
if (s == -1 && (s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "<%s> socket: %s", __FUNCTION__,
+ syslog(LOG_ERR, "<%s> socket: %s", __func__,
strerror(errno));
exit(1);
}
if (errno == ENXIO)
return 0;
else if (errno) {
- syslog(LOG_ERR, "<%s> if_indextoname: %s", __FUNCTION__,
+ syslog(LOG_ERR, "<%s> if_indextoname: %s", __func__,
strerror(errno));
return 1;
}
if (len < sizeof(struct rr_pco_match)) {
tooshort:
syslog(LOG_ERR, "<%s> pkt too short. left len = %d. "
- "gabage at end of pkt?", __FUNCTION__, len);
+ "gabage at end of pkt?", __func__, len);
return 1;
}
rpmlen = rpm->rpm_len << 3;
goto tooshort;
if (do_pco(rr, rpmlen, rpm)) {
- syslog(LOG_WARNING, "<%s> invalid PCO", __FUNCTION__);
+ syslog(LOG_WARNING, "<%s> invalid PCO", __func__);
goto next;
}
rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from,
struct in6_addr *dst)
{
- u_char ntopbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN];
/* omit rr minimal length check. hope kernel have done it. */
/* rr_command length check */
if (len < (sizeof(struct icmp6_router_renum) +
sizeof(struct rr_pco_match))) {
syslog(LOG_ERR, "<%s> rr_command len %d is too short",
- __FUNCTION__, len);
+ __func__, len);
return 1;
}
if (IN6_IS_ADDR_MULTICAST(dst) && !IN6_IS_ADDR_MC_LINKLOCAL(dst) &&
!IN6_IS_ADDR_MC_SITELOCAL(dst)) {
syslog(LOG_ERR, "<%s> dst mcast addr %s is illegal",
- __FUNCTION__,
- inet_ntop(AF_INET6, dst, (char *)ntopbuf, INET6_ADDRSTRLEN));
+ __func__,
+ inet_ntop(AF_INET6, dst, ntopbuf, INET6_ADDRSTRLEN));
return 1;
}
if (rro.rro_seqnum > rr->rr_seqnum) {
syslog(LOG_WARNING,
"<%s> rcvd old seqnum %d from %s",
- __FUNCTION__, (u_int32_t)ntohl(rr->rr_seqnum),
- inet_ntop(AF_INET6, from, (char *)ntopbuf, INET6_ADDRSTRLEN));
+ __func__, (u_int32_t)ntohl(rr->rr_seqnum),
+ inet_ntop(AF_INET6, from, ntopbuf, INET6_ADDRSTRLEN));
return 1;
}
if (rro.rro_seqnum == rr->rr_seqnum &&
if ((rr->rr_flags & ICMP6_RR_FLAGS_REQRESULT) != 0)
syslog(LOG_WARNING,
"<%s> rcvd duped segnum %d from %s",
- __FUNCTION__, rr->rr_segnum,
- inet_ntop(AF_INET6, from, (char *)ntopbuf,
+ __func__, rr->rr_segnum,
+ inet_ntop(AF_INET6, from, ntopbuf,
INET6_ADDRSTRLEN));
return 0;
}
return;
failed:
- syslog(LOG_ERR, "<%s> received RR was invalid", __FUNCTION__);
+ syslog(LOG_ERR, "<%s> received RR was invalid", __func__);
return;
}
rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi,
struct sockaddr_in6 *from, struct in6_addr *dst)
{
- u_char ntopbuf[2][INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
+ char ntopbuf[2][INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
syslog(LOG_DEBUG,
"<%s> RR received from %s to %s on %s",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf[0], INET6_ADDRSTRLEN),
- inet_ntop(AF_INET6, &dst, (char *)ntopbuf[1], INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf[0], INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
/* packet validation based on Section 4.1 of RFC2894 */
if (len < sizeof(struct icmp6_router_renum)) {
syslog(LOG_NOTICE,
"<%s>: RR short message (size %d) from %s to %s on %s",
- __FUNCTION__, len,
+ __func__, len,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf[0], INET6_ADDRSTRLEN),
- inet_ntop(AF_INET6, &dst, (char *)ntopbuf[1], INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf[0], INET6_ADDRSTRLEN),
+ inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
syslog(LOG_NOTICE,
"<%s>: RR message with invalid destination (%s) "
"from %s on %s",
- __FUNCTION__,
- inet_ntop(AF_INET6, &dst, (char *)ntopbuf[0], INET6_ADDRSTRLEN),
+ __func__,
+ inet_ntop(AF_INET6, &dst, ntopbuf[0], INET6_ADDRSTRLEN),
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf[1], INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf[1], INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
break;
default:
syslog(LOG_ERR, "<%s> received unknown code %d",
- __FUNCTION__, rr->rr_code);
+ __func__, rr->rr_code);
break;
}
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/rrenum.h,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
-void rr_input __P((int, struct icmp6_router_renum *, struct in6_pktinfo *,
- struct sockaddr_in6 *, struct in6_addr *));
+void rr_input(int, struct icmp6_router_renum *, struct in6_pktinfo *,
+ struct sockaddr_in6 *, struct in6_addr *);
.\" $FreeBSD: src/usr.sbin/rtadvd/rtadvd.8,v 1.3.2.6 2001/08/16 15:56:30 ru Exp $
-.\" $KAME: rtadvd.8,v 1.17 2001/02/04 05:34:38 jinmei Exp $
+.\" $KAME: rtadvd.8,v 1.24 2002/05/31 16:16:08 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 17, 1998
+.Dd August 27, 2011
.Dt RTADVD 8
.Os
.Sh NAME
.Nm
.Op Fl dDfMRs
.Op Fl c Ar configfile
+.Op Fl F Ar dumpfile
+.Op Fl p Ar pidfile
.Ar interface ...
.Sh DESCRIPTION
.Nm
.Pp
.Nm
also watches the routing table.
-By default, if an interface direct route is
-added/deleted on an advertising interface and no static prefixes are
+If an interface direct route is
+added on an advertising interface and no static prefixes are
specified by the configuration file,
.Nm
-adds/deletes the corresponding prefix to/from its advertising list,
-respectively.
-The
-.Fl s
-option may be used to disable this behavior.
+adds the corresponding prefix to its advertising list.
+.Pp
+Similarly, when an interface direct route is deleted,
+.Nm
+will start advertising the prefixes with zero valid and preferred
+lifetimes to help the receiving hosts switch to a new prefix when
+renumbering.
+Note, however, that the zero valid lifetime cannot invalidate the
+autoconfigured addresses at a receiving host immediately.
+According to the specification, the host will retain the address
+for a certain period, which will typically be two hours.
+The zero lifetimes rather intend to make the address deprecated,
+indicating that a new non-deprecated address should be used as the
+source address of a new connection.
+This behavior will last for two hours.
+Then
+.Nm
+will completely remove the prefix from the advertising list,
+and succeeding advertisements will not contain the prefix information.
+.Pp
Moreover, if the status of an advertising interface changes,
.Nm
will start or stop sending router advertisements according
to the latest status.
.Pp
+The
+.Fl s
+option may be used to disable this behavior;
+.Nm
+will not watch the routing table and the whole functionality described
+above will be suppressed.
+.Pp
Basically, hosts MUST NOT send Router Advertisement messages at any
time (RFC 2461, Section 6.2.3).
However, it would sometimes be useful to allow hosts to advertise some
Even more debugging information is printed.
.It Fl f
Foreground mode (useful when debugging).
+Log messages will be dumped to stderr when this option is specified.
+.It Fl F
+Specify an alternative file in which to dump internal states when
+.Nm
+receives signal
+.Dv SIGUSR1 .
+The default is
+.Pa /var/run/rtadvd.dump .
.It Fl M
Specify an interface to join the all-routers site-local multicast group.
By default,
.Nm
-tries to join the first advertising interface appeared in the command
+tries to join the first advertising interface appearing on the command
line.
This option has meaning only with the
.Fl R
option, which enables routing renumbering protocol support.
-.\".It Fl m
-.\"Enables mobile IPv6 support.
-.\"This changes the content of router advertisement option, as well as
-.\"permitted configuration directives.
+.It Fl p
+Specify an alternative file in which to store the process ID.
+The default is
+.Pa /var/run/rtadvd.pid.
.It Fl R
Accept router renumbering requests.
If you enable it, certain IPsec setup is suggested for security reasons.
-On KAME-based systems,
-.Xr rrenumd 8
-generates router renumbering request packets.
This option is currently disabled, and is ignored by
.Nm
with a warning message.
.Dv SIGUSR1 ,
.Nm
will dump the current internal state into
-.Pa /var/run/rtadvd.dump .
+.Pa /var/run/rtadvd.dump
+or the file specified with option
+.Fl F .
.Pp
Use
.Dv SIGTERM
.Nm
will transmit router advertisement with router lifetime 0
to all the interfaces
-(in accordance with RFC2461 6.2.5).
-.Sh DIAGNOSTICS
-.Ex -std
+.Pq in accordance with RFC2461 6.2.5 .
.Sh FILES
.Bl -tag -width Pa -compact
.It Pa /etc/rtadvd.conf
The default configuration file.
.It Pa /var/run/rtadvd.pid
-contains the pid of the currently running
-.Nm .
+The default process ID file.
.It Pa /var/run/rtadvd.dump
-in which
+The default file in which
.Nm
dumps its internal state.
.El
+.Sh EXIT STATUS
+.Ex -std
.Sh SEE ALSO
.Xr rtadvd.conf 5 ,
-.Xr rrenumd 8 ,
.Xr rtsol 8
.Sh HISTORY
The
.Nm
-command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
-.Sh CAVEAT
+command first appeared in the WIDE Hydrangea IPv6 protocol stack kit.
+.Sh BUGS
There used to be some text that recommended users not to let
.Nm
advertise Router Advertisement messages on an upstream link to avoid
-/* $KAME: rtadvd.c,v 1.50 2001/02/04 06:15:15 itojun Exp $ */
+/* $KAME: rtadvd.c,v 1.82 2003/08/05 12:34:23 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/rtadvd.c,v 1.3.2.2 2001/07/03 11:02:14 ume Exp $
*/
#include <sys/param.h>
#include <stdlib.h>
#include <err.h>
#include <errno.h>
+#include <libutil.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
static size_t rcvcmsgbuflen;
static u_char *sndcmsgbuf = NULL;
static size_t sndcmsgbuflen;
-static int do_dump;
-static int do_die;
+volatile sig_atomic_t do_dump;
+volatile sig_atomic_t do_die;
struct msghdr sndmhdr;
struct iovec rcviov[2];
struct iovec sndiov[2];
-struct sockaddr_in6 from;
+struct sockaddr_in6 rcvfrom;
struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
struct in6_addr in6a_site_allrouters;
-static char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX: should be configurable */
-static char *pidfilename = "/var/run/rtadvd.pid"; /* should be configurable */
+static char *dumpfilename = "/var/run/rtadvd.dump";
+static char *pidfilename = "/var/run/rtadvd.pid";
+static struct pidfh *pfh;
static char *mcastif;
int sock;
int rtsock = -1;
-#ifdef MIP6
-int mobileip6 = 0;
-#endif
int accept_rr = 0;
int dflag = 0, sflag = 0;
+int so_traffic_class = SO_TC_CTL; /* use control class, by default */
-u_char *conffile = NULL;
+char *conffile = NULL;
struct rainfo *ralist = NULL;
struct nd_optlist {
struct nd_opt_hdr *opt;
};
union nd_opts {
- struct nd_opt_hdr *nd_opt_array[7];
+ struct nd_opt_hdr *nd_opt_array[9];
struct {
struct nd_opt_hdr *zero;
struct nd_opt_hdr *src_lladdr;
u_int32_t ndopt_flags[] = {
0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR,
- NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU
+ NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU,
};
-int main __P((int, char *[]));
-static void set_die __P((int));
-static void die __P((void));
-static void sock_open __P((void));
-static void rtsock_open __P((void));
-static void rtadvd_input __P((void));
-static void rs_input __P((int, struct nd_router_solicit *,
- struct in6_pktinfo *, struct sockaddr_in6 *));
-static void ra_input __P((int, struct nd_router_advert *,
- struct in6_pktinfo *, struct sockaddr_in6 *));
-static int prefix_check __P((struct nd_opt_prefix_info *, struct rainfo *,
- struct sockaddr_in6 *));
-static int nd6_options __P((struct nd_opt_hdr *, int,
- union nd_opts *, u_int32_t));
-static void free_ndopts __P((union nd_opts *));
-static void ra_output __P((struct rainfo *));
-static void rtmsg_input __P((void));
-static void rtadvd_set_dump_file __P((void));
-
-struct prefix *find_prefix __P((struct rainfo *, struct in6_addr *, int));
+int main(int, char *[]);
+static void set_die(int);
+static void die(void);
+static void sock_open(void);
+static void rtsock_open(void);
+static void rtadvd_input(void);
+static void rs_input(int, struct nd_router_solicit *,
+ struct in6_pktinfo *, struct sockaddr_in6 *);
+static void ra_input(int, struct nd_router_advert *,
+ struct in6_pktinfo *, struct sockaddr_in6 *);
+static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *,
+ struct sockaddr_in6 *);
+static int nd6_options(struct nd_opt_hdr *, int,
+ union nd_opts *, u_int32_t);
+static void free_ndopts(union nd_opts *);
+static void ra_output(struct rainfo *);
+static void rtmsg_input(void);
+static void rtadvd_set_dump_file(int);
+static void set_short_delay(struct rainfo *);
int
main(argc, argv)
int argc;
char *argv[];
{
- fd_set fdset;
+ fd_set *fdsetp, *selectfdp;
+ int fdmasks;
int maxfd = 0;
struct timeval *timeout;
int i, ch;
- int fflag = 0;
- FILE *pidfp;
- pid_t pid;
-
- openlog("rtadvd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
+ int fflag = 0, logopt;
+ pid_t pid, otherpid;
/* get command line options and arguments */
-#ifdef MIP6
-#define OPTIONS "c:dDfM:mRs"
-#else
-#define OPTIONS "c:dDfM:Rs"
-#endif
- while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
-#undef OPTIONS
- switch(ch) {
- case 'c':
- conffile = (u_char *)optarg;
- break;
- case 'd':
- dflag = 1;
- break;
- case 'D':
- dflag = 2;
- break;
- case 'f':
- fflag = 1;
- break;
+ while ((ch = getopt(argc, argv, "c:dDF:fMp:Rs")) != -1) {
+ switch (ch) {
+ case 'c':
+ conffile = optarg;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'D':
+ dflag = 2;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
case 'M':
mcastif = optarg;
break;
-#ifdef MIP6
- case 'm':
- mobileip6 = 1;
- break;
-#endif
- case 'R':
- fprintf(stderr, "rtadvd: "
- "the -R option is currently ignored.\n");
- /* accept_rr = 1; */
- /* run anyway... */
- break;
- case 's':
- sflag = 1;
- break;
+ case 'R':
+ fprintf(stderr, "rtadvd: "
+ "the -R option is currently ignored.\n");
+ /* accept_rr = 1; */
+ /* run anyway... */
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'p':
+ pidfilename = optarg;
+ break;
+ case 'F':
+ dumpfilename = optarg;
+ break;
}
}
argc -= optind;
argv += optind;
if (argc == 0) {
fprintf(stderr,
-#ifdef MIP6
- "usage: rtadvd [-dDfMmRs] [-c conffile] "
-#else
"usage: rtadvd [-dDfMRs] [-c conffile] "
-#endif
- "interfaces...\n");
+ "[-F dumpfile] [-p pidfile] interfaces...\n");
exit(1);
}
+ logopt = LOG_NDELAY | LOG_PID;
+ if (fflag)
+ logopt |= LOG_PERROR;
+ openlog("rtadvd", logopt, LOG_DAEMON);
+
/* set log level */
if (dflag == 0)
(void)setlogmask(LOG_UPTO(LOG_ERR));
fprintf(stderr, "fatal: inet_pton failed\n");
exit(1);
}
- sock_open();
+
+ pfh = pidfile_open(pidfilename, 0600, &otherpid);
+ if (pfh == NULL) {
+ if (errno == EEXIST)
+ errx(1, "%s already running, pid: %d",
+ getprogname(), otherpid);
+ syslog(LOG_ERR,
+ "<%s> failed to open the pid log file, run anyway.",
+ __func__);
+ }
if (!fflag)
daemon(1, 0);
+ sock_open();
+
/* record the current PID */
pid = getpid();
- if ((pidfp = fopen(pidfilename, "w")) == NULL)
- syslog(LOG_ERR,
- "<%s> failed to open a log file(%s), run anyway.",
- __FUNCTION__, pidfilename);
- else {
- fprintf(pidfp, "%d\n", pid);
- fclose(pidfp);
- }
+ pidfile_write(pfh);
- FD_ZERO(&fdset);
- FD_SET(sock, &fdset);
maxfd = sock;
if (sflag == 0) {
rtsock_open();
- FD_SET(rtsock, &fdset);
if (rtsock > sock)
maxfd = rtsock;
} else
rtsock = -1;
- signal(SIGTERM, (void *)set_die);
- signal(SIGUSR1, (void *)rtadvd_set_dump_file);
+ fdmasks = howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask);
+ if ((fdsetp = malloc(fdmasks)) == NULL) {
+ err(1, "malloc");
+ /*NOTREACHED*/
+ }
+ if ((selectfdp = malloc(fdmasks)) == NULL) {
+ err(1, "malloc");
+ /*NOTREACHED*/
+ }
+ memset(fdsetp, 0, fdmasks);
+ FD_SET(sock, fdsetp);
+ if (rtsock >= 0)
+ FD_SET(rtsock, fdsetp);
+
+ signal(SIGTERM, set_die);
+ signal(SIGUSR1, rtadvd_set_dump_file);
while (1) {
- struct fd_set select_fd = fdset; /* reinitialize */
+ memcpy(selectfdp, fdsetp, fdmasks); /* reinitialize */
if (do_dump) { /* SIGUSR1 */
do_dump = 0;
if (timeout != NULL) {
syslog(LOG_DEBUG,
- "<%s> set timer to %ld:%ld. waiting for "
- "inputs or timeout",
- __FUNCTION__,
- (long int)timeout->tv_sec,
- (long int)timeout->tv_usec);
+ "<%s> set timer to %ld:%ld. waiting for "
+ "inputs or timeout", __func__,
+ (long int)timeout->tv_sec,
+ (long int)timeout->tv_usec);
} else {
syslog(LOG_DEBUG,
- "<%s> there's no timer. waiting for inputs",
- __FUNCTION__);
+ "<%s> there's no timer. waiting for inputs",
+ __func__);
}
- if ((i = select(maxfd + 1, &select_fd,
- NULL, NULL, timeout)) < 0) {
+ if ((i = select(maxfd + 1, selectfdp, NULL, NULL,
+ timeout)) < 0) {
/* EINTR would occur upon SIGUSR1 for status dump */
if (errno != EINTR)
syslog(LOG_ERR, "<%s> select: %s",
- __FUNCTION__, strerror(errno));
+ __func__, strerror(errno));
continue;
}
if (i == 0) /* timeout */
continue;
- if (rtsock != -1 && FD_ISSET(rtsock, &select_fd))
+ if (rtsock != -1 && FD_ISSET(rtsock, selectfdp))
rtmsg_input();
- if (FD_ISSET(sock, &select_fd))
+ if (FD_ISSET(sock, selectfdp))
rtadvd_input();
}
exit(0); /* NOTREACHED */
}
static void
-rtadvd_set_dump_file()
+rtadvd_set_dump_file(sig)
+ int sig;
{
do_dump = 1;
}
if (dflag > 1) {
syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n",
- __FUNCTION__);
+ __func__);
}
for (ra = ralist; ra; ra = ra->next) {
ra_output(ra);
sleep(MIN_DELAY_BETWEEN_RAS);
}
+ pidfile_remove(pfh);
exit(0);
/*NOTREACHED*/
}
int n, type, ifindex = 0, plen;
size_t len;
char msg[2048], *next, *lim;
- u_char ifname[IF_NAMESIZE];
+ char ifname[IF_NAMESIZE];
struct prefix *prefix;
struct rainfo *rai;
struct in6_addr *addr;
char addrbuf[INET6_ADDRSTRLEN];
+ int prefixchange = 0;
n = read(rtsock, msg, sizeof(msg));
if (dflag > 1) {
- syslog(LOG_DEBUG,
- "<%s> received a routing message "
- "(type = %d, len = %d)",
- __FUNCTION__,
- rtmsg_type(msg), n);
+ syslog(LOG_DEBUG, "<%s> received a routing message "
+ "(type = %d, len = %d)", __func__, rtmsg_type(msg), n);
}
if (n > rtmsg_len(msg)) {
/*
*/
if (dflag > 1)
syslog(LOG_DEBUG,
- "<%s> received data length is larger than"
- "1st routing message len. multiple messages?"
- " read %d bytes, but 1st msg len = %d",
- __FUNCTION__, n, rtmsg_len(msg));
+ "<%s> received data length is larger than "
+ "1st routing message len. multiple messages? "
+ "read %d bytes, but 1st msg len = %d",
+ __func__, n, rtmsg_len(msg));
#if 0
/* adjust length */
n = rtmsg_len(msg);
if (dflag > 1) {
syslog(LOG_DEBUG,
"<%s:%d> unknown rtmsg %d on %s",
- __FUNCTION__, __LINE__, type,
- if_indextoname(ifindex, (char *)ifname));
+ __func__, __LINE__, type,
+ if_indextoname(ifindex, ifname));
}
continue;
}
syslog(LOG_DEBUG,
"<%s> route changed on "
"non advertising interface(%s)",
- __FUNCTION__,
- if_indextoname(ifindex, (char *)ifname));
+ __func__,
+ if_indextoname(ifindex, ifname));
}
continue;
}
oldifflags = iflist[ifindex]->ifm_flags;
- switch(type) {
- case RTM_ADD:
- /* init ifflags because it may have changed */
- iflist[ifindex]->ifm_flags =
- if_getflags(ifindex,
- iflist[ifindex]->ifm_flags);
-
- if (sflag)
- break; /* we aren't interested in prefixes */
-
- addr = get_addr(msg);
- plen = get_prefixlen(msg);
- /* sanity check for plen */
- if (plen < 4 /* as RFC2373, prefixlen is at least 4 */
- || plen > 127) {
+ switch (type) {
+ case RTM_ADD:
+ /* init ifflags because it may have changed */
+ iflist[ifindex]->ifm_flags =
+ if_getflags(ifindex, iflist[ifindex]->ifm_flags);
+
+ if (sflag)
+ break; /* we aren't interested in prefixes */
+
+ addr = get_addr(msg);
+ plen = get_prefixlen(msg);
+ /* sanity check for plen */
+ /* as RFC2373, prefixlen is at least 4 */
+ if (plen < 4 || plen > 127) {
syslog(LOG_INFO, "<%s> new interface route's"
- "plen %d is invalid for a prefix",
- __FUNCTION__, plen);
+ "plen %d is invalid for a prefix",
+ __func__, plen);
break;
- }
- prefix = find_prefix(rai, addr, plen);
- if (prefix) {
- if (dflag > 1) {
- syslog(LOG_DEBUG,
- "<%s> new prefix(%s/%d) "
- "added on %s, "
- "but it was already in list",
- __FUNCTION__,
- inet_ntop(AF_INET6,
- addr, (char *)addrbuf,
- INET6_ADDRSTRLEN),
- plen,
- rai->ifname);
- }
- break;
- }
- make_prefix(rai, ifindex, addr, plen);
- break;
- case RTM_DELETE:
- /* init ifflags because it may have changed */
- iflist[ifindex]->ifm_flags =
- if_getflags(ifindex,
- iflist[ifindex]->ifm_flags);
-
- if (sflag)
- break;
-
- addr = get_addr(msg);
- plen = get_prefixlen(msg);
- /* sanity check for plen */
- if (plen < 4 /* as RFC2373, prefixlen is at least 4 */
- || plen > 127) {
- syslog(LOG_INFO, "<%s> deleted interface"
- "route's"
- "plen %d is invalid for a prefix",
- __FUNCTION__, plen);
+ }
+ prefix = find_prefix(rai, addr, plen);
+ if (prefix) {
+ if (prefix->timer) {
+ /*
+ * If the prefix has been invalidated,
+ * make it available again.
+ */
+ update_prefix(prefix);
+ prefixchange = 1;
+ } else if (dflag > 1) {
+ syslog(LOG_DEBUG,
+ "<%s> new prefix(%s/%d) "
+ "added on %s, "
+ "but it was already in list",
+ __func__,
+ inet_ntop(AF_INET6, addr,
+ (char *)addrbuf, INET6_ADDRSTRLEN),
+ plen, rai->ifname);
+ }
break;
- }
- prefix = find_prefix(rai, addr, plen);
- if (prefix == NULL) {
- if (dflag > 1) {
- syslog(LOG_DEBUG,
- "<%s> prefix(%s/%d) was "
- "deleted on %s, "
- "but it was not in list",
- __FUNCTION__,
- inet_ntop(AF_INET6,
- addr, (char *)addrbuf,
- INET6_ADDRSTRLEN),
- plen,
- rai->ifname);
- }
- break;
- }
- delete_prefix(rai, prefix);
- break;
+ }
+ make_prefix(rai, ifindex, addr, plen);
+ prefixchange = 1;
+ break;
+ case RTM_DELETE:
+ /* init ifflags because it may have changed */
+ iflist[ifindex]->ifm_flags =
+ if_getflags(ifindex, iflist[ifindex]->ifm_flags);
+
+ if (sflag)
+ break;
+
+ addr = get_addr(msg);
+ plen = get_prefixlen(msg);
+ /* sanity check for plen */
+ /* as RFC2373, prefixlen is at least 4 */
+ if (plen < 4 || plen > 127) {
+ syslog(LOG_INFO,
+ "<%s> deleted interface route's "
+ "plen %d is invalid for a prefix",
+ __func__, plen);
+ break;
+ }
+ prefix = find_prefix(rai, addr, plen);
+ if (prefix == NULL) {
+ if (dflag > 1) {
+ syslog(LOG_DEBUG,
+ "<%s> prefix(%s/%d) was "
+ "deleted on %s, "
+ "but it was not in list",
+ __func__,
+ inet_ntop(AF_INET6, addr,
+ (char *)addrbuf, INET6_ADDRSTRLEN),
+ plen, rai->ifname);
+ }
+ break;
+ }
+ invalidate_prefix(prefix);
+ prefixchange = 1;
+ break;
case RTM_NEWADDR:
case RTM_DELADDR:
- /* init ifflags because it may have changed */
- iflist[ifindex]->ifm_flags =
- if_getflags(ifindex,
- iflist[ifindex]->ifm_flags);
- break;
+ /* init ifflags because it may have changed */
+ iflist[ifindex]->ifm_flags =
+ if_getflags(ifindex, iflist[ifindex]->ifm_flags);
+ break;
case RTM_IFINFO:
- iflist[ifindex]->ifm_flags = get_ifm_flags(next);
- break;
+ iflist[ifindex]->ifm_flags = get_ifm_flags(next);
+ break;
default:
/* should not reach here */
if (dflag > 1) {
syslog(LOG_DEBUG,
- "<%s:%d> unknown rtmsg %d on %s",
- __FUNCTION__, __LINE__, type,
- if_indextoname(ifindex, (char *)ifname));
+ "<%s:%d> unknown rtmsg %d on %s",
+ __func__, __LINE__, type,
+ if_indextoname(ifindex, ifname));
}
return;
}
/* check if an interface flag is changed */
- if ((oldifflags & IFF_UP) != 0 && /* UP to DOWN */
- (iflist[ifindex]->ifm_flags & IFF_UP) == 0) {
+ if ((oldifflags & IFF_UP) && /* UP to DOWN */
+ !(iflist[ifindex]->ifm_flags & IFF_UP)) {
syslog(LOG_INFO,
- "<%s> interface %s becomes down. stop timer.",
- __FUNCTION__, rai->ifname);
+ "<%s> interface %s becomes down. stop timer.",
+ __func__, rai->ifname);
rtadvd_remove_timer(&rai->timer);
- }
- else if ((oldifflags & IFF_UP) == 0 && /* DOWN to UP */
- (iflist[ifindex]->ifm_flags & IFF_UP) != 0) {
+ } else if (!(oldifflags & IFF_UP) && /* DOWN to UP */
+ (iflist[ifindex]->ifm_flags & IFF_UP)) {
syslog(LOG_INFO,
- "<%s> interface %s becomes up. restart timer.",
- __FUNCTION__, rai->ifname);
+ "<%s> interface %s becomes up. restart timer.",
+ __func__, rai->ifname);
rai->initcounter = 0; /* reset the counter */
rai->waiting = 0; /* XXX */
rai->timer = rtadvd_add_timer(ra_timeout,
- ra_timer_update,
- rai, rai);
+ ra_timer_update, rai, rai);
ra_timer_update((void *)rai, &rai->timer->tm);
rtadvd_set_timer(&rai->timer->tm, rai->timer);
+ } else if (prefixchange &&
+ (iflist[ifindex]->ifm_flags & IFF_UP)) {
+ /*
+ * An advertised prefix has been added or invalidated.
+ * Will notice the change in a short delay.
+ */
+ rai->initcounter = 0;
+ set_short_delay(rai);
}
}
int ifindex = 0;
struct cmsghdr *cm;
struct in6_pktinfo *pi = NULL;
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
+ char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
struct in6_addr dst = in6addr_any;
/*
if (ifindex == 0) {
syslog(LOG_ERR,
"<%s> failed to get receiving interface",
- __FUNCTION__);
+ __func__);
return;
}
if (hlimp == NULL) {
syslog(LOG_ERR,
"<%s> failed to get receiving hop limit",
- __FUNCTION__);
+ __func__);
return;
}
/*
- * If we happen to receive data on an interface which is now down,
- * just discard the data.
+ * If we happen to receive data on an interface which is now gone
+ * or down, just discard the data.
*/
- if ((iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) {
+ if (iflist[pi->ipi6_ifindex] == NULL ||
+ (iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) {
syslog(LOG_INFO,
"<%s> received data on a disabled interface (%s)",
- __FUNCTION__,
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ __func__,
+ (iflist[pi->ipi6_ifindex] == NULL) ? "[gone]" :
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
if (i < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) {
syslog(LOG_ERR,
"<%s> packet size(%d) is too short",
- __FUNCTION__, i);
+ __func__, i);
return;
}
if (i < sizeof(struct icmp6_hdr)) {
syslog(LOG_ERR,
"<%s> packet size(%d) is too short",
- __FUNCTION__, i);
+ __func__, i);
return;
}
icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
#endif
- switch(icp->icmp6_type) {
- case ND_ROUTER_SOLICIT:
- /*
- * Message verification - RFC-2461 6.1.1
- * XXX: these checks must be done in the kernel as well,
- * but we can't completely rely on them.
- */
- if (*hlimp != 255) {
- syslog(LOG_NOTICE,
- "<%s> RS with invalid hop limit(%d) "
- "received from %s on %s",
- __FUNCTION__, *hlimp,
- inet_ntop(AF_INET6, &from.sin6_addr, (char *)ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
- return;
- }
- if (icp->icmp6_code) {
- syslog(LOG_NOTICE,
- "<%s> RS with invalid ICMP6 code(%d) "
- "received from %s on %s",
- __FUNCTION__, icp->icmp6_code,
- inet_ntop(AF_INET6, &from.sin6_addr, (char *)ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
- return;
- }
- if (i < sizeof(struct nd_router_solicit)) {
- syslog(LOG_NOTICE,
- "<%s> RS from %s on %s does not have enough "
- "length (len = %d)",
- __FUNCTION__,
- inet_ntop(AF_INET6, &from.sin6_addr, (char *)ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf), i);
- return;
- }
- rs_input(i, (struct nd_router_solicit *)icp, pi, &from);
- break;
- case ND_ROUTER_ADVERT:
- /*
- * Message verification - RFC-2461 6.1.2
- * XXX: there's a same dilemma as above...
- */
- if (*hlimp != 255) {
- syslog(LOG_NOTICE,
- "<%s> RA with invalid hop limit(%d) "
- "received from %s on %s",
- __FUNCTION__, *hlimp,
- inet_ntop(AF_INET6, &from.sin6_addr, (char *)ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
- return;
- }
- if (icp->icmp6_code) {
- syslog(LOG_NOTICE,
- "<%s> RA with invalid ICMP6 code(%d) "
- "received from %s on %s",
- __FUNCTION__, icp->icmp6_code,
- inet_ntop(AF_INET6, &from.sin6_addr, (char *)ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
- return;
- }
- if (i < sizeof(struct nd_router_advert)) {
- syslog(LOG_NOTICE,
- "<%s> RA from %s on %s does not have enough "
- "length (len = %d)",
- __FUNCTION__,
- inet_ntop(AF_INET6, &from.sin6_addr, (char *)ntopbuf,
- INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf), i);
- return;
- }
- ra_input(i, (struct nd_router_advert *)icp, pi, &from);
- break;
- case ICMP6_ROUTER_RENUMBERING:
- if (accept_rr == 0) {
- syslog(LOG_ERR,
- "<%s> received a router renumbering "
- "message, but not allowed to be accepted",
- __FUNCTION__);
- break;
- }
- rr_input(i, (struct icmp6_router_renum *)icp, pi, &from,
- &dst);
- break;
- default:
- /*
- * Note that this case is POSSIBLE, especially just
- * after invocation of the daemon. This is because we
- * could receive message after opening the socket and
- * before setting ICMP6 type filter(see sock_open()).
- */
- syslog(LOG_ERR,
- "<%s> invalid icmp type(%d)",
- __FUNCTION__, icp->icmp6_type);
- return;
+ switch (icp->icmp6_type) {
+ case ND_ROUTER_SOLICIT:
+ /*
+ * Message verification - RFC-2461 6.1.1
+ * XXX: these checks must be done in the kernel as well,
+ * but we can't completely rely on them.
+ */
+ if (*hlimp != 255) {
+ syslog(LOG_NOTICE,
+ "<%s> RS with invalid hop limit(%d) "
+ "received from %s on %s",
+ __func__, *hlimp,
+ inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
+ INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
+ if (icp->icmp6_code) {
+ syslog(LOG_NOTICE,
+ "<%s> RS with invalid ICMP6 code(%d) "
+ "received from %s on %s",
+ __func__, icp->icmp6_code,
+ inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
+ INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
+ if (i < sizeof(struct nd_router_solicit)) {
+ syslog(LOG_NOTICE,
+ "<%s> RS from %s on %s does not have enough "
+ "length (len = %d)",
+ __func__,
+ inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
+ INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
+ return;
+ }
+ rs_input(i, (struct nd_router_solicit *)icp, pi, &rcvfrom);
+ break;
+ case ND_ROUTER_ADVERT:
+ /*
+ * Message verification - RFC-2461 6.1.2
+ * XXX: there's a same dilemma as above...
+ */
+ if (*hlimp != 255) {
+ syslog(LOG_NOTICE,
+ "<%s> RA with invalid hop limit(%d) "
+ "received from %s on %s",
+ __func__, *hlimp,
+ inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
+ INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
+ if (icp->icmp6_code) {
+ syslog(LOG_NOTICE,
+ "<%s> RA with invalid ICMP6 code(%d) "
+ "received from %s on %s",
+ __func__, icp->icmp6_code,
+ inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
+ INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
+ return;
+ }
+ if (i < sizeof(struct nd_router_advert)) {
+ syslog(LOG_NOTICE,
+ "<%s> RA from %s on %s does not have enough "
+ "length (len = %d)",
+ __func__,
+ inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
+ INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
+ return;
+ }
+ ra_input(i, (struct nd_router_advert *)icp, pi, &rcvfrom);
+ break;
+ case ICMP6_ROUTER_RENUMBERING:
+ if (accept_rr == 0) {
+ syslog(LOG_ERR, "<%s> received a router renumbering "
+ "message, but not allowed to be accepted",
+ __func__);
+ break;
+ }
+ rr_input(i, (struct icmp6_router_renum *)icp, pi, &rcvfrom,
+ &dst);
+ break;
+ default:
+ /*
+ * Note that this case is POSSIBLE, especially just
+ * after invocation of the daemon. This is because we
+ * could receive message after opening the socket and
+ * before setting ICMP6 type filter(see sock_open()).
+ */
+ syslog(LOG_ERR, "<%s> invalid icmp type(%d)",
+ __func__, icp->icmp6_type);
+ return;
}
return;
rs_input(int len, struct nd_router_solicit *rs,
struct in6_pktinfo *pi, struct sockaddr_in6 *from)
{
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
+ char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
union nd_opts ndopts;
struct rainfo *ra;
+ struct soliciter *sol;
syslog(LOG_DEBUG,
"<%s> RS received from %s on %s",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf, INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
/* ND option check */
memset(&ndopts, 0, sizeof(ndopts));
if (nd6_options((struct nd_opt_hdr *)(rs + 1),
len - sizeof(struct nd_router_solicit),
- &ndopts, NDOPT_FLAG_SRCLINKADDR)) {
- syslog(LOG_DEBUG,
+ &ndopts, NDOPT_FLAG_SRCLINKADDR)) {
+ syslog(LOG_INFO,
"<%s> ND option check failed for an RS from %s on %s",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf, INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
*/
if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) &&
ndopts.nd_opts_src_lladdr) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"<%s> RS from unspecified src on %s has a link-layer"
" address option",
- __FUNCTION__,
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ __func__,
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
goto done;
}
if (ra == NULL) {
syslog(LOG_INFO,
"<%s> RS received on non advertising interface(%s)",
- __FUNCTION__,
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ __func__,
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
goto done;
}
* Decide whether to send RA according to the rate-limit
* consideration.
*/
- {
- long delay; /* must not be greater than 1000000 */
- struct timeval interval, now, min_delay, tm_tmp, *rest;
- struct soliciter *sol;
-
- /*
- * record sockaddr waiting for RA, if possible
- */
- sol = (struct soliciter *)malloc(sizeof(*sol));
- if (sol) {
- sol->addr = *from;
- /*XXX RFC2553 need clarification on flowinfo */
- sol->addr.sin6_flowinfo = 0;
- sol->next = ra->soliciter;
- ra->soliciter = sol->next;
- }
-
- /*
- * If there is already a waiting RS packet, don't
- * update the timer.
- */
- if (ra->waiting++)
- goto done;
- /*
- * Compute a random delay. If the computed value
- * corresponds to a time later than the time the next
- * multicast RA is scheduled to be sent, ignore the random
- * delay and send the advertisement at the
- * already-scheduled time. RFC-2461 6.2.6
- */
- delay = random() % MAX_RA_DELAY_TIME;
- interval.tv_sec = 0;
- interval.tv_usec = delay;
- rest = rtadvd_timer_rest(ra->timer);
- if (TIMEVAL_LT(*rest, interval)) {
- syslog(LOG_DEBUG,
- "<%s> random delay is larger than "
- "the rest of normal timer",
- __FUNCTION__);
- interval = *rest;
- }
+ /* record sockaddr waiting for RA, if possible */
+ sol = (struct soliciter *)malloc(sizeof(*sol));
+ if (sol) {
+ sol->addr = *from;
+ /* XXX RFC2553 need clarification on flowinfo */
+ sol->addr.sin6_flowinfo = 0;
+ sol->next = ra->soliciter;
+ ra->soliciter = sol;
+ }
- /*
- * If we sent a multicast Router Advertisement within
- * the last MIN_DELAY_BETWEEN_RAS seconds, schedule
- * the advertisement to be sent at a time corresponding to
- * MIN_DELAY_BETWEEN_RAS plus the random value after the
- * previous advertisement was sent.
- */
- gettimeofday(&now, NULL);
- TIMEVAL_SUB(&now, &ra->lastsent, &tm_tmp);
- min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS;
- min_delay.tv_usec = 0;
- if (TIMEVAL_LT(tm_tmp, min_delay)) {
- TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay);
- TIMEVAL_ADD(&min_delay, &interval, &interval);
- }
- rtadvd_set_timer(&interval, ra->timer);
+ /*
+ * If there is already a waiting RS packet, don't
+ * update the timer.
+ */
+ if (ra->waiting++)
goto done;
- }
+
+ set_short_delay(ra);
done:
free_ndopts(&ndopts);
return;
}
+static void
+set_short_delay(rai)
+ struct rainfo *rai;
+{
+ long delay; /* must not be greater than 1000000 */
+ struct timeval interval, now, min_delay, tm_tmp, *rest;
+
+ /*
+ * Compute a random delay. If the computed value
+ * corresponds to a time later than the time the next
+ * multicast RA is scheduled to be sent, ignore the random
+ * delay and send the advertisement at the
+ * already-scheduled time. RFC-2461 6.2.6
+ */
+#ifdef HAVE_ARC4RANDOM
+ delay = arc4random_uniform(MAX_RA_DELAY_TIME);
+#else
+ delay = random() % MAX_RA_DELAY_TIME;
+#endif
+ interval.tv_sec = 0;
+ interval.tv_usec = delay;
+ rest = rtadvd_timer_rest(rai->timer);
+ if (TIMEVAL_LT(*rest, interval)) {
+ syslog(LOG_DEBUG, "<%s> random delay is larger than "
+ "the rest of the current timer", __func__);
+ interval = *rest;
+ }
+
+ /*
+ * If we sent a multicast Router Advertisement within
+ * the last MIN_DELAY_BETWEEN_RAS seconds, schedule
+ * the advertisement to be sent at a time corresponding to
+ * MIN_DELAY_BETWEEN_RAS plus the random value after the
+ * previous advertisement was sent.
+ */
+ gettimeofday(&now, NULL);
+ TIMEVAL_SUB(&now, &rai->lastsent, &tm_tmp);
+ min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS;
+ min_delay.tv_usec = 0;
+ if (TIMEVAL_LT(tm_tmp, min_delay)) {
+ TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay);
+ TIMEVAL_ADD(&min_delay, &interval, &interval);
+ }
+ rtadvd_set_timer(&interval, rai->timer);
+}
+
static void
ra_input(int len, struct nd_router_advert *ra,
struct in6_pktinfo *pi, struct sockaddr_in6 *from)
{
struct rainfo *rai;
- u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
+ char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
union nd_opts ndopts;
char *on_off[] = {"OFF", "ON"};
u_int32_t reachabletime, retranstimer, mtu;
syslog(LOG_DEBUG,
"<%s> RA received from %s on %s",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf, INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
/* ND option check */
memset(&ndopts, 0, sizeof(ndopts));
len - sizeof(struct nd_router_advert),
&ndopts, NDOPT_FLAG_SRCLINKADDR |
NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
- syslog(LOG_ERR,
+ syslog(LOG_INFO,
"<%s> ND option check failed for an RA from %s on %s",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf, INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
return;
}
syslog(LOG_INFO,
"<%s> received RA from %s on non-advertising"
" interface(%s)",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
- if_indextoname(pi->ipi6_ifindex, (char *)ifnamebuf));
+ ntopbuf, INET6_ADDRSTRLEN),
+ if_indextoname(pi->ipi6_ifindex, ifnamebuf));
goto done;
}
rai->rainput++; /* increment statistics */
syslog(LOG_INFO,
"<%s> CurHopLimit inconsistent on %s:"
" %d from %s, %d from us",
- __FUNCTION__,
+ __func__,
rai->ifname,
ra->nd_ra_curhoplimit,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
rai->hoplimit);
inconsistent++;
}
syslog(LOG_INFO,
"<%s> M flag inconsistent on %s:"
" %s from %s, %s from us",
- __FUNCTION__,
+ __func__,
rai->ifname,
on_off[!rai->managedflg],
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
on_off[rai->managedflg]);
inconsistent++;
}
syslog(LOG_INFO,
"<%s> O flag inconsistent on %s:"
" %s from %s, %s from us",
- __FUNCTION__,
+ __func__,
rai->ifname,
on_off[!rai->otherflg],
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
on_off[rai->otherflg]);
inconsistent++;
}
syslog(LOG_INFO,
"<%s> ReachableTime inconsistent on %s:"
" %d from %s, %d from us",
- __FUNCTION__,
+ __func__,
rai->ifname,
reachabletime,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
rai->reachabletime);
inconsistent++;
}
syslog(LOG_INFO,
"<%s> RetranceTimer inconsistent on %s:"
" %d from %s, %d from us",
- __FUNCTION__,
+ __func__,
rai->ifname,
retranstimer,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
rai->retranstimer);
inconsistent++;
}
syslog(LOG_INFO,
"<%s> MTU option value inconsistent on %s:"
" %d from %s, %d from us",
- __FUNCTION__,
+ __func__,
rai->ifname, mtu,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
rai->linkmtu);
inconsistent++;
}
u_int32_t preferred_time, valid_time;
struct prefix *pp;
int inconsistent = 0;
- u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
+ char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
struct timeval now;
#if 0 /* impossible */
syslog(LOG_INFO,
"<%s> link-local prefix %s/%d is advertised "
"from %s on %s",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- (char *)prefixbuf, INET6_ADDRSTRLEN),
+ prefixbuf, INET6_ADDRSTRLEN),
pinfo->nd_opt_pi_prefix_len,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
rai->ifname);
}
pinfo->nd_opt_pi_prefix_len)) == NULL) {
syslog(LOG_INFO,
"<%s> prefix %s/%d from %s on %s is not in our list",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- (char *)prefixbuf, INET6_ADDRSTRLEN),
+ prefixbuf, INET6_ADDRSTRLEN),
pinfo->nd_opt_pi_prefix_len,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
rai->ifname);
return(0);
}
gettimeofday(&now, NULL);
preferred_time += now.tv_sec;
- if (rai->clockskew &&
+ if (!pp->timer && rai->clockskew &&
abs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
syslog(LOG_INFO,
- "<%s> prefeerred lifetime for %s/%d"
+ "<%s> preferred lifetime for %s/%d"
" (decr. in real time) inconsistent on %s:"
" %d from %s, %ld from us",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- (char *)prefixbuf, INET6_ADDRSTRLEN),
+ prefixbuf, INET6_ADDRSTRLEN),
pinfo->nd_opt_pi_prefix_len,
rai->ifname, preferred_time,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
pp->pltimeexpire);
inconsistent++;
}
- }
- else if (preferred_time != pp->preflifetime) {
+ } else if (!pp->timer && preferred_time != pp->preflifetime) {
syslog(LOG_INFO,
- "<%s> prefeerred lifetime for %s/%d"
+ "<%s> preferred lifetime for %s/%d"
" inconsistent on %s:"
" %d from %s, %d from us",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- (char *)prefixbuf, INET6_ADDRSTRLEN),
+ prefixbuf, INET6_ADDRSTRLEN),
pinfo->nd_opt_pi_prefix_len,
rai->ifname, preferred_time,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
pp->preflifetime);
}
gettimeofday(&now, NULL);
valid_time += now.tv_sec;
- if (rai->clockskew &&
+ if (!pp->timer && rai->clockskew &&
abs(valid_time - pp->vltimeexpire) > rai->clockskew) {
syslog(LOG_INFO,
"<%s> valid lifetime for %s/%d"
" (decr. in real time) inconsistent on %s:"
" %d from %s, %ld from us",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- (char *)prefixbuf, INET6_ADDRSTRLEN),
+ prefixbuf, INET6_ADDRSTRLEN),
pinfo->nd_opt_pi_prefix_len,
rai->ifname, preferred_time,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
pp->vltimeexpire);
inconsistent++;
}
- }
- else if (valid_time != pp->validlifetime) {
+ } else if (!pp->timer && valid_time != pp->validlifetime) {
syslog(LOG_INFO,
"<%s> valid lifetime for %s/%d"
" inconsistent on %s:"
" %d from %s, %d from us",
- __FUNCTION__,
+ __func__,
inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
- (char *)prefixbuf, INET6_ADDRSTRLEN),
+ prefixbuf, INET6_ADDRSTRLEN),
pinfo->nd_opt_pi_prefix_len,
rai->ifname, valid_time,
inet_ntop(AF_INET6, &from->sin6_addr,
- (char *)ntopbuf, INET6_ADDRSTRLEN),
+ ntopbuf, INET6_ADDRSTRLEN),
pp->validlifetime);
inconsistent++;
}
{
struct prefix *pp;
int bytelen, bitlen;
+ u_char bitmask;
for (pp = rai->prefix.next; pp != &rai->prefix; pp = pp->next) {
if (plen != pp->prefixlen)
continue;
bytelen = plen / 8;
bitlen = plen % 8;
+ bitmask = 0xff << (8 - bitlen);
if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen))
continue;
- if (prefix->s6_addr[bytelen] >> (8 - bitlen) ==
- pp->prefix.s6_addr[bytelen] >> (8 - bitlen))
+ if (bitlen == 0 ||
+ ((prefix->s6_addr[bytelen] & bitmask) ==
+ (pp->prefix.s6_addr[bytelen] & bitmask))) {
return(pp);
+ }
}
return(NULL);
struct in6_addr *p1, int plen1)
{
int bytelen, bitlen;
+ u_char bitmask;
if (plen0 < plen1)
return(0);
bytelen = plen1 / 8;
bitlen = plen1 % 8;
+ bitmask = 0xff << (8 - bitlen);
if (memcmp((void *)p0, (void *)p1, bytelen))
return(0);
- if (p0->s6_addr[bytelen] >> (8 - bitlen) ==
- p1->s6_addr[bytelen] >> (8 - bitlen))
+ if (bitlen == 0 ||
+ ((p0->s6_addr[bytelen] & bitmask) ==
+ (p1->s6_addr[bytelen] & bitmask))) {
return(1);
+ }
return(0);
}
int optlen = 0;
for (; limit > 0; limit -= optlen) {
+ if (limit < sizeof(struct nd_opt_hdr)) {
+ syslog(LOG_INFO, "<%s> short option header", __func__);
+ goto bad;
+ }
+
hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen);
- optlen = hdr->nd_opt_len << 3;
if (hdr->nd_opt_len == 0) {
- syslog(LOG_ERR,
- "<%s> bad ND option length(0) (type = %d)",
- __FUNCTION__, hdr->nd_opt_type);
+ syslog(LOG_INFO,
+ "<%s> bad ND option length(0) (type = %d)",
+ __func__, hdr->nd_opt_type);
+ goto bad;
+ }
+ optlen = hdr->nd_opt_len << 3;
+ if (optlen > limit) {
+ syslog(LOG_INFO, "<%s> short option", __func__);
goto bad;
}
if (hdr->nd_opt_type > ND_OPT_MTU) {
- syslog(LOG_INFO,
- "<%s> unknown ND option(type %d)",
- __FUNCTION__,
- hdr->nd_opt_type);
+ syslog(LOG_INFO, "<%s> unknown ND option(type %d)",
+ __func__, hdr->nd_opt_type);
continue;
}
if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) {
- syslog(LOG_INFO,
- "<%s> unexpected ND option(type %d)",
- __FUNCTION__,
- hdr->nd_opt_type);
+ syslog(LOG_INFO, "<%s> unexpected ND option(type %d)",
+ __func__, hdr->nd_opt_type);
continue;
}
- switch(hdr->nd_opt_type) {
- case ND_OPT_SOURCE_LINKADDR:
- case ND_OPT_TARGET_LINKADDR:
- case ND_OPT_REDIRECTED_HEADER:
- case ND_OPT_MTU:
- if (ndopts->nd_opt_array[hdr->nd_opt_type]) {
- syslog(LOG_INFO,
- "<%s> duplicated ND option"
- " (type = %d)",
- __FUNCTION__,
- hdr->nd_opt_type);
- }
- ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
- break;
- case ND_OPT_PREFIX_INFORMATION:
- {
- struct nd_optlist *pfxlist;
-
- if (ndopts->nd_opts_pi == 0) {
- ndopts->nd_opts_pi =
- (struct nd_opt_prefix_info *)hdr;
- continue;
- }
- if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) {
- syslog(LOG_ERR,
- "<%s> can't allocate memory",
- __FUNCTION__);
- goto bad;
- }
- pfxlist->next = ndopts->nd_opts_list;
- pfxlist->opt = hdr;
- ndopts->nd_opts_list = pfxlist;
-
- break;
- }
- default: /* impossible */
- break;
+ /*
+ * Option length check. Do it here for all fixed-length
+ * options.
+ */
+ if ((hdr->nd_opt_type == ND_OPT_MTU &&
+ (optlen != sizeof(struct nd_opt_mtu))) ||
+ ((hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
+ optlen != sizeof(struct nd_opt_prefix_info)))) {
+ syslog(LOG_INFO, "<%s> invalid option length",
+ __func__);
+ continue;
+ }
+
+ switch (hdr->nd_opt_type) {
+ case ND_OPT_TARGET_LINKADDR:
+ case ND_OPT_REDIRECTED_HEADER:
+ break; /* we don't care about these options */
+ case ND_OPT_SOURCE_LINKADDR:
+ case ND_OPT_MTU:
+ if (ndopts->nd_opt_array[hdr->nd_opt_type]) {
+ syslog(LOG_INFO,
+ "<%s> duplicated ND option (type = %d)",
+ __func__, hdr->nd_opt_type);
+ }
+ ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
+ break;
+ case ND_OPT_PREFIX_INFORMATION:
+ {
+ struct nd_optlist *pfxlist;
+
+ if (ndopts->nd_opts_pi == 0) {
+ ndopts->nd_opts_pi =
+ (struct nd_opt_prefix_info *)hdr;
+ continue;
+ }
+ if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) {
+ syslog(LOG_ERR, "<%s> can't allocate memory",
+ __func__);
+ goto bad;
+ }
+ pfxlist->next = ndopts->nd_opts_list;
+ pfxlist->opt = hdr;
+ ndopts->nd_opts_list = pfxlist;
+
+ break;
+ }
+ default: /* impossible */
+ break;
}
}
{
struct nd_optlist *opt = ndopts->nd_opts_list, *next;
- while(opt) {
+ while (opt) {
next = opt->next;
free(opt);
opt = next;
CMSG_SPACE(sizeof(int));
rcvcmsgbuf = (u_char *)malloc(rcvcmsgbuflen);
if (rcvcmsgbuf == NULL) {
- syslog(LOG_ERR, "<%s> not enough core", __FUNCTION__);
+ syslog(LOG_ERR, "<%s> not enough core", __func__);
exit(1);
}
CMSG_SPACE(sizeof(int));
sndcmsgbuf = (u_char *)malloc(sndcmsgbuflen);
if (sndcmsgbuf == NULL) {
- syslog(LOG_ERR, "<%s> not enough core", __FUNCTION__);
+ syslog(LOG_ERR, "<%s> not enough core", __func__);
exit(1);
}
if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
- syslog(LOG_ERR, "<%s> socket: %s", __FUNCTION__,
+ syslog(LOG_ERR, "<%s> socket: %s", __func__,
strerror(errno));
exit(1);
}
+ (void) setsockopt(sock, SOL_SOCKET, SO_TRAFFIC_CLASS,
+ (void *)&so_traffic_class, sizeof (so_traffic_class));
+
/* specify to tell receiving interface */
on = 1;
#ifdef IPV6_RECVPKTINFO
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
sizeof(on)) < 0) {
syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s",
- __FUNCTION__, strerror(errno));
+ __func__, strerror(errno));
exit(1);
}
#else /* old adv. API */
if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
sizeof(on)) < 0) {
syslog(LOG_ERR, "<%s> IPV6_PKTINFO: %s",
- __FUNCTION__, strerror(errno));
+ __func__, strerror(errno));
exit(1);
}
#endif
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
sizeof(on)) < 0) {
syslog(LOG_ERR, "<%s> IPV6_RECVHOPLIMIT: %s",
- __FUNCTION__, strerror(errno));
+ __func__, strerror(errno));
exit(1);
}
#else /* old adv. API */
if (setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
sizeof(on)) < 0) {
syslog(LOG_ERR, "<%s> IPV6_HOPLIMIT: %s",
- __FUNCTION__, strerror(errno));
+ __func__, strerror(errno));
exit(1);
}
#endif
if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
sizeof(filt)) < 0) {
syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s",
- __FUNCTION__, strerror(errno));
+ __func__, strerror(errno));
exit(1);
}
&mreq.ipv6mr_multiaddr.s6_addr)
!= 1) {
syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
- __FUNCTION__);
+ __func__);
exit(1);
}
- while(ra) {
+ while (ra) {
mreq.ipv6mr_interface = ra->ifindex;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
sizeof(mreq)) < 0) {
syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s",
- __FUNCTION__, ra->ifname, strerror(errno));
+ __func__, ra->ifname, strerror(errno));
exit(1);
}
ra = ra->next;
if (inet_pton(AF_INET6, ALLROUTERS_SITE,
&in6a_site_allrouters) != 1) {
syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
- __FUNCTION__);
+ __func__);
exit(1);
}
mreq.ipv6mr_multiaddr = in6a_site_allrouters;
== 0) {
syslog(LOG_ERR,
"<%s> invalid interface: %s",
- __FUNCTION__, mcastif);
+ __func__, mcastif);
exit(1);
}
} else
&mreq, sizeof(mreq)) < 0) {
syslog(LOG_ERR,
"<%s> IPV6_JOIN_GROUP(site) on %s: %s",
- __FUNCTION__,
+ __func__,
mcastif ? mcastif : ralist->ifname,
strerror(errno));
exit(1);
/* initialize msghdr for receiving packets */
rcviov[0].iov_base = (caddr_t)answer;
rcviov[0].iov_len = sizeof(answer);
- rcvmhdr.msg_name = (caddr_t)&from;
- rcvmhdr.msg_namelen = sizeof(from);
+ rcvmhdr.msg_name = (caddr_t)&rcvfrom;
+ rcvmhdr.msg_namelen = sizeof(rcvfrom);
rcvmhdr.msg_iov = rcviov;
rcvmhdr.msg_iovlen = 1;
rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
{
if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
syslog(LOG_ERR,
- "<%s> socket: %s", __FUNCTION__, strerror(errno));
+ "<%s> socket: %s", __func__, strerror(errno));
exit(1);
}
}
struct rainfo *
-if_indextorainfo(int index)
+if_indextorainfo(int idx)
{
struct rainfo *rai = ralist;
for (rai = ralist; rai; rai = rai->next) {
- if (rai->ifindex == index)
+ if (rai->ifindex == idx)
return(rai);
}
if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA",
- __FUNCTION__, rainfo->ifname);
+ __func__, rainfo->ifname);
return;
}
syslog(LOG_DEBUG,
"<%s> send RA on %s, # of waitings = %d",
- __FUNCTION__, rainfo->ifname, rainfo->waiting);
+ __func__, rainfo->ifname, rainfo->waiting);
i = sendmsg(sock, &sndmhdr, 0);
if (i < 0 || i != rainfo->ra_datalen) {
if (i < 0) {
syslog(LOG_ERR, "<%s> sendmsg on %s: %s",
- __FUNCTION__, rainfo->ifname,
+ __func__, rainfo->ifname,
strerror(errno));
}
}
+ /* update counter */
+ if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
+ rainfo->initcounter++;
+ rainfo->raoutput++;
/*
* unicast advertisements
for (sol = rainfo->soliciter; sol; sol = nextsol) {
nextsol = sol->next;
-#if 0
- sndmhdr.msg_name = (caddr_t)&sol->addr;
- i = sendmsg(sock, &sndmhdr, 0);
- if (i < 0 || i != rainfo->ra_datalen) {
- if (i < 0) {
- syslog(LOG_ERR,
- "<%s> unicast sendmsg on %s: %s",
- __FUNCTION__, rainfo->ifname,
- strerror(errno));
- }
- }
-#endif
-
sol->next = NULL;
free(sol);
}
rainfo->soliciter = NULL;
- /* update counter */
- if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
- rainfo->initcounter++;
- rainfo->raoutput++;
-
/* update timestamp */
gettimeofday(&rainfo->lastsent, NULL);
}
/* process RA timer */
-void
+struct rtadvd_timer *
ra_timeout(void *data)
{
struct rainfo *rai = (struct rainfo *)data;
syslog(LOG_DEBUG,
"<%s> RA timer on %s is expired",
- __FUNCTION__, rai->ifname);
+ __func__, rai->ifname);
ra_output(rai);
+
+ return(rai->timer);
}
/* update RA timer */
syslog(LOG_DEBUG,
"<%s> RA timer on %s is set to %ld:%ld",
- __FUNCTION__, rai->ifname,
+ __func__, rai->ifname,
(long int)tm->tv_sec, (long int)tm->tv_usec);
return;
-# $FreeBSD: src/usr.sbin/rtadvd/rtadvd.conf,v 1.1.2.2 2001/02/22 07:51:05 ume Exp $
-# $KAME: rtadvd.conf,v 1.12 2001/01/21 14:56:38 itojun Exp $
+# $KAME: rtadvd.conf,v 1.13 2003/06/25 03:45:21 itojun Exp $
#
# Note: All of the following parameters have default values defined
# in specifications, and hence you usually do not have to set them
# this part by hand, and then invoke rtadvd with the -s option.
#ef0:\
-# :addrs#1:addr="3ffe:501:ffff:1000::":prefixlen#64:
+# :addr="3ffe:501:ffff:1000::":prefixlen#64:
-.\" $FreeBSD: src/usr.sbin/rtadvd/rtadvd.conf.5,v 1.1.2.8 2001/08/16 15:56:30 ru Exp $
-.\" $KAME: rtadvd.conf.5,v 1.35 2001/05/25 07:40:22 jinmei Exp $
+.\" $KAME: rtadvd.conf.5,v 1.50 2005/01/14 05:30:59 jinmei Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 2, 2010
+.Dd February 24, 2012
.Dt RTADVD.CONF 5
.Os
.Sh NAME
.It Cm \&maxinterval
(num) The maximum time allowed between sending unsolicited
multicast router advertisements
-(unit: seconds).
+.Pq unit: seconds .
The default value is 600.
Its value must be no less than 4 seconds
and no greater than 1800 seconds.
.It Cm \&mininterval
(num) The minimum time allowed between sending unsolicited multicast
router advertisements
-(unit: seconds).
+.Pq unit: seconds .
The default value is the one third of value of
.Cm maxinterval .
Its value must be no less than 3 seconds and no greater than .75 *
(num) The value for Cur Hop Limit field.
The default value is 64.
.It Cm \&raflags
-(num) Flags field in router advertisement message header.
+(str or num) A 8-bit flags field in router advertisement message header.
+This field can be specified either as a case-sensitive string or as an
+integer.
+A string consists of characters each of which corresponds to a
+particular flag bit(s).
+An integer should be the logical OR of all enabled bits.
Bit 7
-.Pq Li 0x80
+.Po
+.Li 'm' or 0x80
+.Pc
means Managed address configuration flag bit,
and Bit 6
-.Pq Li 0x40
+.Po
+.Li 'o' or 0x40
+.Pc
means Other stateful configuration flag bit.
Bit 4
-.Pq Li 0x10
+.Po
+.Li 0x10
+.Pc
and Bit 3
-.Pq Li 0x08
+.Po
+.Li 0x08
+.Pc
are used to encode router preference.
-0x01 means high, 0x00 means medium, and 0x11 means low.
-The default value is 0.
+Bits 01
+.Po
+or 'h'
+.Pc
+means high, 00 means medium, and 11
+.Po
+or 'l'
+.Pc
+means low.
+Bits 10 is reserved, and must not be specified.
+There is no character to specify the medium preference explicitly.
+The default value of the entire flag is 0
+.Po
+or a null string,
+.Pc
+which means no additional
+configuration methods, and the medium router preference.
.It Cm \&rltime
(num) Router lifetime field
-(unit: seconds).
-Its value must be no greater than 3600000.
+.Pq unit: seconds .
+The value must be either zero or between
+the value of
+.Cm maxinterval
+and 9000.
When
.Nm rtadvd
runs on a host, this value must explicitly set 0 on all the
The default value is 1800.
.It Cm \&rtime
(num) Reachable time field
-(unit: milliseconds).
+.Pq unit: milliseconds .
The default value is 0, which means unspecified by this router.
.It Cm \&retrans
(num) Retrans Timer field
-(unit: milliseconds).
+.Pq unit: milliseconds .
The default value is 0, which means unspecified by this router.
.El
.Pp
.Nm rtadvd
will automatically get appropriate prefixes from the kernel's routing table,
and advertise the prefixes with the default parameters.
+Keywords other than
+.Cm clockskew
+can be augmented with a number, like
+.Dq Li prefix2 ,
+to specify multiple prefixes.
.Bl -tag -width indent
.It Cm \&clockskew
(num) Time skew to adjust link propagation delays and clock skews
-betwen routers on the link
-(unit: seconds).
+between routers on the link
+.Pq unit: seconds .
This value is used in consistency check for locally-configured and
advertised prefix lifetimes, and has its meaning when the local router
configures a prefix on the link with a lifetime that decrements in
If the value is 0, it means the consistency check will be skipped
for such prefixes.
The default value is 0.
-.It Cm \&addrs
-(num) Number of prefixes.
-Its default is 0, so it must explicitly be set to positive values
-if you want to specify any prefix information option.
-If its value is 0,
-.Xr rtadvd 8
-looks up the system routing table and
-advertise the prefixes corresponding to interface routes
-on the interface.
-If its value is more than 1, you must specify the index of the prefix
-for each item below.
-Indices vary from 0 to N-1, where N is the
-value of
-.Cm addrs .
-Each index shall follow the name of each item, e.g.,
-.Dq prefixlen2 .
.It Cm \&prefixlen
(num) Prefix length field.
The default value is 64.
.It Cm \&pinfoflags
-(num) Flags field in prefix information option.
+(str or num) A 8-bit flags field in prefix information option.
+This field can be specified either as a case-sensitive string or as an
+integer.
+A string consists of characters each of which corresponds to a
+particular flag bit(s).
+An integer should be the logical OR of all enabled bits.
Bit 7
-.Pq Li 0x80
+.Po
+.Li 'l' or 0x80
+.Pc
means On-link flag bit,
and Bit 6
-.Pq Li 0x40
+.Po
+.Li 'a' or 0x40
+.Pc
means Autonomous address-configuration flag bit.
-The default value is 0xc0, i.e., both bits are set.
+The default value is "la" or 0xc0, i.e., both bits are set.
.It Cm \&addr
(str) The address filled into Prefix field.
Since
.Xr termcap 5
file format as well as IPv6 numeric address, the field MUST be quoted by
doublequote character.
-This field cannot be
-omitted if the value of
-.Cm addrs
-is more than 0.
.It Cm \&vltime
(num) Valid lifetime field
-(unit: seconds).
+.Pq unit: seconds .
The default value is 2592000 (30 days).
.It Cm \&vltimedecr
-(bool) This item means the advertised valid lifetime will decrements
+(bool) This item means the advertised valid lifetime will decrement
in real time, which is disabled by default.
.It Cm \&pltime
(num) Preferred lifetime field
-(unit: seconds).
+.Pq unit: seconds .
The default value is 604800 (7 days).
.It Cm \&pltimedecr
-(bool) This item means the advertised preferred lifetime will decrements
+(bool) This item means the advertised preferred lifetime will decrement
in real time, which is disabled by default.
.El
.Pp
.Bl -tag -width indent
.It Cm \&nolladdr
(bool) By default
-(if
+.Po
+if
.Cm \&nolladdr
-is not specified),
+is not specified
+.Pc ,
.Xr rtadvd 8
will try to get link-layer address for the interface from the kernel,
and attach that in source link-layer address option.
router advertisement packets.
.El
.Pp
-The following item controls ICMPV6 home agent information option,
+The following item controls ICMPv6 home agent information option,
which was defined with mobile IPv6 support.
It will be attached to router advertisement header just like other options do.
.Bl -tag -width indent
The following items are for ICMPv6 route information option,
which will be attached to router advertisement header.
These items are optional.
+Each items can be augmented with number, like
+.Dq Li rtplen2 ,
+to specify multiple routes.
.Bl -tag -width indent
-.It Cm \&routes
-(num) Number of routes.
-Its default is 0, so it must explicitly be set to positive values
-if you want to specify any route information option.
-If its value is 0, no route information is sent.
-If its value is more than 1, you must specify the index of the routes
-for each item below.
-Indices vary from 0 to N-1, where N is the
-value of
-.Cm routes.
-Each index shall follow the name of each item, e.g.,
-.Dq rtrplen2 .
-.It Cm \&rtrplen
-(num) Prefix length field in route information option.
-The default value is 64.
-.It Cm \&rtrflags
-(num) Flags field in route information option.
-Bit 4
-.Pq Li 0x10
-and
-and Bit 3
-.Pq Li 0x08
-are used to encode router preference for the route.
-The default value is 0x00, i.e. medium router preference.
-.It Cm \&rtrprefix
+.It Cm \&rtprefix
(str) The prefix filled into the Prefix field of route information option.
Since
.Dq \&:
.Xr termcap 5
file format as well as IPv6 numeric address, the field MUST be quoted by
doublequote character.
-This field cannot be
-omitted if the value of
-.Cm addrs
-is more than 0.
-.It Cm \&rtrltime
+.It Cm \&rtplen
+(num) Prefix length field in route information option.
+The default value is 64.
+.It Cm \&rtflags
+(str or num) A 8-bit flags field in route information option.
+Currently only the preference values are defined.
+The notation is same as that of the raflags field.
+Bit 4
+.Po
+.Li 0x10
+.Pc
+and
+Bit 3
+.Po
+.Li 0x08
+.Pc
+are used to encode the route preference for the route.
+The default value is 0x00, i.e., medium preference.
+.It Cm \&rtltime
(num) route lifetime field in route information option.
-(unit: seconds).
-The default value is 2592000 (30 days). (not specified in draft-draves-router-selection-01.txt now)
+.Pq unit: seconds .
+Since the specification does not define the default value of this
+item, the value for this item should be specified by hand.
+However,
+.Nm rtadvd
+allows this item to be unspecified, and uses the router lifetime
+as the default value in such a case, just for compatibility with an
+old version of the program.
.El
+.Pp
+In the above list, each keyword beginning with
+.Dq Li rt
+could be replaced with the one beginning with
+.Dq Li rtr
+for backward compatibility reason.
+For example,
+.Cm rtrplen
+is accepted instead of
+.Cm rtplen .
+However, keywords that start with
+.Dq Li rtr
+have basically been obsoleted, and should not be used any more.
+.Pp
You can also refer one line from another by using
.Cm tc
capability.
.Cm \&maxinterval .
If you specify a value outside of this range, a message is logged.
.El
+.Pp
+The following items are for the ICMPv6 DNS search list (DNSSL) option,
+which will be attached to the router advertisement header.
+.Bl -tag -width indent
+.It Cm \&dnssldomains
+(num) Number of DNS search domains.
+Its default is 0, so it must explicitly be set to positive values
+if you want to specify any DNS search domains.
+If its value is 0, no DNS search domain information is sent.
+If its value is more than 1, you must specify the index of the search domain
+for the
+.Cm dnssldomain
+item below.
+Indices vary from 0 to N-1, where N is the
+value of
+.Cm dnssldomains .
+Each index shall follow the name of
+.Cm dnssldomain ,
+e.g.,
+.Dq dnssldomain0 .
+.It Cm \&dnssldomain
+(str) The DNS search domain.
+This field cannot be
+omitted if the value of
+.Cm dnssldomains
+is more than 0.
+.It Cm \&dnssllifetime
+(num) The lifetime field in the DNSSL option.
+(unit: seconds).
+The default value is 2 * the value of
+.Cm \&maxinterval ,
+which is also the maximum value that should be set. The minimum value is
+.Cm \&maxinterval .
+If you specify a value outside of this range, a message is logged.
+.El
.Sh EXAMPLES
As presented above, all of the advertised parameters have default values
defined in specifications, and hence you usually do not have to set them
.Xr rtadvd 8 .
.Bd -literal -offset
ef0:\\
- :addrs#1:addr="3ffe:501:ffff:1000::":prefixlen#64:
+ :addr="3ffe:501:ffff:1000::":prefixlen#64:
.Ed
.Pp
The following example presents the default values in an explicit manner.
.Bd -literal -offset
default:\\
:chlim#64:raflags#0:rltime#1800:rtime#0:retrans#0:\\
- :pinfoflags#192:vltime#2592000:pltime#604800:mtu#0:
+ :pinfoflags="la":vltime#2592000:pltime#604800:mtu#0:
ef0:\\
- :addrs#1:addr="3ffe:501:ffff:1000::":prefixlen#64:tc=default:
+ :addr="3ffe:501:ffff:1000::":prefixlen#64:tc=default:
.Ed
.Sh SEE ALSO
.Xr termcap 5 ,
.Xr rtadvd 8 ,
.Xr rtsol 8
-.Pp
-Thomas Narten, Erik Nordmark and W. A. Simpson,
-.Do
-Neighbor Discovery for IP version 6 (IPv6)
-.Dc ,
-RFC 2461
-.Pp
-Richard Draves,
-.Do
-Default Router Preferences and More-Specific Routes
-.Dc ,
-draft-ietf-ipngwg-router-selection-01.txt
-.Pp
-Jeong, J., Park, S., Beloeil, L., and S. Madanapalli,
-.Do
-IPv6 Router Advertisement Option for DNS Configuration
-.Dc ,
-RFC 5006
+.Rs
+.%A Thomas Narten
+.%A Erik Nordmark
+.%A W. A. Simpson
+.%T Neighbor Discovery for IP version 6 (IPv6)
+.%R RFC 2461
+.Re
+.Rs
+.%A Richard Draves
+.%T Default Router Preferences and More-Specific Routes
+.%R draft-ietf-ipngwg-router-selection-xx.txt
+.Re
+.Rs
+.%A J. Jeong
+.%A S. Park
+.%A L. Beloeil
+.%A S. Madanapalli
+.%T IPv6 Router Advertisement Option for DNS Configuration
+.%R RFC 5006
+.Re
.Sh HISTORY
The
.Xr rtadvd 8
-/* $KAME: rtadvd.h,v 1.16 2001/04/10 15:08:31 suz Exp $ */
+/* $KAME: rtadvd.h,v 1.26 2003/08/05 12:34:23 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/rtadvd.h,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
+#define ROUTEINFO 1
+
#define ALLNODES "ff02::1"
#define ALLROUTERS_LINK "ff02::2"
#define ALLROUTERS_SITE "ff05::2"
#define DEF_ADVVALIDLIFETIME 2592000
#define DEF_ADVPREFERREDLIFETIME 604800
-/*XXX int-to-double comparison for INTERVAL items */
-#ifndef MIP6
-#define mobileip6 0
-#endif
-
#define MAXROUTERLIFETIME 9000
-#define MIN_MAXINTERVAL (mobileip6 ? 1.5 : 4.0)
+#define MIN_MAXINTERVAL 4
#define MAX_MAXINTERVAL 1800
-#define MIN_MININTERVAL (mobileip6 ? 0.5 : 3)
+#define MIN_MININTERVAL 3
#define MAXREACHABLETIME 3600000
-#ifndef MIP6
-#undef miobileip6
-#endif
-
#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16
#define MAX_INITIAL_RTR_ADVERTISEMENTS 3
#define MAX_FINAL_RTR_ADVERTISEMENTS 3
struct prefix *next; /* forward link */
struct prefix *prev; /* previous link */
+ struct rainfo *rainfo; /* back pointer to the interface */
+
+ struct rtadvd_timer *timer; /* expiration timer. used when a prefix
+ * derived from the kernel is deleted.
+ */
+
u_int32_t validlifetime; /* AdvValidLifetime */
long vltimeexpire; /* expiration of vltime; decrement case only */
u_int32_t preflifetime; /* AdvPreferredLifetime */
long pltimeexpire; /* expiration of pltime; decrement case only */
u_int onlinkflg; /* bool: AdvOnLinkFlag */
u_int autoconfflg; /* bool: AdvAutonomousFlag */
-#ifdef MIP6
- u_int routeraddr; /* bool: RouterAddress */
-#endif
int prefixlen;
- int origin; /* from kernel or cofig */
+ int origin; /* from kernel or config */
struct in6_addr prefix;
};
+#ifdef ROUTEINFO
struct rtinfo {
struct rtinfo *prev; /* previous link */
struct rtinfo *next; /* forward link */
u_int32_t ltime; /* route lifetime */
- u_int rtpref; /* router preference */
+ u_int rtpref; /* route preference */
int prefixlen;
struct in6_addr prefix;
};
+#endif
struct soliciter {
struct soliciter *next;
struct in6_addr addr;
};
+struct dnssl {
+ struct dnssl *next;
+ struct dnssl *prev;
+
+ char domain[1];
+};
+
struct rainfo {
/* pointer for list */
struct rainfo *next;
u_int mininterval; /* MinRtrAdvInterval */
int managedflg; /* AdvManagedFlag */
int otherflg; /* AdvOtherConfigFlag */
-#ifdef MIP6
- int haflg; /* HAFlag */
-#endif
+
int rtpref; /* router preference */
u_int32_t linkmtu; /* AdvLinkMTU */
u_int32_t reachabletime; /* AdvReachableTime */
int pfxs; /* number of prefixes */
long clockskew; /* used for consisitency check of lifetimes */
-#ifdef MIP6
- u_short hapref; /* Home Agent Preference */
- u_short hatime; /* Home Agent Lifetime */
-#endif
+#ifdef ROUTEINFO
struct rtinfo route; /* route information option (link head) */
int routes; /* number of route information options */
+#endif
/* Recursive DNS Servers RFC5006 */
struct rdnss rdnss_list;
int rdnss_length;
u_int32_t rdnss_lifetime;
+ /* DNS Search List RFC6106 */
+ struct dnssl dnssl_list;
+ int dnssl_length;
+ u_int32_t dnssl_lifetime;
+ u_int32_t dnssl_option_length;
+
/* actual RA packet data and its length */
size_t ra_datalen;
u_char *ra_data;
struct soliciter *soliciter; /* recent solication source */
};
-void ra_timeout __P((void *));
-void ra_timer_update __P((void *, struct timeval *));
+struct rtadvd_timer *ra_timeout(void *);
+void ra_timer_update(void *, struct timeval *);
-int prefix_match __P((struct in6_addr *, int, struct in6_addr *, int));
-struct rainfo *if_indextorainfo __P((int));
+int prefix_match(struct in6_addr *, int, struct in6_addr *, int);
+struct rainfo *if_indextorainfo(int);
+struct prefix *find_prefix(struct rainfo *, struct in6_addr *, int);
extern struct in6_addr in6a_site_allrouters;
-#ifdef MIP6
-extern int mobileip6;
-#endif
-/* $KAME: timer.c,v 1.4 2000/05/27 11:30:43 jinmei Exp $ */
+/* $KAME: timer.c,v 1.9 2002/06/10 19:59:47 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/timer.c,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
#include <sys/time.h>
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
-#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
#include <search.h>
-#endif
#include "timer.h"
static struct rtadvd_timer timer_head;
#define MILLION 1000000
#define TIMEVAL_EQUAL(t1,t2) ((t1)->tv_sec == (t2)->tv_sec &&\
- (t1)->tv_usec == (t2)->tv_usec)
+ (t1)->tv_usec == (t2)->tv_usec)
static struct timeval tm_max = {0x7fffffff, 0x7fffffff};
}
struct rtadvd_timer *
-rtadvd_add_timer(void (*timeout) __P((void *)),
- void (*update) __P((void *, struct timeval *)),
- void *timeodata, void *updatedata)
+rtadvd_add_timer(struct rtadvd_timer *(*timeout)(void *),
+ void (*update)(void *, struct timeval *),
+ void *timeodata, void *updatedata)
{
struct rtadvd_timer *newtimer;
if ((newtimer = malloc(sizeof(*newtimer))) == NULL) {
syslog(LOG_ERR,
- "<%s> can't allocate memory", __FUNCTION__);
+ "<%s> can't allocate memory", __func__);
exit(1);
}
if (timeout == NULL) {
syslog(LOG_ERR,
- "<%s> timeout function unspecfied", __FUNCTION__);
- exit(1);
- }
- if (update == NULL) {
- syslog(LOG_ERR,
- "<%s> update function unspecfied", __FUNCTION__);
+ "<%s> timeout function unspecified", __func__);
exit(1);
}
newtimer->expire = timeout;
}
/*
- * Check expiration for each timer. If a timer is expired,
+ * Check expiration for each timer. If a timer expires,
* call the expire function for the timer and update the timer.
* Return the next interval for select() call.
*/
{
static struct timeval returnval;
struct timeval now;
- struct rtadvd_timer *tm = timer_head.next;
+ struct rtadvd_timer *tm = timer_head.next, *tm_next;
gettimeofday(&now, NULL);
timer_head.tm = tm_max;
- while(tm != &timer_head) {
+ for (tm = timer_head.next; tm != &timer_head; tm = tm_next) {
+ tm_next = tm->next;
+
if (TIMEVAL_LEQ(tm->tm, now)) {
- (*tm->expire)(tm->expire_data);
- (*tm->update)(tm->update_data, &tm->tm);
+ if (((*tm->expire)(tm->expire_data) == NULL))
+ continue; /* the timer was removed */
+ if (tm->update)
+ (*tm->update)(tm->update_data, &tm->tm);
TIMEVAL_ADD(&tm->tm, &now, &tm->tm);
}
if (TIMEVAL_LT(tm->tm, timer_head.tm))
timer_head.tm = tm->tm;
-
- tm = tm->next;
}
if (TIMEVAL_EQUAL(&tm_max, &timer_head.tm)) {
/* no need to timeout */
return(NULL);
- }
- else if (TIMEVAL_LT(timer_head.tm, now)) {
+ } else if (TIMEVAL_LT(timer_head.tm, now)) {
/* this may occur when the interval is too small */
returnval.tv_sec = returnval.tv_usec = 0;
- }
- else
+ } else
TIMEVAL_SUB(&timer_head.tm, &now, &returnval);
return(&returnval);
}
if (TIMEVAL_LEQ(timer->tm, now)) {
syslog(LOG_DEBUG,
"<%s> a timer must be expired, but not yet",
- __FUNCTION__);
+ __func__);
returnval.tv_sec = returnval.tv_usec = 0;
}
else
-/* $KAME: timer.h,v 1.3 2000/05/27 11:30:43 jinmei Exp $ */
+/* $KAME: timer.h,v 1.5 2002/05/31 13:30:38 jinmei Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/usr.sbin/rtadvd/timer.h,v 1.1.2.2 2001/07/03 11:02:14 ume Exp $
*/
/* a < b */
struct rainfo *rai;
struct timeval tm;
- void (*expire) __P((void *)); /* expiration function */
+ struct rtadvd_timer *(*expire)(void *); /* expiration function */
void *expire_data;
- void (*update) __P((void *, struct timeval *)); /* update function */
+ void (*update)(void *, struct timeval *); /* update function */
void *update_data;
};
-void rtadvd_timer_init __P((void));
-struct rtadvd_timer *rtadvd_add_timer __P((void (*) __P((void *)),
- void (*) __P((void *, struct timeval *)), void *, void *));
-void rtadvd_set_timer __P((struct timeval *, struct rtadvd_timer *));
-void rtadvd_remove_timer __P((struct rtadvd_timer **));
-struct timeval * rtadvd_check_timer __P((void));
-struct timeval * rtadvd_timer_rest __P((struct rtadvd_timer *));
-void TIMEVAL_ADD __P((struct timeval *, struct timeval *,
- struct timeval *));
-void TIMEVAL_SUB __P((struct timeval *, struct timeval *,
- struct timeval *));
+void rtadvd_timer_init(void);
+struct rtadvd_timer *rtadvd_add_timer(struct rtadvd_timer *(*)(void *),
+ void (*)(void *, struct timeval *), void *, void *);
+void rtadvd_set_timer(struct timeval *, struct rtadvd_timer *);
+void rtadvd_remove_timer(struct rtadvd_timer **);
+struct timeval * rtadvd_check_timer(void);
+struct timeval * rtadvd_timer_rest(struct rtadvd_timer *);
+void TIMEVAL_ADD(struct timeval *, struct timeval *,
+ struct timeval *);
+void TIMEVAL_SUB(struct timeval *, struct timeval *,
+ struct timeval *);
static void dump_interface_status __P((void));
static char *sec2str __P((time_t));
-char *ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE"};
+char *ifstatstr[] = {
+ "IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE", "OPTIMISTIC"
+};
static void
dump_interface_status()
return 0;
}
- if (!(llflag & IN6_IFF_NOTREADY)) {
+ if (!(llflag & (IN6_IFF_NOTREADY | IN6_IFF_DADPROGRESS))) {
warnmsg(LOG_DEBUG, __FUNCTION__,
"%s is ready", name);
return(0);
name);
return IFS_TENTATIVE;
}
+ if (llflag & IN6_IFF_OPTIMISTIC) {
+ warnmsg(LOG_DEBUG, __FUNCTION__, "%s is optimistic",
+ name);
+ return IFS_OPTIMISTIC;
+ }
if (llflag & IN6_IFF_DUPLICATED)
warnmsg(LOG_DEBUG, __FUNCTION__, "%s is duplicated",
name);
#define IFS_PROBE 2
#define IFS_DOWN 3
#define IFS_TENTATIVE 4
+#define IFS_OPTIMISTIC 5
/* rtsold.c */
extern struct timeval tm_max;