1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * options.c - handles option processing for PPP. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001 by Sun Microsystems, Inc. 5*7c478bd9Sstevel@tonic-gate * All rights reserved. 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its 8*7c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright 9*7c478bd9Sstevel@tonic-gate * notice appears in all copies. 10*7c478bd9Sstevel@tonic-gate * 11*7c478bd9Sstevel@tonic-gate * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF 12*7c478bd9Sstevel@tonic-gate * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13*7c478bd9Sstevel@tonic-gate * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 14*7c478bd9Sstevel@tonic-gate * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR 15*7c478bd9Sstevel@tonic-gate * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR 16*7c478bd9Sstevel@tonic-gate * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES 17*7c478bd9Sstevel@tonic-gate * 18*7c478bd9Sstevel@tonic-gate * Copyright (c) 1989 Carnegie Mellon University. 19*7c478bd9Sstevel@tonic-gate * All rights reserved. 20*7c478bd9Sstevel@tonic-gate * 21*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 22*7c478bd9Sstevel@tonic-gate * provided that the above copyright notice and this paragraph are 23*7c478bd9Sstevel@tonic-gate * duplicated in all such forms and that any documentation, 24*7c478bd9Sstevel@tonic-gate * advertising materials, and other materials related to such 25*7c478bd9Sstevel@tonic-gate * distribution and use acknowledge that the software was developed 26*7c478bd9Sstevel@tonic-gate * by Carnegie Mellon University. The name of the 27*7c478bd9Sstevel@tonic-gate * University may not be used to endorse or promote products derived 28*7c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 29*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 30*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 31*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 35*7c478bd9Sstevel@tonic-gate #define RCSID "$Id: options.c,v 1.74 2000/04/15 01:27:13 masputra Exp $" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <ctype.h> 38*7c478bd9Sstevel@tonic-gate #include <stdio.h> 39*7c478bd9Sstevel@tonic-gate #include <errno.h> 40*7c478bd9Sstevel@tonic-gate #include <unistd.h> 41*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 42*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 43*7c478bd9Sstevel@tonic-gate #include <syslog.h> 44*7c478bd9Sstevel@tonic-gate #include <string.h> 45*7c478bd9Sstevel@tonic-gate #include <netdb.h> 46*7c478bd9Sstevel@tonic-gate #include <pwd.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 49*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 50*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 51*7c478bd9Sstevel@tonic-gate #ifdef PLUGIN 52*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 53*7c478bd9Sstevel@tonic-gate #endif /* PLUGIN */ 54*7c478bd9Sstevel@tonic-gate #ifdef PPP_FILTER 55*7c478bd9Sstevel@tonic-gate #include <pcap.h> 56*7c478bd9Sstevel@tonic-gate #include <pcap-int.h> /* XXX: To get struct pcap */ 57*7c478bd9Sstevel@tonic-gate #endif /* PPP_FILTER */ 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate #include "pppd.h" 60*7c478bd9Sstevel@tonic-gate #include "pathnames.h" 61*7c478bd9Sstevel@tonic-gate #include "patchlevel.h" 62*7c478bd9Sstevel@tonic-gate #include "fsm.h" 63*7c478bd9Sstevel@tonic-gate #include "lcp.h" 64*7c478bd9Sstevel@tonic-gate #include "ipcp.h" 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #if defined(ultrix) || defined(NeXT) 67*7c478bd9Sstevel@tonic-gate char *strdup __P((char *)); 68*7c478bd9Sstevel@tonic-gate #endif 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(_lint) 71*7c478bd9Sstevel@tonic-gate static const char rcsid[] = RCSID; 72*7c478bd9Sstevel@tonic-gate #endif 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /* 75*7c478bd9Sstevel@tonic-gate * Option variables and default values. 76*7c478bd9Sstevel@tonic-gate */ 77*7c478bd9Sstevel@tonic-gate #ifdef PPP_FILTER 78*7c478bd9Sstevel@tonic-gate int dflag = 0; /* Tell libpcap we want debugging */ 79*7c478bd9Sstevel@tonic-gate #endif /* PPP_FILTER */ 80*7c478bd9Sstevel@tonic-gate int debug = 0; /* Debug flag */ 81*7c478bd9Sstevel@tonic-gate int kdebugflag = 0; /* Tell kernel to print debug messages */ 82*7c478bd9Sstevel@tonic-gate int default_device = 1; /* Using /dev/tty or equivalent */ 83*7c478bd9Sstevel@tonic-gate char devnam[MAXPATHLEN]; /* Device name */ 84*7c478bd9Sstevel@tonic-gate int crtscts = 0; /* Use hardware flow control */ 85*7c478bd9Sstevel@tonic-gate bool modem = 1; /* Use modem control lines */ 86*7c478bd9Sstevel@tonic-gate int inspeed = 0; /* Input/Output speed requested */ 87*7c478bd9Sstevel@tonic-gate u_int32_t netmask = 0; /* IP netmask to set on interface */ 88*7c478bd9Sstevel@tonic-gate bool lockflag = 0; /* Create lock file to lock the serial dev */ 89*7c478bd9Sstevel@tonic-gate bool nodetach = 0; /* Don't detach from controlling tty */ 90*7c478bd9Sstevel@tonic-gate bool updetach = 0; /* Detach once link is up */ 91*7c478bd9Sstevel@tonic-gate char *initializer = NULL; /* Script to initialize physical link */ 92*7c478bd9Sstevel@tonic-gate char *connect_script = NULL; /* Script to establish physical link */ 93*7c478bd9Sstevel@tonic-gate char *disconnect_script = NULL; /* Script to disestablish physical link */ 94*7c478bd9Sstevel@tonic-gate char *welcomer = NULL; /* Script to run after phys link estab. */ 95*7c478bd9Sstevel@tonic-gate char *ptycommand = NULL; /* Command to run on other side of pty */ 96*7c478bd9Sstevel@tonic-gate int maxconnect = 0; /* Maximum connect time */ 97*7c478bd9Sstevel@tonic-gate char user[MAXNAMELEN]; /* Username for PAP */ 98*7c478bd9Sstevel@tonic-gate char passwd[MAXSECRETLEN]; /* Password for PAP */ 99*7c478bd9Sstevel@tonic-gate bool persist = 0; /* Reopen link after it goes down */ 100*7c478bd9Sstevel@tonic-gate char our_name[MAXNAMELEN]; /* Our name for authentication purposes */ 101*7c478bd9Sstevel@tonic-gate bool demand = 0; /* do dial-on-demand */ 102*7c478bd9Sstevel@tonic-gate char *ipparam = NULL; /* Extra parameter for ip up/down scripts */ 103*7c478bd9Sstevel@tonic-gate int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ 104*7c478bd9Sstevel@tonic-gate int holdoff = 30; /* # seconds to pause before reconnecting */ 105*7c478bd9Sstevel@tonic-gate bool holdoff_specified; /* true if a holdoff value has been given */ 106*7c478bd9Sstevel@tonic-gate bool notty = 0; /* Stdin/out is not a tty */ 107*7c478bd9Sstevel@tonic-gate char *pty_socket = NULL; /* Socket to connect to pty */ 108*7c478bd9Sstevel@tonic-gate char *record_file = NULL; /* File to record chars sent/received */ 109*7c478bd9Sstevel@tonic-gate int using_pty = 0; 110*7c478bd9Sstevel@tonic-gate bool sync_serial = 0; /* Device is synchronous serial device */ 111*7c478bd9Sstevel@tonic-gate int log_to_fd = 1; /* send log messages to this fd too */ 112*7c478bd9Sstevel@tonic-gate int maxfail = 10; /* max # of unsuccessful connection attempts */ 113*7c478bd9Sstevel@tonic-gate char linkname[MAXPATHLEN]; /* logical name for link */ 114*7c478bd9Sstevel@tonic-gate bool tune_kernel; /* may alter kernel settings */ 115*7c478bd9Sstevel@tonic-gate int connect_delay = 1000; /* wait this many ms after connect script */ 116*7c478bd9Sstevel@tonic-gate int max_data_rate; /* max bytes/sec through charshunt */ 117*7c478bd9Sstevel@tonic-gate int req_unit = -1; /* requested interface unit */ 118*7c478bd9Sstevel@tonic-gate bool multilink = 0; /* Enable multilink operation */ 119*7c478bd9Sstevel@tonic-gate char *bundle_name = NULL; /* bundle name for multilink */ 120*7c478bd9Sstevel@tonic-gate bool direct_tty = 0; /* use standard input directly; not a tty */ 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* Maximum depth of include files; prevents looping. */ 123*7c478bd9Sstevel@tonic-gate #define MAXFILENESTING 10 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate struct option_info initializer_info; 126*7c478bd9Sstevel@tonic-gate struct option_info connect_script_info; 127*7c478bd9Sstevel@tonic-gate struct option_info disconnect_script_info; 128*7c478bd9Sstevel@tonic-gate struct option_info welcomer_info; 129*7c478bd9Sstevel@tonic-gate struct option_info devnam_info; 130*7c478bd9Sstevel@tonic-gate struct option_info ptycommand_info; 131*7c478bd9Sstevel@tonic-gate struct option_info ipsrc_info; 132*7c478bd9Sstevel@tonic-gate struct option_info ipdst_info; 133*7c478bd9Sstevel@tonic-gate struct option_info speed_info; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate #ifdef PPP_FILTER 136*7c478bd9Sstevel@tonic-gate struct bpf_program pass_filter;/* Filter program for packets to pass */ 137*7c478bd9Sstevel@tonic-gate struct bpf_program active_filter; /* Filter program for link-active pkts */ 138*7c478bd9Sstevel@tonic-gate pcap_t pc; /* Fake struct pcap so we can compile expr */ 139*7c478bd9Sstevel@tonic-gate #endif /* PPP_FILTER */ 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate char *current_option; /* the name of the option being parsed */ 142*7c478bd9Sstevel@tonic-gate bool privileged_option; /* set iff the current option came from root */ 143*7c478bd9Sstevel@tonic-gate char *option_source = NULL; /* string saying where the option came from */ 144*7c478bd9Sstevel@tonic-gate int option_line = 0; /* line number in file */ 145*7c478bd9Sstevel@tonic-gate bool log_to_file; /* log_to_fd is a file opened by us */ 146*7c478bd9Sstevel@tonic-gate bool log_to_specific_fd; /* log_to_fd was specified by user option */ 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * Prototypes. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate static int setdevname __P((char *)); 152*7c478bd9Sstevel@tonic-gate static int setipaddr __P((char *)); 153*7c478bd9Sstevel@tonic-gate static int setspeed __P((char *)); 154*7c478bd9Sstevel@tonic-gate static int noopt __P((char **, option_t *)); 155*7c478bd9Sstevel@tonic-gate static int setdomain __P((char **, option_t *)); 156*7c478bd9Sstevel@tonic-gate static int setnetmask __P((char **, option_t *)); 157*7c478bd9Sstevel@tonic-gate static int setxonxoff __P((char **, option_t *)); 158*7c478bd9Sstevel@tonic-gate static int readfile __P((char **, option_t *)); 159*7c478bd9Sstevel@tonic-gate static int callfile __P((char **, option_t *)); 160*7c478bd9Sstevel@tonic-gate static int showversion __P((char **, option_t *)); 161*7c478bd9Sstevel@tonic-gate static int showhelp __P((char **, option_t *)); 162*7c478bd9Sstevel@tonic-gate static int showalloptions __P((char **, option_t *)); 163*7c478bd9Sstevel@tonic-gate static void usage __P((void)); 164*7c478bd9Sstevel@tonic-gate static int setlogfile __P((char **, option_t *)); 165*7c478bd9Sstevel@tonic-gate #ifdef PLUGIN 166*7c478bd9Sstevel@tonic-gate static int loadplugin __P((char **, option_t *)); 167*7c478bd9Sstevel@tonic-gate #endif 168*7c478bd9Sstevel@tonic-gate #ifdef PPP_FILTER 169*7c478bd9Sstevel@tonic-gate static int setpassfilter __P((char **, option_t *)); 170*7c478bd9Sstevel@tonic-gate static int setactivefilter __P((char **, option_t *)); 171*7c478bd9Sstevel@tonic-gate #endif /* PPP_FILTER */ 172*7c478bd9Sstevel@tonic-gate static option_t *find_option __P((char *name)); 173*7c478bd9Sstevel@tonic-gate static int process_option __P((option_t *opt, char **argv, int sline)); 174*7c478bd9Sstevel@tonic-gate static int n_arguments __P((option_t *opt)); 175*7c478bd9Sstevel@tonic-gate static int number_option __P((char *str, u_int32_t *valp, int base)); 176*7c478bd9Sstevel@tonic-gate static u_int32_t opt_hash __P((const void *key)); 177*7c478bd9Sstevel@tonic-gate static int opt_compare __P((const void *p1, const void *p2)); 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate typedef struct _opt_t { 180*7c478bd9Sstevel@tonic-gate option_t *p; 181*7c478bd9Sstevel@tonic-gate } opt_t; 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate typedef struct _hashentry_t { 184*7c478bd9Sstevel@tonic-gate struct _hashentry_t *next; 185*7c478bd9Sstevel@tonic-gate opt_t opt; 186*7c478bd9Sstevel@tonic-gate } hashentry_t; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* 189*7c478bd9Sstevel@tonic-gate * A prime number describing the size of hash table. 190*7c478bd9Sstevel@tonic-gate */ 191*7c478bd9Sstevel@tonic-gate #define OPTHASH_TBLSIZE 101 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate * Chained hash table containing pointers to available options. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate static hashentry_t *hash_tbl[OPTHASH_TBLSIZE] = { NULL }; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * Total number of entries in the hash table. 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate int hash_tblcnt = 0; 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate /* 204*7c478bd9Sstevel@tonic-gate * Valid arguments. 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate option_t general_options[] = { 207*7c478bd9Sstevel@tonic-gate { "debug", o_int, &debug, 208*7c478bd9Sstevel@tonic-gate "Increase debugging level", OPT_INC|OPT_NOARG|1 }, 209*7c478bd9Sstevel@tonic-gate { "-d", o_int, &debug, 210*7c478bd9Sstevel@tonic-gate "Increase debugging level", OPT_INC|OPT_NOARG|1 }, 211*7c478bd9Sstevel@tonic-gate { "kdebug", o_int, &kdebugflag, 212*7c478bd9Sstevel@tonic-gate "Set kernel driver debug level" }, 213*7c478bd9Sstevel@tonic-gate { "nodetach", o_bool, &nodetach, 214*7c478bd9Sstevel@tonic-gate "Don't detach from controlling tty", 1 }, 215*7c478bd9Sstevel@tonic-gate { "-detach", o_bool, &nodetach, 216*7c478bd9Sstevel@tonic-gate "Don't detach from controlling tty", 1 }, 217*7c478bd9Sstevel@tonic-gate { "updetach", o_bool, &updetach, 218*7c478bd9Sstevel@tonic-gate "Detach from controlling tty once link is up", 1 }, 219*7c478bd9Sstevel@tonic-gate { "holdoff", o_int, &holdoff, 220*7c478bd9Sstevel@tonic-gate "Set time in seconds before retrying connection" }, 221*7c478bd9Sstevel@tonic-gate { "idle", o_int, &idle_time_limit, 222*7c478bd9Sstevel@tonic-gate "Set time in seconds before disconnecting idle link" }, 223*7c478bd9Sstevel@tonic-gate { "lock", o_bool, &lockflag, 224*7c478bd9Sstevel@tonic-gate "Lock serial device with UUCP-style lock file", 1 }, 225*7c478bd9Sstevel@tonic-gate { "-all", o_special_noarg, (void *)noopt, 226*7c478bd9Sstevel@tonic-gate "Don't request/allow any LCP or IPCP options (useless)" }, 227*7c478bd9Sstevel@tonic-gate { "init", o_string, &initializer, 228*7c478bd9Sstevel@tonic-gate "A program to initialize the device", 229*7c478bd9Sstevel@tonic-gate OPT_A2INFO | OPT_PRIVFIX, &initializer_info }, 230*7c478bd9Sstevel@tonic-gate { "connect", o_string, &connect_script, 231*7c478bd9Sstevel@tonic-gate "A program to set up a connection", 232*7c478bd9Sstevel@tonic-gate OPT_A2INFO | OPT_PRIVFIX, &connect_script_info }, 233*7c478bd9Sstevel@tonic-gate { "disconnect", o_string, &disconnect_script, 234*7c478bd9Sstevel@tonic-gate "Program to disconnect serial device", 235*7c478bd9Sstevel@tonic-gate OPT_A2INFO | OPT_PRIVFIX, &disconnect_script_info }, 236*7c478bd9Sstevel@tonic-gate { "welcome", o_string, &welcomer, 237*7c478bd9Sstevel@tonic-gate "Script to welcome client", 238*7c478bd9Sstevel@tonic-gate OPT_A2INFO | OPT_PRIVFIX, &welcomer_info }, 239*7c478bd9Sstevel@tonic-gate { "pty", o_string, &ptycommand, 240*7c478bd9Sstevel@tonic-gate "Script to run on pseudo-tty master side", 241*7c478bd9Sstevel@tonic-gate OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info }, 242*7c478bd9Sstevel@tonic-gate { "notty", o_bool, ¬ty, 243*7c478bd9Sstevel@tonic-gate "Input/output is not a tty", OPT_DEVNAM | 1 }, 244*7c478bd9Sstevel@tonic-gate { "directtty", o_bool, &direct_tty, 245*7c478bd9Sstevel@tonic-gate "Use standard input as tty without checking", OPT_DEVNAM | 1 }, 246*7c478bd9Sstevel@tonic-gate { "socket", o_string, &pty_socket, 247*7c478bd9Sstevel@tonic-gate "Send and receive over socket, arg is host:port", OPT_DEVNAM }, 248*7c478bd9Sstevel@tonic-gate { "record", o_string, &record_file, 249*7c478bd9Sstevel@tonic-gate "Record characters sent/received to file" }, 250*7c478bd9Sstevel@tonic-gate { "maxconnect", o_int, &maxconnect, 251*7c478bd9Sstevel@tonic-gate "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF }, 252*7c478bd9Sstevel@tonic-gate { "crtscts", o_int, &crtscts, 253*7c478bd9Sstevel@tonic-gate "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) }, 254*7c478bd9Sstevel@tonic-gate { "nocrtscts", o_int, &crtscts, 255*7c478bd9Sstevel@tonic-gate "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, 256*7c478bd9Sstevel@tonic-gate { "-crtscts", o_int, &crtscts, 257*7c478bd9Sstevel@tonic-gate "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, 258*7c478bd9Sstevel@tonic-gate { "cdtrcts", o_int, &crtscts, 259*7c478bd9Sstevel@tonic-gate "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) }, 260*7c478bd9Sstevel@tonic-gate { "nocdtrcts", o_int, &crtscts, 261*7c478bd9Sstevel@tonic-gate "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, 262*7c478bd9Sstevel@tonic-gate { "xonxoff", o_special_noarg, (void *)setxonxoff, 263*7c478bd9Sstevel@tonic-gate "Set software (XON/XOFF) flow control" }, 264*7c478bd9Sstevel@tonic-gate { "domain", o_special, (void *)setdomain, 265*7c478bd9Sstevel@tonic-gate "Add given domain name to hostname" }, 266*7c478bd9Sstevel@tonic-gate { "netmask", o_special, (void *)setnetmask, 267*7c478bd9Sstevel@tonic-gate "set netmask" }, 268*7c478bd9Sstevel@tonic-gate { "modem", o_bool, &modem, 269*7c478bd9Sstevel@tonic-gate "Use modem control lines", 1 }, 270*7c478bd9Sstevel@tonic-gate { "local", o_bool, &modem, 271*7c478bd9Sstevel@tonic-gate "Don't use modem control lines" }, 272*7c478bd9Sstevel@tonic-gate { "file", o_special, (void *)readfile, 273*7c478bd9Sstevel@tonic-gate "Take options from a file", OPT_PREPASS }, 274*7c478bd9Sstevel@tonic-gate { "call", o_special, (void *)callfile, 275*7c478bd9Sstevel@tonic-gate "Take options from a privileged file", OPT_PREPASS }, 276*7c478bd9Sstevel@tonic-gate { "persist", o_bool, &persist, 277*7c478bd9Sstevel@tonic-gate "Keep on reopening connection after close", 1 }, 278*7c478bd9Sstevel@tonic-gate { "nopersist", o_bool, &persist, 279*7c478bd9Sstevel@tonic-gate "Turn off persist option" }, 280*7c478bd9Sstevel@tonic-gate { "demand", o_bool, &demand, 281*7c478bd9Sstevel@tonic-gate "Dial on demand", OPT_INITONLY | 1, &persist }, 282*7c478bd9Sstevel@tonic-gate { "--version", o_special_noarg, (void *)showversion, 283*7c478bd9Sstevel@tonic-gate "Show version number" }, 284*7c478bd9Sstevel@tonic-gate { "--help", o_special_noarg, (void *)showhelp, 285*7c478bd9Sstevel@tonic-gate "Show brief listing of options" }, 286*7c478bd9Sstevel@tonic-gate { "-h", o_special_noarg, (void *)showhelp, 287*7c478bd9Sstevel@tonic-gate "Show brief listing of options" }, 288*7c478bd9Sstevel@tonic-gate { "options", o_special_noarg, (void *)showalloptions, 289*7c478bd9Sstevel@tonic-gate "Show full listing of options" }, 290*7c478bd9Sstevel@tonic-gate { "sync", o_bool, &sync_serial, 291*7c478bd9Sstevel@tonic-gate "Use synchronous HDLC serial encoding", 1 }, 292*7c478bd9Sstevel@tonic-gate { "logfd", o_int, &log_to_fd, 293*7c478bd9Sstevel@tonic-gate "Send log messages to this file descriptor", 294*7c478bd9Sstevel@tonic-gate 0, &log_to_specific_fd }, 295*7c478bd9Sstevel@tonic-gate { "logfile", o_special, (void *)setlogfile, 296*7c478bd9Sstevel@tonic-gate "Append log messages to this file" }, 297*7c478bd9Sstevel@tonic-gate { "nolog", o_int, &log_to_fd, 298*7c478bd9Sstevel@tonic-gate "Don't send log messages to any file", 299*7c478bd9Sstevel@tonic-gate OPT_NOARG | OPT_VAL(-1) }, 300*7c478bd9Sstevel@tonic-gate { "nologfd", o_int, &log_to_fd, 301*7c478bd9Sstevel@tonic-gate "Don't send log messages to any file descriptor", 302*7c478bd9Sstevel@tonic-gate OPT_NOARG | OPT_VAL(-1) }, 303*7c478bd9Sstevel@tonic-gate { "linkname", o_string, linkname, 304*7c478bd9Sstevel@tonic-gate "Set logical name for link", 305*7c478bd9Sstevel@tonic-gate OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, 306*7c478bd9Sstevel@tonic-gate { "maxfail", o_int, &maxfail, 307*7c478bd9Sstevel@tonic-gate "Number of unsuccessful connection attempts to allow" }, 308*7c478bd9Sstevel@tonic-gate { "ktune", o_bool, &tune_kernel, 309*7c478bd9Sstevel@tonic-gate "Alter kernel settings as necessary", 1 }, 310*7c478bd9Sstevel@tonic-gate { "noktune", o_bool, &tune_kernel, 311*7c478bd9Sstevel@tonic-gate "Don't alter kernel settings", 0 }, 312*7c478bd9Sstevel@tonic-gate { "connect-delay", o_int, &connect_delay, 313*7c478bd9Sstevel@tonic-gate "Maximum wait time (msec) after connect script finishes" }, 314*7c478bd9Sstevel@tonic-gate { "datarate", o_int, &max_data_rate, 315*7c478bd9Sstevel@tonic-gate "Max data rate in bytes/sec for pty, notty, or record" }, 316*7c478bd9Sstevel@tonic-gate { "unit", o_int, &req_unit, 317*7c478bd9Sstevel@tonic-gate "PPP interface unit number to use if possible", OPT_LLIMIT, 0, 0 }, 318*7c478bd9Sstevel@tonic-gate #ifdef HAVE_MULTILINK 319*7c478bd9Sstevel@tonic-gate { "multilink", o_bool, &multilink, 320*7c478bd9Sstevel@tonic-gate "Enable multilink operation", 1 }, 321*7c478bd9Sstevel@tonic-gate { "nomultilink", o_bool, &multilink, 322*7c478bd9Sstevel@tonic-gate "Disable multilink operation", 0 }, 323*7c478bd9Sstevel@tonic-gate { "mp", o_bool, &multilink, 324*7c478bd9Sstevel@tonic-gate "Enable multilink operation", 1 }, 325*7c478bd9Sstevel@tonic-gate { "nomp", o_bool, &multilink, 326*7c478bd9Sstevel@tonic-gate "Disable multilink operation", 0 }, 327*7c478bd9Sstevel@tonic-gate { "bundle", o_string, &bundle_name, 328*7c478bd9Sstevel@tonic-gate "Bundle name for multilink" }, 329*7c478bd9Sstevel@tonic-gate #endif /* HAVE_MULTILINK */ 330*7c478bd9Sstevel@tonic-gate #ifdef PLUGIN 331*7c478bd9Sstevel@tonic-gate { "plugin", o_special, (void *)loadplugin, 332*7c478bd9Sstevel@tonic-gate "Load a plug-in module into pppd", OPT_PRIV }, 333*7c478bd9Sstevel@tonic-gate #endif /* PLUGIN */ 334*7c478bd9Sstevel@tonic-gate #ifdef PPP_FILTER 335*7c478bd9Sstevel@tonic-gate { "pdebug", o_int, &dflag, 336*7c478bd9Sstevel@tonic-gate "libpcap debugging" }, 337*7c478bd9Sstevel@tonic-gate { "pass-filter", o_special, setpassfilter, 338*7c478bd9Sstevel@tonic-gate "set filter for packets to pass" }, 339*7c478bd9Sstevel@tonic-gate { "active-filter", o_special, setactivefilter, 340*7c478bd9Sstevel@tonic-gate "set filter for active pkts" }, 341*7c478bd9Sstevel@tonic-gate #endif /* PPP_FILTER */ 342*7c478bd9Sstevel@tonic-gate { NULL } 343*7c478bd9Sstevel@tonic-gate }; 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate /* 346*7c478bd9Sstevel@tonic-gate * This string gets printed out when "options" is given on the command 347*7c478bd9Sstevel@tonic-gate * line. Following this string, all of the available options and 348*7c478bd9Sstevel@tonic-gate * their descriptions are printed out as well. Certain options which 349*7c478bd9Sstevel@tonic-gate * are not available as part of the option_t structure are placed in 350*7c478bd9Sstevel@tonic-gate * the "dummy" option structure. 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate static const char pre_allopt_string[] = "\ 353*7c478bd9Sstevel@tonic-gate pppd version %s.%d%s\n\ 354*7c478bd9Sstevel@tonic-gate Usage: %s [ options ], where options are:\n\n\ 355*7c478bd9Sstevel@tonic-gate "; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* Do not call add_options() on this structure */ 358*7c478bd9Sstevel@tonic-gate static option_t dummy_options[] = { 359*7c478bd9Sstevel@tonic-gate { "<device>", o_special_noarg, NULL, 360*7c478bd9Sstevel@tonic-gate "Communicate over the named device" }, 361*7c478bd9Sstevel@tonic-gate { "<speed>", o_special_noarg, NULL, 362*7c478bd9Sstevel@tonic-gate "Set the baud rate to <speed>" }, 363*7c478bd9Sstevel@tonic-gate { "[<loc>]:[<rem>]", o_special_noarg, NULL, 364*7c478bd9Sstevel@tonic-gate "Set the local and/or remote interface IP addresses" }, 365*7c478bd9Sstevel@tonic-gate { NULL } 366*7c478bd9Sstevel@tonic-gate }; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate static const char post_allopt_string[] = "\ 369*7c478bd9Sstevel@tonic-gate \n\ 370*7c478bd9Sstevel@tonic-gate Notes:\ 371*7c478bd9Sstevel@tonic-gate \t<n>\tinteger type argument\n\ 372*7c478bd9Sstevel@tonic-gate \t<s>\tstring type argument\n\ 373*7c478bd9Sstevel@tonic-gate \t<r>\tspecial type argument\n\ 374*7c478bd9Sstevel@tonic-gate \t(!)\tprivileged option available only when pppd is executed by root\n\ 375*7c478bd9Sstevel@tonic-gate \t\tor when found in the privileged option files (/etc/ppp/options,\n\ 376*7c478bd9Sstevel@tonic-gate \t\t/etc/ppp/options.ttyname, /etc/ppp/peers/name, or following\n\ 377*7c478bd9Sstevel@tonic-gate \t\t\"--\" in /etc/ppp/pap-secrets or /etc/ppp/chap-secrets).\n\ 378*7c478bd9Sstevel@tonic-gate \t(#)\tdisabled option\n\ 379*7c478bd9Sstevel@tonic-gate \n\ 380*7c478bd9Sstevel@tonic-gate Please see the pppd man page for details.\n"; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * parse_args - parse a string of arguments from the command line. If prepass 384*7c478bd9Sstevel@tonic-gate * is true, we are scanning for the device name and only processing a few 385*7c478bd9Sstevel@tonic-gate * options, so error messages are suppressed. Returns 1 upon successful 386*7c478bd9Sstevel@tonic-gate * processing of options, and 0 otherwise. 387*7c478bd9Sstevel@tonic-gate */ 388*7c478bd9Sstevel@tonic-gate int 389*7c478bd9Sstevel@tonic-gate parse_args(argc, argv) 390*7c478bd9Sstevel@tonic-gate int argc; 391*7c478bd9Sstevel@tonic-gate char **argv; 392*7c478bd9Sstevel@tonic-gate { 393*7c478bd9Sstevel@tonic-gate char *arg; 394*7c478bd9Sstevel@tonic-gate option_t *opt; 395*7c478bd9Sstevel@tonic-gate int ret; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate privileged_option = privileged; 398*7c478bd9Sstevel@tonic-gate option_source = "command line"; 399*7c478bd9Sstevel@tonic-gate option_line = 0; 400*7c478bd9Sstevel@tonic-gate while (argc > 0) { 401*7c478bd9Sstevel@tonic-gate arg = *argv++; 402*7c478bd9Sstevel@tonic-gate --argc; 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate /* 405*7c478bd9Sstevel@tonic-gate * First check to see if it's a known option name. If so, parse the 406*7c478bd9Sstevel@tonic-gate * argument(s) and set the option. 407*7c478bd9Sstevel@tonic-gate */ 408*7c478bd9Sstevel@tonic-gate opt = find_option(arg); 409*7c478bd9Sstevel@tonic-gate if (opt != NULL) { 410*7c478bd9Sstevel@tonic-gate int n = n_arguments(opt); 411*7c478bd9Sstevel@tonic-gate if (argc < n) { 412*7c478bd9Sstevel@tonic-gate option_error("too few parameters for option '%s'", arg); 413*7c478bd9Sstevel@tonic-gate return (0); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate current_option = arg; 416*7c478bd9Sstevel@tonic-gate if (!process_option(opt, argv, 0)) 417*7c478bd9Sstevel@tonic-gate return (0); 418*7c478bd9Sstevel@tonic-gate argc -= n; 419*7c478bd9Sstevel@tonic-gate argv += n; 420*7c478bd9Sstevel@tonic-gate continue; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * Maybe a tty name, speed or IP address ? 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate if (((ret = setdevname(arg)) == 0) && 427*7c478bd9Sstevel@tonic-gate ((ret = setspeed(arg)) == 0) && 428*7c478bd9Sstevel@tonic-gate ((ret = setipaddr(arg)) == 0) && !prepass) { 429*7c478bd9Sstevel@tonic-gate option_error("unrecognized option '%s'", arg); 430*7c478bd9Sstevel@tonic-gate usage(); 431*7c478bd9Sstevel@tonic-gate return (0); 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate if (ret < 0) /* error */ 434*7c478bd9Sstevel@tonic-gate return (0); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate return (1); 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate /* 440*7c478bd9Sstevel@tonic-gate * options_from_file - read a string of options from a file, and 441*7c478bd9Sstevel@tonic-gate * interpret them. Returns 1 upon successful processing of options, 442*7c478bd9Sstevel@tonic-gate * and 0 otherwise. 443*7c478bd9Sstevel@tonic-gate */ 444*7c478bd9Sstevel@tonic-gate int 445*7c478bd9Sstevel@tonic-gate options_from_file 446*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 447*7c478bd9Sstevel@tonic-gate (char *filename, bool must_exist, bool check_prot, bool priv) 448*7c478bd9Sstevel@tonic-gate #else 449*7c478bd9Sstevel@tonic-gate (filename, must_exist, check_prot, priv) 450*7c478bd9Sstevel@tonic-gate char *filename; 451*7c478bd9Sstevel@tonic-gate bool must_exist; 452*7c478bd9Sstevel@tonic-gate bool check_prot; 453*7c478bd9Sstevel@tonic-gate bool priv; 454*7c478bd9Sstevel@tonic-gate #endif 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate FILE *f; 457*7c478bd9Sstevel@tonic-gate int i, newline, ret, err; 458*7c478bd9Sstevel@tonic-gate option_t *opt; 459*7c478bd9Sstevel@tonic-gate bool oldpriv; 460*7c478bd9Sstevel@tonic-gate int oldline, sline; 461*7c478bd9Sstevel@tonic-gate char *oldsource; 462*7c478bd9Sstevel@tonic-gate char *argv[MAXARGS]; 463*7c478bd9Sstevel@tonic-gate char args[MAXARGS][MAXWORDLEN]; 464*7c478bd9Sstevel@tonic-gate char cmd[MAXWORDLEN]; 465*7c478bd9Sstevel@tonic-gate static bool firsterr = 1; 466*7c478bd9Sstevel@tonic-gate static int nestlevel = 0; 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate if (nestlevel >= MAXFILENESTING) { 469*7c478bd9Sstevel@tonic-gate option_error("file nesting too deep"); 470*7c478bd9Sstevel@tonic-gate return (0); 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate if (check_prot) 473*7c478bd9Sstevel@tonic-gate (void) seteuid(getuid()); 474*7c478bd9Sstevel@tonic-gate errno = 0; 475*7c478bd9Sstevel@tonic-gate f = fopen(filename, "r"); 476*7c478bd9Sstevel@tonic-gate err = errno; 477*7c478bd9Sstevel@tonic-gate if (check_prot) 478*7c478bd9Sstevel@tonic-gate (void) seteuid(0); 479*7c478bd9Sstevel@tonic-gate if (f == NULL) { 480*7c478bd9Sstevel@tonic-gate if (!must_exist && err == ENOENT) 481*7c478bd9Sstevel@tonic-gate return (1); 482*7c478bd9Sstevel@tonic-gate errno = err; 483*7c478bd9Sstevel@tonic-gate option_error("Can't open options file %s: %m", filename); 484*7c478bd9Sstevel@tonic-gate return (0); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate nestlevel++; 488*7c478bd9Sstevel@tonic-gate oldpriv = privileged_option; 489*7c478bd9Sstevel@tonic-gate privileged_option = priv; 490*7c478bd9Sstevel@tonic-gate oldsource = option_source; 491*7c478bd9Sstevel@tonic-gate /* 492*7c478bd9Sstevel@tonic-gate * strdup() is used here because the pointer might refer to the 493*7c478bd9Sstevel@tonic-gate * caller's automatic (stack) storage, and the option_info array 494*7c478bd9Sstevel@tonic-gate * records the source file name. 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate option_source = strdup(filename); 497*7c478bd9Sstevel@tonic-gate oldline = option_line; 498*7c478bd9Sstevel@tonic-gate option_line = 1; 499*7c478bd9Sstevel@tonic-gate if (option_source == NULL) 500*7c478bd9Sstevel@tonic-gate option_source = "file"; 501*7c478bd9Sstevel@tonic-gate ret = 0; 502*7c478bd9Sstevel@tonic-gate while (getword(f, cmd, &newline, filename)) { 503*7c478bd9Sstevel@tonic-gate sline = option_line; 504*7c478bd9Sstevel@tonic-gate /* 505*7c478bd9Sstevel@tonic-gate * First see if it's a command. 506*7c478bd9Sstevel@tonic-gate */ 507*7c478bd9Sstevel@tonic-gate opt = find_option(cmd); 508*7c478bd9Sstevel@tonic-gate if (opt != NULL) { 509*7c478bd9Sstevel@tonic-gate int n = n_arguments(opt); 510*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; ++i) { 511*7c478bd9Sstevel@tonic-gate if (!getword(f, args[i], &newline, filename)) { 512*7c478bd9Sstevel@tonic-gate option_error("too few parameters for option '%s'", cmd); 513*7c478bd9Sstevel@tonic-gate goto err; 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate argv[i] = args[i]; 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate current_option = cmd; 518*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) { 519*7c478bd9Sstevel@tonic-gate option_error("the '%s' option may not be used here", cmd); 520*7c478bd9Sstevel@tonic-gate goto err; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate if (!process_option(opt, argv, sline)) 523*7c478bd9Sstevel@tonic-gate goto err; 524*7c478bd9Sstevel@tonic-gate continue; 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate /* 528*7c478bd9Sstevel@tonic-gate * Maybe a tty name, speed or IP address ? 529*7c478bd9Sstevel@tonic-gate */ 530*7c478bd9Sstevel@tonic-gate if (((i = setdevname(cmd)) == 0) && 531*7c478bd9Sstevel@tonic-gate ((i = setspeed(cmd)) == 0) && 532*7c478bd9Sstevel@tonic-gate ((i = setipaddr(cmd)) == 0)) { 533*7c478bd9Sstevel@tonic-gate option_error("unrecognized option '%s'", cmd); 534*7c478bd9Sstevel@tonic-gate goto err; 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate if (i < 0) /* error */ 537*7c478bd9Sstevel@tonic-gate goto err; 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate ret = 1; 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate err: 542*7c478bd9Sstevel@tonic-gate (void) fclose(f); 543*7c478bd9Sstevel@tonic-gate /* We assume here that we abort all processing on the first error. */ 544*7c478bd9Sstevel@tonic-gate if (firsterr) 545*7c478bd9Sstevel@tonic-gate firsterr = 0; 546*7c478bd9Sstevel@tonic-gate else if (!prepass && !ret) 547*7c478bd9Sstevel@tonic-gate option_error("error in included file"); 548*7c478bd9Sstevel@tonic-gate /* 549*7c478bd9Sstevel@tonic-gate * Cannot free option_source because it might be referenced in one 550*7c478bd9Sstevel@tonic-gate * or more option_info structures now. 551*7c478bd9Sstevel@tonic-gate */ 552*7c478bd9Sstevel@tonic-gate privileged_option = oldpriv; 553*7c478bd9Sstevel@tonic-gate option_source = oldsource; 554*7c478bd9Sstevel@tonic-gate option_line = oldline; 555*7c478bd9Sstevel@tonic-gate nestlevel--; 556*7c478bd9Sstevel@tonic-gate return (ret); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* 560*7c478bd9Sstevel@tonic-gate * options_from_user - see if the user has a ~/.ppprc file, and if so, 561*7c478bd9Sstevel@tonic-gate * interpret options from it. Returns 1 upon successful processing of 562*7c478bd9Sstevel@tonic-gate * options, and 0 otherwise. 563*7c478bd9Sstevel@tonic-gate */ 564*7c478bd9Sstevel@tonic-gate int 565*7c478bd9Sstevel@tonic-gate options_from_user() 566*7c478bd9Sstevel@tonic-gate { 567*7c478bd9Sstevel@tonic-gate char *user, *path, *file; 568*7c478bd9Sstevel@tonic-gate int ret; 569*7c478bd9Sstevel@tonic-gate struct passwd *pw; 570*7c478bd9Sstevel@tonic-gate size_t pl; 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate pw = getpwuid(getuid()); 573*7c478bd9Sstevel@tonic-gate if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == '\0') 574*7c478bd9Sstevel@tonic-gate return (1); 575*7c478bd9Sstevel@tonic-gate file = _PATH_USEROPT; 576*7c478bd9Sstevel@tonic-gate pl = strlen(user) + strlen(file) + 2; 577*7c478bd9Sstevel@tonic-gate path = malloc(pl); 578*7c478bd9Sstevel@tonic-gate if (path == NULL) 579*7c478bd9Sstevel@tonic-gate novm("init file name"); 580*7c478bd9Sstevel@tonic-gate (void) slprintf(path, pl, "%s/%s", user, file); 581*7c478bd9Sstevel@tonic-gate ret = options_from_file(path, 0, 1, privileged); 582*7c478bd9Sstevel@tonic-gate free(path); 583*7c478bd9Sstevel@tonic-gate return (ret); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate /* 587*7c478bd9Sstevel@tonic-gate * options_for_tty - see if an options file exists for the serial device, and 588*7c478bd9Sstevel@tonic-gate * if so, interpret options from it. Returns 1 upon successful processing of 589*7c478bd9Sstevel@tonic-gate * options, and 0 otherwise. 590*7c478bd9Sstevel@tonic-gate */ 591*7c478bd9Sstevel@tonic-gate int 592*7c478bd9Sstevel@tonic-gate options_for_tty() 593*7c478bd9Sstevel@tonic-gate { 594*7c478bd9Sstevel@tonic-gate char *dev, *path, *p; 595*7c478bd9Sstevel@tonic-gate int ret; 596*7c478bd9Sstevel@tonic-gate size_t pl; 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate dev = devnam; 599*7c478bd9Sstevel@tonic-gate if (strncmp(dev, "/dev/", 5) == 0) 600*7c478bd9Sstevel@tonic-gate dev += 5; 601*7c478bd9Sstevel@tonic-gate if (dev[0] == '\0' || strcmp(dev, "tty") == 0) 602*7c478bd9Sstevel@tonic-gate return (1); /* don't look for /etc/ppp/options.tty */ 603*7c478bd9Sstevel@tonic-gate pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1; 604*7c478bd9Sstevel@tonic-gate path = malloc(pl); 605*7c478bd9Sstevel@tonic-gate if (path == NULL) 606*7c478bd9Sstevel@tonic-gate novm("tty init file name"); 607*7c478bd9Sstevel@tonic-gate (void) slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev); 608*7c478bd9Sstevel@tonic-gate /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */ 609*7c478bd9Sstevel@tonic-gate for (p = path + strlen(_PATH_TTYOPT); *p != '\0'; ++p) 610*7c478bd9Sstevel@tonic-gate if (*p == '/') 611*7c478bd9Sstevel@tonic-gate *p = '.'; 612*7c478bd9Sstevel@tonic-gate ret = options_from_file(path, 0, 0, 1); 613*7c478bd9Sstevel@tonic-gate free(path); 614*7c478bd9Sstevel@tonic-gate return (ret); 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* 618*7c478bd9Sstevel@tonic-gate * options_from_list - process a string of options in a wordlist. Returns 1 619*7c478bd9Sstevel@tonic-gate * upon successful processing of options, and 0 otherwise. 620*7c478bd9Sstevel@tonic-gate */ 621*7c478bd9Sstevel@tonic-gate int 622*7c478bd9Sstevel@tonic-gate options_from_list 623*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 624*7c478bd9Sstevel@tonic-gate (struct wordlist *w, bool priv) 625*7c478bd9Sstevel@tonic-gate #else 626*7c478bd9Sstevel@tonic-gate (w, priv) 627*7c478bd9Sstevel@tonic-gate struct wordlist *w; 628*7c478bd9Sstevel@tonic-gate bool priv; 629*7c478bd9Sstevel@tonic-gate #endif 630*7c478bd9Sstevel@tonic-gate { 631*7c478bd9Sstevel@tonic-gate char *argv[MAXARGS]; 632*7c478bd9Sstevel@tonic-gate option_t *opt; 633*7c478bd9Sstevel@tonic-gate int i, ret = 0; 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate privileged_option = priv; 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate /* Caller is expected to set option_source and option_line. */ 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate while (w != NULL) { 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * First see if it's a command. 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate opt = find_option(w->word); 644*7c478bd9Sstevel@tonic-gate if (opt != NULL) { 645*7c478bd9Sstevel@tonic-gate int n = n_arguments(opt); 646*7c478bd9Sstevel@tonic-gate struct wordlist *w0 = w; 647*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; ++i) { 648*7c478bd9Sstevel@tonic-gate w = w->next; 649*7c478bd9Sstevel@tonic-gate if (w == NULL) { 650*7c478bd9Sstevel@tonic-gate option_error("too few parameters for option '%s'", 651*7c478bd9Sstevel@tonic-gate w0->word); 652*7c478bd9Sstevel@tonic-gate goto err; 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate argv[i] = w->word; 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate current_option = w0->word; 657*7c478bd9Sstevel@tonic-gate if (!process_option(opt, argv, option_line)) 658*7c478bd9Sstevel@tonic-gate goto err; 659*7c478bd9Sstevel@tonic-gate continue; 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* 663*7c478bd9Sstevel@tonic-gate * Options from the {p,ch}ap-secrets files can't change the device 664*7c478bd9Sstevel@tonic-gate * name nor the speed. Therefore, calls to setdevname() and 665*7c478bd9Sstevel@tonic-gate * setspeed() were removed. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate if ((i = setipaddr(w->word)) == 0) { 668*7c478bd9Sstevel@tonic-gate option_error("unrecognized option '%s'", w->word); 669*7c478bd9Sstevel@tonic-gate goto err; 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate if (i < 0) /* error */ 672*7c478bd9Sstevel@tonic-gate goto err; 673*7c478bd9Sstevel@tonic-gate } 674*7c478bd9Sstevel@tonic-gate ret = 1; 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate err: 677*7c478bd9Sstevel@tonic-gate return (ret); 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate /* 681*7c478bd9Sstevel@tonic-gate * find_option - scan the option lists for the various protocols looking for an 682*7c478bd9Sstevel@tonic-gate * entry with the given name. Returns a pointer to the matching option_t 683*7c478bd9Sstevel@tonic-gate * structure upon successful processing of options, and NULL otherwise. 684*7c478bd9Sstevel@tonic-gate */ 685*7c478bd9Sstevel@tonic-gate static option_t * 686*7c478bd9Sstevel@tonic-gate find_option(name) 687*7c478bd9Sstevel@tonic-gate char *name; 688*7c478bd9Sstevel@tonic-gate { 689*7c478bd9Sstevel@tonic-gate hashentry_t *bucket; 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate bucket = hash_tbl[opt_hash(name)]; 692*7c478bd9Sstevel@tonic-gate for (; bucket != NULL; bucket = bucket->next) { 693*7c478bd9Sstevel@tonic-gate if (bucket->opt.p->name != NULL) { 694*7c478bd9Sstevel@tonic-gate if ((strcmp(bucket->opt.p->name, name) == 0) && 695*7c478bd9Sstevel@tonic-gate !(bucket->opt.p->flags & OPT_DISABLE)) { 696*7c478bd9Sstevel@tonic-gate return (bucket->opt.p); 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate return (NULL); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate /* 704*7c478bd9Sstevel@tonic-gate * process_option - process one new-style option (something other than a 705*7c478bd9Sstevel@tonic-gate * port name, bit rate, or IP address). Returns 1 upon successful 706*7c478bd9Sstevel@tonic-gate * processing of options, and 0 otherwise. 707*7c478bd9Sstevel@tonic-gate */ 708*7c478bd9Sstevel@tonic-gate static int 709*7c478bd9Sstevel@tonic-gate process_option(opt, argv, sline) 710*7c478bd9Sstevel@tonic-gate option_t *opt; 711*7c478bd9Sstevel@tonic-gate char **argv; 712*7c478bd9Sstevel@tonic-gate int sline; 713*7c478bd9Sstevel@tonic-gate { 714*7c478bd9Sstevel@tonic-gate u_int32_t v; 715*7c478bd9Sstevel@tonic-gate int iv, a; 716*7c478bd9Sstevel@tonic-gate char *sv; 717*7c478bd9Sstevel@tonic-gate int (*parser) __P((char **, option_t *)); 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_PREPASS) == 0 && prepass) 720*7c478bd9Sstevel@tonic-gate return (1); 721*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) { 722*7c478bd9Sstevel@tonic-gate option_error("it's too late to use the '%s' option", opt->name); 723*7c478bd9Sstevel@tonic-gate return (0); 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_PRIV) && !privileged_option) { 726*7c478bd9Sstevel@tonic-gate option_error("using the '%s' option requires root privilege", 727*7c478bd9Sstevel@tonic-gate opt->name); 728*7c478bd9Sstevel@tonic-gate return (0); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_ENABLE) && !privileged_option && 731*7c478bd9Sstevel@tonic-gate *(bool *)(opt->addr2) == 0) { 732*7c478bd9Sstevel@tonic-gate option_error("'%s' option is disabled", opt->name); 733*7c478bd9Sstevel@tonic-gate return (0); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_PRIVFIX) && !privileged_option) { 736*7c478bd9Sstevel@tonic-gate struct option_info *ip = (struct option_info *) opt->addr2; 737*7c478bd9Sstevel@tonic-gate if ((ip != NULL) && ip->priv) { 738*7c478bd9Sstevel@tonic-gate option_error("'%s' option cannot be overridden", opt->name); 739*7c478bd9Sstevel@tonic-gate return (0); 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate switch (opt->type) { 744*7c478bd9Sstevel@tonic-gate case o_bool: 745*7c478bd9Sstevel@tonic-gate v = opt->flags & OPT_VALUE; 746*7c478bd9Sstevel@tonic-gate *(bool *)(opt->addr) = (v != 0); 747*7c478bd9Sstevel@tonic-gate if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY)) 748*7c478bd9Sstevel@tonic-gate *(bool *)(opt->addr2) = (v != 0); 749*7c478bd9Sstevel@tonic-gate break; 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate case o_int: 752*7c478bd9Sstevel@tonic-gate iv = 0; 753*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_NOARG) == 0) { 754*7c478bd9Sstevel@tonic-gate if (!int_option(*argv, &iv)) 755*7c478bd9Sstevel@tonic-gate return (0); 756*7c478bd9Sstevel@tonic-gate if ((((opt->flags & OPT_LLIMIT) && (iv < opt->lower_limit)) || 757*7c478bd9Sstevel@tonic-gate ((opt->flags & OPT_ULIMIT) && (iv > opt->upper_limit))) && 758*7c478bd9Sstevel@tonic-gate !((opt->flags & OPT_ZEROOK) && (iv == 0))) { 759*7c478bd9Sstevel@tonic-gate char *zok = (opt->flags & OPT_ZEROOK) ? " zero or" : ""; 760*7c478bd9Sstevel@tonic-gate switch (opt->flags & OPT_LIMITS) { 761*7c478bd9Sstevel@tonic-gate case OPT_LLIMIT: 762*7c478bd9Sstevel@tonic-gate option_error("%s value must be%s >= %d", 763*7c478bd9Sstevel@tonic-gate opt->name, zok, opt->lower_limit); 764*7c478bd9Sstevel@tonic-gate break; 765*7c478bd9Sstevel@tonic-gate case OPT_ULIMIT: 766*7c478bd9Sstevel@tonic-gate option_error("%s value must be%s <= %d", 767*7c478bd9Sstevel@tonic-gate opt->name, zok, opt->upper_limit); 768*7c478bd9Sstevel@tonic-gate break; 769*7c478bd9Sstevel@tonic-gate case OPT_LIMITS: 770*7c478bd9Sstevel@tonic-gate option_error("%s value must be%s between %d and %d", 771*7c478bd9Sstevel@tonic-gate opt->name, zok, opt->lower_limit, opt->upper_limit); 772*7c478bd9Sstevel@tonic-gate break; 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate return (0); 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate a = opt->flags & OPT_VALUE; 778*7c478bd9Sstevel@tonic-gate if (a >= 128) 779*7c478bd9Sstevel@tonic-gate a -= 256; /* sign extend */ 780*7c478bd9Sstevel@tonic-gate iv += a; 781*7c478bd9Sstevel@tonic-gate if (opt->flags & OPT_INC) 782*7c478bd9Sstevel@tonic-gate iv += *(int *)(opt->addr); 783*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_NOINCR) && !privileged_option) { 784*7c478bd9Sstevel@tonic-gate int oldv = *(int *)(opt->addr); 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate if ((opt->flags & OPT_ZEROINF) && (iv == 0)) { 787*7c478bd9Sstevel@tonic-gate if (oldv > 0) { 788*7c478bd9Sstevel@tonic-gate option_error("%s value cannot be set to infinity; limited to %d", 789*7c478bd9Sstevel@tonic-gate opt->name, oldv); 790*7c478bd9Sstevel@tonic-gate return (0); 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate } else if (iv > oldv) { 793*7c478bd9Sstevel@tonic-gate option_error("%s value cannot be increased beyond %d", 794*7c478bd9Sstevel@tonic-gate opt->name, oldv); 795*7c478bd9Sstevel@tonic-gate return (0); 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate *(int *)(opt->addr) = iv; 799*7c478bd9Sstevel@tonic-gate if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY)) 800*7c478bd9Sstevel@tonic-gate *(int *)(opt->addr2) = iv; 801*7c478bd9Sstevel@tonic-gate break; 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate case o_uint32: 804*7c478bd9Sstevel@tonic-gate if (opt->flags & OPT_NOARG) { 805*7c478bd9Sstevel@tonic-gate v = opt->flags & OPT_VALUE; 806*7c478bd9Sstevel@tonic-gate } else if (!number_option(*argv, &v, 16)) 807*7c478bd9Sstevel@tonic-gate return (0); 808*7c478bd9Sstevel@tonic-gate if (opt->flags & OPT_OR) 809*7c478bd9Sstevel@tonic-gate v |= *(u_int32_t *)(opt->addr); 810*7c478bd9Sstevel@tonic-gate *(u_int32_t *)(opt->addr) = v; 811*7c478bd9Sstevel@tonic-gate if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY)) 812*7c478bd9Sstevel@tonic-gate *(u_int32_t *)(opt->addr2) = v; 813*7c478bd9Sstevel@tonic-gate break; 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate case o_string: 816*7c478bd9Sstevel@tonic-gate if (opt->flags & OPT_STATIC) { 817*7c478bd9Sstevel@tonic-gate (void) strlcpy((char *)(opt->addr), *argv, opt->upper_limit); 818*7c478bd9Sstevel@tonic-gate if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY)) { 819*7c478bd9Sstevel@tonic-gate (void) strlcpy((char *)(opt->addr2), *argv, opt->upper_limit); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate } else { 822*7c478bd9Sstevel@tonic-gate sv = strdup(*argv); 823*7c478bd9Sstevel@tonic-gate if (sv == NULL) 824*7c478bd9Sstevel@tonic-gate novm("option argument"); 825*7c478bd9Sstevel@tonic-gate *(char **)(opt->addr) = sv; 826*7c478bd9Sstevel@tonic-gate if (opt->addr2 != NULL && (opt->flags & OPT_A2COPY)) 827*7c478bd9Sstevel@tonic-gate *(char **)(opt->addr2) = sv; 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate break; 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate case o_special_noarg: 832*7c478bd9Sstevel@tonic-gate case o_special: 833*7c478bd9Sstevel@tonic-gate parser = (int (*) __P((char **, option_t *))) opt->addr; 834*7c478bd9Sstevel@tonic-gate if (!(*parser)(argv, opt)) 835*7c478bd9Sstevel@tonic-gate return (0); 836*7c478bd9Sstevel@tonic-gate break; 837*7c478bd9Sstevel@tonic-gate } 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate if (opt->addr2 != NULL) { 840*7c478bd9Sstevel@tonic-gate if (opt->flags & OPT_A2INFO) { 841*7c478bd9Sstevel@tonic-gate struct option_info *ip = (struct option_info *) opt->addr2; 842*7c478bd9Sstevel@tonic-gate ip->priv = privileged_option; 843*7c478bd9Sstevel@tonic-gate ip->source = option_source; 844*7c478bd9Sstevel@tonic-gate ip->line = sline; 845*7c478bd9Sstevel@tonic-gate } else if ((opt->flags & (OPT_A2COPY|OPT_ENABLE)) == 0) 846*7c478bd9Sstevel@tonic-gate *(bool *)(opt->addr2) = 1; 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate return (1); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * n_arguments - tell how many arguments an option takes. Returns 1 upon 854*7c478bd9Sstevel@tonic-gate * successful processing of options, and 0 otherwise. 855*7c478bd9Sstevel@tonic-gate */ 856*7c478bd9Sstevel@tonic-gate static int 857*7c478bd9Sstevel@tonic-gate n_arguments(opt) 858*7c478bd9Sstevel@tonic-gate option_t *opt; 859*7c478bd9Sstevel@tonic-gate { 860*7c478bd9Sstevel@tonic-gate return ((opt->type == o_bool || opt->type == o_special_noarg || 861*7c478bd9Sstevel@tonic-gate (opt->flags & OPT_NOARG)) ? 0 : 1); 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate /* 865*7c478bd9Sstevel@tonic-gate * opt_hash - a hash function that works quite well for strings. Returns 866*7c478bd9Sstevel@tonic-gate * the hash key of the supplied string. 867*7c478bd9Sstevel@tonic-gate */ 868*7c478bd9Sstevel@tonic-gate static u_int32_t 869*7c478bd9Sstevel@tonic-gate opt_hash(key) 870*7c478bd9Sstevel@tonic-gate const void *key; 871*7c478bd9Sstevel@tonic-gate { 872*7c478bd9Sstevel@tonic-gate register const char *ptr; 873*7c478bd9Sstevel@tonic-gate register u_int32_t val; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate val = 0; 876*7c478bd9Sstevel@tonic-gate ptr = key; 877*7c478bd9Sstevel@tonic-gate while (*ptr != '\0') { 878*7c478bd9Sstevel@tonic-gate int tmp; 879*7c478bd9Sstevel@tonic-gate val = (val << 4) + (*ptr); 880*7c478bd9Sstevel@tonic-gate tmp = val & 0xf0000000; 881*7c478bd9Sstevel@tonic-gate if (tmp) { 882*7c478bd9Sstevel@tonic-gate val ^= (tmp >> 24); 883*7c478bd9Sstevel@tonic-gate val ^= tmp; 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate ptr++; 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate return (val % OPTHASH_TBLSIZE); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate /* 891*7c478bd9Sstevel@tonic-gate * add_options - add a list of options to the chained hash table. 892*7c478bd9Sstevel@tonic-gate * Also detect duplicate options, and if found, disable the older 893*7c478bd9Sstevel@tonic-gate * definition and log it as an error. 894*7c478bd9Sstevel@tonic-gate */ 895*7c478bd9Sstevel@tonic-gate void 896*7c478bd9Sstevel@tonic-gate add_options(opt) 897*7c478bd9Sstevel@tonic-gate option_t *opt; 898*7c478bd9Sstevel@tonic-gate { 899*7c478bd9Sstevel@tonic-gate register option_t *sopt; 900*7c478bd9Sstevel@tonic-gate register hashentry_t *bucket; 901*7c478bd9Sstevel@tonic-gate register u_int32_t loc; 902*7c478bd9Sstevel@tonic-gate hashentry_t *he; 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate /* fill hash-table */ 905*7c478bd9Sstevel@tonic-gate for (sopt = opt; sopt->name != NULL; ++sopt, hash_tblcnt++) { 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate /* first, allocate a hash entry */ 908*7c478bd9Sstevel@tonic-gate he = (hashentry_t *)malloc(sizeof(*he)); 909*7c478bd9Sstevel@tonic-gate if (he == NULL) { 910*7c478bd9Sstevel@tonic-gate novm("option hash table entry"); 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate he->opt.p = sopt; 913*7c478bd9Sstevel@tonic-gate he->next = NULL; 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate /* 916*7c478bd9Sstevel@tonic-gate * fill the chained hash table and take care of any collisions or 917*7c478bd9Sstevel@tonic-gate * duplicate items. 918*7c478bd9Sstevel@tonic-gate */ 919*7c478bd9Sstevel@tonic-gate loc = opt_hash(sopt->name); 920*7c478bd9Sstevel@tonic-gate bucket = hash_tbl[loc]; 921*7c478bd9Sstevel@tonic-gate if (bucket != NULL) { 922*7c478bd9Sstevel@tonic-gate for (;;) { 923*7c478bd9Sstevel@tonic-gate if (!(bucket->opt.p->flags & OPT_DISABLE) && 924*7c478bd9Sstevel@tonic-gate strcmp(sopt->name, bucket->opt.p->name) == 0) { 925*7c478bd9Sstevel@tonic-gate info("option '%s' redefined; old definition disabled", 926*7c478bd9Sstevel@tonic-gate sopt->name); 927*7c478bd9Sstevel@tonic-gate bucket->opt.p->flags |= OPT_DISABLE; 928*7c478bd9Sstevel@tonic-gate } 929*7c478bd9Sstevel@tonic-gate if (bucket->next == NULL) 930*7c478bd9Sstevel@tonic-gate break; 931*7c478bd9Sstevel@tonic-gate bucket = bucket->next; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate bucket->next = he; 934*7c478bd9Sstevel@tonic-gate } else { 935*7c478bd9Sstevel@tonic-gate hash_tbl[loc] = he; 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate } 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate /* 941*7c478bd9Sstevel@tonic-gate * remove_option - disable an option. Returns the option_t structure 942*7c478bd9Sstevel@tonic-gate * of the disabled option, or NULL if the option name is invalid or if 943*7c478bd9Sstevel@tonic-gate * the option has already been disabled. 944*7c478bd9Sstevel@tonic-gate */ 945*7c478bd9Sstevel@tonic-gate option_t * 946*7c478bd9Sstevel@tonic-gate remove_option(name) 947*7c478bd9Sstevel@tonic-gate char *name; 948*7c478bd9Sstevel@tonic-gate { 949*7c478bd9Sstevel@tonic-gate option_t *opt; 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate if ((opt = find_option(name)) != NULL) { 952*7c478bd9Sstevel@tonic-gate opt->flags |= OPT_DISABLE; 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate return (opt); 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate /* 958*7c478bd9Sstevel@tonic-gate * opt_compare - a compare function supplied to the quicksort routine. 959*7c478bd9Sstevel@tonic-gate * Returns an integer less than, equal to, or greater than zero to indicate 960*7c478bd9Sstevel@tonic-gate * if the first argument is considered less than, equal to, or greater 961*7c478bd9Sstevel@tonic-gate * than the second argument. 962*7c478bd9Sstevel@tonic-gate */ 963*7c478bd9Sstevel@tonic-gate static int 964*7c478bd9Sstevel@tonic-gate opt_compare(p1, p2) 965*7c478bd9Sstevel@tonic-gate const void *p1; 966*7c478bd9Sstevel@tonic-gate const void *p2; 967*7c478bd9Sstevel@tonic-gate { 968*7c478bd9Sstevel@tonic-gate opt_t *o1 = (opt_t *)p1; 969*7c478bd9Sstevel@tonic-gate opt_t *o2 = (opt_t *)p2; 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate return (strcmp(o1->p->name, o2->p->name)); 972*7c478bd9Sstevel@tonic-gate } 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 975*7c478bd9Sstevel@tonic-gate static int 976*7c478bd9Sstevel@tonic-gate showalloptions(argv, topt) 977*7c478bd9Sstevel@tonic-gate char **argv; 978*7c478bd9Sstevel@tonic-gate option_t *topt; 979*7c478bd9Sstevel@tonic-gate { 980*7c478bd9Sstevel@tonic-gate #define MAXOPTSTRLEN 257 981*7c478bd9Sstevel@tonic-gate #define PRINTOPTIONS() { \ 982*7c478bd9Sstevel@tonic-gate (void) slprintf(opt_str, sizeof(opt_str), "%s", opt->name); \ 983*7c478bd9Sstevel@tonic-gate if ((opt->type == o_int || opt->type == o_uint32) && \ 984*7c478bd9Sstevel@tonic-gate !(opt->flags & OPT_NOARG)) { \ 985*7c478bd9Sstevel@tonic-gate (void) strlcat(opt_str, " <n>", sizeof(opt_str)); \ 986*7c478bd9Sstevel@tonic-gate } else if (opt->type == o_string) { \ 987*7c478bd9Sstevel@tonic-gate (void) strlcat(opt_str, " <s>", sizeof(opt_str)); \ 988*7c478bd9Sstevel@tonic-gate } else if (opt->type == o_special) { \ 989*7c478bd9Sstevel@tonic-gate (void) strlcat(opt_str, " <r>", sizeof(opt_str)); \ 990*7c478bd9Sstevel@tonic-gate } \ 991*7c478bd9Sstevel@tonic-gate if (opt->flags & OPT_PRIV) { \ 992*7c478bd9Sstevel@tonic-gate (void) strlcat(opt_str, " (!)", sizeof(opt_str)); \ 993*7c478bd9Sstevel@tonic-gate } else if (opt->flags & OPT_DISABLE) { \ 994*7c478bd9Sstevel@tonic-gate (void) strlcat(opt_str, " (#)", sizeof(opt_str)); \ 995*7c478bd9Sstevel@tonic-gate } \ 996*7c478bd9Sstevel@tonic-gate (void) printf("%-26s%s\n", opt_str, opt->description); \ 997*7c478bd9Sstevel@tonic-gate } 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate char opt_str[MAXOPTSTRLEN]; 1000*7c478bd9Sstevel@tonic-gate option_t *opt; 1001*7c478bd9Sstevel@tonic-gate hashentry_t *bucket; 1002*7c478bd9Sstevel@tonic-gate int i, sofar; 1003*7c478bd9Sstevel@tonic-gate opt_t *sopt; 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate if (phase != PHASE_INITIALIZE) { 1006*7c478bd9Sstevel@tonic-gate return (0); 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate (void) printf(pre_allopt_string, VERSION, PATCHLEVEL, IMPLEMENTATION, 1009*7c478bd9Sstevel@tonic-gate progname); 1010*7c478bd9Sstevel@tonic-gate for (opt = dummy_options; opt->name != NULL; ++opt) { 1011*7c478bd9Sstevel@tonic-gate PRINTOPTIONS(); 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate sopt = malloc(sizeof(*sopt) * hash_tblcnt); 1015*7c478bd9Sstevel@tonic-gate if (sopt == NULL) { 1016*7c478bd9Sstevel@tonic-gate novm("sorted option table"); 1017*7c478bd9Sstevel@tonic-gate } 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate sofar = 0; 1020*7c478bd9Sstevel@tonic-gate for (i = 0; i < OPTHASH_TBLSIZE; i++) { 1021*7c478bd9Sstevel@tonic-gate for (bucket = hash_tbl[i]; bucket != NULL; bucket = bucket->next) { 1022*7c478bd9Sstevel@tonic-gate if (sofar >= hash_tblcnt) { 1023*7c478bd9Sstevel@tonic-gate fatal("options hash table corrupted; size mismatch"); 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate sopt[sofar++].p = bucket->opt.p; 1026*7c478bd9Sstevel@tonic-gate } 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate qsort((void *)sopt, sofar, sizeof(sopt[0]), opt_compare); 1030*7c478bd9Sstevel@tonic-gate for (i = 0; i < sofar; i++) { 1031*7c478bd9Sstevel@tonic-gate opt = sopt[i].p; 1032*7c478bd9Sstevel@tonic-gate PRINTOPTIONS(); 1033*7c478bd9Sstevel@tonic-gate } 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate (void) printf(post_allopt_string); 1036*7c478bd9Sstevel@tonic-gate (void) free(sopt); 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate #undef MAXOPTSTRLEN 1039*7c478bd9Sstevel@tonic-gate #undef PRINTOPTIONS 1040*7c478bd9Sstevel@tonic-gate return (0); 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate /* 1044*7c478bd9Sstevel@tonic-gate * usage - print out a message telling how to use the program. 1045*7c478bd9Sstevel@tonic-gate * This string gets printed out when either "--help" or an invalid option 1046*7c478bd9Sstevel@tonic-gate * is specified. 1047*7c478bd9Sstevel@tonic-gate */ 1048*7c478bd9Sstevel@tonic-gate static void 1049*7c478bd9Sstevel@tonic-gate usage() 1050*7c478bd9Sstevel@tonic-gate { 1051*7c478bd9Sstevel@tonic-gate static const char usage_string[] = "\ 1052*7c478bd9Sstevel@tonic-gate pppd version %s.%d%s\n\ 1053*7c478bd9Sstevel@tonic-gate Usage: %s [ options ], where options are:\n\ 1054*7c478bd9Sstevel@tonic-gate \t<device>\tCommunicate over the named device\n\ 1055*7c478bd9Sstevel@tonic-gate \t<speed>\t\tSet the baud rate to <speed>\n\ 1056*7c478bd9Sstevel@tonic-gate \t<loc>:<rem>\tSet the local and/or remote interface IP\n\ 1057*7c478bd9Sstevel@tonic-gate \t\t\taddresses. Either one may be omitted.\n\ 1058*7c478bd9Sstevel@tonic-gate \tnoauth\t\tDon't require authentication from peer\n\ 1059*7c478bd9Sstevel@tonic-gate \tconnect <p>\tInvoke shell command <p> to set up the serial line\n\ 1060*7c478bd9Sstevel@tonic-gate \tdefaultroute\tAdd default route through interface\n\ 1061*7c478bd9Sstevel@tonic-gate Use \"%s options\" or \"man pppd\" for more options.\n\ 1062*7c478bd9Sstevel@tonic-gate "; 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate if (phase == PHASE_INITIALIZE) 1065*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, usage_string, VERSION, PATCHLEVEL, 1066*7c478bd9Sstevel@tonic-gate IMPLEMENTATION, progname, progname); 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate /* 1070*7c478bd9Sstevel@tonic-gate * showhelp - print out usage message and exit program upon success, or 1071*7c478bd9Sstevel@tonic-gate * return 0 otherwise. 1072*7c478bd9Sstevel@tonic-gate */ 1073*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1074*7c478bd9Sstevel@tonic-gate static int 1075*7c478bd9Sstevel@tonic-gate showhelp(argv, opt) 1076*7c478bd9Sstevel@tonic-gate char **argv; 1077*7c478bd9Sstevel@tonic-gate option_t *opt; 1078*7c478bd9Sstevel@tonic-gate { 1079*7c478bd9Sstevel@tonic-gate if (phase == PHASE_INITIALIZE) { 1080*7c478bd9Sstevel@tonic-gate usage(); 1081*7c478bd9Sstevel@tonic-gate exit(0); 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate return (0); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate /* 1087*7c478bd9Sstevel@tonic-gate * showversion - print out the version number and exit program upon success, 1088*7c478bd9Sstevel@tonic-gate * or return 0 otherwise. 1089*7c478bd9Sstevel@tonic-gate */ 1090*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1091*7c478bd9Sstevel@tonic-gate static int 1092*7c478bd9Sstevel@tonic-gate showversion(argv, opt) 1093*7c478bd9Sstevel@tonic-gate char **argv; 1094*7c478bd9Sstevel@tonic-gate option_t *opt; 1095*7c478bd9Sstevel@tonic-gate { 1096*7c478bd9Sstevel@tonic-gate if (phase == PHASE_INITIALIZE) { 1097*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "pppd version %s.%d%s\n", VERSION, PATCHLEVEL, 1098*7c478bd9Sstevel@tonic-gate IMPLEMENTATION); 1099*7c478bd9Sstevel@tonic-gate exit(0); 1100*7c478bd9Sstevel@tonic-gate } 1101*7c478bd9Sstevel@tonic-gate return (0); 1102*7c478bd9Sstevel@tonic-gate } 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate /* 1105*7c478bd9Sstevel@tonic-gate * option_error - print a message about an error in an option. The message is 1106*7c478bd9Sstevel@tonic-gate * logged, and also sent to stderr if phase == PHASE_INITIALIZE. 1107*7c478bd9Sstevel@tonic-gate */ 1108*7c478bd9Sstevel@tonic-gate void 1109*7c478bd9Sstevel@tonic-gate option_error __V((char *fmt, ...)) 1110*7c478bd9Sstevel@tonic-gate { 1111*7c478bd9Sstevel@tonic-gate va_list args; 1112*7c478bd9Sstevel@tonic-gate char buf[256]; 1113*7c478bd9Sstevel@tonic-gate int i, err; 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate #if defined(__STDC__) 1116*7c478bd9Sstevel@tonic-gate va_start(args, fmt); 1117*7c478bd9Sstevel@tonic-gate #else 1118*7c478bd9Sstevel@tonic-gate char *fmt; 1119*7c478bd9Sstevel@tonic-gate va_start(args); 1120*7c478bd9Sstevel@tonic-gate fmt = va_arg(args, char *); 1121*7c478bd9Sstevel@tonic-gate #endif 1122*7c478bd9Sstevel@tonic-gate if (prepass) { 1123*7c478bd9Sstevel@tonic-gate va_end(args); 1124*7c478bd9Sstevel@tonic-gate return; 1125*7c478bd9Sstevel@tonic-gate } 1126*7c478bd9Sstevel@tonic-gate err = errno; 1127*7c478bd9Sstevel@tonic-gate if (option_source == NULL) { 1128*7c478bd9Sstevel@tonic-gate i = 0; 1129*7c478bd9Sstevel@tonic-gate } else if (option_line <= 0) { 1130*7c478bd9Sstevel@tonic-gate (void) strlcpy(buf, option_source, sizeof (buf)); 1131*7c478bd9Sstevel@tonic-gate i = strlen(buf); 1132*7c478bd9Sstevel@tonic-gate } else { 1133*7c478bd9Sstevel@tonic-gate i = slprintf(buf, sizeof(buf), "%s:%d", option_source, option_line); 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate if (i != 0) { 1136*7c478bd9Sstevel@tonic-gate (void) strlcat(buf, ": ", sizeof (buf)); 1137*7c478bd9Sstevel@tonic-gate i += 2; 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate errno = err; 1140*7c478bd9Sstevel@tonic-gate (void) vslprintf(buf + i, sizeof (buf) - i, fmt, args); 1141*7c478bd9Sstevel@tonic-gate va_end(args); 1142*7c478bd9Sstevel@tonic-gate if ((phase == PHASE_INITIALIZE) && !detached) 1143*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", progname, buf); 1144*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "%s", buf); 1145*7c478bd9Sstevel@tonic-gate } 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate /* 1148*7c478bd9Sstevel@tonic-gate * getword - read a word from a file. Words are delimited by white-space or by 1149*7c478bd9Sstevel@tonic-gate * quotes (" or '). Quotes, white-space and \ may be escaped with \. 1150*7c478bd9Sstevel@tonic-gate * \<newline> is ignored. Returns 1 upon successful processing of options, 1151*7c478bd9Sstevel@tonic-gate * and 0 otherwise. 1152*7c478bd9Sstevel@tonic-gate */ 1153*7c478bd9Sstevel@tonic-gate int 1154*7c478bd9Sstevel@tonic-gate getword(f, word, newlinep, filename) 1155*7c478bd9Sstevel@tonic-gate FILE *f; 1156*7c478bd9Sstevel@tonic-gate char *word; 1157*7c478bd9Sstevel@tonic-gate int *newlinep; 1158*7c478bd9Sstevel@tonic-gate char *filename; 1159*7c478bd9Sstevel@tonic-gate { 1160*7c478bd9Sstevel@tonic-gate int c, len, escape; 1161*7c478bd9Sstevel@tonic-gate int quoted, comment; 1162*7c478bd9Sstevel@tonic-gate int value, digit, got, n; 1163*7c478bd9Sstevel@tonic-gate 1164*7c478bd9Sstevel@tonic-gate #define isoctal(c) ((c) >= '0' && (c) < '8') 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate *newlinep = 0; 1167*7c478bd9Sstevel@tonic-gate len = 0; 1168*7c478bd9Sstevel@tonic-gate escape = 0; 1169*7c478bd9Sstevel@tonic-gate comment = 0; 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate /* 1172*7c478bd9Sstevel@tonic-gate * First skip white-space and comments. 1173*7c478bd9Sstevel@tonic-gate */ 1174*7c478bd9Sstevel@tonic-gate for (;;) { 1175*7c478bd9Sstevel@tonic-gate c = getc(f); 1176*7c478bd9Sstevel@tonic-gate if (c == EOF) 1177*7c478bd9Sstevel@tonic-gate break; 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate /* 1180*7c478bd9Sstevel@tonic-gate * A newline means the end of a comment; backslash-newline 1181*7c478bd9Sstevel@tonic-gate * is ignored. Note that we cannot have escape && comment. 1182*7c478bd9Sstevel@tonic-gate */ 1183*7c478bd9Sstevel@tonic-gate if (c == '\n') { 1184*7c478bd9Sstevel@tonic-gate option_line++; 1185*7c478bd9Sstevel@tonic-gate if (!escape) { 1186*7c478bd9Sstevel@tonic-gate *newlinep = 1; 1187*7c478bd9Sstevel@tonic-gate comment = 0; 1188*7c478bd9Sstevel@tonic-gate } else 1189*7c478bd9Sstevel@tonic-gate escape = 0; 1190*7c478bd9Sstevel@tonic-gate continue; 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate /* 1194*7c478bd9Sstevel@tonic-gate * Ignore characters other than newline in a comment. 1195*7c478bd9Sstevel@tonic-gate */ 1196*7c478bd9Sstevel@tonic-gate if (comment) 1197*7c478bd9Sstevel@tonic-gate continue; 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate /* 1200*7c478bd9Sstevel@tonic-gate * If this character is escaped, we have a word start. 1201*7c478bd9Sstevel@tonic-gate */ 1202*7c478bd9Sstevel@tonic-gate if (escape) 1203*7c478bd9Sstevel@tonic-gate break; 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate /* 1206*7c478bd9Sstevel@tonic-gate * If this is the escape character, look at the next character. 1207*7c478bd9Sstevel@tonic-gate */ 1208*7c478bd9Sstevel@tonic-gate if (c == '\\') { 1209*7c478bd9Sstevel@tonic-gate escape = 1; 1210*7c478bd9Sstevel@tonic-gate continue; 1211*7c478bd9Sstevel@tonic-gate } 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate /* 1214*7c478bd9Sstevel@tonic-gate * If this is the start of a comment, ignore the rest of the line. 1215*7c478bd9Sstevel@tonic-gate */ 1216*7c478bd9Sstevel@tonic-gate if (c == '#') { 1217*7c478bd9Sstevel@tonic-gate comment = 1; 1218*7c478bd9Sstevel@tonic-gate continue; 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate /* 1222*7c478bd9Sstevel@tonic-gate * A non-whitespace character is the start of a word. 1223*7c478bd9Sstevel@tonic-gate */ 1224*7c478bd9Sstevel@tonic-gate if (!isspace(c)) 1225*7c478bd9Sstevel@tonic-gate break; 1226*7c478bd9Sstevel@tonic-gate } 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate /* 1229*7c478bd9Sstevel@tonic-gate * Save the delimiter for quoted strings. 1230*7c478bd9Sstevel@tonic-gate */ 1231*7c478bd9Sstevel@tonic-gate if (!escape && (c == '"' || c == '\'')) { 1232*7c478bd9Sstevel@tonic-gate quoted = c; 1233*7c478bd9Sstevel@tonic-gate c = getc(f); 1234*7c478bd9Sstevel@tonic-gate } else 1235*7c478bd9Sstevel@tonic-gate quoted = 0; 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate /* 1238*7c478bd9Sstevel@tonic-gate * Process characters until the end of the word. 1239*7c478bd9Sstevel@tonic-gate */ 1240*7c478bd9Sstevel@tonic-gate while (c != EOF) { 1241*7c478bd9Sstevel@tonic-gate if (escape) { 1242*7c478bd9Sstevel@tonic-gate /* 1243*7c478bd9Sstevel@tonic-gate * This character is escaped: backslash-newline is ignored, 1244*7c478bd9Sstevel@tonic-gate * various other characters indicate particular values 1245*7c478bd9Sstevel@tonic-gate * as for C backslash-escapes. 1246*7c478bd9Sstevel@tonic-gate */ 1247*7c478bd9Sstevel@tonic-gate escape = 0; 1248*7c478bd9Sstevel@tonic-gate if (c == '\n') { 1249*7c478bd9Sstevel@tonic-gate c = getc(f); 1250*7c478bd9Sstevel@tonic-gate continue; 1251*7c478bd9Sstevel@tonic-gate } 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate got = 0; 1254*7c478bd9Sstevel@tonic-gate switch (c) { 1255*7c478bd9Sstevel@tonic-gate case 'a': 1256*7c478bd9Sstevel@tonic-gate value = '\a'; 1257*7c478bd9Sstevel@tonic-gate break; 1258*7c478bd9Sstevel@tonic-gate case 'b': 1259*7c478bd9Sstevel@tonic-gate value = '\b'; 1260*7c478bd9Sstevel@tonic-gate break; 1261*7c478bd9Sstevel@tonic-gate case 'f': 1262*7c478bd9Sstevel@tonic-gate value = '\f'; 1263*7c478bd9Sstevel@tonic-gate break; 1264*7c478bd9Sstevel@tonic-gate case 'n': 1265*7c478bd9Sstevel@tonic-gate value = '\n'; 1266*7c478bd9Sstevel@tonic-gate break; 1267*7c478bd9Sstevel@tonic-gate case 'r': 1268*7c478bd9Sstevel@tonic-gate value = '\r'; 1269*7c478bd9Sstevel@tonic-gate break; 1270*7c478bd9Sstevel@tonic-gate case 's': 1271*7c478bd9Sstevel@tonic-gate value = ' '; 1272*7c478bd9Sstevel@tonic-gate break; 1273*7c478bd9Sstevel@tonic-gate case 't': 1274*7c478bd9Sstevel@tonic-gate value = '\t'; 1275*7c478bd9Sstevel@tonic-gate break; 1276*7c478bd9Sstevel@tonic-gate 1277*7c478bd9Sstevel@tonic-gate default: 1278*7c478bd9Sstevel@tonic-gate if (isoctal(c)) { 1279*7c478bd9Sstevel@tonic-gate /* 1280*7c478bd9Sstevel@tonic-gate * \ddd octal sequence 1281*7c478bd9Sstevel@tonic-gate */ 1282*7c478bd9Sstevel@tonic-gate value = 0; 1283*7c478bd9Sstevel@tonic-gate for (n = 0; n < 3 && isoctal(c); ++n) { 1284*7c478bd9Sstevel@tonic-gate value = (value << 3) + (c & 07); 1285*7c478bd9Sstevel@tonic-gate c = getc(f); 1286*7c478bd9Sstevel@tonic-gate } 1287*7c478bd9Sstevel@tonic-gate got = 1; 1288*7c478bd9Sstevel@tonic-gate break; 1289*7c478bd9Sstevel@tonic-gate } 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate if (c == 'x') { 1292*7c478bd9Sstevel@tonic-gate /* 1293*7c478bd9Sstevel@tonic-gate * \x<hex_string> sequence 1294*7c478bd9Sstevel@tonic-gate */ 1295*7c478bd9Sstevel@tonic-gate value = 0; 1296*7c478bd9Sstevel@tonic-gate c = getc(f); 1297*7c478bd9Sstevel@tonic-gate for (n = 0; n < 2 && isxdigit(c); ++n) { 1298*7c478bd9Sstevel@tonic-gate digit = (islower(c) ? toupper(c) : c) - '0'; 1299*7c478bd9Sstevel@tonic-gate if (digit > 10 || digit < 0) /* allow non-ASCII */ 1300*7c478bd9Sstevel@tonic-gate digit += '0' + 10 - 'A'; 1301*7c478bd9Sstevel@tonic-gate value = (value << 4) + digit; 1302*7c478bd9Sstevel@tonic-gate c = getc (f); 1303*7c478bd9Sstevel@tonic-gate } 1304*7c478bd9Sstevel@tonic-gate got = 1; 1305*7c478bd9Sstevel@tonic-gate break; 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate /* 1309*7c478bd9Sstevel@tonic-gate * Otherwise the character stands for itself. 1310*7c478bd9Sstevel@tonic-gate */ 1311*7c478bd9Sstevel@tonic-gate value = c; 1312*7c478bd9Sstevel@tonic-gate break; 1313*7c478bd9Sstevel@tonic-gate } 1314*7c478bd9Sstevel@tonic-gate 1315*7c478bd9Sstevel@tonic-gate /* 1316*7c478bd9Sstevel@tonic-gate * Store the resulting character for the escape sequence. 1317*7c478bd9Sstevel@tonic-gate */ 1318*7c478bd9Sstevel@tonic-gate if (len < MAXWORDLEN-1) 1319*7c478bd9Sstevel@tonic-gate word[len] = value; 1320*7c478bd9Sstevel@tonic-gate ++len; 1321*7c478bd9Sstevel@tonic-gate 1322*7c478bd9Sstevel@tonic-gate if (!got) 1323*7c478bd9Sstevel@tonic-gate c = getc(f); 1324*7c478bd9Sstevel@tonic-gate continue; 1325*7c478bd9Sstevel@tonic-gate 1326*7c478bd9Sstevel@tonic-gate } 1327*7c478bd9Sstevel@tonic-gate 1328*7c478bd9Sstevel@tonic-gate /* 1329*7c478bd9Sstevel@tonic-gate * Not escaped: see if we've reached the end of the word. 1330*7c478bd9Sstevel@tonic-gate */ 1331*7c478bd9Sstevel@tonic-gate if (quoted) { 1332*7c478bd9Sstevel@tonic-gate if (c == quoted) 1333*7c478bd9Sstevel@tonic-gate break; 1334*7c478bd9Sstevel@tonic-gate } else { 1335*7c478bd9Sstevel@tonic-gate if (isspace(c) || c == '#') { 1336*7c478bd9Sstevel@tonic-gate (void) ungetc (c, f); 1337*7c478bd9Sstevel@tonic-gate break; 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate } 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate /* 1342*7c478bd9Sstevel@tonic-gate * Backslash starts an escape sequence. 1343*7c478bd9Sstevel@tonic-gate */ 1344*7c478bd9Sstevel@tonic-gate if (c == '\\') { 1345*7c478bd9Sstevel@tonic-gate escape = 1; 1346*7c478bd9Sstevel@tonic-gate c = getc(f); 1347*7c478bd9Sstevel@tonic-gate continue; 1348*7c478bd9Sstevel@tonic-gate } 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate /* 1351*7c478bd9Sstevel@tonic-gate * An ordinary character: store it in the word and get another. 1352*7c478bd9Sstevel@tonic-gate */ 1353*7c478bd9Sstevel@tonic-gate if (len < MAXWORDLEN-1) 1354*7c478bd9Sstevel@tonic-gate word[len] = c; 1355*7c478bd9Sstevel@tonic-gate ++len; 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate c = getc(f); 1358*7c478bd9Sstevel@tonic-gate } 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate /* 1361*7c478bd9Sstevel@tonic-gate * End of the word: check for errors. 1362*7c478bd9Sstevel@tonic-gate */ 1363*7c478bd9Sstevel@tonic-gate if (c == EOF) { 1364*7c478bd9Sstevel@tonic-gate if (ferror(f)) { 1365*7c478bd9Sstevel@tonic-gate if (errno == 0) 1366*7c478bd9Sstevel@tonic-gate errno = EIO; 1367*7c478bd9Sstevel@tonic-gate option_error("Error reading %s: %m", filename); 1368*7c478bd9Sstevel@tonic-gate die(1); 1369*7c478bd9Sstevel@tonic-gate } 1370*7c478bd9Sstevel@tonic-gate /* 1371*7c478bd9Sstevel@tonic-gate * If len is zero, then we didn't find a word before the 1372*7c478bd9Sstevel@tonic-gate * end of the file. 1373*7c478bd9Sstevel@tonic-gate */ 1374*7c478bd9Sstevel@tonic-gate if (len == 0) 1375*7c478bd9Sstevel@tonic-gate return (0); 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate /* 1379*7c478bd9Sstevel@tonic-gate * Warn if the word was too long, and append a terminating null. 1380*7c478bd9Sstevel@tonic-gate */ 1381*7c478bd9Sstevel@tonic-gate if (len >= MAXWORDLEN) { 1382*7c478bd9Sstevel@tonic-gate option_error("warning: word in file %s too long (%.20s...)", 1383*7c478bd9Sstevel@tonic-gate filename, word); 1384*7c478bd9Sstevel@tonic-gate len = MAXWORDLEN - 1; 1385*7c478bd9Sstevel@tonic-gate } 1386*7c478bd9Sstevel@tonic-gate word[len] = '\0'; 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate return (1); 1389*7c478bd9Sstevel@tonic-gate 1390*7c478bd9Sstevel@tonic-gate #undef isoctal 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate } 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate /* 1395*7c478bd9Sstevel@tonic-gate * number_option - parse an unsigned numeric parameter for an option. 1396*7c478bd9Sstevel@tonic-gate * Returns 1 upon successful processing of options, and 0 otherwise. 1397*7c478bd9Sstevel@tonic-gate */ 1398*7c478bd9Sstevel@tonic-gate static int 1399*7c478bd9Sstevel@tonic-gate number_option(str, valp, base) 1400*7c478bd9Sstevel@tonic-gate char *str; 1401*7c478bd9Sstevel@tonic-gate u_int32_t *valp; 1402*7c478bd9Sstevel@tonic-gate int base; 1403*7c478bd9Sstevel@tonic-gate { 1404*7c478bd9Sstevel@tonic-gate char *ptr; 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate *valp = strtoul(str, &ptr, base); 1407*7c478bd9Sstevel@tonic-gate if (ptr == str || *ptr != '\0') { 1408*7c478bd9Sstevel@tonic-gate option_error("invalid numeric parameter '%s' for '%s' option", 1409*7c478bd9Sstevel@tonic-gate str, current_option); 1410*7c478bd9Sstevel@tonic-gate return (0); 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate return (1); 1413*7c478bd9Sstevel@tonic-gate } 1414*7c478bd9Sstevel@tonic-gate 1415*7c478bd9Sstevel@tonic-gate /* 1416*7c478bd9Sstevel@tonic-gate * save_source - store option source, line, and privilege into an 1417*7c478bd9Sstevel@tonic-gate * option_info structure. 1418*7c478bd9Sstevel@tonic-gate */ 1419*7c478bd9Sstevel@tonic-gate void 1420*7c478bd9Sstevel@tonic-gate save_source(info) 1421*7c478bd9Sstevel@tonic-gate struct option_info *info; 1422*7c478bd9Sstevel@tonic-gate { 1423*7c478bd9Sstevel@tonic-gate info->priv = privileged_option; 1424*7c478bd9Sstevel@tonic-gate info->source = option_source; 1425*7c478bd9Sstevel@tonic-gate info->line = option_line; 1426*7c478bd9Sstevel@tonic-gate } 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate /* 1429*7c478bd9Sstevel@tonic-gate * set_source - set option source, line, and privilege from an 1430*7c478bd9Sstevel@tonic-gate * option_info structure. 1431*7c478bd9Sstevel@tonic-gate */ 1432*7c478bd9Sstevel@tonic-gate void 1433*7c478bd9Sstevel@tonic-gate set_source(info) 1434*7c478bd9Sstevel@tonic-gate struct option_info *info; 1435*7c478bd9Sstevel@tonic-gate { 1436*7c478bd9Sstevel@tonic-gate privileged_option = info->priv; 1437*7c478bd9Sstevel@tonic-gate option_source = info->source; 1438*7c478bd9Sstevel@tonic-gate option_line = info->line; 1439*7c478bd9Sstevel@tonic-gate } 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate /* 1442*7c478bd9Sstevel@tonic-gate * name_source - return string containing option source and line. Can 1443*7c478bd9Sstevel@tonic-gate * be used as part of an option_error call. 1444*7c478bd9Sstevel@tonic-gate */ 1445*7c478bd9Sstevel@tonic-gate const char * 1446*7c478bd9Sstevel@tonic-gate name_source(info) 1447*7c478bd9Sstevel@tonic-gate struct option_info *info; 1448*7c478bd9Sstevel@tonic-gate { 1449*7c478bd9Sstevel@tonic-gate static char buf[MAXPATHLEN]; 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate if (info->source == NULL) 1452*7c478bd9Sstevel@tonic-gate return "none"; 1453*7c478bd9Sstevel@tonic-gate if (info->line <= 0) 1454*7c478bd9Sstevel@tonic-gate return info->source; 1455*7c478bd9Sstevel@tonic-gate (void) slprintf(buf, sizeof (buf), "%s:%d", info->source, info->line); 1456*7c478bd9Sstevel@tonic-gate return (const char *)buf; 1457*7c478bd9Sstevel@tonic-gate } 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate /* 1460*7c478bd9Sstevel@tonic-gate * int_option - like number_option, but valp is int *, the base is assumed to 1461*7c478bd9Sstevel@tonic-gate * be 0, and *valp is not changed if there is an error. Returns 1 upon 1462*7c478bd9Sstevel@tonic-gate * successful processing of options, and 0 otherwise. 1463*7c478bd9Sstevel@tonic-gate */ 1464*7c478bd9Sstevel@tonic-gate int 1465*7c478bd9Sstevel@tonic-gate int_option(str, valp) 1466*7c478bd9Sstevel@tonic-gate char *str; 1467*7c478bd9Sstevel@tonic-gate int *valp; 1468*7c478bd9Sstevel@tonic-gate { 1469*7c478bd9Sstevel@tonic-gate u_int32_t v; 1470*7c478bd9Sstevel@tonic-gate 1471*7c478bd9Sstevel@tonic-gate if (!number_option(str, &v, 0)) 1472*7c478bd9Sstevel@tonic-gate return (0); 1473*7c478bd9Sstevel@tonic-gate *valp = (int) v; 1474*7c478bd9Sstevel@tonic-gate return (1); 1475*7c478bd9Sstevel@tonic-gate } 1476*7c478bd9Sstevel@tonic-gate 1477*7c478bd9Sstevel@tonic-gate 1478*7c478bd9Sstevel@tonic-gate /* 1479*7c478bd9Sstevel@tonic-gate * The following procedures parse options. 1480*7c478bd9Sstevel@tonic-gate */ 1481*7c478bd9Sstevel@tonic-gate 1482*7c478bd9Sstevel@tonic-gate /* 1483*7c478bd9Sstevel@tonic-gate * readfile - take commands from a file. 1484*7c478bd9Sstevel@tonic-gate */ 1485*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1486*7c478bd9Sstevel@tonic-gate static int 1487*7c478bd9Sstevel@tonic-gate readfile(argv, opt) 1488*7c478bd9Sstevel@tonic-gate char **argv; 1489*7c478bd9Sstevel@tonic-gate option_t *opt; 1490*7c478bd9Sstevel@tonic-gate { 1491*7c478bd9Sstevel@tonic-gate return (options_from_file(*argv, 1, 1, privileged_option)); 1492*7c478bd9Sstevel@tonic-gate } 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate /* 1495*7c478bd9Sstevel@tonic-gate * callfile - take commands from /etc/ppp/peers/<name>. Name may not contain 1496*7c478bd9Sstevel@tonic-gate * /../, start with / or ../, or end in /. Returns 1 upon successful 1497*7c478bd9Sstevel@tonic-gate * processing of options, and 0 otherwise. 1498*7c478bd9Sstevel@tonic-gate */ 1499*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1500*7c478bd9Sstevel@tonic-gate static int 1501*7c478bd9Sstevel@tonic-gate callfile(argv, opt) 1502*7c478bd9Sstevel@tonic-gate char **argv; 1503*7c478bd9Sstevel@tonic-gate option_t *opt; 1504*7c478bd9Sstevel@tonic-gate { 1505*7c478bd9Sstevel@tonic-gate char *fname, *arg, *p; 1506*7c478bd9Sstevel@tonic-gate int l, ok; 1507*7c478bd9Sstevel@tonic-gate 1508*7c478bd9Sstevel@tonic-gate arg = *argv; 1509*7c478bd9Sstevel@tonic-gate ok = 1; 1510*7c478bd9Sstevel@tonic-gate if (arg[0] == '/' || arg[0] == '\0') 1511*7c478bd9Sstevel@tonic-gate ok = 0; 1512*7c478bd9Sstevel@tonic-gate else { 1513*7c478bd9Sstevel@tonic-gate for (p = arg; *p != '\0'; ) { 1514*7c478bd9Sstevel@tonic-gate if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) { 1515*7c478bd9Sstevel@tonic-gate ok = 0; 1516*7c478bd9Sstevel@tonic-gate break; 1517*7c478bd9Sstevel@tonic-gate } 1518*7c478bd9Sstevel@tonic-gate while (*p != '/' && *p != '\0') 1519*7c478bd9Sstevel@tonic-gate ++p; 1520*7c478bd9Sstevel@tonic-gate if (*p == '/') 1521*7c478bd9Sstevel@tonic-gate ++p; 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate } 1524*7c478bd9Sstevel@tonic-gate if (!ok) { 1525*7c478bd9Sstevel@tonic-gate option_error("call option value may not contain .. or start with /"); 1526*7c478bd9Sstevel@tonic-gate return (0); 1527*7c478bd9Sstevel@tonic-gate } 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate l = strlen(arg) + strlen(_PATH_PEERFILES) + 1; 1530*7c478bd9Sstevel@tonic-gate if ((fname = (char *) malloc(l)) == NULL) 1531*7c478bd9Sstevel@tonic-gate novm("call file name"); 1532*7c478bd9Sstevel@tonic-gate (void) slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg); 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate ok = options_from_file(fname, 1, 1, 1); 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate free(fname); 1537*7c478bd9Sstevel@tonic-gate return (ok); 1538*7c478bd9Sstevel@tonic-gate } 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate #ifdef PPP_FILTER 1541*7c478bd9Sstevel@tonic-gate /* 1542*7c478bd9Sstevel@tonic-gate * setpdebug - set libpcap debugging level. Returns 1 upon successful 1543*7c478bd9Sstevel@tonic-gate * processing of options, and 0 otherwise. 1544*7c478bd9Sstevel@tonic-gate */ 1545*7c478bd9Sstevel@tonic-gate static int 1546*7c478bd9Sstevel@tonic-gate setpdebug(argv) 1547*7c478bd9Sstevel@tonic-gate char **argv; 1548*7c478bd9Sstevel@tonic-gate { 1549*7c478bd9Sstevel@tonic-gate return (int_option(*argv, &dflag)); 1550*7c478bd9Sstevel@tonic-gate } 1551*7c478bd9Sstevel@tonic-gate 1552*7c478bd9Sstevel@tonic-gate /* 1553*7c478bd9Sstevel@tonic-gate * setpassfilter - set the pass filter for packets. Returns 1 upon successful 1554*7c478bd9Sstevel@tonic-gate * processing of options, and 0 otherwise. 1555*7c478bd9Sstevel@tonic-gate */ 1556*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1557*7c478bd9Sstevel@tonic-gate static int 1558*7c478bd9Sstevel@tonic-gate setpassfilter(argv, opt) 1559*7c478bd9Sstevel@tonic-gate char **argv; 1560*7c478bd9Sstevel@tonic-gate option_t *opt; 1561*7c478bd9Sstevel@tonic-gate { 1562*7c478bd9Sstevel@tonic-gate pc.linktype = DLT_PPP; 1563*7c478bd9Sstevel@tonic-gate pc.snapshot = PPP_HDRLEN; 1564*7c478bd9Sstevel@tonic-gate 1565*7c478bd9Sstevel@tonic-gate if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0) 1566*7c478bd9Sstevel@tonic-gate return (1); 1567*7c478bd9Sstevel@tonic-gate option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc)); 1568*7c478bd9Sstevel@tonic-gate return (0); 1569*7c478bd9Sstevel@tonic-gate } 1570*7c478bd9Sstevel@tonic-gate 1571*7c478bd9Sstevel@tonic-gate /* 1572*7c478bd9Sstevel@tonic-gate * setactivefilter - set the active filter for packets. Returns 1 upon 1573*7c478bd9Sstevel@tonic-gate * successful processing of options, and 0 otherwise. 1574*7c478bd9Sstevel@tonic-gate */ 1575*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1576*7c478bd9Sstevel@tonic-gate static int 1577*7c478bd9Sstevel@tonic-gate setactivefilter(argv, opt) 1578*7c478bd9Sstevel@tonic-gate char **argv; 1579*7c478bd9Sstevel@tonic-gate option_t *opt; 1580*7c478bd9Sstevel@tonic-gate { 1581*7c478bd9Sstevel@tonic-gate pc.linktype = DLT_PPP; 1582*7c478bd9Sstevel@tonic-gate pc.snapshot = PPP_HDRLEN; 1583*7c478bd9Sstevel@tonic-gate 1584*7c478bd9Sstevel@tonic-gate if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0) 1585*7c478bd9Sstevel@tonic-gate return (1); 1586*7c478bd9Sstevel@tonic-gate option_error("error in active-filter expression: %s\n", pcap_geterr(&pc)); 1587*7c478bd9Sstevel@tonic-gate return (0); 1588*7c478bd9Sstevel@tonic-gate } 1589*7c478bd9Sstevel@tonic-gate #endif /* PPP_FILTER */ 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate /* 1592*7c478bd9Sstevel@tonic-gate * noopt - disable all options. Returns 1 upon successful processing of 1593*7c478bd9Sstevel@tonic-gate * options, and 0 otherwise. 1594*7c478bd9Sstevel@tonic-gate */ 1595*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1596*7c478bd9Sstevel@tonic-gate static int 1597*7c478bd9Sstevel@tonic-gate noopt(argv, opt) 1598*7c478bd9Sstevel@tonic-gate char **argv; 1599*7c478bd9Sstevel@tonic-gate option_t *opt; 1600*7c478bd9Sstevel@tonic-gate { 1601*7c478bd9Sstevel@tonic-gate BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); 1602*7c478bd9Sstevel@tonic-gate BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); 1603*7c478bd9Sstevel@tonic-gate BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options)); 1604*7c478bd9Sstevel@tonic-gate BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options)); 1605*7c478bd9Sstevel@tonic-gate 1606*7c478bd9Sstevel@tonic-gate return (1); 1607*7c478bd9Sstevel@tonic-gate } 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate /* 1610*7c478bd9Sstevel@tonic-gate * setdomain - set domain name to append to hostname. Returns 1 upon 1611*7c478bd9Sstevel@tonic-gate * successful processing of options, and 0 otherwise. 1612*7c478bd9Sstevel@tonic-gate */ 1613*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1614*7c478bd9Sstevel@tonic-gate static int 1615*7c478bd9Sstevel@tonic-gate setdomain(argv, opt) 1616*7c478bd9Sstevel@tonic-gate char **argv; 1617*7c478bd9Sstevel@tonic-gate option_t *opt; 1618*7c478bd9Sstevel@tonic-gate { 1619*7c478bd9Sstevel@tonic-gate if (!privileged_option) { 1620*7c478bd9Sstevel@tonic-gate option_error("using the domain option requires root privilege"); 1621*7c478bd9Sstevel@tonic-gate return (0); 1622*7c478bd9Sstevel@tonic-gate } 1623*7c478bd9Sstevel@tonic-gate (void) gethostname(hostname, MAXHOSTNAMELEN+1); 1624*7c478bd9Sstevel@tonic-gate if (**argv != '\0') { 1625*7c478bd9Sstevel@tonic-gate if (**argv != '.') 1626*7c478bd9Sstevel@tonic-gate (void) strncat(hostname, ".", MAXHOSTNAMELEN - strlen(hostname)); 1627*7c478bd9Sstevel@tonic-gate (void) strncat(hostname, *argv, MAXHOSTNAMELEN - strlen(hostname)); 1628*7c478bd9Sstevel@tonic-gate } 1629*7c478bd9Sstevel@tonic-gate hostname[MAXHOSTNAMELEN] = '\0'; 1630*7c478bd9Sstevel@tonic-gate return (1); 1631*7c478bd9Sstevel@tonic-gate } 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate /* 1635*7c478bd9Sstevel@tonic-gate * setspeed - set the speed. Returns 1 upon successful processing of options, 1636*7c478bd9Sstevel@tonic-gate * and 0 otherwise. 1637*7c478bd9Sstevel@tonic-gate */ 1638*7c478bd9Sstevel@tonic-gate static int 1639*7c478bd9Sstevel@tonic-gate setspeed(arg) 1640*7c478bd9Sstevel@tonic-gate char *arg; 1641*7c478bd9Sstevel@tonic-gate { 1642*7c478bd9Sstevel@tonic-gate char *ptr; 1643*7c478bd9Sstevel@tonic-gate int spd; 1644*7c478bd9Sstevel@tonic-gate 1645*7c478bd9Sstevel@tonic-gate if (prepass) 1646*7c478bd9Sstevel@tonic-gate return (1); 1647*7c478bd9Sstevel@tonic-gate spd = strtol(arg, &ptr, 0); 1648*7c478bd9Sstevel@tonic-gate if (ptr == arg || *ptr != '\0' || spd <= 0) 1649*7c478bd9Sstevel@tonic-gate return (0); 1650*7c478bd9Sstevel@tonic-gate inspeed = spd; 1651*7c478bd9Sstevel@tonic-gate save_source(&speed_info); 1652*7c478bd9Sstevel@tonic-gate return (1); 1653*7c478bd9Sstevel@tonic-gate } 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate 1656*7c478bd9Sstevel@tonic-gate /* 1657*7c478bd9Sstevel@tonic-gate * setdevname - set the device name. Returns 1 upon successful processing of 1658*7c478bd9Sstevel@tonic-gate * options, 0 when the device does not exist, and -1 when an error is 1659*7c478bd9Sstevel@tonic-gate * encountered. 1660*7c478bd9Sstevel@tonic-gate */ 1661*7c478bd9Sstevel@tonic-gate static int 1662*7c478bd9Sstevel@tonic-gate setdevname(cp) 1663*7c478bd9Sstevel@tonic-gate char *cp; 1664*7c478bd9Sstevel@tonic-gate { 1665*7c478bd9Sstevel@tonic-gate struct stat statbuf; 1666*7c478bd9Sstevel@tonic-gate char dev[MAXPATHLEN]; 1667*7c478bd9Sstevel@tonic-gate 1668*7c478bd9Sstevel@tonic-gate if (*cp == '\0') 1669*7c478bd9Sstevel@tonic-gate return (0); 1670*7c478bd9Sstevel@tonic-gate 1671*7c478bd9Sstevel@tonic-gate if (strncmp("/dev/", cp, 5) != 0) { 1672*7c478bd9Sstevel@tonic-gate (void) strlcpy(dev, "/dev/", sizeof(dev)); 1673*7c478bd9Sstevel@tonic-gate (void) strlcat(dev, cp, sizeof(dev)); 1674*7c478bd9Sstevel@tonic-gate cp = dev; 1675*7c478bd9Sstevel@tonic-gate } 1676*7c478bd9Sstevel@tonic-gate 1677*7c478bd9Sstevel@tonic-gate /* 1678*7c478bd9Sstevel@tonic-gate * Check if there is a character device by this name. 1679*7c478bd9Sstevel@tonic-gate */ 1680*7c478bd9Sstevel@tonic-gate if (stat(cp, &statbuf) < 0) { 1681*7c478bd9Sstevel@tonic-gate if (errno == ENOENT) { 1682*7c478bd9Sstevel@tonic-gate return (0); 1683*7c478bd9Sstevel@tonic-gate } 1684*7c478bd9Sstevel@tonic-gate option_error("Couldn't stat '%s': %m", cp); 1685*7c478bd9Sstevel@tonic-gate return (-1); 1686*7c478bd9Sstevel@tonic-gate } 1687*7c478bd9Sstevel@tonic-gate if (!S_ISCHR(statbuf.st_mode)) { 1688*7c478bd9Sstevel@tonic-gate option_error("'%s' is not a character device", cp); 1689*7c478bd9Sstevel@tonic-gate return (-1); 1690*7c478bd9Sstevel@tonic-gate } 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate if (phase != PHASE_INITIALIZE) { 1693*7c478bd9Sstevel@tonic-gate option_error("device name cannot be changed after initialization"); 1694*7c478bd9Sstevel@tonic-gate return (-1); 1695*7c478bd9Sstevel@tonic-gate } else if (devnam_fixed) { 1696*7c478bd9Sstevel@tonic-gate option_error("per-tty options file may not specify device name"); 1697*7c478bd9Sstevel@tonic-gate return (-1); 1698*7c478bd9Sstevel@tonic-gate } 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate if (devnam_info.priv && !privileged_option) { 1701*7c478bd9Sstevel@tonic-gate option_error("device name %s from %s cannot be overridden", 1702*7c478bd9Sstevel@tonic-gate devnam, name_source(&devnam_info)); 1703*7c478bd9Sstevel@tonic-gate return (-1); 1704*7c478bd9Sstevel@tonic-gate } 1705*7c478bd9Sstevel@tonic-gate 1706*7c478bd9Sstevel@tonic-gate (void) strlcpy(devnam, cp, sizeof(devnam)); 1707*7c478bd9Sstevel@tonic-gate devstat = statbuf; 1708*7c478bd9Sstevel@tonic-gate default_device = 0; 1709*7c478bd9Sstevel@tonic-gate save_source(&devnam_info); 1710*7c478bd9Sstevel@tonic-gate 1711*7c478bd9Sstevel@tonic-gate return (1); 1712*7c478bd9Sstevel@tonic-gate } 1713*7c478bd9Sstevel@tonic-gate 1714*7c478bd9Sstevel@tonic-gate 1715*7c478bd9Sstevel@tonic-gate /* 1716*7c478bd9Sstevel@tonic-gate * setipaddr - set the IP address. Returns 1 upon successful processing of 1717*7c478bd9Sstevel@tonic-gate * options, 0 when the argument does not contain a `:', and -1 for error. 1718*7c478bd9Sstevel@tonic-gate */ 1719*7c478bd9Sstevel@tonic-gate static int 1720*7c478bd9Sstevel@tonic-gate setipaddr(arg) 1721*7c478bd9Sstevel@tonic-gate char *arg; 1722*7c478bd9Sstevel@tonic-gate { 1723*7c478bd9Sstevel@tonic-gate struct hostent *hp; 1724*7c478bd9Sstevel@tonic-gate char *colon; 1725*7c478bd9Sstevel@tonic-gate u_int32_t local, remote; 1726*7c478bd9Sstevel@tonic-gate ipcp_options *wo = &ipcp_wantoptions[0]; 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate /* 1729*7c478bd9Sstevel@tonic-gate * IP address pair separated by ":". 1730*7c478bd9Sstevel@tonic-gate */ 1731*7c478bd9Sstevel@tonic-gate if ((colon = strchr(arg, ':')) == NULL) 1732*7c478bd9Sstevel@tonic-gate return (0); 1733*7c478bd9Sstevel@tonic-gate if (prepass) 1734*7c478bd9Sstevel@tonic-gate return (1); 1735*7c478bd9Sstevel@tonic-gate 1736*7c478bd9Sstevel@tonic-gate /* 1737*7c478bd9Sstevel@tonic-gate * If colon first character, then no local addr. 1738*7c478bd9Sstevel@tonic-gate */ 1739*7c478bd9Sstevel@tonic-gate if (colon != arg) { 1740*7c478bd9Sstevel@tonic-gate *colon = '\0'; 1741*7c478bd9Sstevel@tonic-gate if ((local = inet_addr(arg)) == (u_int32_t) -1) { 1742*7c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(arg)) == NULL) { 1743*7c478bd9Sstevel@tonic-gate option_error("unknown host: %s", arg); 1744*7c478bd9Sstevel@tonic-gate return (-1); 1745*7c478bd9Sstevel@tonic-gate } else { 1746*7c478bd9Sstevel@tonic-gate BCOPY(hp->h_addr, &local, sizeof(local)); 1747*7c478bd9Sstevel@tonic-gate } 1748*7c478bd9Sstevel@tonic-gate } 1749*7c478bd9Sstevel@tonic-gate if (bad_ip_adrs(local)) { 1750*7c478bd9Sstevel@tonic-gate option_error("bad local IP address %I", local); 1751*7c478bd9Sstevel@tonic-gate return (-1); 1752*7c478bd9Sstevel@tonic-gate } 1753*7c478bd9Sstevel@tonic-gate if (local != 0) { 1754*7c478bd9Sstevel@tonic-gate save_source(&ipsrc_info); 1755*7c478bd9Sstevel@tonic-gate wo->ouraddr = local; 1756*7c478bd9Sstevel@tonic-gate } 1757*7c478bd9Sstevel@tonic-gate *colon = ':'; 1758*7c478bd9Sstevel@tonic-gate } 1759*7c478bd9Sstevel@tonic-gate 1760*7c478bd9Sstevel@tonic-gate /* 1761*7c478bd9Sstevel@tonic-gate * If colon last character, then no remote addr. 1762*7c478bd9Sstevel@tonic-gate */ 1763*7c478bd9Sstevel@tonic-gate if (*++colon != '\0') { 1764*7c478bd9Sstevel@tonic-gate if ((remote = inet_addr(colon)) == (u_int32_t) -1) { 1765*7c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(colon)) == NULL) { 1766*7c478bd9Sstevel@tonic-gate option_error("unknown host: %s", colon); 1767*7c478bd9Sstevel@tonic-gate return (-1); 1768*7c478bd9Sstevel@tonic-gate } else { 1769*7c478bd9Sstevel@tonic-gate BCOPY(hp->h_addr, &remote, sizeof(remote)); 1770*7c478bd9Sstevel@tonic-gate if (remote_name[0] == '\0') 1771*7c478bd9Sstevel@tonic-gate (void) strlcpy(remote_name, colon, sizeof(remote_name)); 1772*7c478bd9Sstevel@tonic-gate } 1773*7c478bd9Sstevel@tonic-gate } 1774*7c478bd9Sstevel@tonic-gate if (bad_ip_adrs(remote)) { 1775*7c478bd9Sstevel@tonic-gate option_error("bad remote IP address %I", remote); 1776*7c478bd9Sstevel@tonic-gate return (-1); 1777*7c478bd9Sstevel@tonic-gate } 1778*7c478bd9Sstevel@tonic-gate if (remote != 0) { 1779*7c478bd9Sstevel@tonic-gate save_source(&ipdst_info); 1780*7c478bd9Sstevel@tonic-gate wo->hisaddr = remote; 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate } 1783*7c478bd9Sstevel@tonic-gate 1784*7c478bd9Sstevel@tonic-gate return (1); 1785*7c478bd9Sstevel@tonic-gate } 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate /* 1789*7c478bd9Sstevel@tonic-gate * setnetmask - set the netmask to be used on the interface. Returns 1 upon 1790*7c478bd9Sstevel@tonic-gate * successful processing of options, and 0 otherwise. 1791*7c478bd9Sstevel@tonic-gate */ 1792*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1793*7c478bd9Sstevel@tonic-gate static int 1794*7c478bd9Sstevel@tonic-gate setnetmask(argv, opt) 1795*7c478bd9Sstevel@tonic-gate char **argv; 1796*7c478bd9Sstevel@tonic-gate option_t *opt; 1797*7c478bd9Sstevel@tonic-gate { 1798*7c478bd9Sstevel@tonic-gate u_int32_t mask; 1799*7c478bd9Sstevel@tonic-gate int n; 1800*7c478bd9Sstevel@tonic-gate char *p; 1801*7c478bd9Sstevel@tonic-gate 1802*7c478bd9Sstevel@tonic-gate /* 1803*7c478bd9Sstevel@tonic-gate * Unfortunately, if we use inet_addr, we can't tell whether 1804*7c478bd9Sstevel@tonic-gate * a result of all 1s is an error or a valid 255.255.255.255. 1805*7c478bd9Sstevel@tonic-gate */ 1806*7c478bd9Sstevel@tonic-gate p = *argv; 1807*7c478bd9Sstevel@tonic-gate n = parse_dotted_ip(p, &mask); 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate mask = htonl(mask); 1810*7c478bd9Sstevel@tonic-gate 1811*7c478bd9Sstevel@tonic-gate if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { 1812*7c478bd9Sstevel@tonic-gate option_error("invalid netmask value '%s'", *argv); 1813*7c478bd9Sstevel@tonic-gate return (0); 1814*7c478bd9Sstevel@tonic-gate } 1815*7c478bd9Sstevel@tonic-gate 1816*7c478bd9Sstevel@tonic-gate netmask = mask; 1817*7c478bd9Sstevel@tonic-gate return (1); 1818*7c478bd9Sstevel@tonic-gate } 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate /* 1821*7c478bd9Sstevel@tonic-gate * parse_dotted_ip - parse and convert the IP address string to make 1822*7c478bd9Sstevel@tonic-gate * sure it conforms to the dotted notation. Returns the length of 1823*7c478bd9Sstevel@tonic-gate * processed characters upon success, and 0 otherwise. If successful, 1824*7c478bd9Sstevel@tonic-gate * the converted IP address number is stored in vp, in the host byte 1825*7c478bd9Sstevel@tonic-gate * order. 1826*7c478bd9Sstevel@tonic-gate */ 1827*7c478bd9Sstevel@tonic-gate int 1828*7c478bd9Sstevel@tonic-gate parse_dotted_ip(cp, vp) 1829*7c478bd9Sstevel@tonic-gate register char *cp; 1830*7c478bd9Sstevel@tonic-gate u_int32_t *vp; 1831*7c478bd9Sstevel@tonic-gate { 1832*7c478bd9Sstevel@tonic-gate register u_int32_t val, base, n; 1833*7c478bd9Sstevel@tonic-gate register char c; 1834*7c478bd9Sstevel@tonic-gate char *cp0 = cp; 1835*7c478bd9Sstevel@tonic-gate u_char parts[3], *pp = parts; 1836*7c478bd9Sstevel@tonic-gate 1837*7c478bd9Sstevel@tonic-gate if ((*cp == '\0') || (vp == NULL)) 1838*7c478bd9Sstevel@tonic-gate return (0); /* disallow null string in cp */ 1839*7c478bd9Sstevel@tonic-gate *vp = 0; 1840*7c478bd9Sstevel@tonic-gate again: 1841*7c478bd9Sstevel@tonic-gate /* 1842*7c478bd9Sstevel@tonic-gate * Collect number up to ``.''. Values are specified as for C: 1843*7c478bd9Sstevel@tonic-gate * 0x=hex, 0=octal, other=decimal. 1844*7c478bd9Sstevel@tonic-gate */ 1845*7c478bd9Sstevel@tonic-gate val = 0; base = 10; 1846*7c478bd9Sstevel@tonic-gate if (*cp == '0') { 1847*7c478bd9Sstevel@tonic-gate if (*++cp == 'x' || *cp == 'X') 1848*7c478bd9Sstevel@tonic-gate base = 16, cp++; 1849*7c478bd9Sstevel@tonic-gate else 1850*7c478bd9Sstevel@tonic-gate base = 8; 1851*7c478bd9Sstevel@tonic-gate } 1852*7c478bd9Sstevel@tonic-gate while ((c = *cp) != '\0') { 1853*7c478bd9Sstevel@tonic-gate if (isdigit(c)) { 1854*7c478bd9Sstevel@tonic-gate if ((c - '0') >= base) 1855*7c478bd9Sstevel@tonic-gate break; 1856*7c478bd9Sstevel@tonic-gate val = (val * base) + (c - '0'); 1857*7c478bd9Sstevel@tonic-gate cp++; 1858*7c478bd9Sstevel@tonic-gate continue; 1859*7c478bd9Sstevel@tonic-gate } 1860*7c478bd9Sstevel@tonic-gate if (base == 16 && isxdigit(c)) { 1861*7c478bd9Sstevel@tonic-gate val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); 1862*7c478bd9Sstevel@tonic-gate cp++; 1863*7c478bd9Sstevel@tonic-gate continue; 1864*7c478bd9Sstevel@tonic-gate } 1865*7c478bd9Sstevel@tonic-gate break; 1866*7c478bd9Sstevel@tonic-gate } 1867*7c478bd9Sstevel@tonic-gate if (*cp == '.') { 1868*7c478bd9Sstevel@tonic-gate /* 1869*7c478bd9Sstevel@tonic-gate * Internet format: 1870*7c478bd9Sstevel@tonic-gate * a.b.c.d 1871*7c478bd9Sstevel@tonic-gate * a.b.c (with c treated as 16-bits) 1872*7c478bd9Sstevel@tonic-gate * a.b (with b treated as 24 bits) 1873*7c478bd9Sstevel@tonic-gate */ 1874*7c478bd9Sstevel@tonic-gate if ((pp >= parts + 3) || (val > 0xff)) { 1875*7c478bd9Sstevel@tonic-gate return (0); 1876*7c478bd9Sstevel@tonic-gate } 1877*7c478bd9Sstevel@tonic-gate *pp++ = (u_char)val; 1878*7c478bd9Sstevel@tonic-gate cp++; 1879*7c478bd9Sstevel@tonic-gate goto again; 1880*7c478bd9Sstevel@tonic-gate } 1881*7c478bd9Sstevel@tonic-gate /* 1882*7c478bd9Sstevel@tonic-gate * Check for trailing characters. 1883*7c478bd9Sstevel@tonic-gate */ 1884*7c478bd9Sstevel@tonic-gate if (*cp != '\0' && !isspace(*cp)) { 1885*7c478bd9Sstevel@tonic-gate return (0); 1886*7c478bd9Sstevel@tonic-gate } 1887*7c478bd9Sstevel@tonic-gate /* 1888*7c478bd9Sstevel@tonic-gate * Concoct the address according to the number of parts specified. 1889*7c478bd9Sstevel@tonic-gate */ 1890*7c478bd9Sstevel@tonic-gate n = pp - parts; 1891*7c478bd9Sstevel@tonic-gate switch (n) { 1892*7c478bd9Sstevel@tonic-gate case 0: /* a -- 32 bits */ 1893*7c478bd9Sstevel@tonic-gate break; 1894*7c478bd9Sstevel@tonic-gate case 1: /* a.b -- 8.24 bits */ 1895*7c478bd9Sstevel@tonic-gate if (val > 0xffffff) 1896*7c478bd9Sstevel@tonic-gate return (0); 1897*7c478bd9Sstevel@tonic-gate val |= parts[0] << 24; 1898*7c478bd9Sstevel@tonic-gate break; 1899*7c478bd9Sstevel@tonic-gate case 2: /* a.b.c -- 8.8.16 bits */ 1900*7c478bd9Sstevel@tonic-gate if (val > 0xffff) 1901*7c478bd9Sstevel@tonic-gate return (0); 1902*7c478bd9Sstevel@tonic-gate val |= (parts[0] << 24) | (parts[1] << 16); 1903*7c478bd9Sstevel@tonic-gate break; 1904*7c478bd9Sstevel@tonic-gate case 3: /* a.b.c.d -- 8.8.8.8 bits */ 1905*7c478bd9Sstevel@tonic-gate if (val > 0xff) 1906*7c478bd9Sstevel@tonic-gate return (0); 1907*7c478bd9Sstevel@tonic-gate val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 1908*7c478bd9Sstevel@tonic-gate break; 1909*7c478bd9Sstevel@tonic-gate default: 1910*7c478bd9Sstevel@tonic-gate return (0); 1911*7c478bd9Sstevel@tonic-gate } 1912*7c478bd9Sstevel@tonic-gate *vp = val; 1913*7c478bd9Sstevel@tonic-gate return (cp - cp0); 1914*7c478bd9Sstevel@tonic-gate } 1915*7c478bd9Sstevel@tonic-gate 1916*7c478bd9Sstevel@tonic-gate /* 1917*7c478bd9Sstevel@tonic-gate * setxonxoff - modify the asyncmap to include escaping XON and XOFF 1918*7c478bd9Sstevel@tonic-gate * characters used for software flow control. Returns 1 upon successful 1919*7c478bd9Sstevel@tonic-gate * processing of options, and 0 otherwise. 1920*7c478bd9Sstevel@tonic-gate */ 1921*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1922*7c478bd9Sstevel@tonic-gate static int 1923*7c478bd9Sstevel@tonic-gate setxonxoff(argv, opt) 1924*7c478bd9Sstevel@tonic-gate char **argv; 1925*7c478bd9Sstevel@tonic-gate option_t *opt; 1926*7c478bd9Sstevel@tonic-gate { 1927*7c478bd9Sstevel@tonic-gate int xonxoff = 0x000A0000; 1928*7c478bd9Sstevel@tonic-gate 1929*7c478bd9Sstevel@tonic-gate lcp_wantoptions[0].neg_asyncmap = 1; 1930*7c478bd9Sstevel@tonic-gate lcp_wantoptions[0].asyncmap |= xonxoff; /* escape ^S and ^Q */ 1931*7c478bd9Sstevel@tonic-gate lcp_allowoptions[0].asyncmap |= xonxoff; 1932*7c478bd9Sstevel@tonic-gate xmit_accm[0][0] |= xonxoff; 1933*7c478bd9Sstevel@tonic-gate xmit_accm[0][4] |= xonxoff; /* escape 0x91 and 0x93 as well */ 1934*7c478bd9Sstevel@tonic-gate 1935*7c478bd9Sstevel@tonic-gate crtscts = -2; 1936*7c478bd9Sstevel@tonic-gate return (1); 1937*7c478bd9Sstevel@tonic-gate } 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate /* 1940*7c478bd9Sstevel@tonic-gate * setlogfile - open (or create) a file used for logging purposes. Returns 1 1941*7c478bd9Sstevel@tonic-gate * upon success, and 0 otherwise. 1942*7c478bd9Sstevel@tonic-gate */ 1943*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1944*7c478bd9Sstevel@tonic-gate static int 1945*7c478bd9Sstevel@tonic-gate setlogfile(argv, opt) 1946*7c478bd9Sstevel@tonic-gate char **argv; 1947*7c478bd9Sstevel@tonic-gate option_t *opt; 1948*7c478bd9Sstevel@tonic-gate { 1949*7c478bd9Sstevel@tonic-gate int fd, err; 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate if (!privileged_option) 1952*7c478bd9Sstevel@tonic-gate (void) seteuid(getuid()); 1953*7c478bd9Sstevel@tonic-gate fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644); 1954*7c478bd9Sstevel@tonic-gate if (fd < 0 && errno == EEXIST) 1955*7c478bd9Sstevel@tonic-gate fd = open(*argv, O_WRONLY | O_APPEND); 1956*7c478bd9Sstevel@tonic-gate err = errno; 1957*7c478bd9Sstevel@tonic-gate if (!privileged_option) 1958*7c478bd9Sstevel@tonic-gate (void) seteuid(0); 1959*7c478bd9Sstevel@tonic-gate if (fd < 0) { 1960*7c478bd9Sstevel@tonic-gate errno = err; 1961*7c478bd9Sstevel@tonic-gate option_error("Can't open log file %s: %m", *argv); 1962*7c478bd9Sstevel@tonic-gate return (0); 1963*7c478bd9Sstevel@tonic-gate } 1964*7c478bd9Sstevel@tonic-gate if (log_to_file && log_to_fd >= 0) 1965*7c478bd9Sstevel@tonic-gate (void) close(log_to_fd); 1966*7c478bd9Sstevel@tonic-gate log_to_fd = fd; 1967*7c478bd9Sstevel@tonic-gate log_to_file = 1; 1968*7c478bd9Sstevel@tonic-gate early_log = 0; 1969*7c478bd9Sstevel@tonic-gate return (1); 1970*7c478bd9Sstevel@tonic-gate } 1971*7c478bd9Sstevel@tonic-gate 1972*7c478bd9Sstevel@tonic-gate #ifdef PLUGIN 1973*7c478bd9Sstevel@tonic-gate /* 1974*7c478bd9Sstevel@tonic-gate * loadplugin - load and initialize the plugin. Returns 1 upon successful 1975*7c478bd9Sstevel@tonic-gate * processing of the plugin, and 0 otherwise. 1976*7c478bd9Sstevel@tonic-gate */ 1977*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1978*7c478bd9Sstevel@tonic-gate static int 1979*7c478bd9Sstevel@tonic-gate loadplugin(argv, opt) 1980*7c478bd9Sstevel@tonic-gate char **argv; 1981*7c478bd9Sstevel@tonic-gate option_t *opt; 1982*7c478bd9Sstevel@tonic-gate { 1983*7c478bd9Sstevel@tonic-gate char *arg = *argv; 1984*7c478bd9Sstevel@tonic-gate void *handle; 1985*7c478bd9Sstevel@tonic-gate const char *err; 1986*7c478bd9Sstevel@tonic-gate void (*init) __P((void)); 1987*7c478bd9Sstevel@tonic-gate 1988*7c478bd9Sstevel@tonic-gate handle = dlopen(arg, RTLD_GLOBAL | RTLD_NOW); 1989*7c478bd9Sstevel@tonic-gate if (handle == NULL) { 1990*7c478bd9Sstevel@tonic-gate err = dlerror(); 1991*7c478bd9Sstevel@tonic-gate if (err != NULL) 1992*7c478bd9Sstevel@tonic-gate option_error("%s", err); 1993*7c478bd9Sstevel@tonic-gate option_error("Couldn't load plugin %s", arg); 1994*7c478bd9Sstevel@tonic-gate return (0); 1995*7c478bd9Sstevel@tonic-gate } 1996*7c478bd9Sstevel@tonic-gate init = (void (*)(void))dlsym(handle, "plugin_init"); 1997*7c478bd9Sstevel@tonic-gate if (init == NULL) { 1998*7c478bd9Sstevel@tonic-gate option_error("%s has no initialization entry point", arg); 1999*7c478bd9Sstevel@tonic-gate (void) dlclose(handle); 2000*7c478bd9Sstevel@tonic-gate return (0); 2001*7c478bd9Sstevel@tonic-gate } 2002*7c478bd9Sstevel@tonic-gate info("Plugin %s loaded.", arg); 2003*7c478bd9Sstevel@tonic-gate (*init)(); 2004*7c478bd9Sstevel@tonic-gate return (1); 2005*7c478bd9Sstevel@tonic-gate } 2006*7c478bd9Sstevel@tonic-gate #endif /* PLUGIN */ 2007