OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [pppd/] [rtemsmain.c] - Blame information for rev 1779

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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   "rtemsmain.c,v 1.3 2002/01/31 21:40:47 joel Exp"
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
 
71
static const char rcsid[] = RCSID;
72
 
73
/* interface vars */
74
char ifname[32];                /* Interface name */
75
int pppifunit;                  /* Interface unit number */
76
 
77
char *progname;                 /* Name of this program */
78
char hostname[MAXNAMELEN];      /* Our hostname */
79
static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
80
 
81
int ttyfd;                      /* Serial port file descriptor */
82
int baud_rate;                  /* Actual bits/second for serial device */
83
int hungup;                     /* terminal has been hung up */
84
int privileged;                 /* we're running as real uid root */
85
int need_holdoff;               /* need holdoff period before restarting */
86
int detached;                   /* have detached from terminal */
87
struct stat devstat;            /* result of stat() on devnam */
88
int prepass = 0;         /* doing prepass to find device name */
89
int devnam_fixed;               /* set while in options.ttyxx file */
90
volatile int status;            /* exit status for pppd */
91
int unsuccess;                  /* # unsuccessful connection attempts */
92
int do_callback;                /* != 0 if we should do callback next */
93
int doing_callback;             /* != 0 if we are doing callback */
94
char *callback_script;          /* script for doing callback */
95
dialerfp pppd_dialer;
96
 
97
int (*holdoff_hook) __P((void)) = NULL;
98
int (*new_phase_hook) __P((int)) = NULL;
99
 
100
static int fd_ppp = -1;         /* fd for talking PPP */
101
static int pty_master;          /* fd for master side of pty */
102
static int pty_slave;           /* fd for slave side of pty */
103
static int real_ttyfd;          /* fd for actual serial port (not pty) */
104
 
105
int phase;                      /* where the link is at */
106
int kill_link;
107
int open_ccp_flag;
108
 
109
char **script_env;              /* Env. variable values for scripts */
110
int s_env_nalloc;               /* # words avail at script_env */
111
 
112
u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
113
u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
114
 
115
char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
116
 
117
static struct timeval start_time;       /* Time when link was started. */
118
 
119
struct pppd_stats link_stats;
120
int link_connect_time;
121
int link_stats_valid;
122
 
123
/* Prototypes for procedures local to this file. */
124
 
125
static void cleanup __P((void));
126
static void close_tty __P((void));
127
static void get_input __P((void));
128
static void calltimeout __P((void));
129
static struct timeval *timeleft __P((struct timeval *));
130
static void holdoff_end __P((void *));
131
static int device_script __P((int, int, char *));
132
 
133
extern  char    *ttyname __P((int));
134
extern  char    *getlogin __P((void));
135
int 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
 */
142
struct 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
 
163
int
164
pppdmain(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
 */
483
static void
484
holdoff_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. */
491
struct 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
 */
562
const char *
563
protocol_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
 */
577
static void
578
get_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
 */
662
void
663
new_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
 */
674
void
675
die(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 */
685
static void
686
cleanup()
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
 */
701
static void
702
close_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
 */
723
void
724
update_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
 
741
struct  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
 
748
static struct callout *callout = NULL;  /* Callout list */
749
static 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
 */
757
void
758
ppptimeout(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
 */
794
void
795
untimeout(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
 */
818
static void
819
calltimeout()
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
 */
844
static struct timeval *
845
timeleft(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
 */
868
static 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
 */
894
void
895
novm(msg)
896
    char *msg;
897
{
898
    fatal("Virtual memory exhausted allocating %s\n", msg);
899
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.