]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-linux.c
use asm/byteorder.h, not endian.h
[ppp.git] / pppd / sys-linux.c
1 /*
2  * sys-linux.c - System-dependent procedures for setting up
3  * PPP interfaces on Linux systems
4  *
5  * Copyright (c) 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
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <syslog.h>
32 #include <string.h>
33 #include <time.h>
34 #include <memory.h>
35 #include <utmp.h>
36 #include <mntent.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <ctype.h>
40
41 /* This is in netdevice.h. However, this compile will fail miserably if
42    you attempt to include netdevice.h because it has so many references
43    to __memcpy functions which it should not attempt to do. So, since I
44    really don't use it, but it must be defined, define it now. */
45
46 #ifndef MAX_ADDR_LEN
47 #define MAX_ADDR_LEN 7
48 #endif
49
50 #include <net/if.h>
51 #include <linux/ppp_defs.h>
52 #include <net/if_arp.h>
53 #include <linux/if_ppp.h>
54 #include <net/route.h>
55 #include <linux/if_ether.h>
56 #include <netinet/in.h>
57
58 #include "pppd.h"
59 #include "fsm.h"
60 #include "ipcp.h"
61
62 #ifdef IPX_CHANGE
63 #include "ipxcp.h"
64 #endif
65
66 #define ok_error(num) ((num)==EIO)
67
68 static int tty_disc = N_TTY;    /* The TTY discipline */
69 static int ppp_disc = N_PPP;    /* The PPP discpline */
70 static int initfdflags = -1;    /* Initial file descriptor flags for fd */
71 static int ppp_fd = -1;         /* fd which is set to PPP discipline */
72 static int sock_fd = -1;        /* socket for doing interface ioctls */
73 static int slave_fd = -1;
74 static int master_fd = -1;
75
76 static int has_proxy_arp       = 0;
77 static int driver_version      = 0;
78 static int driver_modification = 0;
79 static int driver_patch        = 0;
80 static int restore_term        = 0;     /* 1 => we've munged the terminal */
81 static struct termios inittermios;      /* Initial TTY termios */
82
83 static char loop_name[20];
84 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
85
86 static int      if_is_up;       /* Interface has been marked up */
87 static u_int32_t default_route_gateway; /* Gateway for default route added */
88 static u_int32_t proxy_arp_addr;        /* Addr for proxy arp entry added */
89
90 static char *lock_file;
91
92 #define MAX_IFS         100
93
94 #define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
95 #define FLAGS_MASK (IFF_UP          | IFF_BROADCAST | \
96                     IFF_POINTOPOINT | IFF_LOOPBACK  | IFF_NOARP)
97
98 /* Prototypes for procedures local to this file. */
99 static int get_flags (void);
100 static void set_flags (int flags);
101 static int translate_speed (int bps);
102 static int baud_rate_of (int speed);
103 static char *path_to_route (void);
104 static void close_route_table (void);
105 static int open_route_table (void);
106 static int read_route_table (struct rtentry *rt);
107 static int defaultroute_exists (struct rtentry *rt);
108 static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
109                            char *name);
110 static void decode_version (char *buf, int *version, int *mod, int *patch);
111
112 extern u_char   inpacket_buf[]; /* borrowed from main.c */
113
114 /*
115  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
116  * if it exists.
117  */
118
119 #define SET_SA_FAMILY(addr, family)                     \
120     memset ((char *) &(addr), '\0', sizeof(addr));      \
121     addr.sa_family = (family);
122
123 /*
124  * Determine if the PPP connection should still be present.
125  */
126
127 extern int hungup;
128 #define still_ppp() (hungup == 0)
129
130 #ifndef LOCK_PREFIX
131 #define LOCK_PREFIX     "/var/lock/LCK.."
132 #endif
133
134 /********************************************************************
135  *
136  * Functions to read and set the flags value in the device driver
137  */
138
139 static void set_ppp_fd (int new_fd)
140   {    
141     SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", ppp_fd));
142     ppp_fd = new_fd;
143   }
144
145 /********************************************************************
146  *
147  * Functions to read and set the flags value in the device driver
148  */
149
150 static int get_flags (void)
151   {    
152     int flags;
153
154     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0)
155       {
156         if ( ok_error (errno) )
157           {
158             flags = 0;
159           }
160         else
161           {
162             syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
163             quit();
164           }
165       }
166
167     SYSDEBUG ((LOG_DEBUG, "get flags = %x\n", flags));
168     return flags;
169   }
170
171 /********************************************************************/
172
173 static void set_flags (int flags)
174   {    
175     SYSDEBUG ((LOG_DEBUG, "set flags = %x\n", flags));
176
177     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
178       {
179         if (! ok_error (errno) )
180           {
181             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS, %x): %m(%d)", flags, errno);
182             quit();
183           }
184       }
185   }
186
187 /********************************************************************
188  *
189  * sys_init - System-dependent initialization.
190  */
191
192 void sys_init(void)
193   {
194     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
195     setlogmask(LOG_UPTO(LOG_INFO));
196     if (debug)
197       {
198         setlogmask(LOG_UPTO(LOG_DEBUG));
199       }
200     
201     /* Get an internet socket for doing socket ioctls. */
202     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
203     if (sock_fd < 0)
204       {
205         if ( ! ok_error ( errno ))
206           {
207             syslog(LOG_ERR, "Couldn't create IP socket: %m(%d)", errno);
208             die(1);
209           }
210       }
211   }
212
213 /********************************************************************
214  *
215  * sys_cleanup - restore any system state we modified before exiting:
216  * mark the interface down, delete default route and/or proxy arp entry.
217  * This should call die() because it's called from die().
218  */
219
220 void sys_cleanup(void)
221   {
222     struct ifreq ifr;
223 /*
224  * Take down the device
225  */
226     if (if_is_up)
227       {
228         sifdown(0);
229       }
230 /*
231  * Delete any routes through the device.
232  */
233     if (default_route_gateway != 0)
234       {
235         cifdefaultroute(0, default_route_gateway);
236       }
237
238     if (has_proxy_arp)
239       {
240         cifproxyarp(0, proxy_arp_addr);
241       }
242   }
243
244 /********************************************************************
245  *
246  * sys_close - Clean up in a child process before execing.
247  */
248 void
249 sys_close(void)
250   {
251     close(sock_fd);
252     sock_fd = -1;
253     closelog();
254   }
255
256 /********************************************************************
257  *
258  * note_debug_level - note a change in the debug level.
259  */
260
261 void note_debug_level (void)
262   {
263     if (debug)
264       {
265         SYSDEBUG ((LOG_INFO, "Debug turned ON, Level %d", debug));
266         setlogmask(LOG_UPTO(LOG_DEBUG));
267       }
268     else
269       {
270         setlogmask(LOG_UPTO(LOG_WARNING));
271       }
272   }
273
274 /********************************************************************
275  *
276  * set_kdebugflag - Define the debugging level for the kernel
277  */
278
279 int set_kdebugflag (int requested_level)
280   {
281     if (ioctl(ppp_fd, PPPIOCSDEBUG, &requested_level) < 0)
282       {
283         if ( ! ok_error (errno) )
284           {
285             syslog (LOG_ERR, "ioctl(PPPIOCSDEBUG): %m");
286           }
287         return (0);
288       }
289     SYSDEBUG ((LOG_INFO, "set kernel debugging level to %d",
290                 requested_level));
291     return (1);
292   }
293
294 /********************************************************************
295  *
296  * establish_ppp - Turn the serial port into a ppp interface.
297  */
298
299 void establish_ppp (int tty_fd)
300   {
301     int x;
302 /*
303  * The current PPP device will be the tty file.
304  */
305     set_ppp_fd (tty_fd);
306 /*
307  * Ensure that the tty device is in exclusive mode.
308  */
309     if (ioctl(tty_fd, TIOCEXCL, 0) < 0)
310       {
311         if ( ! ok_error ( errno ))
312           {
313             syslog (LOG_WARNING, "ioctl(TIOCEXCL): %m");
314           }
315       }
316 /*
317  * Demand mode - prime the old ppp device to relinquish the unit.
318  */
319     if (demand && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0)
320       {
321         syslog(LOG_ERR, "ioctl(transfer ppp unit): %m(%d)", errno);
322         die(1);
323       }
324 /*
325  * Set the current tty to the PPP discpline
326  */
327     if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
328       {
329         if ( ! ok_error (errno) )
330           {
331             syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
332             die(1);
333           }
334       }
335 /*
336  * Find out which interface we were given.
337  */
338     if (ioctl(ppp_fd, PPPIOCGUNIT, &x) < 0)
339       { 
340         if ( ! ok_error (errno))
341           {
342             syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m(%d)", errno);
343             die(1);
344           }
345       }
346 /*
347  * Check that we got the same unit again.
348  */
349     if (demand)
350       {
351         if (x != ifunit)
352           {
353             syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
354                    ifunit, x);
355             die(1);
356           }
357       }
358
359     ifunit = x;
360 /*
361  * Enable debug in the driver if requested.
362  */
363     if (!demand)
364       set_kdebugflag (kdebugflag);
365
366     set_flags (get_flags() & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
367                                SC_RCV_EVNP | SC_RCV_ODDP));
368
369     SYSDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
370             driver_version, driver_modification, driver_patch));
371 /*
372  * Fetch the initial file flags and reset blocking mode on the file.
373  */
374     initfdflags = fcntl(ppp_fd, F_GETFL);
375
376     if (initfdflags == -1 ||
377         fcntl(ppp_fd, F_SETFL, initfdflags | O_NONBLOCK) == -1)
378       {
379         if ( ! ok_error (errno))
380           {
381             syslog(LOG_WARNING,
382                    "Couldn't set device to non-blocking mode: %m");
383           }
384       }
385   }
386
387 /********************************************************************
388  *
389  * disestablish_ppp - Restore the serial port to normal operation.
390  * This shouldn't call die() because it's called from die().
391  */
392
393 void disestablish_ppp(int tty_fd)
394   {
395     int x;
396     char *s;
397
398 /*
399  * Attempt to restore the previous tty settings
400  */
401     if (!hungup)
402       {
403 /*
404  * Restore the previous line discipline
405  */
406         if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0)
407           {
408             if ( ! ok_error (errno))
409               {
410                 syslog(LOG_ERR, "ioctl(TIOCSETD, N_TTY): %m");
411               }
412           }
413         
414         if (ioctl(tty_fd, TIOCNXCL, 0) < 0)
415           {
416             if ( ! ok_error (errno))
417               {
418                 syslog (LOG_WARNING, "ioctl(TIOCNXCL): %m(%d)", errno);
419               }
420           }
421
422         /* Reset non-blocking mode on fd. */
423         if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0)
424           {
425             if ( ! ok_error (errno))
426               {
427                 syslog (LOG_WARNING,
428                         "Couldn't restore device fd flags: %m");
429               }
430           }
431       }
432     initfdflags = -1;
433   }
434
435 /********************************************************************
436  *
437  * clean_check - Fetch the flags for the device and generate
438  * appropriate error messages.
439  */
440 void clean_check(void)
441   {
442     int x;
443     char *s;
444
445     if (still_ppp())
446       {
447         if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0)
448           {
449             s = NULL;
450             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP))
451               {
452               case SC_RCV_B7_0:
453               case SC_RCV_B7_0 | SC_RCV_EVNP:
454               case SC_RCV_B7_0 | SC_RCV_ODDP:
455               case SC_RCV_B7_0 | SC_RCV_ODDP | SC_RCV_EVNP:
456                 s = "all had bit 7 set to 1";
457                 break;
458                 
459               case SC_RCV_B7_1:
460               case SC_RCV_B7_1 | SC_RCV_EVNP:
461               case SC_RCV_B7_1 | SC_RCV_ODDP:
462               case SC_RCV_B7_1 | SC_RCV_ODDP | SC_RCV_EVNP:
463                 s = "all had bit 7 set to 0";
464                 break;
465                 
466               case SC_RCV_EVNP:
467                 s = "all had odd parity";
468                 break;
469                 
470               case SC_RCV_ODDP:
471                 s = "all had even parity";
472                 break;
473               }
474             
475             if (s != NULL)
476               {
477                 syslog(LOG_WARNING, "Receive serial link is not"
478                        " 8-bit clean:");
479                 syslog(LOG_WARNING, "Problem: %s", s);
480               }
481           }
482       }
483   }
484         
485
486 /*
487  * List of valid speeds.
488  */
489
490 struct speed {
491     int speed_int, speed_val;
492 } speeds[] = {
493 #ifdef B50
494     { 50, B50 },
495 #endif
496 #ifdef B75
497     { 75, B75 },
498 #endif
499 #ifdef B110
500     { 110, B110 },
501 #endif
502 #ifdef B134
503     { 134, B134 },
504 #endif
505 #ifdef B150
506     { 150, B150 },
507 #endif
508 #ifdef B200
509     { 200, B200 },
510 #endif
511 #ifdef B300
512     { 300, B300 },
513 #endif
514 #ifdef B600
515     { 600, B600 },
516 #endif
517 #ifdef B1200
518     { 1200, B1200 },
519 #endif
520 #ifdef B1800
521     { 1800, B1800 },
522 #endif
523 #ifdef B2000
524     { 2000, B2000 },
525 #endif
526 #ifdef B2400
527     { 2400, B2400 },
528 #endif
529 #ifdef B3600
530     { 3600, B3600 },
531 #endif
532 #ifdef B4800
533     { 4800, B4800 },
534 #endif
535 #ifdef B7200
536     { 7200, B7200 },
537 #endif
538 #ifdef B9600
539     { 9600, B9600 },
540 #endif
541 #ifdef B19200
542     { 19200, B19200 },
543 #endif
544 #ifdef B38400
545     { 38400, B38400 },
546 #endif
547 #ifdef B57600
548     { 57600, B57600 },
549 #endif
550 #ifdef B115200
551     { 115200, B115200 },
552 #endif
553 #ifdef EXTA
554     { 19200, EXTA },
555 #endif
556 #ifdef EXTB
557     { 38400, EXTB },
558 #endif
559     { 0, 0 }
560 };
561
562 /********************************************************************
563  *
564  * Translate from bits/second to a speed_t.
565  */
566
567 static int translate_speed (int bps)
568   {
569     struct speed *speedp;
570
571     if (bps != 0)
572       {
573         for (speedp = speeds; speedp->speed_int; speedp++)
574           {
575             if (bps == speedp->speed_int)
576               {
577                 return speedp->speed_val;
578               }
579           }
580         syslog(LOG_WARNING, "speed %d not supported", bps);
581       }
582     return 0;
583   }
584
585 /********************************************************************
586  *
587  * Translate from a speed_t to bits/second.
588  */
589
590 static int baud_rate_of (int speed)
591   {
592     struct speed *speedp;
593     
594     if (speed != 0)
595       {
596         for (speedp = speeds; speedp->speed_int; speedp++)
597           {
598             if (speed == speedp->speed_val)
599               {
600                 return speedp->speed_int;
601               }
602           }
603       }
604     return 0;
605   }
606
607 /********************************************************************
608  *
609  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
610  * at the requested speed, etc.  If `local' is true, set CLOCAL
611  * regardless of whether the modem option was specified.
612  */
613
614 void set_up_tty (int tty_fd, int local)
615   {
616     int speed, x;
617     struct termios tios;
618     
619     if (tcgetattr(tty_fd, &tios) < 0)
620       {
621         syslog(LOG_ERR, "tcgetattr: %m(%d)", errno);
622         die(1);
623       }
624     
625     if (!restore_term)
626       {
627         inittermios = tios;
628       }
629     
630     tios.c_cflag     &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
631     tios.c_cflag     |= CS8 | CREAD | HUPCL;
632
633     tios.c_iflag      = IGNBRK | IGNPAR;
634     tios.c_oflag      = 0;
635     tios.c_lflag      = 0;
636     tios.c_cc[VMIN]   = 1;
637     tios.c_cc[VTIME]  = 0;
638     
639     if (local || !modem)
640       {
641         tios.c_cflag ^= (CLOCAL | HUPCL);
642       }
643
644     switch (crtscts)
645       {
646     case 1:
647         tios.c_cflag |= CRTSCTS;
648         break;
649
650     case -2:
651         tios.c_iflag     |= IXON | IXOFF;
652         tios.c_cc[VSTOP]  = 0x13;       /* DC3 = XOFF = ^S */
653         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
654         break;
655
656     case -1:
657         tios.c_cflag &= ~CRTSCTS;
658         break;
659
660     default:
661         break;
662       }
663     
664     speed = translate_speed(inspeed);
665     if (speed)
666       {
667         cfsetospeed (&tios, speed);
668         cfsetispeed (&tios, speed);
669       }
670 /*
671  * We can't proceed if the serial port speed is B0,
672  * since that implies that the serial port is disabled.
673  */
674     else
675       {
676         speed = cfgetospeed(&tios);
677         if (speed == B0)
678           {
679             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
680                    devnam);
681             die (1);
682           }
683       }
684
685     if (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0)
686       {
687         syslog(LOG_ERR, "tcsetattr: %m");
688         die(1);
689       }
690     
691     baud_rate    = baud_rate_of(speed);
692     restore_term = TRUE;
693   }
694
695 /********************************************************************
696  *
697  * setdtr - control the DTR line on the serial port.
698  * This is called from die(), so it shouldn't call die().
699  */
700
701 void setdtr (int tty_fd, int on)
702   {
703     int modembits = TIOCM_DTR;
704
705     ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
706   }
707
708 /********************************************************************
709  *
710  * restore_tty - restore the terminal to the saved settings.
711  */
712
713 void restore_tty (int tty_fd)
714   {
715     if (restore_term)
716       {
717         restore_term = 0;
718 /*
719  * Turn off echoing, because otherwise we can get into
720  * a loop with the tty and the modem echoing to each other.
721  * We presume we are the sole user of this tty device, so
722  * when we close it, it will revert to its defaults anyway.
723  */
724         if (!default_device)
725           {
726             inittermios.c_lflag &= ~(ECHO | ECHONL);
727           }
728         
729         if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0)
730           {
731             if (! ok_error (errno))
732               {
733                 syslog(LOG_WARNING, "tcsetattr: %m");
734               }
735           }
736       }
737   }
738
739 /********************************************************************
740  *
741  * output - Output PPP packet.
742  */
743
744 void output (int unit, unsigned char *p, int len)
745   {
746     if (debug)
747       {
748         log_packet(p, len, "sent ");
749       }
750     
751     if (write(ppp_fd, p, len) < 0)
752       {
753         if (errno == EWOULDBLOCK || errno == ENOBUFS
754             || errno == ENXIO || errno == EIO)
755           {
756             syslog(LOG_WARNING, "write: warning: %m(%d)", errno);
757           } 
758         else
759           {
760             syslog(LOG_ERR, "write: %m(%d)", errno);
761             die(1);
762           }
763       }
764   }
765
766 /********************************************************************
767  *
768  * wait_input - wait until there is data available on ppp_fd,
769  * for the length of time specified by *timo (indefinite
770  * if timo is NULL).
771  */
772
773 void wait_input (struct timeval *timo)
774   {
775     fd_set ready;
776     int n;
777     
778     FD_ZERO(&ready);
779     FD_SET(ppp_fd, &ready);
780
781     n = select(ppp_fd + 1, &ready, NULL, &ready, timo);
782     if (n < 0 && errno != EINTR)
783       {
784         syslog(LOG_ERR, "select: %m(%d)", errno);
785         die(1);
786       }
787   }
788
789 /********************************************************************
790  *
791  * wait_loop_output - wait until there is data available on the
792  * loopback, for the length of time specified by *timo (indefinite
793  * if timo is NULL).
794  */
795 void wait_loop_output(timo)
796     struct timeval *timo;
797   {
798     fd_set ready;
799     int n;
800
801     FD_ZERO(&ready);
802     FD_SET(master_fd, &ready);
803     n = select(master_fd + 1, &ready, NULL, &ready, timo);
804     if (n < 0 && errno != EINTR)
805       {
806         syslog(LOG_ERR, "select: %m(%d)", errno);
807         die(1);
808       }
809   }
810
811 /********************************************************************
812  *
813  * wait_time - wait for a given length of time or until a
814  * signal is received.
815  */
816
817 void wait_time(timo)
818     struct timeval *timo;
819 {
820     int n;
821
822     n = select(0, NULL, NULL, NULL, timo);
823     if (n < 0 && errno != EINTR) {
824         syslog(LOG_ERR, "select: %m(%d)", errno);
825         die(1);
826     }
827 }
828
829 /********************************************************************
830  *
831  * read_packet - get a PPP packet from the serial device.
832  */
833
834 int read_packet (unsigned char *buf)
835   {
836     int len;
837   
838     len = read(ppp_fd, buf, PPP_MTU + PPP_HDRLEN);
839     if (len < 0)
840       {
841         if (errno == EWOULDBLOCK)
842           {
843             return -1;
844           }
845         syslog(LOG_ERR, "read: %m(%d)", errno);
846         die(1);
847       }
848     return len;
849   }
850
851 /********************************************************************
852  *
853  * get_loop_output - get outgoing packets from the ppp device,
854  * and detect when we want to bring the real link up.
855  * Return value is 1 if we need to bring up the link, 0 otherwise.
856  */
857 int
858 get_loop_output(void)
859   {
860     int rv = 0;
861     int n  = read(master_fd, inbuf, sizeof(inbuf));
862
863     while (n > 0)
864       {
865         if (loop_chars(inbuf, n))
866           {
867             rv = 1;
868           }
869         n = read(master_fd, inbuf, sizeof(inbuf));
870       }
871
872     if (n == 0)
873       {
874         syslog(LOG_ERR, "eof on loopback");
875         die(1);
876       }
877
878     if (errno != EWOULDBLOCK)
879       {
880         syslog(LOG_ERR, "read from loopback: %m(%d)", errno);
881         die(1);
882       }
883     
884     return rv;
885   }
886
887 /********************************************************************
888  *
889  * ppp_send_config - configure the transmit characteristics of
890  * the ppp interface.
891  */
892
893 void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
894   {
895     u_int x;
896     struct ifreq ifr;
897   
898     SYSDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
899 /*
900  * Ensure that the link is still up.
901  */
902     if (still_ppp())
903       {
904 /*
905  * Set the MTU and other parameters for the ppp device
906  */
907         memset (&ifr, '\0', sizeof (ifr));
908         strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
909         ifr.ifr_mtu = mtu;
910         
911         if (ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
912           {
913             syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m(%d)", errno);
914             quit();
915           }
916         
917         SYSDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
918         if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
919           {
920             syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m(%d)", errno);
921             quit();
922           }
923     
924         x = get_flags();
925         x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
926         x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
927         set_flags(x);
928       }
929   }
930
931 /********************************************************************
932  *
933  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
934  */
935
936 void ppp_set_xaccm (int unit, ext_accm accm)
937   {
938     SYSDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
939                 accm[0], accm[1], accm[2], accm[3]));
940
941     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
942       {
943         if ( ! ok_error (errno))
944           {
945             syslog(LOG_WARNING, "ioctl(set extended ACCM): %m(%d)", errno);
946           }
947       }
948   }
949
950 /********************************************************************
951  *
952  * ppp_recv_config - configure the receive-side characteristics of
953  * the ppp interface.
954  */
955
956 void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
957   {
958     u_int x;
959
960     SYSDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
961 /*
962  * If we were called because the link has gone down then there is nothing
963  * which may be done. Just return without incident.
964  */
965     if (!still_ppp())
966       {
967         return;
968       }
969 /*
970  * Set the receiver parameters
971  */
972     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
973       {
974         if ( ! ok_error (errno))
975           {
976             syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m(%d)", errno);
977           }
978       }
979
980     SYSDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
981     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
982       {
983         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m(%d)", errno);
984         quit();
985       }
986
987     x = get_flags();
988     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
989     set_flags (x);
990   }
991
992 /********************************************************************
993  *
994  * ccp_test - ask kernel whether a given compression method
995  * is acceptable for use.
996  */
997
998 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
999   {
1000     struct ppp_option_data data;
1001
1002     memset (&data, '\0', sizeof (data));
1003     data.ptr      = opt_ptr;
1004     data.length   = opt_len;
1005     data.transmit = for_transmit;
1006
1007     if (ioctl(ppp_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1008       {
1009         return 1;
1010       }
1011
1012     return (errno == ENOBUFS)? 0: -1;
1013   }
1014
1015 /********************************************************************
1016  *
1017  * ccp_flags_set - inform kernel about the current state of CCP.
1018  */
1019
1020 void ccp_flags_set (int unit, int isopen, int isup)
1021   {
1022     if (still_ppp())
1023       {
1024         int x = get_flags();
1025         x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
1026         x = isup?   x | SC_CCP_UP   : x &~ SC_CCP_UP;
1027         set_flags (x);
1028       }
1029   }
1030
1031 /********************************************************************
1032  *
1033  * get_idle_time - return how long the link has been idle.
1034  */
1035 int
1036 get_idle_time(u, ip)
1037     int u;
1038     struct ppp_idle *ip;
1039 {
1040     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
1041
1042
1043 /********************************************************************
1044  *
1045  * ccp_fatal_error - returns 1 if decompression was disabled as a
1046  * result of an error detected after decompression of a packet,
1047  * 0 otherwise.  This is necessary because of patent nonsense.
1048  */
1049
1050 int ccp_fatal_error (int unit)
1051   {
1052     int x = get_flags();
1053
1054     return x & SC_DC_FERROR;
1055   }
1056
1057 /*
1058  * path_to_route - determine the path to the proc file system data
1059  */
1060
1061 FILE *route_fd = (FILE *) 0;
1062 static char route_buffer [512];
1063
1064 static char *path_to_route (void);
1065 static int open_route_table (void);
1066 static void close_route_table (void);
1067 static int read_route_table (struct rtentry *rt);
1068
1069 /********************************************************************
1070  *
1071  * path_to_procfs - find the path to the proc file system mount point
1072  */
1073
1074 static int path_to_procfs (void)
1075   {
1076     struct mntent *mntent;
1077     FILE *fp;
1078
1079     fp = fopen (MOUNTED, "r");
1080     if (fp != 0)
1081       {
1082         mntent = getmntent (fp);
1083         while (mntent != (struct mntent *) 0)
1084           {
1085             if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) != 0)
1086               {
1087                 if (strcmp (mntent->mnt_type, "proc") == 0)
1088                   {
1089                     strncpy (route_buffer, mntent->mnt_dir,
1090                              sizeof (route_buffer)-10);
1091                     route_buffer [sizeof (route_buffer)-10] = '\0';
1092                     fclose (fp);
1093                     return 1;
1094                   }
1095               }
1096             mntent = getmntent (fp);
1097           }
1098         fclose (fp);
1099       }
1100     return 0;
1101   }
1102
1103 /********************************************************************
1104  *
1105  * path_to_route - find the path to the route tables in the proc file system
1106  */
1107
1108 static char *path_to_route (void)
1109   {
1110     if (! path_to_procfs())
1111       {
1112         syslog (LOG_ERR, "proc file system not mounted");
1113         return 0;
1114       }
1115     strcat (route_buffer, "/net/route");
1116     return (route_buffer);
1117   }
1118
1119 /********************************************************************
1120  *
1121  * close_route_table - close the interface to the route table
1122  */
1123
1124 static void close_route_table (void)
1125   {
1126     if (route_fd != (FILE *) 0)
1127       {
1128         fclose (route_fd);
1129         route_fd = (FILE *) 0;
1130       }
1131   }
1132
1133 /********************************************************************
1134  *
1135  * open_route_table - open the interface to the route table
1136  */
1137
1138 static int open_route_table (void)
1139   {
1140     char *path;
1141
1142     close_route_table();
1143
1144     path = path_to_route();
1145     if (path == NULL)
1146       {
1147         return 0;
1148       }
1149
1150     route_fd = fopen (path, "r");
1151     if (route_fd == (FILE *) 0)
1152       {
1153         syslog (LOG_ERR, "can not open %s: %m(%d)", path, errno);
1154         return 0;
1155       }
1156     return 1;
1157   }
1158
1159 /********************************************************************
1160  *
1161  * read_route_table - read the next entry from the route table
1162  */
1163
1164 static int read_route_table (struct rtentry *rt)
1165   {
1166     static char delims[] = " \t\n";
1167     char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
1168         
1169     memset (rt, '\0', sizeof (struct rtentry));
1170
1171     for (;;)
1172       {
1173         if (fgets (route_buffer, sizeof (route_buffer), route_fd) ==
1174             (char *) 0)
1175           {
1176             return 0;
1177           }
1178
1179         dev_ptr  = strtok (route_buffer, delims); /* interface name */
1180         dst_ptr  = strtok (NULL,         delims); /* destination address */
1181         gw_ptr   = strtok (NULL,         delims); /* gateway */
1182         flag_ptr = strtok (NULL,         delims); /* flags */
1183     
1184         if (flag_ptr == (char *) 0) /* assume that we failed, somewhere. */
1185           {
1186             return 0;
1187           }
1188         
1189         /* Discard that stupid header line which should never
1190          * have been there in the first place !! */
1191         if (isxdigit (*dst_ptr) && isxdigit (*gw_ptr) && isxdigit (*flag_ptr))
1192           {
1193             break;
1194           }
1195       }
1196
1197     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
1198       strtoul (dst_ptr, NULL, 16);
1199
1200     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
1201       strtoul (gw_ptr, NULL, 16);
1202
1203     rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
1204     rt->rt_dev   = dev_ptr;
1205
1206     return 1;
1207   }
1208
1209 /********************************************************************
1210  *
1211  * defaultroute_exists - determine if there is a default route
1212  */
1213
1214 static int defaultroute_exists (struct rtentry *rt)
1215   {
1216     int    result = 0;
1217
1218     if (!open_route_table())
1219       {
1220         return 0;
1221       }
1222
1223     while (read_route_table(rt) != 0)
1224       {
1225         if ((rt->rt_flags & RTF_UP) == 0)
1226           {
1227             continue;
1228           }
1229
1230         if (((struct sockaddr_in *) (&rt->rt_dst))->sin_addr.s_addr == 0L)
1231           {
1232             result = 1;
1233             break;
1234           }
1235       }
1236
1237     close_route_table();
1238     return result;
1239   }
1240
1241 /********************************************************************
1242  *
1243  * sifdefaultroute - assign a default route through the address given.
1244  */
1245
1246 int sifdefaultroute (int unit, u_int32_t gateway)
1247   {
1248     struct rtentry rt;
1249
1250     if (defaultroute_exists(&rt))
1251       {
1252         u_int32_t old_gateway = ((struct sockaddr_in *) (&rt.rt_gateway))->
1253                                 sin_addr.s_addr;
1254
1255         if (old_gateway != gateway)
1256           {
1257             syslog (LOG_ERR,
1258                     "ppp not replacing existing default route to %s[%s]",
1259                     rt.rt_dev,
1260                     inet_ntoa (old_gateway));
1261           }
1262         return 0;
1263       }
1264
1265     memset (&rt, '\0', sizeof (rt));
1266     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1267     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1268     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1269     
1270     rt.rt_flags = RTF_UP | RTF_GATEWAY;
1271     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0)
1272       {
1273         if ( ! ok_error ( errno ))
1274           {
1275             syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m(%d)", errno);
1276           }
1277         return 0;
1278       }
1279
1280     default_route_gateway = gateway;
1281     return 1;
1282   }
1283
1284 /********************************************************************
1285  *
1286  * cifdefaultroute - delete a default route through the address given.
1287  */
1288
1289 int cifdefaultroute (int unit, u_int32_t gateway)
1290   {
1291     struct rtentry rt;
1292
1293     default_route_gateway = 0;
1294
1295     memset (&rt, '\0', sizeof (rt));
1296     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1297     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1298     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1299     
1300     rt.rt_flags = RTF_UP | RTF_GATEWAY;
1301     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH)
1302       {
1303         if (still_ppp())
1304           {
1305             if ( ! ok_error ( errno ))
1306               {
1307                 syslog (LOG_ERR,
1308                         "default route ioctl(SIOCDELRT): %m(%d)", errno);
1309               }
1310             return 0;
1311           }
1312       }
1313
1314     return 1;
1315   }
1316
1317 /********************************************************************
1318  *
1319  * sifproxyarp - Make a proxy ARP entry for the peer.
1320  */
1321
1322 int sifproxyarp (int unit, u_int32_t his_adr)
1323   {
1324     struct arpreq arpreq;
1325
1326     if (has_proxy_arp == 0)
1327       {
1328         memset (&arpreq, '\0', sizeof(arpreq));
1329     
1330         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1331         ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1332         arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1333 /*
1334  * Get the hardware address of an interface on the same subnet
1335  * as our local address.
1336  */
1337         if (!get_ether_addr(his_adr, &arpreq.arp_ha, arpreq.arp_dev))
1338           {
1339             syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1340             return 0;
1341           }
1342         
1343         if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0)
1344           {
1345             if ( ! ok_error ( errno ))
1346               {
1347                 syslog(LOG_ERR, "ioctl(SIOCSARP): %m(%d)", errno);
1348               }
1349             return 0;
1350           }
1351       }
1352
1353     proxy_arp_addr = his_adr;
1354     has_proxy_arp = 1;
1355     return 1;
1356   }
1357
1358 /********************************************************************
1359  *
1360  * cifproxyarp - Delete the proxy ARP entry for the peer.
1361  */
1362
1363 int cifproxyarp (int unit, u_int32_t his_adr)
1364   {
1365     struct arpreq arpreq;
1366
1367     if (has_proxy_arp == 1)
1368       {
1369         memset (&arpreq, '\0', sizeof(arpreq));
1370         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1371     
1372         ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1373         if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0)
1374           {
1375             if ( ! ok_error ( errno ))
1376               {
1377                 syslog(LOG_WARNING, "ioctl(SIOCDARP): %m(%d)", errno);
1378               }
1379             return 0;
1380           }
1381       }
1382     has_proxy_arp = 0;
1383     return 1;
1384   }
1385      
1386 /********************************************************************
1387  *
1388  * get_ether_addr - get the hardware address of an interface on the
1389  * the same subnet as ipaddr.
1390  */
1391
1392 static int get_ether_addr (u_int32_t ipaddr,
1393                            struct sockaddr *hwaddr,
1394                            char *name)
1395   {
1396     struct ifreq *ifr, *ifend, *ifp;
1397     int i;
1398     u_int32_t ina, mask;
1399     struct sockaddr_dl *dla;
1400     struct ifreq ifreq;
1401     struct ifconf ifc;
1402     struct ifreq ifs[MAX_IFS];
1403     
1404     ifc.ifc_len = sizeof(ifs);
1405     ifc.ifc_req = ifs;
1406     if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0)
1407       {
1408         if ( ! ok_error ( errno ))
1409           {
1410             syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m(%d)", errno);
1411           }
1412         return 0;
1413       }
1414
1415     SYSDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
1416                 ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
1417 /*
1418  * Scan through looking for an interface with an Internet
1419  * address on the same subnet as `ipaddr'.
1420  */
1421     ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1422     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1423       {
1424         if (ifr->ifr_addr.sa_family == AF_INET)
1425           {
1426             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1427             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1428             SYSDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
1429                         ifreq.ifr_name));
1430 /*
1431  * Check that the interface is up, and not point-to-point
1432  * nor loopback.
1433  */
1434             if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1435               {
1436                 continue;
1437               }
1438
1439             if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1440               {
1441                 continue;
1442               }
1443 /*
1444  * Get its netmask and check that it's on the right subnet.
1445  */
1446             if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1447               {
1448                 continue;
1449               }
1450
1451             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1452             SYSDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
1453                         ip_ntoa(ina), ntohl(mask)));
1454
1455             if (((ipaddr ^ ina) & mask) != 0)
1456               {
1457                 continue;
1458               }
1459             break;
1460           }
1461       }
1462     
1463     if (ifr >= ifend)
1464       {
1465         return 0;
1466       }
1467
1468     memcpy (name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
1469     syslog(LOG_INFO, "found interface %s for proxy arp", name);
1470 /*
1471  * Now get the hardware address.
1472  */
1473     memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
1474     if (ioctl (sock_fd, SIOCGIFHWADDR, &ifreq) < 0)
1475       {
1476         syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m(%d)", ifreq.ifr_name, errno);
1477         return 0;
1478       }
1479
1480     memcpy (hwaddr,
1481             &ifreq.ifr_hwaddr,
1482             sizeof (struct sockaddr));
1483
1484     SYSDEBUG ((LOG_DEBUG,
1485            "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1486                 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1487                 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1488                 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1489                 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1490                 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1491                 (int) ((unsigned char *) &hwaddr->sa_data)[5],
1492                 (int) ((unsigned char *) &hwaddr->sa_data)[6],
1493                 (int) ((unsigned char *) &hwaddr->sa_data)[7]));
1494     return 1;
1495   }
1496
1497 /********************************************************************
1498  *
1499  * Return user specified netmask, modified by any mask we might determine
1500  * for address `addr' (in network byte order).
1501  * Here we scan through the system's list of interfaces, looking for
1502  * any non-point-to-point interfaces which might appear to be on the same
1503  * network as `addr'.  If we find any, we OR in their netmask to the
1504  * user-specified netmask.
1505  */
1506
1507 u_int32_t GetMask (u_int32_t addr)
1508   {
1509     u_int32_t mask, nmask, ina;
1510     struct ifreq *ifr, *ifend, ifreq;
1511     struct ifconf ifc;
1512     struct ifreq ifs[MAX_IFS];
1513
1514     addr = ntohl(addr);
1515     
1516     if (IN_CLASSA(addr))        /* determine network mask for address class */
1517       {
1518         nmask = IN_CLASSA_NET;
1519       }
1520     else
1521       {
1522         if (IN_CLASSB(addr))
1523           {
1524             nmask = IN_CLASSB_NET;
1525           }
1526         else
1527           {
1528             nmask = IN_CLASSC_NET;
1529           }
1530       }
1531     
1532     /* class D nets are disallowed by bad_ip_adrs */
1533     mask = netmask | htonl(nmask);
1534 /*
1535  * Scan through the system's network interfaces.
1536  */
1537     ifc.ifc_len = sizeof(ifs);
1538     ifc.ifc_req = ifs;
1539     if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0)
1540       {
1541         if ( ! ok_error ( errno ))
1542           {
1543             syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m(%d)", errno);
1544           }
1545         return mask;
1546       }
1547     
1548     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1549     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1550       {
1551 /*
1552  * Check the interface's internet address.
1553  */
1554         if (ifr->ifr_addr.sa_family != AF_INET)
1555           {
1556             continue;
1557           }
1558         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1559         if (((ntohl(ina) ^ addr) & nmask) != 0)
1560           {
1561             continue;
1562           }
1563 /*
1564  * Check that the interface is up, and not point-to-point nor loopback.
1565  */
1566         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1567         if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1568           {
1569             continue;
1570           }
1571         
1572         if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1573           {
1574             continue;
1575           }
1576 /*
1577  * Get its netmask and OR it into our mask.
1578  */
1579         if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1580           {
1581             continue;
1582           }
1583         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1584         break;
1585       }
1586     return mask;
1587   }
1588
1589 /********************************************************************
1590  *
1591  * Internal routine to decode the version.modification.patch level
1592  */
1593
1594 static void decode_version (char *buf, int *version,
1595                             int *modification, int *patch)
1596   {
1597     *version      = (int) strtoul (buf, &buf, 10);
1598     *modification = 0;
1599     *patch        = 0;
1600     
1601     if (*buf == '.')
1602       {
1603         ++buf;
1604         *modification = (int) strtoul (buf, &buf, 10);
1605         if (*buf == '.')
1606           {
1607             ++buf;
1608             *patch = (int) strtoul (buf, &buf, 10);
1609           }
1610       }
1611     
1612     if (*buf != '\0')
1613       {
1614         *version      =
1615         *modification =
1616         *patch        = 0;
1617       }
1618   }
1619
1620 /********************************************************************
1621  *
1622  * Procedure to determine if the PPP line dicipline is registered.
1623  */
1624
1625 int
1626 ppp_registered(void)
1627   {
1628     int local_fd;
1629     int init_disc = -1;
1630     int initfdflags;
1631
1632     local_fd = open(devnam, O_NONBLOCK | O_RDWR, 0);
1633     if (local_fd < 0)
1634       {
1635         syslog(LOG_ERR, "Failed to open %s: %m(%d)", devnam, errno);
1636         return 0;
1637       }
1638
1639     initfdflags = fcntl(local_fd, F_GETFL);
1640     if (initfdflags == -1)
1641       {
1642         syslog(LOG_ERR, "Couldn't get device fd flags: %m(%d)", errno);
1643         close (local_fd);
1644         return 0;
1645       }
1646
1647     initfdflags &= ~O_NONBLOCK;
1648     fcntl(local_fd, F_SETFL, initfdflags);
1649 /*
1650  * Read the initial line dicipline and try to put the device into the
1651  * PPP dicipline.
1652  */
1653     if (ioctl(local_fd, TIOCGETD, &init_disc) < 0)
1654       {
1655         syslog(LOG_ERR, "ioctl(TIOCGETD): %m(%d)", errno);
1656         close (local_fd);
1657         return 0;
1658       }
1659     
1660     if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0)
1661       {
1662         syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
1663         close (local_fd);
1664         return 0;
1665       }
1666     
1667     if (ioctl(local_fd, TIOCSETD, &init_disc) < 0)
1668       {
1669         syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
1670         close (local_fd);
1671         return 0;
1672       }
1673     
1674     close (local_fd);
1675     return 1;
1676   }
1677
1678 /********************************************************************
1679  *
1680  * ppp_available - check whether the system has any ppp interfaces
1681  * (in fact we check whether we can do an ioctl on ppp0).
1682  */
1683
1684 int ppp_available(void)
1685   {
1686     int s, ok;
1687     struct ifreq ifr;
1688     int    size;
1689     int    my_version, my_modification, my_patch;
1690     extern char *no_ppp_msg;
1691 /*
1692  * Open a socket for doing the ioctl operations.
1693  */    
1694     s = socket(AF_INET, SOCK_DGRAM, 0);
1695     if (s < 0)
1696       {
1697         return 0;
1698       }
1699     
1700     strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1701     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1702 /*
1703  * If the device did not exist then attempt to create one by putting the
1704  * current tty into the PPP discipline. If this works then obtain the
1705  * flags for the device again.
1706  */
1707     if (!ok)
1708       {
1709         if (ppp_registered())
1710           {
1711             strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1712             ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1713           }
1714       }
1715 /*
1716  * Ensure that the hardware address is for PPP and not something else
1717  */
1718     if (ok)
1719       {
1720         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
1721       }
1722
1723     if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
1724       {
1725         ok = 0;
1726       }
1727
1728     if (!ok)
1729       {
1730         no_ppp_msg = 
1731           "This system lacks kernel support for PPP. To include PPP support\n"
1732           "in the kernel, please follow the steps detailed in the "
1733           "README.linux\nfile in the ppp-2.3 distribution.\n";
1734       }
1735 /*
1736  *  This is the PPP device. Validate the version of the driver at this
1737  *  point to ensure that this program will work with the driver.
1738  */
1739     else
1740       {
1741         char   abBuffer [1024];
1742
1743         ifr.ifr_data = abBuffer;
1744         size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
1745         ok   = size >= 0;
1746
1747         if (ok)
1748           {
1749             decode_version (abBuffer,
1750                             &driver_version,
1751                             &driver_modification,
1752                             &driver_patch);
1753           }
1754     
1755         if (!ok)
1756           {
1757             driver_version      =
1758             driver_modification =
1759             driver_patch        = 0;
1760           }
1761 /*
1762  * Validate the version of the driver against the version that we used.
1763  */
1764         decode_version (PPP_VERSION,
1765                         &my_version,
1766                         &my_modification,
1767                         &my_patch);
1768
1769         /* The version numbers must match */
1770         if (driver_version != my_version)
1771           {
1772             ok = 0;
1773           }
1774       
1775         /* The modification levels must be legal */
1776         if (driver_modification < my_modification)
1777           {
1778             ok = 0;
1779           }
1780
1781         close (s);
1782         if (!ok)
1783           {
1784             sprintf (route_buffer,
1785                      "Sorry - PPP driver version %d.%d.%d is out of date\n",
1786                      driver_version, driver_modification, driver_patch);
1787
1788             no_ppp_msg = route_buffer;
1789           }
1790       }
1791     return ok;
1792   }
1793
1794 /********************************************************************
1795  *
1796  * Update the wtmp file with the appropriate user name and tty device.
1797  */
1798
1799 int logwtmp (char *line, char *name, char *host)
1800   {
1801     int    wtmp;
1802     struct utmp ut, *utp;
1803     pid_t  mypid = getpid();
1804 /*
1805  * Update the signon database for users.
1806  * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
1807  */
1808     utmpname(_PATH_UTMP);
1809     setutent();
1810     while ((utp = getutent()) && (utp->ut_pid != mypid))
1811         /* nothing */;
1812
1813     /* Is this call really necessary? There is another one after the 'put' */
1814     endutent();
1815     
1816     if (utp)
1817       {
1818         memcpy(&ut, utp, sizeof(ut));
1819       }
1820     else
1821       {
1822         /* some gettys/telnetds don't initialize utmp... */
1823         memset(&ut, 0, sizeof(ut));
1824       }
1825
1826     if (ut.ut_id[0] == 0)
1827       {
1828         strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
1829       }
1830         
1831     strncpy(ut.ut_user, name, sizeof(ut.ut_user));
1832     strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1833
1834     time(&ut.ut_time);
1835
1836     ut.ut_type = USER_PROCESS;
1837     ut.ut_pid  = mypid;
1838
1839     /* Insert the host name if one is supplied */
1840     if (*host)
1841       {
1842         strncpy (ut.ut_host, host, sizeof(ut.ut_host));
1843       }
1844
1845     /* Insert the IP address of the remote system if IP is enabled */
1846     if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
1847       {
1848         memcpy  (&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
1849                  sizeof(ut.ut_addr));
1850       }
1851         
1852     /* CL: Makes sure that the logout works */
1853     if (*host == 0 && *name==0)
1854       {
1855         ut.ut_host[0]=0;
1856       }
1857
1858     pututline(&ut);
1859     endutent();
1860 /*
1861  * Update the wtmp file.
1862  */
1863     wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
1864     if (wtmp >= 0)
1865       {
1866         flock(wtmp, LOCK_EX);
1867
1868         /* we really should check for error on the write for a full disk! */
1869         write (wtmp, (char *)&ut, sizeof(ut));
1870         close (wtmp);
1871
1872         flock(wtmp, LOCK_UN);
1873       }
1874   }
1875
1876 /********************************************************************
1877  * Code for locking/unlocking the serial device.
1878  * This code is derived from chat.c.
1879  */
1880
1881 /*
1882  * lock - create a lock file for the named device
1883  */
1884
1885 int lock (char *dev)
1886   {
1887     char hdb_lock_buffer[12];
1888     int fd, n;
1889     int pid = getpid();
1890     char *p;
1891
1892     p = strrchr(dev, '/');
1893     if (p != NULL)
1894       {
1895         dev = ++p;
1896       }
1897
1898     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1899     if (lock_file == NULL)
1900       {
1901         novm("lock file name");
1902       }
1903
1904     strcpy (lock_file, LOCK_PREFIX);
1905     strcat (lock_file, dev);
1906 /*
1907  * Attempt to create the lock file at this point.
1908  */
1909     while (1)
1910       {
1911         fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644);
1912         if (fd >= 0)
1913           {
1914             pid = getpid();
1915 #ifndef PID_BINARY
1916             sprintf (hdb_lock_buffer, "%010d\n", pid);
1917             write (fd, hdb_lock_buffer, 11);
1918 #else
1919             write(fd, &pid, sizeof (pid));
1920 #endif
1921             close(fd);
1922             return 0;
1923           }
1924 /*
1925  * If the file exists then check to see if the pid is stale
1926  */
1927         if (errno == EEXIST)
1928           {
1929             fd = open(lock_file, O_RDONLY, 0);
1930             if (fd < 0)
1931               {
1932                 if (errno == ENOENT) /* This is just a timing problem. */
1933                   {
1934                     continue;
1935                   }
1936                 break;
1937               }
1938
1939             /* Read the lock file to find out who has the device locked */
1940             n = read (fd, hdb_lock_buffer, 11);
1941             close (fd);
1942             if (n < 0)
1943               {
1944                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1945                 break;
1946               }
1947
1948             /* See the process still exists. */
1949             if (n > 0)
1950               {
1951 #ifndef PID_BINARY
1952                 hdb_lock_buffer[n] = '\0';
1953                 sscanf (hdb_lock_buffer, " %d", &pid);
1954 #else
1955                 pid = ((int *) hdb_lock_buffer)[0];
1956 #endif
1957                 if (pid == 0 || (kill(pid, 0) == -1 && errno == ESRCH))
1958                   {
1959                     n = 0;
1960                   }
1961               }
1962
1963             /* If the process does not exist then try to remove the lock */
1964             if (n == 0 && unlink (lock_file) == 0)
1965               {
1966                 syslog (LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1967                         dev, pid);
1968                 continue;
1969               }
1970
1971             syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, pid);
1972             break;
1973           }
1974
1975         syslog(LOG_ERR, "Can't create lock file %s: %m(%d)", lock_file, errno);
1976         break;
1977       }
1978
1979     free(lock_file);
1980     lock_file = NULL;
1981     return -1;
1982 }
1983
1984
1985 /********************************************************************
1986  *
1987  * unlock - remove our lockfile
1988  */
1989
1990 void unlock(void)
1991   {
1992     if (lock_file)
1993       {
1994         unlink(lock_file);
1995         free(lock_file);
1996         lock_file = NULL;
1997       }
1998   }
1999
2000 /********************************************************************
2001  *
2002  * sifvjcomp - config tcp header compression
2003  */
2004
2005 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
2006   {
2007     u_int x = get_flags();
2008
2009     if (vjcomp)
2010       {
2011         if (ioctl (ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
2012           {
2013             if (! ok_error (errno))
2014               {
2015                 syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m(%d)", errno);
2016               }
2017             vjcomp = 0;
2018           }
2019       }
2020
2021     x = vjcomp  ? x | SC_COMP_TCP     : x &~ SC_COMP_TCP;
2022     x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
2023     set_flags (x);
2024
2025     return 1;
2026   }
2027
2028 /********************************************************************
2029  *
2030  * sifup - Config the interface up and enable IP packets to pass.
2031  */
2032
2033 int sifup (int u)
2034   {
2035     struct ifreq ifr;
2036
2037     memset (&ifr, '\0', sizeof (ifr));
2038     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2039     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
2040       {
2041         if (! ok_error (errno))
2042           {
2043             syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m(%d)", errno);
2044           }
2045         return 0;
2046       }
2047
2048     ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
2049     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
2050       {
2051         if (! ok_error (errno))
2052           {
2053             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m(%d)", errno);
2054           }
2055         return 0;
2056       }
2057     if_is_up = 1;
2058     return 1;
2059   }
2060
2061 /********************************************************************
2062  *
2063  * sifdown - Config the interface down and disable IP.
2064  */
2065
2066 int sifdown (int u)
2067   {
2068     struct ifreq ifr;
2069
2070     if_is_up = 0;
2071
2072     memset (&ifr, '\0', sizeof (ifr));
2073     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2074     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
2075       {
2076         if (! ok_error (errno))
2077           {
2078             syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m(%d)", errno);
2079           }
2080         return 0;
2081       }
2082
2083     ifr.ifr_flags &= ~IFF_UP;
2084     ifr.ifr_flags |= IFF_POINTOPOINT;
2085     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
2086       {
2087         if (! ok_error (errno))
2088           {
2089             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m(%d)", errno);
2090           }
2091         return 0;
2092       }
2093     return 1;
2094   }
2095
2096 /********************************************************************
2097  *
2098  * sifaddr - Config the interface IP addresses and netmask.
2099  */
2100
2101 int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
2102              u_int32_t net_mask)
2103   {
2104     struct ifreq   ifr; 
2105     struct rtentry rt;
2106     
2107     memset (&ifr, '\0', sizeof (ifr));
2108     memset (&rt,  '\0', sizeof (rt));
2109     
2110     SET_SA_FAMILY (ifr.ifr_addr,    AF_INET); 
2111     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); 
2112     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); 
2113
2114     strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2115 /*
2116  *  Set our IP address
2117  */
2118     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
2119     if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
2120       {
2121         if (errno != EEXIST)
2122           {
2123             if (! ok_error (errno))
2124               {
2125                 syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m(%d)", errno);
2126               }
2127           }
2128         else
2129           {
2130             syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
2131           }
2132         return (0);
2133       } 
2134 /*
2135  *  Set the gateway address
2136  */
2137     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
2138     if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
2139       {
2140         if (! ok_error (errno))
2141           {
2142             syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m(%d)", errno); 
2143           }
2144         return (0);
2145       } 
2146 /*
2147  *  Set the netmask
2148  */
2149     if (net_mask != 0)
2150       {
2151         ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
2152         if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
2153           {
2154             if (! ok_error (errno))
2155               {
2156                 syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m(%d)", errno); 
2157               }
2158             return (0);
2159           } 
2160       }
2161 /*
2162  *  Add the device route
2163  */
2164     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2165     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2166     rt.rt_dev = ifname;  /* MJC */
2167
2168     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0L;
2169     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
2170     rt.rt_flags = RTF_UP | RTF_HOST;
2171
2172     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0)
2173       {
2174         if (! ok_error (errno))
2175           {
2176             syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m(%d)", errno);
2177           }
2178         return (0);
2179       }
2180     return 1;
2181   }
2182
2183 /********************************************************************
2184  *
2185  * cifaddr - Clear the interface IP addresses, and delete routes
2186  * through the interface if possible.
2187  */
2188
2189 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
2190   {
2191     struct rtentry rt;
2192 /*
2193  *  Delete the route through the device
2194  */
2195     memset (&rt, '\0', sizeof (rt));
2196
2197     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2198     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2199     rt.rt_dev = ifname;  /* MJC */
2200
2201     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
2202     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
2203     rt.rt_flags = RTF_UP | RTF_HOST;
2204
2205     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH)
2206       {
2207         if (still_ppp() && ! ok_error (errno))
2208           {
2209             syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m(%d)", errno);
2210           }
2211         return (0);
2212       }
2213     return 1;
2214   }
2215
2216 /********************************************************************
2217  *
2218  * open_loopback - open the device we use for getting packets
2219  * in demand mode.  Under Linux, we use our existing fd
2220  * to the ppp driver.
2221  */
2222 void
2223 open_ppp_loopback(void)
2224   {
2225     int            flags;
2226     struct termios tios;
2227
2228     if (openpty (&master_fd, &slave_fd, loop_name, NULL, NULL) < 0)
2229       {
2230         syslog(LOG_ERR, "No free pty for loopback");
2231         die(1);
2232       }
2233     SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
2234
2235     set_ppp_fd(slave_fd);
2236
2237     if (tcgetattr(ppp_fd, &tios) == 0)
2238       {
2239         tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
2240         tios.c_cflag |= CS8 | CREAD;
2241         tios.c_iflag  = IGNPAR | CLOCAL;
2242         tios.c_oflag  = 0;
2243         tios.c_lflag  = 0;
2244         if (tcsetattr(ppp_fd, TCSAFLUSH, &tios) < 0)
2245           {
2246             syslog(LOG_WARNING, "couldn't set attributes on loopback: %m(%d)", errno);
2247           }
2248       }
2249
2250     flags = fcntl(master_fd, F_GETFL);
2251     if (flags == -1 ||
2252         fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2253       {
2254         syslog(LOG_WARNING, "couldn't set master loopback to nonblock: %m(%d)", errno);
2255       }
2256
2257     flags = fcntl(ppp_fd, F_GETFL);
2258     if (flags == -1 ||
2259         fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2260       {
2261         syslog(LOG_WARNING, "couldn't set slave loopback to nonblock: %m(%d)", errno);
2262       }
2263
2264     if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
2265       {
2266         syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
2267         die(1);
2268       }
2269 /*
2270  * Find out which interface we were given.
2271  */
2272     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
2273       { 
2274         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m(%d)", errno);
2275         die(1);
2276       }
2277 /*
2278  * Enable debug in the driver if requested.
2279  */
2280     set_kdebugflag (kdebugflag);
2281   }
2282
2283 /********************************************************************
2284  *
2285  * restore_loop - reattach the ppp unit to the loopback.
2286  *
2287  * The kernel ppp driver automatically reattaches the ppp unit to
2288  * the loopback if the serial port is set to a line discipline other
2289  * than ppp, or if it detects a modem hangup.  The former will happen
2290  * in disestablish_ppp if the latter hasn't already happened, so we
2291  * shouldn't need to do anything.
2292  *
2293  * Just to be sure, set the real serial port to the normal discipline.
2294  */
2295
2296 void
2297 restore_loop(void)
2298   {
2299     if (ppp_fd != slave_fd)
2300       {
2301         (void) ioctl(ppp_fd, TIOCSETD, &tty_disc);
2302         set_ppp_fd(slave_fd);
2303       }
2304   }
2305
2306 /********************************************************************
2307  *
2308  * sifnpmode - Set the mode for handling packets for a given NP.
2309  */
2310
2311 int
2312 sifnpmode(u, proto, mode)
2313     int u;
2314     int proto;
2315     enum NPmode mode;
2316 {
2317     struct npioctl npi;
2318
2319     npi.protocol = proto;
2320     npi.mode     = mode;
2321     if (ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0)
2322       {
2323         if (! ok_error (errno))
2324           {
2325             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE, %d, %d): %m(%d)",
2326                    proto, mode, errno);
2327             syslog(LOG_ERR, "ppp_fd=%d slave_fd=%d\n", ppp_fd, slave_fd);
2328           }
2329         return 0;
2330       }
2331     return 1;
2332   }
2333
2334 \f
2335 #include <linux/ipx.h>
2336
2337 /********************************************************************
2338  *
2339  * sipxfaddr - Config the interface IPX networknumber
2340  */
2341
2342 int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
2343   {
2344     int    skfd; 
2345     int    result = 1;
2346     struct sockaddr_ipx  ipx_addr;
2347     struct ifreq         ifr;
2348     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2349
2350 #ifdef IPX_CHANGE
2351     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2352     if (skfd < 0)
2353       { 
2354         if (! ok_error (errno))
2355           {
2356             syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
2357           }
2358         result = 0;
2359       }
2360     else
2361       {
2362         memset (&ifr, '\0', sizeof (ifr));
2363         strcpy (ifr.ifr_name, ifname);
2364
2365         memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
2366         sipx->sipx_family  = AF_IPX;
2367         sipx->sipx_port    = 0;
2368         sipx->sipx_network = htonl (network);
2369         sipx->sipx_type    = IPX_FRAME_ETHERII;
2370         sipx->sipx_action  = IPX_CRTITF;
2371 /*
2372  *  Set the IPX device
2373  */
2374         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
2375           {
2376             result = 0;
2377             if (errno != EEXIST)
2378               {
2379                 if (! ok_error (errno))
2380                   {
2381                     syslog (LOG_DEBUG,
2382                             "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno);
2383                   }
2384               }
2385             else
2386               {
2387                 syslog (LOG_WARNING,
2388                         "ioctl(SIOCAIFADDR, CRTITF): Address already exists");
2389               }
2390           }
2391         close (skfd);
2392       }
2393 #endif
2394     return result;
2395   }
2396
2397 /********************************************************************
2398  *
2399  * cipxfaddr - Clear the information for the IPX network. The IPX routes
2400  *             are removed and the device is no longer able to pass IPX
2401  *             frames.
2402  */
2403
2404 int cipxfaddr (int unit)
2405   {
2406     int    skfd; 
2407     int    result = 1;
2408     struct sockaddr_ipx  ipx_addr;
2409     struct ifreq         ifr;
2410     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2411
2412 #ifdef IPX_CHANGE
2413     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2414     if (skfd < 0)
2415       { 
2416         if (! ok_error (errno))
2417           {
2418             syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
2419           }
2420         result = 0;
2421       }
2422     else
2423       {
2424         memset (&ifr, '\0', sizeof (ifr));
2425         strcpy (ifr.ifr_name, ifname);
2426
2427         sipx->sipx_type    = IPX_FRAME_ETHERII;
2428         sipx->sipx_action  = IPX_DLTITF;
2429         sipx->sipx_family  = AF_IPX;
2430 /*
2431  *  Set the IPX device
2432  */
2433         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
2434           {
2435             if (! ok_error (errno))
2436               {
2437                 syslog (LOG_INFO,
2438                         "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno);
2439               }
2440             result = 0;
2441           }
2442         close (skfd);
2443       }
2444 #endif
2445     return result;
2446   }
2447
2448 /********************************************************************
2449  *
2450  * sys_check_options - check the options that the user specified
2451  */
2452
2453 void
2454 sys_check_options(void)
2455   {
2456 #ifdef IPX_CHANGE
2457     struct stat stat_buf;
2458 /*
2459  * Disable the IPX protocol if the support is not present in the kernel.
2460  * If we disable it then ensure that IP support is enabled.
2461  */
2462     while (ipxcp_protent.enabled_flag)
2463       {
2464         if (path_to_procfs())
2465           {
2466             strcat (route_buffer, "/net/ipx_interface");
2467             if (lstat (route_buffer, &stat_buf) >= 0)
2468               {
2469                 break;
2470               }
2471           }
2472         syslog (LOG_ERR, "IPX support is not present in the kernel\n");
2473         ipxcp_protent.enabled_flag = 0;
2474         ipcp_protent.enabled_flag  = 1;
2475         break;
2476       }
2477 #endif
2478   }