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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [ppp/] [current/] [src/] [pppd.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/pppd.c
4
//
5
//==========================================================================
6
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
7
// -------------------------------------------                              
8
// This file is part of eCos, the Embedded Configurable Operating System.   
9
// Copyright (C) 2003 Free Software Foundation, Inc.                        
10
//
11
// eCos is free software; you can redistribute it and/or modify it under    
12
// the terms of the GNU General Public License as published by the Free     
13
// Software Foundation; either version 2 or (at your option) any later      
14
// version.                                                                 
15
//
16
// eCos is distributed in the hope that it will be useful, but WITHOUT      
17
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
18
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
19
// for more details.                                                        
20
//
21
// You should have received a copy of the GNU General Public License        
22
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
23
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
24
//
25
// As a special exception, if other files instantiate templates or use      
26
// macros or inline functions from this file, or you compile this file      
27
// and link it with other works to produce a work based on this file,       
28
// this file does not by itself cause the resulting work to be covered by   
29
// the GNU General Public License. However the source code for this file    
30
// must still be made available in accordance with section (3) of the GNU   
31
// General Public License v2.                                               
32
//
33
// This exception does not invalidate any other reasons why a work based    
34
// on this file might be covered by the GNU General Public License.         
35
// -------------------------------------------                              
36
// ####ECOSGPLCOPYRIGHTEND####                                              
37
// ####BSDALTCOPYRIGHTBEGIN####                                             
38
// -------------------------------------------                              
39
// Portions of this software may have been derived from FreeBSD, OpenBSD,   
40
// or other sources, and if so are covered by the appropriate copyright     
41
// and license included herein.                                             
42
// -------------------------------------------                              
43
// ####BSDALTCOPYRIGHTEND####                                               
44
//==========================================================================
45
 
46
/*
47
 * main.c - Point-to-Point Protocol main module
48
 *
49
 * Copyright (c) 1989 Carnegie Mellon University.
50
 * All rights reserved.
51
 *
52
 * Redistribution and use in source and binary forms are permitted
53
 * provided that the above copyright notice and this paragraph are
54
 * duplicated in all such forms and that any documentation,
55
 * advertising materials, and other materials related to such
56
 * distribution and use acknowledge that the software was developed
57
 * by Carnegie Mellon University.  The name of the
58
 * University may not be used to endorse or promote products derived
59
 * from this software without specific prior written permission.
60
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
61
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
62
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
63
 */
64
 
65
#ifndef lint
66
//static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/main.c,v 1.19.6.1 2002/07/30 19:17:27 nectar Exp $";
67
#endif
68
 
69
#include <stdio.h>
70
#include <ctype.h>
71
#include <stdlib.h>
72
#include <string.h>
73
#include <unistd.h>
74
#include <signal.h>
75
#include <errno.h>
76
#include <fcntl.h>
77
#include <cyg/ppp/syslog.h>
78
#include <sys/param.h>
79
#include <netdb.h>
80
#include <sys/types.h>
81
#ifndef __ECOS
82
#include <sys/wait.h>
83
#endif
84
#include <sys/time.h>
85
#ifndef __ECOS
86
#include <sys/resource.h>
87
#endif
88
#include <sys/stat.h>
89
#include <sys/socket.h>
90
 
91
#define MAXPATHLEN PATH_MAX
92
 
93
#include "cyg/ppp/pppd.h"
94
#include "cyg/ppp/magic.h"
95
#include "cyg/ppp/fsm.h"
96
#include "cyg/ppp/lcp.h"
97
#include "cyg/ppp/ipcp.h"
98
#include "cyg/ppp/upap.h"
99
#include "cyg/ppp/chap.h"
100
#include "cyg/ppp/ccp.h"
101
#include "cyg/ppp/ppp_io.h"
102
 
103
#ifdef CBCP_SUPPORT
104
#include "cbcp.h"
105
#endif
106
 
107
#if defined(SUNOS4)
108
extern char *strerror();
109
#endif
110
 
111
#ifdef IPX_CHANGE
112
#include "ipxcp.h"
113
#endif /* IPX_CHANGE */
114
#ifdef AT_CHANGE
115
#include "atcp.h"
116
#endif
117
 
118
/* options */
119
 
120
#define option_error(msg) db_printf("Option error: %s\n", msg )
121
 
122
 
123
/*
124
 * Variables set by command-line options.
125
 */
126
 
127
int     debug = 1;              /* Debug flag */
128
int     kdebugflag = 1;         /* Tell kernel to print debug messages */
129
int     default_device = 0;      /* Using /dev/tty or equivalent */
130
char    devnam[MAXPATHLEN] = "/dev/ser0";       /* Device name */
131
int     flowctl = CYG_PPP_FLOWCTL_HARDWARE; /* flow control */
132
int     modem  = 0;              /* Use modem control lines */
133
cyg_serial_baud_rate_t  inspeed = 0;     /* Input/Output speed requested */
134
u_int32_t netmask = 0;           /* IP netmask to set on interface */
135
int     lockflag = 0;            /* Create lock file to lock the serial dev */
136
char    *connector = NULL;      /* Script to establish physical link */
137
char    *disconnector = NULL;   /* Script to disestablish physical link */
138
char    *welcomer = NULL;       /* Script to welcome client after connection */
139
int     max_con_attempts = 10;  /* Maximum number of times to try dialing */
140
int     maxconnect = 0;          /* Maximum connect time (seconds) */
141
char    user[MAXNAMELEN] = "nickg";     /* Our name for authenticating ourselves */
142
char    passwd[MAXSECRETLEN] = "xsecretx";      /* Password for PAP */
143
int     auth_required = 0;       /* Peer is required to authenticate */
144
int     proxyarp = 0;            /* Set up proxy ARP entry for peer */
145
int     persist = 0;             /* Reopen link after it goes down */
146
int     uselogin = 0;            /* Use /etc/passwd for checking PAP */
147
int     lcp_echo_interval = 60; /* Interval between LCP echo-requests */
148
int     lcp_echo_fails = 4;     /* Tolerance to unanswered echo-requests */
149
char    our_name[20];           /* Our name for authentication purposes */
150
char    remote_name[20];        /* Peer's name for authentication */
151
int     explicit_remote = 1;    /* remote_name specified with remotename opt */
152
int     usehostname = 0; /* Use hostname for our_name */
153
int     disable_defaultip = 0;  /* Don't use hostname for default IP adrs */
154
//int   demand = 0;             /* Do dial-on-demand */
155
char    *ipparam = NULL;        /* Extra parameter for ip up/down scripts */
156
int     cryptpap = 0;            /* Others' PAP passwords are encrypted */
157
int     idle_time_limit = 60;   /* Shut down link if idle for this long */
158
int     holdoff = 0;             /* Dead time before restarting */
159
int     refuse_pap = 0;          /* Don't wanna auth. ourselves with PAP */
160
int     refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */
161
int     neg_accm = 0;            /* Flag to enable ACCM negotiation */
162
int     conf_accm = 0;           /* Confgurable value of ACCM */
163
 
164
const char    **script;               /* Chat connection script */
165
 
166
 
167
/* interface vars */
168
char ifname[32];                /* Interface name */
169
static int ifunit;              /* Interface unit number */
170
 
171
char *progname;                 /* Name of this program */
172
char cyg_ppp_hostname[MAXNAMELEN];      /* Our hostname */
173
time_t          etime,stime;    /* End and Start time */
174
int             minutes;        /* connection duration */
175
 
176
cyg_io_handle_t tty_handle;     /* IO handle on serial stream */
177
mode_t tty_mode = -1;           /* Original access permissions to tty */
178
int baud_rate;                  /* Actual bits/second for serial device */
179
int hungup;                     /* terminal has been hung up */
180
int privileged;                 /* we're running as real uid root */
181
int need_holdoff;               /* need holdoff period before restarting */
182
 
183
int phase;                      /* where the link is at */
184
int kill_link;
185
int open_ccp_flag;
186
 
187
char **script_env;              /* Env. variable values for scripts */
188
int s_env_nalloc;               /* # words avail at script_env */
189
 
190
u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
191
u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
192
 
193
char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
194
cyg_ppp_stats_t cyg_ppp_stats;
195
 
196
/* Prototypes for procedures local to this file. */
197
 
198
static void cleanup __P((void));
199
static void close_tty __P((void));
200
static void get_input __P((void));
201
static void calltimeout __P((void));
202
static struct timeval *timeleft __P((struct timeval *));
203
//static void holdoff_end __P((void *));
204
static void pr_log __P((void *, char *, ...));
205
 
206
extern  char    *ttyname __P((int));
207
extern  char    *getlogin __P((void));
208
int main __P((int, char *[]));
209
 
210
#ifdef ultrix
211
#undef  O_NONBLOCK
212
#define O_NONBLOCK      O_NDELAY
213
#endif
214
 
215
#ifdef ULTRIX
216
#define setlogmask(x)
217
#endif
218
 
219
/*
220
 * PPP Data Link Layer "protocol" table.
221
 * One entry per supported protocol.
222
 * The last entry must be NULL.
223
 */
224
struct protent *protocols[] = {
225
    &lcp_protent,
226
#ifdef CYGPKG_PPP_PAP
227
    &pap_protent,
228
#endif
229
#ifdef CYGPKG_PPP_CHAP    
230
    &chap_protent,
231
#endif
232
#ifdef CBCP_SUPPORT
233
    &cbcp_protent,
234
#endif
235
    &ipcp_protent,
236
    &ccp_protent,
237
#ifdef IPX_CHANGE
238
    &ipxcp_protent,
239
#endif
240
#ifdef AT_CHANGE
241
    &atcp_protent,
242
#endif
243
    NULL
244
};
245
 
246
 
247
externC void
248
cyg_pppd_main(CYG_ADDRWORD arg)
249
{
250
    int i;
251
    struct timeval timo;
252
    struct protent *protp;
253
    int connect_attempts = 0;
254
 
255
    phase = PHASE_INITIALIZE;
256
 
257
    cyg_ppp_options_install( ((struct tty *)arg)->options );
258
 
259
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
260
        (*protp->init)(0);
261
 
262
    if (!ppp_available()) {
263
        option_error(no_ppp_msg);
264
        exit(1);
265
    }
266
 
267
    /*
268
     * Initialize system-dependent stuff and magic number package.
269
     */
270
    sys_init();
271
    magic_init();
272
    if (debug)
273
        setlogmask(LOG_UPTO(LOG_DEBUG));
274
 
275
 
276
    for (;;) {
277
 
278
        need_holdoff = 1;
279
 
280
        {
281
            Cyg_ErrNo err;
282
            while ((err = cyg_io_lookup(devnam, &tty_handle)) < 0) {
283
                if (err != 0)
284
                    syslog(LOG_ERR, "Failed to open %s: %d", devnam,err);
285
            }
286
 
287
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
288
            if( modem )
289
            {
290
                cyg_uint32 len = sizeof(ppp_tty.serial_callbacks);
291
                ppp_tty.serial_callbacks.fn = cyg_ppp_serial_callback;
292
                ppp_tty.serial_callbacks.priv = (CYG_ADDRWORD)&ppp_tty;
293
 
294
 
295
                err = cyg_io_set_config( tty_handle,
296
                                         CYG_IO_SET_CONFIG_SERIAL_STATUS_CALLBACK,
297
                                         &ppp_tty.serial_callbacks,
298
                                         &len);
299
 
300
                if( err != 0 ) {
301
                    syslog(LOG_ERR, "cyg_io_set_config(serial callbacks): %d",err);
302
                    die(1);
303
                }
304
 
305
            }
306
#endif
307
        }
308
 
309
        hungup = 0;
310
        kill_link = 0;
311
 
312
        /* set line speed, flow control, etc.; clear CLOCAL if modem option */
313
        set_up_tty(tty_handle, 0);
314
 
315
#ifdef CYGPKG_PPP_CHAT          
316
        if( script != NULL )
317
        {
318
            if( !cyg_ppp_chat( devnam, script ) )
319
            {
320
                connect_attempts++;
321
                goto fail;
322
            }
323
        }
324
#endif
325
 
326
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
327
        if( modem )
328
        {
329
            while( !ppp_tty.carrier_detected )
330
                cyg_thread_delay(100);
331
        }
332
#endif
333
 
334
        connect_attempts = 0;    /* we made it through ok */
335
 
336
        /* set up the serial device as a ppp interface */
337
        establish_ppp(tty_handle);
338
 
339
        syslog(LOG_INFO, "Using interface ppp%d", ifunit);
340
        (void) sprintf(ifname, "ppp%d", ifunit);
341
 
342
        /*
343
         * Start opening the connection and wait for
344
         * incoming events (reply, timeout, etc.).
345
         */
346
        syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
347
        stime = time((time_t *) NULL);
348
 
349
        lcp_lowerup(0);
350
        lcp_open(0);             /* Start protocol */
351
        for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
352
            wait_input(timeleft(&timo));
353
            calltimeout();
354
            get_input();
355
            if (kill_link) {
356
                lcp_close(0, "User request");
357
                kill_link = 0;
358
            }
359
            if (open_ccp_flag) {
360
                if (phase == PHASE_NETWORK) {
361
                    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
362
                    (*ccp_protent.open)(0);
363
                }
364
                open_ccp_flag = 0;
365
            }
366
        }
367
 
368
        clean_check();
369
        disestablish_ppp(tty_handle);
370
 
371
#ifdef CYGPKG_PPP_CHAT          
372
    fail:
373
#endif
374
        if (tty_handle != 0)
375
            close_tty();
376
 
377
        /* limit to retries? */
378
        if (max_con_attempts)
379
            if (connect_attempts >= max_con_attempts)
380
                break;
381
 
382
        if (!persist)
383
            die(1);
384
 
385
#if 0
386
        if (holdoff > 0 && need_holdoff) {
387
            phase = PHASE_HOLDOFF;
388
            TIMEOUT(holdoff_end, NULL, holdoff);
389
            do {
390
                wait_time(timeleft(&timo));
391
                calltimeout();
392
                if (kill_link) {
393
                    if (!persist)
394
                        die(0);
395
                    kill_link = 0;
396
                    phase = PHASE_DORMANT; /* allow signal to end holdoff */
397
                }
398
 
399
            } while (phase == PHASE_HOLDOFF);
400
        }
401
#endif
402
 
403
    }
404
 
405
    die(0);
406
}
407
 
408
/*
409
 * get_input - called when incoming data is available.
410
 */
411
static void
412
get_input()
413
{
414
    int len, i;
415
    u_char *p;
416
    u_short protocol;
417
    struct protent *protp;
418
 
419
    p = inpacket_buf;   /* point to beginning of packet buffer */
420
 
421
    len = read_packet(inpacket_buf);
422
 
423
    if (len < 0)
424
        return;
425
 
426
    if (len == 0) {
427
        etime = time((time_t *) NULL);
428
        minutes = (etime-stime)/60;
429
        syslog(LOG_NOTICE, "Modem hangup, connected for %d minutes", (minutes >1) ? minutes : 1);
430
        hungup = 1;
431
        lcp_lowerdown(0);        /* serial link is no longer available */
432
        link_terminated(0);
433
        return;
434
    }
435
 
436
    if (debug /*&& (debugflags & DBG_INPACKET)*/)
437
        log_packet(p, len, "rcvd ", LOG_DEBUG);
438
 
439
    if (len < PPP_HDRLEN) {
440
        MAINDEBUG((LOG_INFO, "io(): Received short packet."));
441
        return;
442
    }
443
 
444
    p += 2;                             /* Skip address and control */
445
    GETSHORT(protocol, p);
446
    len -= PPP_HDRLEN;
447
 
448
    /*
449
     * Toss all non-LCP packets unless LCP is OPEN.
450
     */
451
    if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
452
        MAINDEBUG((LOG_INFO,
453
                   "get_input: Received non-LCP packet when LCP not open."));
454
        return;
455
    }
456
 
457
    /*
458
     * Until we get past the authentication phase, toss all packets
459
     * except LCP, LQR and authentication packets.
460
     */
461
    if (phase <= PHASE_AUTHENTICATE
462
        && !(protocol == PPP_LCP || protocol == PPP_LQR
463
             || protocol == PPP_PAP || protocol == PPP_CHAP)) {
464
        MAINDEBUG((LOG_INFO, "get_input: discarding proto 0x%x in phase %d",
465
                   protocol, phase));
466
        return;
467
    }
468
 
469
    /*
470
     * Upcall the proper protocol input routine.
471
     */
472
    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
473
        if (protp->protocol == protocol && protp->enabled_flag) {
474
            (*protp->input)(0, p, len);
475
            return;
476
        }
477
        if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
478
            && protp->datainput != NULL) {
479
            (*protp->datainput)(0, p, len);
480
            return;
481
        }
482
    }
483
 
484
    if (debug)
485
        syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
486
    lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
487
}
488
 
489
 
490
/*
491
 * quit - Clean up state and exit (with an error indication).
492
 */
493
void
494
quit()
495
{
496
    die(1);
497
}
498
 
499
/*
500
 * die - like quit, except we can specify an exit status.
501
 */
502
void
503
die(status)
504
    int status;
505
{
506
db_printf("%s called\n", __PRETTY_FUNCTION__);
507
#ifndef __ECOS
508
    cleanup();
509
    syslog(LOG_INFO, "Exit.");
510
    exit(status);
511
#else
512
    externC void sys_exit(void);
513
    cleanup();
514
    sys_exit();
515
#endif
516
}
517
 
518
/*
519
 * cleanup - restore anything which needs to be restored before we exit
520
 */
521
/* ARGSUSED */
522
static void
523
cleanup()
524
{
525
db_printf("%s called\n", __PRETTY_FUNCTION__);
526
    sys_cleanup();
527
 
528
    if (tty_handle != 0)
529
        close_tty();
530
}
531
 
532
/*
533
 * close_tty - restore the terminal device and close it.
534
 */
535
static void
536
close_tty()
537
{
538
    disestablish_ppp(tty_handle);
539
 
540
#ifndef __ECOS
541
    /* drop dtr to hang up */
542
    if (modem) {
543
        setdtr(ttyfd, FALSE);
544
        /*
545
         * This sleep is in case the serial port has CLOCAL set by default,
546
         * and consequently will reassert DTR when we close the device.
547
         */
548
        sleep(1);
549
    }
550
#endif
551
 
552
    db_printf("%s called\n", __PRETTY_FUNCTION__);
553
 
554
    restore_tty(tty_handle);
555
 
556
    if( ppp_tty.t_handle != 0 )
557
    {
558
        cyg_ppp_pppclose( &ppp_tty, 0 );
559
        ppp_tty.t_handle = 0;
560
    }
561
 
562
    tty_handle = 0;
563
}
564
 
565
 
566
struct  callout {
567
    struct timeval      c_time;         /* time at which to call routine */
568
    void                *c_arg;         /* argument to routine */
569
    void                (*c_func) __P((void *)); /* routine */
570
    struct              callout *c_next;
571
};
572
 
573
static struct callout *callout = NULL;  /* Callout list */
574
static struct timeval timenow;          /* Current time */
575
 
576
/*
577
 * timeout - Schedule a timeout.
578
 *
579
 * Note that this timeout takes the number of seconds, NOT hz (as in
580
 * the kernel).
581
 */
582
void
583
cyg_ppp_timeout(void (*func) __P((void *)),
584
                void *arg,
585
                int time)
586
{
587
    struct callout *newp, *p, **pp;
588
 
589
    MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
590
               (long) func, (long) arg, time));
591
 
592
    /*
593
     * Allocate timeout.
594
     */
595
    if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
596
        syslog(LOG_ERR, "Out of memory in timeout()!");
597
        die(1);
598
    }
599
    newp->c_arg = arg;
600
    newp->c_func = func;
601
    gettimeofday(&timenow, NULL);
602
    newp->c_time.tv_sec = timenow.tv_sec + time;
603
    newp->c_time.tv_usec = timenow.tv_usec;
604
 
605
    /*
606
     * Find correct place and link it in.
607
     */
608
    for (pp = &callout; (p = *pp); pp = &p->c_next)
609
        if (newp->c_time.tv_sec < p->c_time.tv_sec
610
            || (newp->c_time.tv_sec == p->c_time.tv_sec
611
                && newp->c_time.tv_usec < p->c_time.tv_sec))
612
            break;
613
    newp->c_next = p;
614
    *pp = newp;
615
}
616
 
617
 
618
/*
619
 * untimeout - Unschedule a timeout.
620
 */
621
void
622
cyg_ppp_untimeout(void (*func) __P((void *)),
623
                  void *arg)
624
{
625
    struct callout **copp, *freep;
626
 
627
    MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));
628
 
629
    /*
630
     * Find first matching timeout and remove it from the list.
631
     */
632
    for (copp = &callout; (freep = *copp); copp = &freep->c_next)
633
        if (freep->c_func == func && freep->c_arg == arg) {
634
            *copp = freep->c_next;
635
            (void) free((char *) freep);
636
            break;
637
        }
638
}
639
 
640
 
641
/*
642
 * calltimeout - Call any timeout routines which are now due.
643
 */
644
static void
645
calltimeout()
646
{
647
    struct callout *p;
648
 
649
    while (callout != NULL) {
650
        p = callout;
651
 
652
        if (gettimeofday(&timenow, NULL) < 0) {
653
            syslog(LOG_ERR, "Failed to get time of day: %m");
654
            die(1);
655
        }
656
        if (!(p->c_time.tv_sec < timenow.tv_sec
657
              || (p->c_time.tv_sec == timenow.tv_sec
658
                  && p->c_time.tv_usec <= timenow.tv_usec)))
659
            break;              /* no, it's not time yet */
660
        callout = p->c_next;
661
        (*p->c_func)(p->c_arg);
662
        free((char *) p);
663
    }
664
}
665
 
666
 
667
/*
668
 * timeleft - return the length of time until the next timeout is due.
669
 */
670
static struct timeval *
671
timeleft(tvp)
672
    struct timeval *tvp;
673
{
674
    if (callout == NULL)
675
        return NULL;
676
 
677
    gettimeofday(&timenow, NULL);
678
    tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
679
    tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
680
    if (tvp->tv_usec < 0) {
681
        tvp->tv_usec += 1000000;
682
        tvp->tv_sec -= 1;
683
    }
684
    if (tvp->tv_sec < 0)
685
        tvp->tv_sec = tvp->tv_usec = 0;
686
 
687
    return tvp;
688
}
689
 
690
/*
691
 * log_packet - format a packet and log it.
692
 */
693
 
694
char line[256];                 /* line to be logged accumulated here */
695
char *linep;
696
 
697
void
698
log_packet(p, len, prefix, level)
699
    u_char *p;
700
    int len;
701
    char *prefix;
702
    int level;
703
{
704
    strcpy(line, prefix);
705
    linep = line + strlen(line);
706
    format_packet(p, len, pr_log, NULL);
707
    if (linep != line)
708
        syslog(level, "%s", line);
709
}
710
 
711
/*
712
 * format_packet - make a readable representation of a packet,
713
 * calling `printer(arg, format, ...)' to output it.
714
 */
715
void
716
format_packet(p, len, printer, arg)
717
    u_char *p;
718
    int len;
719
    void (*printer) __P((void *, char *, ...));
720
    void *arg;
721
{
722
    int i, n;
723
    u_short proto;
724
    u_char x;
725
    struct protent *protp;
726
 
727
    if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
728
        p += 2;
729
        GETSHORT(proto, p);
730
        len -= PPP_HDRLEN;
731
        for (i = 0; (protp = protocols[i]) != NULL; ++i)
732
            if (proto == protp->protocol)
733
                break;
734
        if (protp != NULL) {
735
            printer(arg, "[%s", protp->name);
736
            n = (*protp->printpkt)(p, len, printer, arg);
737
            printer(arg, "]");
738
            p += n;
739
            len -= n;
740
        } else {
741
            printer(arg, "[proto=0x%x]", proto);
742
        }
743
    }
744
 
745
    for (; len > 0; --len) {
746
        GETCHAR(x, p);
747
        printer(arg, " %.2x", x);
748
    }
749
}
750
 
751
static void
752
pr_log __V((void *arg, char *fmt, ...))
753
{
754
    int n;
755
    va_list pvar;
756
    char buf[256];
757
 
758
#if __STDC__
759
    va_start(pvar, fmt);
760
#else
761
    void *arg;
762
    char *fmt;
763
    va_start(pvar);
764
    arg = va_arg(pvar, void *);
765
    fmt = va_arg(pvar, char *);
766
#endif
767
 
768
    n = vfmtmsg(buf, sizeof(buf), fmt, pvar);
769
    va_end(pvar);
770
 
771
    if (linep + n + 1 > line + sizeof(line)) {
772
        syslog(LOG_DEBUG, "%s", line);
773
        linep = line;
774
    }
775
    strcpy(linep, buf);
776
    linep += n;
777
}
778
 
779
/*
780
 * print_string - print a readable representation of a string using
781
 * printer.
782
 */
783
void
784
print_string(p, len, printer, arg)
785
    unsigned char *p;
786
    int len;
787
    void (*printer) __P((void *, char *, ...));
788
    void *arg;
789
{
790
    int c;
791
 
792
    printer(arg, "\"");
793
    for (; len > 0; --len) {
794
        c = *p++;
795
        if (' ' <= c && c <= '~') {
796
            if (c == '\\' || c == '"')
797
                printer(arg, "\\");
798
            printer(arg, "%c", c);
799
        } else {
800
            switch (c) {
801
            case '\n':
802
                printer(arg, "\\n");
803
                break;
804
            case '\r':
805
                printer(arg, "\\r");
806
                break;
807
            case '\t':
808
                printer(arg, "\\t");
809
                break;
810
            default:
811
                printer(arg, "\\%.3o", c);
812
            }
813
        }
814
    }
815
    printer(arg, "\"");
816
}
817
 
818
/*
819
 * novm - log an error message saying we ran out of memory, and die.
820
 */
821
void
822
novm(msg)
823
    char *msg;
824
{
825
    syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
826
    die(1);
827
}
828
 
829
/*
830
 * fmtmsg - format a message into a buffer.  Like sprintf except we
831
 * also specify the length of the output buffer, and we handle
832
 * %r (recursive format), %m (error message) and %I (IP address) formats.
833
 * Doesn't do floating-point formats.
834
 * Returns the number of chars put into buf.
835
 */
836
int
837
fmtmsg __V((char *buf, int buflen, char *fmt, ...))
838
{
839
    va_list args;
840
    int n;
841
 
842
#if __STDC__
843
    va_start(args, fmt);
844
#else
845
    char *buf;
846
    int buflen;
847
    char *fmt;
848
    va_start(args);
849
    buf = va_arg(args, char *);
850
    buflen = va_arg(args, int);
851
    fmt = va_arg(args, char *);
852
#endif
853
    n = vfmtmsg(buf, buflen, fmt, args);
854
    va_end(args);
855
    return n;
856
}
857
 
858
/*
859
 * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
860
 */
861
#define OUTCHAR(c)      (buflen > 0? (--buflen, *buf++ = (c)): 0)
862
 
863
int
864
vfmtmsg(buf, buflen, fmt, args)
865
    char *buf;
866
    int buflen;
867
    char *fmt;
868
    va_list args;
869
{
870
    int c, i, n;
871
    int width, prec, fillch;
872
    int base, len, neg, quoted;
873
    unsigned long val = 0;
874
    char *str, *f, *buf0;
875
    unsigned char *p;
876
    char num[32];
877
    time_t t;
878
    static char hexchars[] = "0123456789abcdef";
879
 
880
    buf0 = buf;
881
    --buflen;
882
    while (buflen > 0) {
883
        for (f = fmt; *f != '%' && *f != 0; ++f)
884
            ;
885
        if (f > fmt) {
886
            len = f - fmt;
887
            if (len > buflen)
888
                len = buflen;
889
            memcpy(buf, fmt, len);
890
            buf += len;
891
            buflen -= len;
892
            fmt = f;
893
        }
894
        if (*fmt == 0)
895
            break;
896
        c = *++fmt;
897
        width = prec = 0;
898
        fillch = ' ';
899
        if (c == '0') {
900
            fillch = '0';
901
            c = *++fmt;
902
        }
903
        if (c == '*') {
904
            width = va_arg(args, int);
905
            c = *++fmt;
906
        } else {
907
            while (isdigit(c)) {
908
                width = width * 10 + c - '0';
909
                c = *++fmt;
910
            }
911
        }
912
        if (c == '.') {
913
            c = *++fmt;
914
            if (c == '*') {
915
                prec = va_arg(args, int);
916
                c = *++fmt;
917
            } else {
918
                while (isdigit(c)) {
919
                    prec = prec * 10 + c - '0';
920
                    c = *++fmt;
921
                }
922
            }
923
        }
924
        str = 0;
925
        base = 0;
926
        neg = 0;
927
        ++fmt;
928
        switch (c) {
929
        case 'd':
930
            i = va_arg(args, int);
931
            if (i < 0) {
932
                neg = 1;
933
                val = -i;
934
            } else
935
                val = i;
936
            base = 10;
937
            break;
938
        case 'o':
939
            val = va_arg(args, unsigned int);
940
            base = 8;
941
            break;
942
        case 'x':
943
            val = va_arg(args, unsigned int);
944
            base = 16;
945
            break;
946
        case 'p':
947
            val = (unsigned long) va_arg(args, void *);
948
            base = 16;
949
            neg = 2;
950
            break;
951
        case 's':
952
            str = va_arg(args, char *);
953
            break;
954
        case 'c':
955
            num[0] = va_arg(args, int);
956
            num[1] = 0;
957
            str = num;
958
            break;
959
        case 'm':
960
            str = strerror(errno);
961
            break;
962
        case 'I':
963
            str = ip_ntoa(va_arg(args, u_int32_t));
964
            break;
965
        case 'r':
966
            f = va_arg(args, char *);
967
//#ifndef __powerpc__
968
//          n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list));
969
//#else
970
            /* On the powerpc, a va_list is an array of 1 structure */
971
            n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *));
972
//#endif
973
            buf += n;
974
            buflen -= n;
975
            continue;
976
        case 't':
977
            time(&t);
978
            str = ctime(&t);
979
            str += 4;           /* chop off the day name */
980
            str[15] = 0; /* chop off year and newline */
981
            break;
982
        case 'v':               /* "visible" string */
983
        case 'q':               /* quoted string */
984
            quoted = c == 'q';
985
            p = va_arg(args, unsigned char *);
986
            if (fillch == '0' && prec > 0) {
987
                n = prec;
988
            } else {
989
                n = strlen((char *)p);
990
                if (prec > 0 && prec < n)
991
                    n = prec;
992
            }
993
            while (n > 0 && buflen > 0) {
994
                c = *p++;
995
                --n;
996
                if (!quoted && c >= 0x80) {
997
                    OUTCHAR('M');
998
                    OUTCHAR('-');
999
                    c -= 0x80;
1000
                }
1001
                if (quoted && (c == '"' || c == '\\'))
1002
                    OUTCHAR('\\');
1003
                if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
1004
                    if (quoted) {
1005
                        OUTCHAR('\\');
1006
                        switch (c) {
1007
                        case '\t':      OUTCHAR('t');   break;
1008
                        case '\n':      OUTCHAR('n');   break;
1009
                        case '\b':      OUTCHAR('b');   break;
1010
                        case '\f':      OUTCHAR('f');   break;
1011
                        default:
1012
                            OUTCHAR('x');
1013
                            OUTCHAR(hexchars[c >> 4]);
1014
                            OUTCHAR(hexchars[c & 0xf]);
1015
                        }
1016
                    } else {
1017
                        if (c == '\t')
1018
                            OUTCHAR(c);
1019
                        else {
1020
                            OUTCHAR('^');
1021
                            OUTCHAR(c ^ 0x40);
1022
                        }
1023
                    }
1024
                } else
1025
                    OUTCHAR(c);
1026
            }
1027
            continue;
1028
        default:
1029
            *buf++ = '%';
1030
            if (c != '%')
1031
                --fmt;          /* so %z outputs %z etc. */
1032
            --buflen;
1033
            continue;
1034
        }
1035
        if (base != 0) {
1036
            str = num + sizeof(num);
1037
            *--str = 0;
1038
            while (str > num + neg) {
1039
                *--str = hexchars[val % base];
1040
                val = val / base;
1041
                if (--prec <= 0 && val == 0)
1042
                    break;
1043
            }
1044
            switch (neg) {
1045
            case 1:
1046
                *--str = '-';
1047
                break;
1048
            case 2:
1049
                *--str = 'x';
1050
                *--str = '0';
1051
                break;
1052
            }
1053
            len = num + sizeof(num) - 1 - str;
1054
        } else {
1055
            len = strlen(str);
1056
            if (prec > 0 && len > prec)
1057
                len = prec;
1058
        }
1059
        if (width > 0) {
1060
            if (width > buflen)
1061
                width = buflen;
1062
            if ((n = width - len) > 0) {
1063
                buflen -= n;
1064
                for (; n > 0; --n)
1065
                    *buf++ = fillch;
1066
            }
1067
        }
1068
        if (len > buflen)
1069
            len = buflen;
1070
        memcpy(buf, str, len);
1071
        buf += len;
1072
        buflen -= len;
1073
    }
1074
    *buf = 0;
1075
    return buf - buf0;
1076
}
1077
 

powered by: WebSVN 2.1.0

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