From 7af5ce03cf81eb8cf0c6e1bfd903b52fcc7c224a Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 30 Apr 2012 22:57:51 +0000 Subject: [PATCH] network_cmds-396.6.tar.gz --- arp.tproj/arp.8 | 31 + arp.tproj/arp.c | 67 +- dnctl/dnctl.8 | 549 +++++++ dnctl/dnctl.c | 1309 +++++++++++++++++ ifconfig.tproj/af_inet.c | 42 + ifconfig.tproj/af_inet6.c | 27 +- ifconfig.tproj/ifconfig.c | 377 ++++- ifconfig.tproj/ifconfig.h | 30 + ip6conf.tproj/6to4.conf | 20 - ip6conf.tproj/ip6.8 | 45 - ip6conf.tproj/ip6config | 209 --- ip6conf.tproj/ip6config.8 | 160 -- ip6conf.tproj/ip6tool.c | 247 ---- ip6fw.tproj/ip6fw.8 | 6 + mnc.tproj/LICENCE | 37 + mnc.tproj/README | 63 + mnc.tproj/mnc.1 | 101 ++ mnc.tproj/mnc.h | 92 ++ mnc.tproj/mnc_error.c | 95 ++ mnc.tproj/mnc_main.c | 131 ++ mnc.tproj/mnc_multicast.c | 404 +++++ mnc.tproj/mnc_opts.c | 182 +++ mtest.tproj/mtest.c | 2 +- ndp.tproj/ndp.8 | 31 + ndp.tproj/ndp.c | 87 +- netstat.tproj/if.c | 988 ++++++++++++- netstat.tproj/inet.c | 265 +--- netstat.tproj/main.c | 38 +- netstat.tproj/netstat.1 | 59 +- netstat.tproj/netstat.h | 9 +- netstat.tproj/route.c | 6 +- mtest.tproj/mtest.plist => network_cmds.plist | 6 +- network_cmds.xcodeproj/project.pbxproj | 657 ++++++--- ping.tproj/ping.8 | 4 +- ping.tproj/ping.c | 18 +- ping6.tproj/ping6.c | 26 +- rarpd.tproj/rarpd.c | 1 - route.tproj/route.c | 8 +- rtadvd.tproj/advcap.c | 71 +- rtadvd.tproj/advcap.h | 12 +- rtadvd.tproj/config.c | 1026 ++++++++----- rtadvd.tproj/config.h | 23 +- rtadvd.tproj/dump.c | 118 +- rtadvd.tproj/dump.h | 4 +- rtadvd.tproj/if.c | 83 +- rtadvd.tproj/if.h | 42 +- rtadvd.tproj/rrenum.c | 78 +- rtadvd.tproj/rrenum.h | 6 +- rtadvd.tproj/rtadvd.8 | 83 +- rtadvd.tproj/rtadvd.c | 1117 +++++++------- rtadvd.tproj/rtadvd.conf | 5 +- rtadvd.tproj/rtadvd.conf.5 | 280 ++-- rtadvd.tproj/rtadvd.h | 69 +- rtadvd.tproj/timer.c | 47 +- rtadvd.tproj/timer.h | 30 +- rtsol.tproj/dump.c | 4 +- rtsol.tproj/if.c | 7 +- rtsol.tproj/rtsold.h | 1 + 58 files changed, 6924 insertions(+), 2611 deletions(-) create mode 100644 dnctl/dnctl.8 create mode 100644 dnctl/dnctl.c delete mode 100644 ip6conf.tproj/6to4.conf delete mode 100644 ip6conf.tproj/ip6.8 delete mode 100644 ip6conf.tproj/ip6config delete mode 100644 ip6conf.tproj/ip6config.8 delete mode 100644 ip6conf.tproj/ip6tool.c create mode 100644 mnc.tproj/LICENCE create mode 100644 mnc.tproj/README create mode 100644 mnc.tproj/mnc.1 create mode 100644 mnc.tproj/mnc.h create mode 100644 mnc.tproj/mnc_error.c create mode 100644 mnc.tproj/mnc_main.c create mode 100644 mnc.tproj/mnc_multicast.c create mode 100644 mnc.tproj/mnc_opts.c rename mtest.tproj/mtest.plist => network_cmds.plist (77%) diff --git a/arp.tproj/arp.8 b/arp.tproj/arp.8 index ab31601..b586c26 100644 --- a/arp.tproj/arp.8 +++ b/arp.tproj/arp.8 @@ -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 , diff --git a/arp.tproj/arp.c b/arp.tproj/arp.c index 665aa94..a152574 100644 --- a/arp.tproj/arp.c +++ b/arp.tproj/arp.c @@ -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 index 0000000..19c09d4 --- /dev/null +++ b/dnctl/dnctl.8 @@ -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 index 0000000..d913f90 --- /dev/null +++ b/dnctl/dnctl.c @@ -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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +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] where 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; +} diff --git a/ifconfig.tproj/af_inet.c b/ifconfig.tproj/af_inet.c index ccac9b0..9ad175e 100644 --- a/ifconfig.tproj/af_inet.c +++ b/ifconfig.tproj/af_inet.c @@ -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, diff --git a/ifconfig.tproj/af_inet6.c b/ifconfig.tproj/af_inet6.c index cd5e34a..0f32774 100644 --- a/ifconfig.tproj/af_inet6.c +++ b/ifconfig.tproj/af_inet6.c @@ -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, }; diff --git a/ifconfig.tproj/ifconfig.c b/ifconfig.tproj/ifconfig.c index 9346350..a6cd36d 100644 --- a/ifconfig.tproj/ifconfig.c +++ b/ifconfig.tproj/ifconfig.c @@ -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 #include #include +#include #include +#include /* IP */ #include @@ -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); +} diff --git a/ifconfig.tproj/ifconfig.h b/ifconfig.tproj/ifconfig.h index b2501c7..1a89a33 100644 --- a/ifconfig.tproj/ifconfig.h +++ b/ifconfig.tproj/ifconfig.h @@ -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 index b3a3c80..0000000 --- a/ip6conf.tproj/6to4.conf +++ /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 index feb6cc3..0000000 --- a/ip6conf.tproj/ip6.8 +++ /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 index 7294275..0000000 --- a/ip6conf.tproj/ip6config +++ /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 -# - - -# 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 () { - 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 index 0a1ebdb..0000000 --- a/ip6conf.tproj/ip6config.8 +++ /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 for NetBSD. diff --git a/ip6conf.tproj/ip6tool.c b/ip6conf.tproj/ip6tool.c deleted file mode 100644 index 8d044f9..0000000 --- a/ip6conf.tproj/ip6tool.c +++ /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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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; -} diff --git a/ip6fw.tproj/ip6fw.8 b/ip6fw.tproj/ip6fw.8 index ef3f9a8..61771a0 100644 --- a/ip6fw.tproj/ip6fw.8 +++ b/ip6fw.tproj/ip6fw.8 @@ -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 index 0000000..4fec3e3 --- /dev/null +++ b/mnc.tproj/LICENCE @@ -0,0 +1,37 @@ +/* + * Colm MacCarthaigh, + * + * 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 index 0000000..291ce1a --- /dev/null +++ b/mnc.tproj/README @@ -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 index 0000000..ed1073b --- /dev/null +++ b/mnc.tproj/mnc.1 @@ -0,0 +1,101 @@ +.\" +.\" mnc.1 -- mnc manual +.\" +.\" Colm MacCárthaigh, +.\" +.\" 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 and is available from: +.PP +http://people.apache.org/~colm/mnc/ +.PP +Additional multicast development and support provided by John Lyons + and Eoin Kenny diff --git a/mnc.tproj/mnc.h b/mnc.tproj/mnc.h new file mode 100644 index 0000000..db6e68e --- /dev/null +++ b/mnc.tproj/mnc.h @@ -0,0 +1,92 @@ +/* + * $Id: mnc.h,v 1.4 2004/09/22 14:07:10 colmmacc Exp $ + * + * mnc.h -- Multicast NetCat + * + * Colm MacCarthaigh, + * + * 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 +#include +#include + +#else + +#include +#include + +#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 index 0000000..4478e7e --- /dev/null +++ b/mnc.tproj/mnc_error.c @@ -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, + * + * 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 +#include +#include + +#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 index 0000000..1e5c5af --- /dev/null +++ b/mnc.tproj/mnc_main.c @@ -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, + * + * 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 +#include +#include +#include + +#else + +/* Windows-specific includes */ + +#include +#include +#include +#include + +#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 index 0000000..35f3415 --- /dev/null +++ b/mnc.tproj/mnc_multicast.c @@ -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, + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include + +#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 index 0000000..606746f --- /dev/null +++ b/mnc.tproj/mnc_opts.c @@ -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, + * + * 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 +#include +#include + +#ifndef WINDOWS + +/* UNIX-y includes */ +#include +#include +#include +#else + +/* WINDOWS-y includes */ +#include +#include +#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; +} diff --git a/mtest.tproj/mtest.c b/mtest.tproj/mtest.c index 0401832..12eb891 100644 --- a/mtest.tproj/mtest.c +++ b/mtest.tproj/mtest.c @@ -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/ndp.tproj/ndp.8 b/ndp.tproj/ndp.8 index a030fc5..bf480d4 100644 --- a/ndp.tproj/ndp.8 +++ b/ndp.tproj/ndp.8 @@ -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 diff --git a/ndp.tproj/ndp.c b/ndp.tproj/ndp.c index 096551b..7677017 100644 --- a/ndp.tproj/ndp.c +++ b/ndp.tproj/ndp.c @@ -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 diff --git a/netstat.tproj/if.c b/netstat.tproj/if.c index 962a3ba..70e5705 100644 --- a/netstat.tproj/if.c +++ b/netstat.tproj/if.c @@ -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 #include #include +#include #include #include @@ -80,6 +81,9 @@ static const char rcsid[] = #include #include +#include +#include + #include #include @@ -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; + } +} diff --git a/netstat.tproj/inet.c b/netstat.tproj/inet.c index ffad668..dd17d27 100644 --- a/netstat.tproj/inet.c +++ b/netstat.tproj/inet.c @@ -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"); diff --git a/netstat.tproj/main.c b/netstat.tproj/main.c index f77b6f3..efc37dd 100644 --- a/netstat.tproj/main.c +++ b/netstat.tproj/main.c @@ -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 diff --git a/netstat.tproj/netstat.1 b/netstat.tproj/netstat.1 index c54ef88..86e711e 100644 --- a/netstat.tproj/netstat.1 +++ b/netstat.tproj/netstat.1 @@ -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 diff --git a/netstat.tproj/netstat.h b/netstat.tproj/netstat.h index bcc4214..da71069 100644 --- a/netstat.tproj/netstat.h +++ b/netstat.tproj/netstat.h @@ -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); diff --git a/netstat.tproj/route.c b/netstat.tproj/route.c index 885a19b..203cb14 100644 --- a/netstat.tproj/route.c +++ b/netstat.tproj/route.c @@ -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/mtest.tproj/mtest.plist b/network_cmds.plist similarity index 77% rename from mtest.tproj/mtest.plist rename to network_cmds.plist index 8b726f1..9d6cf73 100644 --- a/mtest.tproj/mtest.plist +++ b/network_cmds.plist @@ -5,12 +5,12 @@ OpenSourceProject mtest - OpenSouceVersion + OpenSourceVersion 1.11 OpenSourceWebsiteURL http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/ OpenSourceURL - http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.sbin/mtest/ + http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/usr.sbin/mtest/mtest.c?rev=1.11;content-type=text%2Fplain OpenSourceSHA1 OpenSourceMD5 @@ -20,7 +20,7 @@ OpenSourceLicense Other OpenSourceLicenseFile - mtest.txt + network_cmds.txt diff --git a/network_cmds.xcodeproj/project.pbxproj b/network_cmds.xcodeproj/project.pbxproj index ca9bdf6..a642039 100644 --- a/network_cmds.xcodeproj/project.pbxproj +++ b/network_cmds.xcodeproj/project.pbxproj @@ -14,13 +14,15 @@ ); 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 */, @@ -35,14 +37,14 @@ 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 */, @@ -84,14 +86,30 @@ 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 */; }; @@ -134,6 +152,7 @@ 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 */; }; @@ -165,11 +184,6 @@ 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 */; }; @@ -181,11 +195,14 @@ 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 */ @@ -246,13 +263,6 @@ 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 */; @@ -281,6 +291,13 @@ 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 */; @@ -288,6 +305,27 @@ 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 */; @@ -358,6 +396,20 @@ 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 */; @@ -393,13 +445,6 @@ 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 */; @@ -414,13 +459,6 @@ 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 */; @@ -442,13 +480,6 @@ 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 */; @@ -526,6 +557,13 @@ 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 */; @@ -536,16 +574,36 @@ /* 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; @@ -562,7 +620,7 @@ 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; @@ -667,6 +725,16 @@ ); 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; @@ -747,38 +815,6 @@ ); 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; @@ -806,10 +842,18 @@ 4D2B04E51208C12F0004A3F3 /* ip6addrctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ip6addrctl.c; sourceTree = ""; }; 4D2B04E61208C12F0004A3F3 /* ip6addrctl.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6addrctl.conf; sourceTree = ""; }; 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 = ""; }; + 565825951339217B003E5FA5 /* LICENCE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENCE; sourceTree = ""; }; + 565825961339217B003E5FA5 /* mnc_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_error.c; sourceTree = ""; }; + 565825971339217B003E5FA5 /* mnc_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_main.c; sourceTree = ""; }; + 565825981339217B003E5FA5 /* mnc_multicast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_multicast.c; sourceTree = ""; }; + 565825991339217B003E5FA5 /* mnc_opts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mnc_opts.c; sourceTree = ""; }; + 5658259A1339217B003E5FA5 /* mnc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mnc.h; sourceTree = ""; }; + 5658259B1339217B003E5FA5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; + 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 = ""; }; 690D979512DE6E76004323A7 /* mtest.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mtest.8; sourceTree = ""; }; - 69C10A7712DF7F2700BCDF4C /* mtest.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = mtest.plist; sourceTree = ""; }; 69C10A7912DF80F200BCDF4C /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = ""; }; 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; }; @@ -819,6 +863,8 @@ 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 = ""; }; 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; }; @@ -843,11 +889,6 @@ 726120580EE86F0900AFED1B /* ifconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ifconfig.h; sourceTree = ""; }; 726120590EE86F0900AFED1B /* ifmedia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifmedia.c; sourceTree = ""; }; 7261205A0EE86F0900AFED1B /* ifvlan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifvlan.c; sourceTree = ""; }; - 7261205F0EE86F1A00AFED1B /* 6to4.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 6to4.conf; sourceTree = ""; }; - 726120600EE86F1A00AFED1B /* ip6.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6.8; sourceTree = ""; }; - 726120610EE86F1A00AFED1B /* ip6config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = ip6config; sourceTree = ""; }; - 726120620EE86F1A00AFED1B /* ip6config.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6config.8; sourceTree = ""; }; - 726120630EE86F1A00AFED1B /* ip6tool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ip6tool.c; sourceTree = ""; }; 726120680EE86F2300AFED1B /* ip6fw.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ip6fw.8; sourceTree = ""; }; 726120690EE86F2300AFED1B /* ip6fw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ip6fw.c; sourceTree = ""; }; 7261206E0EE86F2D00AFED1B /* com.apple.kdumpd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.kdumpd.plist; sourceTree = ""; }; @@ -951,18 +992,27 @@ 726121240EE870D400AFED1B /* libalias.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = libalias.3; sourceTree = ""; }; 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 = ""; }; + 72D000C3142BB11100151981 /* dnctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dnctl.c; sourceTree = ""; }; + 72E42BA214B7CF37003AAE28 /* network_cmds.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = network_cmds.plist; sourceTree = ""; }; 72E650A2107BF2F000AAF325 /* af_inet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = af_inet.c; sourceTree = ""; }; 72E650A3107BF2F000AAF325 /* af_inet6.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = af_inet6.c; sourceTree = ""; }; 72E650A4107BF2F000AAF325 /* af_link.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = af_link.c; sourceTree = ""; }; 72E650A5107BF2F000AAF325 /* ifbridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifbridge.c; sourceTree = ""; }; 72E650A6107BF2F000AAF325 /* ifclone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifclone.c; sourceTree = ""; }; + E01AB08F1368880F008C66FF /* libutil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libutil.dylib; path = $SDKROOT/usr/lib/libutil.dylib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 5658259D1339218F003E5FA5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 690D977F12DE6034004323A7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1010,6 +1060,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E01AB0901368880F008C66FF /* libutil.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1027,6 +1078,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 723C7065142BAFEA007C87E9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 724DAB5D0EE88E2A008900D0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1084,13 +1142,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 726121810EE8897C00AFED1B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 7294F0F70EE8BB460052EC88 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1119,29 +1170,55 @@ path = ip6addrctl.tproj; sourceTree = ""; }; + 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 = ""; + }; 690D973F12DE5A21004323A7 /* mtest.tproj */ = { isa = PBXGroup; children = ( 690D979512DE6E76004323A7 /* mtest.8 */, 690D979412DE6E6B004323A7 /* mtest.c */, - 69C10A7712DF7F2700BCDF4C /* mtest.plist */, 69C10A7912DF80F200BCDF4C /* COPYING */, ); path = mtest.tproj; sourceTree = ""; }; + 723C706A142BAFEA007C87E9 /* dnctl */ = { + isa = PBXGroup; + children = ( + 724753E61448E1EF00F6A941 /* dnctl.8 */, + 72D000C3142BB11100151981 /* dnctl.c */, + ); + path = dnctl; + sourceTree = ""; + }; 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 */, @@ -1207,18 +1284,6 @@ path = ifconfig.tproj; sourceTree = ""; }; - 7261205E0EE86F1A00AFED1B /* ip6conf.tproj */ = { - isa = PBXGroup; - children = ( - 7261205F0EE86F1A00AFED1B /* 6to4.conf */, - 726120600EE86F1A00AFED1B /* ip6.8 */, - 726120610EE86F1A00AFED1B /* ip6config */, - 726120620EE86F1A00AFED1B /* ip6config.8 */, - 726120630EE86F1A00AFED1B /* ip6tool.c */, - ); - path = ip6conf.tproj; - sourceTree = ""; - }; 726120670EE86F2300AFED1B /* ip6fw.tproj */ = { isa = PBXGroup; children = ( @@ -1427,7 +1492,6 @@ 7261210C0EE8707500AFED1B /* libalias.A.dylib */, 7261212D0EE8710B00AFED1B /* arp */, 726121540EE8881700AFED1B /* ifconfig */, - 726121830EE8897C00AFED1B /* ip6 */, 724DAB5F0EE88E2A008900D0 /* ipfw */, 724DAB820EE88EFA008900D0 /* ip6fw */, 724DABA20EE88FE3008900D0 /* kdumpd */, @@ -1445,6 +1509,8 @@ 7294F12A0EE8BD280052EC88 /* traceroute6 */, 4D2B04F31208C2040004A3F3 /* ip6addrctl */, 690D978112DE6034004323A7 /* mtest */, + 5658259F1339218F003E5FA5 /* mnc */, + 723C7068142BAFEA007C87E9 /* dnctl */, ); name = Products; sourceTree = ""; @@ -1468,6 +1534,7 @@ buildPhases = ( 4D2B04F01208C2040004A3F3 /* Sources */, 4D2B05221208CB410004A3F3 /* CopyFiles */, + 03EB2FB6120A1E740007C1A0 /* CopyFiles */, 039D6A11120A2CF60006B8C8 /* ShellScript */, ); buildRules = ( @@ -1479,6 +1546,23 @@ 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" */; @@ -1646,6 +1730,23 @@ 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" */; @@ -1791,26 +1892,6 @@ 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" */; @@ -1870,13 +1951,17 @@ 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 */, @@ -1889,8 +1974,6 @@ 7216D3A60EE8A3BA00AE70E4 /* spray */, 7294F0F80EE8BB460052EC88 /* traceroute */, 7294F1290EE8BD280052EC88 /* traceroute6 */, - 4D2B04F21208C2040004A3F3 /* ip6addrctl */, - 690D978012DE6034004323A7 /* mtest */, ); }; /* End PBXProject section */ @@ -1907,7 +1990,7 @@ ); 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; @@ -1932,11 +2015,11 @@ ); 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; @@ -2094,19 +2177,6 @@ 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; @@ -2196,6 +2266,17 @@ ); 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; @@ -2293,6 +2374,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 723C7064142BAFEA007C87E9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 72D000C4142BB11100151981 /* dnctl.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 724DAB5C0EE88E2A008900D0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2376,14 +2465,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 726121800EE8897C00AFED1B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 726121890EE889C100AFED1B /* ip6tool.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 7294F0F60EE8BB460052EC88 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2437,11 +2518,6 @@ target = 7294F0F80EE8BB460052EC88 /* traceroute */; targetProxy = 034E4484100BE15F009CA3DC /* PBXContainerItemProxy */; }; - 03B2DBC5100BE332005349BC /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 726121820EE8897C00AFED1B /* ip6conf */; - targetProxy = 03B2DBC4100BE332005349BC /* PBXContainerItemProxy */; - }; 03B2DBD1100BE626005349BC /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 724DAC0C0EE8940D008900D0 /* ndp */; @@ -2462,11 +2538,31 @@ 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 */; @@ -2517,6 +2613,16 @@ 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 */; @@ -2542,11 +2648,6 @@ target = 724DAC0C0EE8940D008900D0 /* ndp */; targetProxy = 724DAC230EE89525008900D0 /* PBXContainerItemProxy */; }; - 726121470EE8717B00AFED1B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7261210B0EE8707500AFED1B /* alias */; - targetProxy = 726121460EE8717B00AFED1B /* PBXContainerItemProxy */; - }; 726121490EE8717B00AFED1B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 7261212C0EE8710B00AFED1B /* arp */; @@ -2557,11 +2658,6 @@ target = 726121530EE8881700AFED1B /* ifconfig */; targetProxy = 7261217C0EE8896800AFED1B /* PBXContainerItemProxy */; }; - 726121B30EE88B7900AFED1B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 726121820EE8897C00AFED1B /* ip6conf */; - targetProxy = 726121B20EE88B7900AFED1B /* PBXContainerItemProxy */; - }; 7294F0EA0EE8BAC80052EC88 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 7216D3A60EE8A3BA00AE70E4 /* spray */; @@ -2577,11 +2673,6 @@ target = 726121530EE8881700AFED1B /* ifconfig */; targetProxy = 72ABD0871083D750008C721C /* PBXContainerItemProxy */; }; - 72ABD08A1083D753008C721C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 726121820EE8897C00AFED1B /* ip6conf */; - targetProxy = 72ABD0891083D753008C721C /* PBXContainerItemProxy */; - }; 72ABD08C1083D75D008C721C /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 724DAC0C0EE8940D008900D0 /* ndp */; @@ -2637,6 +2728,11 @@ target = 7261212C0EE8710B00AFED1B /* arp */; targetProxy = 72ABD0A31083D818008C721C /* PBXContainerItemProxy */; }; + 72C77D3B1484199C002D2577 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7261210B0EE8707500AFED1B /* alias */; + targetProxy = 72C77D3C1484199C002D2577 /* PBXContainerItemProxy */; + }; 72CD1D9C0EE8C47C005F825D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 7294F1290EE8BD280052EC88 /* traceroute6 */; @@ -2669,7 +2765,6 @@ PREBINDING = NO; SDKROOT = ""; "STRIPFLAGS[sdk=iphoneos*]" = "-S"; - VALID_ARCHS = "armv6 armv7 i386 x86_64"; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; @@ -2704,6 +2799,7 @@ 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; @@ -2750,18 +2846,6 @@ }; 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 = { @@ -2785,6 +2869,7 @@ "$(inherited)", IP_FW_PRIVATE, ); + HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; INSTALL_GROUP = wheel; INSTALL_MODE_FLAG = 0555; INSTALL_OWNER = root; @@ -3046,6 +3131,48 @@ }; 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 = { @@ -3354,6 +3481,58 @@ }; 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 = { @@ -3377,7 +3556,6 @@ GCC_TREAT_WARNINGS_AS_ERRORS = YES; PREBINDING = NO; SDKROOT = ""; - VALID_ARCHS = "armv6 armv7 i386 x86_64"; WARNING_CFLAGS = "-Wall"; }; name = Debug; @@ -3406,7 +3584,6 @@ PREBINDING = NO; SDKROOT = ""; "STRIPFLAGS[sdk=iphoneos*]" = "-S"; - VALID_ARCHS = "armv6 armv7 i386 x86_64"; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; @@ -3451,6 +3628,7 @@ "$(inherited)", IP_FW_PRIVATE, ); + HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; INSTALL_GROUP = wheel; INSTALL_MODE_FLAG = 0555; INSTALL_OWNER = root; @@ -3466,6 +3644,7 @@ "$(inherited)", IP_FW_PRIVATE, ); + HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders; INSTALL_GROUP = wheel; INSTALL_MODE_FLAG = 0555; INSTALL_OWNER = root; @@ -3592,6 +3771,7 @@ 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; @@ -3612,6 +3792,7 @@ 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; @@ -3714,30 +3895,6 @@ }; 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 = { @@ -3834,6 +3991,38 @@ }; 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 */ @@ -3847,6 +4036,16 @@ 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 = ( @@ -3937,6 +4136,16 @@ 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 = ( @@ -4047,16 +4256,6 @@ 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 = ( @@ -4087,6 +4286,16 @@ 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 */; diff --git a/ping.tproj/ping.8 b/ping.tproj/ping.8 index feb8e76..0760922 100644 --- a/ping.tproj/ping.8 +++ b/ping.tproj/ping.8 @@ -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 diff --git a/ping.tproj/ping.c b/ping.tproj/ping.c index 7227bd4..8290b7a 100644 --- a/ping.tproj/ping.c +++ b/ping.tproj/ping.c @@ -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))]; diff --git a/ping6.tproj/ping6.c b/ping6.tproj/ping6.c index 4892b95..5a1b25d 100644 --- a/ping6.tproj/ping6.c +++ b/ping6.tproj/ping6.c @@ -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; diff --git a/rarpd.tproj/rarpd.c b/rarpd.tproj/rarpd.c index d26a1e4..fcea9bc 100644 --- a/rarpd.tproj/rarpd.c +++ b/rarpd.tproj/rarpd.c @@ -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) diff --git a/route.tproj/route.c b/route.tproj/route.c index 818bdd0..23cba41 100644 --- a/route.tproj/route.c +++ b/route.tproj/route.c @@ -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); diff --git a/rtadvd.tproj/advcap.c b/rtadvd.tproj/advcap.c index cc01ae2..2c9e34d 100644 --- a/rtadvd.tproj/advcap.c +++ b/rtadvd.tproj/advcap.c @@ -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 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; diff --git a/rtadvd.tproj/advcap.h b/rtadvd.tproj/advcap.h index 44d90e6..1b42b40 100644 --- a/rtadvd.tproj/advcap.h +++ b/rtadvd.tproj/advcap.h @@ -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 */ @@ -37,10 +35,10 @@ __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 diff --git a/rtadvd.tproj/config.c b/rtadvd.tproj/config.c index c2746e9..ac25640 100644 --- a/rtadvd.tproj/config.c +++ b/rtadvd.tproj/config.c @@ -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 @@ -66,9 +64,7 @@ #include #include -#if defined(__FreeBSD__) && __FreeBSD__ >= 3 #include -#endif /* __FreeBSD__ >= 3 */ #include #include @@ -77,9 +73,7 @@ #include #include #include -#ifdef MIP6 -#include -#endif +#include #include @@ -87,12 +81,11 @@ #include #include #include -#include -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #include -#endif +#include #include #include +#include #include "rtadvd.h" #include "advcap.h" @@ -100,29 +93,34 @@ #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); +} diff --git a/rtadvd.tproj/config.h b/rtadvd.tproj/config.h index f6bd083..f1f0387 100644 --- a/rtadvd.tproj/config.h +++ b/rtadvd.tproj/config.h @@ -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. @@ -27,11 +27,20 @@ * 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 diff --git a/rtadvd.tproj/dump.c b/rtadvd.tproj/dump.c index 03f4575..fad2a61 100644 --- a/rtadvd.tproj/dump.c +++ b/rtadvd.tproj/dump.c @@ -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. @@ -55,17 +55,13 @@ * 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 #include #include #include -#if defined(__FreeBSD__) && __FreeBSD__ >= 3 #include -#endif /* __FreeBSD__ >= 3 */ #include #include @@ -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; } diff --git a/rtadvd.tproj/dump.h b/rtadvd.tproj/dump.h index eb73c36..4e10b4a 100644 --- a/rtadvd.tproj/dump.h +++ b/rtadvd.tproj/dump.h @@ -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 *); diff --git a/rtadvd.tproj/if.c b/rtadvd.tproj/if.c index 7d70482..db83a69 100644 --- a/rtadvd.tproj/if.c +++ b/rtadvd.tproj/if.c @@ -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 @@ -37,23 +35,12 @@ #include #include #include -#if defined(__FreeBSD__) || defined (__APPLE__) -# include -#endif +#include #include -#ifdef __NetBSD__ -#include -#endif #include #include #include #include -#ifdef __bsdi__ -# include -#endif -#ifdef __OpenBSD__ -#include -#endif #include #include #include @@ -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; } diff --git a/rtadvd.tproj/if.h b/rtadvd.tproj/if.h index 06d2d72..32c70ae 100644 --- a/rtadvd.tproj/if.h +++ b/rtadvd.tproj/if.h @@ -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); diff --git a/rtadvd.tproj/rrenum.c b/rtadvd.tproj/rrenum.c index 1ba14ec..bdac431 100644 --- a/rtadvd.tproj/rrenum.c +++ b/rtadvd.tproj/rrenum.c @@ -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 #include @@ -37,9 +35,7 @@ #include #include -#if defined(__FreeBSD__) && __FreeBSD__ >= 3 #include -#endif /* __FreeBSD__ >= 3 */ #include #include #include @@ -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; } diff --git a/rtadvd.tproj/rrenum.h b/rtadvd.tproj/rrenum.h index ad8db33..b6ed486 100644 --- a/rtadvd.tproj/rrenum.h +++ b/rtadvd.tproj/rrenum.h @@ -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 *); diff --git a/rtadvd.tproj/rtadvd.8 b/rtadvd.tproj/rtadvd.8 index 4ec5483..69ebe9a 100644 --- a/rtadvd.tproj/rtadvd.8 +++ b/rtadvd.tproj/rtadvd.8 @@ -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 diff --git a/rtadvd.tproj/rtadvd.c b/rtadvd.tproj/rtadvd.c index 0a454d8..a4dff6d 100644 --- a/rtadvd.tproj/rtadvd.c +++ b/rtadvd.tproj/rtadvd.c @@ -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 @@ -53,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/rtadvd.tproj/rtadvd.conf b/rtadvd.tproj/rtadvd.conf index 4c653ed..6d109b2 100644 --- a/rtadvd.tproj/rtadvd.conf +++ b/rtadvd.tproj/rtadvd.conf @@ -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: diff --git a/rtadvd.tproj/rtadvd.conf.5 b/rtadvd.tproj/rtadvd.conf.5 index c9e9ba3..87978fc 100644 --- a/rtadvd.tproj/rtadvd.conf.5 +++ b/rtadvd.tproj/rtadvd.conf.5 @@ -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 diff --git a/rtadvd.tproj/rtadvd.h b/rtadvd.tproj/rtadvd.h index 332b799..fdd8977 100644 --- a/rtadvd.tproj/rtadvd.h +++ b/rtadvd.tproj/rtadvd.h @@ -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. @@ -27,10 +27,10 @@ * 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" @@ -46,21 +46,12 @@ #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 diff --git a/rtadvd.tproj/timer.c b/rtadvd.tproj/timer.c index 4cce63b..b03b4bf 100644 --- a/rtadvd.tproj/timer.c +++ b/rtadvd.tproj/timer.c @@ -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 @@ -37,16 +35,14 @@ #include #include #include -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #include -#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 diff --git a/rtadvd.tproj/timer.h b/rtadvd.tproj/timer.h index 63705a1..78314b7 100644 --- a/rtadvd.tproj/timer.h +++ b/rtadvd.tproj/timer.h @@ -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 *); diff --git a/rtsol.tproj/dump.c b/rtsol.tproj/dump.c index c42f8f5..69937f0 100644 --- a/rtsol.tproj/dump.c +++ b/rtsol.tproj/dump.c @@ -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() diff --git a/rtsol.tproj/if.c b/rtsol.tproj/if.c index d361c27..79da223 100644 --- a/rtsol.tproj/if.c +++ b/rtsol.tproj/if.c @@ -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); diff --git a/rtsol.tproj/rtsold.h b/rtsol.tproj/rtsold.h index dccbc57..fdda539 100644 --- a/rtsol.tproj/rtsold.h +++ b/rtsol.tproj/rtsold.h @@ -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; -- 2.45.2