]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-linux.c
Initial revision
[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 /*
22  * TODO:
23  */
24
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/time.h>
29 #include <sys/errno.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
42 #include <net/if.h>
43 #include <net/ppp_defs.h>
44 #include <net/if_arp.h>
45 #include <net/if_ppp.h>
46 #include <net/if_route.h>
47 #include <linux/if_ether.h>
48 #include <netinet/in.h>
49
50 #include "pppd.h"
51 #include "fsm.h"
52 #include "ipcp.h"
53
54 static int initdisc = -1;       /* Initial TTY discipline */
55 static int prev_kdebugflag = 0;
56
57 static int restore_term;                /* 1 => we've munged the terminal */
58 static struct termios inittermios;      /* Initial TTY termios */
59
60 int sockfd;                     /* socket for doing interface ioctls */
61
62 static int driver_version      = 0;
63 static int driver_modification = 0;
64 static int driver_patch        = 0;
65
66 static char *lock_file;
67
68 #define MAX_IFS         32
69
70 #define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
71 #define FLAGS_MASK (IFF_UP          | IFF_BROADCAST | \
72                     IFF_POINTOPOINT | IFF_LOOPBACK  | IFF_NOARP)
73
74 /*
75  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
76  * if it exists.
77  */
78
79 #define SET_SA_FAMILY(addr, family)                     \
80     memset ((char *) &(addr), '\0', sizeof(addr));      \
81     addr.sa_family = (family);
82
83 /*
84  * Functions to read and set the flags value in the device driver
85  */
86
87 int get_flags (void)
88   {    
89     int flags;
90
91     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0)
92       {
93         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
94         quit();
95       }
96
97     MAINDEBUG ((LOG_DEBUG, "get flags = %x\n", flags));
98     return flags;
99   }
100
101 void set_flags (int flags)
102   {    
103     MAINDEBUG ((LOG_DEBUG, "set flags = %x\n", flags));
104     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
105       {
106         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS, %x): %m", flags);
107         quit();
108       }
109   }
110
111 /*
112  * sys_init - System-dependent initialization.
113  */
114
115 void sys_init(void)
116   {
117     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
118     setlogmask(LOG_UPTO(LOG_INFO));
119     if (debug)
120       {
121         setlogmask(LOG_UPTO(LOG_DEBUG));
122       }
123     
124     /* Get an internet socket for doing socket ioctls. */
125     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
126     if (sockfd < 0)
127       {
128         syslog(LOG_ERR, "Couldn't create IP socket: %m");
129         die(1);
130       }
131   }
132
133 /*
134  * note_debug_level - note a change in the debug level.
135  */
136
137 void note_debug_level (void)
138   {
139     if (debug)
140       {
141         MAINDEBUG ((LOG_INFO, "Debug turned ON, Level %d", debug));
142         setlogmask(LOG_UPTO(LOG_DEBUG));
143       }
144     else
145       {
146         setlogmask(LOG_UPTO(LOG_WARNING));
147       }
148   }
149
150 /*
151  * set_kdebugflag - Define the debugging level for the kernel
152  */
153
154 int set_kdebugflag (int requested_level)
155   {
156     if (ioctl(fd, PPPIOCGDEBUG, &prev_kdebugflag) < 0)
157       {
158         syslog(LOG_ERR, "ioctl(PPPIOCGDEBUG): %m");
159         return (0);
160       }
161     
162     if (prev_kdebugflag != requested_level)
163       {
164         if (ioctl(fd, PPPIOCSDEBUG, &requested_level) < 0)
165           {
166             syslog (LOG_ERR, "ioctl(PPPIOCSDEBUG): %m");
167             return (0);
168           }
169         MAINDEBUG ((LOG_INFO, "set kernel debugging level to %d", requested_level));
170       }
171     return (1);
172   }
173
174 /*
175  * establish_ppp - Turn the serial port into a ppp interface.
176  */
177
178 void establish_ppp (void)
179   {
180     int pppdisc = N_PPP;
181     int sig     = SIGIO;
182
183     if (ioctl(fd, TIOCEXCL, 0) < 0)
184       {
185         syslog (LOG_WARNING, "ioctl(TIOCEXCL): %m");
186       }
187     
188     if (ioctl(fd, TIOCGETD, &initdisc) < 0)
189       {
190         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
191         die (1);
192       }
193     
194     if (ioctl(fd, TIOCSETD, &pppdisc) < 0)
195       {
196         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
197         die (1);
198       }
199     
200     if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0)
201       {
202         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
203         die (1);
204       }
205     
206     set_kdebugflag (kdebugflag);
207
208     set_flags (get_flags() & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
209                                SC_RCV_EVNP | SC_RCV_ODDP));
210
211     MAINDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
212             driver_version, driver_modification, driver_patch));
213   }
214
215 /*
216  * disestablish_ppp - Restore the serial port to normal operation.
217  * This shouldn't call die() because it's called from die().
218  */
219
220 void disestablish_ppp(void)
221   {
222     int x;
223     char *s;
224 /*
225  * Check whether the link seems not to be 8-bit clean.
226  */
227     if (initdisc >= 0)
228       {
229         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0)
230           {
231             s = NULL;
232             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP))
233               {
234             case SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP:
235                 s = "nothing was received";
236                 break;
237
238             case SC_RCV_B7_0:
239             case SC_RCV_B7_0 | SC_RCV_EVNP:
240             case SC_RCV_B7_0 | SC_RCV_ODDP:
241             case SC_RCV_B7_0 | SC_RCV_ODDP | SC_RCV_EVNP:
242                 s = "all had bit 7 set to 1";
243                 break;
244
245             case SC_RCV_B7_1:
246             case SC_RCV_B7_1 | SC_RCV_EVNP:
247             case SC_RCV_B7_1 | SC_RCV_ODDP:
248             case SC_RCV_B7_1 | SC_RCV_ODDP | SC_RCV_EVNP:
249                 s = "all had bit 7 set to 0";
250                 break;
251
252             case SC_RCV_EVNP:
253                 s = "all had odd parity";
254                 break;
255
256             case SC_RCV_ODDP:
257                 s = "all had even parity";
258                 break;
259               }
260
261             if (s != NULL)
262               {
263                 syslog(LOG_WARNING, "Receive serial link is not 8-bit clean:");
264                 syslog(LOG_WARNING, "Problem: %s", s);
265               }
266           }
267
268         set_kdebugflag (prev_kdebugflag);
269         
270         if (ioctl(fd, TIOCSETD, &initdisc) < 0)
271           {
272             syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
273           }
274         
275         if (ioctl(fd, TIOCNXCL, 0) < 0)
276           {
277             syslog (LOG_WARNING, "ioctl(TIOCNXCL): %m");
278           }
279         
280         initdisc = -1;
281       }
282   }
283
284 /*
285  * List of valid speeds.
286  */
287
288 struct speed {
289     int speed_int, speed_val;
290 } speeds[] = {
291 #ifdef B50
292     { 50, B50 },
293 #endif
294 #ifdef B75
295     { 75, B75 },
296 #endif
297 #ifdef B110
298     { 110, B110 },
299 #endif
300 #ifdef B134
301     { 134, B134 },
302 #endif
303 #ifdef B150
304     { 150, B150 },
305 #endif
306 #ifdef B200
307     { 200, B200 },
308 #endif
309 #ifdef B300
310     { 300, B300 },
311 #endif
312 #ifdef B600
313     { 600, B600 },
314 #endif
315 #ifdef B1200
316     { 1200, B1200 },
317 #endif
318 #ifdef B1800
319     { 1800, B1800 },
320 #endif
321 #ifdef B2000
322     { 2000, B2000 },
323 #endif
324 #ifdef B2400
325     { 2400, B2400 },
326 #endif
327 #ifdef B3600
328     { 3600, B3600 },
329 #endif
330 #ifdef B4800
331     { 4800, B4800 },
332 #endif
333 #ifdef B7200
334     { 7200, B7200 },
335 #endif
336 #ifdef B9600
337     { 9600, B9600 },
338 #endif
339 #ifdef B19200
340     { 19200, B19200 },
341 #endif
342 #ifdef B38400
343     { 38400, B38400 },
344 #endif
345 #ifdef EXTA
346     { 19200, EXTA },
347 #endif
348 #ifdef EXTB
349     { 38400, EXTB },
350 #endif
351 #ifdef B57600
352     { 57600, B57600 },
353 #endif
354 #ifdef B115200
355     { 115200, B115200 },
356 #endif
357     { 0, 0 }
358 };
359
360 /*
361  * Translate from bits/second to a speed_t.
362  */
363
364 int translate_speed (int bps)
365   {
366     struct speed *speedp;
367
368     if (bps == 0)
369       {
370         for (speedp = speeds; speedp->speed_int; speedp++)
371           {
372             if (bps == speedp->speed_int)
373               {
374                 return speedp->speed_val;
375               }
376           }
377         syslog(LOG_WARNING, "speed %d not supported", bps);
378       }
379     return 0;
380   }
381
382 /*
383  * Translate from a speed_t to bits/second.
384  */
385
386 int baud_rate_of (int speed)
387   {
388     struct speed *speedp;
389     
390     if (speed != 0)
391       {
392         for (speedp = speeds; speedp->speed_int; speedp++)
393           {
394             if (speed == speedp->speed_val)
395               {
396                 return speedp->speed_int;
397               }
398           }
399       }
400     return 0;
401   }
402
403 /*
404  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
405  * at the requested speed, etc.  If `local' is true, set CLOCAL
406  * regardless of whether the modem option was specified.
407  */
408
409 void set_up_tty (int fd, int local)
410   {
411     int speed, x;
412     struct termios tios;
413     
414     if (tcgetattr(fd, &tios) < 0)
415       {
416         syslog(LOG_ERR, "tcgetattr: %m");
417         die(1);
418       }
419     
420     if (!restore_term)
421       {
422         inittermios = tios;
423       }
424     
425     tios.c_cflag     &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
426     tios.c_cflag     |= CS8 | CREAD | HUPCL;
427
428     tios.c_iflag      = IGNBRK | IGNPAR;
429     tios.c_oflag      = 0;
430     tios.c_lflag      = 0;
431     tios.c_cc[VMIN]   = 1;
432     tios.c_cc[VTIME]  = 0;
433     
434     if (local || !modem)
435       {
436         tios.c_cflag ^= (CLOCAL | HUPCL);
437       }
438
439     switch (crtscts)
440       {
441     case 1:
442         tios.c_cflag |= CRTSCTS;
443         break;
444
445     case 2:
446         tios.c_iflag     |= IXOFF;
447         tios.c_cc[VSTOP]  = 0x13;       /* DC3 = XOFF = ^S */
448         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
449         break;
450
451     case -1:
452         tios.c_cflag &= ~CRTSCTS;
453         break;
454
455     default:
456         break;
457       }
458     
459     speed = translate_speed(inspeed);
460     if (speed)
461       {
462         cfsetospeed (&tios, speed);
463         cfsetispeed (&tios, speed);
464       }
465 /*
466  * We can't proceed if the serial port speed is B0,
467  * since that implies that the serial port is disabled.
468  */
469     else
470       {
471         speed = cfgetospeed(&tios);
472         if (speed == B0)
473           {
474             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
475                    devnam);
476             die (1);
477           }
478       }
479
480     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0)
481       {
482         syslog(LOG_ERR, "tcsetattr: %m");
483         die(1);
484       }
485     
486     baud_rate    = baud_rate_of(speed);
487     restore_term = TRUE;
488   }
489
490 /*
491  * setdtr - control the DTR line on the serial port.
492  * This is called from die(), so it shouldn't call die().
493  */
494
495 void setdtr (int fd, int on)
496   {
497     int modembits = TIOCM_DTR;
498
499     ioctl(fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
500   }
501
502 /*
503  * restore_tty - restore the terminal to the saved settings.
504  */
505
506 void restore_tty (void)
507   {
508     if (restore_term)
509       {
510         restore_term = 0;
511 /*
512  * Turn off echoing, because otherwise we can get into
513  * a loop with the tty and the modem echoing to each other.
514  * We presume we are the sole user of this tty device, so
515  * when we close it, it will revert to its defaults anyway.
516  */
517         if (!default_device)
518           {
519             inittermios.c_lflag &= ~(ECHO | ECHONL);
520           }
521         
522         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
523           {
524             if (errno != ENXIO)
525               {
526                 syslog(LOG_WARNING, "tcsetattr: %m");
527               }
528           }
529       }
530   }
531
532 /*
533  * output - Output PPP packet.
534  */
535
536 void output (int unit, unsigned char *p, int len)
537   {
538     if (unit != 0)
539       {
540         MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
541       }
542     
543     if (debug)
544       {
545         log_packet(p, len, "sent ");
546       }
547     
548     if (write(fd, p, len) < 0)
549       {
550         syslog(LOG_ERR, "write: %m");
551         die(1);
552       }
553   }
554
555 /*
556  * wait_input - wait until there is data available on fd,
557  * for the length of time specified by *timo (indefinite
558  * if timo is NULL).
559  */
560
561 void wait_input (struct timeval *timo)
562   {
563     fd_set ready;
564     int n;
565     
566     FD_ZERO(&ready);
567     FD_SET(fd, &ready);
568
569     n = select(fd+1, &ready, NULL, &ready, timo);
570     if (n < 0 && errno != EINTR)
571       {
572         syslog(LOG_ERR, "select: %m");
573         die(1);
574       }
575   }
576
577 /*
578  * read_packet - get a PPP packet from the serial device.
579  */
580
581 int read_packet (unsigned char *buf)
582   {
583     int len;
584   
585     len = read(fd, buf, PPP_MTU + PPP_HDRLEN);
586     if (len < 0)
587       {
588         if (errno == EWOULDBLOCK)
589           {
590             return -1;
591           }
592         syslog(LOG_ERR, "read(fd): %m");
593         die(1);
594       }
595     return len;
596   }
597
598 /*
599  * ppp_send_config - configure the transmit characteristics of
600  * the ppp interface.
601  */
602
603 void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
604   {
605     u_int x;
606     struct ifreq ifr;
607   
608     MAINDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
609     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
610     ifr.ifr_mtu = mtu;
611
612     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
613       {
614         syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
615         quit();
616       }
617     
618     MAINDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
619     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
620       {
621         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
622         quit();
623       }
624     
625     x = get_flags();
626     x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
627     x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
628     set_flags(x);
629   }
630
631 /*
632  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
633  */
634
635 void ppp_set_xaccm (int unit, ext_accm accm)
636   {
637     MAINDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
638                 accm[0], accm[1], accm[2], accm[3]));
639
640     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
641       {
642         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
643       }
644   }
645
646 /*
647  * ppp_recv_config - configure the receive-side characteristics of
648  * the ppp interface.
649  */
650
651 void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
652   {
653     u_int x;
654
655     MAINDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
656     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
657       {
658         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
659       }
660
661     MAINDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
662     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
663       {
664         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
665         quit();
666       }
667
668     x = get_flags();
669     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
670     set_flags (x);
671   }
672
673 /*
674  * ccp_test - ask kernel whether a given compression method
675  * is acceptable for use.
676  */
677
678 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
679   {
680     struct ppp_option_data data;
681
682     data.ptr      = opt_ptr;
683     data.length   = opt_len;
684     data.transmit = for_transmit;
685
686     return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
687   }
688
689 /*
690  * ccp_flags_set - inform kernel about the current state of CCP.
691  */
692
693 void ccp_flags_set (int unit, int isopen, int isup)
694   {
695     int x = get_flags();
696     x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
697     x = isup?   x | SC_CCP_UP   : x &~ SC_CCP_UP;
698     set_flags (x);
699   }
700
701 /*
702  * ccp_fatal_error - returns 1 if decompression was disabled as a
703  * result of an error detected after decompression of a packet,
704  * 0 otherwise.  This is necessary because of patent nonsense.
705  */
706
707 int ccp_fatal_error (int unit)
708   {
709     int x = get_flags();
710
711     return x & SC_DC_FERROR;
712   }
713
714 /*
715  * sifvjcomp - config tcp header compression
716  */
717
718 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
719   {
720     u_int x = get_flags();
721
722     if (vjcomp)
723       {
724         if (ioctl (fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
725           {
726             syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
727             vjcomp = 0;
728           }
729       }
730
731     x = vjcomp  ? x | SC_COMP_TCP     : x &~ SC_COMP_TCP;
732     x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
733     set_flags (x);
734
735     return 1;
736   }
737
738 /*
739  * sifup - Config the interface up and enable IP packets to pass.
740  */
741
742 int sifup (int u)
743   {
744     struct ifreq ifr;
745
746     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
747     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
748       {
749         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
750         return 0;
751       }
752
753     ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
754     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
755       {
756         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
757         return 0;
758       }
759     return 1;
760   }
761
762 /*
763  * sifdown - Config the interface down and disable IP.
764  */
765
766 int sifdown (int u)
767   {
768     struct ifreq ifr;
769
770     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
771     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
772       {
773         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
774         return 0;
775       }
776
777     ifr.ifr_flags &= ~IFF_UP;
778     ifr.ifr_flags |= IFF_POINTOPOINT;
779     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
780       {
781         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
782         return 0;
783       }
784     return 1;
785   }
786
787 /*
788  * sifaddr - Config the interface IP addresses and netmask.
789  */
790
791 int sifaddr (int unit, int our_adr, int his_adr, int net_mask)
792   {
793     struct ifreq   ifr; 
794     struct rtentry rt;
795     
796     SET_SA_FAMILY (ifr.ifr_addr,    AF_INET); 
797     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); 
798     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); 
799
800     strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
801 /*
802  *  Set our IP address
803  */
804     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
805     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
806       {
807         if (errno != EEXIST)
808           {
809             syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m");
810           }
811         else
812           {
813             syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
814           }
815         return (0);
816       } 
817 /*
818  *  Set the gateway address
819  */
820     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
821     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
822       {
823         syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m"); 
824         return (0);
825       } 
826 /*
827  *  Set the netmask
828  */
829     if (net_mask != 0)
830       {
831         ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
832         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
833           {
834             syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m"); 
835             return (0);
836           } 
837       }
838 /*
839  *  Add the device route
840  */
841     memset (&rt, '\0', sizeof (rt));
842
843     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
844     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
845     rt.rt_dev = ifname;  /* MJC */
846
847     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
848     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
849     rt.rt_flags = RTF_UP | RTF_HOST;
850
851     if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
852       {
853         syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m");
854         return (0);
855       }
856     return 1;
857   }
858
859 /*
860  * cifaddr - Clear the interface IP addresses, and delete routes
861  * through the interface if possible.
862  */
863
864 int cifaddr (int unit, int our_adr, int his_adr)
865   {
866     struct rtentry rt;
867 /*
868  *  Delete the route through the device
869  */
870     memset (&rt, '\0', sizeof (rt));
871
872     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
873     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
874     rt.rt_dev = ifname;  /* MJC */
875
876     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
877     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
878     rt.rt_flags = RTF_UP | RTF_HOST;
879
880     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
881       {
882         syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m");
883         return (0);
884       }
885     return 1;
886   }
887
888 /*
889  * path_to_route - determine the path to the proc file system data
890  */
891
892 FILE *route_fd = (FILE *) 0;
893 static char route_buffer [100];
894
895 static char *path_to_route (void);
896 static int open_route_table (void);
897 static void close_route_table (void);
898 static int read_route_table (struct rtentry *rt);
899 static int defaultroute_exists (void);
900
901 /*
902  * path_to_route - find the path to the route tables in the proc file system
903  */
904
905 static char *path_to_route (void)
906   {
907     struct mntent *mntent;
908     FILE *fp;
909
910     fp = fopen (MOUNTED, "r");
911     if (fp != 0)
912       {
913         mntent = getmntent (fp);
914         while (mntent != (struct mntent *) 0)
915           {
916             if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) != 0)
917               {
918                 if (strcmp (mntent->mnt_type, "proc") == 0)
919                   {
920                     strncpy (route_buffer, mntent->mnt_dir,
921                              sizeof (route_buffer)-10);
922                     route_buffer [sizeof (route_buffer)-10] = '\0';
923                     strcat (route_buffer, "/net/route");
924                     
925                     fclose (fp);
926                     return (route_buffer);
927                   }
928               }
929             mntent = getmntent (fp);
930           }
931         fclose (fp);
932       }
933
934     syslog (LOG_ERR, "proc file system not mounted");
935     return 0;
936   }
937
938 /*
939  * open_route_table - open the interface to the route table
940  */
941
942 static int open_route_table (void)
943   {
944     char *path;
945
946     if (route_fd != (FILE *) 0)
947       {
948         close_route_table();
949       }
950
951     path = path_to_route();
952     if (path == NULL)
953       {
954         return 0;
955       }
956
957     route_fd = fopen (path, "r");
958     if (route_fd == (FILE *) 0)
959       {
960         syslog (LOG_ERR, "can not open %s: %m", path);
961         return 0;
962       }
963
964     /* read and discard the header line. */
965     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
966       {
967         close_route_table();
968         return 0;
969       }
970     return 1;
971   }
972
973 /*
974  * close_route_table - close the interface to the route table
975  */
976
977 static void close_route_table (void)
978   {
979     if (route_fd != (FILE *) 0)
980       {
981         fclose (route_fd);
982         route_fd = (FILE *) 0;
983       }
984   }
985
986 /*
987  * read_route_table - read the next entry from the route table
988  */
989
990 static int read_route_table (struct rtentry *rt)
991   {
992     static char delims[] = " \t\n";
993     char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
994
995     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
996       {
997         return 0;
998       }
999
1000     memset (rt, '\0', sizeof (struct rtentry));
1001
1002     dev_ptr  = strtok (route_buffer, delims); /* interface name */
1003     dst_ptr  = strtok (NULL,         delims); /* destination address */
1004     gw_ptr   = strtok (NULL,         delims); /* gateway */
1005     flag_ptr = strtok (NULL,         delims); /* flags */
1006
1007     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
1008       strtoul (dst_ptr, NULL, 16);
1009
1010     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
1011       strtoul (gw_ptr, NULL, 16);
1012
1013     rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
1014     rt->rt_dev   = dev_ptr;
1015
1016     return 1;
1017   }
1018
1019 /*
1020  * defaultroute_exists - determine if there is a default route
1021  */
1022
1023 static int defaultroute_exists (void)
1024   {
1025     struct rtentry rt;
1026     int    result = 0;
1027
1028     if (!open_route_table())
1029       {
1030         return 0;
1031       }
1032
1033     while (read_route_table(&rt) != 0)
1034       {
1035         if (rt.rt_flags & RTF_UP == 0)
1036           {
1037             continue;
1038           }
1039
1040         if (((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr == 0L)
1041           {
1042             syslog (LOG_ERR,
1043                     "ppp not replacing existing default route to %s[%s]",
1044                     rt.rt_dev,
1045                     inet_ntoa (((struct sockaddr_in *) &rt.rt_gateway)->
1046                                sin_addr.s_addr));
1047             result = 1;
1048             break;
1049           }
1050       }
1051
1052     close_route_table();
1053     return result;
1054   }
1055
1056 /*
1057  * sifdefaultroute - assign a default route through the address given.
1058  */
1059
1060 int sifdefaultroute (int unit, int gateway)
1061   {
1062     struct rtentry rt;
1063
1064     if (defaultroute_exists())
1065       {
1066         return 0;
1067       }
1068
1069     memset (&rt, '\0', sizeof (rt));
1070     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1071     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1072     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1073     
1074     rt.rt_flags = RTF_UP | RTF_GATEWAY;
1075     if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
1076       {
1077         syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m");
1078         return 0;
1079       }
1080     return 1;
1081   }
1082
1083 /*
1084  * cifdefaultroute - delete a default route through the address given.
1085  */
1086
1087 int cifdefaultroute (int unit, int gateway)
1088   {
1089     struct rtentry rt;
1090   
1091     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1092     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1093     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1094     
1095     rt.rt_flags = RTF_UP | RTF_GATEWAY;
1096     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
1097       {
1098         syslog (LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1099         return 0;
1100       }
1101     return 1;
1102   }
1103
1104 /*
1105  * sifproxyarp - Make a proxy ARP entry for the peer.
1106  */
1107
1108 int sifproxyarp (int unit, u_int32_t his_adr)
1109   {
1110     struct arpreq arpreq;
1111
1112     memset (&arpreq, '\0', sizeof(arpreq));
1113 /*
1114  * Get the hardware address of an interface on the same subnet
1115  * as our local address.
1116  */
1117     if (!get_ether_addr(his_adr, &arpreq.arp_ha))
1118       {
1119         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1120         return 0;
1121       }
1122     
1123     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1124     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1125     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1126     
1127     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0)
1128       {
1129         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1130         return 0;
1131       }
1132     return 1;
1133   }
1134
1135 /*
1136  * cifproxyarp - Delete the proxy ARP entry for the peer.
1137  */
1138
1139 int cifproxyarp (int unit, u_int32_t his_adr)
1140   {
1141     struct arpreq arpreq;
1142   
1143     memset (&arpreq, '\0', sizeof(arpreq));
1144     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1145     
1146     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1147     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0)
1148       {
1149         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1150         return 0;
1151       }
1152     return 1;
1153   }
1154      
1155 /*
1156  * get_ether_addr - get the hardware address of an interface on the
1157  * the same subnet as ipaddr.
1158  */
1159
1160 int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr)
1161   {
1162     struct ifreq *ifr, *ifend, *ifp;
1163     int i;
1164     u_int32_t ina, mask;
1165     struct sockaddr_dl *dla;
1166     struct ifreq ifreq;
1167     struct ifconf ifc;
1168     struct ifreq ifs[MAX_IFS];
1169     
1170     ifc.ifc_len = sizeof(ifs);
1171     ifc.ifc_req = ifs;
1172     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1173       {
1174         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1175         return 0;
1176       }
1177
1178     MAINDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
1179                 ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
1180 /*
1181  * Scan through looking for an interface with an Internet
1182  * address on the same subnet as `ipaddr'.
1183  */
1184     ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1185     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1186       {
1187         if (ifr->ifr_addr.sa_family == AF_INET)
1188           {
1189             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1190             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1191             MAINDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
1192                         ifreq.ifr_name));
1193 /*
1194  * Check that the interface is up, and not point-to-point
1195  * or loopback.
1196  */
1197             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1198               {
1199                 continue;
1200               }
1201
1202             if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1203               {
1204                 continue;
1205               }
1206 /*
1207  * Get its netmask and check that it's on the right subnet.
1208  */
1209             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1210               {
1211                 continue;
1212               }
1213
1214             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1215             MAINDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
1216                         ip_ntoa(ina), ntohl(mask)));
1217
1218             if (((ipaddr ^ ina) & mask) != 0)
1219               {
1220                 continue;
1221               }
1222             break;
1223           }
1224       }
1225     
1226     if (ifr >= ifend)
1227       {
1228         return 0;
1229       }
1230
1231     syslog(LOG_INFO, "found interface %s for proxy arp", ifreq.ifr_name);
1232 /*
1233  * Now get the hardware address.
1234  */
1235     if (ioctl (sockfd, SIOCGIFHWADDR, &ifreq) < 0)
1236       {
1237         syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m", ifreq.ifr_name);
1238         return 0;
1239       }
1240
1241     hwaddr->sa_family = ARPHRD_ETHER;
1242     memcpy (&hwaddr->sa_data, &ifreq.ifr_hwaddr.sa_data, ETH_ALEN);
1243
1244     MAINDEBUG ((LOG_DEBUG,
1245                 "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x",
1246                 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1247                 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1248                 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1249                 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1250                 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1251                 (int) ((unsigned char *) &hwaddr->sa_data)[5]));
1252     return 1;
1253   }
1254
1255 /*
1256  * Return user specified netmask, modified by any mask we might determine
1257  * for address `addr' (in network byte order).
1258  * Here we scan through the system's list of interfaces, looking for
1259  * any non-point-to-point interfaces which might appear to be on the same
1260  * network as `addr'.  If we find any, we OR in their netmask to the
1261  * user-specified netmask.
1262  */
1263
1264 u_int32_t GetMask (u_int32_t addr)
1265   {
1266     u_int32_t mask, nmask, ina;
1267     struct ifreq *ifr, *ifend, ifreq;
1268     struct ifconf ifc;
1269     struct ifreq ifs[MAX_IFS];
1270
1271     addr = ntohl(addr);
1272     
1273     if (IN_CLASSA(addr))        /* determine network mask for address class */
1274       {
1275         nmask = IN_CLASSA_NET;
1276       }
1277     else
1278       {
1279         if (IN_CLASSB(addr))
1280           {
1281             nmask = IN_CLASSB_NET;
1282           }
1283         else
1284           {
1285             nmask = IN_CLASSC_NET;
1286           }
1287       }
1288     
1289     /* class D nets are disallowed by bad_ip_adrs */
1290     mask = netmask | htonl(nmask);
1291 /*
1292  * Scan through the system's network interfaces.
1293  */
1294     ifc.ifc_len = sizeof(ifs);
1295     ifc.ifc_req = ifs;
1296     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1297       {
1298         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1299         return mask;
1300       }
1301     
1302     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1303     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1304       {
1305 /*
1306  * Check the interface's internet address.
1307  */
1308         if (ifr->ifr_addr.sa_family != AF_INET)
1309           {
1310             continue;
1311           }
1312         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1313         if (((ntohl(ina) ^ addr) & nmask) != 0)
1314           {
1315             continue;
1316           }
1317 /*
1318  * Check that the interface is up, and not point-to-point or loopback.
1319  */
1320         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1321         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1322           {
1323             continue;
1324           }
1325         
1326         if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1327           {
1328             continue;
1329           }
1330 /*
1331  * Get its netmask and OR it into our mask.
1332  */
1333         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1334           {
1335             continue;
1336           }
1337         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1338         break;
1339       }
1340
1341     return mask;
1342   }
1343
1344 /*
1345  * Internal routine to decode the version.modification.patch level
1346  */
1347
1348 static void decode_version (char *buf, int *version,
1349                             int *modification, int *patch)
1350   {
1351
1352     *version      = (int) strtoul (buf, &buf, 10);
1353     *modification = 0;
1354     *patch        = 0;
1355     
1356     if (*buf == '.')
1357       {
1358         ++buf;
1359         *modification = (int) strtoul (buf, &buf, 10);
1360         if (*buf == '.')
1361           {
1362             ++buf;
1363             *patch = (int) strtoul (buf, &buf, 10);
1364           }
1365       }
1366     
1367     if (*buf != '\0')
1368       {
1369         *version      =
1370         *modification =
1371         *patch        = 0;
1372       }
1373   }
1374
1375 /*
1376  * Procedure to determine if the PPP line dicipline is registered.
1377  */
1378
1379 int
1380 ppp_registered(void)
1381   {
1382     int local_fd;
1383     int ppp_disc  = N_PPP;
1384     int init_disc = -1;
1385     int initfdflags;
1386
1387     local_fd = open(devnam, O_NONBLOCK | O_RDWR, 0);
1388     if (local_fd < 0)
1389       {
1390         syslog(LOG_ERR, "Failed to open %s: %m", devnam);
1391         return 0;
1392       }
1393
1394     initfdflags = fcntl(local_fd, F_GETFL);
1395     if (initfdflags == -1)
1396       {
1397         syslog(LOG_ERR, "Couldn't get device fd flags: %m");
1398         close (local_fd);
1399         return 0;
1400       }
1401
1402     initfdflags &= ~O_NONBLOCK;
1403     fcntl(local_fd, F_SETFL, initfdflags);
1404 /*
1405  * Read the initial line dicipline and try to put the device into the
1406  * PPP dicipline.
1407  */
1408     if (ioctl(local_fd, TIOCGETD, &init_disc) < 0)
1409       {
1410         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
1411         close (local_fd);
1412         return 0;
1413       }
1414     
1415     if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0)
1416       {
1417         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1418         close (local_fd);
1419         return 0;
1420       }
1421     
1422     if (ioctl(local_fd, TIOCSETD, &init_disc) < 0)
1423       {
1424         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1425         close (local_fd);
1426         return 0;
1427       }
1428     
1429     close (local_fd);
1430     return 1;
1431   }
1432
1433 /*
1434  * ppp_available - check whether the system has any ppp interfaces
1435  * (in fact we check whether we can do an ioctl on ppp0).
1436  */
1437
1438 int ppp_available(void)
1439   {
1440     int s, ok;
1441     struct ifreq ifr;
1442     int my_version,     my_modification,     my_patch;
1443 /*
1444  * Open a socket for doing the ioctl operations.
1445  */    
1446     s = socket(AF_INET, SOCK_DGRAM, 0);
1447     if (s < 0)
1448       {
1449         return 0;
1450       }
1451     
1452     strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1453     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1454 /*
1455  * If the device did not exist then attempt to create one by putting the
1456  * current tty into the PPP discipline. If this works then obtain the
1457  * flags for the device again.
1458  */
1459     if (!ok)
1460       {
1461         if (ppp_registered())
1462           {
1463             strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1464             ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1465           }
1466       }
1467 /*
1468  * Ensure that the hardware address is for PPP and not something else
1469  */
1470     if (ok)
1471       {
1472         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
1473       }
1474
1475     if (ok && ifr.ifr_hwaddr.sa_family != ARPHRD_PPP)
1476       {
1477         ok = 0;
1478       }
1479 /*
1480  *  This is the PPP device. Validate the version of the driver at this
1481  *  point to ensure that this program will work with the driver.
1482  */
1483     if (ok)
1484       {
1485         char   abBuffer [1024];
1486         int    size;
1487
1488         ifr.ifr_data = abBuffer;
1489         size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
1490         ok   = size >= 0;
1491
1492         if (ok)
1493           {
1494             decode_version (abBuffer,
1495                             &driver_version,
1496                             &driver_modification,
1497                             &driver_patch);
1498           }
1499       }
1500     
1501     if (!ok)
1502       {
1503         driver_version      =
1504         driver_modification =
1505         driver_patch        = 0;
1506       }
1507 /*
1508  * Validate the version of the driver against the version that we used.
1509  */
1510     decode_version (PPP_VERSION,
1511                     &my_version,
1512                     &my_modification,
1513                     &my_patch);
1514
1515     /* The version numbers must match */
1516     if (driver_version != my_version)
1517       {
1518         ok = 0;
1519       }
1520       
1521     /* The modification levels must be legal */
1522     if (driver_modification < my_modification)
1523       {
1524         ok = 0;
1525       }
1526
1527     if (!ok)
1528       {
1529         fprintf(stderr, "Sorry - PPP driver version %d.%d.%d is out of date\n",
1530                 driver_version, driver_modification, driver_patch);
1531         close (s);
1532         exit (1);
1533       }
1534     
1535     close(s);
1536     return ok;
1537   }
1538
1539 int logwtmp (char *line, char *name, char *host)
1540   {
1541     struct utmp ut;
1542     int    mode;
1543 /*
1544  * Control the 'mesg' function based upon the state of the logon
1545  * operation.
1546  */
1547     mode = (*name != '\0') ? 0600 : 0622;
1548     if (chmod (devnam, mode) < 0)
1549       {
1550         syslog (LOG_ERR, "chmod(\"%s\", 0%o): %m", devnam, mode);
1551       }
1552 /*
1553  * Update the signon database for users.
1554  */
1555     memset (&ut, 0, sizeof (ut));
1556     (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1557     (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1558     (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1559     (void)time(&ut.ut_time);
1560         
1561     pututline (&ut);            /* Write the line to the proper place */
1562     endutent();                 /* Indicate operation is complete */
1563   }
1564
1565 /*
1566  * Code for locking/unlocking the serial device.
1567  * This code is derived from chat.c.
1568  */
1569
1570 #define LOCK_PREFIX     "/var/lock/LCK.."
1571
1572 /*
1573  * lock - create a lock file for the named device
1574  */
1575
1576 int lock (char *dev)
1577   {
1578     char hdb_lock_buffer[12];
1579     int fd, pid, n;
1580     char *p;
1581
1582     p = strrchr(dev, '/');
1583     if (p != NULL)
1584       {
1585         dev = ++p;
1586       }
1587
1588     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1589     if (lock_file == NULL)
1590       {
1591         novm("lock file name");
1592       }
1593
1594     strcpy (lock_file, LOCK_PREFIX);
1595     strcat (lock_file, dev);
1596 /*
1597  * Attempt to create the lock file at this point.
1598  */
1599     while (1)
1600       {
1601         fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644);
1602         if (fd >= 0)
1603           {
1604             sprintf(hdb_lock_buffer, "%010d\n", getpid());
1605             write(fd, hdb_lock_buffer, 11);
1606             close(fd);
1607             return 0;
1608           }
1609 /*
1610  * If the file exists then check to see if the pid is stale
1611  */
1612         if (errno == EEXIST)
1613           {
1614             fd = open(lock_file, O_RDONLY, 0);
1615             if (fd < 0)
1616               {
1617                 if (errno == ENOENT) /* This is just a timing problem. */
1618                   {
1619                     continue;
1620                   }
1621                 break;
1622               }
1623
1624             /* Read the lock file to find out who has the device locked */
1625             n = read (fd, hdb_lock_buffer, 11);
1626             close (fd);
1627             if (n < 0)
1628               {
1629                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1630                 break;
1631               }
1632
1633             if (n == 0)
1634               {
1635                 unlink (lock_file);
1636                 syslog (LOG_NOTICE, "Removed stale lock on %s", lock_file);
1637                 continue;
1638               }
1639
1640             hdb_lock_buffer[n] = '\0';
1641             sscanf (hdb_lock_buffer, " %d", &pid);
1642
1643             if (kill(pid, 0) == -1 && errno == ESRCH)
1644               {
1645                 /* pid no longer exists - remove the lock file */
1646                 if (unlink (lock_file) == 0)
1647                   {
1648                     syslog (LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1649                             dev, pid);
1650                     continue;
1651                   }
1652               }
1653
1654             syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, pid);
1655             break;
1656           }
1657
1658         syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1659         break;
1660       }
1661
1662     free(lock_file);
1663     lock_file = NULL;
1664     return -1;
1665 }
1666
1667 /*
1668  * unlock - remove our lockfile
1669  */
1670
1671 void unlock(void)
1672   {
1673     if (lock_file)
1674       {
1675         unlink(lock_file);
1676         free(lock_file);
1677         lock_file = NULL;
1678       }
1679   }