/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * The size of the table we initially use to retrieve the kernel's policy * table. If this value is too small, we use the value returned from the * SIOCGIP6ADDRPOLICY ioctl. */ #define KERN_POLICY_SIZE 32 #define IPV6DAS_MAXLINELEN 1024 #define IPV6DAS_MAXENTRIES 512 typedef enum { IPV6DAS_PRINTPOLICY, IPV6DAS_SETPOLICY, IPV6DAS_SETDEFAULT } ipv6das_cmd_t; static char *myname; /* Copied from argv[0] */ static int parseconf(const char *, ip6_asp_t **); static int setpolicy(int, ip6_asp_t *, int); static int printpolicy(int); static int ip_mask_to_plen_v6(const in6_addr_t *); static in6_addr_t *ip_plen_to_mask_v6(int, in6_addr_t *); static int strioctl(int, int, void *, int); static void usage(void); int main(int argc, char **argv) { int opt, status, sock, count; char *conf_filename; ipv6das_cmd_t ipv6das_cmd = IPV6DAS_PRINTPOLICY; ip6_asp_t *policy_table; myname = *argv; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); while ((opt = getopt(argc, argv, "df:")) != EOF) switch (opt) { case 'd': ipv6das_cmd = IPV6DAS_SETDEFAULT; break; case 'f': conf_filename = optarg; ipv6das_cmd = IPV6DAS_SETPOLICY; break; default: usage(); return (EXIT_FAILURE); } if (argc > optind) { /* shouldn't be any extra args */ usage(); return (EXIT_FAILURE); } /* Open a socket that we can use to send ioctls down to IP. */ if ((sock = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) { perror("socket"); return (EXIT_FAILURE); } switch (ipv6das_cmd) { case IPV6DAS_SETPOLICY: if ((count = parseconf(conf_filename, &policy_table)) <= 0) return (EXIT_FAILURE); status = setpolicy(sock, policy_table, count); free(policy_table); break; case IPV6DAS_SETDEFAULT: status = setpolicy(sock, NULL, 0); break; case IPV6DAS_PRINTPOLICY: default: status = printpolicy(sock); break; } (void) close(sock); return (status); } /* * parseconf(filename, new_policy) * * Parses the file identified by filename, filling in new_policy * with the address selection policy table specified in filename. * Returns -1 on failure, or the number of table entries found * on success. */ static int parseconf(const char *filename, ip6_asp_t **new_policy) { FILE *fp; char line[IPV6DAS_MAXLINELEN]; char *cp, *end; char *prefixstr; uint_t lineno = 0, entryindex = 0; int plen, precedence; char *label; size_t labellen; int retval; ip6_asp_t tmp_policy[IPV6DAS_MAXENTRIES]; boolean_t have_default = B_FALSE; in6_addr_t prefix, mask; boolean_t comment_found = B_FALSE, end_of_line = B_FALSE; if ((fp = fopen(filename, "r")) == NULL) { perror(filename); return (-1); } while (fgets(line, sizeof (line), fp) != NULL) { if (entryindex == IPV6DAS_MAXENTRIES) { (void) fprintf(stderr, gettext("%s: too many entries\n"), filename); retval = -1; goto end_parse; } lineno++; cp = line; /* Skip leading whitespace */ while (isspace(*cp)) cp++; /* Is this a comment or blank line? */ if (*cp == '#' || *cp == '\0') continue; /* * Anything else must be of the form: * /