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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/sys-ecos.c
4
//
5
//==========================================================================
6
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
7
// -------------------------------------------                              
8
// This file is part of eCos, the Embedded Configurable Operating System.   
9
// Copyright (C) 2003, 2004 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
 * sys-bsd.c - System-dependent procedures for setting up
48
 * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
49
 *
50
 * Copyright (c) 1989 Carnegie Mellon University.
51
 * Copyright (c) 1995 The Australian National University.
52
 * All rights reserved.
53
 *
54
 * Redistribution and use in source and binary forms are permitted
55
 * provided that the above copyright notice and this paragraph are
56
 * duplicated in all such forms and that any documentation,
57
 * advertising materials, and other materials related to such
58
 * distribution and use acknowledge that the software was developed
59
 * by Carnegie Mellon University and The Australian National University.
60
 * The names of the Universities may not be used to endorse or promote
61
 * products derived from this software without specific prior written
62
 * permission.
63
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
64
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
65
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
66
 */
67
 
68
#ifndef lint
69
//static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/sys-bsd.c,v 1.17 1999/08/28 01:19:08 peter Exp $";
70
#endif
71
/*      $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */
72
 
73
/*
74
 * TODO:
75
 */
76
 
77
//==========================================================================
78
 
79
#include <pkgconf/system.h>
80
#include <pkgconf/net.h>
81
#include <pkgconf/ppp.h>
82
 
83
#include <stdio.h>
84
#include <string.h>
85
#include <stdlib.h>
86
#include <unistd.h>
87
#include <errno.h>
88
#include <fcntl.h>
89
#include <termios.h>
90
#include <signal.h>
91
#define _KERNEL 1
92
#include <sys/param.h>
93
#undef _KERNEL
94
#include <sys/ioctl.h>
95
#include <sys/types.h>
96
#include <sys/socket.h>
97
#include <sys/time.h>
98
#include <sys/stat.h>
99
#ifdef NetBSD1_2
100
#include <util.h>
101
#endif
102
#ifdef PPP_FILTER
103
#include <net/bpf.h>
104
#endif
105
 
106
#include <cyg/ppp/syslog.h>
107
 
108
#include <net/if.h>
109
#include <cyg/ppp/net/ppp_defs.h>
110
#include <cyg/ppp/net/if_ppp.h>
111
#include <net/route.h>
112
#include <net/if_dl.h>
113
#include <netinet/in.h>
114
 
115
#ifdef IPX_CHANGE
116
#include <netipx/ipx.h>
117
#endif
118
 
119
#if RTM_VERSION >= 3
120
#include <sys/param.h>
121
#if defined(NetBSD) && (NetBSD >= 199703)
122
#include <netinet/if_inarp.h>
123
#else   /* NetBSD 1.2D or later */
124
#include <netinet/if_ether.h>
125
#endif
126
#endif
127
 
128
#include "cyg/ppp/pppd.h"
129
#include "cyg/ppp/fsm.h"
130
#include "cyg/ppp/ipcp.h"
131
 
132
#include "cyg/ppp/ppp_io.h"
133
 
134
#include <cyg/ppp/ppp.h>
135
 
136
//==========================================================================
137
 
138
static int rtm_seq;
139
 
140
static cyg_io_handle_t ppp_handle; /* IO subsystem handle to PPP stream */
141
struct tty ppp_tty;             /* dummy TTY structure */
142
 
143
static cyg_handle_t ppp_rtc;
144
static cyg_resolution_t ppp_rtc_resolution;
145
 
146
static int loop_slave = -1;
147
static int loop_master;
148
 
149
static unsigned char inbuf[PPP_MTU + PPP_HDRLEN + 100]; /* buffer for chars read from input */
150
 
151
static int sockfd = -1;         /* socket for doing interface ioctls */
152
 
153
static int if_is_up;            /* the interface is currently up */
154
static u_int32_t ifaddrs[2];    /* local and remote addresses we set */
155
static u_int32_t default_route_gateway; /* gateway addr for default route */
156
static u_int32_t proxy_arp_addr;        /* remote addr for proxy arp */
157
 
158
/* Prototypes for procedures local to this file. */
159
static int dodefaultroute __P((u_int32_t, int));
160
static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *));
161
 
162
static void wait_input_alarm(cyg_handle_t alarm, cyg_addrword_t data);
163
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
164
void cyg_ppp_serial_callback( cyg_serial_line_status_t *s,
165
                                     CYG_ADDRWORD priv );
166
#endif
167
 
168
extern u_int32_t netmask;       /* IP netmask to set on interface */
169
 
170
//==========================================================================
171
/*
172
 * sys_init - System-dependent initialization.
173
 */
174
void
175
sys_init()
176
{
177
    if( sockfd == -1 )
178
    {
179
        /* Get an internet socket for doing socket ioctl's on. */
180
        if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
181
            syslog(LOG_ERR, "Couldn't create IP socket: %d",errno);
182
            die(1);
183
        }
184
    }
185
 
186
    ppp_tty.pppd_wakeup = 0;
187
    ppp_tty.pppd_thread_running = true;
188
 
189
    ppp_rtc = cyg_real_time_clock();
190
    ppp_rtc_resolution = cyg_clock_get_resolution( ppp_rtc );
191
 
192
    cyg_alarm_create( ppp_rtc,
193
                      wait_input_alarm,
194
                      (cyg_addrword_t)&ppp_tty,
195
                      &ppp_tty.alarm,
196
                      &ppp_tty.alarm_obj);
197
}
198
 
199
//==========================================================================
200
/*
201
 * sys_cleanup - restore any system state we modified before exiting:
202
 * mark the interface down, delete default route and/or proxy arp entry.
203
 * This should call die() because it's called from die().
204
 */
205
void
206
sys_cleanup()
207
{
208
    struct ifreq ifr;
209
 
210
db_printf("%s called\n", __PRETTY_FUNCTION__);
211
    if (if_is_up) {
212
        strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
213
        if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
214
            && ((ifr.ifr_flags & IFF_UP) != 0)) {
215
            ifr.ifr_flags &= ~IFF_UP;
216
            ioctl(sockfd, SIOCSIFFLAGS, &ifr);
217
        }
218
    }
219
    if (ifaddrs[0] != 0)
220
        cifaddr(0, ifaddrs[0], ifaddrs[1]);
221
    if (default_route_gateway)
222
        cifdefaultroute(0, 0, default_route_gateway);
223
    if (proxy_arp_addr)
224
        cifproxyarp(0, proxy_arp_addr);
225
 
226
    if( sockfd != -1 )
227
    {
228
        close(sockfd);
229
        sockfd = -1;
230
    }
231
}
232
 
233
//==========================================================================
234
 
235
#ifdef __ECOS
236
 
237
void
238
sys_exit(void)
239
{
240
db_printf("%s called\n", __PRETTY_FUNCTION__);
241
    phase = PHASE_DEAD;
242
    while( ppp_tty.tx_thread_running )
243
    {
244
        db_printf("kick tx thread\n");
245
        cyg_semaphore_post( &ppp_tty.tx_sem );
246
        cyg_thread_delay(100);
247
    }
248
    ppp_tty.pppd_thread_running = false;
249
    cyg_thread_exit();
250
}
251
#endif
252
 
253
//==========================================================================
254
/*
255
 * sys_close - Clean up in a child process before execing.
256
 */
257
void
258
sys_close()
259
{
260
db_printf("%s called\n", __PRETTY_FUNCTION__);
261
    if (loop_slave >= 0) {
262
        close(loop_slave);
263
        close(loop_master);
264
    }
265
}
266
 
267
//==========================================================================
268
/*
269
 * sys_check_options - check the options that the user specified
270
 */
271
void
272
sys_check_options()
273
{
274
//db_printf("%s called\n", __PRETTY_FUNCTION__);
275
}
276
 
277
//==========================================================================
278
/*
279
 * ppp_available - check whether the system has any ppp interfaces
280
 * (in fact we check whether we can do an ioctl on ppp0).
281
 */
282
int
283
ppp_available()
284
{
285
    int s, ok;
286
    struct ifreq ifr;
287
    extern char *no_ppp_msg;
288
 
289
    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
290
        return 1;               /* can't tell */
291
 
292
    strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
293
    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
294
    close(s);
295
 
296
    no_ppp_msg = "\
297
This system lacks kernel support for PPP.  To include PPP support\n\
298
in the kernel, please follow the steps detailed in the README.bsd\n\
299
file in the ppp-2.2 distribution.\n";
300
    return ok;
301
}
302
 
303
//==========================================================================
304
/*
305
 * establish_ppp - Turn the serial port into a ppp interface.
306
 */
307
void
308
establish_ppp(cyg_io_handle_t handle)
309
{
310
    int s;
311
    int x;
312
    int err;
313
 
314
//db_printf("%s called\n", __PRETTY_FUNCTION__);
315
 
316
    ppp_handle = ppp_tty.t_handle = handle;
317
    ppp_tty.t_sc = NULL;
318
 
319
    s = splsoftnet();
320
 
321
    err = cyg_ppp_pppopen( &ppp_tty );
322
 
323
    if( err != 0 )
324
        syslog( LOG_ERR, "Couldn't establish PPP interface: %d", err );
325
 
326
    /*
327
     * Enable debug in the driver if requested.
328
     */
329
    if (kdebugflag) {
330
        if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) {
331
            syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %d",err);
332
        } else {
333
            x |= (kdebugflag & 0xFF) * SC_DEBUG;
334
            if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0)
335
                syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %d",err);
336
        }
337
    }
338
 
339
    splx(s);
340
}
341
 
342
//==========================================================================
343
/*
344
 * restore_loop - reattach the ppp unit to the loopback.
345
 */
346
void
347
restore_loop()
348
{
349
db_printf("%s called\n", __PRETTY_FUNCTION__);
350
}
351
 
352
 
353
//==========================================================================
354
/*
355
 * disestablish_ppp - Restore the serial port to normal operation.
356
 * This shouldn't call die() because it's called from die().
357
 */
358
void
359
disestablish_ppp(cyg_io_handle_t handle)
360
{
361
    db_printf("%s called\n", __PRETTY_FUNCTION__);
362
}
363
 
364
//==========================================================================
365
/*
366
 * Check whether the link seems not to be 8-bit clean.
367
 */
368
void
369
clean_check()
370
{
371
db_printf("%s called\n", __PRETTY_FUNCTION__);
372
}
373
 
374
//==========================================================================
375
/*
376
 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
377
 * at the requested speed, etc.  If `local' is true, set CLOCAL
378
 * regardless of whether the modem option was specified.
379
 *
380
 * For *BSD, we assume that speed_t values numerically equal bits/second.
381
 */
382
void
383
set_up_tty(cyg_io_handle_t handle, int local)
384
{
385
    cyg_serial_info_t   cfg;
386
    int                 err;
387
    cyg_uint32          len = sizeof(cfg);
388
 
389
    err = cyg_io_get_config( handle,
390
                             CYG_IO_GET_CONFIG_SERIAL_INFO,
391
                             &cfg,
392
                             &len);
393
 
394
    if( err != 0 ) {
395
        syslog(LOG_ERR, "cyg_io_get_config: %d",err);
396
        die(1);
397
    }
398
 
399
    switch ( flowctl )
400
    {
401
    case CYG_PPP_FLOWCTL_DEFAULT:
402
        break;
403
 
404
    case CYG_PPP_FLOWCTL_NONE:
405
        cfg.flags &= ~(CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX|
406
                       CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX);
407
        break;
408
 
409
    case CYG_PPP_FLOWCTL_HARDWARE:
410
        cfg.flags &= ~(CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX);
411
        cfg.flags |= CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX;
412
        break;
413
 
414
    case CYG_PPP_FLOWCTL_SOFTWARE:
415
        cfg.flags &= ~(CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX);
416
        cfg.flags |= CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX;
417
        break;
418
    }
419
 
420
    if( inspeed != 0 )
421
        cfg.baud = inspeed;
422
 
423
    err = cyg_io_set_config( handle,
424
                             CYG_IO_SET_CONFIG_SERIAL_INFO,
425
                             &cfg,
426
                             &len);
427
 
428
    if( err != 0 ) {
429
        syslog(LOG_ERR, "cyg_io_set_config: %d",err);
430
        die(1);
431
    }
432
}
433
 
434
//==========================================================================
435
/*
436
 * restore_tty - restore the terminal to the saved settings.
437
 */
438
void
439
restore_tty(cyg_io_handle_t handle)
440
{
441
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
442
    if( modem )
443
    {
444
        // Restore callback handler if it was set.
445
 
446
        Cyg_ErrNo err;
447
        cyg_uint32 len = sizeof(ppp_tty.serial_callbacks);
448
 
449
        db_printf("%s called\n", __PRETTY_FUNCTION__);
450
 
451
        err = cyg_io_set_config( handle,
452
                                 CYG_IO_SET_CONFIG_SERIAL_STATUS_CALLBACK,
453
                                 &ppp_tty.serial_callbacks,
454
                                 &len);
455
 
456
        if( err != 0 ) {
457
            syslog(LOG_ERR, "cyg_io_set_config(restore serial callbacks): %d",err);
458
            die(1);
459
        }
460
    }
461
#endif
462
}
463
 
464
//==========================================================================
465
/*
466
 * setdtr - control the DTR line on the serial port.
467
 * This is called from die(), so it shouldn't call die().
468
 */
469
void
470
setdtr(fd, on)
471
int fd, on;
472
{
473
db_printf("%s called\n", __PRETTY_FUNCTION__);
474
}
475
 
476
//==========================================================================
477
/*
478
 * output - Output PPP packet.
479
 */
480
void
481
output(unit, p, len)
482
    int unit;
483
    u_char *p;
484
    int len;
485
{
486
    Cyg_ErrNo err;
487
    struct uio uio;
488
    struct iovec iov;
489
    int s;
490
 
491
    if (debug)
492
        log_packet(p, len, "sent ", LOG_DEBUG);
493
 
494
 
495
    iov.iov_base    = p;
496
    iov.iov_len     = len;
497
    uio.uio_iov     = &iov;
498
    uio.uio_iovcnt  = 1;
499
    uio.uio_resid   = len;
500
    uio.uio_segflg  = UIO_USERSPACE;
501
    uio.uio_rw      = UIO_WRITE;
502
 
503
    s = splsoftnet();
504
 
505
    err = cyg_ppp_pppwrite( &ppp_tty, &uio, 0 );
506
 
507
    splx(s);
508
 
509
    if( err != 0 )
510
        syslog(LOG_ERR, "write: %d",err);
511
 
512
}
513
 
514
//==========================================================================
515
 
516
#ifdef __ECOS
517
 
518
static void wait_input_alarm(cyg_handle_t alarm, cyg_addrword_t data)
519
{
520
    cyg_thread_release( ppp_tty.pppd_thread );
521
    ppp_tty.pppd_wakeup = 1;
522
}
523
 
524
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
525
void cyg_ppp_serial_callback( cyg_serial_line_status_t *s,
526
                                     CYG_ADDRWORD priv )
527
{
528
    externC int kill_link;
529
 
530
//    db_printf("serial callback %d %x\n",s->which, s->value );
531
 
532
    if( s->which == CYGNUM_SERIAL_STATUS_CARRIERDETECT )
533
    {
534
        if( s->value == 0 )
535
        {
536
            // CD lost
537
            ppp_tty.carrier_detected = 0;
538
            kill_link = 1;
539
            cyg_thread_release( ppp_tty.pppd_thread );
540
            ppp_tty.pppd_wakeup = 1;
541
        }
542
        else
543
        {
544
            // CD up
545
            ppp_tty.carrier_detected = 1;
546
        }
547
    }
548
}
549
#endif
550
 
551
static void cyg_ppp_tx_thread(CYG_ADDRWORD arg)
552
{
553
    ppp_tty.tx_thread_running = true;
554
 
555
    // Wait for the PPPD thread to get going and start the PPP
556
    // initialization phase.
557
    while(phase == PHASE_DEAD)
558
        cyg_thread_delay(100);
559
 
560
    // Now loop until the link goes back down.
561
    while( phase != PHASE_DEAD )
562
    {
563
        cyg_semaphore_wait( &ppp_tty.tx_sem );
564
 
565
        if( phase == PHASE_DEAD )
566
            break;
567
 
568
        // Call into PPP driver to get transmissions going. This is
569
        // only called if some other thread has failed to transmit all
570
        // of a packet due to a full buffer, or flow control.
571
 
572
        cyg_ppp_pppstart( &ppp_tty );
573
    }
574
 
575
db_printf("%s exiting\n", __PRETTY_FUNCTION__);
576
    ppp_tty.tx_thread_running = false;
577
    cyg_thread_exit();
578
}
579
 
580
#endif
581
 
582
 
583
//==========================================================================
584
/*
585
 * wait_input - wait until there is data available on ttyfd,
586
 * for the length of time specified by *timo (indefinite
587
 * if timo is NULL).
588
 */
589
void
590
wait_input(timo)
591
    struct timeval *timo;
592
{
593
    // If there are any packets still waiting on the input queue then
594
    // return immediately to let the PPPD handle them.
595
    if (cyg_ppp_pppcheck(&ppp_tty) != 0)
596
        return;
597
 
598
    if( timo != NULL )
599
    {
600
        cyg_tick_count_t trigger = timo->tv_sec*ppp_rtc_resolution.divisor;
601
 
602
        // If the timeval has a microseconds value, just add another
603
        // second on to the trigger time. These are after all just
604
        // timeouts, not accurate timings, so a bit of imprecision
605
        // will not hurt.
606
        if( timo->tv_usec != 0 )
607
            trigger += ppp_rtc_resolution.divisor;
608
 
609
        trigger += cyg_current_time();
610
 
611
        // We set the alarm to retrigger after a second. This is in
612
        // case it catches cyg_io_read() at an uninterruptible
613
        // point. The alarm is disabled as soon as the read returns,
614
        // so the retrigger will usually not happen.
615
        cyg_alarm_initialize( ppp_tty.alarm,
616
                              trigger,
617
                              ppp_rtc_resolution.divisor );
618
    }
619
 
620
    for(;;)
621
    {
622
        int s;
623
        cyg_uint32 len = 1;
624
        Cyg_ErrNo err;
625
        cyg_serial_buf_info_t info;
626
        cyg_uint32 ilen = sizeof(info);
627
 
628
#if 1
629
        // Work out how many bytes are waiting in the serial device
630
        // buffer and read them all at once. If there are none, we
631
        // just wait for a single character to arrive.
632
 
633
        if( cyg_io_get_config( ppp_tty.t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO,
634
                               &info, &ilen ) == 0 && info.rx_count > 1 )
635
        {
636
            len = info.rx_count-1;
637
            if( len > sizeof(inbuf) )
638
                len = sizeof(inbuf);
639
        }
640
#endif
641
 
642
        if( timo != NULL )
643
            cyg_alarm_enable( ppp_tty.alarm );
644
 
645
        err = cyg_io_read( ppp_handle, &inbuf, &len );
646
 
647
        if( timo != NULL )
648
            cyg_alarm_disable( ppp_tty.alarm );
649
 
650
//        db_printf("read: err %d len %d byte %02x\n",err,len,inbuf[0]);
651
 
652
        if( err == 0 )
653
        {
654
            int i;
655
 
656
            // Pass all input data to PPP driver for analysis. If this
657
            // turns out to be for the PPPD, it will call
658
            // pppasyncctlp() which in turn will set
659
            // ppp_tty.pppd_wakeup. We detect that on return from
660
            // pppinput() and return to the caller to do pppd
661
            // processing.
662
 
663
            s = splsoftnet();
664
 
665
            for( i = 0; i < len; i++ )
666
            {
667
                err = cyg_ppp_pppinput( inbuf[i], &ppp_tty );
668
 
669
                if( err != 0 )
670
                    syslog( LOG_ERR, "pppinput error: %d", err);
671
 
672
            }
673
 
674
            splx(s);
675
 
676
        }
677
        else if( err != -EINTR )
678
            syslog( LOG_ERR, "Read error: %d",err);
679
 
680
        if( ppp_tty.pppd_wakeup )
681
        {
682
            ppp_tty.pppd_wakeup = 0;
683
            break;
684
        }
685
    }
686
}
687
 
688
//==========================================================================
689
/*
690
 * wait_time - wait for a given length of time or until a
691
 * signal is received.
692
 */
693
void
694
wait_time(timo)
695
    struct timeval *timo;
696
{
697
db_printf("%s called\n", __PRETTY_FUNCTION__);
698
}
699
 
700
 
701
//==========================================================================
702
/*
703
 * read_packet - get a PPP packet from the serial device.
704
 */
705
int
706
read_packet(buf)
707
    u_char *buf;
708
{
709
    int err;
710
    struct uio uio;
711
    struct iovec iov;
712
    int len = PPP_MTU + PPP_HDRLEN;
713
    int s;
714
 
715
//db_printf("%s called\n", __PRETTY_FUNCTION__);
716
 
717
    iov.iov_base        = buf;
718
    iov.iov_len         = len;
719
    uio.uio_iov         = &iov;
720
    uio.uio_iovcnt      = 1;
721
    uio.uio_resid       = len;
722
    uio.uio_segflg      = UIO_USERSPACE;
723
    uio.uio_rw          = UIO_READ;
724
 
725
    s = splsoftnet();
726
 
727
    err = cyg_ppp_pppread( &ppp_tty, &uio, 0 );
728
 
729
    splx(s);
730
 
731
    if( err == EWOULDBLOCK )
732
        return -1;
733
 
734
    if( err != 0 )
735
    {
736
        syslog(LOG_ERR, "pppread: %d",err);
737
        die(1);
738
    }
739
 
740
    len -= uio.uio_resid;
741
 
742
    return len;
743
}
744
 
745
//==========================================================================
746
/*
747
 * ppp_send_config - configure the transmit characteristics of
748
 * the ppp interface.
749
 */
750
void
751
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
752
    int unit, mtu;
753
    u_int32_t asyncmap;
754
    int pcomp, accomp;
755
{
756
    u_int x;
757
    struct ifreq ifr;
758
    int err;
759
    int s;
760
 
761
//    db_printf("%s: unit %d mtu %d asyncmap %08x pcomp %08x accomp %08x\n", __PRETTY_FUNCTION__,
762
//              unit,mtu,asyncmap,pcomp,accomp);
763
 
764
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
765
    ifr.ifr_mtu = mtu;
766
    if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
767
        syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %d",errno);
768
        quit();
769
    }
770
 
771
 
772
    s = splsoftnet();
773
 
774
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSASYNCMAP, (caddr_t) &asyncmap, 0)) < 0) {
775
        syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %d",err);
776
    }
777
 
778
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) {
779
        syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
780
    }
781
    x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
782
    x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
783
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0) {
784
        syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
785
    }
786
 
787
    splx(s);
788
}
789
 
790
 
791
//==========================================================================
792
/*
793
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
794
 */
795
void
796
ppp_set_xaccm(unit, accm)
797
    int unit;
798
    ext_accm accm;
799
{
800
    int error;
801
    int s;
802
 
803
//db_printf("%s called\n", __PRETTY_FUNCTION__);
804
 
805
    s = splsoftnet();
806
 
807
    error = cyg_ppp_ppptioctl( &ppp_tty, PPPIOCSXASYNCMAP, (caddr_t)accm, 0 );
808
 
809
    splx(s);
810
 
811
    if( error != 0 )
812
        syslog(LOG_WARNING, "ioctl(set extended ACCM): %d",error);
813
}
814
 
815
 
816
//==========================================================================
817
/*
818
 * ppp_recv_config - configure the receive-side characteristics of
819
 * the ppp interface.
820
 */
821
void
822
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
823
    int unit, mru;
824
    u_int32_t asyncmap;
825
    int pcomp, accomp;
826
{
827
    int x;
828
    int err;
829
    int s;
830
 
831
    s = splsoftnet();
832
 
833
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSMRU, (caddr_t) &mru, 0)) < 0) {
834
        syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %d",err);
835
    }
836
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap, 0)) < 0) {
837
        syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %d",err);
838
    }
839
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) {
840
        syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
841
    }
842
    x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
843
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0) {
844
        syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
845
    }
846
 
847
    splx(s);
848
}
849
 
850
//==========================================================================
851
/*
852
 * ccp_test - ask kernel whether a given compression method
853
 * is acceptable for use.  Returns 1 if the method and parameters
854
 * are OK, 0 if the method is known but the parameters are not OK
855
 * (e.g. code size should be reduced), or -1 if the method is unknown.
856
 */
857
int
858
ccp_test(unit, opt_ptr, opt_len, for_transmit)
859
    int unit, opt_len, for_transmit;
860
    u_char *opt_ptr;
861
{
862
    struct ppp_option_data data;
863
    int s;
864
 
865
    data.ptr = opt_ptr;
866
    data.length = opt_len;
867
    data.transmit = for_transmit;
868
//db_printf("%s called\n", __PRETTY_FUNCTION__);
869
 
870
    s = splsoftnet();
871
 
872
    errno = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSCOMPRESS, (caddr_t) &data, 0 );
873
 
874
    splx(s);
875
 
876
    if (errno == 0)
877
        return 1;
878
    else return (errno == ENOBUFS)? 0: -1;
879
 
880
}
881
 
882
//==========================================================================
883
/*
884
 * ccp_flags_set - inform kernel about the current state of CCP.
885
 */
886
void
887
ccp_flags_set(unit, isopen, isup)
888
    int unit, isopen, isup;
889
{
890
    int x;
891
 
892
    int err;
893
//db_printf("%s called\n", __PRETTY_FUNCTION__);
894
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) {
895
        syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
896
        return;
897
    }
898
    x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
899
    x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
900
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x,0)) != 0)
901
        syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
902
}
903
 
904
//==========================================================================
905
/*
906
 * ccp_fatal_error - returns 1 if decompression was disabled as a
907
 * result of an error detected after decompression of a packet,
908
 * 0 otherwise.  This is necessary because of patent nonsense.
909
 */
910
int
911
ccp_fatal_error(unit)
912
    int unit;
913
{
914
    int x;
915
    int err;
916
 
917
db_printf("%s called\n", __PRETTY_FUNCTION__);
918
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) {
919
        syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %d",err);
920
        return 0;
921
    }
922
    return x & SC_DC_FERROR;
923
}
924
 
925
//==========================================================================
926
/*
927
 * get_idle_time - return how long the link has been idle.
928
 */
929
int
930
get_idle_time(u, ip)
931
    int u;
932
    struct ppp_idle *ip;
933
{
934
    return cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGIDLE, (caddr_t)ip, 0) == 0;
935
}
936
 
937
 
938
//==========================================================================
939
 
940
#ifdef PPP_FILTER
941
/*
942
 * set_filters - transfer the pass and active filters to the kernel.
943
 */
944
int
945
set_filters(pass, active)
946
    struct bpf_program *pass, *active;
947
{
948
    int ret = 1;
949
 
950
db_printf("%s called\n", __PRETTY_FUNCTION__);
951
    if (pass->bf_len > 0) {
952
        if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
953
            syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
954
            ret = 0;
955
        }
956
    }
957
    if (active->bf_len > 0) {
958
        if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
959
            syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
960
            ret = 0;
961
        }
962
    }
963
    return ret;
964
}
965
#endif
966
 
967
//==========================================================================
968
/*
969
 * sifvjcomp - config tcp header compression
970
 */
971
int
972
sifvjcomp(u, vjcomp, cidcomp, maxcid)
973
    int u, vjcomp, cidcomp, maxcid;
974
{
975
    u_int x;
976
    int err;
977
 
978
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) {
979
        syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
980
        return 0;
981
    }
982
    x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
983
    x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
984
    if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) != 0) {
985
        syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
986
        return 0;
987
    }
988
    if (vjcomp && ((err=cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSMAXCID, (caddr_t) &maxcid, 0)) != 0)) {
989
        syslog(LOG_ERR, "ioctl(PPPIOCSMAXCID): %d",err);
990
        return 0;
991
    }
992
    return 1;
993
}
994
 
995
//==========================================================================
996
/*
997
 * sifup - Config the interface up and enable IP packets to pass.
998
 */
999
int
1000
sifup(u)
1001
    int u;
1002
{
1003
    struct ifreq ifr;
1004
 
1005
//db_printf("%s called\n", __PRETTY_FUNCTION__);
1006
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1007
    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1008
        syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1009
        return 0;
1010
    }
1011
    ifr.ifr_flags |= IFF_UP;
1012
    if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1013
        syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1014
        return 0;
1015
    }
1016
    if_is_up = 1;
1017
    return 1;
1018
}
1019
 
1020
//==========================================================================
1021
/*
1022
 * sifnpmode - Set the mode for handling packets for a given NP.
1023
 */
1024
int
1025
sifnpmode(u, proto, mode)
1026
    int u;
1027
    int proto;
1028
    enum NPmode mode;
1029
{
1030
    struct npioctl npi;
1031
 
1032
//db_printf("%s called\n", __PRETTY_FUNCTION__);
1033
    npi.protocol = proto;
1034
    npi.mode = mode;
1035
    {
1036
        int err;
1037
 
1038
        if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSNPMODE, (caddr_t)&npi, 0)) < 0) {
1039
            syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %d", proto, mode,err);
1040
            return 0;
1041
        }
1042
    }
1043
 
1044
    return 1;
1045
}
1046
 
1047
//==========================================================================
1048
/*
1049
 * sifdown - Config the interface down and disable IP.
1050
 */
1051
int
1052
sifdown(u)
1053
    int u;
1054
{
1055
    struct ifreq ifr;
1056
    int rv;
1057
    struct npioctl npi;
1058
 
1059
db_printf("%s called\n", __PRETTY_FUNCTION__);
1060
    rv = 1;
1061
    npi.protocol = PPP_IP;
1062
    npi.mode = NPMODE_ERROR;
1063
    {
1064
        int err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSNPMODE, (caddr_t) &npi, 0);
1065
        if( err < 0 )
1066
            syslog(LOG_WARNING, "ioctl(PPPIOCSNPMODE): %d",err);
1067
    }
1068
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1069
    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1070
        syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1071
        rv = 0;
1072
    } else {
1073
        ifr.ifr_flags &= ~IFF_UP;
1074
        if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1075
            syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1076
            rv = 0;
1077
        } else
1078
            if_is_up = 0;
1079
    }
1080
    return rv;
1081
    return 0;
1082
}
1083
 
1084
//==========================================================================
1085
/*
1086
 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
1087
 * if it exists.
1088
 */
1089
#define SET_SA_FAMILY(addr, family)             \
1090
    BZERO((char *) &(addr), sizeof(addr));      \
1091
    addr.sa_family = (family);                  \
1092
    addr.sa_len = sizeof(addr);
1093
 
1094
//==========================================================================
1095
/*
1096
 * sifaddr - Config the interface IP addresses and netmask.
1097
 */
1098
int
1099
sifaddr(u, o, h, m)
1100
    int u;
1101
    u_int32_t o, h, m;
1102
{
1103
    struct ifaliasreq ifra;
1104
    struct ifreq ifr;
1105
 
1106
//db_printf("%s called\n", __PRETTY_FUNCTION__);
1107
    strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1108
    SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1109
    ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1110
    SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1111
    ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1112
    if (m != 0) {
1113
        SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
1114
        ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
1115
    } else
1116
        BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1117
    BZERO(&ifr, sizeof(ifr));
1118
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1119
    if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1120
        if (errno != EADDRNOTAVAIL)
1121
            syslog(LOG_WARNING, "Couldn't remove interface address: %d",errno);
1122
    }
1123
    if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
1124
        if (errno != EEXIST) {
1125
            syslog(LOG_ERR, "Couldn't set interface address: %d",errno);
1126
            return 0;
1127
        }
1128
        syslog(LOG_WARNING,
1129
               "Couldn't set interface address: Address %s already exists",
1130
                ip_ntoa(o));
1131
    }
1132
    ifaddrs[0] = o;
1133
    ifaddrs[1] = h;
1134
    return 1;
1135
}
1136
 
1137
//==========================================================================
1138
/*
1139
 * cifaddr - Clear the interface IP addresses, and delete routes
1140
 * through the interface if possible.
1141
 */
1142
int
1143
cifaddr(u, o, h)
1144
    int u;
1145
    u_int32_t o, h;
1146
{
1147
    struct ifaliasreq ifra;
1148
 
1149
db_printf("%s called\n", __PRETTY_FUNCTION__);
1150
    ifaddrs[0] = 0;
1151
    strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1152
    SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1153
    ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1154
    SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1155
    ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1156
    BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1157
    if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
1158
        if (errno != EADDRNOTAVAIL)
1159
            syslog(LOG_WARNING, "Couldn't delete interface address: %m");
1160
        return 0;
1161
    }
1162
    return 1;
1163
}
1164
 
1165
//==========================================================================
1166
/*
1167
 * sifdefaultroute - assign a default route through the address given.
1168
 */
1169
int
1170
sifdefaultroute(u, l, g)
1171
    int u;
1172
    u_int32_t l, g;
1173
{
1174
db_printf("%s called\n", __PRETTY_FUNCTION__);
1175
    return dodefaultroute(g, 's');
1176
}
1177
 
1178
//==========================================================================
1179
/*
1180
 * cifdefaultroute - delete a default route through the address given.
1181
 */
1182
int
1183
cifdefaultroute(u, l, g)
1184
    int u;
1185
    u_int32_t l, g;
1186
{
1187
db_printf("%s called\n", __PRETTY_FUNCTION__);
1188
    return dodefaultroute(g, 'c');
1189
}
1190
 
1191
//==========================================================================
1192
/*
1193
 * dodefaultroute - talk to a routing socket to add/delete a default route.
1194
 */
1195
static int
1196
dodefaultroute(g, cmd)
1197
    u_int32_t g;
1198
    int cmd;
1199
{
1200
    int routes;
1201
    struct {
1202
        struct rt_msghdr        hdr;
1203
        struct sockaddr_in      dst;
1204
        struct sockaddr_in      gway;
1205
        struct sockaddr_in      mask;
1206
    } rtmsg;
1207
 
1208
db_printf("%s %08x %c\n", __PRETTY_FUNCTION__,g,cmd);
1209
    if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1210
        syslog(LOG_ERR, "Couldn't %s default route: socket: %d",
1211
               cmd=='s'? "add": "delete",errno);
1212
        return 0;
1213
    }
1214
 
1215
    memset(&rtmsg, 0, sizeof(rtmsg));
1216
    rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE;
1217
    rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
1218
    rtmsg.hdr.rtm_version = RTM_VERSION;
1219
    rtmsg.hdr.rtm_seq = ++rtm_seq;
1220
    rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
1221
    rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1222
    rtmsg.dst.sin_family = AF_INET;
1223
    rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1224
    rtmsg.gway.sin_family = AF_INET;
1225
    rtmsg.gway.sin_addr.s_addr = g;
1226
    rtmsg.mask.sin_len = sizeof(rtmsg.dst);
1227
    rtmsg.mask.sin_family = AF_INET;
1228
 
1229
    rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
1230
    if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
1231
        syslog(LOG_ERR, "Couldn't %s default route: %d",
1232
               cmd=='s'? "add": "delete",errno);
1233
        close(routes);
1234
        return 0;
1235
    }
1236
 
1237
    close(routes);
1238
    default_route_gateway = (cmd == 's')? g: 0;
1239
    return 1;
1240
}
1241
 
1242
//==========================================================================
1243
 
1244
#if RTM_VERSION >= 3
1245
 
1246
/*
1247
 * sifproxyarp - Make a proxy ARP entry for the peer.
1248
 */
1249
static struct {
1250
    struct rt_msghdr            hdr;
1251
    struct sockaddr_inarp       dst;
1252
    struct sockaddr_dl          hwa;
1253
    char                        extra[128];
1254
} arpmsg;
1255
 
1256
static int arpmsg_valid;
1257
 
1258
int
1259
sifproxyarp(unit, hisaddr)
1260
    int unit;
1261
    u_int32_t hisaddr;
1262
{
1263
    int routes;
1264
 
1265
db_printf("%s called\n", __PRETTY_FUNCTION__);
1266
    /*
1267
     * Get the hardware address of an interface on the same subnet
1268
     * as our local address.
1269
     */
1270
    memset(&arpmsg, 0, sizeof(arpmsg));
1271
    if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1272
        syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1273
        return 0;
1274
    }
1275
 
1276
    if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1277
        syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m");
1278
        return 0;
1279
    }
1280
 
1281
    arpmsg.hdr.rtm_type = RTM_ADD;
1282
    arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
1283
    arpmsg.hdr.rtm_version = RTM_VERSION;
1284
    arpmsg.hdr.rtm_seq = ++rtm_seq;
1285
    arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
1286
    arpmsg.hdr.rtm_inits = RTV_EXPIRE;
1287
    arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1288
    arpmsg.dst.sin_family = AF_INET;
1289
    arpmsg.dst.sin_addr.s_addr = hisaddr;
1290
    arpmsg.dst.sin_other = SIN_PROXY;
1291
 
1292
    arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1293
        + arpmsg.hwa.sdl_len;
1294
    if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1295
        syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1296
        close(routes);
1297
        return 0;
1298
    }
1299
 
1300
    close(routes);
1301
    arpmsg_valid = 1;
1302
    proxy_arp_addr = hisaddr;
1303
    return 1;
1304
}
1305
 
1306
/*
1307
 * cifproxyarp - Delete the proxy ARP entry for the peer.
1308
 */
1309
int
1310
cifproxyarp(unit, hisaddr)
1311
    int unit;
1312
    u_int32_t hisaddr;
1313
{
1314
    int routes;
1315
 
1316
db_printf("%s called\n", __PRETTY_FUNCTION__);
1317
    if (!arpmsg_valid)
1318
        return 0;
1319
    arpmsg_valid = 0;
1320
 
1321
    arpmsg.hdr.rtm_type = RTM_DELETE;
1322
    arpmsg.hdr.rtm_seq = ++rtm_seq;
1323
 
1324
    if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1325
        syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m");
1326
        return 0;
1327
    }
1328
 
1329
    if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1330
        syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m");
1331
        close(routes);
1332
        return 0;
1333
    }
1334
 
1335
    close(routes);
1336
    proxy_arp_addr = 0;
1337
    return 1;
1338
}
1339
 
1340
//==========================================================================
1341
 
1342
#else   /* RTM_VERSION */
1343
 
1344
/*
1345
 * sifproxyarp - Make a proxy ARP entry for the peer.
1346
 */
1347
int
1348
sifproxyarp(unit, hisaddr)
1349
    int unit;
1350
    u_int32_t hisaddr;
1351
{
1352
    struct arpreq arpreq;
1353
    struct {
1354
        struct sockaddr_dl      sdl;
1355
        char                    space[128];
1356
    } dls;
1357
 
1358
db_printf("%s called\n", __PRETTY_FUNCTION__);
1359
    BZERO(&arpreq, sizeof(arpreq));
1360
 
1361
    /*
1362
     * Get the hardware address of an interface on the same subnet
1363
     * as our local address.
1364
     */
1365
    if (!get_ether_addr(hisaddr, &dls.sdl)) {
1366
        syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1367
        return 0;
1368
    }
1369
 
1370
    arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1371
    arpreq.arp_ha.sa_family = AF_UNSPEC;
1372
    BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1373
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1374
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1375
    arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1376
    if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1377
        syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1378
        return 0;
1379
    }
1380
 
1381
    proxy_arp_addr = hisaddr;
1382
    return 1;
1383
}
1384
 
1385
/*
1386
 * cifproxyarp - Delete the proxy ARP entry for the peer.
1387
 */
1388
int
1389
cifproxyarp(unit, hisaddr)
1390
    int unit;
1391
    u_int32_t hisaddr;
1392
{
1393
    struct arpreq arpreq;
1394
 
1395
db_printf("%s called\n", __PRETTY_FUNCTION__);
1396
    BZERO(&arpreq, sizeof(arpreq));
1397
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1398
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1399
    if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1400
        syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m");
1401
        return 0;
1402
    }
1403
    proxy_arp_addr = 0;
1404
    return 1;
1405
}
1406
#endif  /* RTM_VERSION */
1407
 
1408
 
1409
//==========================================================================
1410
/*
1411
 * get_ether_addr - get the hardware address of an interface on the
1412
 * the same subnet as ipaddr.
1413
 */
1414
#define MAX_IFS         32
1415
 
1416
static int
1417
get_ether_addr(ipaddr, hwaddr)
1418
    u_int32_t ipaddr;
1419
    struct sockaddr_dl *hwaddr;
1420
{
1421
    struct ifreq *ifr, *ifend, *ifp;
1422
    u_int32_t ina, mask;
1423
    struct sockaddr_dl *dla;
1424
    struct ifreq ifreq;
1425
    struct ifconf ifc;
1426
    struct ifreq ifs[MAX_IFS];
1427
 
1428
db_printf("%s called\n", __PRETTY_FUNCTION__);
1429
    ifc.ifc_len = sizeof(ifs);
1430
    ifc.ifc_req = ifs;
1431
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1432
        syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1433
        return 0;
1434
    }
1435
 
1436
    /*
1437
     * Scan through looking for an interface with an Internet
1438
     * address on the same subnet as `ipaddr'.
1439
     */
1440
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1441
    for (ifr = ifc.ifc_req; ifr < ifend;
1442
                ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
1443
                    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
1444
        if (ifr->ifr_addr.sa_family == AF_INET) {
1445
            ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1446
            strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1447
            /*
1448
             * Check that the interface is up, and not point-to-point
1449
             * or loopback.
1450
             */
1451
            if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1452
                continue;
1453
            if ((ifreq.ifr_flags &
1454
                 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1455
                 != (IFF_UP|IFF_BROADCAST))
1456
                continue;
1457
            /*
1458
             * Get its netmask and check that it's on the right subnet.
1459
             */
1460
            if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1461
                continue;
1462
            mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1463
            if ((ipaddr & mask) != (ina & mask))
1464
                continue;
1465
 
1466
            break;
1467
        }
1468
    }
1469
 
1470
    if (ifr >= ifend)
1471
        return 0;
1472
    syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1473
 
1474
    /*
1475
     * Now scan through again looking for a link-level address
1476
     * for this interface.
1477
     */
1478
    ifp = ifr;
1479
    for (ifr = ifc.ifc_req; ifr < ifend; ) {
1480
        if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
1481
            && ifr->ifr_addr.sa_family == AF_LINK) {
1482
            /*
1483
             * Found the link-level address - copy it out
1484
             */
1485
            dla = (struct sockaddr_dl *) &ifr->ifr_addr;
1486
            BCOPY(dla, hwaddr, dla->sdl_len);
1487
            return 1;
1488
        }
1489
        ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
1490
            + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)));
1491
    }
1492
 
1493
    return 0;
1494
}
1495
 
1496
//==========================================================================
1497
/*
1498
 * Return user specified netmask, modified by any mask we might determine
1499
 * for address `addr' (in network byte order).
1500
 * Here we scan through the system's list of interfaces, looking for
1501
 * any non-point-to-point interfaces which might appear to be on the same
1502
 * network as `addr'.  If we find any, we OR in their netmask to the
1503
 * user-specified netmask.
1504
 */
1505
u_int32_t
1506
GetMask(addr)
1507
    u_int32_t addr;
1508
{
1509
    u_int32_t mask, nmask, ina;
1510
    struct ifreq *ifr, *ifend, ifreq;
1511
    struct ifconf ifc;
1512
    struct ifreq ifs[MAX_IFS];
1513
 
1514
    addr = ntohl(addr);
1515
    if (IN_CLASSA(addr))        /* determine network mask for address class */
1516
        nmask = IN_CLASSA_NET;
1517
    else if (IN_CLASSB(addr))
1518
        nmask = IN_CLASSB_NET;
1519
    else
1520
        nmask = IN_CLASSC_NET;
1521
    /* class D nets are disallowed by bad_ip_adrs */
1522
    mask = netmask | htonl(nmask);
1523
 
1524
    /*
1525
     * Scan through the system's network interfaces.
1526
     */
1527
    ifc.ifc_len = sizeof(ifs);
1528
    ifc.ifc_req = ifs;
1529
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1530
        syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1531
        return mask;
1532
    }
1533
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1534
    for (ifr = ifc.ifc_req; ifr < ifend;
1535
                ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
1536
                    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
1537
        /*
1538
         * Check the interface's internet address.
1539
         */
1540
        if (ifr->ifr_addr.sa_family != AF_INET)
1541
            continue;
1542
        ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1543
        if ((ntohl(ina) & nmask) != (addr & nmask))
1544
            continue;
1545
        /*
1546
         * Check that the interface is up, and not point-to-point or loopback.
1547
         */
1548
        strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1549
        if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1550
            continue;
1551
        if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1552
            != IFF_UP)
1553
            continue;
1554
        /*
1555
         * Get its netmask and OR it into our mask.
1556
         */
1557
        if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1558
            continue;
1559
        mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1560
    }
1561
 
1562
    return mask;
1563
}
1564
 
1565
//==========================================================================
1566
/*
1567
 * Use the hostid as part of the random number seed.
1568
 */
1569
int
1570
get_host_seed()
1571
{
1572
//db_printf("%s called\n", __PRETTY_FUNCTION__);
1573
#ifndef __ECOS
1574
    return gethostid();
1575
#endif
1576
    return 0;
1577
}
1578
 
1579
//=====================================================================
1580
// PAP stubs
1581
//
1582
// When omitting PAP, these fill in the dangling references from auth.c
1583
//
1584
 
1585
#ifndef CYGPKG_PPP_PAP
1586
 
1587
void
1588
upap_authwithpeer(unit, user, password)
1589
    int unit;
1590
    char *user, *password;
1591
{
1592
    unit=unit;
1593
    user=user;
1594
    password=password;
1595
}
1596
 
1597
void
1598
upap_authpeer(unit)
1599
    int unit;
1600
{
1601
    unit=unit;
1602
}
1603
 
1604
#endif
1605
 
1606
//=====================================================================
1607
// CHAP stubs
1608
//
1609
// When omitting CHAP, these fill in the dangling references from auth.c
1610
//
1611
 
1612
#ifndef CYGPKG_PPP_CHAP
1613
 
1614
void
1615
ChapAuthWithPeer(unit, our_name, digest)
1616
    int unit;
1617
    char *our_name;
1618
    int digest;
1619
{
1620
    unit=unit;
1621
    our_name=our_name;
1622
    digest=digest;
1623
}
1624
 
1625
void
1626
ChapAuthPeer(unit, our_name, digest)
1627
    int unit;
1628
    char *our_name;
1629
    int digest;
1630
{
1631
    unit=unit;
1632
    our_name=our_name;
1633
    digest=digest;
1634
}
1635
 
1636
#endif
1637
 
1638
//=====================================================================
1639
// eCos API
1640
 
1641
externC cyg_int32 cyg_ppp_options_init( cyg_ppp_options_t *options )
1642
{
1643
    if( options == NULL )
1644
        return -1;
1645
 
1646
    options->debug              = 0;
1647
    options->kdebugflag         = 0;
1648
    options->default_route      = 1;
1649
    options->modem              = 0;
1650
    options->flowctl            = CYG_PPP_FLOWCTL_HARDWARE;
1651
    options->refuse_pap         = 0;
1652
    options->refuse_chap        = 0;
1653
    options->neg_accm           = 0;
1654
    options->conf_accm          = 0;
1655
 
1656
    options->baud               = CYGNUM_SERIAL_BAUD_115200;
1657
 
1658
    options->idle_time_limit    = 1*60;
1659
    options->maxconnect         = 0;
1660
 
1661
    options->our_address        = 0;
1662
    options->his_address        = 0;
1663
 
1664
    options->script             = NULL;
1665
 
1666
    strncpy( options->user, CYGPKG_PPP_AUTH_DEFAULT_USER, MAXNAMELEN );
1667
    strncpy( options->passwd, CYGPKG_PPP_AUTH_DEFAULT_PASSWD, MAXSECRETLEN );
1668
 
1669
    return 0;
1670
}
1671
 
1672
// -------------------------------------------------------------------------
1673
 
1674
 
1675
#define CYGNUM_PPP_PPPD_THREAD_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+0x1000)
1676
 
1677
static char cyg_pppd_stack[CYGNUM_PPP_PPPD_THREAD_STACK_SIZE];
1678
static cyg_thread cyg_pppd_thread_obj;
1679
 
1680
static char cyg_ppp_tx_thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
1681
static cyg_thread cyg_ppp_tx_thread_obj;
1682
 
1683
 
1684
externC void cyg_pppd_main(CYG_ADDRWORD arg);
1685
 
1686
 
1687
externC cyg_ppp_handle_t cyg_ppp_up( const char *devnam_arg,
1688
                                     const cyg_ppp_options_t *options )
1689
{
1690
 
1691
    if( options == NULL || phase != PHASE_DEAD )
1692
        return 0;
1693
 
1694
    // Initialize control block    
1695
        memset(&ppp_tty, 0, sizeof(struct tty));
1696
 
1697
    strncpy( devnam, devnam_arg, PATH_MAX );
1698
 
1699
    ppp_tty.options = options;
1700
 
1701
    cyg_semaphore_init( &ppp_tty.tx_sem,  0 );
1702
 
1703
    // Start the PPPD thread
1704
    cyg_thread_create(CYGNUM_PPP_PPPD_THREAD_PRIORITY,
1705
                      cyg_pppd_main,
1706
                      (CYG_ADDRWORD)&ppp_tty,
1707
                      "PPPD",
1708
                      &cyg_pppd_stack[0],
1709
                      CYGNUM_PPP_PPPD_THREAD_STACK_SIZE,
1710
                      &ppp_tty.pppd_thread,
1711
                      &cyg_pppd_thread_obj
1712
            );
1713
    cyg_thread_resume(ppp_tty.pppd_thread);
1714
 
1715
    // Start the TX thread
1716
    cyg_thread_create(CYGNUM_PPP_PPPD_THREAD_PRIORITY+1,
1717
                      cyg_ppp_tx_thread,
1718
                      (CYG_ADDRWORD)&ppp_tty,
1719
                      "PPP Tx Thread",
1720
                      &cyg_ppp_tx_thread_stack[0],
1721
                      sizeof(cyg_ppp_tx_thread_stack),
1722
                      &ppp_tty.tx_thread,
1723
                      &cyg_ppp_tx_thread_obj
1724
            );
1725
    cyg_thread_resume(ppp_tty.tx_thread);
1726
 
1727
    // Wait for the PPPD thread to get going and start the PPP
1728
    // initialization phase.
1729
    while(phase == PHASE_DEAD)
1730
        cyg_thread_delay(100);
1731
 
1732
    return (cyg_ppp_handle_t)&ppp_tty;
1733
}
1734
 
1735
// -------------------------------------------------------------------------
1736
 
1737
externC char **script;
1738
 
1739
externC void cyg_ppp_options_install( const cyg_ppp_options_t *options )
1740
{
1741
    debug               = options->debug;
1742
    kdebugflag          = options->kdebugflag;
1743
 
1744
    modem               = options->modem;
1745
    flowctl             = options->flowctl;
1746
    refuse_pap          = options->refuse_pap;
1747
    refuse_chap         = options->refuse_chap;
1748
    neg_accm            = options->neg_accm;
1749
    conf_accm           = options->conf_accm;
1750
 
1751
    inspeed             = options->baud;
1752
 
1753
    idle_time_limit     = options->idle_time_limit;
1754
    maxconnect          = options->maxconnect;
1755
 
1756
    script              = options->script;
1757
 
1758
    strncpy( user, &options->user[0], MAXNAMELEN );
1759
    strncpy( passwd, &options->passwd[0], MAXSECRETLEN );
1760
 
1761
}
1762
 
1763
// -------------------------------------------------------------------------
1764
 
1765
externC cyg_int32 cyg_ppp_down( const cyg_ppp_handle_t handle )
1766
{
1767
    if( phase != PHASE_DEAD )
1768
    {
1769
        externC int kill_link;
1770
        kill_link = 1;
1771
        cyg_thread_release( ppp_tty.pppd_thread );
1772
        ppp_tty.pppd_wakeup = 1;
1773
        return 0;
1774
    }
1775
    else
1776
        return -1;
1777
}
1778
 
1779
// -------------------------------------------------------------------------
1780
 
1781
externC cyg_int32 cyg_ppp_wait_up( cyg_ppp_handle_t handle )
1782
{
1783
    while(!( (phase == PHASE_NETWORK && ifaddrs[0] != 0) ||
1784
             phase == PHASE_DEAD ) )
1785
        cyg_thread_delay(100);
1786
 
1787
    return phase == PHASE_NETWORK ? 0 : -1;
1788
}
1789
 
1790
// -------------------------------------------------------------------------
1791
 
1792
externC void cyg_ppp_wait_down( cyg_ppp_handle_t handle )
1793
{
1794
    while( ppp_tty.tx_thread_running || ppp_tty.pppd_thread_running )
1795
        cyg_thread_delay(100);
1796
 
1797
    cyg_thread_delete( ppp_tty.tx_thread );
1798
    cyg_thread_delete( ppp_tty.pppd_thread );
1799
}
1800
 
1801
// -------------------------------------------------------------------------
1802
#ifdef CYGOPT_PPP_NS_NEGOTIATE
1803
externC u_int32_t cyg_ppp_get_neg_addrs(cyg_ppp_neg_addrs_t *addrs)
1804
{
1805
        if (phase == PHASE_NETWORK && ifaddrs[0] != 0)
1806
        {
1807
                addrs->local_ip = ipcp_gotoptions[0].ouraddr;
1808
                addrs->peer_ip = ipcp_hisoptions[0].hisaddr;
1809
                addrs->pri_dns = ipcp_gotoptions[0].dnsaddr[0];
1810
                addrs->alt_dns = ipcp_gotoptions[0].dnsaddr[1];
1811
                addrs->pri_wins = ipcp_gotoptions[0].winsaddr[0];
1812
                addrs->alt_wins = ipcp_gotoptions[0].winsaddr[1];
1813
                return(1);
1814
        }
1815
        else
1816
        {
1817
                return(0);
1818
        }
1819
}
1820
#endif
1821
//=====================================================================
1822
// eCos extras
1823
 
1824
void syslog( int level, char *fmt, ... )
1825
{
1826
    va_list ap;
1827
    int ret;
1828
 
1829
#ifdef CYGPKG_PPP_DEBUG_WARN_ONLY
1830
    if(!( level == LOG_ERR ||
1831
          level == LOG_WARNING ))
1832
        return;
1833
#endif
1834
 
1835
    va_start(ap, fmt);
1836
    diag_printf("SYSLOG %02x: ",level);
1837
    ret = diag_vprintf(fmt, ap);
1838
    diag_printf("\n");
1839
    va_end(ap);
1840
}
1841
 
1842
//=====================================================================
1843
 
1844
char *crypt (const char *key, const char *salt)
1845
{
1846
    static char res[13];
1847
 
1848
    db_printf("%s called\n", __PRETTY_FUNCTION__);
1849
 
1850
    return res;
1851
}
1852
 
1853
 
1854
//=====================================================================
1855
/*
1856
 * Substitute procedures for those systems which don't have
1857
 * drand48 et al.
1858
 */
1859
 
1860
double
1861
drand48(void)
1862
{
1863
    return (double)rand() / (double)0x7fffffffL; /* 2**31-1 */
1864
}
1865
 
1866
long
1867
mrand48(void)
1868
{
1869
    return rand();
1870
}
1871
 
1872
void
1873
srand48(long seedval)
1874
{
1875
    srand(seedval);
1876
}
1877
 
1878
 
1879
//=====================================================================
1880
 
1881
#if 0
1882
 
1883
#undef MD5Init
1884
#undef MD5Update
1885
#undef MD5Final
1886
 
1887
#include <sys/types.h>
1888
 
1889
#include <sys/md5.h>
1890
 
1891
 
1892
void   cyg_MD5Init( MD5_CTX *ctx );
1893
void   cyg_MD5Update (MD5_CTX *ctx, const unsigned char *buf, unsigned int size);
1894
void   cyg_MD5Final (unsigned char hash[16], MD5_CTX *ctx);
1895
 
1896
 
1897
void   cyg_ppp_MD5Init( MD5_CTX *ctx )
1898
{
1899
    db_printf("%s called\n", __PRETTY_FUNCTION__);
1900
    cyg_MD5Init( ctx );
1901
    return;
1902
}
1903
 
1904
void   cyg_ppp_MD5Update (MD5_CTX *ctx, const unsigned char *buf, unsigned int size)
1905
{
1906
    db_printf("%s called\n", __PRETTY_FUNCTION__);
1907
    cyg_MD5Update( ctx, buf, size );
1908
    return;
1909
}
1910
 
1911
void   cyg_ppp_MD5Final (unsigned char hash[16], MD5_CTX *ctx)
1912
{
1913
    db_printf("%s called\n", __PRETTY_FUNCTION__);
1914
    cyg_MD5Final( hash, ctx );
1915
    return;
1916
}
1917
 
1918
#endif
1919
 
1920
//=====================================================================
1921
// End of sys-ecos.c
1922
 
1923
 

powered by: WebSVN 2.1.0

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