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