source: rtems/c/src/libnetworking/pppd/rtemsmain.c @ d0d73ec

4.104.114.84.95
Last change on this file since d0d73ec was 0286b9f, checked in by Joel Sherrill <joel.sherrill@…>, on 01/31/02 at 21:42:11

2001-01-31 Mike Siers <mikes@…>

  • Nice Update of PPPD support which eliminates the requiremetn that drivers be in the termios TASK_DRIVEN mode. Mike did significant testing and reports that it seems to be more stable and handle larger packets better. This patch replaces the termios tasks with more general pppd network driver tasks. The functions pppinput() and pppstart() get called from the interrupt service routine.
  • Makefile.am, configure.ac, net/Makefile.am, net/bpf.h, net/ethernet.h, net/if.c, net/if.h, net/if_arp.h, net/if_dl.h, net/if_ethersubr.c, net/if_llc.h, net/if_loop.c, net/if_ppp.h, net/if_pppvar.h, net/if_types.h, net/netisr.h, net/ppp-comp.h, net/ppp_defs.h, net/pppcompress.h, net/radix.c, net/radix.h, net/raw_cb.c, net/raw_cb.h, net/raw_usrreq.c, net/route.c, net/route.h, net/rtsock.c, pppd/Makefile.am, pppd/README, pppd/STATUS, pppd/auth.c, pppd/cbcp.c, pppd/ccp.c, pppd/ccp.h, pppd/chap.c, pppd/chap.h, pppd/chap_ms.c, pppd/chap_ms.h, pppd/chat.c, pppd/demand.c, pppd/fsm.c, pppd/fsm.h, pppd/ipcp.c, pppd/ipcp.h, pppd/ipxcp.c, pppd/ipxcp.h, pppd/lcp.c, pppd/lcp.h, pppd/magic.c, pppd/magic.h, pppd/options.c, pppd/patchlevel.h, pppd/pathnames.h, pppd/pppd.8, pppd/pppd.h, pppd/rtemsmain.c, pppd/rtemspppd.c, pppd/rtemspppd.h, pppd/sys-rtems.c, pppd/upap.c, pppd/upap.h, pppd/utils.c, pppd/example/README, pppd/example/netconfig.h, wrapup/Makefile.am: Modified.
  • net/bsd-comp.c, net/if_ppp.c, net/ppp-deflate.c, net/ppp.h, net/ppp_tty.c, net/pppcompress.c, net/zlib.c, net/zlib.h: New file.
  • modem/, modem/.cvsignore, modem/Makefile.am, modem/ppp.c, modem/ppp.h, modem/ppp_tty.c, modem/pppcompress.c: Subdirectory removed.
  • Property mode set to 100644
File size: 22.1 KB
Line 
1/*
2 * main.c - Point-to-Point Protocol main module
3 *
4 * Copyright (c) 1989 Carnegie Mellon University.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by Carnegie Mellon University.  The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#define RCSID   "$Id$"
21
22#include <stdio.h>
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <signal.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <netdb.h>
31#include <pwd.h>
32#include <setjmp.h>
33#include <sys/param.h>
34#include <sys/types.h>
35#include <sys/wait.h>
36#include <sys/time.h>
37#include <sys/resource.h>
38#include <sys/stat.h>
39#include <sys/socket.h>
40#include <netinet/in.h>
41
42#include <rtems.h>
43#include <rtems/rtems_bsdnet.h>
44
45#include "pppd.h"
46#include "magic.h"
47#include "fsm.h"
48#include "lcp.h"
49#include "ipcp.h"
50#ifdef INET6
51#include "ipv6cp.h"
52#endif
53#include "upap.h"
54#include "chap.h"
55#include "ccp.h"
56#include "pathnames.h"
57#include "patchlevel.h"
58#include "rtemsdialer.h"
59
60#ifdef CBCP_SUPPORT
61#include "cbcp.h"
62#endif
63
64#ifdef IPX_CHANGE
65#include "ipxcp.h"
66#endif /* IPX_CHANGE */
67#ifdef AT_CHANGE
68#include "atcp.h"
69#endif
70
71static const char rcsid[] = RCSID;
72
73/* interface vars */
74char ifname[32];                /* Interface name */
75int pppifunit;                  /* Interface unit number */
76
77char *progname;                 /* Name of this program */
78char hostname[MAXNAMELEN];      /* Our hostname */
79static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
80
81int ttyfd;                      /* Serial port file descriptor */
82int baud_rate;                  /* Actual bits/second for serial device */
83int hungup;                     /* terminal has been hung up */
84int privileged;                 /* we're running as real uid root */
85int need_holdoff;               /* need holdoff period before restarting */
86int detached;                   /* have detached from terminal */
87struct stat devstat;            /* result of stat() on devnam */
88int prepass = 0;                /* doing prepass to find device name */
89int devnam_fixed;               /* set while in options.ttyxx file */
90volatile int status;            /* exit status for pppd */
91int unsuccess;                  /* # unsuccessful connection attempts */
92int do_callback;                /* != 0 if we should do callback next */
93int doing_callback;             /* != 0 if we are doing callback */
94char *callback_script;          /* script for doing callback */
95dialerfp pppd_dialer;
96
97int (*holdoff_hook) __P((void)) = NULL;
98int (*new_phase_hook) __P((int)) = NULL;
99
100static int fd_ppp = -1;         /* fd for talking PPP */
101static int pty_master;          /* fd for master side of pty */
102static int pty_slave;           /* fd for slave side of pty */
103static int real_ttyfd;          /* fd for actual serial port (not pty) */
104
105int phase;                      /* where the link is at */
106int kill_link;
107int open_ccp_flag;
108
109char **script_env;              /* Env. variable values for scripts */
110int s_env_nalloc;               /* # words avail at script_env */
111
112u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
113u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
114
115char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
116
117static struct timeval start_time;       /* Time when link was started. */
118
119struct pppd_stats link_stats;
120int link_connect_time;
121int link_stats_valid;
122
123/* Prototypes for procedures local to this file. */
124
125static void cleanup __P((void));
126static void close_tty __P((void));
127static void get_input __P((void));
128static void calltimeout __P((void));
129static struct timeval *timeleft __P((struct timeval *));
130static void holdoff_end __P((void *));
131static int device_script __P((int, int, char *));
132
133extern  char    *ttyname __P((int));
134extern  char    *getlogin __P((void));
135int pppdmain __P((int, char *[]));
136
137/*
138 * PPP Data Link Layer "protocol" table.
139 * One entry per supported protocol.
140 * The last entry must be NULL.
141 */
142struct protent *protocols[] = {
143    &lcp_protent,
144    &pap_protent,
145    &chap_protent,
146#ifdef CBCP_SUPPORT
147    &cbcp_protent,
148#endif
149    &ipcp_protent,
150#ifdef INET6
151    &ipv6cp_protent,
152#endif
153    &ccp_protent,
154#ifdef IPX_CHANGE
155    &ipxcp_protent,
156#endif
157#ifdef AT_CHANGE
158    &atcp_protent,
159#endif
160    NULL
161};
162
163int
164pppdmain(argc, argv)
165    int argc;
166    char *argv[];
167{
168    int i, fdflags, t;
169    char *connector;
170    struct timeval timo;
171    struct protent *protp;
172
173    new_phase(PHASE_INITIALIZE);
174
175    script_env = NULL;
176    hostname[MAXNAMELEN-1] = 0;
177    privileged = 1;
178    privileged_option = 1;
179
180    /*
181     * Initialize magic number generator now so that protocols may
182     * use magic numbers in initialization.
183     */
184    magic_init();
185
186#ifdef XXX_XXX
187    /* moved code the the rtems_pppd_reset_options function */
188
189    /*
190     * Initialize to the standard option set, then parse, in order,
191     * the system options file, the user's options file,
192     * the tty's options file, and the command line arguments.
193     */
194    for (i = 0; (protp = protocols[i]) != NULL; ++i)
195        (*protp->init)(0);
196#endif
197
198    progname = *argv;
199
200
201    if (!ppp_available()) {
202        option_error(no_ppp_msg);
203        return(EXIT_NO_KERNEL_SUPPORT);
204    }
205
206    /*
207     * Check that the options given are valid and consistent.
208     */
209    if (!sys_check_options()) {
210        return(EXIT_OPTION_ERROR);
211    }
212    if (!auth_check_options()) {
213        return(EXIT_OPTION_ERROR);
214    }
215    for (i = 0; (protp = protocols[i]) != NULL; ++i)
216        if (protp->check_options != NULL)
217            (*protp->check_options)();
218
219    /* default holdoff to 0 if no connect script has been given */
220    if (connect_script == 0 && !holdoff_specified)
221        holdoff = 0;
222
223    if (default_device)
224        nodetach = 1;
225
226    /*
227     * Initialize system-dependent stuff.
228     */
229    sys_init();
230    /* if (debug)
231        setlogmask(LOG_UPTO(LOG_DEBUG));
232    */
233
234    do_callback = 0;
235    for (;;) {
236
237        need_holdoff = 1;
238        ttyfd = -1;
239        real_ttyfd = -1;
240        status = EXIT_OK;
241        ++unsuccess;
242        doing_callback = do_callback;
243        do_callback = 0;
244
245        new_phase(PHASE_SERIALCONN);
246
247        /*
248         * Get a pty master/slave pair if the pty, notty, or record
249         * options were specified.
250         */
251        strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
252        pty_master = -1;
253        pty_slave = -1;
254
255        /*
256         * Open the serial device and set it up to be the ppp interface.
257         * First we open it in non-blocking mode so we can set the
258         * various termios flags appropriately.  If we aren't dialling
259         * out and we want to use the modem lines, we reopen it later
260         * in order to wait for the carrier detect signal from the modem.
261         */
262        hungup = 0;
263        kill_link = 0;
264        connector = doing_callback? callback_script: connect_script;
265        if (devnam[0] != 0) {
266            for (;;) {
267                /* If the user specified the device name, become the
268                   user before opening it. */
269                int err;
270                ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
271                err = errno;
272                if (ttyfd >= 0) {
273                    break;
274                }
275                errno = err;
276                if (err != EINTR) {
277                    error("Failed to open %s: %m", devnam);
278                    status = EXIT_OPEN_FAILED;
279                }
280                if (!persist || err != EINTR)
281                    goto fail;
282            }
283            if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
284                || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
285                warn("Couldn't reset non-blocking mode on device: %m");
286
287            /*
288             * Set line speed, flow control, etc.
289             * If we have a non-null connection or initializer script,
290             * on most systems we set CLOCAL for now so that we can talk
291             * to the modem before carrier comes up.  But this has the
292             * side effect that we might miss it if CD drops before we
293             * get to clear CLOCAL below.  On systems where we can talk
294             * successfully to the modem with CLOCAL clear and CD down,
295             * we could clear CLOCAL at this point.
296             */
297            set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0)
298                               || initializer != NULL));
299            real_ttyfd = ttyfd;
300        }
301
302        /* run connection script */
303        if ((connector && connector[0]) || initializer) {
304            if (real_ttyfd != -1) {
305                /* XXX do this if doing_callback == CALLBACK_DIALIN? */
306                if (!default_device && modem) {
307                    setdtr(real_ttyfd, 0);      /* in case modem is off hook */
308                    sleep(1);
309                    setdtr(real_ttyfd, 1);
310                }
311            }
312
313            if (initializer && initializer[0]) {
314                if (device_script(ttyfd, DIALER_INIT, initializer) < 0) {
315                    error("Initializer script failed");
316                    status = EXIT_INIT_FAILED;
317                    goto fail;
318                }
319                if (kill_link)
320                    goto disconnect;
321
322                info("Serial port initialized.");
323            }
324
325            if (connector && connector[0]) {
326                if (device_script(ttyfd, DIALER_CONNECT, connector) < 0) {
327                    error("Connect script failed");
328                    status = EXIT_CONNECT_FAILED;
329                    goto fail;
330                }
331                if (kill_link)
332                    goto disconnect;
333
334                info("Serial connection established.");
335            }
336
337            /* set line speed, flow control, etc.;
338               clear CLOCAL if modem option */
339            if (real_ttyfd != -1)
340                set_up_tty(real_ttyfd, 0);
341
342            if (doing_callback == CALLBACK_DIALIN)
343                connector = NULL;
344        }
345
346        /* reopen tty if necessary to wait for carrier */
347        if (connector == NULL && modem && devnam[0] != 0) {
348            for (;;) {
349                if ((i = open(devnam, O_RDWR)) >= 0)
350                    break;
351                if (errno != EINTR) {
352                    error("Failed to reopen %s: %m", devnam);
353                    status = EXIT_OPEN_FAILED;
354                }
355                if (!persist || errno != EINTR || hungup || kill_link)
356                    goto fail;
357            }
358            close(i);
359        }
360
361        info("Serial connection established.");
362        sleep(1);
363
364        /* run welcome script, if any */
365        if (welcomer && welcomer[0]) {
366            if (device_script(ttyfd, DIALER_WELCOME, welcomer) < 0)
367                warn("Welcome script failed");
368        }
369
370        /* set up the serial device as a ppp interface */
371        fd_ppp = establish_ppp(ttyfd);
372        if (fd_ppp < 0) {
373            status = EXIT_FATAL_ERROR;
374            goto disconnect;
375        }
376
377        if (!demand) {
378            info("Using interface ppp%d", pppifunit);
379            slprintf(ifname, sizeof(ifname), "ppp%d", pppifunit);
380        }
381
382        /*
383         * Start opening the connection and wait for
384         * incoming events (reply, timeout, etc.).
385         */
386        notice("Connect: %s <--> %s", ifname, ppp_devnam);
387        gettimeofday(&start_time, NULL);
388
389        lcp_lowerup(0);
390        lcp_open(0);            /* Start protocol */
391
392        open_ccp_flag = 0;
393        status = EXIT_NEGOTIATION_FAILED;
394        new_phase(PHASE_ESTABLISH);
395        while (phase != PHASE_DEAD) {
396            wait_input(timeleft(&timo));
397            calltimeout();
398            get_input();
399
400            if (kill_link) {
401                lcp_close(0, "User request");
402                kill_link = 0;
403            }
404            if (open_ccp_flag) {
405                if (phase == PHASE_NETWORK || phase == PHASE_RUNNING) {
406                    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
407                    (*ccp_protent.open)(0);
408                }
409                open_ccp_flag = 0;
410            }
411        }
412
413        /*
414         * If we may want to bring the link up again, transfer
415         * the ppp unit back to the loopback.  Set the
416         * real serial device back to its normal mode of operation.
417         */
418        clean_check();
419        if (demand)
420            restore_loop();
421        disestablish_ppp(ttyfd);
422        fd_ppp = -1;
423        if (!hungup)
424            lcp_lowerdown(0);
425
426        /*
427         * Run disconnector script, if requested.
428         * XXX we may not be able to do this if the line has hung up!
429         */
430    disconnect:
431        if (disconnect_script && !hungup) {
432            new_phase(PHASE_DISCONNECT);
433            if (real_ttyfd >= 0)
434                set_up_tty(real_ttyfd, 1);
435            if (device_script(ttyfd, DIALER_DISCONNECT, disconnect_script) < 0) {
436                warn("disconnect script failed");
437            } else {
438                info("Serial link disconnected.");
439            }
440        }
441
442    fail:
443        if (pty_master >= 0)
444            close(pty_master);
445        if (pty_slave >= 0)
446            close(pty_slave);
447        if (real_ttyfd >= 0)
448            close_tty();
449
450        if (!persist || (maxfail > 0 && unsuccess >= maxfail))
451            break;
452
453        kill_link = 0;
454        if (demand)
455            demand_discard();
456        t = need_holdoff? holdoff: 0;
457        if (holdoff_hook)
458            t = (*holdoff_hook)();
459        if (t > 0) {
460            new_phase(PHASE_HOLDOFF);
461            TIMEOUT(holdoff_end, NULL, t);
462            do {
463                wait_input(timeleft(&timo));
464
465                calltimeout();
466                if (kill_link) {
467                    kill_link = 0;
468                    new_phase(PHASE_DORMANT); /* allow signal to end holdoff */
469                }
470            } while (phase == PHASE_HOLDOFF);
471            if (!persist)
472                break;
473        }
474    }
475
476    die(status);
477    return status;
478}
479
480/*
481 * holdoff_end - called via a timeout when the holdoff period ends.
482 */
483static void
484holdoff_end(arg)
485    void *arg;
486{
487    new_phase(PHASE_DORMANT);
488}
489
490/* List of protocol names, to make our messages a little more informative. */
491struct protocol_list {
492    u_short     proto;
493    const char  *name;
494} protocol_list[] = {
495    { 0x21,     "IP" },
496    { 0x23,     "OSI Network Layer" },
497    { 0x25,     "Xerox NS IDP" },
498    { 0x27,     "DECnet Phase IV" },
499    { 0x29,     "Appletalk" },
500    { 0x2b,     "Novell IPX" },
501    { 0x2d,     "VJ compressed TCP/IP" },
502    { 0x2f,     "VJ uncompressed TCP/IP" },
503    { 0x31,     "Bridging PDU" },
504    { 0x33,     "Stream Protocol ST-II" },
505    { 0x35,     "Banyan Vines" },
506    { 0x39,     "AppleTalk EDDP" },
507    { 0x3b,     "AppleTalk SmartBuffered" },
508    { 0x3d,     "Multi-Link" },
509    { 0x3f,     "NETBIOS Framing" },
510    { 0x41,     "Cisco Systems" },
511    { 0x43,     "Ascom Timeplex" },
512    { 0x45,     "Fujitsu Link Backup and Load Balancing (LBLB)" },
513    { 0x47,     "DCA Remote Lan" },
514    { 0x49,     "Serial Data Transport Protocol (PPP-SDTP)" },
515    { 0x4b,     "SNA over 802.2" },
516    { 0x4d,     "SNA" },
517    { 0x4f,     "IP6 Header Compression" },
518    { 0x6f,     "Stampede Bridging" },
519    { 0xfb,     "single-link compression" },
520    { 0xfd,     "1st choice compression" },
521    { 0x0201,   "802.1d Hello Packets" },
522    { 0x0203,   "IBM Source Routing BPDU" },
523    { 0x0205,   "DEC LANBridge100 Spanning Tree" },
524    { 0x0231,   "Luxcom" },
525    { 0x0233,   "Sigma Network Systems" },
526    { 0x8021,   "Internet Protocol Control Protocol" },
527    { 0x8023,   "OSI Network Layer Control Protocol" },
528    { 0x8025,   "Xerox NS IDP Control Protocol" },
529    { 0x8027,   "DECnet Phase IV Control Protocol" },
530    { 0x8029,   "Appletalk Control Protocol" },
531    { 0x802b,   "Novell IPX Control Protocol" },
532    { 0x8031,   "Bridging NCP" },
533    { 0x8033,   "Stream Protocol Control Protocol" },
534    { 0x8035,   "Banyan Vines Control Protocol" },
535    { 0x803d,   "Multi-Link Control Protocol" },
536    { 0x803f,   "NETBIOS Framing Control Protocol" },
537    { 0x8041,   "Cisco Systems Control Protocol" },
538    { 0x8043,   "Ascom Timeplex" },
539    { 0x8045,   "Fujitsu LBLB Control Protocol" },
540    { 0x8047,   "DCA Remote Lan Network Control Protocol (RLNCP)" },
541    { 0x8049,   "Serial Data Control Protocol (PPP-SDCP)" },
542    { 0x804b,   "SNA over 802.2 Control Protocol" },
543    { 0x804d,   "SNA Control Protocol" },
544    { 0x804f,   "IP6 Header Compression Control Protocol" },
545    { 0x006f,   "Stampede Bridging Control Protocol" },
546    { 0x80fb,   "Single Link Compression Control Protocol" },
547    { 0x80fd,   "Compression Control Protocol" },
548    { 0xc021,   "Link Control Protocol" },
549    { 0xc023,   "Password Authentication Protocol" },
550    { 0xc025,   "Link Quality Report" },
551    { 0xc027,   "Shiva Password Authentication Protocol" },
552    { 0xc029,   "CallBack Control Protocol (CBCP)" },
553    { 0xc081,   "Container Control Protocol" },
554    { 0xc223,   "Challenge Handshake Authentication Protocol" },
555    { 0xc281,   "Proprietary Authentication Protocol" },
556    { 0,        NULL },
557};
558
559/*
560 * protocol_name - find a name for a PPP protocol.
561 */
562const char *
563protocol_name(proto)
564    int proto;
565{
566    struct protocol_list *lp;
567
568    for (lp = protocol_list; lp->proto != 0; ++lp)
569        if (proto == lp->proto)
570            return lp->name;
571    return NULL;
572}
573
574/*
575 * get_input - called when incoming data is available.
576 */
577static void
578get_input(void)
579{
580    int len, i;
581    u_char *p;
582    u_short protocol;
583    struct protent *protp;
584
585    p = inpacket_buf;   /* point to beginning of packet buffer */
586
587    len = read_packet(inpacket_buf);
588    if (len < 0)
589        return;
590
591    if (len == 0) {
592        notice("Modem hangup");
593        hungup = 1;
594        status = EXIT_HANGUP;
595        lcp_lowerdown(0);       /* serial link is no longer available */
596        link_terminated(0);
597        return;
598    }
599
600    if (debug /*&& (debugflags & DBG_INPACKET)*/)
601        dbglog("rcvd %P", p, len);
602
603    if (len < PPP_HDRLEN) {
604        MAINDEBUG(("io(): Received short packet."));
605        return;
606    }
607
608    p += 2;                             /* Skip address and control */
609    GETSHORT(protocol, p);
610    len -= PPP_HDRLEN;
611
612    /*
613     * Toss all non-LCP packets unless LCP is OPEN.
614     */
615    if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
616        MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
617        return;
618    }
619
620    /*
621     * Until we get past the authentication phase, toss all packets
622     * except LCP, LQR and authentication packets.
623     */
624    if (phase <= PHASE_AUTHENTICATE
625        && !(protocol == PPP_LCP || protocol == PPP_LQR
626             || protocol == PPP_PAP || protocol == PPP_CHAP)) {
627        MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
628                   protocol, phase));
629        return;
630    }
631
632    /*
633     * Upcall the proper protocol input routine.
634     */
635    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
636        if (protp->protocol == protocol && protp->enabled_flag) {
637            (*protp->input)(0, p, len);
638            return;
639        }
640        if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
641            && protp->datainput != NULL) {
642            (*protp->datainput)(0, p, len);
643            return;
644        }
645    }
646
647    if (debug) {
648        const char *pname = protocol_name(protocol);
649        if (pname != NULL)
650            warn("Unsupported protocol '%s' (0x%x) received", pname, protocol);
651        else
652            warn("Unsupported protocol 0x%x received", protocol);
653    }
654    lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
655
656    return;
657}
658
659/*
660 * new_phase - signal the start of a new phase of pppd's operation.
661 */
662void
663new_phase(p)
664    int p;
665{
666    phase = p;
667    if (new_phase_hook)
668        (*new_phase_hook)(p);
669}
670
671/*
672 * die - clean up state and exit with the specified status.
673 */
674void
675die(status)
676    int status;
677{
678    cleanup();
679}
680
681/*
682 * cleanup - restore anything which needs to be restored before we exit
683 */
684/* ARGSUSED */
685static void
686cleanup()
687{
688    sys_cleanup();
689
690    if (fd_ppp >= 0)
691        disestablish_ppp(ttyfd);
692    if (real_ttyfd >= 0)
693        close_tty();
694
695    sys_close();
696}
697
698/*
699 * close_tty - restore the terminal device and close it.
700 */
701static void
702close_tty()
703{
704    /* drop dtr to hang up */
705    if (!default_device && modem) {
706        setdtr(real_ttyfd, 0);
707        /*
708         * This sleep is in case the serial port has CLOCAL set by default,
709         * and consequently will reassert DTR when we close the device.
710         */
711        sleep(1);
712    }
713
714    restore_tty(real_ttyfd);
715
716    close(real_ttyfd);
717    real_ttyfd = -1;
718}
719
720/*
721 * update_link_stats - get stats at link termination.
722 */
723void
724update_link_stats(u)
725    int u;
726{
727    struct timeval now;
728    char numbuf[32];
729
730    if (!get_ppp_stats(u, &link_stats)
731        || gettimeofday(&now, NULL) < 0)
732        return;
733    link_connect_time = now.tv_sec - start_time.tv_sec;
734    link_stats_valid = 1;
735
736    slprintf(numbuf, sizeof(numbuf), "%d", link_connect_time);
737    slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_out);
738    slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_in);
739}
740
741struct  callout {
742    struct timeval      c_time;         /* time at which to call routine */
743    void                *c_arg;         /* argument to routine */
744    void                (*c_func) __P((void *)); /* routine */
745    struct              callout *c_next;
746};
747
748static struct callout *callout = NULL;  /* Callout list */
749static struct timeval timenow;          /* Current time */
750
751/*
752 * timeout - Schedule a timeout.
753 *
754 * Note that this timeout takes the number of seconds, NOT hz (as in
755 * the kernel).
756 */
757void
758ppptimeout(func, arg, time)
759    void (*func) __P((void *));
760    void *arg;
761    int time;
762{
763    struct callout *newp, *p, **pp;
764 
765    MAINDEBUG(("Timeout %p:%p in %d seconds.", func, arg, time));
766 
767    /*
768     * Allocate timeout.
769     */
770    if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
771        fatal("Out of memory in timeout()!");
772    newp->c_arg = arg;
773    newp->c_func = func;
774    gettimeofday(&timenow, NULL);
775    newp->c_time.tv_sec = timenow.tv_sec + time;
776    newp->c_time.tv_usec = timenow.tv_usec;
777 
778    /*
779     * Find correct place and link it in.
780     */
781    for (pp = &callout; (p = *pp); pp = &p->c_next)
782        if (newp->c_time.tv_sec < p->c_time.tv_sec
783            || (newp->c_time.tv_sec == p->c_time.tv_sec
784                && newp->c_time.tv_usec < p->c_time.tv_usec))
785            break;
786    newp->c_next = p;
787    *pp = newp;
788}
789
790
791/*
792 * untimeout - Unschedule a timeout.
793 */
794void
795untimeout(func, arg)
796    void (*func) __P((void *));
797    void *arg;
798{
799    struct callout **copp, *freep;
800 
801    MAINDEBUG(("Untimeout %p:%p.", func, arg));
802 
803    /*
804     * Find first matching timeout and remove it from the list.
805     */
806    for (copp = &callout; (freep = *copp); copp = &freep->c_next)
807        if (freep->c_func == func && freep->c_arg == arg) {
808            *copp = freep->c_next;
809            free((char *) freep);
810            break;
811        }
812}
813
814
815/*
816 * calltimeout - Call any timeout routines which are now due.
817 */
818static void
819calltimeout()
820{
821    struct callout *p;
822
823    while (callout != NULL) {
824        p = callout;
825
826        if (gettimeofday(&timenow, NULL) < 0)
827            fatal("Failed to get time of day: %m");
828        if (!(p->c_time.tv_sec < timenow.tv_sec
829              || (p->c_time.tv_sec == timenow.tv_sec
830                  && p->c_time.tv_usec <= timenow.tv_usec)))
831            break;              /* no, it's not time yet */
832
833        callout = p->c_next;
834        (*p->c_func)(p->c_arg);
835
836        free((char *) p);
837    }
838}
839
840
841/*
842 * timeleft - return the length of time until the next timeout is due.
843 */
844static struct timeval *
845timeleft(tvp)
846    struct timeval *tvp;
847{
848    if (callout == NULL)
849        return NULL;
850
851    gettimeofday(&timenow, NULL);
852    tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
853    tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
854    if (tvp->tv_usec < 0) {
855        tvp->tv_usec += 1000000;
856        tvp->tv_sec -= 1;
857    }
858    if (tvp->tv_sec < 0)
859        tvp->tv_sec = tvp->tv_usec = 0;
860
861    return tvp;
862}
863
864/*
865 * device_script - run a program to talk to the serial device
866 * (e.g. to run the connector or disconnector script).
867 */
868static int device_script(int fd, int mode, char *program)
869{
870    int    iReturn = -1;
871    char   pScript[128];
872
873    /* copyt script into temporary location */
874    strcpy(pScript, program);
875
876    /* check to see if dialer was initialized */
877    if ( !pppd_dialer ) {
878      /* set default dialer to chatmain */
879      pppd_dialer = chatmain;
880    }
881
882    /* check to see if dialer is set */
883    if ( pppd_dialer ) {
884      /* call the dialer */
885      iReturn = (*pppd_dialer)(fd, mode, program);
886    }
887
888    return ( -iReturn );
889}
890
891/*
892 * novm - log an error message saying we ran out of memory, and die.
893 */
894void
895novm(msg)
896    char *msg;
897{
898    fatal("Virtual memory exhausted allocating %s\n", msg);
899}
Note: See TracBrowser for help on using the repository browser.