ipaddrsel.c revision 0c6f1683238ba0627fb13bb20513e4917993c79d
/*
* 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
* 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <libintl.h>
#include <locale.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <stropts.h>
/*
* 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 {
static char *myname; /* Copied from argv[0] */
static int printpolicy(int);
static int ip_mask_to_plen_v6(const in6_addr_t *);
static int strioctl(int, int, void *, int);
static void usage(void);
int
{
char *conf_filename;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
switch (opt) {
case 'd':
break;
case 'f':
break;
default:
usage();
return (EXIT_FAILURE);
}
/* shouldn't be any extra args */
usage();
return (EXIT_FAILURE);
}
/* Open a socket that we can use to send ioctls down to IP. */
perror("socket");
return (EXIT_FAILURE);
}
switch (ipv6das_cmd) {
case IPV6DAS_SETPOLICY:
return (EXIT_FAILURE);
break;
case IPV6DAS_SETDEFAULT:
break;
case IPV6DAS_PRINTPOLICY:
default:
break;
}
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
{
char line[IPV6DAS_MAXLINELEN];
char *prefixstr;
int plen, precedence;
char *label;
int retval;
return (-1);
}
if (entryindex == IPV6DAS_MAXENTRIES) {
retval = -1;
goto end_parse;
}
lineno++;
/* Skip leading whitespace */
cp++;
/* Is this a comment or blank line? */
continue;
/*
* Anything else must be of the form:
* <IPv6-addr>/<plen> <precedence> <label>
*/
gettext("%s: invalid prefix on line %d: %s\n"),
continue;
}
*cp = '\0';
gettext("%s: invalid prefix on line %d: %s\n"),
continue;
}
cp++;
errno = 0;
gettext("%s: invalid prefix length on line %d\n"),
continue;
}
gettext("%s: invalid prefix length on line %d:"
continue;
}
errno = 0;
gettext("%s: invalid precedence on line %d\n"),
continue;
}
cp++;
/*
* NULL terminate the label string. The label string is
* composed of non-blank characters, and can optionally be
* followed by a comment.
*/
cp++;
if (*cp == '#')
*cp = '\0';
if (labellen == 0) {
gettext("%s: missing label on line %d\n"),
continue;
}
if (labellen >= IP6_ASP_MAXLABELSIZE) {
gettext("%s: label too long on line %d, labels "
IP6_ASP_MAXLABELSIZE - 1);
continue;
}
/*
* We're specifically using strncpy() to copy the label
* to take advantage of the fact that strncpy will add
* NULL characters to the target string up to the given
* length, so don't change the call to strncpy() with
* out also taking into account this requirement. The
* labels are stored in the kernel in that way in order
* to make comparisons more efficient: all 16 bytes of
* the labels are compared to each other; random bytes
* after the NULL terminator would yield incorrect
* comparisons.
*/
/*
* Anything else on the line should be a comment; print
* a warning if that's not the case.
*/
if (!comment_found && !end_of_line) {
cp++;
cp++;
gettext("%s: characters following label "
"on line %d will be ignored\n"),
}
}
entryindex++;
}
if (!have_default) {
gettext("%s: config doesn't contain a default entry.\n"),
filename);
retval = -1;
goto end_parse;
}
/* Allocate the caller's array. */
perror("malloc");
retval = -1;
goto end_parse;
}
retval = entryindex;
return (retval);
}
/*
* setpolicy(sock, new_policy, count)
*
* Sends an SIOCSIP6ADDRPOLICY ioctl to the kernel to set the address
* selection policy table pointed to by new_policy. count should be
* the number of entries in the table; sock should be an open INET6
* socket. Returns EXIT_FAILURE or EXIT_SUCCESS.
*/
static int
{
perror("SIOCSIP6ADDRPOLICY");
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}
/*
* printpolicy(sock)
*
* Queries the kernel for the current address selection policy using
* the open socket sock, and prints the result. Returns EXIT_FAILURE
* if the table cannot be obtained, or EXIT_SUCCESS if the table is
* obtained and printed successfully.
*/
static int
printpolicy(int sock)
{
int count, policy_index;
KERN_POLICY_SIZE * sizeof (ip6_asp_t))) < 0) {
perror("SIOCGIP6ADDRPOLICY");
return (EXIT_FAILURE);
}
if (count > KERN_POLICY_SIZE) {
if (policy_ptr == NULL) {
perror("malloc");
return (EXIT_FAILURE);
}
perror("SIOCGIP6ADDRPOLICY");
return (EXIT_FAILURE);
}
}
if (count == 0) {
/*
* There should always at least be a default entry in the
* policy table, so the minimum acceptable value of
* policy_count is 1.
*/
"IPv6 address selection policy is empty.\n"), myname);
return (EXIT_FAILURE);
}
/*
* The format printed here must also be parsable by parseconf(),
* since we expect users to be able to redirect this output to
* a usable configuration file if need be.
*/
(void) printf("# Prefix "
" Precedence Label\n");
sizeof (prefixstr)),
}
if (policy_ptr != policy)
return (EXIT_SUCCESS);
}
/*
* ip_mask_to_plen_v6(v6mask)
*
* This function takes a mask and returns number of bits set in the
* mask (the represented prefix length). Assumes a contigious mask.
*/
int
{
int i;
return (IPV6_ABITS);
/* Find number of words with 32 ones */
bits = 0;
for (i = 0; i < 4; i++) {
bits += 32;
continue;
}
break;
}
/*
* Find number of bits in the last word by searching
* for the first one from the right
*/
if (mask == 0)
return (bits);
}
/*
* ip_plen_to_mask_v6(plen, bitmask)
*
* Convert a prefix length to the mask for that prefix.
* Returns the argument bitmask.
*/
{
return (NULL);
if (plen == 0)
return (bitmask);
while (plen > 32) {
*ptr++ = 0xffffffffU;
plen -= 32;
}
return (bitmask);
}
/*
* strioctl(fd, cmd, ptr, ilen)
*
* Passes an I_STR ioctl to fd. The ioctl type is specified by cmd, and
* any date to be sent down is specified by a pointer to the buffer (ptr)
* and the buffer size (ilen). Returns the return value from the ioctl()
* call.
*/
static int
{
int retv;
break;
}
return (retv);
}
static void
usage(void)
{
"Usage: %s\n"
" %s -f <filename>\n"
}