source: rtems/cpukit/pppd/rtemsmain.c @ 2f1b930

4.104.114.84.9
Last change on this file since 2f1b930 was 2f1b930, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 16, 2001 at 8:42:09 PM

2001-08-16 Mike Siers <mikes@…>

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