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