options.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798
  1. /*
  2. * options.c - handles option processing for PPP.
  3. *
  4. * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. *
  18. * 3. The name "Carnegie Mellon University" must not be used to
  19. * endorse or promote products derived from this software without
  20. * prior written permission. For permission or any legal
  21. * details, please contact
  22. * Office of Technology Transfer
  23. * Carnegie Mellon University
  24. * 5000 Forbes Avenue
  25. * Pittsburgh, PA 15213-3890
  26. * (412) 268-4387, fax: (412) 268-7395
  27. * tech-transfer@andrew.cmu.edu
  28. *
  29. * 4. Redistributions of any form whatsoever must retain the following
  30. * acknowledgment:
  31. * "This product includes software developed by Computing Services
  32. * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
  33. *
  34. * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
  35. * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  36. * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
  37. * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  38. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  39. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  40. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41. */
  42. #define RCSID "$Id: options.c,v 1.102 2008/06/15 06:53:06 paulus Exp $"
  43. #include <ctype.h>
  44. #include <stdio.h>
  45. #include <errno.h>
  46. #include <unistd.h>
  47. #include <fcntl.h>
  48. #include <stdlib.h>
  49. #include <syslog.h>
  50. #include <string.h>
  51. #include <pwd.h>
  52. #ifdef PLUGIN
  53. #include <dlfcn.h>
  54. #endif
  55. #ifdef PPP_FILTER
  56. #include <pcap.h>
  57. /*
  58. * There have been 3 or 4 different names for this in libpcap CVS, but
  59. * this seems to be what they have settled on...
  60. * For older versions of libpcap, use DLT_PPP - but that means
  61. * we lose the inbound and outbound qualifiers.
  62. */
  63. #ifndef DLT_PPP_PPPD
  64. #ifdef DLT_PPP_WITHDIRECTION
  65. #define DLT_PPP_PPPD DLT_PPP_WITHDIRECTION
  66. #else
  67. #define DLT_PPP_PPPD DLT_PPP
  68. #endif
  69. #endif
  70. #endif /* PPP_FILTER */
  71. #include "pppd.h"
  72. #include "pathnames.h"
  73. #if defined(ultrix) || defined(NeXT)
  74. char *strdup __P((char *));
  75. #endif
  76. static const char rcsid[] = RCSID;
  77. struct option_value {
  78. struct option_value *next;
  79. const char *source;
  80. char value[1];
  81. };
  82. /*
  83. * Option variables and default values.
  84. */
  85. int debug = 0; /* Debug flag */
  86. int kdebugflag = 0; /* Tell kernel to print debug messages */
  87. int default_device = 1; /* Using /dev/tty or equivalent */
  88. char devnam[MAXPATHLEN]; /* Device name */
  89. bool nodetach = 0; /* Don't detach from controlling tty */
  90. bool updetach = 0; /* Detach once link is up */
  91. bool master_detach; /* Detach when we're (only) multilink master */
  92. int maxconnect = 0; /* Maximum connect time */
  93. char user[MAXNAMELEN]; /* Username for PAP */
  94. char passwd[MAXSECRETLEN]; /* Password for PAP */
  95. bool persist = 0; /* Reopen link after it goes down */
  96. char our_name[MAXNAMELEN]; /* Our name for authentication purposes */
  97. bool demand = 0; /* do dial-on-demand */
  98. char *ipparam = NULL; /* Extra parameter for ip up/down scripts */
  99. int idle_time_limit = 0; /* Disconnect if idle for this many seconds */
  100. int holdoff = 30; /* # seconds to pause before reconnecting */
  101. bool holdoff_specified; /* true if a holdoff value has been given */
  102. int log_to_fd = 1; /* send log messages to this fd too */
  103. bool log_default = 1; /* log_to_fd is default (stdout) */
  104. int maxfail = 10; /* max # of unsuccessful connection attempts */
  105. char linkname[MAXPATHLEN]; /* logical name for link */
  106. bool tune_kernel; /* may alter kernel settings */
  107. int connect_delay = 1000; /* wait this many ms after connect script */
  108. int req_unit = -1; /* requested interface unit */
  109. bool multilink = 0; /* Enable multilink operation */
  110. char *bundle_name = NULL; /* bundle name for multilink */
  111. bool dump_options; /* print out option values */
  112. bool dryrun; /* print out option values and exit */
  113. char *domain; /* domain name set by domain option */
  114. int child_wait = 5; /* # seconds to wait for children at exit */
  115. struct userenv *userenv_list; /* user environment variables */
  116. #ifdef MAXOCTETS
  117. unsigned int maxoctets = 0; /* default - no limit */
  118. int maxoctets_dir = 0; /* default - sum of traffic */
  119. int maxoctets_timeout = 1; /* default 1 second */
  120. #endif
  121. extern option_t auth_options[];
  122. extern struct stat devstat;
  123. #ifdef PPP_FILTER
  124. struct bpf_program pass_filter;/* Filter program for packets to pass */
  125. struct bpf_program active_filter; /* Filter program for link-active pkts */
  126. #endif
  127. static option_t *curopt; /* pointer to option being processed */
  128. char *current_option; /* the name of the option being parsed */
  129. int privileged_option; /* set iff the current option came from root */
  130. char *option_source; /* string saying where the option came from */
  131. int option_priority = OPRIO_CFGFILE; /* priority of the current options */
  132. bool devnam_fixed; /* can no longer change device name */
  133. static int logfile_fd = -1; /* fd opened for log file */
  134. static char logfile_name[MAXPATHLEN]; /* name of log file */
  135. /*
  136. * Prototypes
  137. */
  138. static int setdomain __P((char **));
  139. static int readfile __P((char **));
  140. static int callfile __P((char **));
  141. static int showversion __P((char **));
  142. static int showhelp __P((char **));
  143. static void usage __P((void));
  144. static int setlogfile __P((char **));
  145. #ifdef PLUGIN
  146. static int loadplugin __P((char **));
  147. #endif
  148. #ifdef PPP_FILTER
  149. static int setpassfilter __P((char **));
  150. static int setactivefilter __P((char **));
  151. #endif
  152. #ifdef MAXOCTETS
  153. static int setmodir __P((char **));
  154. #endif
  155. static int user_setenv __P((char **));
  156. static void user_setprint __P((option_t *, printer_func, void *));
  157. static int user_unsetenv __P((char **));
  158. static void user_unsetprint __P((option_t *, printer_func, void *));
  159. static option_t *find_option __P((const char *name));
  160. static int process_option __P((option_t *, char *, char **));
  161. static int n_arguments __P((option_t *));
  162. static int number_option __P((char *, u_int32_t *, int));
  163. /*
  164. * Structure to store extra lists of options.
  165. */
  166. struct option_list {
  167. option_t *options;
  168. struct option_list *next;
  169. };
  170. static struct option_list *extra_options = NULL;
  171. /*
  172. * Valid arguments.
  173. */
  174. option_t general_options[] = {
  175. { "debug", o_int, &debug,
  176. "Increase debugging level", OPT_INC | OPT_NOARG | 1 },
  177. { "-d", o_int, &debug,
  178. "Increase debugging level",
  179. OPT_ALIAS | OPT_INC | OPT_NOARG | 1 },
  180. { "kdebug", o_int, &kdebugflag,
  181. "Set kernel driver debug level", OPT_PRIO },
  182. { "nodetach", o_bool, &nodetach,
  183. "Don't detach from controlling tty", OPT_PRIO | 1 },
  184. { "-detach", o_bool, &nodetach,
  185. "Don't detach from controlling tty", OPT_ALIAS | OPT_PRIOSUB | 1 },
  186. { "updetach", o_bool, &updetach,
  187. "Detach from controlling tty once link is up",
  188. OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach },
  189. { "master_detach", o_bool, &master_detach,
  190. "Detach when we're multilink master but have no link", 1 },
  191. { "holdoff", o_int, &holdoff,
  192. "Set time in seconds before retrying connection",
  193. OPT_PRIO, &holdoff_specified },
  194. { "idle", o_int, &idle_time_limit,
  195. "Set time in seconds before disconnecting idle link", OPT_PRIO },
  196. { "maxconnect", o_int, &maxconnect,
  197. "Set connection time limit",
  198. OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
  199. { "domain", o_special, (void *)setdomain,
  200. "Add given domain name to hostname",
  201. OPT_PRIO | OPT_PRIV | OPT_A2STRVAL, &domain },
  202. { "file", o_special, (void *)readfile,
  203. "Take options from a file", OPT_NOPRINT },
  204. { "call", o_special, (void *)callfile,
  205. "Take options from a privileged file", OPT_NOPRINT },
  206. { "persist", o_bool, &persist,
  207. "Keep on reopening connection after close", OPT_PRIO | 1 },
  208. { "nopersist", o_bool, &persist,
  209. "Turn off persist option", OPT_PRIOSUB },
  210. { "demand", o_bool, &demand,
  211. "Dial on demand", OPT_INITONLY | 1, &persist },
  212. { "--version", o_special_noarg, (void *)showversion,
  213. "Show version number" },
  214. { "--help", o_special_noarg, (void *)showhelp,
  215. "Show brief listing of options" },
  216. { "-h", o_special_noarg, (void *)showhelp,
  217. "Show brief listing of options", OPT_ALIAS },
  218. { "logfile", o_special, (void *)setlogfile,
  219. "Append log messages to this file",
  220. OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, &logfile_name },
  221. { "logfd", o_int, &log_to_fd,
  222. "Send log messages to this file descriptor",
  223. OPT_PRIOSUB | OPT_A2CLR, &log_default },
  224. { "nolog", o_int, &log_to_fd,
  225. "Don't send log messages to any file",
  226. OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) },
  227. { "nologfd", o_int, &log_to_fd,
  228. "Don't send log messages to any file descriptor",
  229. OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) },
  230. { "linkname", o_string, linkname,
  231. "Set logical name for link",
  232. OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN },
  233. { "maxfail", o_int, &maxfail,
  234. "Maximum number of unsuccessful connection attempts to allow",
  235. OPT_PRIO },
  236. { "ktune", o_bool, &tune_kernel,
  237. "Alter kernel settings as necessary", OPT_PRIO | 1 },
  238. { "noktune", o_bool, &tune_kernel,
  239. "Don't alter kernel settings", OPT_PRIOSUB },
  240. { "connect-delay", o_int, &connect_delay,
  241. "Maximum time (in ms) to wait after connect script finishes",
  242. OPT_PRIO },
  243. { "unit", o_int, &req_unit,
  244. "PPP interface unit number to use if possible",
  245. OPT_PRIO | OPT_LLIMIT, 0, 0 },
  246. { "dump", o_bool, &dump_options,
  247. "Print out option values after parsing all options", 1 },
  248. { "dryrun", o_bool, &dryrun,
  249. "Stop after parsing, printing, and checking options", 1 },
  250. { "child-timeout", o_int, &child_wait,
  251. "Number of seconds to wait for child processes at exit",
  252. OPT_PRIO },
  253. { "set", o_special, (void *)user_setenv,
  254. "Set user environment variable",
  255. OPT_A2PRINTER | OPT_NOPRINT, (void *)user_setprint },
  256. { "unset", o_special, (void *)user_unsetenv,
  257. "Unset user environment variable",
  258. OPT_A2PRINTER | OPT_NOPRINT, (void *)user_unsetprint },
  259. #ifdef HAVE_MULTILINK
  260. { "multilink", o_bool, &multilink,
  261. "Enable multilink operation", OPT_PRIO | 1 },
  262. { "mp", o_bool, &multilink,
  263. "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 },
  264. { "nomultilink", o_bool, &multilink,
  265. "Disable multilink operation", OPT_PRIOSUB | 0 },
  266. { "nomp", o_bool, &multilink,
  267. "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },
  268. { "bundle", o_string, &bundle_name,
  269. "Bundle name for multilink", OPT_PRIO },
  270. #endif /* HAVE_MULTILINK */
  271. #ifdef PLUGIN
  272. { "plugin", o_special, (void *)loadplugin,
  273. "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST },
  274. #endif
  275. #ifdef PPP_FILTER
  276. { "pass-filter", o_special, setpassfilter,
  277. "set filter for packets to pass", OPT_PRIO },
  278. { "active-filter", o_special, setactivefilter,
  279. "set filter for active pkts", OPT_PRIO },
  280. #endif
  281. #ifdef MAXOCTETS
  282. { "maxoctets", o_int, &maxoctets,
  283. "Set connection traffic limit",
  284. OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
  285. { "mo", o_int, &maxoctets,
  286. "Set connection traffic limit",
  287. OPT_ALIAS | OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
  288. { "mo-direction", o_special, setmodir,
  289. "Set direction for limit traffic (sum,in,out,max)" },
  290. { "mo-timeout", o_int, &maxoctets_timeout,
  291. "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 },
  292. #endif
  293. { NULL }
  294. };
  295. #ifndef IMPLEMENTATION
  296. #define IMPLEMENTATION ""
  297. #endif
  298. static char *usage_string = "\
  299. pppd version %s\n\
  300. Usage: %s [ options ], where options are:\n\
  301. <device> Communicate over the named device\n\
  302. <speed> Set the baud rate to <speed>\n\
  303. <loc>:<rem> Set the local and/or remote interface IP\n\
  304. addresses. Either one may be omitted.\n\
  305. asyncmap <n> Set the desired async map to hex <n>\n\
  306. auth Require authentication from peer\n\
  307. connect <p> Invoke shell command <p> to set up the serial line\n\
  308. crtscts Use hardware RTS/CTS flow control\n\
  309. defaultroute Add default route through interface\n\
  310. file <f> Take options from file <f>\n\
  311. modem Use modem control lines\n\
  312. mru <n> Set MRU value to <n> for negotiation\n\
  313. See pppd(8) for more options.\n\
  314. ";
  315. /*
  316. * parse_args - parse a string of arguments from the command line.
  317. */
  318. int
  319. parse_args(argc, argv)
  320. int argc;
  321. char **argv;
  322. {
  323. char *arg;
  324. option_t *opt;
  325. int n;
  326. privileged_option = privileged;
  327. option_source = "command line";
  328. option_priority = OPRIO_CMDLINE;
  329. while (argc > 0) {
  330. arg = *argv++;
  331. --argc;
  332. opt = find_option(arg);
  333. if (opt == NULL) {
  334. option_error("unrecognized option '%s'", arg);
  335. usage();
  336. return 0;
  337. }
  338. n = n_arguments(opt);
  339. if (argc < n) {
  340. option_error("too few parameters for option %s", arg);
  341. return 0;
  342. }
  343. if (!process_option(opt, arg, argv))
  344. return 0;
  345. argc -= n;
  346. argv += n;
  347. }
  348. return 1;
  349. }
  350. /*
  351. * options_from_file - Read a string of options from a file,
  352. * and interpret them.
  353. */
  354. int
  355. options_from_file(filename, must_exist, check_prot, priv)
  356. char *filename;
  357. int must_exist;
  358. int check_prot;
  359. int priv;
  360. {
  361. FILE *f;
  362. int i, newline, ret, err;
  363. option_t *opt;
  364. int oldpriv, n;
  365. char *oldsource;
  366. uid_t euid;
  367. char *argv[MAXARGS];
  368. char args[MAXARGS][MAXWORDLEN];
  369. char cmd[MAXWORDLEN];
  370. euid = geteuid();
  371. if (check_prot && seteuid(getuid()) == -1) {
  372. option_error("unable to drop privileges to open %s: %m", filename);
  373. return 0;
  374. }
  375. f = fopen(filename, "r");
  376. err = errno;
  377. if (check_prot && seteuid(euid) == -1)
  378. fatal("unable to regain privileges");
  379. if (f == NULL) {
  380. errno = err;
  381. if (!must_exist) {
  382. if (err != ENOENT && err != ENOTDIR)
  383. warn("Warning: can't open options file %s: %m", filename);
  384. return 1;
  385. }
  386. option_error("Can't open options file %s: %m", filename);
  387. return 0;
  388. }
  389. oldpriv = privileged_option;
  390. privileged_option = priv;
  391. oldsource = option_source;
  392. option_source = strdup(filename);
  393. if (option_source == NULL)
  394. option_source = "file";
  395. ret = 0;
  396. while (getword(f, cmd, &newline, filename)) {
  397. opt = find_option(cmd);
  398. if (opt == NULL) {
  399. option_error("In file %s: unrecognized option '%s'",
  400. filename, cmd);
  401. goto err;
  402. }
  403. n = n_arguments(opt);
  404. for (i = 0; i < n; ++i) {
  405. if (!getword(f, args[i], &newline, filename)) {
  406. option_error(
  407. "In file %s: too few parameters for option '%s'",
  408. filename, cmd);
  409. goto err;
  410. }
  411. argv[i] = args[i];
  412. }
  413. if (!process_option(opt, cmd, argv))
  414. goto err;
  415. }
  416. ret = 1;
  417. err:
  418. fclose(f);
  419. privileged_option = oldpriv;
  420. option_source = oldsource;
  421. return ret;
  422. }
  423. /*
  424. * options_from_user - See if the use has a ~/.ppprc file,
  425. * and if so, interpret options from it.
  426. */
  427. int
  428. options_from_user()
  429. {
  430. char *user, *path, *file;
  431. int ret;
  432. struct passwd *pw;
  433. size_t pl;
  434. pw = getpwuid(getuid());
  435. if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0)
  436. return 1;
  437. file = _PATH_USEROPT;
  438. pl = strlen(user) + strlen(file) + 2;
  439. path = malloc(pl);
  440. if (path == NULL)
  441. novm("init file name");
  442. slprintf(path, pl, "%s/%s", user, file);
  443. option_priority = OPRIO_CFGFILE;
  444. ret = options_from_file(path, 0, 1, privileged);
  445. free(path);
  446. return ret;
  447. }
  448. /*
  449. * options_for_tty - See if an options file exists for the serial
  450. * device, and if so, interpret options from it.
  451. * We only allow the per-tty options file to override anything from
  452. * the command line if it is something that the user can't override
  453. * once it has been set by root; this is done by giving configuration
  454. * files a lower priority than the command line.
  455. */
  456. int
  457. options_for_tty()
  458. {
  459. char *dev, *path, *p;
  460. int ret;
  461. size_t pl;
  462. dev = devnam;
  463. if ((p = strstr(dev, "/dev/")) != NULL)
  464. dev = p + 5;
  465. if (dev[0] == 0 || strcmp(dev, "tty") == 0)
  466. return 1; /* don't look for /etc/ppp/options.tty */
  467. pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1;
  468. path = malloc(pl);
  469. if (path == NULL)
  470. novm("tty init file name");
  471. slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev);
  472. /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
  473. for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p)
  474. if (*p == '/')
  475. *p = '.';
  476. option_priority = OPRIO_CFGFILE;
  477. ret = options_from_file(path, 0, 0, 1);
  478. free(path);
  479. return ret;
  480. }
  481. /*
  482. * options_from_list - process a string of options in a wordlist.
  483. */
  484. int
  485. options_from_list(w, priv)
  486. struct wordlist *w;
  487. int priv;
  488. {
  489. char *argv[MAXARGS];
  490. option_t *opt;
  491. int i, n, ret = 0;
  492. struct wordlist *w0;
  493. privileged_option = priv;
  494. option_source = "secrets file";
  495. option_priority = OPRIO_SECFILE;
  496. while (w != NULL) {
  497. opt = find_option(w->word);
  498. if (opt == NULL) {
  499. option_error("In secrets file: unrecognized option '%s'",
  500. w->word);
  501. goto err;
  502. }
  503. n = n_arguments(opt);
  504. w0 = w;
  505. for (i = 0; i < n; ++i) {
  506. w = w->next;
  507. if (w == NULL) {
  508. option_error(
  509. "In secrets file: too few parameters for option '%s'",
  510. w0->word);
  511. goto err;
  512. }
  513. argv[i] = w->word;
  514. }
  515. if (!process_option(opt, w0->word, argv))
  516. goto err;
  517. w = w->next;
  518. }
  519. ret = 1;
  520. err:
  521. return ret;
  522. }
  523. /*
  524. * match_option - see if this option matches an option_t structure.
  525. */
  526. static int
  527. match_option(name, opt, dowild)
  528. char *name;
  529. option_t *opt;
  530. int dowild;
  531. {
  532. int (*match) __P((char *, char **, int));
  533. if (dowild != (opt->type == o_wild))
  534. return 0;
  535. if (!dowild)
  536. return strcmp(name, opt->name) == 0;
  537. match = (int (*) __P((char *, char **, int))) opt->addr;
  538. return (*match)(name, NULL, 0);
  539. }
  540. /*
  541. * find_option - scan the option lists for the various protocols
  542. * looking for an entry with the given name.
  543. * This could be optimized by using a hash table.
  544. */
  545. static option_t *
  546. find_option(name)
  547. const char *name;
  548. {
  549. option_t *opt;
  550. struct option_list *list;
  551. int i, dowild;
  552. for (dowild = 0; dowild <= 1; ++dowild) {
  553. for (opt = general_options; opt->name != NULL; ++opt)
  554. if (match_option(name, opt, dowild))
  555. return opt;
  556. for (opt = auth_options; opt->name != NULL; ++opt)
  557. if (match_option(name, opt, dowild))
  558. return opt;
  559. for (list = extra_options; list != NULL; list = list->next)
  560. for (opt = list->options; opt->name != NULL; ++opt)
  561. if (match_option(name, opt, dowild))
  562. return opt;
  563. for (opt = the_channel->options; opt->name != NULL; ++opt)
  564. if (match_option(name, opt, dowild))
  565. return opt;
  566. for (i = 0; protocols[i] != NULL; ++i)
  567. if ((opt = protocols[i]->options) != NULL)
  568. for (; opt->name != NULL; ++opt)
  569. if (match_option(name, opt, dowild))
  570. return opt;
  571. }
  572. return NULL;
  573. }
  574. /*
  575. * process_option - process one new-style option.
  576. */
  577. static int
  578. process_option(opt, cmd, argv)
  579. option_t *opt;
  580. char *cmd;
  581. char **argv;
  582. {
  583. u_int32_t v;
  584. int iv, a;
  585. char *sv;
  586. int (*parser) __P((char **));
  587. int (*wildp) __P((char *, char **, int));
  588. char *optopt = (opt->type == o_wild)? "": " option";
  589. int prio = option_priority;
  590. option_t *mainopt = opt;
  591. current_option = opt->name;
  592. if ((opt->flags & OPT_PRIVFIX) && privileged_option)
  593. prio += OPRIO_ROOT;
  594. while (mainopt->flags & OPT_PRIOSUB)
  595. --mainopt;
  596. if (mainopt->flags & OPT_PRIO) {
  597. if (prio < mainopt->priority) {
  598. /* new value doesn't override old */
  599. if (prio == OPRIO_CMDLINE && mainopt->priority > OPRIO_ROOT) {
  600. option_error("%s%s set in %s cannot be overridden\n",
  601. opt->name, optopt, mainopt->source);
  602. return 0;
  603. }
  604. return 1;
  605. }
  606. if (prio > OPRIO_ROOT && mainopt->priority == OPRIO_CMDLINE)
  607. warn("%s%s from %s overrides command line",
  608. opt->name, optopt, option_source);
  609. }
  610. if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) {
  611. option_error("%s%s cannot be changed after initialization",
  612. opt->name, optopt);
  613. return 0;
  614. }
  615. if ((opt->flags & OPT_PRIV) && !privileged_option) {
  616. option_error("using the %s%s requires root privilege",
  617. opt->name, optopt);
  618. return 0;
  619. }
  620. if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) {
  621. option_error("%s%s is disabled", opt->name, optopt);
  622. return 0;
  623. }
  624. if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) {
  625. option_error("the %s%s may not be changed in %s",
  626. opt->name, optopt, option_source);
  627. return 0;
  628. }
  629. switch (opt->type) {
  630. case o_bool:
  631. v = opt->flags & OPT_VALUE;
  632. *(bool *)(opt->addr) = v;
  633. if (opt->addr2 && (opt->flags & OPT_A2COPY))
  634. *(bool *)(opt->addr2) = v;
  635. else if (opt->addr2 && (opt->flags & OPT_A2CLR))
  636. *(bool *)(opt->addr2) = 0;
  637. else if (opt->addr2 && (opt->flags & OPT_A2CLRB))
  638. *(u_char *)(opt->addr2) &= ~v;
  639. else if (opt->addr2 && (opt->flags & OPT_A2OR))
  640. *(u_char *)(opt->addr2) |= v;
  641. break;
  642. case o_int:
  643. iv = 0;
  644. if ((opt->flags & OPT_NOARG) == 0) {
  645. if (!int_option(*argv, &iv))
  646. return 0;
  647. if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit)
  648. || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit))
  649. && !((opt->flags & OPT_ZEROOK && iv == 0))) {
  650. char *zok = (opt->flags & OPT_ZEROOK)? " zero or": "";
  651. switch (opt->flags & OPT_LIMITS) {
  652. case OPT_LLIMIT:
  653. option_error("%s value must be%s >= %d",
  654. opt->name, zok, opt->lower_limit);
  655. break;
  656. case OPT_ULIMIT:
  657. option_error("%s value must be%s <= %d",
  658. opt->name, zok, opt->upper_limit);
  659. break;
  660. case OPT_LIMITS:
  661. option_error("%s value must be%s between %d and %d",
  662. opt->name, zok, opt->lower_limit, opt->upper_limit);
  663. break;
  664. }
  665. return 0;
  666. }
  667. }
  668. a = opt->flags & OPT_VALUE;
  669. if (a >= 128)
  670. a -= 256; /* sign extend */
  671. iv += a;
  672. if (opt->flags & OPT_INC)
  673. iv += *(int *)(opt->addr);
  674. if ((opt->flags & OPT_NOINCR) && !privileged_option) {
  675. int oldv = *(int *)(opt->addr);
  676. if ((opt->flags & OPT_ZEROINF) ?
  677. (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) {
  678. option_error("%s value cannot be increased", opt->name);
  679. return 0;
  680. }
  681. }
  682. *(int *)(opt->addr) = iv;
  683. if (opt->addr2 && (opt->flags & OPT_A2COPY))
  684. *(int *)(opt->addr2) = iv;
  685. break;
  686. case o_uint32:
  687. if (opt->flags & OPT_NOARG) {
  688. v = opt->flags & OPT_VALUE;
  689. if (v & 0x80)
  690. v |= 0xffffff00U;
  691. } else if (!number_option(*argv, &v, 16))
  692. return 0;
  693. if (opt->flags & OPT_OR)
  694. v |= *(u_int32_t *)(opt->addr);
  695. *(u_int32_t *)(opt->addr) = v;
  696. if (opt->addr2 && (opt->flags & OPT_A2COPY))
  697. *(u_int32_t *)(opt->addr2) = v;
  698. break;
  699. case o_string:
  700. if (opt->flags & OPT_STATIC) {
  701. strlcpy((char *)(opt->addr), *argv, opt->upper_limit);
  702. } else {
  703. char **optptr = (char **)(opt->addr);
  704. sv = strdup(*argv);
  705. if (sv == NULL)
  706. novm("option argument");
  707. if (*optptr)
  708. free(*optptr);
  709. *optptr = sv;
  710. }
  711. break;
  712. case o_special_noarg:
  713. case o_special:
  714. parser = (int (*) __P((char **))) opt->addr;
  715. curopt = opt;
  716. if (!(*parser)(argv))
  717. return 0;
  718. if (opt->flags & OPT_A2LIST) {
  719. struct option_value *ovp, *pp;
  720. ovp = malloc(sizeof(*ovp) + strlen(*argv));
  721. if (ovp != 0) {
  722. strcpy(ovp->value, *argv);
  723. ovp->source = option_source;
  724. ovp->next = NULL;
  725. if (opt->addr2 == NULL) {
  726. opt->addr2 = ovp;
  727. } else {
  728. for (pp = opt->addr2; pp->next != NULL; pp = pp->next)
  729. ;
  730. pp->next = ovp;
  731. }
  732. }
  733. }
  734. break;
  735. case o_wild:
  736. wildp = (int (*) __P((char *, char **, int))) opt->addr;
  737. if (!(*wildp)(cmd, argv, 1))
  738. return 0;
  739. break;
  740. }
  741. /*
  742. * If addr2 wasn't used by any flag (OPT_A2COPY, etc.) but is set,
  743. * treat it as a bool and set/clear it based on the OPT_A2CLR bit.
  744. */
  745. if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE
  746. |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST|OPT_A2OR)) == 0)
  747. *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR);
  748. mainopt->source = option_source;
  749. mainopt->priority = prio;
  750. mainopt->winner = opt - mainopt;
  751. return 1;
  752. }
  753. /*
  754. * override_value - if the option priorities would permit us to
  755. * override the value of option, return 1 and update the priority
  756. * and source of the option value. Otherwise returns 0.
  757. */
  758. int
  759. override_value(option, priority, source)
  760. const char *option;
  761. int priority;
  762. const char *source;
  763. {
  764. option_t *opt;
  765. opt = find_option(option);
  766. if (opt == NULL)
  767. return 0;
  768. while (opt->flags & OPT_PRIOSUB)
  769. --opt;
  770. if ((opt->flags & OPT_PRIO) && priority < opt->priority)
  771. return 0;
  772. opt->priority = priority;
  773. opt->source = source;
  774. opt->winner = -1;
  775. return 1;
  776. }
  777. /*
  778. * n_arguments - tell how many arguments an option takes
  779. */
  780. static int
  781. n_arguments(opt)
  782. option_t *opt;
  783. {
  784. return (opt->type == o_bool || opt->type == o_special_noarg
  785. || (opt->flags & OPT_NOARG))? 0: 1;
  786. }
  787. /*
  788. * add_options - add a list of options to the set we grok.
  789. */
  790. void
  791. add_options(opt)
  792. option_t *opt;
  793. {
  794. struct option_list *list;
  795. list = malloc(sizeof(*list));
  796. if (list == 0)
  797. novm("option list entry");
  798. list->options = opt;
  799. list->next = extra_options;
  800. extra_options = list;
  801. }
  802. /*
  803. * check_options - check that options are valid and consistent.
  804. */
  805. void
  806. check_options()
  807. {
  808. if (logfile_fd >= 0 && logfile_fd != log_to_fd)
  809. close(logfile_fd);
  810. }
  811. /*
  812. * print_option - print out an option and its value
  813. */
  814. static void
  815. print_option(opt, mainopt, printer, arg)
  816. option_t *opt, *mainopt;
  817. printer_func printer;
  818. void *arg;
  819. {
  820. int i, v;
  821. char *p;
  822. if (opt->flags & OPT_NOPRINT)
  823. return;
  824. switch (opt->type) {
  825. case o_bool:
  826. v = opt->flags & OPT_VALUE;
  827. if (*(bool *)opt->addr != v)
  828. /* this can happen legitimately, e.g. lock
  829. option turned off for default device */
  830. break;
  831. printer(arg, "%s", opt->name);
  832. break;
  833. case o_int:
  834. v = opt->flags & OPT_VALUE;
  835. if (v >= 128)
  836. v -= 256;
  837. i = *(int *)opt->addr;
  838. if (opt->flags & OPT_NOARG) {
  839. printer(arg, "%s", opt->name);
  840. if (i != v) {
  841. if (opt->flags & OPT_INC) {
  842. for (; i > v; i -= v)
  843. printer(arg, " %s", opt->name);
  844. } else
  845. printer(arg, " # oops: %d not %d\n",
  846. i, v);
  847. }
  848. } else {
  849. printer(arg, "%s %d", opt->name, i);
  850. }
  851. break;
  852. case o_uint32:
  853. printer(arg, "%s", opt->name);
  854. if ((opt->flags & OPT_NOARG) == 0)
  855. printer(arg, " %x", *(u_int32_t *)opt->addr);
  856. break;
  857. case o_string:
  858. if (opt->flags & OPT_HIDE) {
  859. p = "??????";
  860. } else {
  861. p = (char *) opt->addr;
  862. if ((opt->flags & OPT_STATIC) == 0)
  863. p = *(char **)p;
  864. }
  865. printer(arg, "%s %q", opt->name, p);
  866. break;
  867. case o_special:
  868. case o_special_noarg:
  869. case o_wild:
  870. if (opt->type != o_wild) {
  871. printer(arg, "%s", opt->name);
  872. if (n_arguments(opt) == 0)
  873. break;
  874. printer(arg, " ");
  875. }
  876. if (opt->flags & OPT_A2PRINTER) {
  877. void (*oprt) __P((option_t *, printer_func, void *));
  878. oprt = (void (*) __P((option_t *, printer_func,
  879. void *)))opt->addr2;
  880. (*oprt)(opt, printer, arg);
  881. } else if (opt->flags & OPT_A2STRVAL) {
  882. p = (char *) opt->addr2;
  883. if ((opt->flags & OPT_STATIC) == 0)
  884. p = *(char **)p;
  885. printer("%q", p);
  886. } else if (opt->flags & OPT_A2LIST) {
  887. struct option_value *ovp;
  888. ovp = (struct option_value *) opt->addr2;
  889. for (;;) {
  890. printer(arg, "%q", ovp->value);
  891. if ((ovp = ovp->next) == NULL)
  892. break;
  893. printer(arg, "\t\t# (from %s)\n%s ",
  894. ovp->source, opt->name);
  895. }
  896. } else {
  897. printer(arg, "xxx # [don't know how to print value]");
  898. }
  899. break;
  900. default:
  901. printer(arg, "# %s value (type %d\?\?)", opt->name, opt->type);
  902. break;
  903. }
  904. printer(arg, "\t\t# (from %s)\n", mainopt->source);
  905. }
  906. /*
  907. * print_option_list - print out options in effect from an
  908. * array of options.
  909. */
  910. static void
  911. print_option_list(opt, printer, arg)
  912. option_t *opt;
  913. printer_func printer;
  914. void *arg;
  915. {
  916. while (opt->name != NULL) {
  917. if (opt->priority != OPRIO_DEFAULT
  918. && opt->winner != (short int) -1)
  919. print_option(opt + opt->winner, opt, printer, arg);
  920. do {
  921. ++opt;
  922. } while (opt->flags & OPT_PRIOSUB);
  923. }
  924. }
  925. /*
  926. * print_options - print out what options are in effect.
  927. */
  928. void
  929. print_options(printer, arg)
  930. printer_func printer;
  931. void *arg;
  932. {
  933. struct option_list *list;
  934. int i;
  935. printer(arg, "pppd options in effect:\n");
  936. print_option_list(general_options, printer, arg);
  937. print_option_list(auth_options, printer, arg);
  938. for (list = extra_options; list != NULL; list = list->next)
  939. print_option_list(list->options, printer, arg);
  940. print_option_list(the_channel->options, printer, arg);
  941. for (i = 0; protocols[i] != NULL; ++i)
  942. print_option_list(protocols[i]->options, printer, arg);
  943. }
  944. /*
  945. * usage - print out a message telling how to use the program.
  946. */
  947. static void
  948. usage()
  949. {
  950. if (phase == PHASE_INITIALIZE)
  951. fprintf(stderr, usage_string, VERSION, progname);
  952. }
  953. /*
  954. * showhelp - print out usage message and exit.
  955. */
  956. static int
  957. showhelp(argv)
  958. char **argv;
  959. {
  960. if (phase == PHASE_INITIALIZE) {
  961. usage();
  962. exit(0);
  963. }
  964. return 0;
  965. }
  966. /*
  967. * showversion - print out the version number and exit.
  968. */
  969. static int
  970. showversion(argv)
  971. char **argv;
  972. {
  973. if (phase == PHASE_INITIALIZE) {
  974. fprintf(stderr, "pppd version %s\n", VERSION);
  975. exit(0);
  976. }
  977. return 0;
  978. }
  979. /*
  980. * option_error - print a message about an error in an option.
  981. * The message is logged, and also sent to
  982. * stderr if phase == PHASE_INITIALIZE.
  983. */
  984. void
  985. option_error __V((char *fmt, ...))
  986. {
  987. va_list args;
  988. char buf[1024];
  989. #if defined(__STDC__)
  990. va_start(args, fmt);
  991. #else
  992. char *fmt;
  993. va_start(args);
  994. fmt = va_arg(args, char *);
  995. #endif
  996. vslprintf(buf, sizeof(buf), fmt, args);
  997. va_end(args);
  998. if (phase == PHASE_INITIALIZE)
  999. fprintf(stderr, "%s: %s\n", progname, buf);
  1000. syslog(LOG_ERR, "%s", buf);
  1001. }
  1002. #if 0
  1003. /*
  1004. * readable - check if a file is readable by the real user.
  1005. */
  1006. int
  1007. readable(fd)
  1008. int fd;
  1009. {
  1010. uid_t uid;
  1011. int i;
  1012. struct stat sbuf;
  1013. uid = getuid();
  1014. if (uid == 0)
  1015. return 1;
  1016. if (fstat(fd, &sbuf) != 0)
  1017. return 0;
  1018. if (sbuf.st_uid == uid)
  1019. return sbuf.st_mode & S_IRUSR;
  1020. if (sbuf.st_gid == getgid())
  1021. return sbuf.st_mode & S_IRGRP;
  1022. for (i = 0; i < ngroups; ++i)
  1023. if (sbuf.st_gid == groups[i])
  1024. return sbuf.st_mode & S_IRGRP;
  1025. return sbuf.st_mode & S_IROTH;
  1026. }
  1027. #endif
  1028. /*
  1029. * Read a word from a file.
  1030. * Words are delimited by white-space or by quotes (" or ').
  1031. * Quotes, white-space and \ may be escaped with \.
  1032. * \<newline> is ignored.
  1033. */
  1034. int
  1035. getword(f, word, newlinep, filename)
  1036. FILE *f;
  1037. char *word;
  1038. int *newlinep;
  1039. char *filename;
  1040. {
  1041. int c, len, escape;
  1042. int quoted, comment;
  1043. int value, digit, got, n;
  1044. #define isoctal(c) ((c) >= '0' && (c) < '8')
  1045. *newlinep = 0;
  1046. len = 0;
  1047. escape = 0;
  1048. comment = 0;
  1049. quoted = 0;
  1050. /*
  1051. * First skip white-space and comments.
  1052. */
  1053. for (;;) {
  1054. c = getc(f);
  1055. if (c == EOF)
  1056. break;
  1057. /*
  1058. * A newline means the end of a comment; backslash-newline
  1059. * is ignored. Note that we cannot have escape && comment.
  1060. */
  1061. if (c == '\n') {
  1062. if (!escape) {
  1063. *newlinep = 1;
  1064. comment = 0;
  1065. } else
  1066. escape = 0;
  1067. continue;
  1068. }
  1069. /*
  1070. * Ignore characters other than newline in a comment.
  1071. */
  1072. if (comment)
  1073. continue;
  1074. /*
  1075. * If this character is escaped, we have a word start.
  1076. */
  1077. if (escape)
  1078. break;
  1079. /*
  1080. * If this is the escape character, look at the next character.
  1081. */
  1082. if (c == '\\') {
  1083. escape = 1;
  1084. continue;
  1085. }
  1086. /*
  1087. * If this is the start of a comment, ignore the rest of the line.
  1088. */
  1089. if (c == '#') {
  1090. comment = 1;
  1091. continue;
  1092. }
  1093. /*
  1094. * A non-whitespace character is the start of a word.
  1095. */
  1096. if (!isspace(c))
  1097. break;
  1098. }
  1099. /*
  1100. * Process characters until the end of the word.
  1101. */
  1102. while (c != EOF) {
  1103. if (escape) {
  1104. /*
  1105. * This character is escaped: backslash-newline is ignored,
  1106. * various other characters indicate particular values
  1107. * as for C backslash-escapes.
  1108. */
  1109. escape = 0;
  1110. if (c == '\n') {
  1111. c = getc(f);
  1112. continue;
  1113. }
  1114. got = 0;
  1115. switch (c) {
  1116. case 'a':
  1117. value = '\a';
  1118. break;
  1119. case 'b':
  1120. value = '\b';
  1121. break;
  1122. case 'f':
  1123. value = '\f';
  1124. break;
  1125. case 'n':
  1126. value = '\n';
  1127. break;
  1128. case 'r':
  1129. value = '\r';
  1130. break;
  1131. case 's':
  1132. value = ' ';
  1133. break;
  1134. case 't':
  1135. value = '\t';
  1136. break;
  1137. default:
  1138. if (isoctal(c)) {
  1139. /*
  1140. * \ddd octal sequence
  1141. */
  1142. value = 0;
  1143. for (n = 0; n < 3 && isoctal(c); ++n) {
  1144. value = (value << 3) + (c & 07);
  1145. c = getc(f);
  1146. }
  1147. got = 1;
  1148. break;
  1149. }
  1150. if (c == 'x') {
  1151. /*
  1152. * \x<hex_string> sequence
  1153. */
  1154. value = 0;
  1155. c = getc(f);
  1156. for (n = 0; n < 2 && isxdigit(c); ++n) {
  1157. digit = toupper(c) - '0';
  1158. if (digit > 10)
  1159. digit += '0' + 10 - 'A';
  1160. value = (value << 4) + digit;
  1161. c = getc (f);
  1162. }
  1163. got = 1;
  1164. break;
  1165. }
  1166. /*
  1167. * Otherwise the character stands for itself.
  1168. */
  1169. value = c;
  1170. break;
  1171. }
  1172. /*
  1173. * Store the resulting character for the escape sequence.
  1174. */
  1175. if (len < MAXWORDLEN) {
  1176. word[len] = value;
  1177. ++len;
  1178. }
  1179. if (!got)
  1180. c = getc(f);
  1181. continue;
  1182. }
  1183. /*
  1184. * Backslash starts a new escape sequence.
  1185. */
  1186. if (c == '\\') {
  1187. escape = 1;
  1188. c = getc(f);
  1189. continue;
  1190. }
  1191. /*
  1192. * Not escaped: check for the start or end of a quoted
  1193. * section and see if we've reached the end of the word.
  1194. */
  1195. if (quoted) {
  1196. if (c == quoted) {
  1197. quoted = 0;
  1198. c = getc(f);
  1199. continue;
  1200. }
  1201. } else if (c == '"' || c == '\'') {
  1202. quoted = c;
  1203. c = getc(f);
  1204. continue;
  1205. } else if (isspace(c) || c == '#') {
  1206. ungetc (c, f);
  1207. break;
  1208. }
  1209. /*
  1210. * An ordinary character: store it in the word and get another.
  1211. */
  1212. if (len < MAXWORDLEN) {
  1213. word[len] = c;
  1214. ++len;
  1215. }
  1216. c = getc(f);
  1217. }
  1218. /*
  1219. * End of the word: check for errors.
  1220. */
  1221. if (c == EOF) {
  1222. if (ferror(f)) {
  1223. if (errno == 0)
  1224. errno = EIO;
  1225. option_error("Error reading %s: %m", filename);
  1226. die(1);
  1227. }
  1228. /*
  1229. * If len is zero, then we didn't find a word before the
  1230. * end of the file.
  1231. */
  1232. if (len == 0)
  1233. return 0;
  1234. if (quoted)
  1235. option_error("warning: quoted word runs to end of file (%.20s...)",
  1236. filename, word);
  1237. }
  1238. /*
  1239. * Warn if the word was too long, and append a terminating null.
  1240. */
  1241. if (len >= MAXWORDLEN) {
  1242. option_error("warning: word in file %s too long (%.20s...)",
  1243. filename, word);
  1244. len = MAXWORDLEN - 1;
  1245. }
  1246. word[len] = 0;
  1247. return 1;
  1248. #undef isoctal
  1249. }
  1250. /*
  1251. * number_option - parse an unsigned numeric parameter for an option.
  1252. */
  1253. static int
  1254. number_option(str, valp, base)
  1255. char *str;
  1256. u_int32_t *valp;
  1257. int base;
  1258. {
  1259. char *ptr;
  1260. *valp = strtoul(str, &ptr, base);
  1261. if (ptr == str) {
  1262. option_error("invalid numeric parameter '%s' for %s option",
  1263. str, current_option);
  1264. return 0;
  1265. }
  1266. return 1;
  1267. }
  1268. /*
  1269. * int_option - like number_option, but valp is int *,
  1270. * the base is assumed to be 0, and *valp is not changed
  1271. * if there is an error.
  1272. */
  1273. int
  1274. int_option(str, valp)
  1275. char *str;
  1276. int *valp;
  1277. {
  1278. u_int32_t v;
  1279. if (!number_option(str, &v, 0))
  1280. return 0;
  1281. *valp = (int) v;
  1282. return 1;
  1283. }
  1284. /*
  1285. * The following procedures parse options.
  1286. */
  1287. /*
  1288. * readfile - take commands from a file.
  1289. */
  1290. static int
  1291. readfile(argv)
  1292. char **argv;
  1293. {
  1294. return options_from_file(*argv, 1, 1, privileged_option);
  1295. }
  1296. /*
  1297. * callfile - take commands from /etc/ppp/peers/<name>.
  1298. * Name may not contain /../, start with / or ../, or end in /..
  1299. */
  1300. static int
  1301. callfile(argv)
  1302. char **argv;
  1303. {
  1304. char *fname, *arg, *p;
  1305. int l, ok;
  1306. arg = *argv;
  1307. ok = 1;
  1308. if (arg[0] == '/' || arg[0] == 0)
  1309. ok = 0;
  1310. else {
  1311. for (p = arg; *p != 0; ) {
  1312. if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
  1313. ok = 0;
  1314. break;
  1315. }
  1316. while (*p != '/' && *p != 0)
  1317. ++p;
  1318. if (*p == '/')
  1319. ++p;
  1320. }
  1321. }
  1322. if (!ok) {
  1323. option_error("call option value may not contain .. or start with /");
  1324. return 0;
  1325. }
  1326. l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
  1327. if ((fname = (char *) malloc(l)) == NULL)
  1328. novm("call file name");
  1329. slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg);
  1330. ok = options_from_file(fname, 1, 1, 1);
  1331. free(fname);
  1332. return ok;
  1333. }
  1334. #ifdef PPP_FILTER
  1335. /*
  1336. * setpassfilter - Set the pass filter for packets
  1337. */
  1338. static int
  1339. setpassfilter(argv)
  1340. char **argv;
  1341. {
  1342. pcap_t *pc;
  1343. int ret = 1;
  1344. pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
  1345. if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) {
  1346. option_error("error in pass-filter expression: %s\n",
  1347. pcap_geterr(pc));
  1348. ret = 0;
  1349. }
  1350. pcap_close(pc);
  1351. return ret;
  1352. }
  1353. /*
  1354. * setactivefilter - Set the active filter for packets
  1355. */
  1356. static int
  1357. setactivefilter(argv)
  1358. char **argv;
  1359. {
  1360. pcap_t *pc;
  1361. int ret = 1;
  1362. pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
  1363. if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) {
  1364. option_error("error in active-filter expression: %s\n",
  1365. pcap_geterr(pc));
  1366. ret = 0;
  1367. }
  1368. pcap_close(pc);
  1369. return ret;
  1370. }
  1371. #endif
  1372. /*
  1373. * setdomain - Set domain name to append to hostname
  1374. */
  1375. static int
  1376. setdomain(argv)
  1377. char **argv;
  1378. {
  1379. gethostname(hostname, MAXNAMELEN);
  1380. if (**argv != 0) {
  1381. if (**argv != '.')
  1382. strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
  1383. domain = hostname + strlen(hostname);
  1384. strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
  1385. }
  1386. hostname[MAXNAMELEN-1] = 0;
  1387. return (1);
  1388. }
  1389. static int
  1390. setlogfile(argv)
  1391. char **argv;
  1392. {
  1393. int fd, err;
  1394. uid_t euid;
  1395. euid = geteuid();
  1396. if (!privileged_option && seteuid(getuid()) == -1) {
  1397. option_error("unable to drop permissions to open %s: %m", *argv);
  1398. return 0;
  1399. }
  1400. fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644);
  1401. if (fd < 0 && errno == EEXIST)
  1402. fd = open(*argv, O_WRONLY | O_APPEND);
  1403. err = errno;
  1404. if (!privileged_option && seteuid(euid) == -1)
  1405. fatal("unable to regain privileges: %m");
  1406. if (fd < 0) {
  1407. errno = err;
  1408. option_error("Can't open log file %s: %m", *argv);
  1409. return 0;
  1410. }
  1411. strlcpy(logfile_name, *argv, sizeof(logfile_name));
  1412. if (logfile_fd >= 0)
  1413. close(logfile_fd);
  1414. logfile_fd = fd;
  1415. log_to_fd = fd;
  1416. log_default = 0;
  1417. return 1;
  1418. }
  1419. #ifdef MAXOCTETS
  1420. static int
  1421. setmodir(argv)
  1422. char **argv;
  1423. {
  1424. if(*argv == NULL)
  1425. return 0;
  1426. if(!strcmp(*argv,"in")) {
  1427. maxoctets_dir = PPP_OCTETS_DIRECTION_IN;
  1428. } else if (!strcmp(*argv,"out")) {
  1429. maxoctets_dir = PPP_OCTETS_DIRECTION_OUT;
  1430. } else if (!strcmp(*argv,"max")) {
  1431. maxoctets_dir = PPP_OCTETS_DIRECTION_MAXOVERAL;
  1432. } else {
  1433. maxoctets_dir = PPP_OCTETS_DIRECTION_SUM;
  1434. }
  1435. return 1;
  1436. }
  1437. #endif
  1438. #ifdef PLUGIN
  1439. static int
  1440. loadplugin(argv)
  1441. char **argv;
  1442. {
  1443. char *arg = *argv;
  1444. void *handle;
  1445. const char *err;
  1446. void (*init) __P((void));
  1447. char *path = arg;
  1448. const char *vers;
  1449. if (strchr(arg, '/') == 0) {
  1450. const char *base = _PATH_PLUGIN;
  1451. int l = strlen(base) + strlen(arg) + 2;
  1452. path = malloc(l);
  1453. if (path == 0)
  1454. novm("plugin file path");
  1455. strlcpy(path, base, l);
  1456. strlcat(path, "/", l);
  1457. strlcat(path, arg, l);
  1458. }
  1459. handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
  1460. if (handle == 0) {
  1461. err = dlerror();
  1462. if (err != 0)
  1463. option_error("%s", err);
  1464. option_error("Couldn't load plugin %s", arg);
  1465. goto err;
  1466. }
  1467. init = (void (*)(void))dlsym(handle, "plugin_init");
  1468. if (init == 0) {
  1469. option_error("%s has no initialization entry point", arg);
  1470. goto errclose;
  1471. }
  1472. vers = (const char *) dlsym(handle, "pppd_version");
  1473. if (vers == 0) {
  1474. warn("Warning: plugin %s has no version information", arg);
  1475. } else if (strcmp(vers, VERSION) != 0) {
  1476. option_error("Plugin %s is for pppd version %s, this is %s",
  1477. arg, vers, VERSION);
  1478. goto errclose;
  1479. }
  1480. info("Plugin %s loaded.", arg);
  1481. (*init)();
  1482. return 1;
  1483. errclose:
  1484. dlclose(handle);
  1485. err:
  1486. if (path != arg)
  1487. free(path);
  1488. return 0;
  1489. }
  1490. #endif /* PLUGIN */
  1491. /*
  1492. * Set an environment variable specified by the user.
  1493. */
  1494. static int
  1495. user_setenv(argv)
  1496. char **argv;
  1497. {
  1498. char *arg = argv[0];
  1499. char *eqp;
  1500. struct userenv *uep, **insp;
  1501. if ((eqp = strchr(arg, '=')) == NULL) {
  1502. option_error("missing = in name=value: %s", arg);
  1503. return 0;
  1504. }
  1505. if (eqp == arg) {
  1506. option_error("missing variable name: %s", arg);
  1507. return 0;
  1508. }
  1509. for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
  1510. int nlen = strlen(uep->ue_name);
  1511. if (nlen == (eqp - arg) &&
  1512. strncmp(arg, uep->ue_name, nlen) == 0)
  1513. break;
  1514. }
  1515. /* Ignore attempts by unprivileged users to override privileged sources */
  1516. if (uep != NULL && !privileged_option && uep->ue_priv)
  1517. return 1;
  1518. /* The name never changes, so allocate it with the structure */
  1519. if (uep == NULL) {
  1520. uep = malloc(sizeof (*uep) + (eqp-arg));
  1521. strncpy(uep->ue_name, arg, eqp-arg);
  1522. uep->ue_name[eqp-arg] = '\0';
  1523. uep->ue_next = NULL;
  1524. insp = &userenv_list;
  1525. while (*insp != NULL)
  1526. insp = &(*insp)->ue_next;
  1527. *insp = uep;
  1528. } else {
  1529. struct userenv *uep2;
  1530. for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
  1531. if (uep2 != uep && !uep2->ue_isset)
  1532. break;
  1533. }
  1534. if (uep2 == NULL && !uep->ue_isset)
  1535. find_option("unset")->flags |= OPT_NOPRINT;
  1536. free(uep->ue_value);
  1537. }
  1538. uep->ue_isset = 1;
  1539. uep->ue_priv = privileged_option;
  1540. uep->ue_source = option_source;
  1541. uep->ue_value = strdup(eqp + 1);
  1542. curopt->flags &= ~OPT_NOPRINT;
  1543. return 1;
  1544. }
  1545. static void
  1546. user_setprint(opt, printer, arg)
  1547. option_t *opt;
  1548. printer_func printer;
  1549. void *arg;
  1550. {
  1551. struct userenv *uep, *uepnext;
  1552. uepnext = userenv_list;
  1553. while (uepnext != NULL && !uepnext->ue_isset)
  1554. uepnext = uepnext->ue_next;
  1555. while ((uep = uepnext) != NULL) {
  1556. uepnext = uep->ue_next;
  1557. while (uepnext != NULL && !uepnext->ue_isset)
  1558. uepnext = uepnext->ue_next;
  1559. (*printer)(arg, "%s=%s", uep->ue_name, uep->ue_value);
  1560. if (uepnext != NULL)
  1561. (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
  1562. else
  1563. opt->source = uep->ue_source;
  1564. }
  1565. }
  1566. static int
  1567. user_unsetenv(argv)
  1568. char **argv;
  1569. {
  1570. struct userenv *uep, **insp;
  1571. char *arg = argv[0];
  1572. if (strchr(arg, '=') != NULL) {
  1573. option_error("unexpected = in name: %s", arg);
  1574. return 0;
  1575. }
  1576. if (arg == '\0') {
  1577. option_error("missing variable name for unset");
  1578. return 0;
  1579. }
  1580. for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
  1581. if (strcmp(arg, uep->ue_name) == 0)
  1582. break;
  1583. }
  1584. /* Ignore attempts by unprivileged users to override privileged sources */
  1585. if (uep != NULL && !privileged_option && uep->ue_priv)
  1586. return 1;
  1587. /* The name never changes, so allocate it with the structure */
  1588. if (uep == NULL) {
  1589. uep = malloc(sizeof (*uep) + strlen(arg));
  1590. strcpy(uep->ue_name, arg);
  1591. uep->ue_next = NULL;
  1592. insp = &userenv_list;
  1593. while (*insp != NULL)
  1594. insp = &(*insp)->ue_next;
  1595. *insp = uep;
  1596. } else {
  1597. struct userenv *uep2;
  1598. for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
  1599. if (uep2 != uep && uep2->ue_isset)
  1600. break;
  1601. }
  1602. if (uep2 == NULL && uep->ue_isset)
  1603. find_option("set")->flags |= OPT_NOPRINT;
  1604. free(uep->ue_value);
  1605. }
  1606. uep->ue_isset = 0;
  1607. uep->ue_priv = privileged_option;
  1608. uep->ue_source = option_source;
  1609. uep->ue_value = NULL;
  1610. curopt->flags &= ~OPT_NOPRINT;
  1611. return 1;
  1612. }
  1613. static void
  1614. user_unsetprint(opt, printer, arg)
  1615. option_t *opt;
  1616. printer_func printer;
  1617. void *arg;
  1618. {
  1619. struct userenv *uep, *uepnext;
  1620. uepnext = userenv_list;
  1621. while (uepnext != NULL && uepnext->ue_isset)
  1622. uepnext = uepnext->ue_next;
  1623. while ((uep = uepnext) != NULL) {
  1624. uepnext = uep->ue_next;
  1625. while (uepnext != NULL && uepnext->ue_isset)
  1626. uepnext = uepnext->ue_next;
  1627. (*printer)(arg, "%s", uep->ue_name);
  1628. if (uepnext != NULL)
  1629. (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
  1630. else
  1631. opt->source = uep->ue_source;
  1632. }
  1633. }