aboutsummaryrefslogtreecommitdiffstats
path: root/network_cmds/ip6addrctl.tproj
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
commit5fd83771641d15c418f747bd343ba6738d3875f7 (patch)
tree5abf0f78f680d9837dbd93d4d4c3933bb7509599 /network_cmds/ip6addrctl.tproj
downloadapple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip
Import macOS userland
adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106
Diffstat (limited to 'network_cmds/ip6addrctl.tproj')
-rw-r--r--network_cmds/ip6addrctl.tproj/ip6addrctl.8126
-rw-r--r--network_cmds/ip6addrctl.tproj/ip6addrctl.c467
-rw-r--r--network_cmds/ip6addrctl.tproj/ip6addrctl.conf12
3 files changed, 605 insertions, 0 deletions
diff --git a/network_cmds/ip6addrctl.tproj/ip6addrctl.8 b/network_cmds/ip6addrctl.tproj/ip6addrctl.8
new file mode 100644
index 0000000..59154d4
--- /dev/null
+++ b/network_cmds/ip6addrctl.tproj/ip6addrctl.8
@@ -0,0 +1,126 @@
+.\" $KAME: ip6addrctl.8,v 1.3 2003/03/22 05:56:41 jinmei Exp $
+.\"
+.\" Copyright (C) 2001 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 25, 2001
+.Dt IP6ADDRCTL 8
+.Os
+.\"
+.Sh NAME
+.Nm ip6addrctl
+.Nd configure address selection policy for IPv6 and IPv4
+.\"
+.Sh SYNOPSIS
+.Nm
+.Op Cm show
+.Nm
+.Cm add
+.Ar prefix precedence label
+.Nm
+.Cm delete
+.Ar prefix
+.Nm
+.Cm flush
+.Nm
+.Cm install
+.Ar configfile
+.\"
+.Sh DESCRIPTION
+The
+.Nm
+utility manages the policy table of source and destination address
+selection for outgoing IPv4 and IPv6 packets.
+When
+.Nm
+is invoked without an argument or with a single argument
+.Cm show ,
+it prints the content of the policy table currently installed in the
+kernel.
+.Pp
+To modify the table, the following operations are available:
+.Bl -tag -width indent
+.It Cm add Ar prefix precedence label
+Add a policy entry.
+The
+.Ar prefix
+argument
+is an IPv6 prefix, which is a key for the entry.
+An IPv4 prefix should be specified with an IPv6 prefix using an
+IPv4-mapped IPv6 address.
+The
+.Ar precedence
+and
+.Ar label
+arguments
+are decimal numbers, which specify the precedence and label values
+for the entry, respectively.
+This operation should be performed without an existing entry for the
+prefix.
+.It Cm delete Ar prefix
+Delete a policy entry specified by
+.Ar prefix ,
+which should be an IPv6 prefix.
+A corresponding entry for the prefix should have already been
+installed.
+.It Cm flush
+Delete all existing policy entries in the kernel.
+.It Cm install Ar configfile
+Install policy entries from a configuration file named
+.Ar configfile .
+The configuration file should contain a set of policy entries.
+Each entry is specified in a single line which contains an IPv6 prefix,
+a decimal precedence value, and a decimal label value, separated with
+white space or tab characters.
+In the configuration file, lines beginning with the pound-sign
+.Pq Ql #
+are
+comments and are ignored.
+.El
+.\"
+.Sh EXIT STATUS
+.Ex -std
+.\"
+.Sh SEE ALSO
+.Rs
+.%A "Richard Draves"
+.%T "Default Address Selection for IPv6"
+.%N RFC 3484
+.Re
+.\"
+.Sh HISTORY
+The
+.Nm
+utility first appeared in the KAME IPv6 protocol stack kit.
+The original command name was
+.Nm addrselect ,
+but it was then renamed to the current one so that the name would
+describe its function well.
+.\" .Sh BUGS
+.\" (to be written)
diff --git a/network_cmds/ip6addrctl.tproj/ip6addrctl.c b/network_cmds/ip6addrctl.tproj/ip6addrctl.c
new file mode 100644
index 0000000..400412a
--- /dev/null
+++ b/network_cmds/ip6addrctl.tproj/ip6addrctl.c
@@ -0,0 +1,467 @@
+/* $KAME: ip6addrctl.c,v 1.3 2003/12/16 08:14:28 suz Exp $ */
+
+/*
+ * Copyright (C) 2001 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+
+#include <stdlib.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <err.h>
+
+static char *configfile;
+
+struct policyqueue {
+ TAILQ_ENTRY(policyqueue) pc_entry;
+ struct in6_addrpolicy pc_policy;
+};
+TAILQ_HEAD(policyhead, policyqueue);
+struct policyhead policyhead;
+
+static void usage __P((void));
+static void get_policy __P((void));
+static void dump_policy __P((void));
+static int mask2plen __P((struct sockaddr_in6 *));
+static int parse_prefix __P((const char *, struct in6_addrpolicy *));
+static void make_policy_fromfile __P((char *));
+static void plen2mask __P((struct sockaddr_in6 *, int));
+static void set_policy __P((void));
+static void add_policy __P((char *, char *, char *));
+static void delete_policy __P((char *));
+static void flush_policy __P(());
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ TAILQ_INIT(&policyhead);
+
+ if (argc == 1 || strcasecmp(argv[1], "show") == 0) {
+ get_policy();
+ dump_policy();
+ } else if (strcasecmp(argv[1], "add") == 0) {
+ if (argc < 5)
+ usage();
+ add_policy(argv[2], argv[3], argv[4]);
+ } else if (strcasecmp(argv[1], "delete") == 0) {
+ if (argc < 3)
+ usage();
+ delete_policy(argv[2]);
+ } else if (strcasecmp(argv[1], "flush") == 0) {
+ get_policy();
+ flush_policy();
+ } else if (strcasecmp(argv[1], "install") == 0) {
+ if (argc < 3)
+ usage();
+ configfile = argv[2];
+ make_policy_fromfile(configfile);
+ set_policy();
+ } else
+ usage();
+
+ exit(0);
+}
+
+static void
+get_policy()
+{
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
+ size_t l;
+ char *buf;
+ struct in6_addrpolicy *pol, *ep;
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) {
+ err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
+ /* NOTREACHED */
+ }
+ if (l == 0) {
+ printf("no source-address-selection policy is installed\n");
+ return;
+ }
+ if ((buf = malloc(l)) == NULL) {
+ errx(1, "malloc failed");
+ /* NOTREACHED */
+ }
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
+ /* NOTREACHED */
+ }
+
+ ep = (struct in6_addrpolicy *)(buf + l);
+ for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
+ struct policyqueue *new;
+
+ if ((new = malloc(sizeof(*new))) == NULL)
+ errx(1, "malloc failed\n");
+ new->pc_policy = *pol;
+ TAILQ_INSERT_TAIL(&policyhead, new, pc_entry);
+ }
+
+ free(buf);
+}
+
+static void
+dump_policy()
+{
+ size_t addrlen;
+ char addrbuf[NI_MAXHOST];
+ struct in6_addrpolicy *pol;
+ struct policyqueue *ent;
+ int plen, first = 1;
+
+ for (ent = TAILQ_FIRST(&policyhead); ent;
+ ent = TAILQ_NEXT(ent, pc_entry)) {
+ pol = &ent->pc_policy;
+ if (first) {
+ printf("%-30s %5s %5s %8s\n",
+ "Prefix", "Prec", "Label", "Use");
+ first = 0;
+ }
+
+ if ((getnameinfo((struct sockaddr *)&pol->addr,
+ sizeof(pol->addr), addrbuf, sizeof(addrbuf),
+ NULL, 0, NI_NUMERICHOST))) {
+ warnx("getnameinfo for prefix address failed");
+ continue;
+ }
+ if ((plen = mask2plen(&pol->addrmask)) < 0) {
+ warnx("invalid address mask");
+ continue;
+ }
+ addrlen = strlen(addrbuf);
+ if (addrlen + sizeof("/128") < sizeof(addrbuf)) {
+ snprintf(&addrbuf[addrlen],
+ sizeof(addrbuf) - addrlen - 1,
+ "/%d", plen);
+ printf("%-30s", addrbuf);
+ } else /* XXX */
+ printf("%s/%d", addrbuf, plen);
+ printf(" %5d %5d %8llu\n", pol->preced, pol->label,
+ (unsigned long long)pol->use);
+ }
+}
+
+#define SKIP_WHITE(p, emptyok) \
+ do { \
+ while((*(p) == ' ' || *(p) == '\t')) \
+ (p)++; \
+ if ((*(p) == '\0' || (*(p) == '\n')) && !(emptyok)) \
+ goto bad; \
+ } while (0);
+#define SKIP_WORD(p) \
+ do { \
+ while(*(p) != ' ' && *(p) != '\t') \
+ (p)++; \
+ if (*(p) == '\0' || *(p) == '\n') \
+ goto bad; \
+ } while (0);
+
+static void
+make_policy_fromfile(conf)
+ char *conf;
+{
+ char line[_POSIX2_LINE_MAX], *cp;
+ char *addrstr;
+ FILE *fp;
+ int count = 0;
+ struct in6_addrpolicy pol0;
+ struct policyqueue *new;
+
+ if ((fp = fopen(conf, "r")) == NULL)
+ err(1, "fopen: %s", conf);
+
+ while(fgets(line, sizeof(line), fp)) {
+ count++;
+ cp = line;
+
+ memset(&pol0, 0, sizeof(pol0));
+
+ /* get prefix */
+ SKIP_WHITE(cp, 1);
+ if (*cp == '\n') /* empty line */
+ continue;
+ if (*cp == '#')
+ continue;
+ addrstr = cp;
+ if (parse_prefix((const char *)addrstr, &pol0))
+ goto bad;
+
+ /* get precedence value */
+ SKIP_WORD(cp);
+ SKIP_WHITE(cp, 0);
+ pol0.preced = atoi(cp);
+
+ /* get label */
+ SKIP_WORD(cp);
+ SKIP_WHITE(cp, 0);
+ pol0.label = atoi(cp);
+
+ /* parse succeeded. make a control buffer entry. */
+ if ((new = malloc(sizeof(*new))) == NULL)
+ errx(1, "malloc failed\n");
+ memset(new, 0, sizeof(*new));
+ new->pc_policy = pol0;
+ TAILQ_INSERT_TAIL(&policyhead, new, pc_entry);
+ }
+
+ fclose(fp);
+ return;
+
+ bad:
+ errx(1, "parse failed at line %d", count);
+ /* NOTREACHED */
+}
+
+static int
+parse_prefix(prefix0, pol)
+ const char *prefix0;
+ struct in6_addrpolicy *pol;
+{
+ int e = 0, plen;
+ char *prefix, *plenstr;
+ struct addrinfo hints, *res;
+
+ if ((prefix = strdup(prefix0)) == NULL)
+ errx(1, "strdup failed");
+
+ if ((plenstr = strchr(prefix, '/')) == NULL) {
+ e = -1;
+ goto end;
+ }
+ *plenstr = '\0';
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF_INET6;
+
+ if ((e = getaddrinfo(prefix, NULL, &hints, &res)) != 0) {
+ warnx("getaddrinfo failed for %s: %s", prefix,
+ gai_strerror(e));
+ goto end;
+ }
+ memcpy(&pol->addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ plen = atoi(plenstr + 1);
+ if (plen < 0 || plen > 128) {
+ warnx("invalid prefix length: %d", plen);
+ e = -1;
+ goto end;
+ }
+ plen2mask(&pol->addrmask, plen);
+
+ end:
+ free(prefix);
+ return(e);
+}
+
+static void
+plen2mask(mask, plen)
+ struct sockaddr_in6 *mask;
+ int plen;
+{
+ u_char *cp = (unsigned char *)&mask->sin6_addr;
+
+ memset(mask, 0, sizeof(*mask));
+ mask->sin6_family = AF_INET6; /* just in case */
+ mask->sin6_len = sizeof(*mask);
+
+ for(; plen >= 8; plen -= 8)
+ *cp++ = 0xff;
+ if (plen > 0)
+ *cp = (0xff << (8 - plen));
+}
+
+static void
+set_policy()
+{
+ struct policyqueue *ent;
+ int s;
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+
+ for (ent = TAILQ_FIRST(&policyhead); ent;
+ ent = TAILQ_NEXT(ent, pc_entry)) {
+ if (ioctl(s, SIOCAADDRCTL_POLICY, &ent->pc_policy))
+ warn("ioctl(SIOCAADDRCTL_POLICY)");
+ }
+
+ close(s);
+}
+
+static int
+mask2plen(mask)
+ struct sockaddr_in6 *mask;
+{
+ int masklen, final = 0;
+ u_char *p, *lim;
+
+ masklen = 0;
+ lim = (u_char *)(mask + 1);
+ for (p = (u_char *)(&mask->sin6_addr); p < lim; p++) {
+ if (final && *p) {
+ goto bad;
+ }
+
+ switch (*p & 0xff) {
+ case 0xff:
+ masklen += 8;
+ break;
+ case 0xfe:
+ masklen += 7;
+ final++;
+ break;
+ case 0xfc:
+ masklen += 6;
+ final++;
+ break;
+ case 0xf8:
+ masklen += 5;
+ final++;
+ break;
+ case 0xf0:
+ masklen += 4;
+ final++;
+ break;
+ case 0xe0:
+ masklen += 3;
+ final++;
+ break;
+ case 0xc0:
+ masklen += 2;
+ final++;
+ break;
+ case 0x80:
+ masklen += 1;
+ final++;
+ break;
+ case 0x00:
+ final++;
+ break;
+ default:
+ goto bad;
+ break;
+ }
+ }
+ return(masklen);
+
+ bad:
+ return(-1);
+}
+
+static void
+add_policy(prefix, prec, label)
+ char *prefix, *prec, *label;
+{
+ struct in6_addrpolicy p;
+ int s;
+
+ memset(&p, 0, sizeof(p));
+
+ if (parse_prefix((const char *)prefix, &p))
+ errx(1, "bad prefix: %s", prefix);
+ p.preced = atoi(prec);
+ p.label = atoi(label);
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+ if (ioctl(s, SIOCAADDRCTL_POLICY, &p))
+ err(1, "ioctl(SIOCAADDRCTL_POLICY)");
+
+ close(s);
+}
+
+static void
+delete_policy(prefix)
+ char *prefix;
+{
+ struct in6_addrpolicy p;
+ int s;
+
+ memset(&p, 0, sizeof(p));
+
+ if (parse_prefix((const char *)prefix, &p))
+ errx(1, "bad prefix: %s", prefix);
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+ if (ioctl(s, SIOCDADDRCTL_POLICY, &p))
+ err(1, "ioctl(SIOCDADDRCTL_POLICY)");
+
+ close(s);
+}
+
+static void
+flush_policy()
+{
+ struct policyqueue *ent;
+ int s;
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ err(1, "socket(UDP)");
+
+ for (ent = TAILQ_FIRST(&policyhead); ent;
+ ent = TAILQ_NEXT(ent, pc_entry)) {
+ if (ioctl(s, SIOCDADDRCTL_POLICY, &ent->pc_policy))
+ warn("ioctl(SIOCDADDRCTL_POLICY)");
+ }
+
+ close(s);
+}
+
+static void
+usage()
+{
+ fprintf(stderr, "usage: ip6addrctl [show]\n");
+ fprintf(stderr, " ip6addrctl add "
+ "<prefix> <precedence> <label>\n");
+ fprintf(stderr, " ip6addrctl delete <prefix>\n");
+ fprintf(stderr, " ip6addrctl flush\n");
+ fprintf(stderr, " ip6addrctl install <configfile>\n");
+
+ exit(1);
+}
diff --git a/network_cmds/ip6addrctl.tproj/ip6addrctl.conf b/network_cmds/ip6addrctl.tproj/ip6addrctl.conf
new file mode 100644
index 0000000..a2b3759
--- /dev/null
+++ b/network_cmds/ip6addrctl.tproj/ip6addrctl.conf
@@ -0,0 +1,12 @@
+# default policy table based on RFC 3484.
+# usage: ip6addrctl install path_to_this_file
+#
+# $FreeBSD$
+#
+#Format:
+#Prefix Precedence Label
+::1/128 50 0
+::/0 40 1
+2002::/16 30 2
+::/96 20 3
+::ffff:0:0/96 10 4