]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-linux.c
Merge https://github.com/yasuoka/ppp
[ppp.git] / pppd / sys-linux.c
1 /*
2  * sys-linux.c - System-dependent procedures for setting up
3  * PPP interfaces on Linux systems
4  *
5  * Copyright (c) 1994-2004 Paul Mackerras. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. The name(s) of the authors of this software must not be used to
15  *    endorse or promote products derived from this software without
16  *    prior written permission.
17  *
18  * 3. Redistributions of any form whatsoever must retain the following
19  *    acknowledgment:
20  *    "This product includes software developed by Paul Mackerras
21  *     <paulus@samba.org>".
22  *
23  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
24  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
25  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
26  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
28  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
29  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30  *
31  * Derived from main.c and pppd.h, which are:
32  *
33  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  *
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  *
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in
44  *    the documentation and/or other materials provided with the
45  *    distribution.
46  *
47  * 3. The name "Carnegie Mellon University" must not be used to
48  *    endorse or promote products derived from this software without
49  *    prior written permission. For permission or any legal
50  *    details, please contact
51  *      Office of Technology Transfer
52  *      Carnegie Mellon University
53  *      5000 Forbes Avenue
54  *      Pittsburgh, PA  15213-3890
55  *      (412) 268-4387, fax: (412) 268-7395
56  *      tech-transfer@andrew.cmu.edu
57  *
58  * 4. Redistributions of any form whatsoever must retain the following
59  *    acknowledgment:
60  *    "This product includes software developed by Computing Services
61  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
62  *
63  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
64  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
65  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
66  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
67  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
68  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
69  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
70  */
71
72 #include <sys/ioctl.h>
73 #include <sys/types.h>
74 #include <sys/socket.h>
75 #include <sys/time.h>
76 #include <sys/errno.h>
77 #include <sys/file.h>
78 #include <sys/stat.h>
79 #include <sys/utsname.h>
80 #include <sys/sysmacros.h>
81
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <syslog.h>
85 #include <string.h>
86 #include <time.h>
87 #include <memory.h>
88 #include <utmp.h>
89 #include <mntent.h>
90 #include <signal.h>
91 #include <fcntl.h>
92 #include <ctype.h>
93 #include <termios.h>
94 #include <unistd.h>
95
96 /* This is in netdevice.h. However, this compile will fail miserably if
97    you attempt to include netdevice.h because it has so many references
98    to __memcpy functions which it should not attempt to do. So, since I
99    really don't use it, but it must be defined, define it now. */
100
101 #ifndef MAX_ADDR_LEN
102 #define MAX_ADDR_LEN 7
103 #endif
104
105 #if __GLIBC__ >= 2
106 #include <asm/types.h>          /* glibc 2 conflicts with linux/types.h */
107 #include <net/if.h>
108 #include <net/if_arp.h>
109 #include <net/route.h>
110 #include <netinet/if_ether.h>
111 #else
112 #include <linux/types.h>
113 #include <linux/if.h>
114 #include <linux/if_arp.h>
115 #include <linux/route.h>
116 #include <linux/if_ether.h>
117 #endif
118 #include <netinet/in.h>
119 #include <arpa/inet.h>
120
121 #include <linux/ppp_defs.h>
122 #include <linux/if_ppp.h>
123
124 #include "pppd.h"
125 #include "fsm.h"
126 #include "ipcp.h"
127
128 #ifdef IPX_CHANGE
129 #include "ipxcp.h"
130 #if __GLIBC__ >= 2 && \
131     !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
132 #include <netipx/ipx.h>
133 #else
134 #include <linux/ipx.h>
135 #endif
136 #endif /* IPX_CHANGE */
137
138 #ifdef PPP_FILTER
139 #include <pcap-bpf.h>
140 #include <linux/filter.h>
141 #endif /* PPP_FILTER */
142
143 #ifdef LOCKLIB
144 #include <sys/locks.h>
145 #endif
146
147 #ifdef INET6
148 #ifndef _LINUX_IN6_H
149 /*
150  *    This is in linux/include/net/ipv6.h.
151  */
152
153 struct in6_ifreq {
154     struct in6_addr ifr6_addr;
155     __u32 ifr6_prefixlen;
156     unsigned int ifr6_ifindex;
157 };
158 #endif
159
160 #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {                 \
161         memset(&sin6.s6_addr, 0, sizeof(struct in6_addr));      \
162         sin6.s6_addr16[0] = htons(0xfe80);                      \
163         eui64_copy(eui64, sin6.s6_addr32[2]);                   \
164         } while (0)
165
166 #endif /* INET6 */
167
168 /* We can get an EIO error on an ioctl if the modem has hung up */
169 #define ok_error(num) ((num)==EIO)
170
171 static int tty_disc = N_TTY;    /* The TTY discipline */
172 static int ppp_disc = N_PPP;    /* The PPP discpline */
173 static int initfdflags = -1;    /* Initial file descriptor flags for fd */
174 static int ppp_fd = -1;         /* fd which is set to PPP discipline */
175 static int sock_fd = -1;        /* socket for doing interface ioctls */
176 static int slave_fd = -1;       /* pty for old-style demand mode, slave */
177 static int master_fd = -1;      /* pty for old-style demand mode, master */
178 #ifdef INET6
179 static int sock6_fd = -1;
180 #endif /* INET6 */
181
182 /*
183  * For the old-style kernel driver, this is the same as ppp_fd.
184  * For the new-style driver, it is the fd of an instance of /dev/ppp
185  * which is attached to the ppp unit and is used for controlling it.
186  */
187 int ppp_dev_fd = -1;            /* fd for /dev/ppp (new style driver) */
188
189 static int chindex;             /* channel index (new style driver) */
190
191 static fd_set in_fds;           /* set of fds that wait_input waits for */
192 static int max_in_fd;           /* highest fd set in in_fds */
193
194 static int has_proxy_arp       = 0;
195 static int driver_version      = 0;
196 static int driver_modification = 0;
197 static int driver_patch        = 0;
198 static int driver_is_old       = 0;
199 static int restore_term        = 0;     /* 1 => we've munged the terminal */
200 static struct termios inittermios;      /* Initial TTY termios */
201
202 int new_style_driver = 0;
203
204 static char loop_name[20];
205 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
206
207 static int      if_is_up;       /* Interface has been marked up */
208 static int      if6_is_up;      /* Interface has been marked up for IPv6, to help differentiate */
209 static int      have_default_route;     /* Gateway for default route added */
210 static u_int32_t proxy_arp_addr;        /* Addr for proxy arp entry added */
211 static char proxy_arp_dev[16];          /* Device for proxy arp entry */
212 static u_int32_t our_old_addr;          /* for detecting address changes */
213 static int      dynaddr_set;            /* 1 if ip_dynaddr set */
214 static int      looped;                 /* 1 if using loop */
215 static int      link_mtu;               /* mtu for the link (not bundle) */
216
217 static struct utsname utsname;  /* for the kernel version */
218 static int kernel_version;
219 #define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p))
220
221 #define MAX_IFS         100
222
223 #define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
224 #define FLAGS_MASK (IFF_UP          | IFF_BROADCAST | \
225                     IFF_POINTOPOINT | IFF_LOOPBACK  | IFF_NOARP)
226
227 #define SIN_ADDR(x)     (((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
228
229 /* Prototypes for procedures local to this file. */
230 static int modify_flags(int fd, int clear_bits, int set_bits);
231 static int translate_speed (int bps);
232 static int baud_rate_of (int speed);
233 static void close_route_table (void);
234 static int open_route_table (void);
235 static int read_route_table (struct rtentry *rt);
236 static int defaultroute_exists (struct rtentry *rt, int metric);
237 static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
238                            char *name, int namelen);
239 static void decode_version (char *buf, int *version, int *mod, int *patch);
240 static int set_kdebugflag(int level);
241 static int ppp_registered(void);
242 static int make_ppp_unit(void);
243 static int setifstate (int u, int state);
244
245 extern u_char   inpacket_buf[]; /* borrowed from main.c */
246
247 extern int dfl_route_metric;
248
249 /*
250  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
251  * if it exists.
252  */
253
254 #define SET_SA_FAMILY(addr, family)                     \
255     memset ((char *) &(addr), '\0', sizeof(addr));      \
256     addr.sa_family = (family);
257
258 /*
259  * Determine if the PPP connection should still be present.
260  */
261
262 extern int hungup;
263
264 /* new_fd is the fd of a tty */
265 static void set_ppp_fd (int new_fd)
266 {
267         ppp_fd = new_fd;
268         if (!new_style_driver)
269                 ppp_dev_fd = new_fd;
270 }
271
272 static int still_ppp(void)
273 {
274         if (new_style_driver)
275                 return !hungup && ppp_fd >= 0;
276         if (!hungup || ppp_fd == slave_fd)
277                 return 1;
278         if (slave_fd >= 0) {
279                 set_ppp_fd(slave_fd);
280                 return 1;
281         }
282         return 0;
283 }
284
285 /*
286  * modify_flags - set and clear flag bits controlling the kernel
287  * PPP driver.
288  */
289 static int modify_flags(int fd, int clear_bits, int set_bits)
290 {
291         int flags;
292
293         if (ioctl(fd, PPPIOCGFLAGS, &flags) == -1)
294                 goto err;
295         flags = (flags & ~clear_bits) | set_bits;
296         if (ioctl(fd, PPPIOCSFLAGS, &flags) == -1)
297                 goto err;
298
299         return 0;
300
301  err:
302         if (errno != EIO)
303                 error("Failed to set PPP kernel option flags: %m");
304         return -1;
305 }
306
307 /********************************************************************
308  *
309  * sys_init - System-dependent initialization.
310  */
311
312 void sys_init(void)
313 {
314     /* Get an internet socket for doing socket ioctls. */
315     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
316     if (sock_fd < 0)
317         fatal("Couldn't create IP socket: %m(%d)", errno);
318
319 #ifdef INET6
320     sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
321     if (sock6_fd < 0)
322         sock6_fd = -errno;      /* save errno for later */
323 #endif
324
325     FD_ZERO(&in_fds);
326     max_in_fd = 0;
327 }
328
329 /********************************************************************
330  *
331  * sys_cleanup - restore any system state we modified before exiting:
332  * mark the interface down, delete default route and/or proxy arp entry.
333  * This shouldn't call die() because it's called from die().
334  */
335
336 void sys_cleanup(void)
337 {
338 /*
339  * Take down the device
340  */
341     if (if_is_up) {
342         if_is_up = 0;
343         sifdown(0);
344     }
345     if (if6_is_up)
346         sif6down(0);
347
348 /*
349  * Delete any routes through the device.
350  */
351     if (have_default_route)
352         cifdefaultroute(0, 0, 0);
353
354     if (has_proxy_arp)
355         cifproxyarp(0, proxy_arp_addr);
356 }
357
358 /********************************************************************
359  *
360  * sys_close - Clean up in a child process before execing.
361  */
362 void
363 sys_close(void)
364 {
365     if (new_style_driver && ppp_dev_fd >= 0)
366         close(ppp_dev_fd);
367     if (sock_fd >= 0)
368         close(sock_fd);
369 #ifdef INET6
370     if (sock6_fd >= 0)
371         close(sock6_fd);
372 #endif
373     if (slave_fd >= 0)
374         close(slave_fd);
375     if (master_fd >= 0)
376         close(master_fd);
377 }
378
379 /********************************************************************
380  *
381  * set_kdebugflag - Define the debugging level for the kernel
382  */
383
384 static int set_kdebugflag (int requested_level)
385 {
386     if (ppp_dev_fd < 0)
387         return 1;
388     if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
389         if ( ! ok_error (errno) )
390             error("ioctl(PPPIOCSDEBUG): %m (line %d)", __LINE__);
391         return (0);
392     }
393     return (1);
394 }
395
396 /********************************************************************
397  *
398  * tty_establish_ppp - Turn the serial port into a ppp interface.
399  */
400
401 int tty_establish_ppp (int tty_fd)
402 {
403     int ret_fd;
404
405 /*
406  * Ensure that the tty device is in exclusive mode.
407  */
408     if (ioctl(tty_fd, TIOCEXCL, 0) < 0) {
409         if ( ! ok_error ( errno ))
410             warn("Couldn't make tty exclusive: %m");
411     }
412 /*
413  * Demand mode - prime the old ppp device to relinquish the unit.
414  */
415     if (!new_style_driver && looped
416         && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
417         error("ioctl(transfer ppp unit): %m, line %d", __LINE__);
418         return -1;
419     }
420 /*
421  * Set the current tty to the PPP discpline
422  */
423
424 #ifndef N_SYNC_PPP
425 #define N_SYNC_PPP 14
426 #endif
427     ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
428     if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
429         if ( ! ok_error (errno) ) {
430             error("Couldn't set tty to PPP discipline: %m");
431             return -1;
432         }
433     }
434
435     ret_fd = generic_establish_ppp(tty_fd);
436
437 #define SC_RCVB (SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP)
438 #define SC_LOGB (SC_DEBUG | SC_LOG_INPKT | SC_LOG_OUTPKT | SC_LOG_RAWIN \
439                  | SC_LOG_FLUSH)
440
441     if (ret_fd >= 0) {
442         modify_flags(ppp_fd, SC_RCVB | SC_LOGB,
443                      (kdebugflag * SC_DEBUG) & SC_LOGB);
444     } else {
445         if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
446             warn("Couldn't reset tty to normal line discipline: %m");
447     }
448
449     return ret_fd;
450 }
451
452 /********************************************************************
453  *
454  * generic_establish_ppp - Turn the fd into a ppp interface.
455  */
456 int generic_establish_ppp (int fd)
457 {
458     int x;
459
460     if (new_style_driver) {
461         int flags;
462
463         /* Open an instance of /dev/ppp and connect the channel to it */
464         if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
465             error("Couldn't get channel number: %m");
466             goto err;
467         }
468         dbglog("using channel %d", chindex);
469         fd = open("/dev/ppp", O_RDWR);
470         if (fd < 0) {
471             error("Couldn't reopen /dev/ppp: %m");
472             goto err;
473         }
474         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
475         if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
476             error("Couldn't attach to channel %d: %m", chindex);
477             goto err_close;
478         }
479         flags = fcntl(fd, F_GETFL);
480         if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
481             warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
482         set_ppp_fd(fd);
483
484         if (!looped)
485             ifunit = -1;
486         if (!looped && !multilink) {
487             /*
488              * Create a new PPP unit.
489              */
490             if (make_ppp_unit() < 0)
491                 goto err_close;
492         }
493
494         if (looped)
495             modify_flags(ppp_dev_fd, SC_LOOP_TRAFFIC, 0);
496
497         if (!multilink) {
498             add_fd(ppp_dev_fd);
499             if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
500                 error("Couldn't attach to PPP unit %d: %m", ifunit);
501                 goto err_close;
502             }
503         }
504
505     } else {
506         /*
507          * Old-style driver: find out which interface we were given.
508          */
509         set_ppp_fd (fd);
510         if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
511             if (ok_error (errno))
512                 goto err;
513             fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
514         }
515         /* Check that we got the same unit again. */
516         if (looped && x != ifunit)
517             fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
518         ifunit = x;
519
520         /*
521          * Fetch the initial file flags and reset blocking mode on the file.
522          */
523         initfdflags = fcntl(fd, F_GETFL);
524         if (initfdflags == -1 ||
525             fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
526             if ( ! ok_error (errno))
527                 warn("Couldn't set device to non-blocking mode: %m");
528         }
529     }
530
531     /*
532      * Enable debug in the driver if requested.
533      */
534     if (!looped)
535         set_kdebugflag (kdebugflag);
536
537     looped = 0;
538
539     return ppp_fd;
540
541  err_close:
542     close(fd);
543  err:
544     return -1;
545 }
546
547 /********************************************************************
548  *
549  * tty_disestablish_ppp - Restore the serial port to normal operation.
550  * This shouldn't call die() because it's called from die().
551  */
552
553 void tty_disestablish_ppp(int tty_fd)
554 {
555     if (!hungup) {
556 /*
557  * Flush the tty output buffer so that the TIOCSETD doesn't hang.
558  */
559         if (tcflush(tty_fd, TCIOFLUSH) < 0)
560         {
561             warn("tcflush failed: %m");
562             goto flushfailed;
563         }
564 /*
565  * Restore the previous line discipline
566  */
567         if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0) {
568             if ( ! ok_error (errno))
569                 error("ioctl(TIOCSETD, N_TTY): %m (line %d)", __LINE__);
570         }
571
572         if (ioctl(tty_fd, TIOCNXCL, 0) < 0) {
573             if ( ! ok_error (errno))
574                 warn("ioctl(TIOCNXCL): %m (line %d)", __LINE__);
575         }
576
577         /* Reset non-blocking mode on fd. */
578         if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0) {
579             if ( ! ok_error (errno))
580                 warn("Couldn't restore device fd flags: %m");
581         }
582     }
583 flushfailed:
584     initfdflags = -1;
585
586     generic_disestablish_ppp(tty_fd);
587 }
588
589 /********************************************************************
590  *
591  * generic_disestablish_ppp - Restore device components to normal
592  * operation, and reconnect the ppp unit to the loopback if in demand
593  * mode.  This shouldn't call die() because it's called from die().
594  */
595 void generic_disestablish_ppp(int dev_fd)
596 {
597     if (new_style_driver) {
598         close(ppp_fd);
599         ppp_fd = -1;
600         if (demand) {
601             modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
602             looped = 1;
603         } else if (!doing_multilink && ppp_dev_fd >= 0) {
604             close(ppp_dev_fd);
605             remove_fd(ppp_dev_fd);
606             ppp_dev_fd = -1;
607         }
608     } else {
609         /* old-style driver */
610         if (demand)
611             set_ppp_fd(slave_fd);
612         else
613             ppp_dev_fd = -1;
614     }
615 }
616
617 /*
618  * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
619  * Assumes new_style_driver.
620  */
621 static int make_ppp_unit()
622 {
623         int x, flags;
624
625         if (ppp_dev_fd >= 0) {
626                 dbglog("in make_ppp_unit, already had /dev/ppp open?");
627                 close(ppp_dev_fd);
628         }
629         ppp_dev_fd = open("/dev/ppp", O_RDWR);
630         if (ppp_dev_fd < 0)
631                 fatal("Couldn't open /dev/ppp: %m");
632         flags = fcntl(ppp_dev_fd, F_GETFL);
633         if (flags == -1
634             || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
635                 warn("Couldn't set /dev/ppp to nonblock: %m");
636
637         ifunit = req_unit;
638         x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
639         if (x < 0 && req_unit >= 0 && errno == EEXIST) {
640                 warn("Couldn't allocate PPP unit %d as it is already in use", req_unit);
641                 ifunit = -1;
642                 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
643         }
644         if (x < 0)
645                 error("Couldn't create new ppp unit: %m");
646
647         if (x == 0 && req_ifname[0] != '\0') {
648                 struct ifreq ifr;
649                 char t[MAXIFNAMELEN];
650                 memset(&ifr, 0, sizeof(struct ifreq));
651                 slprintf(t, sizeof(t), "%s%d", PPP_DRV_NAME, ifunit);
652                 strncpy(ifr.ifr_name, t, IF_NAMESIZE);
653                 strncpy(ifr.ifr_newname, req_ifname, IF_NAMESIZE);
654                 x = ioctl(sock_fd, SIOCSIFNAME, &ifr);
655                 if (x < 0)
656                     error("Couldn't rename interface %s to %s: %m", t, req_ifname);
657                 else
658                     info("Renamed interface %s to %s", t, req_ifname);
659         }
660
661         return x;
662 }
663
664 /*
665  * cfg_bundle - configure the existing bundle.
666  * Used in demand mode.
667  */
668 void cfg_bundle(int mrru, int mtru, int rssn, int tssn)
669 {
670         if (!new_style_driver)
671                 return;
672
673         /* set the mrru, mtu and flags */
674         if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
675                 error("Couldn't set MRRU: %m");
676
677         modify_flags(ppp_dev_fd, SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ|SC_MULTILINK,
678                      ((rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
679                       | (mrru? SC_MULTILINK: 0)));
680
681         /* connect up the channel */
682         if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
683                 fatal("Couldn't attach to PPP unit %d: %m", ifunit);
684         add_fd(ppp_dev_fd);
685 }
686
687 /*
688  * make_new_bundle - create a new PPP unit (i.e. a bundle)
689  * and connect our channel to it.  This should only get called
690  * if `multilink' was set at the time establish_ppp was called.
691  * In demand mode this uses our existing bundle instead of making
692  * a new one.
693  */
694 void make_new_bundle(int mrru, int mtru, int rssn, int tssn)
695 {
696         if (!new_style_driver)
697                 return;
698
699         /* make us a ppp unit */
700         if (make_ppp_unit() < 0)
701                 die(1);
702
703         /* set the mrru and flags */
704         cfg_bundle(mrru, mtru, rssn, tssn);
705 }
706
707 /*
708  * bundle_attach - attach our link to a given PPP unit.
709  * We assume the unit is controlled by another pppd.
710  */
711 int bundle_attach(int ifnum)
712 {
713         int master_fd;
714
715         if (!new_style_driver)
716                 return -1;
717
718         master_fd = open("/dev/ppp", O_RDWR);
719         if (master_fd < 0)
720                 fatal("Couldn't open /dev/ppp: %m");
721         if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) {
722                 if (errno == ENXIO) {
723                         close(master_fd);
724                         return 0;       /* doesn't still exist */
725                 }
726                 fatal("Couldn't attach to interface unit %d: %m\n", ifnum);
727         }
728         if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
729                 fatal("Couldn't connect to interface unit %d: %m", ifnum);
730         modify_flags(master_fd, 0, SC_MULTILINK);
731         close(master_fd);
732
733         ifunit = ifnum;
734         return 1;
735 }
736
737 /*
738  * destroy_bundle - tell the driver to destroy our bundle.
739  */
740 void destroy_bundle(void)
741 {
742         if (ppp_dev_fd >= 0) {
743                 close(ppp_dev_fd);
744                 remove_fd(ppp_dev_fd);
745                 ppp_dev_fd = -1;
746         }
747 }
748
749 /********************************************************************
750  *
751  * clean_check - Fetch the flags for the device and generate
752  * appropriate error messages.
753  */
754 void clean_check(void)
755 {
756     int x;
757     char *s;
758
759     if (still_ppp()) {
760         if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
761             s = NULL;
762             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
763             case SC_RCV_B7_0:
764                 s = "all had bit 7 set to 1";
765                 break;
766
767             case SC_RCV_B7_1:
768                 s = "all had bit 7 set to 0";
769                 break;
770
771             case SC_RCV_EVNP:
772                 s = "all had odd parity";
773                 break;
774
775             case SC_RCV_ODDP:
776                 s = "all had even parity";
777                 break;
778             }
779
780             if (s != NULL) {
781                 warn("Receive serial link is not 8-bit clean:");
782                 warn("Problem: %s", s);
783             }
784         }
785     }
786 }
787
788
789 /*
790  * List of valid speeds.
791  */
792
793 struct speed {
794     int speed_int, speed_val;
795 } speeds[] = {
796 #ifdef B50
797     { 50, B50 },
798 #endif
799 #ifdef B75
800     { 75, B75 },
801 #endif
802 #ifdef B110
803     { 110, B110 },
804 #endif
805 #ifdef B134
806     { 134, B134 },
807 #endif
808 #ifdef B150
809     { 150, B150 },
810 #endif
811 #ifdef B200
812     { 200, B200 },
813 #endif
814 #ifdef B300
815     { 300, B300 },
816 #endif
817 #ifdef B600
818     { 600, B600 },
819 #endif
820 #ifdef B1200
821     { 1200, B1200 },
822 #endif
823 #ifdef B1800
824     { 1800, B1800 },
825 #endif
826 #ifdef B2000
827     { 2000, B2000 },
828 #endif
829 #ifdef B2400
830     { 2400, B2400 },
831 #endif
832 #ifdef B3600
833     { 3600, B3600 },
834 #endif
835 #ifdef B4800
836     { 4800, B4800 },
837 #endif
838 #ifdef B7200
839     { 7200, B7200 },
840 #endif
841 #ifdef B9600
842     { 9600, B9600 },
843 #endif
844 #ifdef B19200
845     { 19200, B19200 },
846 #endif
847 #ifdef B38400
848     { 38400, B38400 },
849 #endif
850 #ifdef B57600
851     { 57600, B57600 },
852 #endif
853 #ifdef B76800
854     { 76800, B76800 },
855 #endif
856 #ifdef B115200
857     { 115200, B115200 },
858 #endif
859 #ifdef EXTA
860     { 19200, EXTA },
861 #endif
862 #ifdef EXTB
863     { 38400, EXTB },
864 #endif
865 #ifdef B230400
866     { 230400, B230400 },
867 #endif
868 #ifdef B460800
869     { 460800, B460800 },
870 #endif
871 #ifdef B921600
872     { 921600, B921600 },
873 #endif
874 #ifdef B1000000
875     { 1000000, B1000000 },
876 #endif
877 #ifdef B1152000
878     { 1152000, B1152000 },
879 #endif
880 #ifdef B1500000
881     { 1500000, B1500000 },
882 #endif
883 #ifdef B2000000
884     { 2000000, B2000000 },
885 #endif
886 #ifdef B2500000
887     { 2500000, B2500000 },
888 #endif
889 #ifdef B3000000
890     { 3000000, B3000000 },
891 #endif
892 #ifdef B3500000
893     { 3500000, B3500000 },
894 #endif
895 #ifdef B4000000
896     { 4000000, B4000000 },
897 #endif
898     { 0, 0 }
899 };
900
901 /********************************************************************
902  *
903  * Translate from bits/second to a speed_t.
904  */
905
906 static int translate_speed (int bps)
907 {
908     struct speed *speedp;
909
910     if (bps != 0) {
911         for (speedp = speeds; speedp->speed_int; speedp++) {
912             if (bps == speedp->speed_int)
913                 return speedp->speed_val;
914         }
915         warn("speed %d not supported", bps);
916     }
917     return 0;
918 }
919
920 /********************************************************************
921  *
922  * Translate from a speed_t to bits/second.
923  */
924
925 static int baud_rate_of (int speed)
926 {
927     struct speed *speedp;
928
929     if (speed != 0) {
930         for (speedp = speeds; speedp->speed_int; speedp++) {
931             if (speed == speedp->speed_val)
932                 return speedp->speed_int;
933         }
934     }
935     return 0;
936 }
937
938 /********************************************************************
939  *
940  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
941  * at the requested speed, etc.  If `local' is true, set CLOCAL
942  * regardless of whether the modem option was specified.
943  */
944
945 void set_up_tty(int tty_fd, int local)
946 {
947     int speed;
948     struct termios tios;
949
950     setdtr(tty_fd, 1);
951     if (tcgetattr(tty_fd, &tios) < 0) {
952         if (!ok_error(errno))
953             fatal("tcgetattr: %m (line %d)", __LINE__);
954         return;
955     }
956
957     if (!restore_term)
958         inittermios = tios;
959
960     tios.c_cflag     &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
961     tios.c_cflag     |= CS8 | CREAD | HUPCL;
962
963     tios.c_iflag      = IGNBRK | IGNPAR;
964     tios.c_oflag      = 0;
965     tios.c_lflag      = 0;
966     tios.c_cc[VMIN]   = 1;
967     tios.c_cc[VTIME]  = 0;
968
969     if (local || !modem)
970         tios.c_cflag ^= (CLOCAL | HUPCL);
971
972     switch (crtscts) {
973     case 1:
974         tios.c_cflag |= CRTSCTS;
975         break;
976
977     case -2:
978         tios.c_iflag     |= IXON | IXOFF;
979         tios.c_cc[VSTOP]  = 0x13;       /* DC3 = XOFF = ^S */
980         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
981         break;
982
983     case -1:
984         tios.c_cflag &= ~CRTSCTS;
985         break;
986
987     default:
988         break;
989     }
990
991     if (stop_bits >= 2)
992         tios.c_cflag |= CSTOPB;
993
994     speed = translate_speed(inspeed);
995     if (speed) {
996         cfsetospeed (&tios, speed);
997         cfsetispeed (&tios, speed);
998     }
999 /*
1000  * We can't proceed if the serial port speed is B0,
1001  * since that implies that the serial port is disabled.
1002  */
1003     else {
1004         speed = cfgetospeed(&tios);
1005         if (speed == B0)
1006             fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
1007     }
1008
1009     while (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0 && !ok_error(errno))
1010         if (errno != EINTR)
1011             fatal("tcsetattr: %m (line %d)", __LINE__);
1012
1013     baud_rate    = baud_rate_of(speed);
1014     restore_term = 1;
1015 }
1016
1017 /********************************************************************
1018  *
1019  * setdtr - control the DTR line on the serial port.
1020  * This is called from die(), so it shouldn't call die().
1021  */
1022
1023 void setdtr (int tty_fd, int on)
1024 {
1025     int modembits = TIOCM_DTR;
1026
1027     ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
1028 }
1029
1030 /********************************************************************
1031  *
1032  * restore_tty - restore the terminal to the saved settings.
1033  */
1034
1035 void restore_tty (int tty_fd)
1036 {
1037     if (restore_term) {
1038         restore_term = 0;
1039 /*
1040  * Turn off echoing, because otherwise we can get into
1041  * a loop with the tty and the modem echoing to each other.
1042  * We presume we are the sole user of this tty device, so
1043  * when we close it, it will revert to its defaults anyway.
1044  */
1045         if (!default_device)
1046             inittermios.c_lflag &= ~(ECHO | ECHONL);
1047
1048         if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0) {
1049             if (! ok_error (errno))
1050                 warn("tcsetattr: %m (line %d)", __LINE__);
1051         }
1052     }
1053 }
1054
1055 /********************************************************************
1056  *
1057  * output - Output PPP packet.
1058  */
1059
1060 void output (int unit, unsigned char *p, int len)
1061 {
1062     int fd = ppp_fd;
1063     int proto;
1064
1065     dump_packet("sent", p, len);
1066     if (snoop_send_hook) snoop_send_hook(p, len);
1067
1068     if (len < PPP_HDRLEN)
1069         return;
1070     if (new_style_driver) {
1071         p += 2;
1072         len -= 2;
1073         proto = (p[0] << 8) + p[1];
1074         if (ppp_dev_fd >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
1075             fd = ppp_dev_fd;
1076     }
1077     if (write(fd, p, len) < 0) {
1078         if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOBUFS
1079             || errno == ENXIO || errno == EIO || errno == EINTR)
1080             warn("write: warning: %m (%d)", errno);
1081         else
1082             error("write: %m (%d)", errno);
1083     }
1084 }
1085
1086 /********************************************************************
1087  *
1088  * wait_input - wait until there is data available,
1089  * for the length of time specified by *timo (indefinite
1090  * if timo is NULL).
1091  */
1092
1093 void wait_input(struct timeval *timo)
1094 {
1095     fd_set ready, exc;
1096     int n;
1097
1098     ready = in_fds;
1099     exc = in_fds;
1100     n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
1101     if (n < 0 && errno != EINTR)
1102         fatal("select: %m");
1103 }
1104
1105 /*
1106  * add_fd - add an fd to the set that wait_input waits for.
1107  */
1108 void add_fd(int fd)
1109 {
1110     if (fd >= FD_SETSIZE)
1111         fatal("internal error: file descriptor too large (%d)", fd);
1112     FD_SET(fd, &in_fds);
1113     if (fd > max_in_fd)
1114         max_in_fd = fd;
1115 }
1116
1117 /*
1118  * remove_fd - remove an fd from the set that wait_input waits for.
1119  */
1120 void remove_fd(int fd)
1121 {
1122     FD_CLR(fd, &in_fds);
1123 }
1124
1125
1126 /********************************************************************
1127  *
1128  * read_packet - get a PPP packet from the serial device.
1129  */
1130
1131 int read_packet (unsigned char *buf)
1132 {
1133     int len, nr;
1134
1135     len = PPP_MRU + PPP_HDRLEN;
1136     if (new_style_driver) {
1137         *buf++ = PPP_ALLSTATIONS;
1138         *buf++ = PPP_UI;
1139         len -= 2;
1140     }
1141     nr = -1;
1142     if (ppp_fd >= 0) {
1143         nr = read(ppp_fd, buf, len);
1144         if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1145             && errno != EIO && errno != EINTR)
1146             error("read: %m");
1147         if (nr < 0 && errno == ENXIO)
1148             return 0;
1149     }
1150     if (nr < 0 && new_style_driver && ppp_dev_fd >= 0 && !bundle_eof) {
1151         /* N.B. we read ppp_fd first since LCP packets come in there. */
1152         nr = read(ppp_dev_fd, buf, len);
1153         if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1154             && errno != EIO && errno != EINTR)
1155             error("read /dev/ppp: %m");
1156         if (nr < 0 && errno == ENXIO)
1157             nr = 0;
1158         if (nr == 0 && doing_multilink) {
1159             remove_fd(ppp_dev_fd);
1160             bundle_eof = 1;
1161         }
1162     }
1163     if (new_style_driver && ppp_fd < 0 && ppp_dev_fd < 0)
1164         nr = 0;
1165     return (new_style_driver && nr > 0)? nr+2: nr;
1166 }
1167
1168 /********************************************************************
1169  *
1170  * get_loop_output - get outgoing packets from the ppp device,
1171  * and detect when we want to bring the real link up.
1172  * Return value is 1 if we need to bring up the link, 0 otherwise.
1173  */
1174 int
1175 get_loop_output(void)
1176 {
1177     int rv = 0;
1178     int n;
1179
1180     if (new_style_driver) {
1181         while ((n = read_packet(inpacket_buf)) > 0)
1182             if (loop_frame(inpacket_buf, n))
1183                 rv = 1;
1184         return rv;
1185     }
1186
1187     while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0)
1188         if (loop_chars(inbuf, n))
1189             rv = 1;
1190
1191     if (n == 0)
1192         fatal("eof on loopback");
1193
1194     if (errno != EWOULDBLOCK && errno != EAGAIN)
1195         fatal("read from loopback: %m(%d)", errno);
1196
1197     return rv;
1198 }
1199
1200 /*
1201  * netif_set_mtu - set the MTU on the PPP network interface.
1202  */
1203 void
1204 netif_set_mtu(int unit, int mtu)
1205 {
1206     struct ifreq ifr;
1207
1208     memset (&ifr, '\0', sizeof (ifr));
1209     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1210     ifr.ifr_mtu = mtu;
1211
1212     if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
1213         error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);
1214 }
1215
1216 /*
1217  * netif_get_mtu - get the MTU on the PPP network interface.
1218  */
1219 int
1220 netif_get_mtu(int unit)
1221 {
1222     struct ifreq ifr;
1223
1224     memset (&ifr, '\0', sizeof (ifr));
1225     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1226
1227     if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
1228         error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__);
1229         return 0;
1230     }
1231     return ifr.ifr_mtu;
1232 }
1233
1234 /********************************************************************
1235  *
1236  * tty_send_config - configure the transmit characteristics of
1237  * the ppp interface.
1238  */
1239
1240 void tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
1241 {
1242         int x;
1243
1244         if (!still_ppp())
1245                 return;
1246         link_mtu = mtu;
1247         if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
1248                 if (errno != EIO && errno != ENOTTY)
1249                         error("Couldn't set transmit async character map: %m");
1250                 ++error_count;
1251                 return;
1252         }
1253
1254         x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0)
1255             | (sync_serial? SC_SYNC: 0);
1256         modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x);
1257 }
1258
1259 /********************************************************************
1260  *
1261  * tty_set_xaccm - set the extended transmit ACCM for the interface.
1262  */
1263
1264 void tty_set_xaccm (ext_accm accm)
1265 {
1266     if (!still_ppp())
1267         return;
1268     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) {
1269         if ( ! ok_error (errno))
1270             warn("ioctl(set extended ACCM): %m (line %d)", __LINE__);
1271     }
1272 }
1273
1274 /********************************************************************
1275  *
1276  * tty_recv_config - configure the receive-side characteristics of
1277  * the ppp interface.
1278  */
1279
1280 void tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
1281 {
1282 /*
1283  * If we were called because the link has gone down then there is nothing
1284  * which may be done. Just return without incident.
1285  */
1286         if (!still_ppp())
1287                 return;
1288 /*
1289  * Set the receiver parameters
1290  */
1291         if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
1292                 if (errno != EIO && errno != ENOTTY)
1293                         error("Couldn't set channel receive MRU: %m");
1294         }
1295         if (new_style_driver && ppp_dev_fd >= 0
1296             && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
1297                 error("Couldn't set MRU in generic PPP layer: %m");
1298
1299         if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
1300                 if (errno != EIO && errno != ENOTTY)
1301                         error("Couldn't set channel receive asyncmap: %m");
1302         }
1303 }
1304
1305 /********************************************************************
1306  *
1307  * ccp_test - ask kernel whether a given compression method
1308  * is acceptable for use.
1309  */
1310
1311 int
1312 ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
1313 {
1314     struct ppp_option_data data;
1315
1316     memset (&data, '\0', sizeof (data));
1317     data.ptr      = opt_ptr;
1318     data.length   = opt_len;
1319     data.transmit = for_transmit;
1320
1321     if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1322         return 1;
1323
1324     return (errno == ENOBUFS)? 0: -1;
1325 }
1326
1327 /********************************************************************
1328  *
1329  * ccp_flags_set - inform kernel about the current state of CCP.
1330  */
1331
1332 void ccp_flags_set (int unit, int isopen, int isup)
1333 {
1334         int x;
1335
1336         x = (isopen? SC_CCP_OPEN: 0) | (isup? SC_CCP_UP: 0);
1337         if (still_ppp() && ppp_dev_fd >= 0)
1338                 modify_flags(ppp_dev_fd, SC_CCP_OPEN|SC_CCP_UP, x);
1339 }
1340
1341 #ifdef PPP_FILTER
1342 /*
1343  * set_filters - set the active and pass filters in the kernel driver.
1344  */
1345 int set_filters(struct bpf_program *pass, struct bpf_program *active)
1346 {
1347         struct sock_fprog fp;
1348
1349         fp.len = pass->bf_len;
1350         fp.filter = (struct sock_filter *) pass->bf_insns;
1351         if (ioctl(ppp_dev_fd, PPPIOCSPASS, &fp) < 0) {
1352                 if (errno == ENOTTY)
1353                         warn("kernel does not support PPP filtering");
1354                 else
1355                         error("Couldn't set pass-filter in kernel: %m");
1356                 return 0;
1357         }
1358         fp.len = active->bf_len;
1359         fp.filter = (struct sock_filter *) active->bf_insns;
1360         if (ioctl(ppp_dev_fd, PPPIOCSACTIVE, &fp) < 0) {
1361                 error("Couldn't set active-filter in kernel: %m");
1362                 return 0;
1363         }
1364         return 1;
1365 }
1366 #endif /* PPP_FILTER */
1367
1368 /********************************************************************
1369  *
1370  * get_idle_time - return how long the link has been idle.
1371  */
1372 int
1373 get_idle_time(u, ip)
1374     int u;
1375     struct ppp_idle *ip;
1376 {
1377     return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;
1378 }
1379
1380 /********************************************************************
1381  *
1382  * get_ppp_stats - return statistics for the link.
1383  */
1384 int
1385 get_ppp_stats(u, stats)
1386     int u;
1387     struct pppd_stats *stats;
1388 {
1389     struct ifpppstatsreq req;
1390
1391     memset (&req, 0, sizeof (req));
1392
1393     req.stats_ptr = (caddr_t) &req.stats;
1394     strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
1395     if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
1396         error("Couldn't get PPP statistics: %m");
1397         return 0;
1398     }
1399     stats->bytes_in = req.stats.p.ppp_ibytes;
1400     stats->bytes_out = req.stats.p.ppp_obytes;
1401     stats->pkts_in = req.stats.p.ppp_ipackets;
1402     stats->pkts_out = req.stats.p.ppp_opackets;
1403     return 1;
1404 }
1405
1406 /********************************************************************
1407  *
1408  * ccp_fatal_error - returns 1 if decompression was disabled as a
1409  * result of an error detected after decompression of a packet,
1410  * 0 otherwise.  This is necessary because of patent nonsense.
1411  */
1412
1413 int ccp_fatal_error (int unit)
1414 {
1415         int flags;
1416
1417         if (ioctl(ppp_dev_fd, PPPIOCGFLAGS, &flags) < 0) {
1418                 error("Couldn't read compression error flags: %m");
1419                 flags = 0;
1420         }
1421         return flags & SC_DC_FERROR;
1422 }
1423
1424 /********************************************************************
1425  *
1426  * path_to_procfs - find the path to the proc file system mount point
1427  */
1428 static char proc_path[MAXPATHLEN];
1429 static int proc_path_len;
1430
1431 static char *path_to_procfs(const char *tail)
1432 {
1433     struct mntent *mntent;
1434     FILE *fp;
1435
1436     if (proc_path_len == 0) {
1437         /* Default the mount location of /proc */
1438         strlcpy (proc_path, "/proc", sizeof(proc_path));
1439         proc_path_len = 5;
1440         fp = fopen(MOUNTED, "r");
1441         if (fp != NULL) {
1442             while ((mntent = getmntent(fp)) != NULL) {
1443                 if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
1444                     continue;
1445                 if (strcmp(mntent->mnt_type, "proc") == 0) {
1446                     strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path));
1447                     proc_path_len = strlen(proc_path);
1448                     break;
1449                 }
1450             }
1451             fclose (fp);
1452         }
1453     }
1454
1455     strlcpy(proc_path + proc_path_len, tail,
1456             sizeof(proc_path) - proc_path_len);
1457     return proc_path;
1458 }
1459
1460 /*
1461  * /proc/net/route parsing stuff.
1462  */
1463 #define ROUTE_MAX_COLS  12
1464 FILE *route_fd = (FILE *) 0;
1465 static char route_buffer[512];
1466 static int route_dev_col, route_dest_col, route_gw_col;
1467 static int route_flags_col, route_metric_col, route_mask_col;
1468 static int route_num_cols;
1469
1470 static int open_route_table (void);
1471 static void close_route_table (void);
1472 static int read_route_table (struct rtentry *rt);
1473
1474 /********************************************************************
1475  *
1476  * close_route_table - close the interface to the route table
1477  */
1478
1479 static void close_route_table (void)
1480 {
1481     if (route_fd != (FILE *) 0) {
1482         fclose (route_fd);
1483         route_fd = (FILE *) 0;
1484     }
1485 }
1486
1487 /********************************************************************
1488  *
1489  * open_route_table - open the interface to the route table
1490  */
1491 static char route_delims[] = " \t\n";
1492
1493 static int open_route_table (void)
1494 {
1495     char *path;
1496
1497     close_route_table();
1498
1499     path = path_to_procfs("/net/route");
1500     route_fd = fopen (path, "r");
1501     if (route_fd == NULL) {
1502         error("can't open routing table %s: %m", path);
1503         return 0;
1504     }
1505
1506     route_dev_col = 0;          /* default to usual columns */
1507     route_dest_col = 1;
1508     route_gw_col = 2;
1509     route_flags_col = 3;
1510     route_metric_col = 6;
1511     route_mask_col = 7;
1512     route_num_cols = 8;
1513
1514     /* parse header line */
1515     if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
1516         char *p = route_buffer, *q;
1517         int col;
1518         for (col = 0; col < ROUTE_MAX_COLS; ++col) {
1519             int used = 1;
1520             if ((q = strtok(p, route_delims)) == 0)
1521                 break;
1522             if (strcasecmp(q, "iface") == 0)
1523                 route_dev_col = col;
1524             else if (strcasecmp(q, "destination") == 0)
1525                 route_dest_col = col;
1526             else if (strcasecmp(q, "gateway") == 0)
1527                 route_gw_col = col;
1528             else if (strcasecmp(q, "flags") == 0)
1529                 route_flags_col = col;
1530             else if (strcasecmp(q, "mask") == 0)
1531                 route_mask_col = col;
1532             else
1533                 used = 0;
1534             if (used && col >= route_num_cols)
1535                 route_num_cols = col + 1;
1536             p = NULL;
1537         }
1538     }
1539
1540     return 1;
1541 }
1542
1543 /********************************************************************
1544  *
1545  * read_route_table - read the next entry from the route table
1546  */
1547
1548 static int read_route_table(struct rtentry *rt)
1549 {
1550     char *cols[ROUTE_MAX_COLS], *p;
1551     int col;
1552
1553     memset (rt, '\0', sizeof (struct rtentry));
1554
1555     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
1556         return 0;
1557
1558     p = route_buffer;
1559     for (col = 0; col < route_num_cols; ++col) {
1560         cols[col] = strtok(p, route_delims);
1561         if (cols[col] == NULL)
1562             return 0;           /* didn't get enough columns */
1563         p = NULL;
1564     }
1565
1566     SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
1567     SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
1568     SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
1569
1570     rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
1571     rt->rt_metric = (short) strtoul(cols[route_metric_col], NULL, 10);
1572     rt->rt_dev   = cols[route_dev_col];
1573
1574     return 1;
1575 }
1576
1577 /********************************************************************
1578  *
1579  * defaultroute_exists - determine if there is a default route
1580  * with the given metric (or negative for any)
1581  */
1582
1583 static int defaultroute_exists (struct rtentry *rt, int metric)
1584 {
1585     int result = 0;
1586
1587     if (!open_route_table())
1588         return 0;
1589
1590     while (read_route_table(rt) != 0) {
1591         if ((rt->rt_flags & RTF_UP) == 0)
1592             continue;
1593
1594         if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
1595             continue;
1596         if (SIN_ADDR(rt->rt_dst) == 0L && (metric < 0
1597                                            || rt->rt_metric == metric)) {
1598             result = 1;
1599             break;
1600         }
1601     }
1602
1603     close_route_table();
1604     return result;
1605 }
1606
1607 /*
1608  * have_route_to - determine if the system has any route to
1609  * a given IP address.  `addr' is in network byte order.
1610  * Return value is 1 if yes, 0 if no, -1 if don't know.
1611  * For demand mode to work properly, we have to ignore routes
1612  * through our own interface.
1613  */
1614 int have_route_to(u_int32_t addr)
1615 {
1616     struct rtentry rt;
1617     int result = 0;
1618
1619     if (!open_route_table())
1620         return -1;              /* don't know */
1621
1622     while (read_route_table(&rt)) {
1623         if ((rt.rt_flags & RTF_UP) == 0 || strcmp(rt.rt_dev, ifname) == 0)
1624             continue;
1625         if ((addr & SIN_ADDR(rt.rt_genmask)) == SIN_ADDR(rt.rt_dst)) {
1626             result = 1;
1627             break;
1628         }
1629     }
1630
1631     close_route_table();
1632     return result;
1633 }
1634
1635 /********************************************************************
1636  *
1637  * sifdefaultroute - assign a default route through the address given.
1638  */
1639
1640 int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
1641 {
1642     struct rtentry rt;
1643
1644     if (defaultroute_exists(&rt, dfl_route_metric) && strcmp(rt.rt_dev, ifname) != 0) {
1645         if (rt.rt_flags & RTF_GATEWAY)
1646             error("not replacing existing default route via %I with metric %d",
1647                   SIN_ADDR(rt.rt_gateway), dfl_route_metric);
1648         else
1649             error("not replacing existing default route through %s with metric %d",
1650                   rt.rt_dev, dfl_route_metric);
1651         return 0;
1652     }
1653
1654     memset (&rt, 0, sizeof (rt));
1655     SET_SA_FAMILY (rt.rt_dst, AF_INET);
1656
1657     rt.rt_dev = ifname;
1658     rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
1659
1660     if (kernel_version > KVERSION(2,1,0)) {
1661         SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1662         SIN_ADDR(rt.rt_genmask) = 0L;
1663     }
1664
1665     rt.rt_flags = RTF_UP;
1666     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
1667         if ( ! ok_error ( errno ))
1668             error("default route ioctl(SIOCADDRT): %m");
1669         return 0;
1670     }
1671
1672     have_default_route = 1;
1673     return 1;
1674 }
1675
1676 /********************************************************************
1677  *
1678  * cifdefaultroute - delete a default route through the address given.
1679  */
1680
1681 int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
1682 {
1683     struct rtentry rt;
1684
1685     have_default_route = 0;
1686
1687     memset (&rt, '\0', sizeof (rt));
1688     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1689     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1690
1691     rt.rt_dev = ifname;
1692
1693     rt.rt_dev = ifname;
1694     rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
1695
1696     if (kernel_version > KVERSION(2,1,0)) {
1697         SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1698         SIN_ADDR(rt.rt_genmask) = 0L;
1699     }
1700
1701     rt.rt_flags = RTF_UP;
1702     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
1703         if (still_ppp()) {
1704             if ( ! ok_error ( errno ))
1705                 error("default route ioctl(SIOCDELRT): %m");
1706             return 0;
1707         }
1708     }
1709
1710     return 1;
1711 }
1712
1713 /********************************************************************
1714  *
1715  * sifproxyarp - Make a proxy ARP entry for the peer.
1716  */
1717
1718 int sifproxyarp (int unit, u_int32_t his_adr)
1719 {
1720     struct arpreq arpreq;
1721     char *forw_path;
1722
1723     if (has_proxy_arp == 0) {
1724         memset (&arpreq, '\0', sizeof(arpreq));
1725
1726         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1727         SIN_ADDR(arpreq.arp_pa) = his_adr;
1728         arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1729 /*
1730  * Get the hardware address of an interface on the same subnet
1731  * as our local address.
1732  */
1733         if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,
1734                             sizeof(proxy_arp_dev))) {
1735             error("Cannot determine ethernet address for proxy ARP");
1736             return 0;
1737         }
1738         strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
1739
1740         if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1741             if ( ! ok_error ( errno ))
1742                 error("ioctl(SIOCSARP): %m");
1743             return 0;
1744         }
1745         proxy_arp_addr = his_adr;
1746         has_proxy_arp = 1;
1747
1748         if (tune_kernel) {
1749             forw_path = path_to_procfs("/sys/net/ipv4/ip_forward");
1750             if (forw_path != 0) {
1751                 int fd = open(forw_path, O_WRONLY);
1752                 if (fd >= 0) {
1753                     if (write(fd, "1", 1) != 1)
1754                         error("Couldn't enable IP forwarding: %m");
1755                     close(fd);
1756                 }
1757             }
1758         }
1759     }
1760
1761     return 1;
1762 }
1763
1764 /********************************************************************
1765  *
1766  * cifproxyarp - Delete the proxy ARP entry for the peer.
1767  */
1768
1769 int cifproxyarp (int unit, u_int32_t his_adr)
1770 {
1771     struct arpreq arpreq;
1772
1773     if (has_proxy_arp) {
1774         has_proxy_arp = 0;
1775         memset (&arpreq, '\0', sizeof(arpreq));
1776         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1777         SIN_ADDR(arpreq.arp_pa) = his_adr;
1778         arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1779         strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
1780
1781         if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1782             if ( ! ok_error ( errno ))
1783                 warn("ioctl(SIOCDARP): %m");
1784             return 0;
1785         }
1786     }
1787     return 1;
1788 }
1789
1790 /********************************************************************
1791  *
1792  * get_ether_addr - get the hardware address of an interface on the
1793  * the same subnet as ipaddr.
1794  */
1795
1796 static int get_ether_addr (u_int32_t ipaddr,
1797                            struct sockaddr *hwaddr,
1798                            char *name, int namelen)
1799 {
1800     struct ifreq *ifr, *ifend;
1801     u_int32_t ina, mask;
1802     char *aliasp;
1803     struct ifreq ifreq, bestifreq;
1804     struct ifconf ifc;
1805     struct ifreq ifs[MAX_IFS];
1806
1807     u_int32_t bestmask=0;
1808     int found_interface = 0;
1809
1810     ifc.ifc_len = sizeof(ifs);
1811     ifc.ifc_req = ifs;
1812     if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
1813         if ( ! ok_error ( errno ))
1814             error("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
1815         return 0;
1816     }
1817
1818 /*
1819  * Scan through looking for an interface with an Internet
1820  * address on the same subnet as `ipaddr'.
1821  */
1822     ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1823     for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1824         if (ifr->ifr_addr.sa_family == AF_INET) {
1825             ina = SIN_ADDR(ifr->ifr_addr);
1826             strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1827 /*
1828  * Check that the interface is up, and not point-to-point
1829  * nor loopback.
1830  */
1831             if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1832                 continue;
1833
1834             if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1835                 continue;
1836 /*
1837  * Get its netmask and check that it's on the right subnet.
1838  */
1839             if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1840                 continue;
1841
1842             mask = SIN_ADDR(ifreq.ifr_addr);
1843
1844             if (((ipaddr ^ ina) & mask) != 0)
1845                 continue; /* no match */
1846             /* matched */
1847             if (mask >= bestmask) {
1848                 /* Compare using >= instead of > -- it is possible for
1849                    an interface to have a netmask of 0.0.0.0 */
1850                 found_interface = 1;
1851                 bestifreq = ifreq;
1852                 bestmask = mask;
1853             }
1854         }
1855     }
1856
1857     if (!found_interface) return 0;
1858
1859     strlcpy(name, bestifreq.ifr_name, namelen);
1860
1861     /* trim off the :1 in eth0:1 */
1862     aliasp = strchr(name, ':');
1863     if (aliasp != 0)
1864         *aliasp = 0;
1865
1866     info("found interface %s for proxy arp", name);
1867 /*
1868  * Now get the hardware address.
1869  */
1870     memset (&bestifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
1871     if (ioctl (sock_fd, SIOCGIFHWADDR, &bestifreq) < 0) {
1872         error("SIOCGIFHWADDR(%s): %m", bestifreq.ifr_name);
1873         return 0;
1874     }
1875
1876     memcpy (hwaddr,
1877             &bestifreq.ifr_hwaddr,
1878             sizeof (struct sockaddr));
1879
1880     return 1;
1881 }
1882
1883 /*
1884  * get_if_hwaddr - get the hardware address for the specified
1885  * network interface device.
1886  */
1887 int
1888 get_if_hwaddr(u_char *addr, char *name)
1889 {
1890         struct ifreq ifreq;
1891         int ret, sock_fd;
1892
1893         sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
1894         if (sock_fd < 0)
1895                 return 0;
1896         memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
1897         strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
1898         ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
1899         close(sock_fd);
1900         if (ret >= 0)
1901                 memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6);
1902         return ret;
1903 }
1904
1905 /*
1906  * get_first_ethernet - return the name of the first ethernet-style
1907  * interface on this system.
1908  */
1909 char *
1910 get_first_ethernet()
1911 {
1912         return "eth0";
1913 }
1914
1915 /********************************************************************
1916  *
1917  * Return user specified netmask, modified by any mask we might determine
1918  * for address `addr' (in network byte order).
1919  * Here we scan through the system's list of interfaces, looking for
1920  * any non-point-to-point interfaces which might appear to be on the same
1921  * network as `addr'.  If we find any, we OR in their netmask to the
1922  * user-specified netmask.
1923  */
1924
1925 u_int32_t GetMask (u_int32_t addr)
1926 {
1927     u_int32_t mask, nmask, ina;
1928     struct ifreq *ifr, *ifend, ifreq;
1929     struct ifconf ifc;
1930     struct ifreq ifs[MAX_IFS];
1931
1932     addr = ntohl(addr);
1933
1934     if (IN_CLASSA(addr))        /* determine network mask for address class */
1935         nmask = IN_CLASSA_NET;
1936     else if (IN_CLASSB(addr))
1937             nmask = IN_CLASSB_NET;
1938     else
1939             nmask = IN_CLASSC_NET;
1940
1941     /* class D nets are disallowed by bad_ip_adrs */
1942     mask = netmask | htonl(nmask);
1943 /*
1944  * Scan through the system's network interfaces.
1945  */
1946     ifc.ifc_len = sizeof(ifs);
1947     ifc.ifc_req = ifs;
1948     if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
1949         if ( ! ok_error ( errno ))
1950             warn("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
1951         return mask;
1952     }
1953
1954     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1955     for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1956 /*
1957  * Check the interface's internet address.
1958  */
1959         if (ifr->ifr_addr.sa_family != AF_INET)
1960             continue;
1961         ina = SIN_ADDR(ifr->ifr_addr);
1962         if (((ntohl(ina) ^ addr) & nmask) != 0)
1963             continue;
1964 /*
1965  * Check that the interface is up, and not point-to-point nor loopback.
1966  */
1967         strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1968         if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1969             continue;
1970
1971         if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1972             continue;
1973 /*
1974  * Get its netmask and OR it into our mask.
1975  */
1976         if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1977             continue;
1978         mask |= SIN_ADDR(ifreq.ifr_addr);
1979         break;
1980     }
1981     return mask;
1982 }
1983
1984 /********************************************************************
1985  *
1986  * Internal routine to decode the version.modification.patch level
1987  */
1988
1989 static void decode_version (char *buf, int *version,
1990                             int *modification, int *patch)
1991 {
1992     char *endp;
1993
1994     *version      = (int) strtoul (buf, &endp, 10);
1995     *modification = 0;
1996     *patch        = 0;
1997
1998     if (endp != buf && *endp == '.') {
1999         buf = endp + 1;
2000         *modification = (int) strtoul (buf, &endp, 10);
2001         if (endp != buf && *endp == '.') {
2002             buf = endp + 1;
2003             *patch = (int) strtoul (buf, &buf, 10);
2004         }
2005     }
2006 }
2007
2008 /********************************************************************
2009  *
2010  * Procedure to determine if the PPP line discipline is registered.
2011  */
2012
2013 static int
2014 ppp_registered(void)
2015 {
2016     int local_fd;
2017     int mfd = -1;
2018     int ret = 0;
2019     char slave[16];
2020
2021     /*
2022      * We used to open the serial device and set it to the ppp line
2023      * discipline here, in order to create a ppp unit.  But that is
2024      * not a good idea - the user might have specified a device that
2025      * they can't open (permission, or maybe it doesn't really exist).
2026      * So we grab a pty master/slave pair and use that.
2027      */
2028     if (!get_pty(&mfd, &local_fd, slave, 0)) {
2029         no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";
2030         return 0;
2031     }
2032
2033     /*
2034      * Try to put the device into the PPP discipline.
2035      */
2036     if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
2037         error("ioctl(TIOCSETD(PPP)): %m (line %d)", __LINE__);
2038     } else
2039         ret = 1;
2040
2041     close(local_fd);
2042     close(mfd);
2043     return ret;
2044 }
2045
2046 /********************************************************************
2047  *
2048  * ppp_available - check whether the system has any ppp interfaces
2049  * (in fact we check whether we can do an ioctl on ppp0).
2050  */
2051
2052 int ppp_available(void)
2053 {
2054     int s, ok, fd;
2055     struct ifreq ifr;
2056     int    size;
2057     int    my_version, my_modification, my_patch;
2058     int osmaj, osmin, ospatch;
2059
2060     /* get the kernel version now, since we are called before sys_init */
2061     uname(&utsname);
2062     osmaj = osmin = ospatch = 0;
2063     sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
2064     kernel_version = KVERSION(osmaj, osmin, ospatch);
2065
2066     fd = open("/dev/ppp", O_RDWR);
2067     if (fd >= 0) {
2068         new_style_driver = 1;
2069
2070         /* XXX should get from driver */
2071         driver_version = 2;
2072         driver_modification = 4;
2073         driver_patch = 0;
2074         close(fd);
2075         return 1;
2076     }
2077
2078     if (kernel_version >= KVERSION(2,3,13)) {
2079         error("Couldn't open the /dev/ppp device: %m");
2080         if (errno == ENOENT)
2081             no_ppp_msg =
2082                 "You need to create the /dev/ppp device node by\n"
2083                 "executing the following command as root:\n"
2084                 "       mknod /dev/ppp c 108 0\n";
2085         else if (errno == ENODEV || errno == ENXIO)
2086             no_ppp_msg =
2087                 "Please load the ppp_generic kernel module.\n";
2088         return 0;
2089     }
2090
2091     /* we are running on a really really old kernel */
2092     no_ppp_msg =
2093         "This system lacks kernel support for PPP.  This could be because\n"
2094         "the PPP kernel module could not be loaded, or because PPP was not\n"
2095         "included in the kernel configuration.  If PPP was included as a\n"
2096         "module, try `/sbin/modprobe -v ppp'.  If that fails, check that\n"
2097         "ppp.o exists in /lib/modules/`uname -r`/net.\n"
2098         "See README.linux file in the ppp distribution for more details.\n";
2099
2100 /*
2101  * Open a socket for doing the ioctl operations.
2102  */
2103     s = socket(AF_INET, SOCK_DGRAM, 0);
2104     if (s < 0)
2105         return 0;
2106
2107     strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2108     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2109 /*
2110  * If the device did not exist then attempt to create one by putting the
2111  * current tty into the PPP discipline. If this works then obtain the
2112  * flags for the device again.
2113  */
2114     if (!ok) {
2115         if (ppp_registered()) {
2116             strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2117             ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2118         }
2119     }
2120 /*
2121  * Ensure that the hardware address is for PPP and not something else
2122  */
2123     if (ok)
2124         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
2125
2126     if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
2127         ok = 0;
2128
2129 /*
2130  *  This is the PPP device. Validate the version of the driver at this
2131  *  point to ensure that this program will work with the driver.
2132  */
2133     if (ok) {
2134         char   abBuffer [1024];
2135
2136         ifr.ifr_data = abBuffer;
2137         size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
2138         if (size < 0) {
2139             error("Couldn't read driver version: %m");
2140             ok = 0;
2141             no_ppp_msg = "Sorry, couldn't verify kernel driver version\n";
2142
2143         } else {
2144             decode_version(abBuffer,
2145                            &driver_version,
2146                            &driver_modification,
2147                            &driver_patch);
2148 /*
2149  * Validate the version of the driver against the version that we used.
2150  */
2151             decode_version(VERSION,
2152                            &my_version,
2153                            &my_modification,
2154                            &my_patch);
2155
2156             /* The version numbers must match */
2157             if (driver_version != my_version)
2158                 ok = 0;
2159
2160             /* The modification levels must be legal */
2161             if (driver_modification < 3) {
2162                 if (driver_modification >= 2) {
2163                     /* we can cope with 2.2.0 and above */
2164                     driver_is_old = 1;
2165                 } else {
2166                     ok = 0;
2167                 }
2168             }
2169
2170             close (s);
2171             if (!ok) {
2172                 slprintf(route_buffer, sizeof(route_buffer),
2173                          "Sorry - PPP driver version %d.%d.%d is out of date\n",
2174                          driver_version, driver_modification, driver_patch);
2175
2176                 no_ppp_msg = route_buffer;
2177             }
2178         }
2179     }
2180     return ok;
2181 }
2182
2183 #ifndef HAVE_LOGWTMP
2184 /********************************************************************
2185  *
2186  * Update the wtmp file with the appropriate user name and tty device.
2187  */
2188
2189 void logwtmp (const char *line, const char *name, const char *host)
2190 {
2191     struct utmp ut, *utp;
2192     pid_t  mypid = getpid();
2193 #if __GLIBC__ < 2
2194     int    wtmp;
2195 #endif
2196
2197 /*
2198  * Update the signon database for users.
2199  * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
2200  */
2201     utmpname(_PATH_UTMP);
2202     setutent();
2203     while ((utp = getutent()) && (utp->ut_pid != mypid))
2204         /* nothing */;
2205
2206     if (utp)
2207         memcpy(&ut, utp, sizeof(ut));
2208     else
2209         /* some gettys/telnetds don't initialize utmp... */
2210         memset(&ut, 0, sizeof(ut));
2211
2212     if (ut.ut_id[0] == 0)
2213         strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
2214
2215     strncpy(ut.ut_user, name, sizeof(ut.ut_user));
2216     strncpy(ut.ut_line, line, sizeof(ut.ut_line));
2217
2218     time(&ut.ut_time);
2219
2220     ut.ut_type = USER_PROCESS;
2221     ut.ut_pid  = mypid;
2222
2223     /* Insert the host name if one is supplied */
2224     if (*host)
2225         strncpy (ut.ut_host, host, sizeof(ut.ut_host));
2226
2227     /* Insert the IP address of the remote system if IP is enabled */
2228     if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
2229         memcpy(&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
2230                  sizeof(ut.ut_addr));
2231
2232     /* CL: Makes sure that the logout works */
2233     if (*host == 0 && *name==0)
2234         ut.ut_host[0]=0;
2235
2236     pututline(&ut);
2237     endutent();
2238 /*
2239  * Update the wtmp file.
2240  */
2241 #if __GLIBC__ >= 2
2242     updwtmp(_PATH_WTMP, &ut);
2243 #else
2244     wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
2245     if (wtmp >= 0) {
2246         flock(wtmp, LOCK_EX);
2247
2248         if (write (wtmp, (char *)&ut, sizeof(ut)) != sizeof(ut))
2249             warn("error writing %s: %m", _PATH_WTMP);
2250
2251         flock(wtmp, LOCK_UN);
2252
2253         close (wtmp);
2254     }
2255 #endif
2256 }
2257 #endif /* HAVE_LOGWTMP */
2258
2259 /********************************************************************
2260  *
2261  * sifvjcomp - config tcp header compression
2262  */
2263
2264 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
2265 {
2266         u_int x;
2267
2268         if (vjcomp) {
2269                 if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
2270                         error("Couldn't set up TCP header compression: %m");
2271                         vjcomp = 0;
2272                 }
2273         }
2274
2275         x = (vjcomp? SC_COMP_TCP: 0) | (cidcomp? 0: SC_NO_TCP_CCID);
2276         modify_flags(ppp_dev_fd, SC_COMP_TCP|SC_NO_TCP_CCID, x);
2277
2278         return 1;
2279 }
2280
2281 /********************************************************************
2282  *
2283  * sifup - Config the interface up and enable IP packets to pass.
2284  */
2285
2286 int sifup(int u)
2287 {
2288     int ret;
2289
2290     if ((ret = setifstate(u, 1)))
2291         if_is_up++;
2292
2293     return ret;
2294 }
2295
2296 /********************************************************************
2297  *
2298  * sifdown - Disable the indicated protocol and config the interface
2299  *           down if there are no remaining protocols.
2300  */
2301
2302 int sifdown (int u)
2303 {
2304     if (if_is_up && --if_is_up > 0)
2305         return 1;
2306
2307 #ifdef INET6
2308     if (if6_is_up)
2309         return 1;
2310 #endif /* INET6 */
2311
2312     return setifstate(u, 0);
2313 }
2314
2315 #ifdef INET6
2316 /********************************************************************
2317  *
2318  * sif6up - Config the interface up for IPv6
2319  */
2320
2321 int sif6up(int u)
2322 {
2323     int ret;
2324
2325     if ((ret = setifstate(u, 1)))
2326         if6_is_up = 1;
2327
2328     return ret;
2329 }
2330
2331 /********************************************************************
2332  *
2333  * sif6down - Disable the IPv6CP protocol and config the interface
2334  *            down if there are no remaining protocols.
2335  */
2336
2337 int sif6down (int u)
2338 {
2339     if6_is_up = 0;
2340
2341     if (if_is_up)
2342         return 1;
2343
2344     return setifstate(u, 0);
2345 }
2346 #endif /* INET6 */
2347
2348 /********************************************************************
2349  *
2350  * setifstate - Config the interface up or down
2351  */
2352
2353 static int setifstate (int u, int state)
2354 {
2355     struct ifreq ifr;
2356
2357     memset (&ifr, '\0', sizeof (ifr));
2358     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2359     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
2360         if (! ok_error (errno))
2361             error("ioctl (SIOCGIFFLAGS): %m (line %d)", __LINE__);
2362         return 0;
2363     }
2364
2365     if (state)
2366         ifr.ifr_flags |= IFF_UP;
2367     else
2368         ifr.ifr_flags &= ~IFF_UP;
2369     ifr.ifr_flags |= IFF_POINTOPOINT;
2370     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
2371         if (! ok_error (errno))
2372             error("ioctl(SIOCSIFFLAGS): %m (line %d)", __LINE__);
2373         return 0;
2374     }
2375     return 1;
2376 }
2377
2378 /********************************************************************
2379  *
2380  * sifaddr - Config the interface IP addresses and netmask.
2381  */
2382
2383 int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
2384              u_int32_t net_mask)
2385 {
2386     struct ifreq   ifr;
2387     struct rtentry rt;
2388
2389     memset (&ifr, '\0', sizeof (ifr));
2390     memset (&rt,  '\0', sizeof (rt));
2391
2392     SET_SA_FAMILY (ifr.ifr_addr,    AF_INET);
2393     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
2394     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
2395
2396     strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2397 /*
2398  *  Set our IP address
2399  */
2400     SIN_ADDR(ifr.ifr_addr) = our_adr;
2401     if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2402         if (errno != EEXIST) {
2403             if (! ok_error (errno))
2404                 error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2405         }
2406         else {
2407             warn("ioctl(SIOCSIFADDR): Address already exists");
2408         }
2409         return (0);
2410     }
2411 /*
2412  *  Set the gateway address
2413  */
2414     if (his_adr != 0) {
2415         SIN_ADDR(ifr.ifr_dstaddr) = his_adr;
2416         if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
2417             if (! ok_error (errno))
2418                 error("ioctl(SIOCSIFDSTADDR): %m (line %d)", __LINE__);
2419             return (0);
2420         }
2421     }
2422 /*
2423  *  Set the netmask.
2424  *  For recent kernels, force the netmask to 255.255.255.255.
2425  */
2426     if (kernel_version >= KVERSION(2,1,16))
2427         net_mask = ~0L;
2428     if (net_mask != 0) {
2429         SIN_ADDR(ifr.ifr_netmask) = net_mask;
2430         if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
2431             if (! ok_error (errno))
2432                 error("ioctl(SIOCSIFNETMASK): %m (line %d)", __LINE__);
2433             return (0);
2434         }
2435     }
2436 /*
2437  *  Add the device route
2438  */
2439     if (kernel_version < KVERSION(2,1,16)) {
2440         SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2441         SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2442         rt.rt_dev = ifname;
2443
2444         SIN_ADDR(rt.rt_gateway) = 0L;
2445         SIN_ADDR(rt.rt_dst)     = his_adr;
2446         rt.rt_flags = RTF_UP | RTF_HOST;
2447
2448         if (kernel_version > KVERSION(2,1,0)) {
2449             SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2450             SIN_ADDR(rt.rt_genmask) = -1L;
2451         }
2452
2453         if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
2454             if (! ok_error (errno))
2455                 error("ioctl(SIOCADDRT) device route: %m (line %d)", __LINE__);
2456             return (0);
2457         }
2458     }
2459
2460     /* set ip_dynaddr in demand mode if address changes */
2461     if (demand && tune_kernel && !dynaddr_set
2462         && our_old_addr && our_old_addr != our_adr) {
2463         /* set ip_dynaddr if possible */
2464         char *path;
2465         int fd;
2466
2467         path = path_to_procfs("/sys/net/ipv4/ip_dynaddr");
2468         if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
2469             if (write(fd, "1", 1) != 1)
2470                 error("Couldn't enable dynamic IP addressing: %m");
2471             close(fd);
2472         }
2473         dynaddr_set = 1;        /* only 1 attempt */
2474     }
2475     our_old_addr = 0;
2476
2477     return 1;
2478 }
2479
2480 /********************************************************************
2481  *
2482  * cifaddr - Clear the interface IP addresses, and delete routes
2483  * through the interface if possible.
2484  */
2485
2486 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
2487 {
2488     struct ifreq ifr;
2489
2490     if (kernel_version < KVERSION(2,1,16)) {
2491 /*
2492  *  Delete the route through the device
2493  */
2494         struct rtentry rt;
2495         memset (&rt, '\0', sizeof (rt));
2496
2497         SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2498         SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2499         rt.rt_dev = ifname;
2500
2501         SIN_ADDR(rt.rt_gateway) = 0;
2502         SIN_ADDR(rt.rt_dst)     = his_adr;
2503         rt.rt_flags = RTF_UP | RTF_HOST;
2504
2505         if (kernel_version > KVERSION(2,1,0)) {
2506             SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2507             SIN_ADDR(rt.rt_genmask) = -1L;
2508         }
2509
2510         if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
2511             if (still_ppp() && ! ok_error (errno))
2512                 error("ioctl(SIOCDELRT) device route: %m (line %d)", __LINE__);
2513             return (0);
2514         }
2515     }
2516
2517     /* This way it is possible to have an IPX-only or IPv6-only interface */
2518     memset(&ifr, 0, sizeof(ifr));
2519     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
2520     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2521
2522     if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2523         if (! ok_error (errno)) {
2524             error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2525             return 0;
2526         }
2527     }
2528
2529     our_old_addr = our_adr;
2530
2531     return 1;
2532 }
2533
2534 #ifdef INET6
2535 /********************************************************************
2536  *
2537  * sif6addr - Config the interface with an IPv6 link-local address
2538  */
2539 int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
2540 {
2541     struct in6_ifreq ifr6;
2542     struct ifreq ifr;
2543     struct in6_rtmsg rt6;
2544
2545     if (sock6_fd < 0) {
2546         errno = -sock6_fd;
2547         error("IPv6 socket creation failed: %m");
2548         return 0;
2549     }
2550     memset(&ifr, 0, sizeof (ifr));
2551     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2552     if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
2553         error("sif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
2554         return 0;
2555     }
2556
2557     /* Local interface */
2558     memset(&ifr6, 0, sizeof(ifr6));
2559     IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
2560     ifr6.ifr6_ifindex = ifr.ifr_ifindex;
2561     ifr6.ifr6_prefixlen = 10;
2562
2563     if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
2564         error("sif6addr: ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2565         return 0;
2566     }
2567
2568     /* Route to remote host */
2569     memset(&rt6, 0, sizeof(rt6));
2570     IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
2571     rt6.rtmsg_flags = RTF_UP;
2572     rt6.rtmsg_dst_len = 10;
2573     rt6.rtmsg_ifindex = ifr.ifr_ifindex;
2574     rt6.rtmsg_metric = 1;
2575
2576     if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
2577         error("sif6addr: ioctl(SIOCADDRT): %m (line %d)", __LINE__);
2578         return 0;
2579     }
2580
2581     return 1;
2582 }
2583
2584
2585 /********************************************************************
2586  *
2587  * cif6addr - Remove IPv6 address from interface
2588  */
2589 int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
2590 {
2591     struct ifreq ifr;
2592     struct in6_ifreq ifr6;
2593
2594     if (sock6_fd < 0) {
2595         errno = -sock6_fd;
2596         error("IPv6 socket creation failed: %m");
2597         return 0;
2598     }
2599     memset(&ifr, 0, sizeof(ifr));
2600     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2601     if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
2602         error("cif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
2603         return 0;
2604     }
2605
2606     memset(&ifr6, 0, sizeof(ifr6));
2607     IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
2608     ifr6.ifr6_ifindex = ifr.ifr_ifindex;
2609     ifr6.ifr6_prefixlen = 10;
2610
2611     if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
2612         if (errno != EADDRNOTAVAIL) {
2613             if (! ok_error (errno))
2614                 error("cif6addr: ioctl(SIOCDIFADDR): %m (line %d)", __LINE__);
2615         }
2616         else {
2617             warn("cif6addr: ioctl(SIOCDIFADDR): No such address");
2618         }
2619         return (0);
2620     }
2621     return 1;
2622 }
2623 #endif /* INET6 */
2624
2625 /*
2626  * get_pty - get a pty master/slave pair and chown the slave side
2627  * to the uid given.  Assumes slave_name points to >= 16 bytes of space.
2628  */
2629 int
2630 get_pty(master_fdp, slave_fdp, slave_name, uid)
2631     int *master_fdp;
2632     int *slave_fdp;
2633     char *slave_name;
2634     int uid;
2635 {
2636     int i, mfd, sfd = -1;
2637     char pty_name[16];
2638     struct termios tios;
2639
2640 #ifdef TIOCGPTN
2641     /*
2642      * Try the unix98 way first.
2643      */
2644     mfd = open("/dev/ptmx", O_RDWR);
2645     if (mfd >= 0) {
2646         int ptn;
2647         if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) {
2648             slprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn);
2649             chmod(pty_name, S_IRUSR | S_IWUSR);
2650 #ifdef TIOCSPTLCK
2651             ptn = 0;
2652             if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0)
2653                 warn("Couldn't unlock pty slave %s: %m", pty_name);
2654 #endif
2655             if ((sfd = open(pty_name, O_RDWR | O_NOCTTY)) < 0)
2656                 warn("Couldn't open pty slave %s: %m", pty_name);
2657         }
2658     }
2659 #endif /* TIOCGPTN */
2660
2661     if (sfd < 0) {
2662         /* the old way - scan through the pty name space */
2663         for (i = 0; i < 64; ++i) {
2664             slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
2665                      'p' + i / 16, i % 16);
2666             mfd = open(pty_name, O_RDWR, 0);
2667             if (mfd >= 0) {
2668                 pty_name[5] = 't';
2669                 sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
2670                 if (sfd >= 0) {
2671                     fchown(sfd, uid, -1);
2672                     fchmod(sfd, S_IRUSR | S_IWUSR);
2673                     break;
2674                 }
2675                 close(mfd);
2676             }
2677         }
2678     }
2679
2680     if (sfd < 0)
2681         return 0;
2682
2683     strlcpy(slave_name, pty_name, 16);
2684     *master_fdp = mfd;
2685     *slave_fdp = sfd;
2686     if (tcgetattr(sfd, &tios) == 0) {
2687         tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
2688         tios.c_cflag |= CS8 | CREAD | CLOCAL;
2689         tios.c_iflag  = IGNPAR;
2690         tios.c_oflag  = 0;
2691         tios.c_lflag  = 0;
2692         if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
2693             warn("couldn't set attributes on pty: %m");
2694     } else
2695         warn("couldn't get attributes on pty: %m");
2696
2697     return 1;
2698 }
2699
2700 /********************************************************************
2701  *
2702  * open_loopback - open the device we use for getting packets
2703  * in demand mode.  Under Linux, we use a pty master/slave pair.
2704  */
2705 int
2706 open_ppp_loopback(void)
2707 {
2708     int flags;
2709
2710     looped = 1;
2711     if (new_style_driver) {
2712         /* allocate ourselves a ppp unit */
2713         if (make_ppp_unit() < 0)
2714             die(1);
2715         modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
2716         set_kdebugflag(kdebugflag);
2717         ppp_fd = -1;
2718         return ppp_dev_fd;
2719     }
2720
2721     if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
2722         fatal("No free pty for loopback");
2723
2724     set_ppp_fd(slave_fd);
2725
2726     flags = fcntl(master_fd, F_GETFL);
2727     if (flags == -1 ||
2728         fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2729         warn("couldn't set master loopback to nonblock: %m");
2730
2731     flags = fcntl(ppp_fd, F_GETFL);
2732     if (flags == -1 ||
2733         fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2734         warn("couldn't set slave loopback to nonblock: %m");
2735
2736     if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
2737         fatal("ioctl(TIOCSETD): %m (line %d)", __LINE__);
2738 /*
2739  * Find out which interface we were given.
2740  */
2741     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
2742         fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
2743 /*
2744  * Enable debug in the driver if requested.
2745  */
2746     set_kdebugflag (kdebugflag);
2747
2748     return master_fd;
2749 }
2750
2751 /********************************************************************
2752  *
2753  * sifnpmode - Set the mode for handling packets for a given NP.
2754  */
2755
2756 int
2757 sifnpmode(u, proto, mode)
2758     int u;
2759     int proto;
2760     enum NPmode mode;
2761 {
2762     struct npioctl npi;
2763
2764     npi.protocol = proto;
2765     npi.mode     = mode;
2766     if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
2767         if (! ok_error (errno))
2768             error("ioctl(PPPIOCSNPMODE, %d, %d): %m", proto, mode);
2769         return 0;
2770     }
2771     return 1;
2772 }
2773
2774 \f
2775 /********************************************************************
2776  *
2777  * sipxfaddr - Config the interface IPX networknumber
2778  */
2779
2780 int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
2781 {
2782     int    result = 1;
2783
2784 #ifdef IPX_CHANGE
2785     int    skfd;
2786     struct ifreq         ifr;
2787     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2788
2789     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2790     if (skfd < 0) {
2791         if (! ok_error (errno))
2792             dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
2793         result = 0;
2794     }
2795     else {
2796         memset (&ifr, '\0', sizeof (ifr));
2797         strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2798
2799         memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
2800         sipx->sipx_family  = AF_IPX;
2801         sipx->sipx_port    = 0;
2802         sipx->sipx_network = htonl (network);
2803         sipx->sipx_type    = IPX_FRAME_ETHERII;
2804         sipx->sipx_action  = IPX_CRTITF;
2805 /*
2806  *  Set the IPX device
2807  */
2808         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2809             result = 0;
2810             if (errno != EEXIST) {
2811                 if (! ok_error (errno))
2812                     dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (line %d)", __LINE__);
2813             }
2814             else {
2815                 warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists");
2816             }
2817         }
2818         close (skfd);
2819     }
2820 #endif
2821     return result;
2822 }
2823
2824 /********************************************************************
2825  *
2826  * cipxfaddr - Clear the information for the IPX network. The IPX routes
2827  *             are removed and the device is no longer able to pass IPX
2828  *             frames.
2829  */
2830
2831 int cipxfaddr (int unit)
2832 {
2833     int    result = 1;
2834
2835 #ifdef IPX_CHANGE
2836     int    skfd;
2837     struct ifreq         ifr;
2838     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2839
2840     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2841     if (skfd < 0) {
2842         if (! ok_error (errno))
2843             dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
2844         result = 0;
2845     }
2846     else {
2847         memset (&ifr, '\0', sizeof (ifr));
2848         strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2849
2850         sipx->sipx_type    = IPX_FRAME_ETHERII;
2851         sipx->sipx_action  = IPX_DLTITF;
2852         sipx->sipx_family  = AF_IPX;
2853 /*
2854  *  Set the IPX device
2855  */
2856         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2857             if (! ok_error (errno))
2858                 info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (line %d)", __LINE__);
2859             result = 0;
2860         }
2861         close (skfd);
2862     }
2863 #endif
2864     return result;
2865 }
2866
2867 /*
2868  * Use the hostname as part of the random number seed.
2869  */
2870 int
2871 get_host_seed()
2872 {
2873     int h;
2874     char *p = hostname;
2875
2876     h = 407;
2877     for (p = hostname; *p != 0; ++p)
2878         h = h * 37 + *p;
2879     return h;
2880 }
2881
2882 /********************************************************************
2883  *
2884  * sys_check_options - check the options that the user specified
2885  */
2886
2887 int
2888 sys_check_options(void)
2889 {
2890 #ifdef IPX_CHANGE
2891 /*
2892  * Disable the IPX protocol if the support is not present in the kernel.
2893  */
2894     char *path;
2895
2896     if (ipxcp_protent.enabled_flag) {
2897         struct stat stat_buf;
2898         if (  ((path = path_to_procfs("/net/ipx/interface")) == NULL
2899             && (path = path_to_procfs("/net/ipx_interface")) == NULL)
2900             || lstat(path, &stat_buf) < 0) {
2901             error("IPX support is not present in the kernel\n");
2902             ipxcp_protent.enabled_flag = 0;
2903         }
2904     }
2905 #endif
2906     if (demand && driver_is_old) {
2907         option_error("demand dialling is not supported by kernel driver "
2908                      "version %d.%d.%d", driver_version, driver_modification,
2909                      driver_patch);
2910         return 0;
2911     }
2912     if (multilink && !new_style_driver) {
2913         warn("Warning: multilink is not supported by the kernel driver");
2914         multilink = 0;
2915     }
2916     return 1;
2917 }
2918
2919 #ifdef INET6
2920 /*
2921  * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
2922  *
2923  * convert the 48-bit MAC address of eth0 into EUI 64. caller also assumes
2924  * that the system has a properly configured Ethernet interface for this
2925  * function to return non-zero.
2926  */
2927 int
2928 ether_to_eui64(eui64_t *p_eui64)
2929 {
2930     struct ifreq ifr;
2931     int skfd;
2932     const unsigned char *ptr;
2933
2934     skfd = socket(PF_INET6, SOCK_DGRAM, 0);
2935     if(skfd == -1)
2936     {
2937         warn("could not open IPv6 socket");
2938         return 0;
2939     }
2940
2941     strcpy(ifr.ifr_name, "eth0");
2942     if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
2943     {
2944         close(skfd);
2945         warn("could not obtain hardware address for eth0");
2946         return 0;
2947     }
2948     close(skfd);
2949
2950     /*
2951      * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
2952      */
2953     ptr = (unsigned char *) ifr.ifr_hwaddr.sa_data;
2954     p_eui64->e8[0] = ptr[0] | 0x02;
2955     p_eui64->e8[1] = ptr[1];
2956     p_eui64->e8[2] = ptr[2];
2957     p_eui64->e8[3] = 0xFF;
2958     p_eui64->e8[4] = 0xFE;
2959     p_eui64->e8[5] = ptr[3];
2960     p_eui64->e8[6] = ptr[4];
2961     p_eui64->e8[7] = ptr[5];
2962
2963     return 1;
2964 }
2965 #endif