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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 * sys-bsd.c - System-dependent procedures for setting up
3
 * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
4
 *
5
 * Copyright (c) 1989 Carnegie Mellon University.
6
 * Copyright (c) 1995 The Australian National University.
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms are permitted
10
 * provided that the above copyright notice and this paragraph are
11
 * duplicated in all such forms and that any documentation,
12
 * advertising materials, and other materials related to such
13
 * distribution and use acknowledge that the software was developed
14
 * by Carnegie Mellon University and The Australian National University.
15
 * The names of the Universities may not be used to endorse or promote
16
 * products derived from this software without specific prior written
17
 * permission.
18
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21
 */
22
 
23
#define RCSID   "sys-rtems.c,v 1.4 2002/02/27 22:43:31 joel Exp"
24
 
25
#include <stdio.h>
26
#include <string.h>
27
#include <stdlib.h>
28
#include <unistd.h>
29
#include <errno.h>
30
#include <fcntl.h>
31
#include <termios.h>
32
#include <signal.h>
33
#include <sys/ioctl.h>
34
#include <sys/types.h>
35
#include <sys/socket.h>
36
#include <sys/time.h>
37
#include <sys/stat.h>
38
#include <sys/param.h>
39
#ifdef PPP_FILTER
40
#include <net/bpf.h>
41
#endif
42
 
43
#include <net/if.h>
44
#include <net/ppp_defs.h>
45
#include <net/if_ppp.h>
46
#include <net/route.h>
47
#include <net/if_dl.h>
48
#include <netinet/in.h>
49
 
50
#if RTM_VERSION >= 3
51
#include <sys/param.h>
52
#if defined(NetBSD) && (NetBSD >= 199703)
53
#include <netinet/if_inarp.h>
54
#else   /* NetBSD 1.2D or later */
55
#include <netinet/if_ether.h>
56
#endif
57
#endif
58
 
59
#include <rtems.h>
60
#include <rtems/rtems_bsdnet.h>
61
#include <rtems/termiostypes.h>
62
extern int      rtems_bsdnet_microseconds_per_tick;
63
extern rtems_id rtems_pppd_taskid;
64
 
65
#include "pppd.h"
66
#include "fsm.h"
67
#include "ipcp.h"
68
 
69
static const char rcsid[] = RCSID;
70
 
71
 
72
static int initdisc = -1;       /* Initial TTY discipline for ppp_fd */
73
static int initfdflags = -1;    /* Initial file descriptor flags for ppp_fd */
74
static int ppp_fd = -1;         /* fd which is set to PPP discipline */
75
static int rtm_seq;
76
 
77
static int restore_term;        /* 1 => we've munged the terminal */
78
static struct termios inittermios; /* Initial TTY termios */
79
static struct winsize wsinfo;   /* Initial window size info */
80
 
81
static int loop_slave = -1;
82
static int loop_master;
83
 
84
static unsigned char inbuf[512]; /* buffer for chars read from loopback */
85
 
86
static int sockfd;              /* socket for doing interface ioctls */
87
 
88
static int if_is_up;            /* the interface is currently up */
89
static u_int32_t ifaddrs[2];    /* local and remote addresses we set */
90
static u_int32_t default_route_gateway; /* gateway addr for default route */
91
static u_int32_t proxy_arp_addr;        /* remote addr for proxy arp */
92
 
93
/* Prototypes for procedures local to this file. */
94
static int dodefaultroute __P((u_int32_t, int));
95
static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *));
96
 
97
 
98
/*
99
 * sys_init - System-dependent initialization.
100
 */
101
void
102
sys_init()
103
{
104
    /* Get an internet socket for doing socket ioctl's on. */
105
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
106
        fatal("Couldn't create IP socket: %m");
107
}
108
 
109
/*
110
 * sys_cleanup - restore any system state we modified before exiting:
111
 * mark the interface down, delete default route and/or proxy arp entry.
112
 * This should call die() because it's called from die().
113
 */
114
void
115
sys_cleanup()
116
{
117
    struct ifreq ifr;
118
 
119
    if (if_is_up) {
120
        strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
121
        if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
122
            && ((ifr.ifr_flags & IFF_UP) != 0)) {
123
            ifr.ifr_flags &= ~IFF_UP;
124
            ioctl(sockfd, SIOCSIFFLAGS, &ifr);
125
        }
126
    }
127
    if (ifaddrs[0] != 0)
128
        cifaddr(0, ifaddrs[0], ifaddrs[1]);
129
    if (default_route_gateway)
130
        cifdefaultroute(0, 0, default_route_gateway);
131
    if (proxy_arp_addr)
132
        cifproxyarp(0, proxy_arp_addr);
133
}
134
 
135
/*
136
 * sys_close - Clean up in a child process before execing.
137
 */
138
void
139
sys_close()
140
{
141
    close(sockfd);
142
    if (loop_slave >= 0) {
143
        close(loop_slave);
144
        close(loop_master);
145
    }
146
}
147
 
148
/*
149
 * sys_check_options - check the options that the user specified
150
 */
151
int
152
sys_check_options()
153
{
154
    return 1;
155
}
156
 
157
/*
158
 * ppp_available - check whether the system has any ppp interfaces
159
 * (in fact we check whether we can do an ioctl on ppp0).
160
 */
161
int
162
ppp_available()
163
{
164
    int s, ok;
165
    struct ifreq ifr;
166
 
167
    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
168
        return 1;               /* can't tell */
169
 
170
    strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
171
    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
172
    close(s);
173
 
174
    return ok;
175
}
176
 
177
/*
178
 * establish_ppp - Turn the serial port into a ppp interface.
179
 */
180
int
181
establish_ppp(fd)
182
    int fd;
183
{
184
    int taskid  = (int)rtems_pppd_taskid;
185
    int pppdisc = PPPDISC;
186
    int x;
187
 
188
    if (demand) {
189
        /*
190
         * Demand mode - prime the old ppp device to relinquish the unit.
191
         */
192
        if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
193
            fatal("ioctl(transfer ppp unit): %m");
194
    }
195
 
196
    /*
197
     * Save the old line discipline of fd, and set it to PPP.
198
     */
199
    if (ioctl(fd, TIOCGETD, &initdisc) < 0)
200
        fatal("ioctl(TIOCGETD): %m");
201
    if (ioctl(fd, TIOCSETD, &pppdisc) < 0)
202
        fatal("ioctl(TIOCSETD): %m");
203
 
204
    /* set pppd taskid into the driver */
205
    ioctl(fd, PPPIOCSTASK, &taskid);
206
 
207
    if (!demand) {
208
        /*
209
         * Find out which interface we were given.
210
         */
211
        if (ioctl(fd, PPPIOCGUNIT, &pppifunit) < 0)
212
            fatal("ioctl(PPPIOCGUNIT): %m");
213
    } else {
214
        /*
215
         * Check that we got the same unit again.
216
         */
217
        if (ioctl(fd, PPPIOCGUNIT, &x) < 0)
218
            fatal("ioctl(PPPIOCGUNIT): %m");
219
        if (x != pppifunit)
220
            fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x);
221
        x = TTYDISC;
222
        ioctl(loop_slave, TIOCSETD, &x);
223
    }
224
 
225
    ppp_fd = fd;
226
 
227
    /*
228
     * Enable debug in the driver if requested.
229
     */
230
    if (kdebugflag) {
231
        if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
232
            warn("ioctl (PPPIOCGFLAGS): %m");
233
        } else {
234
            x |= (kdebugflag & 0xFF) * SC_DEBUG;
235
            if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
236
                warn("ioctl(PPPIOCSFLAGS): %m");
237
        }
238
    }
239
 
240
    /*
241
     * Set device for non-blocking reads.
242
     */
243
    if ((initfdflags = fcntl(fd, F_GETFL)) == -1
244
        || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
245
        warn("Couldn't set device to non-blocking mode: %m");
246
    }
247
 
248
    return fd;
249
}
250
 
251
/*
252
 * restore_loop - reattach the ppp unit to the loopback.
253
 */
254
void
255
restore_loop()
256
{
257
    int x;
258
 
259
    /*
260
     * Transfer the ppp interface back to the loopback.
261
     */
262
    if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
263
        fatal("ioctl(transfer ppp unit): %m");
264
    x = PPPDISC;
265
    if (ioctl(loop_slave, TIOCSETD, &x) < 0)
266
        fatal("ioctl(TIOCSETD): %m");
267
 
268
    /*
269
     * Check that we got the same unit again.
270
     */
271
    if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0)
272
        fatal("ioctl(PPPIOCGUNIT): %m");
273
    if (x != pppifunit)
274
        fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x);
275
    ppp_fd = loop_slave;
276
}
277
 
278
 
279
/*
280
 * disestablish_ppp - Restore the serial port to normal operation.
281
 * This shouldn't call die() because it's called from die().
282
 */
283
void
284
disestablish_ppp(fd)
285
    int fd;
286
{
287
    int taskid = (int)0;
288
 
289
    /* clear pppd taskid from the driver */
290
    ioctl(fd, PPPIOCSTASK, &taskid);
291
 
292
    /* Reset non-blocking mode on fd. */
293
    if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
294
        warn("Couldn't restore device fd flags: %m");
295
    initfdflags = -1;
296
 
297
    /* Restore old line discipline. */
298
    if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
299
        error("ioctl(TIOCSETD): %m");
300
    initdisc = -1;
301
 
302
    if (fd == ppp_fd)
303
        ppp_fd = -1;
304
}
305
 
306
/*
307
 * Check whether the link seems not to be 8-bit clean.
308
 */
309
void
310
clean_check()
311
{
312
    int x;
313
    char *s;
314
 
315
    if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
316
        s = NULL;
317
        switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
318
        case SC_RCV_B7_0:
319
            s = "bit 7 set to 1";
320
            break;
321
        case SC_RCV_B7_1:
322
            s = "bit 7 set to 0";
323
            break;
324
        case SC_RCV_EVNP:
325
            s = "odd parity";
326
            break;
327
        case SC_RCV_ODDP:
328
            s = "even parity";
329
            break;
330
        }
331
        if (s != NULL) {
332
            warn("Serial link is not 8-bit clean:");
333
            warn("All received characters had %s", s);
334
        }
335
    }
336
}
337
 
338
/*
339
 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
340
 * at the requested speed, etc.  If `local' is true, set CLOCAL
341
 * regardless of whether the modem option was specified.
342
 *
343
 * For *BSD, we assume that speed_t values numerically equal bits/second.
344
 */
345
void
346
set_up_tty(fd, local)
347
    int fd, local;
348
{
349
    struct termios     tios;
350
 
351
    if (tcgetattr(fd, &tios) < 0)
352
        fatal("tcgetattr: %m");
353
 
354
    if (!restore_term) {
355
        inittermios = tios;
356
        ioctl(fd, TIOCGWINSZ, &wsinfo);
357
    }
358
 
359
    tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
360
    if (crtscts > 0 && !local) {
361
        if (crtscts == 2) {
362
#ifdef CDTRCTS
363
            tios.c_cflag |= CDTRCTS;
364
#endif
365
        } else
366
            tios.c_cflag |= CRTSCTS;
367
    } else if (crtscts < 0) {
368
        tios.c_cflag &= ~CRTSCTS;
369
#ifdef CDTRCTS
370
        tios.c_cflag &= ~CDTRCTS;
371
#endif
372
    }
373
 
374
    tios.c_cflag |= CS8 | CREAD | HUPCL;
375
    if (local || !modem)
376
        tios.c_cflag |= CLOCAL;
377
    tios.c_iflag = IGNBRK | IGNPAR;
378
    tios.c_oflag = 0;
379
    tios.c_lflag = 0;
380
    tios.c_cc[VMIN] = 1;
381
    tios.c_cc[VTIME] = 0;
382
 
383
    if (crtscts == -2) {
384
        tios.c_iflag |= IXON | IXOFF;
385
        tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
386
        tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
387
    }
388
 
389
    if (inspeed) {
390
        cfsetospeed(&tios, inspeed);
391
        cfsetispeed(&tios, inspeed);
392
    } else {
393
        inspeed = cfgetospeed(&tios);
394
        /*
395
         * We can't proceed if the serial port speed is 0,
396
         * since that implies that the serial port is disabled.
397
         */
398
        if (inspeed == 0)
399
            fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
400
    }
401
    baud_rate = inspeed;
402
 
403
/*    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {  */
404
    if (tcsetattr(fd, TCSADRAIN, &tios) < 0) {
405
        fatal("tcsetattr: %m");
406
    }
407
 
408
    restore_term = 1;
409
}
410
 
411
/*
412
 * restore_tty - restore the terminal to the saved settings.
413
 */
414
void
415
restore_tty(fd)
416
    int fd;
417
{
418
    if (restore_term) {
419
        if (!default_device) {
420
            /*
421
             * Turn off echoing, because otherwise we can get into
422
             * a loop with the tty and the modem echoing to each other.
423
             * We presume we are the sole user of this tty device, so
424
             * when we close it, it will revert to its defaults anyway.
425
             */
426
            inittermios.c_lflag &= ~(ECHO | ECHONL);
427
        }
428
/*      if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) { */
429
        if (tcsetattr(fd, TCSADRAIN, &inittermios) < 0) {
430
            if (errno != ENXIO)
431
                warn("tcsetattr: %m");
432
        }
433
        ioctl(fd, TIOCSWINSZ, &wsinfo);
434
        restore_term = 0;
435
    }
436
}
437
 
438
/*
439
 * setdtr - control the DTR line on the serial port.
440
 * This is called from die(), so it shouldn't call die().
441
 */
442
void
443
setdtr(fd, on)
444
int fd, on;
445
{
446
    int modembits = TIOCM_DTR;
447
 
448
    ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
449
}
450
 
451
/*
452
 * get_pty - get a pty master/slave pair and chown the slave side
453
 * to the uid given.  Assumes slave_name points to >= 12 bytes of space.
454
 */
455
int
456
get_pty(master_fdp, slave_fdp, slave_name, uid)
457
    int *master_fdp;
458
    int *slave_fdp;
459
    char *slave_name;
460
    int uid;
461
{
462
    return 1;
463
}
464
 
465
 
466
/*
467
 * open_ppp_loopback - open the device we use for getting
468
 * packets in demand mode, and connect it to a ppp interface.
469
 * Here we use a pty.
470
 */
471
int
472
open_ppp_loopback()
473
{
474
    return loop_master;
475
}
476
 
477
 
478
/*
479
 * output - Output PPP packet.
480
 */
481
void
482
output(unit, p, len)
483
    int unit;
484
    u_char *p;
485
    int len;
486
{
487
    if (debug);
488
        dbglog("sent %P", p, len);
489
/*    printf("sent packet [%d]\n", len); */
490
 
491
    if (write(ttyfd, p, len) < 0) {
492
        if (errno != EIO)
493
            error("write: %m");
494
    }
495
}
496
 
497
void
498
ppp_delay(void)
499
{
500
  rtems_interval     ticks;
501
 
502
  /* recommended delay to help negotiation */
503
  ticks = 300000/rtems_bsdnet_microseconds_per_tick;
504
  rtems_task_wake_after(ticks);
505
}
506
 
507
/*
508
 * wait_input - wait until there is data available,
509
 * for the length of time specified by *timo (indefinite
510
 * if timo is NULL).
511
 */
512
void
513
wait_input(timo)
514
    struct timeval *timo;
515
{
516
  rtems_interval     ticks;
517
  rtems_event_set    events;
518
 
519
  ticks = ((timo->tv_sec*1000000)+timo->tv_usec)/rtems_bsdnet_microseconds_per_tick;
520
  if ( ticks > 0 ) {
521
    rtems_event_receive(RTEMS_EVENT_31, (RTEMS_EVENT_ANY|RTEMS_WAIT), ticks, &events);
522
  }
523
}
524
 
525
/*
526
 * read_packet - get a PPP packet from the serial device.
527
 */
528
int
529
read_packet(buf)
530
    u_char *buf;
531
{
532
    int len;
533
 
534
    if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
535
        if (errno == EWOULDBLOCK || errno == EINTR) len = -1;
536
        /*fatal("read: %m"); */
537
    }
538
 
539
/*    printf("read packet [%d]\n", len); */
540
    return len;
541
}
542
 
543
 
544
/*
545
 * get_loop_output - read characters from the loopback, form them
546
 * into frames, and detect when we want to bring the real link up.
547
 * Return value is 1 if we need to bring up the link, 0 otherwise.
548
 */
549
int
550
get_loop_output()
551
{
552
    int rv = 0;
553
    int n;
554
 
555
    while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
556
        if (loop_chars(inbuf, n))
557
            rv = 1;
558
    }
559
 
560
    if (n == 0)
561
        fatal("eof on loopback");
562
    if (errno != EWOULDBLOCK)
563
        fatal("read from loopback: %m");
564
 
565
    return rv;
566
}
567
 
568
 
569
/*
570
 * ppp_send_config - configure the transmit characteristics of
571
 * the ppp interface.
572
 */
573
void
574
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
575
    int unit, mtu;
576
    u_int32_t asyncmap;
577
    int pcomp, accomp;
578
{
579
    u_int x;
580
    struct ifreq ifr;
581
 
582
    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
583
    ifr.ifr_mtu = mtu;
584
    if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
585
        fatal("ioctl(SIOCSIFMTU): %m");
586
 
587
    if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
588
        fatal("ioctl(PPPIOCSASYNCMAP): %m");
589
 
590
    if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
591
        fatal("ioctl (PPPIOCGFLAGS): %m");
592
    x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
593
    x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
594
/*    x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC; */
595
    if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
596
        fatal("ioctl(PPPIOCSFLAGS): %m");
597
}
598
 
599
 
600
/*
601
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
602
 */
603
void
604
ppp_set_xaccm(unit, accm)
605
    int unit;
606
    ext_accm accm;
607
{
608
    if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
609
        warn("ioctl(set extended ACCM): %m");
610
}
611
 
612
 
613
/*
614
 * ppp_recv_config - configure the receive-side characteristics of
615
 * the ppp interface.
616
 */
617
void
618
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
619
    int unit, mru;
620
    u_int32_t asyncmap;
621
    int pcomp, accomp;
622
{
623
    int x;
624
 
625
    if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
626
        fatal("ioctl(PPPIOCSMRU): %m");
627
    if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
628
        fatal("ioctl(PPPIOCSRASYNCMAP): %m");
629
    if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
630
        fatal("ioctl (PPPIOCGFLAGS): %m");
631
    x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
632
    if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
633
        fatal("ioctl(PPPIOCSFLAGS): %m");
634
}
635
 
636
/*
637
 * ccp_test - ask kernel whether a given compression method
638
 * is acceptable for use.  Returns 1 if the method and parameters
639
 * are OK, 0 if the method is known but the parameters are not OK
640
 * (e.g. code size should be reduced), or -1 if the method is unknown.
641
 */
642
int
643
ccp_test(unit, opt_ptr, opt_len, for_transmit)
644
    int unit, opt_len, for_transmit;
645
    u_char *opt_ptr;
646
{
647
    struct ppp_option_data data;
648
 
649
    data.ptr = opt_ptr;
650
    data.length = opt_len;
651
    data.transmit = for_transmit;
652
    if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
653
        return 1;
654
    return (errno == ENOBUFS)? 0: -1;
655
}
656
 
657
/*
658
 * ccp_flags_set - inform kernel about the current state of CCP.
659
 */
660
void
661
ccp_flags_set(unit, isopen, isup)
662
    int unit, isopen, isup;
663
{
664
    int x;
665
 
666
    if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
667
        error("ioctl (PPPIOCGFLAGS): %m");
668
        return;
669
    }
670
    x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
671
    x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
672
    if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
673
        error("ioctl(PPPIOCSFLAGS): %m");
674
}
675
 
676
/*
677
 * ccp_fatal_error - returns 1 if decompression was disabled as a
678
 * result of an error detected after decompression of a packet,
679
 * 0 otherwise.  This is necessary because of patent nonsense.
680
 */
681
int
682
ccp_fatal_error(unit)
683
    int unit;
684
{
685
    int x;
686
 
687
    if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
688
        error("ioctl(PPPIOCGFLAGS): %m");
689
        return 0;
690
    }
691
    return x & SC_DC_FERROR;
692
}
693
 
694
/*
695
 * get_idle_time - return how long the link has been idle.
696
 */
697
int
698
get_idle_time(u, ip)
699
    int u;
700
    struct ppp_idle *ip;
701
{
702
    return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
703
}
704
 
705
/*
706
 * get_ppp_stats - return statistics for the link.
707
 */
708
int
709
get_ppp_stats(u, stats)
710
    int u;
711
    struct pppd_stats *stats;
712
{
713
    struct ifpppstatsreq req;
714
 
715
    memset (&req, 0, sizeof (req));
716
    strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name));
717
    if (ioctl(sockfd, SIOCGPPPSTATS, &req) < 0) {
718
        error("Couldn't get PPP statistics: %m");
719
        return 0;
720
    }
721
    stats->bytes_in = req.stats.p.ppp_ibytes;
722
    stats->bytes_out = req.stats.p.ppp_obytes;
723
    return 1;
724
}
725
 
726
 
727
#ifdef PPP_FILTER
728
/*
729
 * set_filters - transfer the pass and active filters to the kernel.
730
 */
731
int
732
set_filters(pass, active)
733
    struct bpf_program *pass, *active;
734
{
735
    int ret = 1;
736
 
737
    if (pass->bf_len > 0) {
738
        if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
739
            error("Couldn't set pass-filter in kernel: %m");
740
            ret = 0;
741
        }
742
    }
743
    if (active->bf_len > 0) {
744
        if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
745
            error("Couldn't set active-filter in kernel: %m");
746
            ret = 0;
747
        }
748
    }
749
    return ret;
750
}
751
#endif
752
 
753
/*
754
 * sifvjcomp - config tcp header compression
755
 */
756
int
757
sifvjcomp(u, vjcomp, cidcomp, maxcid)
758
    int u, vjcomp, cidcomp, maxcid;
759
{
760
    u_int x;
761
 
762
    if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
763
        error("ioctl (PPPIOCGFLAGS): %m");
764
        return 0;
765
    }
766
    x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
767
    x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
768
    if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
769
        error("ioctl(PPPIOCSFLAGS): %m");
770
        return 0;
771
    }
772
    if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
773
        error("ioctl(PPPIOCSFLAGS): %m");
774
        return 0;
775
    }
776
    return 1;
777
}
778
 
779
/*
780
 * sifup - Config the interface up and enable IP packets to pass.
781
 */
782
int
783
sifup(u)
784
    int u;
785
{
786
    struct ifreq ifr;
787
 
788
    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
789
    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
790
        error("ioctl (SIOCGIFFLAGS): %m");
791
        return 0;
792
    }
793
    ifr.ifr_flags |= IFF_UP;
794
    if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
795
        error("ioctl(SIOCSIFFLAGS): %m");
796
        return 0;
797
    }
798
    if_is_up = 1;
799
    return 1;
800
}
801
 
802
/*
803
 * sifnpmode - Set the mode for handling packets for a given NP.
804
 */
805
int
806
sifnpmode(u, proto, mode)
807
    int u;
808
    int proto;
809
    enum NPmode mode;
810
{
811
    struct npioctl npi;
812
 
813
    npi.protocol = proto;
814
    npi.mode = mode;
815
    if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
816
        error("ioctl(set NP %d mode to %d): %m", proto, mode);
817
        return 0;
818
    }
819
    return 1;
820
}
821
 
822
/*
823
 * sifdown - Config the interface down and disable IP.
824
 */
825
int
826
sifdown(u)
827
    int u;
828
{
829
    struct ifreq ifr;
830
    int rv;
831
    struct npioctl npi;
832
 
833
    rv = 1;
834
    npi.protocol = PPP_IP;
835
    npi.mode = NPMODE_ERROR;
836
    ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
837
    /* ignore errors, because ppp_fd might have been closed by now. */
838
 
839
    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
840
    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
841
        error("ioctl (SIOCGIFFLAGS): %m");
842
        rv = 0;
843
    } else {
844
        ifr.ifr_flags &= ~IFF_UP;
845
        if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
846
            error("ioctl(SIOCSIFFLAGS): %m");
847
            rv = 0;
848
        } else
849
            if_is_up = 0;
850
    }
851
    return rv;
852
}
853
 
854
/*
855
 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
856
 * if it exists.
857
 */
858
#define SET_SA_FAMILY(addr, family)             \
859
    BZERO((char *) &(addr), sizeof(addr));      \
860
    addr.sa_family = (family);                  \
861
    addr.sa_len = sizeof(addr);
862
 
863
/*
864
 * sifaddr - Config the interface IP addresses and netmask.
865
 */
866
int
867
sifaddr(u, o, h, m)
868
    int u;
869
    u_int32_t o, h, m;
870
{
871
    struct ifaliasreq ifra;
872
    struct ifreq ifr;
873
 
874
    strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
875
    SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
876
    ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
877
    SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
878
    ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
879
    if (m != 0) {
880
        SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
881
        ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
882
    } else
883
        BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
884
    BZERO(&ifr, sizeof(ifr));
885
    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
886
    if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
887
        if (errno != EADDRNOTAVAIL)
888
            warn("Couldn't remove interface address: %m");
889
    }
890
    if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
891
        if (errno != EEXIST) {
892
            error("Couldn't set interface address: %m");
893
            return 0;
894
        }
895
        warn("Couldn't set interface address: Address %I already exists", o);
896
    }
897
    ifaddrs[0] = o;
898
    ifaddrs[1] = h;
899
    return 1;
900
}
901
 
902
/*
903
 * cifaddr - Clear the interface IP addresses, and delete routes
904
 * through the interface if possible.
905
 */
906
int
907
cifaddr(u, o, h)
908
    int u;
909
    u_int32_t o, h;
910
{
911
    struct ifaliasreq ifra;
912
 
913
    ifaddrs[0] = 0;
914
    strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
915
    SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
916
    ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
917
    SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
918
    ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
919
    BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
920
    if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
921
        if (errno != EADDRNOTAVAIL)
922
            warn("Couldn't delete interface address: %m");
923
        return 0;
924
    }
925
    return 1;
926
}
927
 
928
/*
929
 * sifdefaultroute - assign a default route through the address given.
930
 */
931
int
932
sifdefaultroute(u, l, g)
933
    int u;
934
    u_int32_t l, g;
935
{
936
    return dodefaultroute(g, 's');
937
}
938
 
939
/*
940
 * cifdefaultroute - delete a default route through the address given.
941
 */
942
int
943
cifdefaultroute(u, l, g)
944
    int u;
945
    u_int32_t l, g;
946
{
947
    return dodefaultroute(g, 'c');
948
}
949
 
950
/*
951
 * dodefaultroute - talk to a routing socket to add/delete a default route.
952
 */
953
static int
954
dodefaultroute(g, cmd)
955
    u_int32_t g;
956
    int cmd;
957
{
958
/*    int    status;  */
959
    struct sockaddr_in address;
960
    struct sockaddr_in netmask;
961
    struct sockaddr_in gateway;
962
 
963
    memset((void *) &address, 0, sizeof(address));
964
    address.sin_len = sizeof address;
965
    address.sin_family = AF_INET;
966
    address.sin_addr.s_addr = INADDR_ANY;
967
 
968
    memset((void *) &netmask, 0, sizeof(netmask));
969
    netmask.sin_len = sizeof netmask;
970
    netmask.sin_addr.s_addr = INADDR_ANY;
971
    netmask.sin_family = AF_INET;
972
 
973
    if (cmd=='s') {
974
      memset((void *) &gateway, 0, sizeof(gateway));
975
      gateway.sin_len = sizeof gateway;
976
      gateway.sin_family = AF_INET;
977
      gateway.sin_addr.s_addr = g;
978
 
979
      rtems_bsdnet_rtrequest(RTM_ADD,
980
                             (struct sockaddr *)&address,
981
                             (struct sockaddr *)&gateway,
982
                             (struct sockaddr *)&netmask,
983
                             (RTF_UP|RTF_GATEWAY|RTF_STATIC), NULL);
984
    }
985
    else {
986
      memset((void *) &gateway, 0, sizeof(gateway));
987
      gateway.sin_len = sizeof gateway;
988
      gateway.sin_family = AF_INET;
989
      gateway.sin_addr.s_addr =  INADDR_ANY;
990
 
991
      rtems_bsdnet_rtrequest(RTM_DELETE,
992
                             (struct sockaddr *)&address,
993
                             (struct sockaddr *)&gateway,
994
                             (struct sockaddr *)&netmask,
995
                             (RTF_UP|RTF_STATIC), NULL);
996
    }
997
 
998
    default_route_gateway = (cmd == 's')? g: 0;
999
 
1000
    return 1;
1001
}
1002
 
1003
#if RTM_VERSION >= 3
1004
 
1005
/*
1006
 * sifproxyarp - Make a proxy ARP entry for the peer.
1007
 */
1008
static struct {
1009
    struct rt_msghdr            hdr;
1010
    struct sockaddr_inarp       dst;
1011
    struct sockaddr_dl          hwa;
1012
    char                        extra[128];
1013
} arpmsg;
1014
 
1015
static int arpmsg_valid;
1016
 
1017
int
1018
sifproxyarp(unit, hisaddr)
1019
    int unit;
1020
    u_int32_t hisaddr;
1021
{
1022
    int routes;
1023
 
1024
    /*
1025
     * Get the hardware address of an interface on the same subnet
1026
     * as our local address.
1027
     */
1028
    memset(&arpmsg, 0, sizeof(arpmsg));
1029
    if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1030
        error("Cannot determine ethernet address for proxy ARP");
1031
        return 0;
1032
    }
1033
 
1034
    if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1035
        error("Couldn't add proxy arp entry: socket: %m");
1036
        return 0;
1037
    }
1038
 
1039
    arpmsg.hdr.rtm_type = RTM_ADD;
1040
    arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
1041
    arpmsg.hdr.rtm_version = RTM_VERSION;
1042
    arpmsg.hdr.rtm_seq = ++rtm_seq;
1043
    arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
1044
    arpmsg.hdr.rtm_inits = RTV_EXPIRE;
1045
    arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1046
    arpmsg.dst.sin_family = AF_INET;
1047
    arpmsg.dst.sin_addr.s_addr = hisaddr;
1048
    arpmsg.dst.sin_other = SIN_PROXY;
1049
 
1050
    arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1051
        + arpmsg.hwa.sdl_len;
1052
    if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1053
        error("Couldn't add proxy arp entry: %m");
1054
        close(routes);
1055
        return 0;
1056
    }
1057
 
1058
    close(routes);
1059
    arpmsg_valid = 1;
1060
    proxy_arp_addr = hisaddr;
1061
    return 1;
1062
}
1063
 
1064
/*
1065
 * cifproxyarp - Delete the proxy ARP entry for the peer.
1066
 */
1067
int
1068
cifproxyarp(unit, hisaddr)
1069
    int unit;
1070
    u_int32_t hisaddr;
1071
{
1072
    int routes;
1073
 
1074
    if (!arpmsg_valid)
1075
        return 0;
1076
    arpmsg_valid = 0;
1077
 
1078
    arpmsg.hdr.rtm_type = RTM_DELETE;
1079
    arpmsg.hdr.rtm_seq = ++rtm_seq;
1080
 
1081
    if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1082
        error("Couldn't delete proxy arp entry: socket: %m");
1083
        return 0;
1084
    }
1085
 
1086
    if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1087
        error("Couldn't delete proxy arp entry: %m");
1088
        close(routes);
1089
        return 0;
1090
    }
1091
 
1092
    close(routes);
1093
    proxy_arp_addr = 0;
1094
    return 1;
1095
}
1096
 
1097
#else   /* RTM_VERSION */
1098
 
1099
/*
1100
 * sifproxyarp - Make a proxy ARP entry for the peer.
1101
 */
1102
int
1103
sifproxyarp(unit, hisaddr)
1104
    int unit;
1105
    u_int32_t hisaddr;
1106
{
1107
    struct arpreq arpreq;
1108
    struct {
1109
        struct sockaddr_dl      sdl;
1110
        char                    space[128];
1111
    } dls;
1112
 
1113
    BZERO(&arpreq, sizeof(arpreq));
1114
 
1115
    /*
1116
     * Get the hardware address of an interface on the same subnet
1117
     * as our local address.
1118
     */
1119
    if (!get_ether_addr(hisaddr, &dls.sdl)) {
1120
        error("Cannot determine ethernet address for proxy ARP");
1121
        return 0;
1122
    }
1123
 
1124
    arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1125
    arpreq.arp_ha.sa_family = AF_UNSPEC;
1126
    BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1127
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1128
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1129
    arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1130
    if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1131
        error("Couldn't add proxy arp entry: %m");
1132
        return 0;
1133
    }
1134
 
1135
    proxy_arp_addr = hisaddr;
1136
    return 1;
1137
}
1138
 
1139
/*
1140
 * cifproxyarp - Delete the proxy ARP entry for the peer.
1141
 */
1142
int
1143
cifproxyarp(unit, hisaddr)
1144
    int unit;
1145
    u_int32_t hisaddr;
1146
{
1147
    struct arpreq arpreq;
1148
 
1149
    BZERO(&arpreq, sizeof(arpreq));
1150
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1151
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1152
    if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1153
        warn("Couldn't delete proxy arp entry: %m");
1154
        return 0;
1155
    }
1156
    proxy_arp_addr = 0;
1157
    return 1;
1158
}
1159
#endif  /* RTM_VERSION */
1160
 
1161
 
1162
/*
1163
 * get_ether_addr - get the hardware address of an interface on the
1164
 * the same subnet as ipaddr.
1165
 */
1166
#define MAX_IFS         32
1167
 
1168
static int
1169
get_ether_addr(ipaddr, hwaddr)
1170
    u_int32_t ipaddr;
1171
    struct sockaddr_dl *hwaddr;
1172
{
1173
    struct ifreq *ifr, *ifend, *ifp;
1174
    u_int32_t ina, mask;
1175
    struct sockaddr_dl *dla;
1176
    struct ifreq ifreq;
1177
    struct ifconf ifc;
1178
    struct ifreq ifs[MAX_IFS];
1179
 
1180
    ifc.ifc_len = sizeof(ifs);
1181
    ifc.ifc_req = ifs;
1182
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1183
        error("ioctl(SIOCGIFCONF): %m");
1184
        return 0;
1185
    }
1186
 
1187
    /*
1188
     * Scan through looking for an interface with an Internet
1189
     * address on the same subnet as `ipaddr'.
1190
     */
1191
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1192
    for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1193
                ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
1194
        if (ifr->ifr_addr.sa_family == AF_INET) {
1195
            ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1196
            strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1197
            /*
1198
             * Check that the interface is up, and not point-to-point
1199
             * or loopback.
1200
             */
1201
            if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1202
                continue;
1203
            if ((ifreq.ifr_flags &
1204
                 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1205
                 != (IFF_UP|IFF_BROADCAST))
1206
                continue;
1207
            /*
1208
             * Get its netmask and check that it's on the right subnet.
1209
             */
1210
            if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1211
                continue;
1212
            mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1213
            if ((ipaddr & mask) != (ina & mask))
1214
                continue;
1215
 
1216
            break;
1217
        }
1218
    }
1219
 
1220
    if (ifr >= ifend)
1221
        return 0;
1222
    info("found interface %s for proxy arp", ifr->ifr_name);
1223
 
1224
    /*
1225
     * Now scan through again looking for a link-level address
1226
     * for this interface.
1227
     */
1228
    ifp = ifr;
1229
    for (ifr = ifc.ifc_req; ifr < ifend; ) {
1230
        if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
1231
            && ifr->ifr_addr.sa_family == AF_LINK) {
1232
            /*
1233
             * Found the link-level address - copy it out
1234
             */
1235
            dla = (struct sockaddr_dl *) &ifr->ifr_addr;
1236
            BCOPY(dla, hwaddr, dla->sdl_len);
1237
            return 1;
1238
        }
1239
        ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
1240
    }
1241
 
1242
    return 0;
1243
}
1244
 
1245
/*
1246
 * Return user specified netmask, modified by any mask we might determine
1247
 * for address `addr' (in network byte order).
1248
 * Here we scan through the system's list of interfaces, looking for
1249
 * any non-point-to-point interfaces which might appear to be on the same
1250
 * network as `addr'.  If we find any, we OR in their netmask to the
1251
 * user-specified netmask.
1252
 */
1253
u_int32_t
1254
GetMask(addr)
1255
    u_int32_t addr;
1256
{
1257
    u_int32_t mask, nmask, ina;
1258
    struct ifreq *ifr, *ifend, ifreq;
1259
    struct ifconf ifc;
1260
    struct ifreq ifs[MAX_IFS];
1261
 
1262
    addr = ntohl(addr);
1263
    if (IN_CLASSA(addr))        /* determine network mask for address class */
1264
        nmask = IN_CLASSA_NET;
1265
    else if (IN_CLASSB(addr))
1266
        nmask = IN_CLASSB_NET;
1267
    else
1268
        nmask = IN_CLASSC_NET;
1269
    /* class D nets are disallowed by bad_ip_adrs */
1270
    mask = netmask | htonl(nmask);
1271
 
1272
    /*
1273
     * Scan through the system's network interfaces.
1274
     */
1275
    ifc.ifc_len = sizeof(ifs);
1276
    ifc.ifc_req = ifs;
1277
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1278
        warn("ioctl(SIOCGIFCONF): %m");
1279
        return mask;
1280
    }
1281
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1282
    for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1283
                ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
1284
        /*
1285
         * Check the interface's internet address.
1286
         */
1287
        if (ifr->ifr_addr.sa_family != AF_INET)
1288
            continue;
1289
        ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1290
        if ((ntohl(ina) & nmask) != (addr & nmask))
1291
            continue;
1292
        /*
1293
         * Check that the interface is up, and not point-to-point or loopback.
1294
         */
1295
        strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1296
        if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1297
            continue;
1298
        if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1299
            != IFF_UP)
1300
            continue;
1301
        /*
1302
         * Get its netmask and OR it into our mask.
1303
         */
1304
        if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1305
            continue;
1306
        mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1307
    }
1308
 
1309
    return mask;
1310
}
1311
 
1312
/*
1313
 * have_route_to - determine if the system has any route to
1314
 * a given IP address.
1315
 * For demand mode to work properly, we have to ignore routes
1316
 * through our own interface.
1317
 */
1318
int have_route_to(u_int32_t addr)
1319
{
1320
    return -1;
1321
}
1322
 
1323
/*
1324
 * Use the hostid as part of the random number seed.
1325
 */
1326
int
1327
get_host_seed()
1328
{
1329
    return 17;
1330
}

powered by: WebSVN 2.1.0

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