]> git.saurik.com Git - apple/network_cmds.git/commitdiff
network_cmds-396.6.tar.gz mac-os-x-108 mac-os-x-1081 mac-os-x-1082 mac-os-x-1083 mac-os-x-1084 mac-os-x-1085 v396.6
authorApple <opensource@apple.com>
Mon, 30 Apr 2012 22:57:51 +0000 (22:57 +0000)
committerApple <opensource@apple.com>
Mon, 30 Apr 2012 22:57:51 +0000 (22:57 +0000)
59 files changed:
arp.tproj/arp.8
arp.tproj/arp.c
dnctl/dnctl.8 [new file with mode: 0644]
dnctl/dnctl.c [new file with mode: 0644]
ifconfig.tproj/af_inet.c
ifconfig.tproj/af_inet6.c
ifconfig.tproj/ifconfig.c
ifconfig.tproj/ifconfig.h
ip6conf.tproj/6to4.conf [deleted file]
ip6conf.tproj/ip6.8 [deleted file]
ip6conf.tproj/ip6config [deleted file]
ip6conf.tproj/ip6config.8 [deleted file]
ip6conf.tproj/ip6tool.c [deleted file]
ip6fw.tproj/ip6fw.8
mnc.tproj/LICENCE [new file with mode: 0644]
mnc.tproj/README [new file with mode: 0644]
mnc.tproj/mnc.1 [new file with mode: 0644]
mnc.tproj/mnc.h [new file with mode: 0644]
mnc.tproj/mnc_error.c [new file with mode: 0644]
mnc.tproj/mnc_main.c [new file with mode: 0644]
mnc.tproj/mnc_multicast.c [new file with mode: 0644]
mnc.tproj/mnc_opts.c [new file with mode: 0644]
mtest.tproj/mtest.c
mtest.tproj/mtest.plist [deleted file]
ndp.tproj/ndp.8
ndp.tproj/ndp.c
netstat.tproj/if.c
netstat.tproj/inet.c
netstat.tproj/main.c
netstat.tproj/netstat.1
netstat.tproj/netstat.h
netstat.tproj/route.c
network_cmds.plist [new file with mode: 0644]
network_cmds.xcodeproj/project.pbxproj
ping.tproj/ping.8
ping.tproj/ping.c
ping6.tproj/ping6.c
rarpd.tproj/rarpd.c
route.tproj/route.c
rtadvd.tproj/advcap.c
rtadvd.tproj/advcap.h
rtadvd.tproj/config.c
rtadvd.tproj/config.h
rtadvd.tproj/dump.c
rtadvd.tproj/dump.h
rtadvd.tproj/if.c
rtadvd.tproj/if.h
rtadvd.tproj/rrenum.c
rtadvd.tproj/rrenum.h
rtadvd.tproj/rtadvd.8
rtadvd.tproj/rtadvd.c
rtadvd.tproj/rtadvd.conf
rtadvd.tproj/rtadvd.conf.5
rtadvd.tproj/rtadvd.h
rtadvd.tproj/timer.c
rtadvd.tproj/timer.h
rtsol.tproj/dump.c
rtsol.tproj/if.c
rtsol.tproj/rtsold.h

index ab316013b4259414225b4dc6997fd557a7274653..b586c2672d37f1a36b99b7f0f6b732caef28c1e1 100644 (file)
@@ -1,3 +1,29 @@
+.\" 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.
 .\"
@@ -207,6 +233,11 @@ Leading whitespace and empty lines are ignored.
 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 ,
index 665aa94d140b5a646a2632b80ba5be27e4eb9ae0..a152574b225b228b0c51f1694d2f1e977f25e6a4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -135,6 +135,7 @@ static int valid_type(int type);
 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;
@@ -168,7 +169,7 @@ main(int argc, char *argv[])
        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;
@@ -194,6 +195,10 @@ main(int argc, char *argv[])
                case 'i':
                        rifname = optarg;
                        break;
+               case 'x':
+                       xflag = 1;
+                       lflag = 1;
+                       break;
                case '?':
                default:
                        usage();
@@ -220,9 +225,13 @@ main(int argc, char *argv[])
                                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);
@@ -1107,6 +1116,54 @@ print_entry_ext(struct sockaddr_dl *sdl, struct sockaddr_inarp *addr,
                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");
 }
diff --git a/dnctl/dnctl.8 b/dnctl/dnctl.8
new file mode 100644 (file)
index 0000000..19c09d4
--- /dev/null
@@ -0,0 +1,549 @@
+.\"
+.\" $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.
diff --git a/dnctl/dnctl.c b/dnctl/dnctl.c
new file mode 100644 (file)
index 0000000..d913f90
--- /dev/null
@@ -0,0 +1,1309 @@
+/*
+ * 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;
+}
index ccac9b02ebc558dcf8464dd5432d2db3e64f120c..9ad175e305608b94d0cf14325b269cab1eb62199 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
 /*
  * Copyright (c) 1983, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -182,6 +210,19 @@ in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
                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,
@@ -189,6 +230,7 @@ static struct afswtch 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,
index cd5e34a7f9c13c417a4fc4715e3fd60203548004..0f32774d64b4b82b7b73ef86db89a7d1690c2a07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -305,6 +305,8 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
                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)
@@ -516,11 +518,31 @@ in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
                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),
@@ -539,9 +561,10 @@ static struct afswtch af_inet6 = {
        .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,
 };
 
index 934635033ce2c01dc997aadd2174efb26194f9c1..a6cd36dc2bd7564065e324df6f8d0329f2d4757f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -84,7 +84,9 @@ static const char rcsid[] =
 #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>
@@ -117,21 +119,29 @@ int       setmask;
 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);
@@ -184,7 +194,7 @@ main(int argc, char *argv[])
        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__
@@ -244,8 +254,13 @@ main(int argc, char *argv[])
        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.. */
@@ -820,11 +835,128 @@ setifname(const char *val, int dummy __unused, int s,
 }
 #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"
@@ -840,6 +972,12 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
        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;
@@ -861,12 +999,21 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
                        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) {
@@ -921,10 +1068,166 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
        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)
 {
@@ -1126,6 +1429,11 @@ static struct cmd basic_cmds[] = {
        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
@@ -1138,3 +1446,58 @@ ifconfig_ctor(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);
+}
index b2501c782eb28c802b771167f87b29524a52b3f2..1a89a335ef128a93d4ad6bcdcd7d8c0971377f98 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
 /*
  * Copyright (c) 1997 Peter Wemm.
  * All rights reserved.
@@ -114,6 +142,8 @@ struct afswtch {
        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 *);
 
diff --git a/ip6conf.tproj/6to4.conf b/ip6conf.tproj/6to4.conf
deleted file mode 100644 (file)
index b3a3c80..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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/
diff --git a/ip6conf.tproj/ip6.8 b/ip6conf.tproj/ip6.8
deleted file mode 100644 (file)
index feb6cc3..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-.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.
diff --git a/ip6conf.tproj/ip6config b/ip6conf.tproj/ip6config
deleted file mode 100644 (file)
index 7294275..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-#!/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;
-}
diff --git a/ip6conf.tproj/ip6config.8 b/ip6conf.tproj/ip6config.8
deleted file mode 100644 (file)
index 0a1ebdb..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-.\"     $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. 
diff --git a/ip6conf.tproj/ip6tool.c b/ip6conf.tproj/ip6tool.c
deleted file mode 100644 (file)
index 8d044f9..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*     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;
-}
index ef3f9a8522bb44d8c04307f4421f4910ab83f112..61771a0148191d4c121d8986e227b6c238b8f4e2 100644 (file)
@@ -79,6 +79,12 @@ to
 .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
diff --git a/mnc.tproj/LICENCE b/mnc.tproj/LICENCE
new file mode 100644 (file)
index 0000000..4fec3e3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ */
+
diff --git a/mnc.tproj/README b/mnc.tproj/README
new file mode 100644 (file)
index 0000000..291ce1a
--- /dev/null
@@ -0,0 +1,63 @@
+                             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.
diff --git a/mnc.tproj/mnc.1 b/mnc.tproj/mnc.1
new file mode 100644 (file)
index 0000000..ed1073b
--- /dev/null
@@ -0,0 +1,101 @@
+.\"
+.\" 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>
diff --git a/mnc.tproj/mnc.h b/mnc.tproj/mnc.h
new file mode 100644 (file)
index 0000000..db6e68e
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * $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_ */
diff --git a/mnc.tproj/mnc_error.c b/mnc.tproj/mnc_error.c
new file mode 100644 (file)
index 0000000..4478e7e
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * $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);
+}
diff --git a/mnc.tproj/mnc_main.c b/mnc.tproj/mnc_main.c
new file mode 100644 (file)
index 0000000..1e5c5af
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * $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;
+}
diff --git a/mnc.tproj/mnc_multicast.c b/mnc.tproj/mnc_multicast.c
new file mode 100644 (file)
index 0000000..35f3415
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * $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;
+}
diff --git a/mnc.tproj/mnc_opts.c b/mnc.tproj/mnc_opts.c
new file mode 100644 (file)
index 0000000..606746f
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * $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;
+}
index 0401832179223ba37c0e16826eb8e6ba3273c169..12eb891160d8a32e5336d89b52d364ebc596c080 100644 (file)
@@ -374,7 +374,7 @@ process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused)
        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__ */
diff --git a/mtest.tproj/mtest.plist b/mtest.tproj/mtest.plist
deleted file mode 100644 (file)
index 8b726f1..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<array>
-       <dict>
-               <key>OpenSourceProject</key>
-               <string>mtest</string>
-               <key>OpenSouceVersion</key>
-               <string>1.11</string>
-               <key>OpenSourceWebsiteURL</key>
-               <string>http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/</string>
-               <key>OpenSourceURL</key>
-               <string>http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/</string>
-               <key>OpenSourceSHA1</key>
-               <string></string>
-               <key>OpenSourceMD5</key>
-               <string></string>
-               <key>OpenSourceImportDate</key>
-               <string>2011-01-13</string>
-               <key>OpenSourceLicense</key>
-               <string>Other</string>
-               <key>OpenSourceLicenseFile</key>
-               <string>mtest.txt</string>
-       </dict>
-</array>
-</plist>
index a030fc5de358d98c66d41fde3ac1c027b40080fd..bf480d4b6b2cde1f094c36e70b0bddaea562f0c7 100644 (file)
@@ -1,3 +1,29 @@
+.\" 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 $
 .\"
@@ -165,6 +191,11 @@ to make it possible to merge output with
 .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
index 096551b541656e2971b11e753b9626bc187eb9a2..76770171c26164fe2934f3b6122a005d970f44a9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -169,7 +169,7 @@ int set __P((int, char **));
 void get __P((char *));
 int delete __P((char *));
 void dump __P((struct in6_addr *));
-void dump_ext __P((struct in6_addr *));
+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 *));
@@ -205,11 +205,12 @@ main(argc, argv)
 {
        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;
@@ -275,6 +276,10 @@ main(argc, argv)
                case 'R':
                        Rflag = 1;
                        break;
+               case 'x':
+                       xflag = 1;
+                       lflag = 1;
+                       break;
                default:
                        usage();
                }
@@ -284,7 +289,7 @@ main(argc, argv)
 
        if (aflag || cflag) {
                if (lflag)
-                       dump_ext(0);
+                       dump_ext(0, xflag);
                else
                        dump(0);
                exit(0);
@@ -593,7 +598,6 @@ dump(addr)
        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;
@@ -785,8 +789,9 @@ again:;
  * 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;
@@ -794,7 +799,6 @@ dump_ext(addr)
        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;
@@ -804,11 +808,15 @@ dump_ext(addr)
        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;
@@ -981,6 +989,54 @@ again:;
                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)
@@ -1184,6 +1240,8 @@ ifinfo(argc, argv)
                }\
        } 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) {
@@ -1229,6 +1287,12 @@ ifinfo(argc, argv)
                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
@@ -1386,12 +1450,13 @@ plist()
                 * 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
index 962a3ba40934002d514499096c812512882f1563..70e57058901c49881a6ac434be9ffa0b9c318c5c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -69,6 +69,7 @@ static const char rcsid[] =
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
+#include <sys/ioctl.h>
 #include <sys/time.h>
 
 #include <net/if.h>
@@ -80,6 +81,9 @@ static const char rcsid[] =
 #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>
 
@@ -108,6 +112,42 @@ static void sidewaysintpr ();
 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 *);
@@ -277,19 +317,19 @@ intpr(void (*pfunc)(char *))
                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)
@@ -307,7 +347,11 @@ intpr(void (*pfunc)(char *))
                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;
@@ -364,6 +408,12 @@ intpr(void (*pfunc)(char *))
                                        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;
@@ -387,8 +437,16 @@ intpr(void (*pfunc)(char *))
                                                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);
@@ -488,6 +546,8 @@ intpr(void (*pfunc)(char *))
                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);
@@ -495,6 +555,8 @@ intpr(void (*pfunc)(char *))
                        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);
@@ -504,6 +566,8 @@ intpr(void (*pfunc)(char *))
                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);
@@ -511,6 +575,8 @@ intpr(void (*pfunc)(char *))
                        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);
@@ -545,6 +611,10 @@ struct     iftot {
        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" */
@@ -620,7 +690,7 @@ sidewaysintpr()
        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",
@@ -629,13 +699,13 @@ banner:
        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;
@@ -659,12 +729,18 @@ loop:
                        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,
@@ -683,6 +759,11 @@ loop:
                                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,
@@ -691,6 +772,11 @@ loop:
                        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,
@@ -709,6 +795,11 @@ loop:
                                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;
@@ -720,6 +811,12 @@ loop:
                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;
@@ -741,6 +838,12 @@ loop:
                        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;
@@ -790,6 +893,10 @@ loop:
                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;
                        
@@ -805,6 +912,12 @@ loop:
                        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;
@@ -826,6 +939,10 @@ loop:
                                        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) {
@@ -834,9 +951,11 @@ loop:
                                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,
@@ -845,9 +964,11 @@ loop:
                        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;
        }
@@ -979,8 +1100,12 @@ intpr_ri(void (*pfunc)(char *))
                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;
@@ -1063,9 +1188,59 @@ llreach_sysctl(uint32_t ifindex)
                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");
@@ -1075,3 +1250,786 @@ out_free:
        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;
+       }
+}
index ffad668e3680f621ebe4a5faf6820594b1133cb1..dd17d2740176839f41d386e69639dfec243c0aed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -183,7 +183,7 @@ _serv_cache_getservbyport(int port, char *proto)
        return &s;
 }
 
-#endif SRVCACHE
+#endif /* SRVCACHE */
        
 /*
  * Print a summary of connections related to an Internet
@@ -191,7 +191,6 @@ _serv_cache_getservbyport(int port, char *proto)
  * Listening processes (aflag) are suppressed unless the
  * -a (all) flag is specified.
  */
-#if !TARGET_OS_EMBEDDED
 
 struct xgen_n {
        u_int32_t       xgn_len;                        /* length of this structure */
@@ -354,12 +353,14 @@ protopr(uint32_t proto,           /* for sysctl version we pass proto # */
                                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");
@@ -392,6 +393,7 @@ protopr(uint32_t proto,             /* for sysctl version we pass proto # */
 #else
                        printf("%8lx ", (u_long)so->so_pcb);
 #endif
+                       printf("%8x ", inp->inp_flowhash);
                }
                if (Lflag) {
                        char buf[15];
@@ -520,258 +522,6 @@ protopr(uint32_t proto,           /* for sysctl version we pass proto # */
        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.
  */
@@ -820,6 +570,7 @@ tcp_stats(uint32_t off , char *name, int af )
        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");
index f77b6f32e0b2bf317576ab3566fd887503003d57..efc37ddbc8db4b8d1fbe12b629d64df8dcebb477 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -274,6 +274,7 @@ extern void _serv_cache_close();
 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 */
@@ -291,7 +292,11 @@ int        sflag;          /* show protocol statistics */
 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 */
@@ -309,7 +314,7 @@ main(argc, argv)
 
        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;
@@ -320,6 +325,10 @@ main(argc, argv)
                case 'b':
                        bflag = 1;
                        break;
+               case 'c':
+                       cflag = 1;
+                       cq = atoi(optarg);
+                       break;
                case 'd':
                        dflag = 1;
                        break;
@@ -382,6 +391,12 @@ main(argc, argv)
                        }
                        pflag = 1;
                        break;
+               case 'q':
+                       qflag++;
+                       break;
+               case 'Q':
+                       Qflag++;
+                       break;
                case 'R':
                        Rflag = 1;
                        break;
@@ -407,6 +422,10 @@ main(argc, argv)
                        interval = atoi(optarg);
                        iflag = 1;
                        break;
+               case 'x':
+                       xflag = 1;
+                       Rflag = 1;
+                       break;
                case '?':
                default:
                        usage();
@@ -431,7 +450,7 @@ main(argc, argv)
                mbpr();
                exit(0);
        }
-       if (iflag && !sflag && !gflag) {
+       if (iflag && !sflag && !gflag && !qflag && !Qflag) {
                if (Rflag)
                        intpr_ri(NULL);
                else
@@ -445,6 +464,19 @@ main(argc, argv)
                        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                
index c54ef88b84bd4ba30afca9cfcc1b02062bf5ef16..86e711ee63a895a85c8a1535dfd3f30a20005487 100644 (file)
@@ -1,3 +1,29 @@
+.\" 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.
 .\"
@@ -50,7 +76,8 @@
 .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
@@ -95,7 +122,7 @@ The options have the following meaning:
 .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
@@ -107,6 +134,11 @@ parent route); normally these routes are not shown.
 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
@@ -196,6 +228,18 @@ is used to show bridging statistics.  A null response typically means that there
 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
@@ -224,6 +268,11 @@ overflow.
 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
 .\"-------------------------------------------------------------------------------
@@ -328,10 +377,12 @@ L RTF_LLINFO      Valid protocol to link address translation
 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;
@@ -343,7 +394,9 @@ obtain a route while sending to the same destination.  The use field
 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
index bcc42145557abaa1df57bd5f02a59d6b981f6fca..da71069e290c3a1f4fb22ffc85872d056027da3e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -69,6 +69,7 @@
 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 */
@@ -85,7 +86,11 @@ extern int   prioflag; /* show packet priority  statistics */
 extern int     tflag;  /* show i/f watchdog timers */
 extern int     vflag;  /* more verbose */
 extern int     Wflag;  /* wide display */
+extern int     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 */
@@ -149,6 +154,8 @@ extern char *netname(uint32_t, uint32_t);
 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);
index 885a19bd86905fa6626d47ccca2c6ca2897e64d1..203cb1439df545c7b4e9f1544d99a96023a01a11 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -116,9 +116,9 @@ struct bits {
        { 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 }
 };
 
diff --git a/network_cmds.plist b/network_cmds.plist
new file mode 100644 (file)
index 0000000..9d6cf73
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+       <dict>
+               <key>OpenSourceProject</key>
+               <string>mtest</string>
+               <key>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>
index ca9bdf623687a7d883fd36938836481e1cd9eead..a642039a3c5f3d17a51712d5c94614dd843017f9 100644 (file)
                        );
                        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 */,
@@ -68,8 +70,8 @@
                        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 */;
index feb8e7653b59ee9d253e4c0ea11413c2126e0916..076092279cf3afea97c5aaefd9347f97a2c3e8a4 100644 (file)
@@ -337,8 +337,8 @@ When the specified number of packets have been sent
 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
index 7227bd42a8c9298cfcc6cd10e9218571d0dda168..8290b7a5024fd425384dbae2d19a248602ebc58e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -208,7 +208,7 @@ char boundifname[IFNAMSIZ];
 #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 */
@@ -719,14 +719,14 @@ main(argc, argv)
        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
@@ -1117,7 +1117,7 @@ pinger(void)
                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))];
index 4892b95a665de1536f48ade082f87d5fe02373c0..5a1b25d86d4cc7eadb9aacd5438e04da1d38b7f0 100644 (file)
@@ -265,7 +265,7 @@ volatile sig_atomic_t seeninfo;
 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 *);
@@ -493,7 +493,7 @@ main(argc, argv)
                        how_so_traffic_class++;
                        so_traffic_class = atoi(optarg);
                        break;
-                       
+
                case 'l':
                        if (getuid()) {
                                errno = EPERM;
@@ -918,18 +918,18 @@ main(argc, argv)
        if (tclass != -2)
                ip6optlen += CMSG_SPACE(sizeof(int));
 
-       if (how_so_traffic_class == 1 && so_traffic_class > 0) {
-               (void)setsockopt(s, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&so_traffic_class,
-                                                sizeof(so_traffic_class));
-       } 
+       if (how_so_traffic_class < 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)
@@ -1028,12 +1028,12 @@ main(argc, argv)
 
                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)) {
@@ -1650,10 +1650,10 @@ pr_pack(buf, cc, mhdr)
                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;
index d26a1e4582bf36409c05eeb99117f9c529b81ac1..fcea9bcb3a573b3c42121da13230a351d1da69a8 100644 (file)
@@ -129,7 +129,6 @@ main(argc, argv)
        int     op, pid, devnull, f;
        char   *ifname, *hostname, *name;
 
-       extern char *optarg;
        extern int optind, opterr;
 
        if ((name = strrchr(argv[0], '/')) != NULL)
index 818bdd0fbf7cdf9a0a50c6f12ed2060f88140889..23cba41d5b4557139c4e6c93c050f30616d996df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -1297,7 +1297,7 @@ char routeflags[] =
 "\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"
@@ -1350,10 +1350,8 @@ print_rtmsg(rtm, msglen)
                        (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);
@@ -1371,7 +1369,7 @@ print_getmsg(rtm, msglen)
        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);
index cc01ae2a2b03c80b845b5fb83f7aca1b70f2c201..2c9e34da0a955368003cb75c6dc870d5e5949c8f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -26,7 +26,7 @@
  * @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.
@@ -59,8 +59,6 @@
  * 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 $
  */
 
 /*
@@ -120,15 +118,15 @@ static    char *remotefile;
 
 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,
@@ -149,8 +147,8 @@ int
 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;
 
@@ -168,7 +166,7 @@ getent(bp, name, cp)
        }
        if (tf < 0) {
                syslog(LOG_INFO,
-                      "<%s> open: %s", __FUNCTION__, strerror(errno));
+                      "<%s> open: %s", __func__, strerror(errno));
                return (-2);
        }
        for (;;) {
@@ -190,8 +188,9 @@ getent(bp, name, cp)
                                }
                                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;
@@ -218,7 +217,7 @@ getent(bp, name, cp)
 int
 tnchktc()
 {
-       register char *p, *q;
+       char *p, *q;
        char tcname[16];        /* name of similar terminal */
        char tcbuf[BUFSIZ];
        char *holdtbuf = tbuf;
@@ -226,21 +225,21 @@ tnchktc()
 
        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) {
@@ -252,7 +251,7 @@ tnchktc()
 
        /* 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);
@@ -270,7 +269,7 @@ int
 tnamatch(np)
        char *np;
 {
-       register char *Np, *Bp;
+       char *Np, *Bp;
 
        Bp = tbuf;
        if (*Bp == '#')
@@ -295,7 +294,7 @@ tnamatch(np)
  */
 static char *
 tskip(bp)
-       register char *bp;
+       char *bp;
 {
        int dquote;
 
@@ -338,13 +337,13 @@ breakbreak:
  * 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);
@@ -378,7 +377,7 @@ int
 tgetflag(id)
        char *id;
 {
-       register char *bp = tbuf;
+       char *bp = tbuf;
 
        for (;;) {
                bp = tskip(bp);
@@ -406,7 +405,7 @@ char *
 tgetstr(id, area)
        char *id, **area;
 {
-       register char *bp = tbuf;
+       char *bp = tbuf;
 
        for (;;) {
                bp = tskip(bp);
@@ -430,12 +429,12 @@ tgetstr(id, area)
  */
 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;
 
index 44d90e6ced9cfb668544d598f2278e5f3d79915d..1b42b4065f0c50ee96682745afe526f4a77073ea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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.
@@ -24,8 +24,6 @@
  * 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
 
index c2746e9e43b0368557b125bdf7128abf72dfed6f..ac25640db4b190f9f6dcb189a0a02b058ff9fc53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -26,7 +26,7 @@
  * @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.
@@ -55,8 +55,6 @@
  * 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>
@@ -66,9 +64,7 @@
 #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>
 
@@ -77,9 +73,7 @@
 #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);                                  \
@@ -142,14 +140,22 @@ getconfig(char *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) {
@@ -166,7 +172,7 @@ getconfig(char *intface)
                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;
@@ -177,7 +183,7 @@ getconfig(char *intface)
                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);
        }
 
        /*
@@ -186,17 +192,18 @@ getconfig(char *intface)
        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);
        }
@@ -205,31 +212,46 @@ getconfig(char *intface)
        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);
        }
        /*
@@ -241,207 +263,165 @@ getconfig(char *intface)
         * 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;
@@ -454,118 +434,196 @@ getconfig(char *intface)
        }
        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;
@@ -579,13 +637,12 @@ getconfig(char *intface)
            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));
@@ -593,32 +650,116 @@ getconfig(char *intface)
                /* 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;
@@ -633,22 +774,25 @@ getconfig(char *intface)
        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)
@@ -656,45 +800,49 @@ get_prefix(struct rainfo *rai)
                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;
@@ -702,6 +850,7 @@ get_prefix(struct rainfo *rai)
                pp->onlinkflg = 1;
                pp->autoconfflg = 1;
                pp->origin = PREFIX_FROM_KERNEL;
+               pp->rainfo = rai;
 
                /* link into chain */
                insque(pp, &rai->prefix);
@@ -714,34 +863,35 @@ get_prefix(struct rainfo *rai)
 }
 
 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));
@@ -754,10 +904,11 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
        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 */
@@ -767,13 +918,6 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
        /* 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);
 }
 
 /*
@@ -782,18 +926,82 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
  * 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);
 }
 
 /*
@@ -804,16 +1012,17 @@ delete_prefix(struct rainfo *rai, struct prefix *prefix)
 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;
@@ -823,12 +1032,12 @@ init_prefix(struct in6_prefixreq *ipr)
                /* 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;
@@ -836,6 +1045,13 @@ init_prefix(struct in6_prefixreq *ipr)
 
        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
@@ -846,7 +1062,7 @@ make_prefix(struct rainfo *rai, int ifindex, struct in6_addr *addr, int plen)
        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);
        }
@@ -864,17 +1080,15 @@ void
 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);
@@ -882,9 +1096,8 @@ make_packet(struct rainfo *rainfo)
                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;
@@ -893,13 +1106,7 @@ make_packet(struct rainfo *rainfo)
                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;
@@ -907,11 +1114,15 @@ make_packet(struct rainfo *rainfo)
        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) {
@@ -919,7 +1130,7 @@ make_packet(struct rainfo *rainfo)
                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;
 
@@ -941,10 +1152,6 @@ make_packet(struct rainfo *rainfo)
                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);
@@ -964,30 +1171,6 @@ make_packet(struct rainfo *rainfo)
                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;
@@ -1004,23 +1187,26 @@ make_packet(struct rainfo *rainfo)
                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
@@ -1036,7 +1222,7 @@ make_packet(struct rainfo *rainfo)
                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;
 
@@ -1045,7 +1231,7 @@ make_packet(struct rainfo *rainfo)
                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;
        }
@@ -1072,6 +1258,39 @@ make_packet(struct rainfo *rainfo)
                }
        }
 
+       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;
 }
 
@@ -1087,10 +1306,39 @@ getinet6sysctl(int code)
        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);
+}
index f6bd0831f64026c6046fbbf9a08ad8e3d27bf591..f1f0387a5a6338a2df546bef864085b4fd6ba43b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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
index 03f4575ba17649cecfc9a250c8f2b6728f4a60ff..fad2a618f9a3178290de173df1abc965140333f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -26,7 +26,7 @@
  * @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>
@@ -92,14 +88,8 @@ static FILE *fp;
 
 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 */
@@ -112,19 +102,17 @@ static char *
 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
@@ -132,6 +120,9 @@ if_dump()
 {
        struct rainfo *rai;
        struct prefix *pfx;
+#ifdef ROUTEINFO
+       struct rtinfo *rti;
+#endif
        char prefixbuf[INET6_ADDRSTRLEN];
        int first;
        struct timeval now;
@@ -148,11 +139,11 @@ if_dump()
                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");
@@ -160,46 +151,35 @@ if_dump()
                        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) {
@@ -207,10 +187,9 @@ if_dump()
                                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;
@@ -246,12 +225,38 @@ if_dump()
                        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
        }
 }
 
@@ -259,9 +264,12 @@ void
 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;
        }
 
index eb73c3662ef6677ee3ff83f43369347b71db5b82..4e10b4a8ce7bf30c9d3a05b473e066150c0f1989 100644 (file)
@@ -27,8 +27,6 @@
  * 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 *);
index 7d7048240855ab892e4073ee27b041ab34aed916..db83a699daf66cb6baf56f9efc230ee1bea20278 100644 (file)
@@ -27,8 +27,6 @@
  * 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>
@@ -75,9 +62,9 @@ int iflist_init_ok;
 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)
@@ -102,14 +89,16 @@ if_nametosdl(char *name)
        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) {
@@ -133,7 +122,8 @@ if_nametosdl(char *name)
        }
        if (next == lim) {
                /* search failed */
-               goto end;
+               free(buf);
+               return(NULL);
        }
 
        if ((ret_sdl = malloc(sdl->sdl_len)) == NULL)
@@ -142,7 +132,7 @@ if_nametosdl(char *name)
 
 end:
        free(buf);
-       return (ret_sdl);
+       return(ret_sdl);
 }
 
 int
@@ -196,7 +186,7 @@ if_getflags(int ifindex, int oifflags)
        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);
        }
@@ -204,7 +194,7 @@ if_getflags(int ifindex, int oifflags)
        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);
        }
@@ -216,11 +206,11 @@ if_getflags(int ifindex, int oifflags)
 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);
        }
 }
 
@@ -231,17 +221,16 @@ lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
 
        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;
@@ -277,7 +266,7 @@ get_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter)
                /* 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;
                }
@@ -496,16 +485,16 @@ get_iflist(char **buf, size_t *size)
 
        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;
@@ -531,7 +520,7 @@ parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
        /* 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);
        }
 
@@ -539,7 +528,7 @@ parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
        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;
                }
@@ -562,7 +551,7 @@ parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
                        /* 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;
                        }
index 06d2d72287d2dfef662736c16f535ba8369d09eb..32c70ae8bc971ed59c3617f204ad4a5a21489b13 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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.
@@ -27,8 +27,6 @@
  * 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)
@@ -38,22 +36,22 @@ extern size_t ifblock_size;
 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);
index 1ba14ec6cf2d7a0d5187b65d3031ad490cce8cc9..bdac431deda9c31db49f1f2062c63af917b1d57b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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.
@@ -27,8 +27,6 @@
  * 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>
@@ -37,9 +35,7 @@
 #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>
@@ -89,24 +85,24 @@ rr_pco_check(int len, struct rr_pco_match *rpm)
        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;
        }
 
@@ -130,7 +126,7 @@ rr_pco_check(int len, struct rr_pco_match *rpm)
                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;
@@ -166,7 +162,7 @@ do_use_prefix(int len, struct rr_pco_match *rpm,
                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;
        }
@@ -179,9 +175,9 @@ do_use_prefix(int len, struct rr_pco_match *rpm,
                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 =
@@ -198,7 +194,7 @@ do_use_prefix(int len, struct rr_pco_match *rpm,
 
                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 */
@@ -251,7 +247,7 @@ do_pco(struct icmp6_router_renum *rr, int len, struct rr_pco_match *rpm)
                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);
        }
@@ -279,7 +275,7 @@ do_pco(struct icmp6_router_renum *rr, int len, struct rr_pco_match *rpm)
        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;
        }
@@ -311,7 +307,7 @@ do_rr(int len, struct icmp6_router_renum *rr)
                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;
@@ -319,7 +315,7 @@ do_rr(int len, struct icmp6_router_renum *rr)
                        goto tooshort;
 
                if (do_pco(rr, rpmlen, rpm)) {
-                       syslog(LOG_WARNING, "<%s> invalid PCO", __FUNCTION__);
+                       syslog(LOG_WARNING, "<%s> invalid PCO", __func__);
                        goto next;
                }
 
@@ -339,14 +335,14 @@ static int
 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;
        }
 
@@ -354,8 +350,8 @@ rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from,
        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;
        }
 
@@ -363,8 +359,8 @@ rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from,
        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 &&
@@ -373,8 +369,8 @@ rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from,
                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;
        }
@@ -414,7 +410,7 @@ rr_command_input(int len, struct icmp6_router_renum *rr,
        return;
 
     failed:
-       syslog(LOG_ERR, "<%s> received RR was invalid", __FUNCTION__);
+       syslog(LOG_ERR, "<%s> received RR was invalid", __func__);
        return;
 }
 
@@ -422,25 +418,25 @@ void
 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;
        }
 
@@ -457,11 +453,11 @@ rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi,
                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;
        }
 
@@ -480,7 +476,7 @@ rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi,
                break;
        default:
                syslog(LOG_ERR, "<%s> received unknown code %d",
-                      __FUNCTION__, rr->rr_code);
+                      __func__, rr->rr_code);
                break;
 
        }
index ad8db33b6e8f7f855f9282c43059995da67f6e57..b6ed486cc1479ee3b66c2b25127fbe5f85b58b7e 100644 (file)
@@ -27,9 +27,7 @@
  * 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 *);
index 4ec5483802e685142d1b0d22d68bb8d2b0fac600..69ebe9ab0689bdc6c4512269474c106de723cab6 100644 (file)
@@ -1,5 +1,5 @@
 .\"    $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.
@@ -28,7 +28,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 17, 1998
+.Dd August 27, 2011
 .Dt RTADVD 8
 .Os
 .Sh NAME
@@ -38,6 +38,8 @@
 .Nm
 .Op Fl dDfMRs
 .Op Fl c Ar configfile
+.Op Fl F Ar dumpfile
+.Op Fl p Ar pidfile
 .Ar interface ...
 .Sh DESCRIPTION
 .Nm
@@ -63,20 +65,42 @@ them as on-link prefixes.
 .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
@@ -102,25 +126,30 @@ Print debugging information.
 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.
@@ -133,7 +162,9 @@ Upon receipt of signal
 .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
@@ -144,30 +175,28 @@ In this case,
 .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
index 0a454d861aced8cee6ab71f254c8f69eb4dab7ad..a4dff6d0e67036480369f1834e28512b7cef4285 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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.
@@ -27,8 +27,6 @@
  * 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>
@@ -53,6 +51,7 @@
 #include <stdlib.h>
 #include <err.h>
 #include <errno.h>
+#include <libutil.h>
 #include <string.h>
 #include <stdlib.h>
 #include <syslog.h>
@@ -69,26 +68,25 @@ static u_char *rcvcmsgbuf;
 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 {
@@ -96,7 +94,7 @@ 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;
@@ -122,98 +120,91 @@ union nd_opts {
 
 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));
@@ -236,38 +227,53 @@ main(argc, argv)
                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;
@@ -284,37 +290,37 @@ main(argc, argv)
 
                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;
 }
@@ -335,7 +341,7 @@ die()
 
        if (dflag > 1) {
                syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n",
-                   __FUNCTION__);
+                   __func__);
        }
 
        for (ra = ralist; ra; ra = ra->next) {
@@ -347,6 +353,7 @@ die()
                        ra_output(ra);
                sleep(MIN_DELAY_BETWEEN_RAS);
        }
+       pidfile_remove(pfh);
        exit(0);
        /*NOTREACHED*/
 }
@@ -357,19 +364,17 @@ rtmsg_input()
        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)) {
                /*
@@ -378,10 +383,10 @@ rtmsg_input()
                 */
                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);
@@ -418,8 +423,8 @@ rtmsg_input()
                        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;
                }
@@ -429,131 +434,139 @@ rtmsg_input()
                                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);
                }
        }
 
@@ -572,7 +585,7 @@ rtadvd_input()
        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;
 
        /*
@@ -603,25 +616,27 @@ rtadvd_input()
        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;
        }
 
@@ -629,7 +644,7 @@ rtadvd_input()
        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;
        }
 
@@ -639,111 +654,109 @@ rtadvd_input()
        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;
@@ -753,28 +766,29 @@ static void
 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;
        }
 
@@ -785,11 +799,11 @@ rs_input(int len, struct nd_router_solicit *rs,
         */
        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;
        }
 
@@ -802,8 +816,8 @@ rs_input(int len, struct nd_router_solicit *rs,
        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;
        }
 
@@ -813,79 +827,83 @@ rs_input(int len, struct nd_router_solicit *rs,
         * 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;
@@ -893,10 +911,10 @@ ra_input(int len, struct nd_router_advert *ra,
 
        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));
@@ -904,12 +922,12 @@ ra_input(int len, struct nd_router_advert *ra,
                        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;
        }
 
@@ -920,10 +938,10 @@ ra_input(int len, struct nd_router_advert *ra,
                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 */
@@ -934,11 +952,11 @@ ra_input(int len, struct nd_router_advert *ra,
                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++;
        }
@@ -948,11 +966,11 @@ ra_input(int len, struct nd_router_advert *ra,
                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++;
        }
@@ -962,11 +980,11 @@ ra_input(int len, struct nd_router_advert *ra,
                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++;
        }
@@ -977,11 +995,11 @@ ra_input(int len, struct nd_router_advert *ra,
                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++;
        }
@@ -992,11 +1010,11 @@ ra_input(int len, struct nd_router_advert *ra,
                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++;
        }
@@ -1007,10 +1025,10 @@ ra_input(int len, struct nd_router_advert *ra,
                        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++;
                }
@@ -1047,7 +1065,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
        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 */
@@ -1062,12 +1080,12 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
                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);
        }
 
@@ -1075,12 +1093,12 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
                              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);
        }
@@ -1097,35 +1115,34 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
                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);
        }
 
@@ -1134,35 +1151,34 @@ prefix_check(struct nd_opt_prefix_info *pinfo,
                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++;
        }
@@ -1175,17 +1191,21 @@ find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
 {
        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);
@@ -1197,16 +1217,20 @@ prefix_match(struct in6_addr *p0, int plen0,
             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);
 }
@@ -1218,68 +1242,84 @@ nd6_options(struct nd_opt_hdr *hdr, int limit,
        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;
                }
        }
 
@@ -1296,7 +1336,7 @@ free_ndopts(union nd_opts *ndopts)
 {
        struct nd_optlist *opt = ndopts->nd_opts_list, *next;
 
-       while(opt) {
+       while (opt) {
                next = opt->next;
                free(opt);
                opt = next;
@@ -1317,7 +1357,7 @@ sock_open()
                                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);
        }
 
@@ -1325,30 +1365,33 @@ sock_open()
                                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 
@@ -1359,14 +1402,14 @@ sock_open()
        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
@@ -1379,7 +1422,7 @@ sock_open()
        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);
        }
 
@@ -1390,15 +1433,15 @@ sock_open()
                      &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;
@@ -1412,7 +1455,7 @@ sock_open()
                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;
@@ -1421,7 +1464,7 @@ sock_open()
                            == 0) {
                                syslog(LOG_ERR,
                                       "<%s> invalid interface: %s",
-                                      __FUNCTION__, mcastif);
+                                      __func__, mcastif);
                                exit(1);
                        }
                } else
@@ -1430,7 +1473,7 @@ sock_open()
                               &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);
@@ -1440,8 +1483,8 @@ sock_open()
        /* 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;
@@ -1463,18 +1506,18 @@ rtsock_open()
 {
        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);
        }
 
@@ -1492,7 +1535,7 @@ struct rainfo *rainfo;
 
        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;
        }
 
@@ -1524,17 +1567,21 @@ struct rainfo *rainfo;
 
        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
@@ -1544,29 +1591,11 @@ struct rainfo *rainfo;
        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);
 
@@ -1575,7 +1604,7 @@ struct rainfo *rainfo;
 }
 
 /* process RA timer */
-void
+struct rtadvd_timer *
 ra_timeout(void *data)
 {
        struct rainfo *rai = (struct rainfo *)data;
@@ -1586,9 +1615,11 @@ ra_timeout(void *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 */
@@ -1623,7 +1654,7 @@ ra_timer_update(void *data, struct timeval *tm)
 
        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;
index 4c653ed598cd4d94095f0d7a0e088598c82576cb..6d109b2a1eddfc2558e2d60cba930404e1618574 100644 (file)
@@ -1,5 +1,4 @@
-#      $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
@@ -18,4 +17,4 @@
 #   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:
index c9e9ba31f15392ac2ff75d90d8a0d2fd1ce41088..87978fcb212172aa017635c600c2b9a1e5d2be25 100644 (file)
@@ -1,5 +1,4 @@
-.\"    $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.
@@ -28,7 +27,7 @@
 .\" 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
@@ -80,14 +79,14 @@ will use the default values.
 .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 *
@@ -105,24 +104,55 @@ will use the default values.
 (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
@@ -131,11 +161,11 @@ advertising interfaces as described in
 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
@@ -145,11 +175,16 @@ These items can be omitted, then
 .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
@@ -157,34 +192,27 @@ real time.
 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
@@ -193,23 +221,19 @@ is used for
 .Xr termcap 5
 file format as well as IPv6 numeric address, the field MUST be quoted by
 doublequote character.
-This field cannot be
-omitted if the value of
-.Cm 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
@@ -237,9 +261,11 @@ will use the default value.
 .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.
@@ -249,7 +275,7 @@ will not attach source link-layer address option to
 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
@@ -272,32 +298,11 @@ explicitly.
 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 \&:
@@ -305,15 +310,49 @@ is used for
 .Xr termcap 5
 file format as well as IPv6 numeric address, the field MUST be quoted by
 doublequote character.
-This field cannot be
-omitted if the value of
-.Cm 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.
@@ -361,6 +400,41 @@ 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
+.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
@@ -388,7 +462,7 @@ option to
 .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.
@@ -397,32 +471,34 @@ YOU DO NOT NEED TO HAVE IT AT ALL.
 .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
index 332b799b7e4fc258b94865dc7ec394a3c9c800a4..fdd897774e06c8e3f62246974bfd393c406026a4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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
@@ -75,29 +66,34 @@ struct prefix {
        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;
@@ -111,6 +107,13 @@ struct rdnss {
        struct in6_addr addr;
 };
 
+struct dnssl {
+       struct dnssl *next;
+       struct dnssl *prev;
+
+       char domain[1];
+};
+
 struct rainfo {
        /* pointer for list */
        struct  rainfo *next;
@@ -134,9 +137,7 @@ struct      rainfo {
        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 */
@@ -146,18 +147,22 @@ struct    rainfo {
        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;
@@ -172,13 +177,11 @@ struct    rainfo {
        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
index 4cce63bac18a0b7892bfee506323b8d1d467a9e0..b03b4bf2012cb4a3e329d0f18d05dc2ace46d436 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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.
@@ -27,8 +27,6 @@
  * 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};
 
@@ -60,15 +56,15 @@ rtadvd_timer_init()
 }
 
 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);
        }
 
@@ -76,12 +72,7 @@ rtadvd_add_timer(void (*timeout) __P((void *)),
 
        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;
@@ -122,7 +113,7 @@ rtadvd_set_timer(struct timeval *tm, struct rtadvd_timer *timer)
 }
 
 /*
- * 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.
  */
@@ -131,34 +122,34 @@ rtadvd_check_timer()
 {
        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);
 }
@@ -172,7 +163,7 @@ rtadvd_timer_rest(struct rtadvd_timer *timer)
        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
index 63705a1af8d41f6005e7906d2e07366f641fbd09..78314b723738c029efbfbefd4bdfa4b1cf81746c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $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.
@@ -27,8 +27,6 @@
  * 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 */
@@ -47,20 +45,20 @@ struct rtadvd_timer {
        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 *);
index c42f8f545d4ec6a8a7f865d966112f4e3b39012e..69937f02bf6182068c5b4e532be2bdca3fbd55b5 100644 (file)
@@ -81,7 +81,9 @@ extern struct ifinfo *iflist;
 
 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()
index d361c27902a31f249f63df6ba3d2f6400e3ba0df..79da223619981798bddde92cb279aa292d22508a 100644 (file)
@@ -151,7 +151,7 @@ interface_up(char *name)
                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);
@@ -161,6 +161,11 @@ interface_up(char *name)
                               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);
index dccbc57ed142595779a92b5f8d4332bb70cfeab8..fdda5398a109aaa6e93f3730029ba55eacd3eb98 100644 (file)
@@ -59,6 +59,7 @@ struct ifinfo {
 #define IFS_PROBE      2
 #define IFS_DOWN       3
 #define IFS_TENTATIVE  4
+#define IFS_OPTIMISTIC 5
 
 /* rtsold.c */
 extern struct timeval tm_max;