1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "defs.h" 30*7c478bd9Sstevel@tonic-gate #include "tables.h" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * Parse the config file which consists of entries of the form: 34*7c478bd9Sstevel@tonic-gate * ifdefault [<variable> <value>]* 35*7c478bd9Sstevel@tonic-gate * prefixdefault [<variable> <value>]* 36*7c478bd9Sstevel@tonic-gate * if <ifname> [<variable> <value>]* 37*7c478bd9Sstevel@tonic-gate * prefix <prefix>/<length> <ifname> [<variable> <value>]* 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * All "ifdefault" and "prefixdefault" entries must preceed any 40*7c478bd9Sstevel@tonic-gate * "if" and "prefix" entries. 41*7c478bd9Sstevel@tonic-gate * 42*7c478bd9Sstevel@tonic-gate * Values (such as expiry dates) which contain white space 43*7c478bd9Sstevel@tonic-gate * can be quoted with single or double quotes. 44*7c478bd9Sstevel@tonic-gate */ 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate /* maximum length of messages we send to syslog */ 47*7c478bd9Sstevel@tonic-gate #define NDPD_LOGMSGSIZE 1024 48*7c478bd9Sstevel@tonic-gate typedef boolean_t (*pfb_t)(char *, uint_t *); 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate struct configinfo { 51*7c478bd9Sstevel@tonic-gate char *ci_name; 52*7c478bd9Sstevel@tonic-gate uint_t ci_min; /* 0: no min check */ 53*7c478bd9Sstevel@tonic-gate uint_t ci_max; /* ~0U: no max check */ 54*7c478bd9Sstevel@tonic-gate uint_t ci_default; 55*7c478bd9Sstevel@tonic-gate uint_t ci_index; /* Into result array */ 56*7c478bd9Sstevel@tonic-gate pfb_t ci_parsefunc; /* Parse function returns -1 on failure */ 57*7c478bd9Sstevel@tonic-gate }; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate enum config_type { CONFIG_IF, CONFIG_PREFIX}; 60*7c478bd9Sstevel@tonic-gate typedef enum config_type config_type_t; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate static void set_protocol_defaults(void); 63*7c478bd9Sstevel@tonic-gate static void print_defaults(void); 64*7c478bd9Sstevel@tonic-gate static void parse_var_value(config_type_t, struct configinfo *, char *, char *, 65*7c478bd9Sstevel@tonic-gate struct confvar *); 66*7c478bd9Sstevel@tonic-gate static void parse_default(config_type_t, struct configinfo *, char **, int, 67*7c478bd9Sstevel@tonic-gate struct confvar *); 68*7c478bd9Sstevel@tonic-gate static void parse_if(struct configinfo *, char **, int); 69*7c478bd9Sstevel@tonic-gate static void parse_prefix(struct configinfo *, char **, int); 70*7c478bd9Sstevel@tonic-gate static boolean_t parse_onoff(char *, uint_t *); /* boolean */ 71*7c478bd9Sstevel@tonic-gate static boolean_t parse_int(char *, uint_t *); /* integer */ 72*7c478bd9Sstevel@tonic-gate static boolean_t parse_ms(char *, uint_t *); /* milliseconds */ 73*7c478bd9Sstevel@tonic-gate static boolean_t parse_s(char *, uint_t *); /* seconds */ 74*7c478bd9Sstevel@tonic-gate static boolean_t parse_date(char *, uint_t *); /* date format */ 75*7c478bd9Sstevel@tonic-gate static void conferr(char *fmt, ...); 76*7c478bd9Sstevel@tonic-gate static FILE *open_conffile(char *filename); 77*7c478bd9Sstevel@tonic-gate static int parse_line(char *line, char *argvec[], int argcount); 78*7c478bd9Sstevel@tonic-gate static int readline(FILE *fp, char *line, int length); 79*7c478bd9Sstevel@tonic-gate static int parse_addrprefix(char *strin, struct in6_addr *in6); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Per interface configuration variables. 83*7c478bd9Sstevel@tonic-gate * Min, max, and default values are from RFC 2461. 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate static struct configinfo iflist[] = { 86*7c478bd9Sstevel@tonic-gate /* Name, Min, Max, Default, Index */ 87*7c478bd9Sstevel@tonic-gate { "DupAddrDetectTransmits", 0, 100, 1, I_DupAddrDetectTransmits, 88*7c478bd9Sstevel@tonic-gate parse_int }, 89*7c478bd9Sstevel@tonic-gate { "AdvSendAdvertisements", 0, 1, 0, I_AdvSendAdvertisements, 90*7c478bd9Sstevel@tonic-gate parse_onoff }, 91*7c478bd9Sstevel@tonic-gate { "MaxRtrAdvInterval", 4, 1800, 600, I_MaxRtrAdvInterval, parse_s }, 92*7c478bd9Sstevel@tonic-gate { "MinRtrAdvInterval", 3, 1350, 200, I_MinRtrAdvInterval, parse_s }, 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * No greater than .75 * MaxRtrAdvInterval. 95*7c478bd9Sstevel@tonic-gate * Default: 0.33 * MaxRtrAdvInterval 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate { "AdvManagedFlag", 0, 1, 0, I_AdvManagedFlag, parse_onoff }, 98*7c478bd9Sstevel@tonic-gate { "AdvOtherConfigFlag", 0, 1, 0, I_AdvOtherConfigFlag, parse_onoff }, 99*7c478bd9Sstevel@tonic-gate { "AdvLinkMTU", IPV6_MIN_MTU, 65535, 0, I_AdvLinkMTU, parse_int }, 100*7c478bd9Sstevel@tonic-gate { "AdvReachableTime", 0, 3600000, 0, I_AdvReachableTime, parse_ms }, 101*7c478bd9Sstevel@tonic-gate { "AdvRetransTimer", 0, ~0U, 0, I_AdvRetransTimer, parse_ms }, 102*7c478bd9Sstevel@tonic-gate { "AdvCurHopLimit", 0, 255, 0, I_AdvCurHopLimit, parse_int }, 103*7c478bd9Sstevel@tonic-gate { "AdvDefaultLifetime", 0, 9000, 1800, I_AdvDefaultLifetime, parse_s }, 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * MUST be either zero or between MaxRtrAdvInterval and 9000 seconds. 106*7c478bd9Sstevel@tonic-gate * Default: 3 * MaxRtrAdvInterval 107*7c478bd9Sstevel@tonic-gate */ 108*7c478bd9Sstevel@tonic-gate { "StatelessAddrConf", 0, 1, 1, I_StatelessAddrConf, parse_onoff }, 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * Tmp* variables from RFC 3041, where defaults are defined. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate { "TmpAddrsEnabled", 0, 1, 0, I_TmpAddrsEnabled, parse_onoff }, 113*7c478bd9Sstevel@tonic-gate { "TmpValidLifetime", 0, ~0U, 604800, I_TmpValidLifetime, parse_s }, 114*7c478bd9Sstevel@tonic-gate { "TmpPreferredLifetime", 0, ~0U, 86400, I_TmpPreferredLifetime, 115*7c478bd9Sstevel@tonic-gate parse_s }, 116*7c478bd9Sstevel@tonic-gate { "TmpRegenAdvance", 0, 60, 5, I_TmpRegenAdvance, parse_s }, 117*7c478bd9Sstevel@tonic-gate { "TmpMaxDesyncFactor", 0, 600, 600, I_TmpMaxDesyncFactor, parse_s }, 118*7c478bd9Sstevel@tonic-gate { NULL, 0, 0, 0, 0 } 119*7c478bd9Sstevel@tonic-gate }; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * Per prefix: AdvPrefixList configuration variables. 123*7c478bd9Sstevel@tonic-gate * Min, max, and default values are from RFC 2461. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate static struct configinfo prefixlist[] = { 126*7c478bd9Sstevel@tonic-gate /* Name, Min, Max, Default, Index */ 127*7c478bd9Sstevel@tonic-gate { "AdvValidLifetime", 0, ~0U, 2592000, I_AdvValidLifetime, 128*7c478bd9Sstevel@tonic-gate parse_s }, 129*7c478bd9Sstevel@tonic-gate { "AdvOnLinkFlag", 0, 1, 1, I_AdvOnLinkFlag, parse_onoff }, 130*7c478bd9Sstevel@tonic-gate { "AdvPreferredLifetime", 0, ~0U, 604800, I_AdvPreferredLifetime, 131*7c478bd9Sstevel@tonic-gate parse_s}, 132*7c478bd9Sstevel@tonic-gate { "AdvAutonomousFlag", 0, 1, 1, I_AdvAutonomousFlag, parse_onoff }, 133*7c478bd9Sstevel@tonic-gate { "AdvValidExpiration", 0, ~0U, 0, I_AdvValidExpiration, 134*7c478bd9Sstevel@tonic-gate parse_date }, 135*7c478bd9Sstevel@tonic-gate { "AdvPreferredExpiration", 0, ~0U, 0, I_AdvPreferredExpiration, 136*7c478bd9Sstevel@tonic-gate parse_date}, 137*7c478bd9Sstevel@tonic-gate { NULL, 0, 0, 0, 0 }, 138*7c478bd9Sstevel@tonic-gate }; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate /* 141*7c478bd9Sstevel@tonic-gate * Data structures used to merge above protocol defaults 142*7c478bd9Sstevel@tonic-gate * with defaults specified in the configuration file. 143*7c478bd9Sstevel@tonic-gate * ifdefault is not static because new interfaces can be 144*7c478bd9Sstevel@tonic-gate * created outside of the configuration context. 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate struct confvar ifdefaults[I_IFSIZE]; 147*7c478bd9Sstevel@tonic-gate static struct confvar prefixdefaults[I_PREFIXSIZE]; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate static char conf_filename[MAXPATHLEN]; 150*7c478bd9Sstevel@tonic-gate static int lineno; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* 153*7c478bd9Sstevel@tonic-gate * Checks for violations of section 5.5.3 (c) of RFC 2462. 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate static void 156*7c478bd9Sstevel@tonic-gate check_var_consistency(struct confvar *cv, void *save, int size) 157*7c478bd9Sstevel@tonic-gate { 158*7c478bd9Sstevel@tonic-gate boolean_t rollback = _B_FALSE; 159*7c478bd9Sstevel@tonic-gate int prefl, prefe, valid; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate prefl = cv[I_AdvPreferredLifetime].cf_value; 162*7c478bd9Sstevel@tonic-gate prefe = cv[I_AdvPreferredExpiration].cf_value; 163*7c478bd9Sstevel@tonic-gate valid = cv[I_AdvValidLifetime].cf_value; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate if (prefl > valid) { 166*7c478bd9Sstevel@tonic-gate conferr("AdvPreferredLifetime (%u) is greater than " 167*7c478bd9Sstevel@tonic-gate "valid lifetime (%u)\n", prefl, valid); 168*7c478bd9Sstevel@tonic-gate rollback = _B_TRUE; 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate if (prefe > valid) { 172*7c478bd9Sstevel@tonic-gate conferr("AdvPreferredExpiration (%u) is greater than " 173*7c478bd9Sstevel@tonic-gate "valid lifetime (%u)\n", prefe, valid); 174*7c478bd9Sstevel@tonic-gate rollback = _B_TRUE; 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if (rollback) { 178*7c478bd9Sstevel@tonic-gate (void) memcpy(cv, save, size); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* 183*7c478bd9Sstevel@tonic-gate * Check for invalid lifetime values for RFC3041 addresses 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate static void 186*7c478bd9Sstevel@tonic-gate check_if_var_consistency(struct confvar *cv, void *save, int size) 187*7c478bd9Sstevel@tonic-gate { 188*7c478bd9Sstevel@tonic-gate boolean_t rollback = _B_FALSE; 189*7c478bd9Sstevel@tonic-gate int tpref, tvalid, tdesync, tregen; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate tpref = cv[I_TmpPreferredLifetime].cf_value; 192*7c478bd9Sstevel@tonic-gate tvalid = cv[I_TmpValidLifetime].cf_value; 193*7c478bd9Sstevel@tonic-gate tdesync = cv[I_TmpMaxDesyncFactor].cf_value; 194*7c478bd9Sstevel@tonic-gate tregen = cv[I_TmpRegenAdvance].cf_value; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * Only need to do this if tmp addrs are enabled. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate if (cv[I_TmpAddrsEnabled].cf_value == 0) 200*7c478bd9Sstevel@tonic-gate return; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (tdesync > tpref) { 203*7c478bd9Sstevel@tonic-gate conferr("TmpDesyncFactor (%u) is greater than " 204*7c478bd9Sstevel@tonic-gate "TmpPreferredLifetime (%u)\n", tdesync, tpref); 205*7c478bd9Sstevel@tonic-gate rollback = _B_TRUE; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate if (tpref > tvalid) { 209*7c478bd9Sstevel@tonic-gate conferr("TmpPreferredLifetime (%u) is greater than " 210*7c478bd9Sstevel@tonic-gate "TmpValidLifetime (%u)\n", tpref, tvalid); 211*7c478bd9Sstevel@tonic-gate rollback = _B_TRUE; 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate if (tregen > tvalid) { 215*7c478bd9Sstevel@tonic-gate conferr("TmpRegenAdvance (%u) is greater than " 216*7c478bd9Sstevel@tonic-gate "TmpValidLifetime (%u)\n", tregen, tvalid); 217*7c478bd9Sstevel@tonic-gate rollback = _B_TRUE; 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if (rollback) { 221*7c478bd9Sstevel@tonic-gate (void) memcpy(cv, save, size); 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate int 226*7c478bd9Sstevel@tonic-gate parse_config(char *config_file, boolean_t file_required) 227*7c478bd9Sstevel@tonic-gate { 228*7c478bd9Sstevel@tonic-gate FILE *fp; 229*7c478bd9Sstevel@tonic-gate char line[MAXLINELEN]; 230*7c478bd9Sstevel@tonic-gate char pline[MAXLINELEN]; 231*7c478bd9Sstevel@tonic-gate int argcount; 232*7c478bd9Sstevel@tonic-gate char *argvec[MAXARGSPERLINE]; 233*7c478bd9Sstevel@tonic-gate int defaultdone = 0; /* Set when first non-default command found */ 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (debug & D_CONFIG) 236*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_config()\n"); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate set_protocol_defaults(); 239*7c478bd9Sstevel@tonic-gate if (debug & D_DEFAULTS) 240*7c478bd9Sstevel@tonic-gate print_defaults(); 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate fp = open_conffile(config_file); 243*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 244*7c478bd9Sstevel@tonic-gate if (errno == ENOENT && !file_required) 245*7c478bd9Sstevel@tonic-gate return (0); 246*7c478bd9Sstevel@tonic-gate logperror(config_file); 247*7c478bd9Sstevel@tonic-gate return (-1); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate while (readline(fp, line, sizeof (line)) != 0) { 250*7c478bd9Sstevel@tonic-gate (void) strncpy(pline, line, sizeof (pline)); 251*7c478bd9Sstevel@tonic-gate pline[sizeof (pline) - 1] = '\0'; /* NULL terminate */ 252*7c478bd9Sstevel@tonic-gate argcount = parse_line(pline, argvec, 253*7c478bd9Sstevel@tonic-gate sizeof (argvec) / sizeof (argvec[0])); 254*7c478bd9Sstevel@tonic-gate if (debug & D_PARSE) { 255*7c478bd9Sstevel@tonic-gate int i; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "scanned %d args\n", argcount); 258*7c478bd9Sstevel@tonic-gate for (i = 0; i < argcount; i++) 259*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "arg[%d]: %s\n", 260*7c478bd9Sstevel@tonic-gate i, argvec[i]); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate if (argcount == 0) { 263*7c478bd9Sstevel@tonic-gate /* Empty line - or comment only line */ 264*7c478bd9Sstevel@tonic-gate continue; 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate if (strcmp(argvec[0], "ifdefault") == 0) { 267*7c478bd9Sstevel@tonic-gate char save[sizeof (ifdefaults)]; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (defaultdone) { 270*7c478bd9Sstevel@tonic-gate conferr("ifdefault after non-default " 271*7c478bd9Sstevel@tonic-gate "command\n"); 272*7c478bd9Sstevel@tonic-gate continue; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * Save existing values in case what we read is 276*7c478bd9Sstevel@tonic-gate * invalid and we need to restore previous settings. 277*7c478bd9Sstevel@tonic-gate */ 278*7c478bd9Sstevel@tonic-gate (void) memcpy(save, ifdefaults, sizeof (ifdefaults)); 279*7c478bd9Sstevel@tonic-gate parse_default(CONFIG_IF, iflist, argvec+1, argcount-1, 280*7c478bd9Sstevel@tonic-gate ifdefaults); 281*7c478bd9Sstevel@tonic-gate check_if_var_consistency(ifdefaults, save, 282*7c478bd9Sstevel@tonic-gate sizeof (save)); 283*7c478bd9Sstevel@tonic-gate } else if (strcmp(argvec[0], "prefixdefault") == 0) { 284*7c478bd9Sstevel@tonic-gate char save[sizeof (prefixdefaults)]; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate if (defaultdone) { 287*7c478bd9Sstevel@tonic-gate conferr("prefixdefault after non-default " 288*7c478bd9Sstevel@tonic-gate "command\n"); 289*7c478bd9Sstevel@tonic-gate continue; 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate /* 292*7c478bd9Sstevel@tonic-gate * Save existing values in case what we read is 293*7c478bd9Sstevel@tonic-gate * invalid and we need to restore previous settings. 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate (void) memcpy(save, prefixdefaults, 296*7c478bd9Sstevel@tonic-gate sizeof (prefixdefaults)); 297*7c478bd9Sstevel@tonic-gate parse_default(CONFIG_PREFIX, prefixlist, argvec+1, 298*7c478bd9Sstevel@tonic-gate argcount-1, prefixdefaults); 299*7c478bd9Sstevel@tonic-gate check_var_consistency(prefixdefaults, save, 300*7c478bd9Sstevel@tonic-gate sizeof (save)); 301*7c478bd9Sstevel@tonic-gate } else if (strcmp(argvec[0], "if") == 0) { 302*7c478bd9Sstevel@tonic-gate defaultdone = 1; 303*7c478bd9Sstevel@tonic-gate parse_if(iflist, argvec+1, argcount-1); 304*7c478bd9Sstevel@tonic-gate } else if (strcmp(argvec[0], "prefix") == 0) { 305*7c478bd9Sstevel@tonic-gate defaultdone = 1; 306*7c478bd9Sstevel@tonic-gate parse_prefix(prefixlist, argvec+1, argcount-1); 307*7c478bd9Sstevel@tonic-gate } else { 308*7c478bd9Sstevel@tonic-gate conferr("Unknown command: %s\n", argvec[0]); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 312*7c478bd9Sstevel@tonic-gate if (debug & D_DEFAULTS) 313*7c478bd9Sstevel@tonic-gate print_defaults(); 314*7c478bd9Sstevel@tonic-gate return (0); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate /* 318*7c478bd9Sstevel@tonic-gate * Extract the defaults from the configinfo tables to initialize 319*7c478bd9Sstevel@tonic-gate * the ifdefaults and prefixdefaults arrays. 320*7c478bd9Sstevel@tonic-gate * The arrays are needed to track which defaults have been changed 321*7c478bd9Sstevel@tonic-gate * by the config file. 322*7c478bd9Sstevel@tonic-gate */ 323*7c478bd9Sstevel@tonic-gate static void 324*7c478bd9Sstevel@tonic-gate set_protocol_defaults(void) 325*7c478bd9Sstevel@tonic-gate { 326*7c478bd9Sstevel@tonic-gate struct configinfo *cip; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (debug & D_DEFAULTS) 329*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "extract_protocol_defaults\n"); 330*7c478bd9Sstevel@tonic-gate for (cip = iflist; cip->ci_name != NULL; cip++) { 331*7c478bd9Sstevel@tonic-gate ifdefaults[cip->ci_index].cf_value = cip->ci_default; 332*7c478bd9Sstevel@tonic-gate ifdefaults[cip->ci_index].cf_notdefault = _B_FALSE; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate for (cip = prefixlist; cip->ci_name != NULL; cip++) { 335*7c478bd9Sstevel@tonic-gate prefixdefaults[cip->ci_index].cf_value = cip->ci_default; 336*7c478bd9Sstevel@tonic-gate prefixdefaults[cip->ci_index].cf_notdefault = _B_FALSE; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate void 341*7c478bd9Sstevel@tonic-gate print_iflist(struct confvar *confvar) 342*7c478bd9Sstevel@tonic-gate { 343*7c478bd9Sstevel@tonic-gate struct configinfo *cip; 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate for (cip = iflist; cip->ci_name != NULL; cip++) { 346*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "\t%s min %u max %u def %u value %u set %d\n", 347*7c478bd9Sstevel@tonic-gate cip->ci_name, cip->ci_min, cip->ci_max, cip->ci_default, 348*7c478bd9Sstevel@tonic-gate confvar[cip->ci_index].cf_value, 349*7c478bd9Sstevel@tonic-gate confvar[cip->ci_index].cf_notdefault); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate void 354*7c478bd9Sstevel@tonic-gate print_prefixlist(struct confvar *confvar) 355*7c478bd9Sstevel@tonic-gate { 356*7c478bd9Sstevel@tonic-gate struct configinfo *cip; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate for (cip = prefixlist; cip->ci_name != NULL; cip++) { 359*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "\t%s min %u max %u def %u value %u set %d\n", 360*7c478bd9Sstevel@tonic-gate cip->ci_name, cip->ci_min, cip->ci_max, cip->ci_default, 361*7c478bd9Sstevel@tonic-gate confvar[cip->ci_index].cf_value, 362*7c478bd9Sstevel@tonic-gate confvar[cip->ci_index].cf_notdefault); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate static void 368*7c478bd9Sstevel@tonic-gate print_defaults(void) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "Default interface variables:\n"); 371*7c478bd9Sstevel@tonic-gate print_iflist(ifdefaults); 372*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "Default prefix variables:\n"); 373*7c478bd9Sstevel@tonic-gate print_prefixlist(prefixdefaults); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * Read from fp. Handle \ at the end of the line by joining lines together. 378*7c478bd9Sstevel@tonic-gate * Return 0 on EOF. 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate static int 381*7c478bd9Sstevel@tonic-gate readline(FILE *fp, char *line, int length) 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate int got = 0; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate retry: 386*7c478bd9Sstevel@tonic-gate errno = 0; 387*7c478bd9Sstevel@tonic-gate if (fgets(line, length, fp) == NULL) { 388*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 389*7c478bd9Sstevel@tonic-gate goto retry; 390*7c478bd9Sstevel@tonic-gate if (got != 0) 391*7c478bd9Sstevel@tonic-gate return (1); 392*7c478bd9Sstevel@tonic-gate else 393*7c478bd9Sstevel@tonic-gate return (0); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate lineno++; 396*7c478bd9Sstevel@tonic-gate got = strlen(line); 397*7c478bd9Sstevel@tonic-gate /* Look for trailing \. Note that fgets includes the linefeed. */ 398*7c478bd9Sstevel@tonic-gate if (got >= 2 && line[got-2] == '\\') { 399*7c478bd9Sstevel@tonic-gate /* Skip \ and LF */ 400*7c478bd9Sstevel@tonic-gate line += got - 2; 401*7c478bd9Sstevel@tonic-gate length -= got - 2; 402*7c478bd9Sstevel@tonic-gate goto retry; 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate /* Remove the trailing linefeed */ 405*7c478bd9Sstevel@tonic-gate if (got > 0) 406*7c478bd9Sstevel@tonic-gate line[got-1] = '\0'; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate return (1); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate /* 412*7c478bd9Sstevel@tonic-gate * Parse a line splitting it off at whitspace characters. 413*7c478bd9Sstevel@tonic-gate * Modifies the content of the string by inserting NULLs. 414*7c478bd9Sstevel@tonic-gate * If more arguments than fits in argvec/argcount then ignore the last. 415*7c478bd9Sstevel@tonic-gate * Returns argcount. 416*7c478bd9Sstevel@tonic-gate * Handles single quotes and double quotes. 417*7c478bd9Sstevel@tonic-gate */ 418*7c478bd9Sstevel@tonic-gate static int 419*7c478bd9Sstevel@tonic-gate parse_line(char *line, char *argvec[], int argcount) 420*7c478bd9Sstevel@tonic-gate { 421*7c478bd9Sstevel@tonic-gate int i = 0; 422*7c478bd9Sstevel@tonic-gate char *cp; 423*7c478bd9Sstevel@tonic-gate boolean_t insingle_quote = _B_FALSE; 424*7c478bd9Sstevel@tonic-gate boolean_t indouble_quote = _B_FALSE; 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate /* Truncate at the beginning of a comment */ 427*7c478bd9Sstevel@tonic-gate cp = strchr(line, '#'); 428*7c478bd9Sstevel@tonic-gate if (cp != NULL) 429*7c478bd9Sstevel@tonic-gate *cp = '\0'; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate for (;;) { 432*7c478bd9Sstevel@tonic-gate /* Skip any whitespace */ 433*7c478bd9Sstevel@tonic-gate while (isspace(*line) && *line != '\0') 434*7c478bd9Sstevel@tonic-gate line++; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate if (*line == '\'') { 437*7c478bd9Sstevel@tonic-gate line++; 438*7c478bd9Sstevel@tonic-gate if (*line == '\0') 439*7c478bd9Sstevel@tonic-gate return (i); 440*7c478bd9Sstevel@tonic-gate insingle_quote = _B_TRUE; 441*7c478bd9Sstevel@tonic-gate } else if (*line == '"') { 442*7c478bd9Sstevel@tonic-gate line++; 443*7c478bd9Sstevel@tonic-gate if (*line == '\0') 444*7c478bd9Sstevel@tonic-gate return (i); 445*7c478bd9Sstevel@tonic-gate indouble_quote = _B_TRUE; 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate argvec[i] = line; 448*7c478bd9Sstevel@tonic-gate if (*line == '\0') 449*7c478bd9Sstevel@tonic-gate return (i); 450*7c478bd9Sstevel@tonic-gate i++; 451*7c478bd9Sstevel@tonic-gate /* Skip until next whitespace or end of quoted text */ 452*7c478bd9Sstevel@tonic-gate if (insingle_quote) { 453*7c478bd9Sstevel@tonic-gate while (*line != '\'' && *line != '\0') 454*7c478bd9Sstevel@tonic-gate line++; 455*7c478bd9Sstevel@tonic-gate if (*line == '\'') { 456*7c478bd9Sstevel@tonic-gate *line = ' '; 457*7c478bd9Sstevel@tonic-gate } else { 458*7c478bd9Sstevel@tonic-gate /* Handle missing quote at end */ 459*7c478bd9Sstevel@tonic-gate i--; 460*7c478bd9Sstevel@tonic-gate conferr("Missing end quote - ignoring <%s>\n", 461*7c478bd9Sstevel@tonic-gate argvec[i]); 462*7c478bd9Sstevel@tonic-gate return (i); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate insingle_quote = _B_FALSE; 465*7c478bd9Sstevel@tonic-gate } else if (indouble_quote) { 466*7c478bd9Sstevel@tonic-gate while (*line != '"' && *line != '\0') 467*7c478bd9Sstevel@tonic-gate line++; 468*7c478bd9Sstevel@tonic-gate if (*line == '"') { 469*7c478bd9Sstevel@tonic-gate *line = ' '; 470*7c478bd9Sstevel@tonic-gate } else { 471*7c478bd9Sstevel@tonic-gate /* Handle missing quote at end */ 472*7c478bd9Sstevel@tonic-gate i--; 473*7c478bd9Sstevel@tonic-gate conferr("Missing end quote - ignoring <%s>\n", 474*7c478bd9Sstevel@tonic-gate argvec[i]); 475*7c478bd9Sstevel@tonic-gate return (i); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate indouble_quote = _B_FALSE; 478*7c478bd9Sstevel@tonic-gate } else { 479*7c478bd9Sstevel@tonic-gate while (!isspace(*line) && *line != '\0') 480*7c478bd9Sstevel@tonic-gate line++; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate if (*line != '\0') { 483*7c478bd9Sstevel@tonic-gate /* Break off argument */ 484*7c478bd9Sstevel@tonic-gate *line++ = '\0'; 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate if (i > argcount) 487*7c478bd9Sstevel@tonic-gate return (argcount); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate static void 493*7c478bd9Sstevel@tonic-gate parse_var_value(config_type_t type, struct configinfo *list, char *varstr, 494*7c478bd9Sstevel@tonic-gate char *valstr, struct confvar *confvar) 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate struct configinfo *cip; 497*7c478bd9Sstevel@tonic-gate uint_t val; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (debug & D_CONFIG) { 500*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_var_value(%d, %s, %s)\n", 501*7c478bd9Sstevel@tonic-gate (int)type, varstr, valstr); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate for (cip = list; cip->ci_name != NULL; cip++) { 505*7c478bd9Sstevel@tonic-gate if (strcasecmp(cip->ci_name, varstr) == 0) 506*7c478bd9Sstevel@tonic-gate break; 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate if (cip->ci_name == NULL) { 509*7c478bd9Sstevel@tonic-gate conferr("Unknown variable: <%s>\n", varstr); 510*7c478bd9Sstevel@tonic-gate return; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate if (!(*cip->ci_parsefunc)(valstr, &val)) { 513*7c478bd9Sstevel@tonic-gate conferr("Bad value: <%s>\n", valstr); 514*7c478bd9Sstevel@tonic-gate return; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate if (cip->ci_min != 0 && val < cip->ci_min) { 517*7c478bd9Sstevel@tonic-gate conferr("Value %s is below minimum %u for %s\n", 518*7c478bd9Sstevel@tonic-gate valstr, cip->ci_min, varstr); 519*7c478bd9Sstevel@tonic-gate return; 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate if (cip->ci_max != ~0U && val > cip->ci_max) { 522*7c478bd9Sstevel@tonic-gate conferr("Value %s is above maximum %u for %s\n", 523*7c478bd9Sstevel@tonic-gate valstr, cip->ci_max, varstr); 524*7c478bd9Sstevel@tonic-gate return; 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate /* Check against dynamic/relative limits */ 527*7c478bd9Sstevel@tonic-gate if (type == CONFIG_IF) { 528*7c478bd9Sstevel@tonic-gate if (cip->ci_index == I_MinRtrAdvInterval && 529*7c478bd9Sstevel@tonic-gate confvar[I_MaxRtrAdvInterval].cf_notdefault && 530*7c478bd9Sstevel@tonic-gate val > confvar[I_MaxRtrAdvInterval].cf_value * 0.75) { 531*7c478bd9Sstevel@tonic-gate conferr("MinRtrAdvInterval exceeds .75 * " 532*7c478bd9Sstevel@tonic-gate "MaxRtrAdvInterval (%u)\n", 533*7c478bd9Sstevel@tonic-gate confvar[I_MaxRtrAdvInterval].cf_value); 534*7c478bd9Sstevel@tonic-gate return; 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate if (cip->ci_index == I_MaxRtrAdvInterval && 537*7c478bd9Sstevel@tonic-gate confvar[I_MinRtrAdvInterval].cf_notdefault && 538*7c478bd9Sstevel@tonic-gate confvar[I_MinRtrAdvInterval].cf_value > val * 0.75) { 539*7c478bd9Sstevel@tonic-gate conferr("MinRtrAdvInterval (%u) exceeds .75 * " 540*7c478bd9Sstevel@tonic-gate "MaxRtrAdvInterval\n", 541*7c478bd9Sstevel@tonic-gate confvar[I_MinRtrAdvInterval].cf_value); 542*7c478bd9Sstevel@tonic-gate return; 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate if (cip->ci_index == I_AdvDefaultLifetime && 545*7c478bd9Sstevel@tonic-gate confvar[I_MaxRtrAdvInterval].cf_notdefault && 546*7c478bd9Sstevel@tonic-gate val != 0 && 547*7c478bd9Sstevel@tonic-gate val < confvar[I_MaxRtrAdvInterval].cf_value) { 548*7c478bd9Sstevel@tonic-gate conferr("AdvDefaultLifetime is not between " 549*7c478bd9Sstevel@tonic-gate "MaxRtrAdrInterval (%u) and 9000 seconds\n", 550*7c478bd9Sstevel@tonic-gate confvar[I_MaxRtrAdvInterval].cf_value); 551*7c478bd9Sstevel@tonic-gate return; 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate if (cip->ci_index == I_MaxRtrAdvInterval && 554*7c478bd9Sstevel@tonic-gate confvar[I_AdvDefaultLifetime].cf_notdefault && 555*7c478bd9Sstevel@tonic-gate confvar[I_AdvDefaultLifetime].cf_value < val) { 556*7c478bd9Sstevel@tonic-gate conferr("AdvDefaultLifetime (%u) is not between " 557*7c478bd9Sstevel@tonic-gate "MaxRtrAdrInterval and 9000 seconds\n", 558*7c478bd9Sstevel@tonic-gate confvar[I_AdvDefaultLifetime].cf_value); 559*7c478bd9Sstevel@tonic-gate return; 560*7c478bd9Sstevel@tonic-gate } 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate confvar[cip->ci_index].cf_value = val; 563*7c478bd9Sstevel@tonic-gate confvar[cip->ci_index].cf_notdefault = _B_TRUE; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* Derive dynamic/relative variables based on this one */ 566*7c478bd9Sstevel@tonic-gate if (type == CONFIG_IF) { 567*7c478bd9Sstevel@tonic-gate if (cip->ci_index == I_MaxRtrAdvInterval && 568*7c478bd9Sstevel@tonic-gate !confvar[I_MinRtrAdvInterval].cf_notdefault) 569*7c478bd9Sstevel@tonic-gate confvar[I_MinRtrAdvInterval].cf_value = val / 3; 570*7c478bd9Sstevel@tonic-gate if (cip->ci_index == I_MaxRtrAdvInterval && 571*7c478bd9Sstevel@tonic-gate !confvar[I_AdvDefaultLifetime].cf_notdefault) 572*7c478bd9Sstevel@tonic-gate confvar[I_AdvDefaultLifetime].cf_value = 3 * val; 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate /* 577*7c478bd9Sstevel@tonic-gate * Split up the line into <variable> <value> pairs 578*7c478bd9Sstevel@tonic-gate */ 579*7c478bd9Sstevel@tonic-gate static void 580*7c478bd9Sstevel@tonic-gate parse_default(config_type_t type, struct configinfo *list, 581*7c478bd9Sstevel@tonic-gate char *argvec[], int argcount, struct confvar *defaults) 582*7c478bd9Sstevel@tonic-gate { 583*7c478bd9Sstevel@tonic-gate if (debug & D_CONFIG) 584*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_default: argc %d\n", argcount); 585*7c478bd9Sstevel@tonic-gate while (argcount >= 2) { 586*7c478bd9Sstevel@tonic-gate parse_var_value(type, list, argvec[0], argvec[1], defaults); 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate argcount -= 2; 589*7c478bd9Sstevel@tonic-gate argvec += 2; 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate if (argcount != 0) 592*7c478bd9Sstevel@tonic-gate conferr("Trailing text <%s> ignored\n", argvec[0]); 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate /* 596*7c478bd9Sstevel@tonic-gate * Returns true if ok; otherwise false. 597*7c478bd9Sstevel@tonic-gate */ 598*7c478bd9Sstevel@tonic-gate static void 599*7c478bd9Sstevel@tonic-gate parse_if(struct configinfo *list, char *argvec[], int argcount) 600*7c478bd9Sstevel@tonic-gate { 601*7c478bd9Sstevel@tonic-gate char *ifname; 602*7c478bd9Sstevel@tonic-gate struct phyint *pi; 603*7c478bd9Sstevel@tonic-gate char save[sizeof (pi->pi_config)]; 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate if (debug & D_CONFIG) 606*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_if: argc %d\n", argcount); 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate if (argcount < 1) { 609*7c478bd9Sstevel@tonic-gate conferr("Missing interface name\n"); 610*7c478bd9Sstevel@tonic-gate return; 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate ifname = argvec[0]; 613*7c478bd9Sstevel@tonic-gate argvec++; 614*7c478bd9Sstevel@tonic-gate argcount--; 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate pi = phyint_lookup(ifname); 617*7c478bd9Sstevel@tonic-gate if (pi == NULL) { 618*7c478bd9Sstevel@tonic-gate /* 619*7c478bd9Sstevel@tonic-gate * Create the physical interface structure. 620*7c478bd9Sstevel@tonic-gate * Note, phyint_create() sets the interface 621*7c478bd9Sstevel@tonic-gate * defaults in pi_config. 622*7c478bd9Sstevel@tonic-gate */ 623*7c478bd9Sstevel@tonic-gate pi = phyint_create(ifname); 624*7c478bd9Sstevel@tonic-gate if (pi == NULL) { 625*7c478bd9Sstevel@tonic-gate conferr("Unable to use interface %s\n", ifname); 626*7c478bd9Sstevel@tonic-gate return; 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate (void) memcpy(save, pi->pi_config, sizeof (save)); 631*7c478bd9Sstevel@tonic-gate while (argcount >= 2) { 632*7c478bd9Sstevel@tonic-gate parse_var_value(CONFIG_IF, list, argvec[0], argvec[1], 633*7c478bd9Sstevel@tonic-gate pi->pi_config); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate argcount -= 2; 636*7c478bd9Sstevel@tonic-gate argvec += 2; 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate if (argcount != 0) 639*7c478bd9Sstevel@tonic-gate logmsg(LOG_ERR, "Trailing text <%s> ignored\n", argvec[0]); 640*7c478bd9Sstevel@tonic-gate check_if_var_consistency(pi->pi_config, save, sizeof (save)); 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate static void 644*7c478bd9Sstevel@tonic-gate parse_prefix(struct configinfo *list, char *argvec[], int argcount) 645*7c478bd9Sstevel@tonic-gate { 646*7c478bd9Sstevel@tonic-gate char *ifname, *prefix; 647*7c478bd9Sstevel@tonic-gate struct phyint *pi; 648*7c478bd9Sstevel@tonic-gate struct adv_prefix *adv_pr; 649*7c478bd9Sstevel@tonic-gate struct in6_addr in6; 650*7c478bd9Sstevel@tonic-gate int prefixlen; 651*7c478bd9Sstevel@tonic-gate char save[sizeof (adv_pr->adv_pr_config)]; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate if (debug & D_CONFIG) 654*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_prefix: argc %d\n", argcount); 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate if (argcount < 2) { 657*7c478bd9Sstevel@tonic-gate conferr("Missing prefix and/or interface name\n"); 658*7c478bd9Sstevel@tonic-gate return; 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate prefix = argvec[0]; 661*7c478bd9Sstevel@tonic-gate ifname = argvec[1]; 662*7c478bd9Sstevel@tonic-gate argvec += 2; 663*7c478bd9Sstevel@tonic-gate argcount -= 2; 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate prefixlen = parse_addrprefix(prefix, &in6); 666*7c478bd9Sstevel@tonic-gate if (prefixlen == -1) { 667*7c478bd9Sstevel@tonic-gate conferr("Bad prefix %s\n", prefix); 668*7c478bd9Sstevel@tonic-gate return; 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate pi = phyint_lookup(ifname); 672*7c478bd9Sstevel@tonic-gate if (pi == NULL) { 673*7c478bd9Sstevel@tonic-gate /* 674*7c478bd9Sstevel@tonic-gate * Create the physical interface structure. 675*7c478bd9Sstevel@tonic-gate * Note, phyint_create() sets the interface 676*7c478bd9Sstevel@tonic-gate * defaults in pi_config. 677*7c478bd9Sstevel@tonic-gate */ 678*7c478bd9Sstevel@tonic-gate pi = phyint_create(ifname); 679*7c478bd9Sstevel@tonic-gate if (pi == NULL) { 680*7c478bd9Sstevel@tonic-gate conferr("Unable to use interface %s\n", ifname); 681*7c478bd9Sstevel@tonic-gate return; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate adv_pr = adv_prefix_lookup(pi, in6, prefixlen); 685*7c478bd9Sstevel@tonic-gate if (adv_pr == NULL) { 686*7c478bd9Sstevel@tonic-gate int i; 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate adv_pr = adv_prefix_create(pi, in6, prefixlen); 689*7c478bd9Sstevel@tonic-gate if (adv_pr == NULL) { 690*7c478bd9Sstevel@tonic-gate conferr("Unable to create prefix %s\n", prefix); 691*7c478bd9Sstevel@tonic-gate return; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate /* 694*7c478bd9Sstevel@tonic-gate * Copy the defaults from the default array. 695*7c478bd9Sstevel@tonic-gate */ 696*7c478bd9Sstevel@tonic-gate for (i = 0; i < I_PREFIXSIZE; i++) { 697*7c478bd9Sstevel@tonic-gate adv_pr->adv_pr_config[i].cf_value = 698*7c478bd9Sstevel@tonic-gate prefixdefaults[i].cf_value; 699*7c478bd9Sstevel@tonic-gate adv_pr->adv_pr_config[i].cf_notdefault = 700*7c478bd9Sstevel@tonic-gate prefixdefaults[i].cf_notdefault; 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate (void) memcpy(save, adv_pr->adv_pr_config, sizeof (save)); 705*7c478bd9Sstevel@tonic-gate while (argcount >= 2) { 706*7c478bd9Sstevel@tonic-gate parse_var_value(CONFIG_PREFIX, list, argvec[0], argvec[1], 707*7c478bd9Sstevel@tonic-gate adv_pr->adv_pr_config); 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate argcount -= 2; 710*7c478bd9Sstevel@tonic-gate argvec += 2; 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate check_var_consistency(adv_pr->adv_pr_config, save, sizeof (save)); 713*7c478bd9Sstevel@tonic-gate if (argcount != 0) 714*7c478bd9Sstevel@tonic-gate logmsg(LOG_ERR, "Trailing text <%s> ignored\n", argvec[0]); 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate /* 718*7c478bd9Sstevel@tonic-gate * Returns true if ok (and *resp updated) and false if failed. 719*7c478bd9Sstevel@tonic-gate */ 720*7c478bd9Sstevel@tonic-gate static boolean_t 721*7c478bd9Sstevel@tonic-gate parse_onoff(char *str, uint_t *resp) 722*7c478bd9Sstevel@tonic-gate { 723*7c478bd9Sstevel@tonic-gate if (strcasecmp(str, "on") == 0) { 724*7c478bd9Sstevel@tonic-gate *resp = 1; 725*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate if (strcasecmp(str, "off") == 0) { 728*7c478bd9Sstevel@tonic-gate *resp = 0; 729*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate if (strcasecmp(str, "true") == 0) { 732*7c478bd9Sstevel@tonic-gate *resp = 1; 733*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate if (strcasecmp(str, "false") == 0) { 736*7c478bd9Sstevel@tonic-gate *resp = 0; 737*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 738*7c478bd9Sstevel@tonic-gate } 739*7c478bd9Sstevel@tonic-gate if (parse_int(str, resp)) { 740*7c478bd9Sstevel@tonic-gate if (*resp == 0 || *resp == 1) 741*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate return (_B_FALSE); 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate /* 747*7c478bd9Sstevel@tonic-gate * Returns true if ok (and *resp updated) and false if failed. 748*7c478bd9Sstevel@tonic-gate */ 749*7c478bd9Sstevel@tonic-gate static boolean_t 750*7c478bd9Sstevel@tonic-gate parse_int(char *str, uint_t *resp) 751*7c478bd9Sstevel@tonic-gate { 752*7c478bd9Sstevel@tonic-gate char *end; 753*7c478bd9Sstevel@tonic-gate int res; 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate res = strtoul(str, &end, 0); 756*7c478bd9Sstevel@tonic-gate if (end == str) 757*7c478bd9Sstevel@tonic-gate return (_B_FALSE); 758*7c478bd9Sstevel@tonic-gate *resp = res; 759*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate /* 763*7c478bd9Sstevel@tonic-gate * Parse something with a unit of millseconds. 764*7c478bd9Sstevel@tonic-gate * Regognizes the suffixes "ms", "s", "m", "h", and "d". 765*7c478bd9Sstevel@tonic-gate * 766*7c478bd9Sstevel@tonic-gate * Returns true if ok (and *resp updated) and false if failed. 767*7c478bd9Sstevel@tonic-gate */ 768*7c478bd9Sstevel@tonic-gate static boolean_t 769*7c478bd9Sstevel@tonic-gate parse_ms(char *str, uint_t *resp) 770*7c478bd9Sstevel@tonic-gate { 771*7c478bd9Sstevel@tonic-gate /* Look at the last and next to last character */ 772*7c478bd9Sstevel@tonic-gate char *cp, *last, *nlast; 773*7c478bd9Sstevel@tonic-gate char str2[BUFSIZ]; /* For local modification */ 774*7c478bd9Sstevel@tonic-gate int multiplier = 1; 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate (void) strncpy(str2, str, sizeof (str2)); 777*7c478bd9Sstevel@tonic-gate str2[sizeof (str2) - 1] = '\0'; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate last = str2; 780*7c478bd9Sstevel@tonic-gate nlast = NULL; 781*7c478bd9Sstevel@tonic-gate for (cp = str2; *cp != '\0'; cp++) { 782*7c478bd9Sstevel@tonic-gate nlast = last; 783*7c478bd9Sstevel@tonic-gate last = cp; 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate if (debug & D_PARSE) { 786*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_ms: last <%c> nlast <%c>\n", 787*7c478bd9Sstevel@tonic-gate (last != NULL ? *last : ' '), 788*7c478bd9Sstevel@tonic-gate (nlast != NULL ? *nlast : ' ')); 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate switch (*last) { 791*7c478bd9Sstevel@tonic-gate case 'd': 792*7c478bd9Sstevel@tonic-gate multiplier *= 24; 793*7c478bd9Sstevel@tonic-gate /* FALLTHRU */ 794*7c478bd9Sstevel@tonic-gate case 'h': 795*7c478bd9Sstevel@tonic-gate multiplier *= 60; 796*7c478bd9Sstevel@tonic-gate /* FALLTHRU */ 797*7c478bd9Sstevel@tonic-gate case 'm': 798*7c478bd9Sstevel@tonic-gate multiplier *= 60; 799*7c478bd9Sstevel@tonic-gate *last = '\0'; 800*7c478bd9Sstevel@tonic-gate multiplier *= 1000; /* Convert to milliseconds */ 801*7c478bd9Sstevel@tonic-gate break; 802*7c478bd9Sstevel@tonic-gate case 's': 803*7c478bd9Sstevel@tonic-gate /* Could be "ms" or "s" */ 804*7c478bd9Sstevel@tonic-gate if (nlast != NULL && *nlast == 'm') { 805*7c478bd9Sstevel@tonic-gate /* "ms" */ 806*7c478bd9Sstevel@tonic-gate *nlast = '\0'; 807*7c478bd9Sstevel@tonic-gate } else { 808*7c478bd9Sstevel@tonic-gate *last = '\0'; 809*7c478bd9Sstevel@tonic-gate multiplier *= 1000; /* Convert to milliseconds */ 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate break; 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate if (!parse_int(str2, resp)) 815*7c478bd9Sstevel@tonic-gate return (_B_FALSE); 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate *resp *= multiplier; 818*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * Parse something with a unit of seconds. 823*7c478bd9Sstevel@tonic-gate * Regognizes the suffixes "s", "m", "h", and "d". 824*7c478bd9Sstevel@tonic-gate * 825*7c478bd9Sstevel@tonic-gate * Returns true if ok (and *resp updated) and false if failed. 826*7c478bd9Sstevel@tonic-gate */ 827*7c478bd9Sstevel@tonic-gate static boolean_t 828*7c478bd9Sstevel@tonic-gate parse_s(char *str, uint_t *resp) 829*7c478bd9Sstevel@tonic-gate { 830*7c478bd9Sstevel@tonic-gate /* Look at the last character */ 831*7c478bd9Sstevel@tonic-gate char *cp, *last; 832*7c478bd9Sstevel@tonic-gate char str2[BUFSIZ]; /* For local modification */ 833*7c478bd9Sstevel@tonic-gate int multiplier = 1; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate (void) strncpy(str2, str, sizeof (str2)); 836*7c478bd9Sstevel@tonic-gate str2[sizeof (str2) - 1] = '\0'; 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate last = str2; 839*7c478bd9Sstevel@tonic-gate for (cp = str2; *cp != '\0'; cp++) { 840*7c478bd9Sstevel@tonic-gate last = cp; 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate if (debug & D_PARSE) { 843*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_s: last <%c>\n", 844*7c478bd9Sstevel@tonic-gate (last != NULL ? *last : ' ')); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate switch (*last) { 847*7c478bd9Sstevel@tonic-gate case 'd': 848*7c478bd9Sstevel@tonic-gate multiplier *= 24; 849*7c478bd9Sstevel@tonic-gate /* FALLTHRU */ 850*7c478bd9Sstevel@tonic-gate case 'h': 851*7c478bd9Sstevel@tonic-gate multiplier *= 60; 852*7c478bd9Sstevel@tonic-gate /* FALLTHRU */ 853*7c478bd9Sstevel@tonic-gate case 'm': 854*7c478bd9Sstevel@tonic-gate multiplier *= 60; 855*7c478bd9Sstevel@tonic-gate /* FALLTHRU */ 856*7c478bd9Sstevel@tonic-gate case 's': 857*7c478bd9Sstevel@tonic-gate *last = '\0'; 858*7c478bd9Sstevel@tonic-gate break; 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate if (!parse_int(str2, resp)) 861*7c478bd9Sstevel@tonic-gate return (_B_FALSE); 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate *resp *= multiplier; 864*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate /* 868*7c478bd9Sstevel@tonic-gate * Return prefixlen (0 to 128) if ok; -1 if failed. 869*7c478bd9Sstevel@tonic-gate */ 870*7c478bd9Sstevel@tonic-gate static int 871*7c478bd9Sstevel@tonic-gate parse_addrprefix(char *strin, struct in6_addr *in6) 872*7c478bd9Sstevel@tonic-gate { 873*7c478bd9Sstevel@tonic-gate char str[BUFSIZ]; /* Local copy for modification */ 874*7c478bd9Sstevel@tonic-gate int prefixlen; 875*7c478bd9Sstevel@tonic-gate char *cp; 876*7c478bd9Sstevel@tonic-gate char *end; 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate (void) strncpy(str, strin, sizeof (str)); 879*7c478bd9Sstevel@tonic-gate str[sizeof (str) - 1] = '\0'; 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate cp = strchr(str, '/'); 882*7c478bd9Sstevel@tonic-gate if (cp == NULL) 883*7c478bd9Sstevel@tonic-gate return (-1); 884*7c478bd9Sstevel@tonic-gate *cp = '\0'; 885*7c478bd9Sstevel@tonic-gate cp++; 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate prefixlen = strtol(cp, &end, 10); 888*7c478bd9Sstevel@tonic-gate if (cp == end) 889*7c478bd9Sstevel@tonic-gate return (-1); 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate if (prefixlen < 0 || prefixlen > IPV6_ABITS) 892*7c478bd9Sstevel@tonic-gate return (-1); 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET6, str, in6) != 1) 895*7c478bd9Sstevel@tonic-gate return (-1); 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate return (prefixlen); 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate /* 901*7c478bd9Sstevel@tonic-gate * Parse an absolute date using a datemsk config file. 902*7c478bd9Sstevel@tonic-gate * Return the difference (measured in seconds) between that date/time and 903*7c478bd9Sstevel@tonic-gate * the current date/time. 904*7c478bd9Sstevel@tonic-gate * If the date has passed return zero. 905*7c478bd9Sstevel@tonic-gate * 906*7c478bd9Sstevel@tonic-gate * Returns true if ok (and *resp updated) and false if failed. 907*7c478bd9Sstevel@tonic-gate * XXX Due to getdate limitations can not exceed year 2038. 908*7c478bd9Sstevel@tonic-gate */ 909*7c478bd9Sstevel@tonic-gate static boolean_t 910*7c478bd9Sstevel@tonic-gate parse_date(char *str, uint_t *resp) 911*7c478bd9Sstevel@tonic-gate { 912*7c478bd9Sstevel@tonic-gate struct tm *tm; 913*7c478bd9Sstevel@tonic-gate struct timeval tvs; 914*7c478bd9Sstevel@tonic-gate time_t time, ntime; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate if (getenv("DATEMSK") == NULL) { 917*7c478bd9Sstevel@tonic-gate (void) putenv("DATEMSK=/etc/inet/datemsk.ndpd"); 918*7c478bd9Sstevel@tonic-gate } 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate if (gettimeofday(&tvs, NULL) < 0) { 921*7c478bd9Sstevel@tonic-gate logperror("gettimeofday"); 922*7c478bd9Sstevel@tonic-gate return (_B_FALSE); 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate time = tvs.tv_sec; 925*7c478bd9Sstevel@tonic-gate tm = getdate(str); 926*7c478bd9Sstevel@tonic-gate if (tm == NULL) { 927*7c478bd9Sstevel@tonic-gate logmsg(LOG_ERR, "Bad date <%s> (error %d)\n", 928*7c478bd9Sstevel@tonic-gate str, getdate_err); 929*7c478bd9Sstevel@tonic-gate return (_B_FALSE); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate ntime = mktime(tm); 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate if (debug & D_PARSE) { 935*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate (void) strftime(buf, sizeof (buf), "%Y-%m-%d %R %Z", tm); 938*7c478bd9Sstevel@tonic-gate logmsg(LOG_DEBUG, "parse_date: <%s>, delta %ld seconds\n", 939*7c478bd9Sstevel@tonic-gate buf, ntime - time); 940*7c478bd9Sstevel@tonic-gate } 941*7c478bd9Sstevel@tonic-gate if (ntime < time) { 942*7c478bd9Sstevel@tonic-gate conferr("Date in the past <%s>\n", str); 943*7c478bd9Sstevel@tonic-gate *resp = 0; 944*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate *resp = (ntime - time); 947*7c478bd9Sstevel@tonic-gate return (_B_TRUE); 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate /* PRINTFLIKE1 */ 951*7c478bd9Sstevel@tonic-gate static void 952*7c478bd9Sstevel@tonic-gate conferr(char *fmt, ...) 953*7c478bd9Sstevel@tonic-gate { 954*7c478bd9Sstevel@tonic-gate char msg[NDPD_LOGMSGSIZE]; 955*7c478bd9Sstevel@tonic-gate size_t slen; 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate va_list ap; 958*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate (void) snprintf(msg, NDPD_LOGMSGSIZE, "%s line %d: ", 961*7c478bd9Sstevel@tonic-gate conf_filename, lineno); 962*7c478bd9Sstevel@tonic-gate slen = strlen(msg); 963*7c478bd9Sstevel@tonic-gate (void) vsnprintf(msg + slen, NDPD_LOGMSGSIZE - slen, fmt, ap); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate logmsg(LOG_ERR, "%s", msg); 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate va_end(ap); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate static FILE * 971*7c478bd9Sstevel@tonic-gate open_conffile(char *filename) 972*7c478bd9Sstevel@tonic-gate { 973*7c478bd9Sstevel@tonic-gate if (strlcpy(conf_filename, filename, MAXPATHLEN) >= MAXPATHLEN) { 974*7c478bd9Sstevel@tonic-gate logmsg(LOG_ERR, "config file pathname is too long\n"); 975*7c478bd9Sstevel@tonic-gate return (NULL); 976*7c478bd9Sstevel@tonic-gate } 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate lineno = 0; 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate return (fopen(filename, "r")); 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate } 983