source: rtems/c/src/libnetworking/pppd/rtems-ppp.c @ a1279374

Last change on this file since a1279374 was a1279374, checked in by Joel Sherrill <joel.sherrill@…>, on 05/25/00 at 17:17:35

Removed warning.

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