pppLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:49k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* pppLib.c - Point-to-Point Protocol library */
  2. /* Copyright 1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1989 Carnegie Mellon University.
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by Carnegie Mellon University.  The name of the
  14.  * University may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20. /*
  21. modification history
  22. --------------------
  23. 01x,04dec00,adb  enabled PPP_HOOK_DISCONNECT in pppDelete
  24. 01w,23oct00,cn   Fix for spr 34068, cleanup of clients' addresses structures.
  25. 01y,19oct00,cn   Fix for spr 34657, cleanup of callout structures.
  26. 01v,17feb99,sgv  Fix for spr 24560, proper cleanup when ppp options file 
  27.  cannot be accessed
  28. 01u,31aug98,fle  doc : got rid of simple quotes to avoid bold troubles
  29. 01t,15aug97,sgv  fixed spr #9109. In cleanup routine, ppp_if[unit] 
  30.  is checked for NULL memory address before freeing it
  31. 01s,10dec96,vin  fixed problem with die(..) if OPT_SILENT or OPT_PASSIVE
  32.  is specified. Made changes to term(..) so that pppDelete()
  33.  would work even if silent or passive options are specified.
  34.  fixed SPR 7604.
  35. 01r,15nov96,vin  fixed problem with OPT_DRIVER_DEBUG, establish_ppp() 
  36.  should be called after the options are set. The only
  37.  dependency is that pppopen() should be called before
  38.  establish_ppp().
  39. 01q,19dec95,vin  doc tweaks.
  40. 01p,30nov95,vin  added hooks on a unit basis.
  41. 01o,11jul95,dzb  doc tweaks.
  42. 01n,22jun95,dzb  changed [un]timeout() to ppp_[un]timeout().
  43.                  removed usehostname option.  Enhanced doc.
  44. 01m,12jun95,dzb  added MIBII counter for unknown protocol packets.
  45.                  changed [dis]connect strings to global hook routines.
  46.                  header file consolidation.  removed device_script().
  47.  removed perror() reference.
  48. 01l,08jun95,dzb  made LOG_NOTICE message printed even w/o debug option.
  49. 01k,16may95,dzb  put back in login option doc.
  50. 01j,09may95,dzb  added callout to pppSecretLibInit().
  51.                  switched all lcp_close() calls to go through die().
  52. 01i,03may95,dzb  doc tweaks: removed login option, fixed require_chap_file,
  53.                  added pap_passwd option.
  54. 01h,07mar95,dzb  changed cfree() to free() (ANSI).  Changed name to pppLib.c.
  55.                  additional doc/formatting.
  56. 01g,13feb95,dab  fixed pppDelete() for multi unit support (SPR #4062).
  57. 01f,09feb95,dzb  fixed proto tbl input call for multi unit support (SPR #4062).
  58. 01e,07feb95,dab  changed syslog to MAINDEBUG for reg status messages.
  59.             dzb  changed to look at (errno != EINTR) after sigsuspend().
  60. 01d,24jan95,dzb  ifdef VXW5_1 for timer_create() backwards capatibility.
  61.                  renamed params for pppInit() and ppp_task().
  62. 01c,13jan95,dab  enhanced doc.
  63. 01b,22dec94,dzb  tree shuffle and warning cleanup.
  64. 01a,21dec94,dab  VxWorks port - first WRS version.
  65.    +dzb  added: path for ppp header files, WRS copyright.
  66. */
  67. /*
  68. DESCRIPTION
  69. This library implements the VxWorks Point-to-Point Protocol (PPP)
  70. facility.  PPP allows VxWorks to communicate with other machines by sending
  71. encapsulated multi-protocol datagrams over a point-to-point serial link.
  72. VxWorks may have up to 16 PPP interfaces active at any one time.  Each
  73. individual interface (or "unit") operates independent of the state of
  74. other PPP units.
  75. USER-CALLABLE ROUTINES
  76. PPP network interfaces are initialized using the pppInit() routine. This 
  77. routine's parameters specify the unit number, the name of the serial 
  78. interface (<tty>) device, Internet (IP) addresses for both ends of the link,
  79. the interface baud rate, an optional pointer to a configuration options 
  80. structure, and an optional pointer to a configuration options file.  
  81. The pppDelete() routine deletes a specified PPP interface.
  82. DATA ENCAPSULATION
  83. PPP uses HDLC-like framing, in which five header and three trailer octets are
  84. used to encapsulate each datagram.  In environments where bandwidth is at
  85. a premium, the total encapsulation may be shortened to four octets with
  86. the available address/control and protocol field compression options.
  87. LINK CONTROL PROTOCOL
  88. PPP incorporates a link-layer protocol called Link Control Protocol (LCP),
  89. which is responsible for the link set up, configuration, and termination.
  90. LCP provides for automatic negotiation of several link options, including
  91. datagram encapsulation format, user authentication, and link monitoring
  92. (LCP echo request/reply).
  93. NETWORK CONTROL PROTOCOLS
  94. PPP's Network Control Protocols (NCP) allow PPP to support 
  95. different network protocols.  VxWorks supports only one NCP, the Internet
  96. Protocol Control Protocol (IPCP), which allows the establishment and
  97. configuration of IP over PPP links.  IPCP supports the negotiation of IP
  98. addresses and TCP/IP header compression (commonly called "VJ" compression).
  99. AUTHENTICATION
  100. The VxWorks PPP implementation supports two separate user authentication
  101. protocols: the Password Authentication Protocol (PAP) and the
  102. Challenge-Handshake Authentication Protocol (CHAP).  While PAP only
  103. authenticates at the time of link establishment, CHAP may be configured to
  104. periodically require authentication throughout the life of the link.
  105. Both protocols are independent of one another, and either may be configured
  106. in through the PPP options structure or options file.
  107. IMPLEMENTATION
  108. Each VxWorks PPP interface is handled by two tasks: the daemon task
  109. (tPPP<unit>) and the write task (tPPP<unit>Wrt).
  110. The daemon task controls the various PPP control protocols (LCP, IPCP, CHAP,
  111. and PAP).  Each PPP interface has its own daemon task that handles link
  112. set up, negotiation of link options, link-layer user athentication, and
  113. link termination.  The daemon task is not used for the actual sending and
  114. receiving of IP datagrams.
  115. The write task controls the transmit end of a PPP driver interface.
  116. Each PPP interface has its own write task that handles the actual sending
  117. of a packet by writing data to the <tty> device.  Whenever a packet is ready
  118. to be sent out, the PPP driver activates this task by giving a semaphore.
  119. The write task then completes the packet framing and writes
  120. the packet data to the <tty> device.
  121. The receive end of the PPP interface is implemented as a "hook" into
  122. the <tty> device driver.  The <tty> driver's receive interrupt service routine
  123. (ISR) calls the PPP driver's ISR every time a character is received on the
  124. serial channel.  When the correct PPP framing character sequence is received,
  125. the PPP ISR schedules the tNetTask task to call the PPP input routine.
  126. The PPP input routine reads a whole PPP packet out of the <tty> ring
  127. buffer and processes it according to PPP framing rules.
  128. The packet is then queued either to the IP input queue or to the PPP daemon
  129. task input queue.
  130. INCLUDE FILES: pppLib.h
  131. SEE ALSO: ifLib, tyLib, pppSecretLib, pppShow,
  132. .pG "Network"
  133. .I "RFC-1332: The PPP Internet Protocol Control Protocol (IPCP)", 
  134. .I "RFC-1334: PPP Authentication Protocols", 
  135. .I "RFC-1548: The Point-to-Point Protocol (PPP)", 
  136. .I "RFC-1549: PPP in HDLC Framing"
  137. ACKNOWLEDGEMENT
  138. This program is based on original work done by Paul Mackerras of
  139. Australian National University, Brad Parker, Greg Christy, Drew D. Perkins,
  140. Rick Adams, and Chris Torek.
  141. INTERNAL
  142.          pppInit               pppDelete 
  143.             |                     |
  144.             |                     |
  145.             |                     |
  146.          pppopen   pppwrite    pppclose   pppintr   pppread   pppioctl
  147.            /          |          |          |               
  148.           /           |          |          |              
  149.          /        pppoutput      |          |             
  150.         /             |          |          |            
  151.        /              |          |          |           
  152.   pppalloc pppWrtTask <-      pppdealloc ppp_tty_read 
  153.       |                                      |           
  154.       |                                      |           
  155.       |                                      |           
  156.   pppattach                               pppinput
  157.                                              |
  158.                                              |
  159.                                              |
  160.                                           ppppktin
  161. */
  162. #include "vxWorks.h"
  163. #include "string.h"
  164. #include "sigLib.h"
  165. #include "sysLib.h"
  166. #include "sockLib.h"
  167. #include "ioLib.h"
  168. #include "iosLib.h"
  169. #include "excLib.h"
  170. #include "time.h"
  171. #include "timers.h"
  172. #include "taskLib.h"
  173. #include "taskVarLib.h"
  174. #include "hostLib.h"
  175. #include "sys/ioctl.h"
  176. #include "netinet/in.h"
  177. #include "arpa/inet.h"
  178. #include "stdio.h"
  179. #include "signal.h"
  180. #include "errno.h"
  181. #include "fcntl.h"
  182. #include "sys/types.h"
  183. #include "sys/stat.h"
  184. #include "sys/socket.h"
  185. #include "sys/times.h"
  186. #include "net/if.h"
  187. #include "netLib.h"
  188. #include "pppLib.h"
  189. /* PPP parameter structure */
  190. typedef struct ppp_parms
  191. {
  192. char *task_name;
  193.         char *devname;
  194.         char *local_addr;
  195.         char *remote_addr;
  196.         char *filename;
  197.         int unit;
  198.         int baud;
  199.         PPP_OPTIONS options;
  200. } PPP_PARMS;
  201. /* globals */
  202. int ppp_unit; /* PPP unit id */
  203. PPP_TASK_VARS *ppp_if[NPPP]; /* per task PPP variables */
  204. PPP_PARMS *ppp_parms[NPPP]; /* PPP parameters */
  205. PPP_HOOK_RTNS * pppHookRtns [NPPP]; /* PPP table of hooks */
  206. int ppp_task_priority = 55;
  207. int ppp_task_options = VX_FP_TASK | VX_DEALLOC_STACK;
  208. int ppp_task_stack_size = 0x4000;
  209. char *ppp_task_name = "tPPP";
  210. /* prototypes */
  211. static int  baud_rate_of __ARGS((int));
  212. static int  translate_speed __ARGS((int));
  213. static int  set_up_tty __ARGS((int));
  214. static void hup __ARGS((int));
  215. static void intr __ARGS((int));
  216. static void term __ARGS((int));
  217. static void alrm __ARGS((int));
  218. static void io __ARGS(());
  219. static void incdebug __ARGS((int));
  220. static void nodebug __ARGS((int));
  221. static void cleanup __ARGS((int, int, caddr_t));
  222. /*
  223.  * PPP Data Link Layer "protocol" table.
  224.  * One entry per supported protocol.
  225.  */
  226. static struct protent {
  227.     u_short protocol;
  228.     void (*init)();
  229.     void (*input)();
  230.     void (*protrej)();
  231.     int  (*printpkt)();
  232.     char *name;
  233. } prottbl[] = {
  234.     { LCP, lcp_init, lcp_input, lcp_protrej, lcp_printpkt, "LCP" },
  235.     { IPCP, ipcp_init, ipcp_input, ipcp_protrej, ipcp_printpkt, "IPCP" },
  236.     { UPAP, upap_init, upap_input, upap_protrej, upap_printpkt, "PAP" },
  237.     { CHAP, ChapInit, ChapInput, ChapProtocolReject, ChapPrintPkt, "CHAP" },
  238. };
  239. #define N_PROTO         (sizeof(prottbl) / sizeof(prottbl[0]))
  240. /*******************************************************************************
  241. *
  242. * pppInit - initialize a PPP network interface
  243. *
  244. * This routine initializes a Point-to-Point Protocol (PPP) network interface.
  245. * The parameters to this routine specify the unit number (<unit>) of the
  246. * PPP interface, the name of the serial interface (<tty>) device (<devname>),
  247. * the IP addresses of the local and remote ends of the link, the interface
  248. * baud rate, an optional configuration options structure pointer, and an
  249. * optional configuration options file name.
  250. *
  251. * IP ADDRESSES:
  252. * The <local_addr> and <remote_addr> parameters specify the IP addresses
  253. * of the local and remote ends of the PPP link, respectively.
  254. * If <local_addr> is NULL, the local IP address will be negotiated with
  255. * the remote peer.  If the remote peer does not assign a local IP address,
  256. * it will default to the address associated with the local target's machine
  257. * name.  If <remote_addr> is NULL, the remote peer's IP address will obtained
  258. * from the remote peer.  A routing table entry to the remote peer will be
  259. * automatically added once the PPP link is established.
  260. *
  261. * CONFIGURATION OPTIONS STRUCTURE:
  262. * The optional parameter <pOptions> specifies configuration options for
  263. * the PPP link.  If NULL, this parameter is ignored, otherwise it
  264. * is assumed to be a pointer to a PPP_OPTIONS options structure (defined
  265. * in h/netinet/ppp/options.h).
  266. *
  267. * The "flags" member of the PPP_OPTIONS structure is a bit-mask, where the
  268. * following bit-flags may be specified:
  269. * .iP "OPT_NO_ALL"
  270. * Do not request/allow any options.
  271. * .iP "OPT_PASSIVE_MODE"
  272. * Set passive mode.
  273. * .iP "OPT_SILENT_MODE"
  274. * Set silent mode.
  275. * .iP "OPT_DEFAULTROUTE"
  276. * Add default route.
  277. * .iP "OPT_PROXYARP"
  278. * Add proxy ARP entry.
  279. * .iP "OPT_IPCP_ACCEPT_LOCAL"
  280. * Accept peer's idea of the local IP address.
  281. * .iP "OPT_IPCP_ACCEPT_REMOTE"
  282. * Accept peer's idea of the remote IP address.
  283. * .iP "OPT_NO_IP"
  284. * Disable IP address negotiation.
  285. * .iP "OPT_NO_ACC"
  286. * Disable address/control compression.
  287. * .iP "OPT_NO_PC"
  288. * Disable protocol field compression.
  289. * .iP "OPT_NO_VJ"
  290. * Disable VJ (Van Jacobson) compression.
  291. * .iP "OPT_NO_VJCCOMP"
  292. * Disable VJ (Van Jacobson) connnection ID compression.
  293. * .iP "OPT_NO_ASYNCMAP"
  294. * Disable async map negotiation.
  295. * .iP "OPT_NO_MN"
  296. * Disable magic number negotiation.
  297. * .iP "OPT_NO_MRU"
  298. * Disable MRU (Maximum Receive Unit) negotiation.
  299. * .iP "OPT_NO_PAP"
  300. * Do not allow PAP authentication with peer.
  301. * .iP "OPT_NO_CHAP"
  302. * Do not allow CHAP authentication with peer.
  303. * .iP "OPT_REQUIRE_PAP"
  304. * Require PAP authentication with peer.
  305. * .iP "OPT_REQUIRE_CHAP"
  306. * Require CHAP authentication with peer.
  307. * .iP "OPT_LOGIN"
  308. * Use the login password database for PAP authentication of peer.
  309. * .iP "OPT_DEBUG"
  310. * Enable PPP daemon debug mode.
  311. * .iP "OPT_DRIVER_DEBUG"
  312. * Enable PPP driver debug mode.
  313. * .LP
  314. *
  315. * The remaining members of the PPP_OPTIONS structure specify PPP configurations
  316. * options that require string values.  These options are:
  317. * .iP "char *asyncmap"
  318. * Set the desired async map to the specified string.
  319. * .iP "char *escape_chars"
  320. * Set the chars to escape on transmission to the specified string.
  321. * .iP "char *vj_max_slots"
  322. * Set maximum number of VJ compression header slots to the specified string.
  323. * .iP "char *netmask"
  324. * Set netmask value for negotiation to the specified string.
  325. * .iP "char *mru"
  326. * Set MRU value for negotiation to the specified string.
  327. * .iP "char *mtu"
  328. * Set MTU (Maximum Transmission Unit) value for negotiation to the
  329. * specified string.
  330. * .iP "char *lcp_echo_failure"
  331. * Set the maximum number of consecutive LCP echo failures to the specified
  332. * string.
  333. * .iP "char *lcp_echo_interval"
  334. * Set the interval in seconds between LCP echo requests to the specified string.
  335. * .iP "char *lcp_restart"
  336. * Set the timeout in seconds for the LCP negotiation to the specified string.
  337. * .iP "char *lcp_max_terminate"
  338. * Set the maximum number of transmissions for LCP termination requests
  339. * to the specified string.
  340. * .iP "char *lcp_max_configure"
  341. * Set the maximum number of transmissions for LCP configuration
  342. * requests to the specified string.
  343. * .iP "char *lcp_max_failure"
  344. * Set the maximum number of LCP configuration NAKs to the specified string.
  345. * .iP "char *ipcp_restart"
  346. * Set the timeout in seconds for IPCP negotiation to the specified string.
  347. * .iP "char *ipcp_max_terminate"
  348. * Set the maximum number of transmissions for IPCP termination requests
  349. * to the specified string.
  350. * .iP "char *ipcp_max_configure"
  351. * Set the maximum number of transmissions for IPCP configuration requests
  352. * to the specified string.
  353. * .iP "char *ipcp_max_failure"
  354. * Set the maximum number of IPCP configuration NAKs to the specified string.
  355. * .iP "char *local_auth_name"
  356. * Set the local name for authentication to the specified string.
  357. * .iP "char *remote_auth_name"
  358. * Set the remote name for authentication to the specified string.
  359. * .iP "char *pap_file"
  360. * Get PAP secrets from the specified file.  This option is necessary
  361. * if either peer requires PAP authentication.
  362. * .iP "char *pap_user_name"
  363. * Set the user name for PAP authentication with the peer to the
  364. * specified string.
  365. * .iP "char *pap_passwd"
  366. * Set the password for PAP authentication with the peer to the specified string.
  367. * .iP "char *pap_restart"
  368. * Set the timeout in seconds for PAP negotiation to the specified string.
  369. * .iP "char *pap_max_authreq"
  370. * Set the maximum number of transmissions for PAP authentication
  371. * requests to the specified string.
  372. * .iP "char *chap_file"
  373. * Get CHAP secrets from the specified file.  This option is necessary
  374. * if either peer requires CHAP authentication.
  375. * .iP "char *chap_restart"
  376. * Set the timeout in seconds for CHAP negotiation to the specified string.
  377. * .iP "char *chap_interval"
  378. * Set the interval in seconds for CHAP rechallenge to the specified string.
  379. * .iP "char *chap_max_challenge"
  380. * Set the maximum number of transmissions for CHAP challenge to the
  381. * specified string.
  382. *
  383. * CONFIGURATION OPTIONS FILE:
  384. * The optional parameter <fOptions> specifies configuration options for
  385. * the PPP link.  If NULL, this parameter is ignored, otherwise it
  386. * is assumed to be the name of a configuration options file.  The format
  387. * of the options file is one option per line; comment lines start with "#".
  388. * The following options are recognized:
  389. * .iP "no_all"
  390. * Do not request/allow any options.
  391. * .iP "passive_mode"
  392. * Set passive mode.
  393. * .iP "silent_mode"
  394. * Set silent mode.
  395. * .iP "defaultroute"
  396. * Add default route.
  397. * .iP "proxyarp"
  398. * Add proxy ARP entry.
  399. * .iP "ipcp_accept_local"
  400. * Accept peer's idea of the local IP address.
  401. * .iP "ipcp_accept_remote"
  402. * Accept peer's idea of the remote IP address.
  403. * .iP "no_ip"
  404. * Disable IP address negotiation.
  405. * .iP "no_acc"
  406. * Disable address/control compression.
  407. * .iP "no_pc"
  408. * Disable protocol field compression.
  409. * .iP "no_vj"
  410. * Disable VJ (Van Jacobson) compression.
  411. * .iP "no_vjccomp"
  412. * Disable VJ (Van Jacobson) connnection ID compression.
  413. * .iP "no_asyncmap"
  414. * Disable async map negotiation.
  415. * .iP "no_mn"
  416. * Disable magic number negotiation.
  417. * .iP "no_mru"
  418. * Disable MRU (Maximum Receive Unit) negotiation.
  419. * .iP "no_pap"
  420. * Do not allow PAP authentication with peer.
  421. * .iP "no_chap"
  422. * Do not allow CHAP authentication with peer.
  423. * .iP "require_pap"
  424. * Require PAP authentication with peer.
  425. * .iP "require_chap"
  426. * Require CHAP authentication with peer.
  427. * .iP "login"
  428. * Use the login password database for PAP authentication of peer.
  429. * .iP "debug"
  430. * Enable PPP daemon debug mode.
  431. * .iP "driver_debug"
  432. * Enable PPP driver debug mode.
  433. * .iP "asyncmap <value>"
  434. * Set the desired async map to the specified value.
  435. * .iP "escape_chars <value>"
  436. * Set the chars to escape on transmission to the specified value.
  437. * .iP "vj_max_slots <value>"
  438. * Set maximum number of VJ compression header slots to the specified value.
  439. * .iP "netmask <value>"
  440. * Set netmask value for negotiation to the specified value.
  441. * .iP "mru <value>"
  442. * Set MRU value for negotiation to the specified value.
  443. * .iP "mtu <value>"
  444. * Set MTU value for negotiation to the specified value.
  445. * .iP "lcp_echo_failure <value>"
  446. * Set the maximum consecutive LCP echo failures to the specified value.
  447. * .iP "lcp_echo_interval <value>"
  448. * Set the interval in seconds between LCP echo requests to the specified value.
  449. * .iP "lcp_restart <value>"
  450. * Set the timeout in seconds for the LCP negotiation to the specified value.
  451. * .iP "lcp_max_terminate <value>"
  452. * Set the maximum number of transmissions for LCP termination requests
  453. * to the specified value.
  454. * .iP "lcp_max_configure <value>"
  455. * Set the maximum number of transmissions for LCP configuration
  456. * requests to the specified value.
  457. * .iP "lcp_max_failure <value>"
  458. * Set the maximum number of LCP configuration NAKs to the specified value.
  459. * .iP "ipcp_restart <value>"
  460. * Set the timeout in seconds for IPCP negotiation to the specified value.
  461. * .iP "ipcp_max_terminate <value>"
  462. * Set the maximum number of transmissions for IPCP termination requests
  463. * to the specified value.
  464. * .iP "ipcp_max_configure <value>"
  465. * Set the maximum number of transmissions for IPCP configuration requests
  466. * to the specified value.
  467. * .iP "ipcp_max_failure <value>"
  468. * Set the maximum number of IPCP configuration NAKs to the specified value.
  469. * .iP "local_auth_name <name>"
  470. * Set the local name for authentication to the specified name.
  471. * .iP "remote_auth_name <name>"
  472. * Set the remote name for authentication to the specified name.
  473. * .iP "pap_file <file>"
  474. * Get PAP secrets from the specified file.  This option is necessary
  475. * if either peer requires PAP authentication.
  476. * .iP "pap_user_name <name>"
  477. * Set the user name for PAP authentication with the peer to the specified name.
  478. * .iP "pap_passwd <password>
  479. * Set the password for PAP authentication with the peer to the specified
  480. * password.
  481. * .iP "pap_restart <value>"
  482. * Set the timeout in seconds for PAP negotiation to the specified value.
  483. * .iP "pap_max_authreq <value>"
  484. * Set the maximum number of transmissions for PAP authentication
  485. * requests to the specified value.
  486. * .iP "chap_file <file>"
  487. * Get CHAP secrets from the specified file.  This option is necessary
  488. * if either peer requires CHAP authentication.
  489. * .iP "chap_restart <value>"
  490. * Set the timeout in seconds for CHAP negotiation to the specified value.
  491. * .iP "chap_interval <value>"
  492. * Set the interval in seconds for CHAP rechallenge to the specified value.
  493. * .iP "chap_max_challenge <value>"
  494. * Set the maximum number of transmissions for CHAP challenge to the
  495. * specified value.
  496. *
  497. * AUTHENTICATION:
  498. * The VxWorks PPP implementation supports two separate user authentication
  499. * protocols: the Password Authentication Protocol (PAP) and the
  500. * Challenge-Handshake Authentication Protocol (CHAP).  If authentication is
  501. * required by either peer, it must be satisfactorily completed before the
  502. * PPP link becomes fully operational.  If authentication fails, the link
  503. * will be automatically terminated.
  504. *
  505. * EXAMPLES:
  506. * The following routine initializes a PPP interface that uses the
  507. * target's second serial port (`/tyCo/1').  The local IP address is
  508. * 90.0.0.1; the IP address of the remote peer is 90.0.0.10.  The baud
  509. * rate is the default rate for the <tty> device.  VJ compression
  510. * and authentication have been disabled, and LCP echo requests have been
  511. * enabled.
  512. *
  513. * .CS
  514. * PPP_OPTIONS pppOpt; /@ PPP configuration options @/
  515. *
  516. * void routine ()
  517. *     {
  518. *     pppOpt.flags = OPT_PASSIVE_MODE | OPT_NO_PAP | OPT_NO_CHAP | OPT_NO_VJ;
  519. *     pppOpt.lcp_echo_interval = "30";
  520. *     pppOpt.lcp_echo_failure = "10";
  521. *
  522. *     pppInit (0, "/tyCo/1", "90.0.0.1", "90.0.0.10", 0, &pppOpt, NULL);
  523. *     }
  524. * .CE
  525. *
  526. * The following routine generates the same results as the previous example.
  527. * The difference is that the configuration options are obtained from
  528. * a file rather than a structure.
  529. * .CS
  530. * pppFile = "phobos:/tmp/ppp_options"; /@ PPP configuration options file @/
  531. *
  532. * void routine ()
  533. *     {
  534. *     pppInit (0, "/tyCo/1", "90.0.0.1", "90.0.0.10", 0, NULL, pppFile);
  535. *     }
  536. * .CE
  537. * where phobos:/tmp/ppp_options contains:
  538. *
  539. * .CS
  540. *     passive
  541. *     no_pap
  542. *     no_chap
  543. *     no_vj
  544. *     lcp_echo_interval 30
  545. *     lcp_echo_failure 10
  546. * .CE
  547. *
  548. * RETURNS:
  549. * OK, or ERROR if the PPP interface cannot be initialized because the
  550. * daemon task cannot be spawned or memory is insufficient.
  551. *
  552. * SEE ALSO: pppShow, pppDelete(),
  553. * .pG "Network"
  554. */
  555. int pppInit
  556.     (
  557.     int unit, /* PPP interface unit number to initialize */
  558.     char *devname, /* name of the <tty> device to be used */
  559.     char *local_addr, /* local IP address of the PPP interface */
  560.     char *remote_addr, /* remote peer IP address of the PPP link */
  561.     int baud, /* baud rate of <tty>; NULL = default */
  562.     PPP_OPTIONS *pOptions, /* PPP options structure pointer */
  563.     char *fOptions /* PPP options file name */
  564.     )
  565.     {
  566.     int status;
  567.     if (ppp_if[unit] != NULL) {
  568.         fprintf(stderr, "PPP Unit %d already in usern", unit);
  569.         return(ERROR);
  570.     }
  571.     if ((ppp_parms[unit] = (PPP_PARMS *)calloc(1, sizeof(PPP_PARMS))) == NULL) {
  572. fprintf(stderr, "Unable to allocate memory for ppp parmetersrn");
  573. return(ERROR);
  574.     }
  575.     /* Save parameters in case they're local variables */
  576.     ppp_parms[unit]->unit = unit;
  577.     ppp_parms[unit]->baud = baud;
  578.     if (devname)
  579.         ppp_parms[unit]->devname = (char *)stringdup(devname);
  580.     else
  581.         ppp_parms[unit]->devname = (char *)stringdup("");
  582.     if (local_addr)
  583.         ppp_parms[unit]->local_addr = (char *)stringdup(local_addr);
  584.     else
  585.         ppp_parms[unit]->local_addr = (char *)stringdup("");
  586.     if (remote_addr)
  587.         ppp_parms[unit]->remote_addr = (char *)stringdup(remote_addr);
  588.     else
  589.         ppp_parms[unit]->remote_addr = (char *)stringdup("");
  590.     if (fOptions)
  591.         ppp_parms[unit]->filename = (char *)stringdup(fOptions);
  592.     ppp_parms[unit]->task_name = (char *)malloc(strlen(ppp_task_name) + 2);
  593.     sprintf(ppp_parms[unit]->task_name, "%s%x", ppp_task_name, unit);
  594.     if (pOptions)
  595.         bcopy((char *)pOptions, (char *)&ppp_parms[unit]->options,
  596.       sizeof(PPP_OPTIONS));
  597.     status = taskSpawn(ppp_parms[unit]->task_name,
  598.        ppp_task_priority,
  599.        ppp_task_options,
  600.                        ppp_task_stack_size, (FUNCPTR)ppp_task,
  601.        ppp_parms[unit]->unit,
  602.        (int)ppp_parms[unit]->devname,
  603.        (int)ppp_parms[unit]->local_addr,
  604.        (int)ppp_parms[unit]->remote_addr,
  605.        ppp_parms[unit]->baud,
  606.        (int)&ppp_parms[unit]->options,
  607.        (int)ppp_parms[unit]->filename,
  608.        0, 0, 0);
  609.     if (status == ERROR)
  610.         return(ERROR);
  611.     else
  612.         return(OK);
  613.     }
  614. /*******************************************************************************
  615. *
  616. * ppp_task - PPP daemon task
  617. *
  618. * This is the entry point for the PPP daemon task.
  619. *
  620. * NOMANUAL
  621. */
  622. void ppp_task(unit, devname, local_addr, remote_addr, baud, pOptions, fOptions)
  623.     int unit;
  624.     char *devname;
  625.     char *local_addr;
  626.     char *remote_addr;
  627.     int baud;
  628.     PPP_OPTIONS *pOptions;
  629.     char *fOptions;
  630. {
  631.     sigset_t mask;
  632.     struct sigaction sa;
  633.     int i;
  634.     char user[MAXNAMELEN];
  635.     if ((ppp_if[unit] = (PPP_TASK_VARS *)calloc(1, sizeof(PPP_TASK_VARS))) == NULL) {
  636. fprintf(stderr, "Unable to allocate memory for ppp taskrn");
  637. return;
  638.     }
  639.     if (taskVarAdd(0, (int *)&ppp_unit) != OK) {
  640.         fprintf(stderr, "Unable to add task variablern");
  641. ppp_if[unit] = NULL;
  642.         return;
  643.     }
  644.     /* Initialize ppp task variables */
  645.     ppp_unit = ppp_if[unit]->ifunit = unit;
  646.     ppp_if[unit]->debug = 0;
  647.     ppp_if[unit]->unknownProto = 0;
  648.     ppp_if[unit]->fd = ERROR;
  649.     ppp_if[unit]->s = ERROR;
  650.     ppp_if[unit]->options = pOptions;
  651.     ppp_if[unit]->task_id = taskIdSelf();
  652.     ppp_if[unit]->hungup = 0;
  653.     strcpy(ppp_if[unit]->devname, devname);
  654. #ifdef VXW5_1
  655.     ppp_if[unit]->timer_id = timer_create (CLOCK_REALTIME, NULL);
  656. #else /* VXW5_1 */
  657.     timer_create (CLOCK_REALTIME, NULL, &ppp_if[unit]->timer_id);
  658. #endif /* VXW5_1 */
  659.     if (ppp_if[unit]->timer_id < (timer_t)0) {
  660.         fprintf(stderr, "timer_create failedrn");
  661. ppp_if[unit] = NULL;
  662.         return;
  663.     }
  664.     if (timer_connect(ppp_if[unit]->timer_id, alrm, 0) < 0) {
  665.         fprintf(stderr, "timer_connect failedrn");
  666. ppp_if[unit] = NULL;
  667.         return;
  668.     }
  669.     if (gethostname(ppp_if[unit]->hostname, MAXNAMELEN) < 0 ) {
  670.         fprintf(stderr, "couldn't get hostnamern");
  671. ppp_if[unit] = NULL;
  672.         return;
  673.     }
  674.     ppp_if[unit]->hostname[MAXNAMELEN-1] = 0;
  675.     /*
  676.      * Open the serial device and set it up to be the ppp interface.
  677.      */
  678.     if (pppopen(unit, devname) == ERROR) {
  679.         fprintf(stderr, "ppp%d: error openning the %s interfacern",
  680.     unit, devname);
  681. ppp_if[unit] = NULL;
  682.         return;
  683.     }
  684.     /* initialize the authentication secrets table (vxWorks) */
  685.     (void) pppSecretLibInit ();
  686.     /*
  687.      * Initialize to the standard option set, then parse, in order,
  688.      * the system options file, the user's options file, and the command
  689.      * line arguments.
  690.      */
  691.     for (i = 0; i < N_PROTO; i++)
  692.         (*prottbl[i].init)(unit);
  693.     if (!parse_args(unit, devname, local_addr, remote_addr, baud, ppp_if[unit]->options, fOptions))
  694.         die(unit, 1);
  695.     /* set up the serial device as a ppp interface */
  696.     establish_ppp();
  697.     check_auth_options();
  698.     setipdefault();
  699.     
  700.     magic_init();
  701.     remCurIdGet(user, NULL);
  702.     syslog (LOG_NOTICE, "ppp %s.%d started by %s", VERSION, PATCHLEVEL, user);
  703.     /* Get an internet socket for doing socket ioctl's on. */
  704.     if ((ppp_if[unit]->s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  705.         syslog(LOG_NOTICE, "socket error");
  706.         die(unit, 1);
  707.     }
  708.     /*
  709.      * Compute mask of all interesting signals and install signal handlers
  710.      * for each.  Only one signal handler may be active at a time.  Therefore,
  711.      * all other signals should be masked when any handler is executing.
  712.      */
  713.     sigemptyset(&mask);
  714.     sigaddset(&mask, SIGHUP);
  715.     sigaddset(&mask, SIGINT);
  716.     sigaddset(&mask, SIGALRM);
  717.     sigaddset(&mask, SIGIO);
  718. #define SIGNAL(s, handler)      { 
  719.         sa.sa_handler = (void (*)())handler; 
  720.         if (sigaction(s, &sa, NULL) < 0) { 
  721.             syslog(LOG_ERR, "sigaction(%d) error", s); 
  722.             die(unit, 1); 
  723.         } 
  724.     }
  725.     sa.sa_mask = mask;
  726.     sa.sa_flags = 0;
  727.     SIGNAL(SIGHUP, hup); /* Hangup */
  728.     SIGNAL(SIGINT, intr); /* Interrupt */
  729.     SIGNAL(SIGTERM, term); /* Terminate */
  730.     SIGNAL(SIGALRM, alrm); /* Timeout */
  731.     SIGNAL(SIGIO, io); /* Input available */
  732.     signal(SIGUSR1, incdebug); /* Increment debug flag */
  733.     signal(SIGUSR2, nodebug); /* Reset debug flag */
  734.     /*
  735.      * Block SIGIOs and SIGPOLLs for now
  736.      */
  737.     sigemptyset(&mask);
  738.     sigaddset(&mask, SIGIO);
  739.     sigprocmask(SIG_BLOCK, &mask, NULL);
  740.     /* set line speed, flow control, etc. */
  741.     set_up_tty(ppp_if[unit]->fd);
  742.     /* run connection hook routine */
  743.     if ((pppHookRtns[unit] != NULL) && 
  744. (pppHookRtns[unit]->connectHook != NULL))
  745. {
  746.         if (((*pppHookRtns[unit]->connectHook) (unit, ppp_if[unit]->fd)) 
  747.     == ERROR)
  748.     {
  749.             syslog(LOG_ERR, "connect hook failed");
  750.             die(unit, 1);
  751.     }
  752.         syslog(LOG_INFO, "Connected...");
  753. }
  754.     MAINDEBUG((LOG_INFO, "Using interface ppp%d", unit));
  755.     (void) sprintf(ppp_if[unit]->ifname, "ppp%d", unit);
  756.     /*
  757.      * Block all signals, start opening the connection, and  wait for
  758.      * incoming signals (reply, timeout, etc.).
  759.      */
  760.     syslog (LOG_NOTICE, "Connect: %s <--> %s", ppp_if[unit]->ifname,
  761.            ppp_if[unit]->devname);
  762.     sigprocmask(SIG_BLOCK, &mask, NULL); /* Block signals now */
  763.     lcp_lowerup(unit); /* XXX Well, sort of... */
  764.     lcp_open(unit); /* Start protocol */
  765.     sigemptyset(&mask);
  766.     for (ppp_if[unit]->phase = PHASE_ESTABLISH, errno = 0;
  767.  ppp_if[unit]->phase != PHASE_DEAD;) {
  768. sigsuspend(&mask); /* Wait for next signal */
  769. if (errno != EINTR)
  770.     {
  771.             syslog(LOG_ERR, "ppp_task: sigsuspend error!");
  772.     break;
  773.     }
  774.         errno = 0; /* reset errno */
  775.     }
  776.     /* run disconnection hook routine */
  777.     if ((pppHookRtns[unit] != NULL) && 
  778. (pppHookRtns[unit]->disconnectHook != NULL))
  779. {
  780.         if (((*pppHookRtns[unit]->disconnectHook) (unit, ppp_if[unit]->fd))
  781.     == ERROR)
  782.     {
  783.             syslog(LOG_WARNING, "disconnect hook failed");
  784.             die(unit, 1);
  785.     }
  786.         syslog(LOG_INFO, "Disconnected...");
  787. }
  788.     die(unit, 1);
  789. }
  790.   
  791. /*******************************************************************************
  792. *
  793. * pppDelete - delete a PPP network interface
  794. *
  795. * This routine deletes the Point-to-Point Protocol (PPP) network interface
  796. * specified by the unit number <unit>.
  797. *
  798. * A Link Control Protocol (LCP) terminate request packet is sent to notify
  799. * the peer of the impending PPP link shut-down.  The associated serial
  800. * interface (<tty>) is then detached from the PPP driver, and the PPP interface
  801. * is deleted from the list of network interfaces.  Finally, all resources
  802. * associated with the PPP link are returned to the VxWorks system.
  803. *
  804. * RETURNS: N/A
  805. */
  806. void pppDelete
  807.     (
  808.     int unit /* PPP interface unit number to delete */
  809.     )
  810.     {
  811.     struct wordlist *next;
  812.     struct wordlist *wp;
  813.  
  814.     if  (ppp_if[unit] != NULL)
  815.     {
  816.         if  ((pppHookRtns[unit] != NULL) &&
  817.          (pppHookRtns[unit]->disconnectHook != NULL))
  818.             {
  819.             if  (ERROR ==
  820.                  (*pppHookRtns[unit]->disconnectHook)(unit, ppp_if[unit]->fd))
  821.                 {
  822.                 syslog(LOG_WARNING, "disconnect hook failed");
  823.                 }
  824.             }
  825.     
  826.     /* check for any clients' addresses */
  827.     wp = ppp_if [unit]->addresses;
  828.     while (wp != NULL) 
  829.         {
  830.         next = wp->next;
  831.         free(wp);
  832.         wp = next;
  833.         }
  834.     netJobAdd ((FUNCPTR)kill, ppp_if[unit]->task_id, SIGTERM, 0, 0, 0);
  835.     }
  836.     }
  837. /*
  838.  * Translate from bits/second to a speed_t.
  839.  */
  840. static int
  841. translate_speed(bps)
  842.     int bps;
  843. {
  844.     return bps;
  845. }
  846. /*
  847.  * translate from a speed_t to bits/second.
  848.  */
  849. static int
  850. baud_rate_of(speed)
  851.     int speed;
  852. {
  853.     return speed;
  854. }
  855. /*
  856.  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
  857.  * at the requested speed, etc.  If `local' is true, set CLOCAL
  858.  * regardless of whether the modem option was specified.
  859.  */
  860. static int
  861. set_up_tty(fd)
  862.     int fd;
  863. {
  864.     int speed;
  865.     int state;
  866.     /*
  867.      * Put the tty in raw mode
  868.      */
  869.     if ((state = ioctl(fd, FIOGETOPTIONS, NULL)) == ERROR) {
  870.         syslog(LOG_ERR, "ioctl(FIOGETOPTIONS) error");
  871.         die(ppp_unit, 1);
  872.     }
  873.     if (!ppp_if[ppp_unit]->restore_term)
  874.         ppp_if[ppp_unit]->ttystate = state;
  875.     speed = translate_speed(ppp_if[ppp_unit]->inspeed);
  876.     if (ioctl(fd, FIOOPTIONS, OPT_RAW) < 0) {
  877.         syslog(LOG_ERR, "ioctl(FIOOPTIONS) error");
  878.         die(ppp_unit, 1);
  879.     }
  880.     if (speed && ioctl(fd, FIOBAUDRATE, speed) == ERROR) {
  881.         syslog(LOG_ERR, "ioctl(FIOBAUDRATE) error");
  882.         die(ppp_unit, 1);
  883.     }
  884.     ppp_if[ppp_unit]->baud_rate = baud_rate_of(speed);
  885.     ppp_if[ppp_unit]->restore_term = TRUE;
  886.     return 0;
  887. }
  888.   
  889. /*
  890.  * die - like quit, except we can specify an exit status.
  891.  */
  892. void
  893. die(unit, status)
  894.     int unit;
  895.     int status;
  896. {
  897.     fsm *f = &ppp_if[unit]->lcp_fsm;
  898.     lcp_close(unit); /* Close connection */
  899.     if (f->flags & (OPT_PASSIVE | OPT_SILENT))
  900. return; 
  901.     MAINDEBUG((LOG_INFO, " Exitting."));
  902.     cleanup(unit, status, NULL);
  903.     if (status)
  904.         exit(status);
  905. }
  906. /*
  907.  * cleanup - restore anything which needs to be restored before we exit
  908.  */
  909. static void
  910. cleanup(unit, status, arg)
  911.     int unit;
  912.     int status;
  913.     caddr_t arg;
  914. {
  915.     struct callout *freep = NULL;
  916.     struct callout *list = NULL;
  917.     if (unit < 0 || unit > NPPP)
  918.         return;
  919.     {
  920.         disestablish_ppp();
  921. if (ppp_if[unit]->restore_term) {
  922.             if (ioctl(ppp_if[unit]->fd, FIOSETOPTIONS, ppp_if[unit]->ttystate) == ERROR)
  923.             syslog(LOG_ERR, "ioctl(FIOSETOPTIONS) error");
  924.         }
  925.         pppclose(unit);
  926.         ppp_if[unit]->fd = ERROR;
  927.     }
  928.     if (ppp_if[unit]->s != ERROR)
  929.         close(ppp_if[unit]->s);
  930.     if (!status)
  931.         if (ppp_if[unit]->task_id)
  932.             taskDelete(ppp_if[unit]->task_id);
  933.     timer_delete(ppp_if[unit]->timer_id);
  934.     /* clean-up callout structures */
  935.     list = ppp_if [ppp_unit]->callout;
  936.     while (list)
  937. {
  938. freep = list;
  939. list = list->c_next;
  940. free ((char *) freep);
  941. freep = NULL;
  942. }
  943.     free(ppp_parms[unit]->task_name);
  944.     if (ppp_parms[unit]->devname)
  945.         free(ppp_parms[unit]->devname);
  946.     if (ppp_parms[unit]->local_addr)
  947.         free(ppp_parms[unit]->local_addr);
  948.     if (ppp_parms[unit]->remote_addr)
  949.         free(ppp_parms[unit]->remote_addr);
  950.     if (ppp_parms[unit]->filename)
  951.         free(ppp_parms[unit]->filename);
  952.     free((char *)ppp_parms[unit]);
  953.     if (ppp_if[unit]->options->pap_file)
  954.         free(ppp_if[unit]->options->pap_file);
  955.     if (ppp_if[unit]->options->chap_file)
  956.         free(ppp_if[unit]->options->chap_file);
  957.     if ((char *)ppp_if[unit])
  958.         free((char *)ppp_if[unit]);
  959.     ppp_if[unit] = NULL;
  960. }
  961.   
  962. /*
  963.  * ppp_timeout - Schedule a timeout.
  964.  *
  965.  * Note that this timeout takes the number of seconds, NOT hz (as in
  966.  * the kernel).
  967.  */
  968. void
  969. ppp_timeout(func, arg, seconds)
  970.     void (*func)();
  971.     caddr_t arg;
  972.     int seconds;
  973. {
  974.     struct itimerspec itv;
  975.     struct callout *newp, **oldpp;
  976.     
  977.     MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.", (int) func, (int) arg, seconds));
  978.   
  979.     /*
  980.      * Allocate timeout.
  981.      */
  982.     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
  983.       syslog(LOG_ERR, "Out of memory in timeout()!");
  984.       die(ppp_unit, 1);
  985.     }
  986.     newp->c_arg = arg;
  987.     newp->c_func = func;
  988.     
  989.     /*
  990.      * Find correct place to link it in and decrement its time by the
  991.      * amount of time used by preceding timeouts.
  992.      */
  993.     for (oldpp = &(ppp_if[ppp_unit]->callout);
  994.          *oldpp && (*oldpp)->c_time <= seconds;
  995.          oldpp = &(*oldpp)->c_next)
  996.         seconds -= (*oldpp)->c_time;
  997.     newp->c_time = seconds;
  998.     newp->c_next = *oldpp;
  999.     if (*oldpp)
  1000.         (*oldpp)->c_time -= seconds;
  1001.     *oldpp = newp;
  1002.     
  1003.     /*
  1004.      * If this is now the first callout then we have to set a new
  1005.      * itimer.
  1006.      */
  1007.     if (ppp_if[ppp_unit]->callout == newp) {
  1008.         itv.it_interval.tv_sec = itv.it_interval.tv_nsec =
  1009.             itv.it_value.tv_nsec = 0;
  1010.         itv.it_value.tv_sec = ppp_if[ppp_unit]->callout->c_time;
  1011.         MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in timeout.",
  1012.              itv.it_value.tv_sec));
  1013.         if (timer_settime(ppp_if[ppp_unit]->timer_id, CLOCK_REALTIME, &itv, NULL) < 0) {
  1014.             syslog(LOG_ERR, "setitimer(ITIMER_REAL): error");
  1015.             die(ppp_unit, 1);
  1016.         }
  1017.         if (time(&(ppp_if[ppp_unit]->schedtime)) == ERROR) {
  1018.             syslog(LOG_ERR, "gettimeofday: error");
  1019.             die(ppp_unit, 1);
  1020.         }
  1021.     }
  1022. }
  1023.   
  1024. /*
  1025.  * ppp_untimeout - Unschedule a timeout.
  1026.  */
  1027. void
  1028. ppp_untimeout(func, arg)
  1029.     void (*func)();
  1030.     caddr_t arg;
  1031. {
  1032.     struct itimerspec itv;
  1033.     struct callout **copp, *freep;
  1034.     int reschedule = 0;
  1035.     
  1036.     MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg));
  1037.     
  1038.     /*
  1039.      * If the first callout is unscheduled then we have to set a new
  1040.      * itimer.
  1041.      */
  1042.     if (ppp_if[ppp_unit]->callout &&
  1043.         ppp_if[ppp_unit]->callout->c_func == func &&
  1044.         ppp_if[ppp_unit]->callout->c_arg == arg)
  1045.         reschedule = 1;
  1046.     
  1047.     /*
  1048.      * Find first matching timeout.  Add its time to the next timeouts
  1049.      * time.
  1050.      */
  1051.     for (copp = &(ppp_if[ppp_unit]->callout); *copp; copp = &(*copp)->c_next)
  1052.         if ((*copp)->c_func == func &&
  1053.        (*copp)->c_arg == arg) {
  1054.             freep = *copp;
  1055.             *copp = freep->c_next;
  1056.             if (*copp)
  1057.        (*copp)->c_time += freep->c_time;
  1058.     (void) free((char *) freep);
  1059.             break;
  1060.           }
  1061.     
  1062.     if (reschedule) {
  1063.         itv.it_interval.tv_sec = itv.it_interval.tv_nsec =
  1064.             itv.it_value.tv_nsec = 0;
  1065.         itv.it_value.tv_sec = ppp_if[ppp_unit]->callout ? ppp_if[ppp_unit]->callout->c_time : 0;
  1066.         MAINDEBUG((LOG_DEBUG, "untimeout: Setting itimer for %d seconds in untimeout.",
  1067.              itv.it_value.tv_sec));
  1068.         if (timer_settime(ppp_if[ppp_unit]->timer_id, CLOCK_REALTIME, &itv, NULL) < 0) {
  1069.             syslog(LOG_ERR, "setitimer(ITIMER_REAL): error");
  1070.             die(ppp_unit, 1);
  1071.         }
  1072.         if (time(&(ppp_if[ppp_unit]->schedtime)) == ERROR) {
  1073.             syslog(LOG_ERR, "gettimeofday: error");
  1074.             die(ppp_unit, 1);
  1075.         }
  1076.     }
  1077. }
  1078. /*
  1079.  * adjtimeout - Decrement the first timeout by the amount of time since
  1080.  * it was scheduled.
  1081.  */
  1082. void
  1083. adjtimeout()
  1084. {
  1085.     time_t tv;
  1086.     int timediff;
  1087.     
  1088.     if (ppp_if[ppp_unit]->callout == NULL)
  1089.         return;
  1090.     /*
  1091.      * Make sure that the clock hasn't been warped dramatically.
  1092.      * Account for recently expired, but blocked timer by adding
  1093.      * small fudge factor.
  1094.      */
  1095.     if (time(&tv) == ERROR) {
  1096.         syslog(LOG_ERR, "gettimeofday: error");
  1097.         die(ppp_unit, 1);
  1098.     }
  1099.     timediff = tv - ppp_if[ppp_unit]->schedtime;
  1100.     if (timediff < 0 ||
  1101.         timediff >= ppp_if[ppp_unit]->callout->c_time)
  1102.         return;
  1103.     
  1104.     ppp_if[ppp_unit]->callout->c_time -= timediff; /* OK, Adjust time */
  1105. }
  1106.   
  1107. /*
  1108.  * hup - Catch SIGHUP signal.
  1109.  *
  1110.  * Indicates that the physical layer has been disconnected.
  1111.  */
  1112. static void
  1113. hup(sig)
  1114.     int sig;
  1115. {
  1116.     MAINDEBUG((LOG_INFO, "Hangup (SIGHUP)"));
  1117.     ppp_if[ppp_unit]->hungup = 1; /* they hung up on us! */
  1118.     adjtimeout();                /* Adjust timeouts */
  1119.     die(ppp_unit, 1); /* Close connection */
  1120. }
  1121. /*
  1122.  * term - Catch SIGTERM signal.
  1123.  *
  1124.  * Indicates that we should initiate a graceful disconnect and exit.
  1125.  */
  1126. static void
  1127. term(sig)
  1128.     int sig;
  1129. {
  1130.     fsm *f = &ppp_if[ppp_unit]->lcp_fsm;
  1131.     /* even if OPT_SILENT | OPT_PASSIVE, force die(..) to delete */
  1132.     f->flags = 0;   
  1133.     MAINDEBUG((LOG_INFO, "Terminating link."));
  1134.     adjtimeout();                /* Adjust timeouts */
  1135.     die(ppp_unit, 1); /* Close connection */
  1136. }
  1137. /*
  1138.  * intr - Catch SIGINT signal (DEL/^C).
  1139.  *
  1140.  * Indicates that we should initiate a graceful disconnect and exit.
  1141.  */
  1142. static void
  1143. intr(sig)
  1144.     int sig;
  1145. {
  1146.     MAINDEBUG((LOG_INFO, "Interrupt received: terminating link"));
  1147.     adjtimeout(); /* Adjust timeouts */
  1148.     die(ppp_unit, 1); /* Close connection */
  1149. }
  1150. /*
  1151.  * alrm - Catch SIGALRM signal.
  1152.  *
  1153.  * Indicates a timeout.
  1154.  */
  1155. static void
  1156. alrm(sig)
  1157.     int sig;
  1158. {
  1159.     struct itimerspec itv;
  1160.     struct callout *freep, *list, *last;
  1161.     
  1162.     MAINDEBUG((LOG_DEBUG, "Alarm"));
  1163.     
  1164.     if (ppp_if[ppp_unit]->callout == NULL)
  1165.         return;
  1166.     /*
  1167.      * Get the first scheduled timeout and any that were scheduled
  1168.      * for the same time as a list, and remove them all from callout
  1169.      * list.
  1170.      */
  1171.     list = last = ppp_if[ppp_unit]->callout;
  1172.     while (last->c_next != NULL && last->c_next->c_time == 0)
  1173.         last = last->c_next;
  1174.     ppp_if[ppp_unit]->callout = last->c_next;
  1175.     last->c_next = NULL;
  1176.     /*
  1177.      * Set a new itimer if there are more timeouts scheduled.
  1178.      */
  1179.     if (ppp_if[ppp_unit]->callout) {
  1180.         itv.it_interval.tv_sec = itv.it_interval.tv_nsec = 0;
  1181.         itv.it_value.tv_nsec = 0;
  1182.         itv.it_value.tv_sec = ppp_if[ppp_unit]->callout->c_time;
  1183.         MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in alrm.",
  1184.                    itv.it_value.tv_sec));
  1185.         if (timer_settime(ppp_if[ppp_unit]->timer_id, CLOCK_REALTIME, &itv, NULL) < 0) {
  1186.             syslog(LOG_ERR, "setitimer(ITIMER_REAL): error");
  1187.             die(ppp_unit, 1);
  1188.         }
  1189.         if (time(&ppp_if[ppp_unit]->schedtime) == ERROR) {
  1190.             syslog(LOG_ERR, "gettimeofday: error");
  1191.             die(ppp_unit, 1);
  1192.         }
  1193.     }
  1194.     /*
  1195.      * Now call all the timeout routines scheduled for this time.
  1196.      */
  1197.     while (list) {
  1198.         (*list->c_func)(list->c_arg);
  1199.         freep = list;
  1200.         list = list->c_next;
  1201.         (void) free((char *) freep);
  1202.     }
  1203.   }
  1204.   
  1205. /*
  1206.  * io - Catch SIGIO signal.
  1207.  *
  1208.  * Indicates that incoming data is available.
  1209.  */
  1210. static void
  1211. io()
  1212. {
  1213.     int len, i;
  1214.     u_char *p;
  1215.     u_short protocol;
  1216.     MAINDEBUG((LOG_DEBUG, "IO signal received"));
  1217.     adjtimeout();         /* Adjust timeouts */
  1218.     /* Yup, this is for real */
  1219.     for (;;) {                    /* Read all available packets */
  1220.         p = ppp_if[ppp_unit]->inpacket_buf;/* point to beggining of packet buffer */
  1221.         len = read_packet(ppp_if[ppp_unit]->inpacket_buf);
  1222.         if (len < 0)
  1223.             break;
  1224.         if (ppp_if[ppp_unit]->debug /*&& (debugflags & DBG_INPACKET)*/)
  1225.             log_packet(p, len, "rcvd ");
  1226.         if (len < DLLHEADERLEN) {
  1227.             MAINDEBUG((LOG_DEBUG, "io(): Received short packet."));
  1228.             break;
  1229.         }
  1230.         p += 2;                             /* Skip address and control */
  1231.         GETSHORT(protocol, p);
  1232.         len -= DLLHEADERLEN;
  1233.         /*
  1234.          * Toss all non-LCP packets unless LCP is OPEN.
  1235.          */
  1236.         if (protocol != LCP && ppp_if[ppp_unit]->lcp_fsm.state != OPENED) {
  1237.             MAINDEBUG((LOG_DEBUG, "io(): Received non-LCP packet and LCP not open."
  1238. ));
  1239.             break;
  1240.         }
  1241.         /*
  1242.          * Upcall the proper protocol input routine.
  1243.          */
  1244.         for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
  1245.             if (prottbl[i].protocol == protocol) {
  1246.                 (*prottbl[i].input)(ppp_unit, p, len);
  1247.                 break;
  1248.             }
  1249.         if (i == sizeof (prottbl) / sizeof (struct protent)) {
  1250.     ppp_if[ppp_unit]->unknownProto++;
  1251.             syslog(LOG_WARNING, "input: Unknown protocol (%x) received!",
  1252.    protocol);
  1253.             lcp_sprotrej(ppp_unit, p - DLLHEADERLEN,
  1254.          len + DLLHEADERLEN);
  1255.         }
  1256.     }
  1257. }
  1258. /*
  1259.  * demuxprotrej - Demultiplex a Protocol-Reject.
  1260.  */
  1261. void
  1262. demuxprotrej
  1263.     (
  1264.     int unit,
  1265.     u_short protocol
  1266.     )
  1267. {
  1268.     int i;
  1269.     
  1270.     /*
  1271.      * Upcall the proper Protocol-Reject routine.
  1272.      */
  1273.     for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
  1274.         if (prottbl[i].protocol == protocol) {
  1275.             (*prottbl[i].protrej)(unit);
  1276.             return;
  1277.         }
  1278.     syslog(LOG_WARNING,
  1279.    "demuxprotrej: Unrecognized Protocol-Reject for protocol %d!",
  1280.    protocol);
  1281. }
  1282. /*
  1283.  * incdebug - Catch SIGUSR1 signal.
  1284.  *
  1285.  * Increment debug flag.
  1286.  */
  1287. /*ARGSUSED*/
  1288. static void
  1289. incdebug(sig)
  1290.     int sig;
  1291. {
  1292.     syslog(LOG_INFO, "Debug turned ON, Level %d", ppp_if[ppp_unit]->debug);
  1293.     ppp_if[ppp_unit]->debug++;
  1294. }
  1295. /*
  1296.  * nodebug - Catch SIGUSR2 signal.
  1297.  *
  1298.  * Turn off debugging.
  1299.  */
  1300. /*ARGSUSED*/
  1301. static void
  1302. nodebug(sig)
  1303.     int sig;
  1304. {
  1305.     ppp_if[ppp_unit]->debug = 0;
  1306. }
  1307. #ifdef notyet
  1308. /*
  1309.  * device_script - run a program to connect or disconnect the
  1310.  * serial device.
  1311.  */
  1312. int
  1313. device_script(program, in, out)
  1314.     char *program;
  1315.     int in, out;
  1316. {
  1317.     int pid;
  1318.     int status;
  1319.     sigset_t mask;
  1320.     sigemptyset(&mask);
  1321.     sigaddset(&mask, SIGINT);
  1322.     sigaddset(&mask, SIGHUP);
  1323.     sigprocmask(SIG_BLOCK, &mask, &mask);
  1324.     pid = fork();
  1325.     if (pid < 0) {
  1326.         syslog(LOG_ERR, "fork: %m");
  1327.         die(1);
  1328.     }
  1329.     if (pid == 0) {
  1330.         setreuid(getuid(), getuid());
  1331.         setregid(getgid(), getgid());
  1332.         sigprocmask(SIG_SETMASK, &mask, NULL);
  1333.         dup2(in, 0);
  1334.         dup2(out, 1);
  1335.         execl("/bin/sh", "sh", "-c", program, (char *)0);
  1336.         syslog(LOG_ERR, "could not exec /bin/sh: %m");
  1337.         _exit(99);
  1338.         /* NOTREACHED */
  1339.     }
  1340.     while (waitpid(pid, &status, 0) < 0) {
  1341.         if (errno == EINTR)
  1342.             continue;
  1343.         syslog(LOG_ERR, "waiting for (dis)connection process: %m");
  1344.         die(1);
  1345.     }
  1346.     sigprocmask(SIG_SETMASK, &mask, NULL);
  1347.     return (status == 0 ? 0 : -1);
  1348. }
  1349. /*
  1350.  * run-program - execute a program with given arguments,
  1351.  * but don't wait for it.
  1352.  * If the program can't be executed, logs an error unless
  1353.  * must_exist is 0 and the program file doesn't exist.
  1354.  */
  1355. int
  1356. run_program(prog, args, must_exist)
  1357.     char *prog;
  1358.     char **args;
  1359.     int must_exist;
  1360. {
  1361.     int pid;
  1362.     pid = fork();
  1363.     if (pid == -1) {
  1364.         syslog(LOG_ERR, "can't fork to run %s: %m", prog);
  1365.         return -1;
  1366.     }
  1367.     if (pid == 0) {
  1368.         execv(prog, args);
  1369.         if (must_exist || errno != ENOENT)
  1370.             syslog(LOG_WARNING, "can't execute %s: %m", prog);
  1371.         _exit(-1);
  1372.     }
  1373.     MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
  1374.     ++n_children;
  1375.     return 0;
  1376. }
  1377. #endif /* notyet */
  1378. /*
  1379.  * log_packet - format a packet and log it.
  1380.  */
  1381. char line[256];                 /* line to be logged accumulated here */
  1382. char *linep;
  1383. void
  1384. log_packet(p, len, prefix)
  1385.     u_char *p;
  1386.     int len;
  1387.     char *prefix;
  1388. {
  1389.     strcpy(line, prefix);
  1390.     linep = line + strlen(line);
  1391.     format_packet(p, len, pr_log, NULL);
  1392.     if (linep != line)
  1393.         syslog(LOG_DEBUG, "%s", line);
  1394. }
  1395. /*
  1396.  * format_packet - make a readable representation of a packet,
  1397.  * calling `printer(arg, format, ...)' to output it.
  1398.  */
  1399. void
  1400. format_packet(p, len, printer, arg)
  1401.     u_char *p;
  1402.     int len;
  1403.     void (*printer) __ARGS((void *, char *, ...));
  1404.     void *arg;
  1405. {
  1406.     int i, n;
  1407.     u_short proto;
  1408.     u_char x;
  1409.     if (len >= DLLHEADERLEN && p[0] == ALLSTATIONS && p[1] == UI) {
  1410.         p += 2;
  1411.         GETSHORT(proto, p);
  1412.         len -= DLLHEADERLEN;
  1413.         for (i = 0; i < N_PROTO; ++i)
  1414.             if (proto == prottbl[i].protocol)
  1415.                 break;
  1416.         if (i < N_PROTO) {
  1417.             printer(arg, "[%s", prottbl[i].name);
  1418.             n = (*prottbl[i].printpkt)(p, len, printer, arg);
  1419.             printer(arg, "]");
  1420.             p += n;
  1421.             len -= n;
  1422.         } else {
  1423.             printer(arg, "[proto=0x%x]", proto);
  1424.         }
  1425.     }
  1426.     for (; len > 0; --len) {
  1427.         GETCHAR(x, p);
  1428.         printer(arg, " %.2x", x);
  1429.     }
  1430. }
  1431. #ifdef __STDC__
  1432. #include <stdarg.h>
  1433. void
  1434. pr_log(void *arg, char *fmt, ...)
  1435. {
  1436.     int n;
  1437.     va_list pvar;
  1438.     char buf[256];
  1439.     va_start(pvar, fmt);
  1440.     vsprintf(buf, fmt, pvar);
  1441.     va_end(pvar);
  1442.     n = strlen(buf);
  1443.     if (linep + n + 1 > line + sizeof(line)) {
  1444.         syslog(LOG_DEBUG, "%s", line);
  1445.         linep = line;
  1446.     }
  1447.     strcpy(linep, buf);
  1448.     linep += n;
  1449. }
  1450. #else /* __STDC__ */
  1451. #include <varargs.h>
  1452. void
  1453. pr_log(arg, fmt, va_alist)
  1454. void *arg;
  1455. char *fmt;
  1456. va_dcl
  1457. {
  1458.     int n;
  1459.     va_list pvar;
  1460.     char buf[256];
  1461.     va_start(pvar);
  1462.     vsprintf(buf, fmt, pvar);
  1463.     va_end(pvar);
  1464.     n = strlen(buf);
  1465.     if (linep + n + 1 > line + sizeof(line)) {
  1466.         syslog(LOG_DEBUG, "%s", line);
  1467.         linep = line;
  1468.     }
  1469.     strcpy(linep, buf);
  1470.     linep += n;
  1471. }
  1472. #endif
  1473. /*
  1474.  * print_string - print a readable representation of a string using
  1475.  * printer.
  1476.  */
  1477. void
  1478. print_string(p, len, printer, arg)
  1479.     char *p;
  1480.     int len;
  1481.     void (*printer) __ARGS((void *, char *, ...));
  1482.     void *arg;
  1483. {
  1484.     int c;
  1485.     printer(arg, """);
  1486.     for (; len > 0; --len) {
  1487.         c = *p++;
  1488.         if (' ' <= c && c <= '~')
  1489.             printer(arg, "%c", c);
  1490.         else
  1491.             printer(arg, "\%.3o", c);
  1492.     }
  1493.     printer(arg, """);
  1494. }
  1495. /*
  1496.  * novm - log an error message saying we ran out of memory, and die.
  1497.  */
  1498. void
  1499. novm(msg)
  1500.     char *msg;
  1501. {
  1502.     syslog(LOG_ERR, "Memory exhausted allocating %s", msg);
  1503.     die(ppp_unit, 1);
  1504. }