]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-svr4.c
support micro$oft DNS options;
[ppp.git] / pppd / sys-svr4.c
1 /*
2  * System-dependent procedures for pppd under Solaris 2.
3  *
4  * Copyright (c) 1994 The Australian National University.
5  * All rights reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation is hereby granted, provided that the above copyright
9  * notice appears in all copies.  This software is provided without any
10  * warranty, express or implied. The Australian National University
11  * makes no representations about the suitability of this software for
12  * any purpose.
13  *
14  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
18  * OF SUCH DAMAGE.
19  *
20  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25  * OR MODIFICATIONS.
26  */
27
28 #ifndef lint
29 static char rcsid[] = "$Id: sys-svr4.c,v 1.8 1995/12/11 05:18:39 paulus Exp $";
30 #endif
31
32 #include <limits.h>
33 #include <stdio.h>
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <alloca.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <termios.h>
42 #ifndef CRTSCTS
43 #include <sys/termiox.h>
44 #endif
45 #include <signal.h>
46 #include <utmpx.h>
47 #include <sys/types.h>
48 #include <sys/ioccom.h>
49 #include <sys/stream.h>
50 #include <sys/stropts.h>
51 #include <sys/socket.h>
52 #include <sys/sockio.h>
53 #include <sys/syslog.h>
54 #include <sys/sysmacros.h>
55 #include <sys/systeminfo.h>
56 #include <sys/dlpi.h>
57 #include <sys/stat.h>
58 #include <sys/mkdev.h>
59 #include <net/if.h>
60 #include <net/if_arp.h>
61 #include <net/route.h>
62 #include <net/ppp_defs.h>
63 #include <net/pppio.h>
64 #include <netinet/in.h>
65
66 #include "pppd.h"
67
68 static int      pppfd;
69 static int      fdmuxid = -1;
70 static int      ipfd;
71 static int      ipmuxid = -1;
72
73 static int      restore_term;
74 static struct termios inittermios;
75 #ifndef CRTSCTS
76 static struct termiox inittermiox;
77 #endif
78 static struct winsize wsinfo;   /* Initial window size info */
79 static pid_t    tty_sid;        /* original session ID for terminal */
80
81 static int      link_mtu, link_mru;
82
83 #define NMODULES        32
84 static int      tty_nmodules;
85 static char     tty_modules[NMODULES][FMNAMESZ+1];
86
87 static int      if_is_up;       /* Interface has been marked up */
88 static u_int32_t default_route_gateway; /* Gateway for default route added */
89 static u_int32_t proxy_arp_addr;        /* Addr for proxy arp entry added */
90
91 /* Prototypes for procedures local to this file. */
92 static int translate_speed __P((int));
93 static int baud_rate_of __P((int));
94 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
95 static int get_hw_addr __P((char *, struct sockaddr *));
96 static int dlpi_attach __P((int, int));
97 static int dlpi_info_req __P((int));
98 static int dlpi_get_reply __P((int, union DL_primitives *, int, int));
99 static int strioctl __P((int, int, void *, int, int));
100
101 /*
102  * sys_init - System-dependent initialization.
103  */
104 void
105 sys_init()
106 {
107     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
108     setlogmask(LOG_UPTO(LOG_INFO));
109     if (debug)
110         setlogmask(LOG_UPTO(LOG_DEBUG));
111
112     ipfd = open("/dev/ip", O_RDWR, 0);
113     if (ipfd < 0) {
114         syslog(LOG_ERR, "Couldn't open IP device: %m");
115         die(1);
116     }
117 }
118
119 /*
120  * sys_cleanup - restore any system state we modified before exiting:
121  * mark the interface down, delete default route and/or proxy arp entry.
122  * This should call die() because it's called from die().
123  */
124 void
125 sys_cleanup()
126 {
127     struct ifreq ifr;
128
129     if (if_is_up)
130         sifdown(0);
131     if (default_route_gateway)
132         cifdefaultroute(0, default_route_gateway);
133     if (proxy_arp_addr)
134         cifproxyarp(0, proxy_arp_addr);
135 }
136
137 /*
138  * daemon - Detach us from controlling terminal session.
139  */
140 int
141 daemon(nochdir, noclose)
142     int nochdir, noclose;
143 {
144     int pid;
145
146     if ((pid = fork()) < 0)
147         return -1;
148     if (pid != 0)
149         exit(0);                /* parent dies */
150     setsid();
151     if (!nochdir)
152         chdir("/");
153     if (!noclose) {
154         fclose(stdin);          /* don't need stdin, stdout, stderr */
155         fclose(stdout);
156         fclose(stderr);
157     }
158     return 0;
159 }
160
161 /*
162  * note_debug_level - note a change in the debug level.
163  */
164 void
165 note_debug_level()
166 {
167     if (debug) {
168         syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
169         setlogmask(LOG_UPTO(LOG_DEBUG));
170     } else {
171         setlogmask(LOG_UPTO(LOG_WARNING));
172     }
173 }
174
175 /*
176  * ppp_available - check whether the system has any ppp interfaces
177  */
178 int
179 ppp_available()
180 {
181     struct stat buf;
182
183     return stat("/dev/ppp", &buf) >= 0;
184 }
185
186 /*
187  * establish_ppp - Turn the serial port into a ppp interface.
188  */
189 void
190 establish_ppp()
191 {
192     int i, ifd, x;
193 #ifndef sun
194     struct ifreq ifr;
195     struct {
196         union DL_primitives prim;
197         char space[64];
198     } reply;
199 #endif
200
201     if (default_device)
202         tty_sid = getsid((pid_t)0);
203
204     pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
205     if (pppfd < 0) {
206         syslog(LOG_ERR, "Can't open /dev/ppp: %m");
207         die(1);
208     }
209     if (kdebugflag) {
210         x = PPPDBG_LOG + PPPDBG_DRIVER;
211         strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
212     }
213
214     /* Assign a new PPA and get its unit number. */
215     if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
216         syslog(LOG_ERR, "Can't create new PPP interface: %m");
217         die(1);
218     }
219
220     /*
221      * Open the ppp device again and link it under the ip multiplexor.
222      * IP will assign a unit number which hopefully is the same as ifunit.
223      * I don't know any way to be certain they will be the same. :-(
224      */
225     ifd = open("/dev/ppp", O_RDWR, 0);
226     if (ifd < 0) {
227         syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
228         die(1);
229     }
230     if (kdebugflag) {
231         x = PPPDBG_LOG + PPPDBG_DRIVER;
232         strioctl(ifd, PPPIO_DEBUG, &x, sizeof(int), 0);
233     }
234 #ifdef sun
235     if (ioctl(ifd, I_PUSH, "ip") < 0) {
236         syslog(LOG_ERR, "Can't push IP module: %m");
237         close(ifd);
238         die(1);
239     }
240 #else
241     if (dlpi_attach(ifd, ifunit) < 0 ||
242         dlpi_get_reply(ifd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0) {
243         syslog(LOG_ERR, "Can't attach to ppp%d: %m", ifunit);
244         close(ifd);
245         die(1);
246     }
247 #endif
248     ipmuxid = ioctl(ipfd, I_LINK, ifd);
249     close(ifd);
250     if (ipmuxid < 0) {
251         syslog(LOG_ERR, "Can't link PPP device to IP: %m");
252         die(1);
253     }
254
255 #ifndef sun
256     /* Set the interface name for the link. */
257     (void) sprintf (ifr.ifr_name, "ppp%d", ifunit);
258     ifr.ifr_metric = ipmuxid;
259     if (strioctl(ipfd, SIOCSIFNAME, (char *)&ifr, sizeof ifr, 0) < 0) {
260         syslog(LOG_ERR, "Can't set interface name %s: %m", ifr.ifr_name);
261         die(1);
262     }
263 #endif
264
265     /* Pop any existing modules off the tty stream. */
266     for (i = 0;; ++i)
267         if (ioctl(fd, I_LOOK, tty_modules[i]) < 0
268             || ioctl(fd, I_POP, 0) < 0)
269             break;
270     tty_nmodules = i;
271
272     /* Push the async hdlc module and the compressor module. */
273     if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) {
274         syslog(LOG_ERR, "Couldn't push PPP Async HDLC module: %m");
275         die(1);
276     }
277     if (ioctl(fd, I_PUSH, "ppp_comp") < 0) {
278         syslog(LOG_ERR, "Couldn't push PPP compression module: %m");
279 /*      die(1); */
280     }
281
282     /* Link the serial port under the PPP multiplexor. */
283     if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) {
284         syslog(LOG_ERR, "Can't link tty to PPP mux: %m");
285         die(1);
286     }
287 }
288
289 /*
290  * disestablish_ppp - Restore the serial port to normal operation.
291  * This shouldn't call die() because it's called from die().
292  */
293 void
294 disestablish_ppp()
295 {
296     int i;
297
298     if (ipmuxid > 0) {
299         if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
300             if (!hungup)
301                 syslog(LOG_ERR, "Can't unlink PPP from IP: %m");
302         }
303     }
304
305     if (fdmuxid >= 0) {
306         if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) {
307             if (!hungup)
308                 syslog(LOG_ERR, "Can't unlink tty from PPP mux: %m");
309         }
310         fdmuxid = -1;
311
312         if (!hungup) {
313             while (ioctl(fd, I_POP, 0) >= 0)
314                 ;
315             for (i = tty_nmodules - 1; i >= 0; --i)
316                 if (ioctl(fd, I_PUSH, tty_modules[i]) < 0)
317                     syslog(LOG_ERR, "Couldn't restore tty module %s: %m",
318                            tty_modules[i]);
319         }
320         if (hungup && default_device && tty_sid > 0) {
321             /*
322              * If we have received a hangup, we need to send a SIGHUP
323              * to the terminal's controlling process.  The reason is
324              * that the original stream head for the terminal hasn't
325              * seen the M_HANGUP message (it went up through the ppp
326              * driver to the stream head for our fd to /dev/ppp).
327              */
328             kill(tty_sid, SIGHUP);
329         }
330     }
331 }
332
333 /*
334  * List of valid speeds.
335  */
336 struct speed {
337     int speed_int, speed_val;
338 } speeds[] = {
339 #ifdef B50
340     { 50, B50 },
341 #endif
342 #ifdef B75
343     { 75, B75 },
344 #endif
345 #ifdef B110
346     { 110, B110 },
347 #endif
348 #ifdef B134
349     { 134, B134 },
350 #endif
351 #ifdef B150
352     { 150, B150 },
353 #endif
354 #ifdef B200
355     { 200, B200 },
356 #endif
357 #ifdef B300
358     { 300, B300 },
359 #endif
360 #ifdef B600
361     { 600, B600 },
362 #endif
363 #ifdef B1200
364     { 1200, B1200 },
365 #endif
366 #ifdef B1800
367     { 1800, B1800 },
368 #endif
369 #ifdef B2000
370     { 2000, B2000 },
371 #endif
372 #ifdef B2400
373     { 2400, B2400 },
374 #endif
375 #ifdef B3600
376     { 3600, B3600 },
377 #endif
378 #ifdef B4800
379     { 4800, B4800 },
380 #endif
381 #ifdef B7200
382     { 7200, B7200 },
383 #endif
384 #ifdef B9600
385     { 9600, B9600 },
386 #endif
387 #ifdef B19200
388     { 19200, B19200 },
389 #endif
390 #ifdef B38400
391     { 38400, B38400 },
392 #endif
393 #ifdef EXTA
394     { 19200, EXTA },
395 #endif
396 #ifdef EXTB
397     { 38400, EXTB },
398 #endif
399 #ifdef B57600
400     { 57600, B57600 },
401 #endif
402 #ifdef B115200
403     { 115200, B115200 },
404 #endif
405     { 0, 0 }
406 };
407
408 /*
409  * Translate from bits/second to a speed_t.
410  */
411 static int
412 translate_speed(bps)
413     int bps;
414 {
415     struct speed *speedp;
416
417     if (bps == 0)
418         return 0;
419     for (speedp = speeds; speedp->speed_int; speedp++)
420         if (bps == speedp->speed_int)
421             return speedp->speed_val;
422     syslog(LOG_WARNING, "speed %d not supported", bps);
423     return 0;
424 }
425
426 /*
427  * Translate from a speed_t to bits/second.
428  */
429 static int
430 baud_rate_of(speed)
431     int speed;
432 {
433     struct speed *speedp;
434
435     if (speed == 0)
436         return 0;
437     for (speedp = speeds; speedp->speed_int; speedp++)
438         if (speed == speedp->speed_val)
439             return speedp->speed_int;
440     return 0;
441 }
442
443 /*
444  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
445  * at the requested speed, etc.  If `local' is true, set CLOCAL
446  * regardless of whether the modem option was specified.
447  */
448 void
449 set_up_tty(fd, local)
450     int fd, local;
451 {
452     int speed;
453     struct termios tios;
454 #if !defined (CRTSCTS)
455     struct termiox tiox;
456 #endif
457
458     if (tcgetattr(fd, &tios) < 0) {
459         syslog(LOG_ERR, "tcgetattr: %m");
460         die(1);
461     }
462
463 #ifndef CRTSCTS
464     if (ioctl (fd, TCGETX, &tiox) < 0) {
465         syslog (LOG_ERR, "TCGETX: %m");
466         die (1);
467     }
468 #endif
469
470     if (!restore_term) {
471         inittermios = tios;
472 #ifndef CRTSCTS
473         inittermiox = tiox;
474 #endif
475         ioctl(fd, TIOCGWINSZ, &wsinfo);
476     }
477
478     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
479 #ifdef CRTSCTS
480     if (crtscts > 0)
481         tios.c_cflag |= CRTSCTS;
482     else if (crtscts < 0)
483         tios.c_cflag &= ~CRTSCTS;
484 #else
485     if (crtscts > 0) {
486         tiox.x_hflag |= RTSXOFF|CTSXON;
487     }
488     else if (crtscts < 0) {
489         tiox.x_hflag &= ~(RTSXOFF|CTSXON);
490     }
491 #endif
492
493     tios.c_cflag |= CS8 | CREAD | HUPCL;
494     if (local || !modem)
495         tios.c_cflag |= CLOCAL;
496     tios.c_iflag = IGNBRK | IGNPAR;
497     tios.c_oflag = 0;
498     tios.c_lflag = 0;
499     tios.c_cc[VMIN] = 1;
500     tios.c_cc[VTIME] = 0;
501
502     if (crtscts == -2) {
503         tios.c_iflag |= IXON | IXOFF;
504         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
505         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
506     }
507
508     speed = translate_speed(inspeed);
509     if (speed) {
510         cfsetospeed(&tios, speed);
511         cfsetispeed(&tios, speed);
512     } else {
513         speed = cfgetospeed(&tios);
514         /*
515          * We can't proceed if the serial port speed is 0,
516          * since that implies that the serial port is disabled.
517          */
518         if (speed == B0) {
519             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
520                    devnam);
521             die(1);
522         }
523     }
524
525     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
526         syslog(LOG_ERR, "tcsetattr: %m");
527         die(1);
528     }
529
530 #ifndef CRTSCTS
531     if (ioctl (fd, TCSETXF, &tiox) < 0){
532         syslog (LOG_ERR, "TCSETXF: %m");
533         die (1);
534     }
535 #endif
536
537     baud_rate = inspeed = baud_rate_of(speed);
538     restore_term = 1;
539 }
540
541 /*
542  * restore_tty - restore the terminal to the saved settings.
543  */
544 void
545 restore_tty()
546 {
547     if (restore_term) {
548         if (!default_device) {
549             /*
550              * Turn off echoing, because otherwise we can get into
551              * a loop with the tty and the modem echoing to each other.
552              * We presume we are the sole user of this tty device, so
553              * when we close it, it will revert to its defaults anyway.
554              */
555             inittermios.c_lflag &= ~(ECHO | ECHONL);
556         }
557         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
558             if (!hungup && errno != ENXIO)
559                 syslog(LOG_WARNING, "tcsetattr: %m");
560 #ifndef CRTSCTS
561         if (ioctl (fd, TCSETXF, &inittermiox) < 0){
562             if (!hungup && errno != ENXIO)
563                 syslog (LOG_ERR, "TCSETXF: %m");
564         }
565 #endif
566         ioctl(fd, TIOCSWINSZ, &wsinfo);
567         restore_term = 0;
568     }
569 }
570
571 /*
572  * setdtr - control the DTR line on the serial port.
573  * This is called from die(), so it shouldn't call die().
574  */
575 void
576 setdtr(fd, on)
577 int fd, on;
578 {
579     int modembits = TIOCM_DTR;
580
581     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
582 }
583
584 /*
585  * output - Output PPP packet.
586  */
587 void
588 output(unit, p, len)
589     int unit;
590     u_char *p;
591     int len;
592 {
593     struct strbuf data;
594     int retries;
595     struct pollfd pfd;
596
597     if (debug)
598         log_packet(p, len, "sent ");
599
600     data.len = len;
601     data.buf = (caddr_t) p;
602     retries = 4;
603     while (putmsg(pppfd, NULL, &data, 0) < 0) {
604         if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
605             if (errno != ENXIO)
606                 syslog(LOG_ERR, "Couldn't send packet: %m");
607             break;
608         }
609         pfd.fd = fd;
610         pfd.events = POLLOUT;
611         poll(&pfd, 1, 250);     /* wait for up to 0.25 seconds */
612     }
613 }
614
615 /*
616  * wait_input - wait until there is data available on fd,
617  * for the length of time specified by *timo (indefinite
618  * if timo is NULL).
619  */
620 void
621 wait_input(timo)
622     struct timeval *timo;
623 {
624     int t;
625     struct pollfd pfd;
626
627     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
628     pfd.fd = pppfd;
629     pfd.events = POLLIN | POLLPRI | POLLHUP;
630     if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
631         syslog(LOG_ERR, "poll: %m");
632         die(1);
633     }
634 }
635
636 /*
637  * read_packet - get a PPP packet from the serial device.
638  */
639 int
640 read_packet(buf)
641     u_char *buf;
642 {
643     struct strbuf ctrl, data;
644     int flags, len;
645     unsigned char ctrlbuf[sizeof(union DL_primitives) + 64];
646
647     for (;;) {
648         data.maxlen = PPP_MRU + PPP_HDRLEN;
649         data.buf = (caddr_t) buf;
650         ctrl.maxlen = sizeof(ctrlbuf);
651         ctrl.buf = (caddr_t) ctrlbuf;
652         flags = 0;
653         len = getmsg(pppfd, &ctrl, &data, &flags);
654         if (len < 0) {
655             if (errno = EAGAIN || errno == EINTR)
656                 return -1;
657             syslog(LOG_ERR, "Error reading packet: %m");
658             die(1);
659         }
660
661         if (ctrl.len <= 0)
662             return data.len;
663
664         /*
665          * Got a M_PROTO or M_PCPROTO message.  Interpret it
666          * as a DLPI primitive.
667          */
668         if (debug)
669             syslog(LOG_DEBUG, "got dlpi prim 0x%x, len=%d",
670                    ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len);
671
672     }
673 }
674
675 /*
676  * ppp_send_config - configure the transmit characteristics of
677  * the ppp interface.
678  */
679 void
680 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
681     int unit, mtu;
682     u_int32_t asyncmap;
683     int pcomp, accomp;
684 {
685     int cf[2];
686
687     link_mtu = mtu;
688     if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
689         if (hungup && errno == ENXIO)
690             return;
691         syslog(LOG_ERR, "Couldn't set MTU: %m");
692     }
693     if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
694         syslog(LOG_ERR, "Couldn't set transmit ACCM: %m");
695     }
696     cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
697     cf[1] = COMP_PROT | COMP_AC;
698     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
699         syslog(LOG_ERR, "Couldn't set prot/AC compression: %m");
700     }
701 }
702
703 /*
704  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
705  */
706 void
707 ppp_set_xaccm(unit, accm)
708     int unit;
709     ext_accm accm;
710 {
711     if (strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
712         if (!hungup || errno != ENXIO)
713             syslog(LOG_WARNING, "Couldn't set extended ACCM: %m");
714     }
715 }
716
717 /*
718  * ppp_recv_config - configure the receive-side characteristics of
719  * the ppp interface.
720  */
721 void
722 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
723     int unit, mru;
724     u_int32_t asyncmap;
725     int pcomp, accomp;
726 {
727     int cf[2];
728
729     link_mru = mru;
730     if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
731         if (hungup && errno == ENXIO)
732             return;
733         syslog(LOG_ERR, "Couldn't set MRU: %m");
734     }
735     if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
736         syslog(LOG_ERR, "Couldn't set receive ACCM: %m");
737     }
738     cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
739     cf[1] = DECOMP_PROT | DECOMP_AC;
740     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
741         syslog(LOG_ERR, "Couldn't set prot/AC decompression: %m");
742     }
743 }
744
745 /*
746  * ccp_test - ask kernel whether a given compression method
747  * is acceptable for use.
748  */
749 int
750 ccp_test(unit, opt_ptr, opt_len, for_transmit)
751     int unit, opt_len, for_transmit;
752     u_char *opt_ptr;
753 {
754     if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
755                  opt_ptr, opt_len, 0) >= 0)
756         return 1;
757     return (errno == ENOSR)? 0: -1;
758 }
759
760 /*
761  * ccp_flags_set - inform kernel about the current state of CCP.
762  */
763 void
764 ccp_flags_set(unit, isopen, isup)
765     int unit, isopen, isup;
766 {
767     int cf[2];
768
769     cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
770     cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
771     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
772         if (!hungup || errno != ENXIO)
773             syslog(LOG_ERR, "Couldn't set kernel CCP state: %m");
774     }
775 }
776
777 /*
778  * ccp_fatal_error - returns 1 if decompression was disabled as a
779  * result of an error detected after decompression of a packet,
780  * 0 otherwise.  This is necessary because of patent nonsense.
781  */
782 int
783 ccp_fatal_error(unit)
784     int unit;
785 {
786     int cf[2];
787
788     cf[0] = cf[1] = 0;
789     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
790         if (errno != ENXIO && errno != EINVAL)
791             syslog(LOG_ERR, "Couldn't get compression flags: %m");
792         return 0;
793     }
794     return cf[0] & CCP_FATALERROR;
795 }
796
797 /*
798  * sifvjcomp - config tcp header compression
799  */
800 int
801 sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
802     int u, vjcomp, xcidcomp, xmaxcid;
803 {
804     int cf[2];
805     char maxcid[2];
806
807     if (vjcomp) {
808         maxcid[0] = xcidcomp;
809         maxcid[1] = 15;         /* XXX should be rmaxcid */
810         if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
811             syslog(LOG_ERR, "Couldn't initialize VJ compression: %m");
812         }
813     }
814
815     cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)  /* XXX this is wrong */
816         + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
817     cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
818     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
819         if (vjcomp)
820             syslog(LOG_ERR, "Couldn't enable VJ compression: %m");
821     }
822
823     return 1;
824 }
825
826 /*
827  * sifup - Config the interface up and enable IP packets to pass.
828  */
829 int
830 sifup(u)
831     int u;
832 {
833     struct ifreq ifr;
834
835     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
836     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
837         syslog(LOG_ERR, "Couldn't mark interface up (get): %m");
838         return 0;
839     }
840     ifr.ifr_flags |= IFF_UP;
841     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
842         syslog(LOG_ERR, "Couldn't mark interface up (set): %m");
843         return 0;
844     }
845     if_is_up = 1;
846     return 1;
847 }
848
849 /*
850  * sifdown - Config the interface down and disable IP.
851  */
852 int
853 sifdown(u)
854     int u;
855 {
856     struct ifreq ifr;
857
858     if (ipmuxid < 0)
859         return 1;
860     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
861     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
862         syslog(LOG_ERR, "Couldn't mark interface down (get): %m");
863         return 0;
864     }
865     ifr.ifr_flags &= ~IFF_UP;
866     if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
867         syslog(LOG_ERR, "Couldn't mark interface down (set): %m");
868         return 0;
869     }
870     if_is_up = 0;
871     return 1;
872 }
873
874 #define INET_ADDR(x)    (((struct sockaddr_in *) &(x))->sin_addr.s_addr)
875
876 /*
877  * sifaddr - Config the interface IP addresses and netmask.
878  */
879 int
880 sifaddr(u, o, h, m)
881     int u;
882     u_int32_t o, h, m;
883 {
884     struct ifreq ifr;
885
886     memset(&ifr, 0, sizeof(ifr));
887     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
888     ifr.ifr_addr.sa_family = AF_INET;
889     INET_ADDR(ifr.ifr_addr) = o;
890     if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
891         syslog(LOG_ERR, "Couldn't set local IP address: %m");
892     }
893     ifr.ifr_dstaddr.sa_family = AF_INET;
894     INET_ADDR(ifr.ifr_dstaddr) = h;
895     if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
896         syslog(LOG_ERR, "Couldn't set remote IP address: %m");
897     }
898     ifr.ifr_addr.sa_family = AF_INET;
899     INET_ADDR(ifr.ifr_addr) = m;
900     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
901         syslog(LOG_ERR, "Couldn't set IP netmask: %m");
902     }
903     ifr.ifr_metric = link_mtu;
904     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
905         syslog(LOG_ERR, "Couldn't set IP MTU: %m");
906     }
907
908     return 1;
909 }
910
911 /*
912  * cifaddr - Clear the interface IP addresses, and delete routes
913  * through the interface if possible.
914  */
915 int
916 cifaddr(u, o, h)
917     int u;
918     u_int32_t o, h;
919 {
920 #if 0
921     if (ipmuxid >= 0) {
922         if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
923             syslog(LOG_ERR, "Can't remove ppp interface unit: %m");
924             return 0;
925         }
926         ipmuxid = -1;
927     }
928 #endif
929     return 1;
930 }
931
932 /*
933  * sifdefaultroute - assign a default route through the address given.
934  */
935 int
936 sifdefaultroute(u, g)
937     int u;
938     u_int32_t g;
939 {
940     struct rtentry rt;
941
942     rt.rt_dst.sa_family = AF_INET;
943     INET_ADDR(rt.rt_dst) = 0;
944     rt.rt_gateway.sa_family = AF_INET;
945     INET_ADDR(rt.rt_gateway) = g;
946     rt.rt_flags = RTF_GATEWAY;
947
948     if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
949         syslog(LOG_ERR, "Can't add default route: %m");
950         return 0;
951     }
952
953     default_route_gateway = g;
954     return 1;
955 }
956
957 /*
958  * cifdefaultroute - delete a default route through the address given.
959  */
960 int
961 cifdefaultroute(u, g)
962     int u;
963     u_int32_t g;
964 {
965     struct rtentry rt;
966
967     rt.rt_dst.sa_family = AF_INET;
968     INET_ADDR(rt.rt_dst) = 0;
969     rt.rt_gateway.sa_family = AF_INET;
970     INET_ADDR(rt.rt_gateway) = g;
971     rt.rt_flags = RTF_GATEWAY;
972
973     if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
974         syslog(LOG_ERR, "Can't delete default route: %m");
975         return 0;
976     }
977
978     default_route_gateway = 0;
979     return 1;
980 }
981
982 /*
983  * sifproxyarp - Make a proxy ARP entry for the peer.
984  */
985 int
986 sifproxyarp(unit, hisaddr)
987     int unit;
988     u_int32_t hisaddr;
989 {
990     struct arpreq arpreq;
991
992     memset(&arpreq, 0, sizeof(arpreq));
993     if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
994         return 0;
995
996     arpreq.arp_pa.sa_family = AF_INET;
997     INET_ADDR(arpreq.arp_pa) = hisaddr;
998     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
999     if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
1000         syslog(LOG_ERR, "Couldn't set proxy ARP entry: %m");
1001         return 0;
1002     }
1003
1004     proxy_arp_addr = hisaddr;
1005     return 1;
1006 }
1007
1008 /*
1009  * cifproxyarp - Delete the proxy ARP entry for the peer.
1010  */
1011 int
1012 cifproxyarp(unit, hisaddr)
1013     int unit;
1014     u_int32_t hisaddr;
1015 {
1016     struct arpreq arpreq;
1017
1018     memset(&arpreq, 0, sizeof(arpreq));
1019     arpreq.arp_pa.sa_family = AF_INET;
1020     INET_ADDR(arpreq.arp_pa) = hisaddr;
1021     if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1022         syslog(LOG_ERR, "Couldn't delete proxy ARP entry: %m");
1023         return 0;
1024     }
1025
1026     proxy_arp_addr = 0;
1027     return 1;
1028 }
1029
1030 /*
1031  * get_ether_addr - get the hardware address of an interface on the
1032  * the same subnet as ipaddr.
1033  */
1034 #define MAX_IFS         32
1035
1036 static int
1037 get_ether_addr(ipaddr, hwaddr)
1038     u_int32_t ipaddr;
1039     struct sockaddr *hwaddr;
1040 {
1041     struct ifreq *ifr, *ifend, ifreq;
1042     int nif;
1043     struct ifconf ifc;
1044     u_int32_t ina, mask;
1045
1046     /*
1047      * Scan through the system's network interfaces.
1048      */
1049 #ifdef SIOCGIFNUM
1050     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
1051 #endif
1052         nif = MAX_IFS;
1053     ifc.ifc_len = nif * sizeof(struct ifreq);
1054     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
1055     if (ifc.ifc_req == 0)
1056         return 0;
1057     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
1058         syslog(LOG_WARNING, "Couldn't get system interface list: %m");
1059         return 0;
1060     }
1061     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1062     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1063         if (ifr->ifr_addr.sa_family != AF_INET)
1064             continue;
1065         /*
1066          * Check that the interface is up, and not point-to-point or loopback.
1067          */
1068         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1069         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
1070             continue;
1071         if ((ifreq.ifr_flags &
1072              (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1073             != (IFF_UP|IFF_BROADCAST))
1074             continue;
1075         /*
1076          * Get its netmask and check that it's on the right subnet.
1077          */
1078         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
1079             continue;
1080         ina = INET_ADDR(ifr->ifr_addr);
1081         mask = INET_ADDR(ifreq.ifr_addr);
1082         if ((ipaddr & mask) == (ina & mask))
1083             break;
1084     }
1085
1086     if (ifr >= ifend) {
1087         syslog(LOG_WARNING, "No suitable interface found for proxy ARP");
1088         return 0;
1089     }
1090
1091     syslog(LOG_INFO, "found interface %s for proxy ARP", ifr->ifr_name);
1092     if (!get_hw_addr(ifr->ifr_name, hwaddr)) {
1093         syslog(LOG_ERR, "Couldn't get hardware address for %s", ifr->ifr_name);
1094         return 0;
1095     }
1096
1097     return 1;
1098 }
1099
1100 /*
1101  * get_hw_addr - obtain the hardware address for a named interface.
1102  */
1103 static int
1104 get_hw_addr(name, hwaddr)
1105     char *name;
1106     struct sockaddr *hwaddr;
1107 {
1108     char *p, *q;
1109     int unit, iffd, adrlen;
1110     unsigned char *adrp;
1111     char ifdev[24];
1112     struct {
1113         union DL_primitives prim;
1114         char space[64];
1115     } reply;
1116
1117     /*
1118      * We have to open the device and ask it for its hardware address.
1119      * First split apart the device name and unit.
1120      */
1121     strcpy(ifdev, "/dev/");
1122     q = ifdev + 5;              /* strlen("/dev/") */
1123     while (*name != 0 && !isdigit(*name))
1124         *q++ = *name++;
1125     *q = 0;
1126     unit = atoi(name);
1127
1128     /*
1129      * Open the device and do a DLPI attach and phys_addr_req.
1130      */
1131     iffd = open(ifdev, O_RDWR);
1132     if (iffd < 0) {
1133         syslog(LOG_ERR, "Can't open %s: %m", ifdev);
1134         return 0;
1135     }
1136     if (dlpi_attach(iffd, unit) < 0
1137         || dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
1138         || dlpi_info_req(iffd) < 0
1139         || dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) {
1140         close(iffd);
1141         return 0;
1142     }
1143
1144     adrlen = reply.prim.info_ack.dl_addr_length;
1145     adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;
1146 #if DL_CURRENT_VERSION >= 2
1147     if (reply.prim.info_ack.dl_sap_length < 0)
1148         adrlen += reply.prim.info_ack.dl_sap_length;
1149     else
1150         adrp += reply.prim.info_ack.dl_sap_length;
1151 #endif
1152     hwaddr->sa_family = AF_UNSPEC;
1153     memcpy(hwaddr->sa_data, adrp, adrlen);
1154
1155     return 1;
1156 }
1157
1158 static int
1159 dlpi_attach(fd, ppa)
1160     int fd, ppa;
1161 {
1162     dl_attach_req_t req;
1163     struct strbuf buf;
1164
1165     req.dl_primitive = DL_ATTACH_REQ;
1166     req.dl_ppa = ppa;
1167     buf.len = sizeof(req);
1168     buf.buf = (void *) &req;
1169     return putmsg(fd, &buf, NULL, RS_HIPRI);
1170 }
1171
1172 static int
1173 dlpi_info_req(fd)
1174     int fd;
1175 {
1176     dl_info_req_t req;
1177     struct strbuf buf;
1178
1179     req.dl_primitive = DL_INFO_REQ;
1180     buf.len = sizeof(req);
1181     buf.buf = (void *) &req;
1182     return putmsg(fd, &buf, NULL, RS_HIPRI);
1183 }
1184
1185 static int
1186 dlpi_get_reply(fd, reply, expected_prim, maxlen)
1187     union DL_primitives *reply;
1188     int fd, expected_prim, maxlen;
1189 {
1190     struct strbuf buf;
1191     int flags, n;
1192     struct pollfd pfd;
1193
1194     /*
1195      * Use poll to wait for a message with a timeout.
1196      */
1197     pfd.fd = fd;
1198     pfd.events = POLLIN | POLLPRI;
1199     do {
1200         n = poll(&pfd, 1, 1000);
1201     } while (n == -1 && errno == EINTR);
1202     if (n <= 0)
1203         return -1;
1204
1205     /*
1206      * Get the reply.
1207      */
1208     buf.maxlen = maxlen;
1209     buf.buf = (void *) reply;
1210     flags = 0;
1211     if (getmsg(fd, &buf, NULL, &flags) < 0)
1212         return -1;
1213
1214     if (buf.len < sizeof(ulong)) {
1215         if (debug)
1216             syslog(LOG_DEBUG, "dlpi response short (len=%d)\n", buf.len);
1217         return -1;
1218     }
1219
1220     if (reply->dl_primitive == expected_prim)
1221         return 0;
1222
1223     if (debug) {
1224         if (reply->dl_primitive == DL_ERROR_ACK) {
1225             syslog(LOG_DEBUG, "dlpi error %d (unix errno %d) for prim %x\n",
1226                    reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
1227                    reply->error_ack.dl_error_primitive);
1228         } else {
1229             syslog(LOG_DEBUG, "dlpi unexpected response prim %x\n",
1230                    reply->dl_primitive);
1231         }
1232     }
1233
1234     return -1;
1235 }
1236
1237 /*
1238  * Return user specified netmask, modified by any mask we might determine
1239  * for address `addr' (in network byte order).
1240  * Here we scan through the system's list of interfaces, looking for
1241  * any non-point-to-point interfaces which might appear to be on the same
1242  * network as `addr'.  If we find any, we OR in their netmask to the
1243  * user-specified netmask.
1244  */
1245 u_int32_t
1246 GetMask(addr)
1247     u_int32_t addr;
1248 {
1249     u_int32_t mask, nmask, ina;
1250     struct ifreq *ifr, *ifend, ifreq;
1251     int nif;
1252     struct ifconf ifc;
1253
1254     addr = ntohl(addr);
1255     if (IN_CLASSA(addr))        /* determine network mask for address class */
1256         nmask = IN_CLASSA_NET;
1257     else if (IN_CLASSB(addr))
1258         nmask = IN_CLASSB_NET;
1259     else
1260         nmask = IN_CLASSC_NET;
1261     /* class D nets are disallowed by bad_ip_adrs */
1262     mask = netmask | htonl(nmask);
1263
1264     /*
1265      * Scan through the system's network interfaces.
1266      */
1267 #ifdef SIOCGIFNUM
1268     if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
1269 #endif
1270         nif = MAX_IFS;
1271     ifc.ifc_len = nif * sizeof(struct ifreq);
1272     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
1273     if (ifc.ifc_req == 0)
1274         return mask;
1275     if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
1276         syslog(LOG_WARNING, "Couldn't get system interface list: %m");
1277         return mask;
1278     }
1279     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1280     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1281         /*
1282          * Check the interface's internet address.
1283          */
1284         if (ifr->ifr_addr.sa_family != AF_INET)
1285             continue;
1286         ina = INET_ADDR(ifr->ifr_addr);
1287         if ((ntohl(ina) & nmask) != (addr & nmask))
1288             continue;
1289         /*
1290          * Check that the interface is up, and not point-to-point or loopback.
1291          */
1292         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1293         if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
1294             continue;
1295         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1296             != IFF_UP)
1297             continue;
1298         /*
1299          * Get its netmask and OR it into our mask.
1300          */
1301         if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
1302             continue;
1303         mask |= INET_ADDR(ifreq.ifr_addr);
1304     }
1305
1306     return mask;
1307 }
1308
1309 /*
1310  * logwtmp - write an accounting record to the /var/adm/wtmp file.
1311  */
1312 int
1313 logwtmp(line, name, host)
1314     char *line, *name, *host;
1315 {
1316     static struct utmpx utmpx;
1317
1318     if (name[0] != 0) {
1319         /* logging in */
1320         strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
1321         strncpy(utmpx.ut_id, ifname, sizeof(utmpx.ut_id));
1322         strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
1323         utmpx.ut_pid = getpid();
1324         utmpx.ut_type = USER_PROCESS;
1325     } else {
1326         utmpx.ut_type = DEAD_PROCESS;
1327     }
1328     gettimeofday(&utmpx.ut_tv, NULL);
1329     updwtmpx("/var/adm/wtmpx", &utmpx);
1330     return 0;
1331 }
1332
1333 /*
1334  * gethostid - return the serial number of this machine.
1335  */
1336 int
1337 gethostid()
1338 {
1339     char buf[32];
1340
1341     if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
1342         syslog(LOG_ERR, "sysinfo: %m");
1343         return 0;
1344     }
1345     return (int) strtoul(buf, NULL, 16);
1346 }
1347
1348 static int
1349 strioctl(fd, cmd, ptr, ilen, olen)
1350     int fd, cmd, ilen, olen;
1351     void *ptr;
1352 {
1353     struct strioctl str;
1354
1355     str.ic_cmd = cmd;
1356     str.ic_timout = 0;
1357     str.ic_len = ilen;
1358     str.ic_dp = ptr;
1359     if (ioctl(fd, I_STR, &str) == -1)
1360         return -1;
1361     if (str.ic_len != olen)
1362         syslog(LOG_DEBUG, "strioctl: expected %d bytes, got %d for cmd %x\n",
1363                olen, str.ic_len, cmd);
1364     return 0;
1365 }
1366
1367 /*
1368  * lock - create a lock file for the named lock device
1369  */
1370
1371 #define LOCK_PREFIX     "/var/spool/locks/LK."
1372 static char lock_file[40];      /* name of lock file created */
1373
1374 int
1375 lock(dev)
1376     char *dev;
1377 {
1378     int n, fd, pid;
1379     struct stat sbuf;
1380     char ascii_pid[12];
1381
1382     if (stat(dev, &sbuf) < 0) {
1383         syslog(LOG_ERR, "Can't get device number for %s: %m", dev);
1384         return -1;
1385     }
1386     if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
1387         syslog(LOG_ERR, "Can't lock %s: not a character device", dev);
1388         return -1;
1389     }
1390     sprintf(lock_file, "%s%03d.%03d.%03d", LOCK_PREFIX, major(sbuf.st_dev),
1391             major(sbuf.st_rdev), minor(sbuf.st_rdev));
1392
1393     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1394         if (errno == EEXIST
1395             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1396             /* Read the lock file to find out who has the device locked */
1397             n = read(fd, ascii_pid, 11);
1398             if (n <= 0) {
1399                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1400                 close(fd);
1401             } else {
1402                 ascii_pid[n] = 0;
1403                 pid = atoi(ascii_pid);
1404                 if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) {
1405                     /* pid no longer exists - remove the lock file */
1406                     if (unlink(lock_file) == 0) {
1407                         close(fd);
1408                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1409                                dev, pid);
1410                         continue;
1411                     } else
1412                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1413                                dev);
1414                 } else
1415                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1416                            dev, pid);
1417             }
1418             close(fd);
1419         } else
1420             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1421         lock_file[0] = 0;
1422         return -1;
1423     }
1424
1425     sprintf(ascii_pid, "%10d\n", getpid());
1426     write(fd, ascii_pid, 11);
1427
1428     close(fd);
1429     return 1;
1430 }
1431
1432 /*
1433  * unlock - remove our lockfile
1434  */
1435 void
1436 unlock()
1437 {
1438     if (lock_file[0]) {
1439         unlink(lock_file);
1440         lock_file[0] = 0;
1441     }
1442 }