]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-osf.c
files added for packet filter expression compilation
[ppp.git] / pppd / sys-osf.c
1 /*
2  * sys-osf.c - System-dependent procedures for setting up
3  * PPP interfaces on OSF/1 systems which use the STREAMS ppp interface.
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 #ifndef lint
22 static char rcsid[] = "$Id: sys-osf.c,v 1.8 1996/04/04 04:06:29 paulus Exp $";
23 #endif
24
25 /*
26  * TODO:
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <syslog.h>
33 #include <termios.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <time.h>
37 #include <utmp.h>
38 #include <poll.h>
39 #include <signal.h>
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/time.h>
43 #include <sys/stream.h>
44 #include <sys/stropts.h>
45
46 #include <net/if.h>
47 #include <net/ppp_defs.h>
48 #include <net/ppp_str.h>
49 #include <net/route.h>
50 #include <net/if_arp.h>
51 #include <netinet/in.h>
52
53 #include "pppd.h"
54
55 #ifndef ifr_mtu
56 #define ifr_mtu         ifr_metric
57 #endif
58
59 #define MAXMODULES      10      /* max number of module names to save */
60 static struct   modlist {
61     char        modname[FMNAMESZ+1];
62 } str_modules[MAXMODULES];
63 static int      str_module_count = 0;
64 static int      pushed_ppp;
65 static int      closed_stdio;
66
67 static int      restore_term;   /* 1 => we've munged the terminal */
68 static struct termios inittermios; /* Initial TTY termios */
69 static struct winsize wsinfo;      /* Initial window size info */
70 static int      initfdflags = -1; /* Initial file descriptor flags for fd */
71
72 static int sockfd;              /* socket for doing interface ioctls */
73
74 int orig_ttyfd = -1;   /*  Original ttyfd if we did a streamify()  */
75
76 static int      if_is_up;       /* Interface has been marked up */
77 static u_int32_t ifaddrs[2];    /* Local and remote addrs we've set */
78 static u_int32_t default_route_gateway; /* Gateway for default route added */
79 static u_int32_t proxy_arp_addr;        /* Addr for proxy arp entry added */
80
81 /* Prototypes for procedures local to this file. */
82 static int translate_speed __P((int));
83 static int baud_rate_of __P((int));
84 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
85
86
87 /*
88  * sys_init - System-dependent initialization.
89  */
90 void
91 sys_init()
92 {
93     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
94     setlogmask(LOG_UPTO(LOG_INFO));
95     if (debug)
96         setlogmask(LOG_UPTO(LOG_DEBUG));
97
98     /* Get an internet socket for doing socket ioctl's on. */
99     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
100         syslog(LOG_ERR, "Couldn't create IP socket: %m");
101         die(1);
102     }
103 }
104
105 /*
106  * sys_cleanup - restore any system state we modified before exiting:
107  * mark the interface down, delete default route and/or proxy arp entry.
108  * This should call die() because it's called from die().
109  */
110 void
111 sys_cleanup()
112 {
113     struct ifreq ifr;
114
115     if (if_is_up) {
116         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
117         if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
118             && ((ifr.ifr_flags & IFF_UP) != 0)) {
119             ifr.ifr_flags &= ~IFF_UP;
120             ioctl(sockfd, SIOCSIFFLAGS, &ifr);
121         }
122     }
123     if (ifaddrs[0])
124         cifaddr(0, ifaddrs[0], ifaddrs[1]);
125     if (default_route_gateway)
126         cifdefaultroute(0, default_route_gateway);
127     if (proxy_arp_addr)
128         cifproxyarp(0, proxy_arp_addr);
129 }
130
131 /*
132  * note_debug_level - note a change in the debug level.
133  */
134 void
135 note_debug_level()
136 {
137     if (debug) {
138         syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
139         setlogmask(LOG_UPTO(LOG_DEBUG));
140     } else {
141         setlogmask(LOG_UPTO(LOG_WARNING));
142     }
143 }
144
145 /*
146  * daemon - Detach us from the terminal session.
147  */
148 int
149 daemon(nochdir, noclose)
150     int nochdir, noclose;
151 {
152     int pid;
153
154     if ((pid = fork()) < 0)
155         return -1;
156     if (pid != 0)
157         exit(0);                /* parent dies */
158     setsid();
159     if (!nochdir)
160         chdir("/");
161     if (!noclose) {
162         fclose(stdin);          /* don't need stdin, stdout, stderr */
163         fclose(stdout);
164         fclose(stderr);
165     }
166     return 0;
167 }
168
169
170 char pipename[] = "/dev/streams/pipe";
171
172 /*
173  * ppp_available - check if this kernel supports PPP.
174  */
175 int
176 ppp_available()
177 {
178     int fd, ret;
179
180     fd = open(pipename, O_RDONLY, 0);
181     if (fd < 0)
182         return 0;               /* can't find out - assume we don't have ppp */
183     ret = ioctl(fd, I_FIND, "pppasync") >= 0;
184     close(fd);
185     return ret;
186 }
187
188
189 /*
190  *  streampipe -- Opens a STREAMS based pipe.  Used by streamify().
191  */
192
193 int 
194 streampipe(int fd[2])
195 {
196     if ((fd[0]=open(pipename, O_RDWR)) == -1)
197         return(-1);
198     else if ((fd[1]=open(pipename, O_RDWR)) == -1) {
199         close(fd[0]);
200         return(-1);
201     } else if (ioctl(fd[0], I_PIPE, fd[1]) != 0) {
202         close(fd[0]);
203         close(fd[1]);
204         return(-1);
205     } else {
206         return(ioctl(fd[0], I_PUSH, "pipemod"));
207     }
208 }
209
210 /*
211  *  streamify -- Needed for DEC OSF/1, since tty devices are not STREAMS
212  *               modules (but ptys are, and pipes can be).
213  */
214
215 #define BUFFSIZE 1000     /*  Size of buffer for streamify()  */
216
217 int 
218 streamify(int fd)
219 {
220     int fdes[2];
221     fd_set readfds;
222     int ret, fret, rret, maxfd;
223     static char buffer[BUFFSIZE];
224     struct sigaction sa;
225
226     if (streampipe(fdes) != 0)
227         syslog(LOG_ERR, "streampipe(): %m\n");
228     else if (isastream(fdes[0]) == 1) {
229         if ((fret=fork()) < 0) {
230             syslog(LOG_ERR, "fork(): %m\n");
231         } else if (fret == 0) {
232             /*  Process to forward things from pipe to tty  */
233             sigemptyset(&(sa.sa_mask));
234             sa.sa_handler = SIG_DFL;
235             sa.sa_flags = 0;
236             sigaction(SIGHUP, &sa, NULL);   /*  Go back to default actions */
237             sigaction(SIGINT, &sa, NULL);   /*  for changed signals.  */
238             sigaction(SIGTERM, &sa, NULL);
239             sigaction(SIGCHLD, &sa, NULL);
240             sigaction(SIGUSR1, &sa, NULL);
241             sigaction(SIGUSR2, &sa, NULL);
242             close(fdes[0]);
243
244             maxfd = (fdes[1]>fd)?fdes[1]:fd;
245             while (1) {
246                 FD_ZERO(&readfds);
247                 FD_SET(fdes[1], &readfds);
248                 FD_SET(fd, &readfds);
249                 ret = select(maxfd+1, &readfds, NULL, NULL, NULL);
250                 if (FD_ISSET(fd, &readfds)) {
251                     rret = read(fd, buffer, BUFFSIZE);
252                     if (rret == 0) {
253                         MAINDEBUG((LOG_DEBUG, "slave died:  EOF on tty."));
254                         exit(0);
255                     } else {
256                         write(fdes[1], buffer, rret);
257                     }
258                 }
259                 if (FD_ISSET(fdes[1], &readfds)) {
260                     rret = read(fdes[1], buffer, BUFFSIZE);
261                     if (rret == 0) {
262                         MAINDEBUG((LOG_DEBUG, "slave died:  EOF on pipe."));
263                         exit(0);
264                     } else {
265                         write(fd, buffer, rret);
266                     }
267                 }
268             }
269         } else {
270             close(fdes[1]);
271             orig_ttyfd = fd;
272             return(fdes[0]);
273         }
274     }
275
276     return(-1);
277 }
278
279
280 /*
281  * establish_ppp - Turn the serial port into a ppp interface.
282  */
283 void
284 establish_ppp(fd)
285     int fd;
286 {
287     int ret;
288
289     if (isastream(fd) != 1) {
290         if ((ttyfd = fd = streamify(fd)) < 0) {
291             syslog(LOG_ERR, "Couldn't get a STREAMS module!\n");
292             die(1);
293         }
294     }
295
296     /* go through and save the name of all the modules, then pop em */
297     for (;;) { 
298         if (ioctl(fd, I_LOOK, str_modules[str_module_count].modname) < 0 ||
299             ioctl(fd, I_POP, 0) < 0)
300             break;
301         MAINDEBUG((LOG_DEBUG, "popped stream module : %s",
302                    str_modules[str_module_count].modname));
303         str_module_count++;
304     }
305
306     /* now push the async/fcs module */
307     if (ioctl(fd, I_PUSH, "pppasync") < 0) {
308         syslog(LOG_ERR, "ioctl(I_PUSH, ppp_async): %m");
309         die(1);
310     }
311     /* push the compress module */
312     if (ioctl(fd, I_PUSH, "pppcomp") < 0) {
313         syslog(LOG_WARNING, "ioctl(I_PUSH, ppp_comp): %m");
314     }
315     /* finally, push the ppp_if module that actually handles the */
316     /* network interface */ 
317     if (ioctl(fd, I_PUSH, "pppif") < 0) {
318         syslog(LOG_ERR, "ioctl(I_PUSH, ppp_if): %m");
319         die(1);
320     }
321     pushed_ppp = 1;
322     /* read mode, message non-discard mode */
323     if (ioctl(fd, I_SRDOPT, RMSGN|RPROTNORM) < 0) {
324         syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m");
325         die(1);
326     }
327     /*
328      * Find out which interface we were given.
329      * (ppp_if handles this ioctl)
330      */
331     if (ioctl(fd, (int)SIOCGETU, &ifunit) < 0) {
332         syslog(LOG_ERR, "ioctl(SIOCGETU): %m");
333         die(1);
334     }
335
336     /* Set debug flags in driver */
337     if (ioctl(fd, (int)SIOCSIFDEBUG, &kdebugflag) < 0) {
338         syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m");
339     }
340
341     /* close stdin, stdout, stderr if they might refer to the device */
342     if (default_device && !closed_stdio) {
343         int i;
344
345         for (i = 0; i <= 2; ++i)
346             if (i != fd && i != sockfd) 
347                 close(i);
348         closed_stdio = 1;
349     }
350
351     /*
352      * Set device for non-blocking reads.
353      */
354     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
355         || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
356         syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
357     }
358 }
359
360 /*  Debugging routine....  */
361
362 void prstrstack(int fd)
363 {
364     struct str_list sl;
365     struct str_mlist names[20];
366     int ret, i;
367
368     sl.sl_modlist = names;
369
370     ret = ioctl(fd, I_LIST, &sl);
371
372     if (ret >= 0) {
373         MAINDEBUG((LOG_DEBUG, "Current streams modules:\n"));
374         for (i=0; i<sl.sl_nmods; i++)
375             MAINDEBUG((LOG_DEBUG,"    %s\n", names[i].l_name));
376     } else {
377         MAINDEBUG((LOG_DEBUG,"I_LIST ioctl() failed.\n"));
378     }
379 }
380
381
382 /*
383  * disestablish_ppp - Restore the serial port to normal operation.
384  * It attempts to reconstruct the stream with the previously popped
385  * modules.  This shouldn't call die() because it's called from die().
386  */
387 void
388 disestablish_ppp(fd)
389     int fd;
390 {
391     int flags;
392     char *s;
393
394     /* Reset non-blocking mode on the file descriptor. */
395     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
396         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
397     initfdflags = -1;
398
399     if (hungup) {
400         /* we can't push or pop modules after the stream has hung up */
401         str_module_count = 0;
402         restore_term = 0;       /* nor can we fix up terminal settings */
403         return;
404     }
405
406     if (pushed_ppp) {
407         while (ioctl(fd, I_POP, 0) == 0) /* pop any we pushed */
408             ;
409         pushed_ppp = 0;
410
411         for (; str_module_count > 0; str_module_count--) {
412             if (ioctl(fd, I_PUSH, str_modules[str_module_count-1].modname)) {
413                 if (errno != ENXIO)
414                     syslog(LOG_WARNING, "str_restore: couldn't push module %s: %m",
415                            str_modules[str_module_count-1].modname);
416             } else {
417                 MAINDEBUG((LOG_INFO, "str_restore: pushed module %s",
418                            str_modules[str_module_count-1].modname));
419             }
420         }
421
422         if (orig_ttyfd >= 0) {
423             close(fd);
424             ttyfd = orig_ttyfd;
425             fd = -1;
426         }
427     }
428
429 }
430
431 /*
432  * clean_check - check whether the link seems to be 8-bit clean.
433  */
434 void
435 clean_check()
436 {
437     if (pushed_ppp) {
438         /*
439          * Check whether the link seems not to be 8-bit clean.
440          */
441         if (ioctl(ttyfd, (int)SIOCGIFDEBUG, (caddr_t) &flags) == 0) {
442             s = NULL;
443             switch (~flags & PAI_FLAGS_HIBITS) {
444               case PAI_FLAGS_B7_0:
445                 s = "bit 7 set to 1";
446                 break;
447               case PAI_FLAGS_B7_1:
448                 s = "bit 7 set to 0";
449                 break;
450               case PAI_FLAGS_PAR_EVEN:
451                 s = "odd parity";
452                 break;
453               case PAI_FLAGS_PAR_ODD:
454                 s = "even parity";
455                 break;
456             }
457             if (s != NULL) {
458                 syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
459                 syslog(LOG_WARNING, "All received characters had %s", s);
460             }
461         }
462     }
463 }
464
465 /*
466  * List of valid speeds.
467  */
468 struct speed {
469     int speed_int, speed_val;
470 } speeds[] = {
471 #ifdef B50
472     { 50, B50 },
473 #endif
474 #ifdef B75
475     { 75, B75 },
476 #endif
477 #ifdef B110
478     { 110, B110 },
479 #endif
480 #ifdef B134
481     { 134, B134 },
482 #endif
483 #ifdef B150
484     { 150, B150 },
485 #endif
486 #ifdef B200
487     { 200, B200 },
488 #endif
489 #ifdef B300
490     { 300, B300 },
491 #endif
492 #ifdef B600
493     { 600, B600 },
494 #endif
495 #ifdef B1200
496     { 1200, B1200 },
497 #endif
498 #ifdef B1800
499     { 1800, B1800 },
500 #endif
501 #ifdef B2000
502     { 2000, B2000 },
503 #endif
504 #ifdef B2400
505     { 2400, B2400 },
506 #endif
507 #ifdef B3600
508     { 3600, B3600 },
509 #endif
510 #ifdef B4800
511     { 4800, B4800 },
512 #endif
513 #ifdef B7200
514     { 7200, B7200 },
515 #endif
516 #ifdef B9600
517     { 9600, B9600 },
518 #endif
519 #ifdef B19200
520     { 19200, B19200 },
521 #endif
522 #ifdef B38400
523     { 38400, B38400 },
524 #endif
525 #ifdef EXTA
526     { 19200, EXTA },
527 #endif
528 #ifdef EXTB
529     { 38400, EXTB },
530 #endif
531 #ifdef B57600
532     { 57600, B57600 },
533 #endif
534 #ifdef B115200
535     { 115200, B115200 },
536 #endif
537     { 0, 0 }
538 };
539
540 /*
541  * Translate from bits/second to a speed_t.
542  */
543 static int
544 translate_speed(bps)
545     int bps;
546 {
547     struct speed *speedp;
548
549     if (bps == 0)
550         return 0;
551     for (speedp = speeds; speedp->speed_int; speedp++)
552         if (bps == speedp->speed_int)
553             return speedp->speed_val;
554     syslog(LOG_WARNING, "speed %d not supported", bps);
555     return 0;
556 }
557
558 /*
559  * Translate from a speed_t to bits/second.
560  */
561 static int
562 baud_rate_of(speed)
563     int speed;
564 {
565     struct speed *speedp;
566
567     if (speed == 0)
568         return 0;
569     for (speedp = speeds; speedp->speed_int; speedp++)
570         if (speed == speedp->speed_val)
571             return speedp->speed_int;
572     return 0;
573 }
574
575 /*
576  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
577  * at the requested speed, etc.  If `local' is true, set CLOCAL
578  * regardless of whether the modem option was specified.
579  */
580 void
581 set_up_tty(fd, local)
582     int fd, local;
583 {
584     int speed;
585     struct termios tios;
586
587     if (tcgetattr(fd, &tios) < 0) {
588         syslog(LOG_ERR, "tcgetattr: %m");
589         die(1);
590     }
591
592     if (!restore_term) {
593         inittermios = tios;
594         ioctl(fd, TIOCGWINSZ, &wsinfo);
595     }
596
597     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
598     if (crtscts > 0)
599         tios.c_cflag |= CRTSCTS;
600     else if (crtscts < 0)
601         tios.c_cflag &= ~CRTSCTS;
602
603     tios.c_cflag |= CS8 | CREAD | HUPCL;
604     if (local || !modem)
605         tios.c_cflag |= CLOCAL;
606     tios.c_iflag = IGNBRK | IGNPAR;
607     tios.c_oflag = 0;
608     tios.c_lflag = 0;
609     tios.c_cc[VMIN] = 1;
610     tios.c_cc[VTIME] = 0;
611
612     if (crtscts == -2) {
613         tios.c_iflag |= IXON | IXOFF;
614         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
615         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
616     }
617
618     speed = translate_speed(inspeed);
619     if (speed) {
620         cfsetospeed(&tios, speed);
621         cfsetispeed(&tios, speed);
622     } else {
623         speed = cfgetospeed(&tios);
624         /*
625          * We can't proceed if the serial port speed is B0,
626          * since that implies that the serial port is disabled.
627          */
628         if (speed == B0) {
629             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
630                    devnam);
631             die(1);
632         }
633     }
634
635     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
636         syslog(LOG_ERR, "tcsetattr: %m");
637         die(1);
638     }
639
640     baud_rate = inspeed = baud_rate_of(speed);
641     restore_term = 1;
642 }
643
644 /*
645  * restore_tty - restore the terminal to the saved settings.
646  */
647 void
648 restore_tty(fd)
649     int fd;
650 {
651     if (restore_term) {
652         if (!default_device) {
653             /*
654              * Turn off echoing, because otherwise we can get into
655              * a loop with the tty and the modem echoing to each other.
656              * We presume we are the sole user of this tty device, so
657              * when we close it, it will revert to its defaults anyway.
658              */
659             inittermios.c_lflag &= ~(ECHO | ECHONL);
660         }
661         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
662             if (errno != ENXIO)
663                 syslog(LOG_WARNING, "tcsetattr: %m");
664         ioctl(fd, TIOCSWINSZ, &wsinfo);
665         restore_term = 0;
666     }
667 }
668
669 /*
670  * setdtr - control the DTR line on the serial port.
671  * This is called from die(), so it shouldn't call die().
672  */
673 void
674 setdtr(fd, on)
675 int fd, on;
676 {
677     int modembits = TIOCM_DTR;
678
679     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
680 }
681
682
683 /*
684  * output - Output PPP packet.
685  */
686 void
687 output(unit, p, len)
688     int unit;
689     u_char *p;
690     int len;
691 {
692     struct strbuf str;
693     int retries;
694     struct pollfd pfd;
695
696     if (debug)
697         log_packet(p, len, "sent ");
698
699     str.len = len;
700     str.buf = (caddr_t) p;
701     retries = 4;
702     while (putmsg(ttyfd, NULL, &str, 0) < 0) {
703         if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
704             if (errno != ENXIO)
705                 syslog(LOG_ERR, "Couldn't send packet: %m");
706             break;
707         }
708         pfd.fd = ttyfd;
709         pfd.events = POLLOUT;
710         poll(&pfd, 1, 250);     /* wait for up to 0.25 seconds */
711     }
712 }
713
714 /*
715  * wait_input - wait for input, for a length of time specified in *timo.
716  */
717 void
718 wait_input(timo)
719     struct timeval *timo;
720 {
721     int t;
722     struct pollfd pfd;
723
724     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
725     pfd.fd = ttyfd;
726     pfd.events = POLLIN | POLLPRI | POLLHUP;
727     if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
728         syslog(LOG_ERR, "poll: %m");
729         die(1);
730     }
731 }
732
733 /*
734  * read_packet - get a PPP packet from the serial device.
735  */
736 int
737 read_packet(buf)
738     u_char *buf;
739 {
740     struct strbuf str, ctl;
741     int len, i;
742     unsigned char ctlbuf[16];
743
744     str.maxlen = PPP_MTU + PPP_HDRLEN;
745     str.buf = (caddr_t) buf;
746     ctl.maxlen = sizeof(ctlbuf);
747     ctl.buf = (caddr_t) ctlbuf;
748     i = 0;
749     len = getmsg(ttyfd, &ctl, &str, &i);
750     if (len < 0) {
751         if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
752             return -1;
753         }
754         syslog(LOG_ERR, "getmsg %m");
755         die(1);
756     }
757     if (len) 
758         MAINDEBUG((LOG_DEBUG, "getmsg returned 0x%x",len));
759     if (ctl.len > 0)
760         syslog(LOG_NOTICE, "got ctrl msg len %d %x %x\n", ctl.len,
761                ctlbuf[0], ctlbuf[1]);
762
763     if (str.len < 0) {
764         MAINDEBUG((LOG_DEBUG, "getmsg short return length %d", str.len));
765         return -1;
766     }
767
768     return str.len;
769 }
770
771
772 /*
773  * ppp_send_config - configure the transmit characteristics of
774  * the ppp interface.
775  */
776 void
777 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
778     int unit, mtu;
779     u_int32_t asyncmap;
780     int pcomp, accomp;
781 {
782     char c;
783     struct ifreq ifr;
784
785     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
786     ifr.ifr_mtu = mtu;
787     if (ioctl(sockfd, (int)SIOCSIPMTU, (caddr_t) &ifr) < 0) {
788         syslog(LOG_ERR, "ioctl(SIOCSIPMTU): %m");
789         quit();
790     }
791
792     if(ioctl(ttyfd, (int)SIOCSIFASYNCMAP, (caddr_t) &asyncmap) < 0) {
793         syslog(LOG_ERR, "ioctl(SIOCSIFASYNCMAP): %m");
794         quit();
795     }
796
797     c = (pcomp? 1: 0);
798     if(ioctl(ttyfd, (int)SIOCSIFCOMPPROT, &c) < 0) {
799         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m");
800         quit();
801     }
802
803     c = (accomp? 1: 0);
804     if(ioctl(ttyfd, (int)SIOCSIFCOMPAC, &c) < 0) {
805         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m");
806         quit();
807     }
808 }
809
810
811 /*
812  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
813  */
814 void
815 ppp_set_xaccm(unit, accm)
816     int unit;
817     ext_accm accm;
818 {
819     if (ioctl(ttyfd, (int)SIOCSIFXASYNCMAP, accm) < 0 && errno != ENOTTY)
820         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
821 }
822
823
824 /*
825  * ppp_recv_config - configure the receive-side characteristics of
826  * the ppp interface.
827  */
828 void
829 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
830     int unit, mru;
831     u_int32_t asyncmap;
832     int pcomp, accomp;
833 {
834     char c;
835
836     if (ioctl(ttyfd, (int)SIOCSIFMRU, &mru) < 0) {
837         syslog(LOG_ERR, "ioctl(SIOCSIFMRU): %m");
838     }
839
840     if (ioctl(ttyfd, (int)SIOCSIFRASYNCMAP, (caddr_t) &asyncmap) < 0) {
841         syslog(LOG_ERR, "ioctl(SIOCSIFRASYNCMAP): %m");
842     }
843
844     c = 2 + (pcomp? 1: 0);
845     if(ioctl(ttyfd, (int)SIOCSIFCOMPPROT, &c) < 0) {
846         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m");
847     }
848
849     c = 2 + (accomp? 1: 0);
850     if (ioctl(ttyfd, (int)SIOCSIFCOMPAC, &c) < 0) {
851         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m");
852     }
853 }
854
855 /*
856  * ccp_test - ask kernel whether a given compression method
857  * is acceptable for use.
858  */
859 int
860 ccp_test(unit, opt_ptr, opt_len, for_transmit)
861     int unit, opt_len, for_transmit;
862     u_char *opt_ptr;
863 {
864     struct ppp_option_data data;
865
866     if ((unsigned) opt_len > MAX_PPP_OPTION)
867         opt_len = MAX_PPP_OPTION;
868     data.length = opt_len;
869     data.transmit = for_transmit;
870     BCOPY(opt_ptr, data.opt_data, opt_len);
871     if (ioctl(ttyfd, (int)SIOCSCOMPRESS, (caddr_t) &data) >= 0)
872         return 1;
873     return (errno == ENOSR)? 0: -1;
874 }
875
876 /*
877  * ccp_flags_set - inform kernel about the current state of CCP.
878  */
879 void
880 ccp_flags_set(unit, isopen, isup)
881     int unit, isopen, isup;
882 {
883     int x;
884
885     x = (isopen? 1: 0) + (isup? 2: 0);
886     if (ioctl(ttyfd, (int)SIOCSIFCOMP, (caddr_t) &x) < 0 && errno != ENOTTY)
887         syslog(LOG_ERR, "ioctl (SIOCSIFCOMP): %m");
888 }
889
890 /*
891  * ccp_fatal_error - returns 1 if decompression was disabled as a
892  * result of an error detected after decompression of a packet,
893  * 0 otherwise.  This is necessary because of patent nonsense.
894  */
895 int
896 ccp_fatal_error(unit)
897     int unit;
898 {
899     int x;
900
901     if (ioctl(ttyfd, (int)SIOCGIFCOMP, (caddr_t) &x) < 0) {
902         syslog(LOG_ERR, "ioctl(SIOCGIFCOMP): %m");
903         return 0;
904     }
905     return x & CCP_FATALERROR;
906 }
907
908 /*
909  * sifvjcomp - config tcp header compression
910  */
911 int
912 sifvjcomp(u, vjcomp, cidcomp, maxcid)
913     int u, vjcomp, cidcomp, maxcid;
914 {
915     char x;
916
917     x = (vjcomp? 1: 0) + (cidcomp? 0: 2) + (maxcid << 4);
918     if (ioctl(ttyfd, (int)SIOCSIFVJCOMP, (caddr_t) &x) < 0) {
919         syslog(LOG_ERR, "ioctl(SIOCSIFVJCOMP): %m");
920         return 0;
921     }
922     return 1;
923 }
924
925 /*
926  * sifup - Config the interface up and enable IP packets to pass.
927  */
928 int
929 sifup(u)
930     int u;
931 {
932     struct ifreq ifr;
933     struct npioctl npi;
934
935     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
936     if (ioctl(sockfd, (int)SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
937         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
938         return 0;
939     }
940     ifr.ifr_flags |= IFF_UP;
941     if (ioctl(sockfd, (int)SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
942         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
943         return 0;
944     }
945     if_is_up = 1;
946     npi.protocol = PPP_IP;
947     npi.mode = NPMODE_PASS;
948     if (ioctl(ttyfd, (int)SIOCSETNPMODE, &npi) < 0) {
949         if (errno != ENOTTY) {
950             syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m");
951             return 0;
952         }
953     }
954     return 1;
955 }
956
957 /*
958  * sifdown - Config the interface down.
959  */
960 int
961 sifdown(u)
962     int u;
963 {
964     struct ifreq ifr;
965     int rv;
966     struct npioctl npi;
967
968     rv = 1;
969     npi.protocol = PPP_IP;
970     npi.mode = NPMODE_ERROR;
971     if (ioctl(ttyfd, (int)SIOCSETNPMODE, (caddr_t) &npi) < 0) {
972         if (errno != ENOTTY) {
973             syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m");
974             rv = 0;
975         }
976     }
977
978     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
979     if (ioctl(sockfd, (int)SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
980         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
981         rv = 0;
982     } else {
983         ifr.ifr_flags &= ~IFF_UP;
984         if (ioctl(sockfd, (int)SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
985             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
986             rv = 0;
987         } else
988             if_is_up = 0;
989     }
990     return rv;
991 }
992
993 /*
994  * SET_SA_FAMILY - initialize a struct sockaddr, setting the sa_family field.
995  */
996 #define SET_SA_FAMILY(addr, family)             \
997     BZERO((char *) &(addr), sizeof(addr));      \
998     addr.sa_family = (family);                  \
999     addr.sa_len = sizeof ((addr))
1000
1001 /*
1002  * sifaddr - Config the interface IP addresses and netmask.
1003  */
1004 int
1005 sifaddr(u, o, h, m)
1006     int u;
1007     u_int32_t o, h, m;
1008 {
1009     struct ifreq ifr;
1010     struct ifaliasreq addreq;
1011     int ret;
1012
1013     ret = 1;
1014
1015     /* flush old address, if any
1016      */
1017     bzero(&ifr, sizeof (ifr));
1018     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1019     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1020     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1021     if ((ioctl(sockfd, (int)SIOCDIFADDR, (caddr_t) &ifr) < 0)
1022         && errno != EADDRNOTAVAIL) {
1023         syslog(LOG_ERR, "ioctl(SIOCDIFADDR): %m");
1024         ret = 0;
1025     }
1026
1027     bzero(&addreq, sizeof (addreq));
1028     strncpy(addreq.ifra_name, ifname, sizeof (addreq.ifra_name));
1029     SET_SA_FAMILY(addreq.ifra_addr, AF_INET);
1030     SET_SA_FAMILY(addreq.ifra_broadaddr, AF_INET);
1031     ((struct sockaddr_in *)&addreq.ifra_addr)->sin_addr.s_addr = o;
1032     ((struct sockaddr_in *)&addreq.ifra_broadaddr)->sin_addr.s_addr = h;
1033
1034     if (m != 0) {
1035         ((struct sockaddr_in *)&addreq.ifra_mask)->sin_addr.s_addr = m;
1036         addreq.ifra_mask.sa_len = sizeof (struct sockaddr);
1037         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
1038     }
1039   
1040     /* install new src/dst and (possibly) netmask
1041      */
1042     if (ioctl(sockfd, SIOCPIFADDR, &addreq) < 0) {
1043         syslog(LOG_ERR, "ioctl(SIOCPIFADDR): %m");
1044         ret = 0;
1045     }
1046   
1047     ifaddrs[0] = o;
1048     ifaddrs[1] = h;
1049     return (ret);
1050 }
1051
1052 /*
1053  * cifaddr - Clear the interface IP addresses, and delete routes
1054  * through the interface if possible.
1055  */
1056 int
1057 cifaddr(u, o, h)
1058     int u;
1059     u_int32_t o, h;
1060 {
1061     struct ifreq ifr;
1062
1063     ifaddrs[0] = 0;
1064     bzero(&ifr, sizeof (ifr));
1065     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1066     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1067     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1068     if (ioctl(sockfd, (int)SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1069         syslog(LOG_ERR, "ioctl(SIOCDIFADDR): %m");
1070         return 0;
1071     }
1072     return 1;
1073 }
1074
1075 /*
1076  * sifdefaultroute - assign a default route through the address given.
1077  */
1078 int
1079 sifdefaultroute(u, g)
1080     int u;
1081     u_int32_t g;
1082 {
1083     struct ortentry rt;
1084
1085     BZERO(&rt, sizeof(rt));
1086     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1087     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1088     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1089     rt.rt_flags = RTF_GATEWAY;
1090     if (ioctl(sockfd, (int)SIOCADDRT, &rt) < 0) {
1091         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
1092         return 0;
1093     }
1094     default_route_gateway = g;
1095     return 1;
1096 }
1097
1098 /*
1099  * cifdefaultroute - delete a default route through the address given.
1100  */
1101 int
1102 cifdefaultroute(u, g)
1103     int u;
1104     u_int32_t g;
1105 {
1106     struct ortentry rt;
1107
1108     BZERO(&rt, sizeof(rt));
1109     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1110     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1111     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1112     rt.rt_flags = RTF_GATEWAY;
1113     if (ioctl(sockfd, (int)SIOCDELRT, &rt) < 0) {
1114         syslog(LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1115         return 0;
1116     }
1117     default_route_gateway = 0;
1118     return 1;
1119 }
1120
1121 /*
1122  * sifproxyarp - Make a proxy ARP entry for the peer.
1123  */
1124 int
1125 sifproxyarp(unit, hisaddr)
1126     int unit;
1127     u_int32_t hisaddr;
1128 {
1129     struct arpreq arpreq;
1130
1131     BZERO(&arpreq, sizeof(arpreq));
1132
1133     /*
1134      * Get the hardware address of an interface on the same subnet
1135      * as our local address.
1136      */
1137     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
1138         syslog(LOG_WARNING, "Cannot determine ethernet address for proxy ARP");
1139         return 0;
1140     }
1141
1142     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1143     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1144     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1145     if (ioctl(sockfd, (int)SIOCSARP, (caddr_t)&arpreq) < 0) {
1146         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1147         return 0;
1148     }
1149
1150     proxy_arp_addr = hisaddr;
1151     return 1;
1152 }
1153
1154 /*
1155  * cifproxyarp - Delete the proxy ARP entry for the peer.
1156  */
1157 int
1158 cifproxyarp(unit, hisaddr)
1159     int unit;
1160     u_int32_t hisaddr;
1161 {
1162     struct arpreq arpreq;
1163
1164     BZERO(&arpreq, sizeof(arpreq));
1165     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1166     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1167     if (ioctl(sockfd, (int)SIOCDARP, (caddr_t)&arpreq) < 0) {
1168         syslog(LOG_ERR, "ioctl(SIOCDARP): %m");
1169         return 0;
1170     }
1171     proxy_arp_addr = 0;
1172     return 1;
1173 }
1174
1175 /*
1176  * get_ether_addr - get the hardware address of an interface on the
1177  * the same subnet as ipaddr.
1178  */
1179 #define MAX_IFS         32
1180
1181 int s;
1182
1183 static int
1184 get_ether_addr(ipaddr, hwaddr)
1185     u_int ipaddr;
1186     struct sockaddr *hwaddr;
1187 {
1188     struct ifreq *ifr, *ifend, *ifp;
1189     u_int ina, mask;
1190     struct sockaddr_dl *dla;
1191     struct ifreq ifreq;
1192     struct ifconf ifc;
1193     struct ifreq ifs[MAX_IFS];
1194     struct ifdevea ifdevreq;
1195
1196     ifc.ifc_len = sizeof(ifs);
1197     ifc.ifc_req = ifs;
1198     if (ioctl(sockfd, (int)SIOCGIFCONF, &ifc) < 0) {
1199         perror("ioctl(SIOCGIFCONF)");
1200         return 0;
1201     }
1202
1203     /*
1204      * Scan through looking for an interface with an Internet
1205      * address on the same subnet as `ipaddr'.
1206      */
1207     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1208     for (ifr = ifc.ifc_req; ifr < ifend; +ifr = (struct ifreq *)
1209                 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len) {
1210         if (ifr->ifr_addr.sa_family == AF_INET) {
1211             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1212             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1213             /*
1214              * Check that the interface is up, and not point-to-point
1215              * or loopback.
1216              */
1217             if (ioctl(sockfd, (int)SIOCGIFFLAGS, &ifreq) < 0)
1218                 continue;
1219             if ((ifreq.ifr_flags &
1220                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1221                  != (IFF_UP|IFF_BROADCAST))
1222                 continue;
1223             /*
1224              * Get its netmask and check that it's on the right subnet.
1225              */
1226             if (ioctl(sockfd, (int)SIOCGIFNETMASK, &ifreq) < 0)
1227                 continue;
1228             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1229             if ((ipaddr & mask) != (ina & mask))
1230                 continue;
1231
1232             break;
1233         }
1234     }
1235
1236     if (ifr >= ifend)
1237         return 0;
1238     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1239
1240     strncpy(ifdevreq.ifr_name, ifr->ifr_name, sizeof(ifdevreq.ifr_name));
1241
1242     if (ioctl(sockfd, (int)SIOCRPHYSADDR, &ifdevreq) < 0) {
1243         perror("ioctl(SIOCRPHYSADDR)");
1244         return(0);
1245     }
1246
1247     hwaddr->sa_family = AF_UNSPEC;
1248     memcpy(hwaddr->sa_data, ifdevreq.current_pa, sizeof(ifdevreq.current_pa));
1249     return(1);
1250 }
1251
1252
1253 /*
1254  * Return user specified netmask, modified by any mask we might determine
1255  * for address `addr' (in network byte order).
1256  * Here we scan through the system's list of interfaces, looking for
1257  * any non-point-to-point interfaces which might appear to be on the same
1258  * network as `addr'.  If we find any, we OR in their netmask to the
1259  * user-specified netmask.
1260  */
1261 u_int32_t
1262 GetMask(addr)
1263     u_int32_t addr;
1264 {
1265     u_int32_t mask, nmask, ina;
1266     struct ifreq *ifr, *ifend, ifreq;
1267     struct ifconf ifc;
1268     struct ifreq ifs[MAX_IFS];
1269
1270     addr = ntohl(addr);
1271     if (IN_CLASSA(addr))        /* determine network mask for address class */
1272         nmask = IN_CLASSA_NET;
1273     else if (IN_CLASSB(addr))
1274         nmask = IN_CLASSB_NET;
1275     else
1276         nmask = IN_CLASSC_NET;
1277     /* class D nets are disallowed by bad_ip_adrs */
1278     mask = netmask | htonl(nmask);
1279
1280     /*
1281      * Scan through the system's network interfaces.
1282      */
1283     ifc.ifc_len = sizeof(ifs);
1284     ifc.ifc_req = ifs;
1285     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1286         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1287         return mask;
1288     }
1289     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1290     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1291         /*
1292          * Check the interface's internet address.
1293          */
1294         if (ifr->ifr_addr.sa_family != AF_INET)
1295             continue;
1296         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1297         if ((ntohl(ina) & nmask) != (addr & nmask))
1298             continue;
1299         /*
1300          * Check that the interface is up, and not point-to-point or loopback.
1301          */
1302         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1303         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1304             continue;
1305         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1306             != IFF_UP)
1307             continue;
1308         /*
1309          * Get its netmask and OR it into our mask.
1310          */
1311         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1312             continue;
1313         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1314     }
1315
1316     return mask;
1317 }
1318
1319
1320 #define WTMPFILE        "/usr/adm/wtmp"
1321 #include <sys/stat.h>
1322
1323 void
1324 logwtmp(line, name, host)
1325     char *line, *name, *host;
1326 {
1327     int fd;
1328     struct stat buf;
1329     struct utmp ut;
1330
1331     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1332         return;
1333     if (!fstat(fd, &buf)) {
1334         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1335         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1336         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1337         (void)time(&ut.ut_time);
1338         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1339             (void)ftruncate(fd, buf.st_size);
1340     }
1341     close(fd);
1342 }
1343
1344 /*
1345  * Code for locking/unlocking the serial device.
1346  * This code is derived from chat.c.
1347  */
1348
1349 #ifndef LOCK_DIR
1350 #  ifdef HDB
1351 #   define      PIDSTRING
1352 #   define      LOCK_PREFIX     "/usr/spool/locks/LCK.."
1353 #  else /* HDB */
1354 #   define      LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1355 #  endif /* HDB */
1356 #endif /* LOCK_DIR */
1357
1358 static char *lock_file;
1359
1360 /*
1361  * lock - create a lock file for the named device
1362  */
1363 int
1364 lock(dev)
1365     char *dev;
1366 {
1367     char hdb_lock_buffer[12];
1368     int fd, pid, n;
1369     char *p;
1370
1371     if ((p = strrchr(dev, '/')) != NULL)
1372         dev = p + 1;
1373     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1374     if (lock_file == NULL)
1375         novm("lock file name");
1376     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1377
1378     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1379         if (errno == EEXIST
1380             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1381             /* Read the lock file to find out who has the device locked */
1382 #ifdef PIDSTRING
1383             n = read(fd, hdb_lock_buffer, 11);
1384             if (n > 0) {
1385                 hdb_lock_buffer[n] = 0;
1386                 pid = atoi(hdb_lock_buffer);
1387             }
1388 #else
1389             n = read(fd, &pid, sizeof(pid));
1390 #endif
1391             if (n <= 0) {
1392                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1393                 close(fd);
1394             } else {
1395                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1396                     /* pid no longer exists - remove the lock file */
1397                     if (unlink(lock_file) == 0) {
1398                         close(fd);
1399                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1400                                dev, pid);
1401                         continue;
1402                     } else
1403                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1404                                dev);
1405                 } else
1406                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1407                            dev, pid);
1408             }
1409             close(fd);
1410         } else
1411             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1412         free(lock_file);
1413         lock_file = NULL;
1414         return -1;
1415     }
1416
1417 # ifdef PIDSTRING
1418     sprintf(hdb_lock_buffer, "%10d\n", getpid());
1419     write(fd, hdb_lock_buffer, 11);
1420 # else
1421     pid = getpid();
1422     write(fd, &pid, sizeof pid);
1423 # endif
1424
1425     close(fd);
1426     return 0;
1427 }
1428
1429 /*
1430  * unlock - remove our lockfile
1431  */
1432 void
1433 unlock()
1434 {
1435     if (lock_file) {
1436         unlink(lock_file);
1437         free(lock_file);
1438         lock_file = NULL;
1439     }
1440 }
1441