Added packet filtering, subnet spec for allowed IP addr; select
[ppp.git] / pppd / sys-ultrix.c
1 /*
2  * sys-ultrix.c - System-dependent procedures for setting up
3  * PPP interfaces on Ultrix systems.
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by Carnegie Mellon University.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 #ifndef lint
22 static char rcsid[] = "$Id: sys-ultrix.c,v 1.15 1995/10/27 03:51:52 paulus Exp $";
23 #endif
24
25 /*
26  * TODO:
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <syslog.h>
32 #include <string.h>
33 #include <termios.h>
34 #include <utmp.h>
35 #include <sys/types.h>
36 #include <sys/file.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
39 #include <sys/time.h>
40 #include <sys/errno.h>
41 #include <sys/stat.h>
42
43 #include <net/if.h>
44 #include <net/ppp_defs.h>
45 #include <net/if_ppp.h>
46 #include <net/route.h>
47 #include <netinet/in.h>
48
49 #include "pppd.h"
50
51 static int initdisc = -1;       /* Initial TTY discipline */
52 static int initfdflags = -1;    /* Initial file descriptor flags for fd */
53
54 static int restore_term;        /* 1 => we've munged the terminal */
55 static struct termios inittermios; /* Initial TTY termios */
56 static struct winsize wsinfo;   /* Initial window size info */
57
58 static char *lock_file;         /* name of lock file created */
59
60 static int sockfd;              /* socket for doing interface ioctls */
61
62 static int if_is_up;            /* the interface is currently up */
63 static u_int32_t default_route_gateway; /* gateway addr for default route */
64 static u_int32_t proxy_arp_addr;        /* remote addr for proxy arp */
65
66 /* Prototypes for procedures local to this file. */
67 static int translate_speed __P((int));
68 static int baud_rate_of __P((int));
69 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
70
71
72 /*
73  * sys_init - System-dependent initialization.
74  */
75 void
76 sys_init()
77 {
78     openlog("pppd", LOG_PID);
79
80     /* Get an internet socket for doing socket ioctl's on. */
81     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
82         syslog(LOG_ERR, "Couldn't create IP socket: %m");
83         die(1);
84     }
85 }
86
87 /*
88  * sys_cleanup - restore any system state we modified before exiting:
89  * mark the interface down, delete default route and/or proxy arp entry.
90  * This should call die() because it's called from die().
91  */
92 void
93 sys_cleanup()
94 {
95     struct ifreq ifr;
96
97     if (if_is_up) {
98         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
99         if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
100             && ((ifr.ifr_flags & IFF_UP) != 0)) {
101             ifr.ifr_flags &= ~IFF_UP;
102             ioctl(sockfd, SIOCSIFFLAGS, &ifr);
103         }
104     }
105
106     if (default_route_gateway)
107         cifdefaultroute(0, default_route_gateway);
108     if (proxy_arp_addr)
109         cifproxyarp(0, proxy_arp_addr);
110 }
111
112 /*
113  * note_debug_level - note a change in the debug level.
114  */
115 void
116 note_debug_level()
117 {
118 }
119
120
121 /*
122  * daemon - Detach us from the terminal session.
123  */
124 int
125 daemon(nochdir, noclose)
126     int nochdir, noclose;
127 {
128     int pid;
129
130     if ((pid = fork()) < 0)
131         return -1;
132     if (pid != 0)
133         exit(0);                /* parent dies */
134     setsid();
135     if (!nochdir)
136         chdir("/");
137     if (!noclose) {
138         fclose(stdin);          /* don't need stdin, stdout, stderr */
139         fclose(stdout);
140         fclose(stderr);
141     }
142     return 0;
143 }
144
145 /*
146  * ppp_available - check whether the system has any ppp interfaces
147  * (in fact we check whether we can do an ioctl on ppp0).
148  */
149 int
150 ppp_available()
151 {
152     int s, ok;
153     struct ifreq ifr;
154     extern char *no_ppp_msg;
155
156     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
157         return 1;               /* can't tell */
158
159     strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
160     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
161     close(s);
162
163     no_ppp_msg = "\
164 This system lacks kernel support for PPP.  To include PPP support\n\
165 in the kernel, please follow the steps detailed in the README.ultrix\n\
166 file in the ppp-2.2 distribution.\n";
167     return ok;
168 }
169
170 /*
171  * establish_ppp - Turn the serial port into a ppp interface.
172  */
173 void
174 establish_ppp()
175 {
176     int pppdisc = PPPDISC;
177     int x;
178
179     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
180         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
181         die(1);
182     }
183     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
184         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
185         die(1);
186     }
187
188     /*
189      * Find out which interface we were given.
190      */
191     if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {  
192         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
193         die(1);
194     }
195
196     /*
197      * Enable debug in the driver if requested.
198      */
199     if (kdebugflag) {
200         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
201             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
202         } else {
203             x |= (kdebugflag & 0xFF) * SC_DEBUG;
204             if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
205                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
206         }
207     }
208
209     /*
210      * Set device for non-blocking reads.
211      */
212     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
213         || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
214         syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
215     }
216 }
217
218
219 /*
220  * disestablish_ppp - Restore the serial port to normal operation.
221  * This shouldn't call die() because it's called from die().
222  */
223 void
224 disestablish_ppp()
225 {
226     int x;
227     char *s;
228
229     /* Reset non-blocking mode on the file descriptor. */
230     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
231         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
232     initfdflags = -1;
233
234     if (initdisc >= 0) {
235         /*
236          * Check whether the link seems not to be 8-bit clean.
237          */
238         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
239             s = NULL;
240             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
241             case SC_RCV_B7_0:
242                 s = "bit 7 set to 1";
243                 break;
244             case SC_RCV_B7_1:
245                 s = "bit 7 set to 0";
246                 break;
247             case SC_RCV_EVNP:
248                 s = "odd parity";
249                 break;
250             case SC_RCV_ODDP:
251                 s = "even parity";
252                 break;
253             }
254             if (s != NULL) {
255                 syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
256                 syslog(LOG_WARNING, "All received characters had %s", s);
257             }
258         }
259         if (ioctl(fd, TIOCSETD, &initdisc) < 0)
260             syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
261     }
262 }
263
264
265 /*
266  * List of valid speeds.
267  */
268 struct speed {
269     int speed_int, speed_val;
270 } speeds[] = {
271 #ifdef B50
272     { 50, B50 },
273 #endif
274 #ifdef B75
275     { 75, B75 },
276 #endif
277 #ifdef B110
278     { 110, B110 },
279 #endif
280 #ifdef B134
281     { 134, B134 },
282 #endif
283 #ifdef B150
284     { 150, B150 },
285 #endif
286 #ifdef B200
287     { 200, B200 },
288 #endif
289 #ifdef B300
290     { 300, B300 },
291 #endif
292 #ifdef B600
293     { 600, B600 },
294 #endif
295 #ifdef B1200
296     { 1200, B1200 },
297 #endif
298 #ifdef B1800
299     { 1800, B1800 },
300 #endif
301 #ifdef B2000
302     { 2000, B2000 },
303 #endif
304 #ifdef B2400
305     { 2400, B2400 },
306 #endif
307 #ifdef B3600
308     { 3600, B3600 },
309 #endif
310 #ifdef B4800
311     { 4800, B4800 },
312 #endif
313 #ifdef B7200
314     { 7200, B7200 },
315 #endif
316 #ifdef B9600
317     { 9600, B9600 },
318 #endif
319 #ifdef B19200
320     { 19200, B19200 },
321 #endif
322 #ifdef B38400
323     { 38400, B38400 },
324 #endif
325 #ifdef EXTA
326     { 19200, EXTA },
327 #endif
328 #ifdef EXTB
329     { 38400, EXTB },
330 #endif
331 #ifdef B57600
332     { 57600, B57600 },
333 #endif
334 #ifdef B115200
335     { 115200, B115200 },
336 #endif
337     { 0, 0 }
338 };
339
340 /*
341  * Translate from bits/second to a speed_t.
342  */
343 int
344 translate_speed(bps)
345     int bps;
346 {
347     struct speed *speedp;
348
349     if (bps == 0)
350         return 0;
351     for (speedp = speeds; speedp->speed_int; speedp++)
352         if (bps == speedp->speed_int)
353             return speedp->speed_val;
354     syslog(LOG_WARNING, "speed %d not supported", bps);
355     return 0;
356 }
357
358 /*
359  * Translate from a speed_t to bits/second.
360  */
361 int
362 baud_rate_of(speed)
363     int speed;
364 {
365     struct speed *speedp;
366
367     if (speed == 0)
368         return 0;
369     for (speedp = speeds; speedp->speed_int; speedp++)
370         if (speed == speedp->speed_val)
371             return speedp->speed_int;
372     return 0;
373 }
374
375 /*
376  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
377  * at the requested speed, etc.  If `local' is true, set CLOCAL
378  * regardless of whether the modem option was specified.
379  */
380 void
381 set_up_tty(fd, local)
382     int fd, local;
383 {
384     int speed, x;
385     struct termios tios;
386
387     if (tcgetattr(fd, &tios) < 0) {
388         syslog(LOG_ERR, "tcgetattr: %m");
389         die(1);
390     }
391
392     if (!restore_term) {
393         inittermios = tios;
394         ioctl(fd, TIOCGWINSZ, &wsinfo);
395     }
396
397     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
398 #ifdef CRTSCTS
399     if (crtscts > 0 && !local)
400         tios.c_cflag |= CRTSCTS;
401     else if (crtscts < 0)
402         tios.c_cflag &= ~CRTSCTS;
403 #endif  /* CRTSCTS */
404
405     tios.c_cflag |= CS8 | CREAD | HUPCL;
406     if (local || !modem)
407         tios.c_cflag |= CLOCAL;
408     tios.c_iflag = IGNBRK | IGNPAR;
409     tios.c_oflag = 0;
410     tios.c_lflag = 0;
411     tios.c_cc[VMIN] = 1;
412     tios.c_cc[VTIME] = 0;
413
414     if (crtscts == -2) {
415         tios.c_iflag |= IXON | IXOFF;
416         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
417         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
418     }
419
420     speed = translate_speed(inspeed);
421     if (speed) {
422         cfsetospeed(&tios, speed);
423         cfsetispeed(&tios, speed);
424     } else {
425         speed = cfgetospeed(&tios);
426         /*
427          * We can't proceed if the serial port speed is B0,
428          * since that implies that the serial port is disabled.
429          */
430         if (speed == B0) {
431             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
432                    devnam);
433             die(1);
434         }
435     }
436
437     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
438         syslog(LOG_ERR, "tcsetattr: %m");
439         die(1);
440     }
441
442     x = 0;
443     if (ioctl(fd, (crtscts > 0 || modem)? TIOCMODEM: TIOCNMODEM, &x) < 0)
444         syslog(LOG_WARNING, "TIOC(N)MODEM: %m");
445     if (ioctl(fd, (local || !modem)? TIOCNCAR: TIOCCAR) < 0)
446         syslog(LOG_WARNING, "TIOC(N)CAR: %m");
447
448     baud_rate = inspeed = baud_rate_of(speed);
449     restore_term = TRUE;
450 }
451
452 /*
453  * restore_tty - restore the terminal to the saved settings.
454  */
455 void
456 restore_tty()
457 {
458     if (restore_term) {
459         if (!default_device) {
460             /*
461              * Turn off echoing, because otherwise we can get into
462              * a loop with the tty and the modem echoing to each other.
463              * We presume we are the sole user of this tty device, so
464              * when we close it, it will revert to its defaults anyway.
465              */
466             inittermios.c_lflag &= ~(ECHO | ECHONL);
467         }
468         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
469             if (errno != ENXIO)
470                 syslog(LOG_WARNING, "tcsetattr: %m");
471         ioctl(fd, TIOCSWINSZ, &wsinfo);
472         restore_term = FALSE;
473     }
474 }
475
476 /*
477  * setdtr - control the DTR line on the serial port.
478  * This is called from die(), so it shouldn't call die().
479  */
480 void
481 setdtr(fd, on)
482 int fd, on;
483 {
484     int modembits = TIOCM_DTR;
485
486     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
487 }
488
489
490 /*
491  * output - Output PPP packet.
492  */
493 void
494 output(unit, p, len)
495     int unit;
496     u_char *p;
497     int len;
498 {
499     if (debug)
500         log_packet(p, len, "sent ");
501
502     if (write(fd, p, len) < 0) {
503         if (errno != EIO)
504             syslog(LOG_ERR, "write: %m");
505     }
506 }
507
508
509 /*
510  * wait_input - wait until there is data available on fd,
511  * for the length of time specified by *timo (indefinite
512  * if timo is NULL).
513  */
514 void
515 wait_input(timo)
516     struct timeval *timo;
517 {
518     fd_set ready;
519     int n;
520
521     FD_ZERO(&ready);
522     FD_SET(fd, &ready);
523     n = select(fd+1, &ready, NULL, &ready, timo);
524     if (n < 0 && errno != EINTR) {
525         syslog(LOG_ERR, "select: %m");
526         die(1);
527     }
528 }
529
530
531 /*
532  * read_packet - get a PPP packet from the serial device.
533  */
534 int
535 read_packet(buf)
536     u_char *buf;
537 {
538     int len;
539
540     if ((len = read(fd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
541         if (errno == EWOULDBLOCK || errno == EINTR)
542             return -1;
543         syslog(LOG_ERR, "read(fd): %m");
544         die(1);
545     }
546     return len;
547 }
548
549
550 /*
551  * ppp_send_config - configure the transmit characteristics of
552  * the ppp interface.
553  */
554 void
555 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
556     int unit, mtu;
557     u_int32_t asyncmap;
558     int pcomp, accomp;
559 {
560     u_int x;
561
562     if (ioctl(fd, PPPIOCSMTU, &mtu) < 0) {
563         syslog(LOG_ERR, "ioctl(PPPIOCSMTU): %m");
564         quit();
565     }
566
567     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
568         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
569         quit();
570     }
571
572     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
573         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
574         quit();
575     }
576     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
577     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
578     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
579         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
580         quit();
581     }
582 }
583
584
585 /*
586  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
587  */
588 void
589 ppp_set_xaccm(unit, accm)
590     int unit;
591     ext_accm accm;
592 {
593     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
594         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
595 }
596
597
598 /*
599  * ppp_recv_config - configure the receive-side characteristics of
600  * the ppp interface.
601  */
602 void
603 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
604     int unit, mru;
605     u_int32_t asyncmap;
606     int pcomp, accomp;
607 {
608     int x;
609
610     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
611         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
612         quit();
613     }
614     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
615         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
616         quit();
617     }
618     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
619         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
620         quit();
621     }
622     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
623     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
624         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
625         quit();
626     }
627 }
628
629 /*
630  * ccp_test - ask kernel whether a given compression method
631  * is acceptable for use.  Returns 1 if the method and parameters
632  * are OK, 0 if the method is known but the parameters are not OK
633  * (e.g. code size should be reduced), or -1 if the method is unknown.
634  */
635 int
636 ccp_test(unit, opt_ptr, opt_len, for_transmit)
637     int unit, opt_len, for_transmit;
638     u_char *opt_ptr;
639 {
640     struct ppp_option_data data;
641
642     data.ptr = opt_ptr;
643     data.length = opt_len;
644     data.transmit = for_transmit;
645     if (ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
646         return 1;
647     return (errno == ENOBUFS)? 0: -1;
648 }
649
650 /*
651  * ccp_flags_set - inform kernel about the current state of CCP.
652  */
653 void
654 ccp_flags_set(unit, isopen, isup)
655     int unit, isopen, isup;
656 {
657     int x;
658
659     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
660         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
661         return;
662     }
663     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
664     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
665     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
666         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
667 }
668
669 /*
670  * ccp_fatal_error - returns 1 if decompression was disabled as a
671  * result of an error detected after decompression of a packet,
672  * 0 otherwise.  This is necessary because of patent nonsense.
673  */
674 int
675 ccp_fatal_error(unit)
676     int unit;
677 {
678     int x;
679
680     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
681         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
682         return 0;
683     }
684     return x & SC_DC_FERROR;
685 }
686
687 /*
688  * sifvjcomp - config tcp header compression
689  */
690 int
691 sifvjcomp(u, vjcomp, cidcomp, maxcid)
692     int u, vjcomp, cidcomp, maxcid;
693 {
694     u_int x;
695
696     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
697         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
698         return 0;
699     }
700     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
701     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
702     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
703         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
704         return 0;
705     }
706     if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
707         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
708         return 0;
709     }
710     return 1;
711 }
712
713 /*
714  * sifup - Config the interface up and enable IP packets to pass.
715  */
716 #ifndef SC_ENABLE_IP
717 #define SC_ENABLE_IP    0x100   /* compat for old versions of kernel code */
718 #endif
719
720 int
721 sifup(u)
722     int u;
723 {
724     struct ifreq ifr;
725     u_int x;
726     struct npioctl npi;
727
728     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
729     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
730         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
731         return 0;
732     }
733     ifr.ifr_flags |= IFF_UP;
734     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
735         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
736         return 0;
737     }
738     if_is_up = 1;
739     npi.protocol = PPP_IP;
740     npi.mode = NPMODE_PASS;
741     if (ioctl(fd, PPPIOCSNPMODE, &npi) < 0) {
742         if (errno != ENOTTY) {
743             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
744             return 0;
745         }
746         /* for backwards compatibility */
747         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
748             syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
749             return 0;
750         }
751         x |= SC_ENABLE_IP;
752         if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
753             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
754             return 0;
755         }
756     }
757     return 1;
758 }
759
760 /*
761  * sifdown - Config the interface down and disable IP.
762  */
763 int
764 sifdown(u)
765     int u;
766 {
767     struct ifreq ifr;
768     u_int x;
769     int rv;
770     struct npioctl npi;
771
772     rv = 1;
773     npi.protocol = PPP_IP;
774     npi.mode = NPMODE_ERROR;
775     if (ioctl(fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
776         if (errno != ENOTTY) {
777             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
778             rv = 0;
779         } else {
780             /* backwards compatibility */
781             if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
782                 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
783                 rv = 0;
784             } else {
785                 x &= ~SC_ENABLE_IP;
786                 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
787                     syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
788                     rv = 0;
789                 }
790             }
791         }
792     }
793
794     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
795     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
796         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
797         rv = 0;
798     } else {
799         ifr.ifr_flags &= ~IFF_UP;
800         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
801             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
802             rv = 0;
803         } else
804             if_is_up = 0;
805     }
806     return rv;
807 }
808
809 /*
810  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
811  * if it exists.
812  */
813 #define SET_SA_FAMILY(addr, family)             \
814     BZERO((char *) &(addr), sizeof(addr));      \
815     addr.sa_family = (family); 
816
817 /*
818  * sifaddr - Config the interface IP addresses and netmask.
819  */
820 int
821 sifaddr(u, o, h, m)
822     int u;
823     u_int32_t o, h, m;
824 {
825     int ret;
826     struct ifreq ifr;
827
828     ret = 1;
829     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
830     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
831     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
832     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
833         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
834         ret = 0;
835     }
836     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
837     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
838         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
839         ret = 0;
840     }
841     if (m != 0) {
842         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
843         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
844         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
845             syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
846             ret = 0;
847         }
848     }
849     return ret;
850 }
851
852 /*
853  * cifaddr - Clear the interface IP addresses, and delete routes
854  * through the interface if possible.
855  */
856 int
857 cifaddr(u, o, h)
858     int u;
859     u_int32_t o, h;
860 {
861     struct rtentry rt;
862
863     SET_SA_FAMILY(rt.rt_dst, AF_INET);
864     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
865     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
866     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
867     rt.rt_flags = RTF_HOST;
868     if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
869         syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
870         return 0;
871     }
872     return 1;
873 }
874
875 /*
876  * sifdefaultroute - assign a default route through the address given.
877  */
878 int
879 sifdefaultroute(u, g)
880 {
881     struct rtentry rt;
882
883     SET_SA_FAMILY(rt.rt_dst, AF_INET);
884     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
885     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
886     rt.rt_flags = RTF_GATEWAY;
887     if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
888         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
889         return 0;
890     }
891     default_route_gateway = g;
892     return 1;
893 }
894
895 /*
896  * cifdefaultroute - delete a default route through the address given.
897  */
898 int
899 cifdefaultroute(u, g)
900 {
901     struct rtentry rt;
902
903     SET_SA_FAMILY(rt.rt_dst, AF_INET);
904     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
905     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
906     rt.rt_flags = RTF_GATEWAY;
907     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
908         syslog(LOG_WARNING, "default route ioctl(SIOCDELRT): %m");
909     default_route_gateway = 0;
910     return 1;
911 }
912
913 /*
914  * sifproxyarp - Make a proxy ARP entry for the peer.
915  */
916 int
917 sifproxyarp(unit, hisaddr)
918     int unit;
919     u_int32_t hisaddr;
920 {
921     struct arpreq arpreq;
922
923     BZERO(&arpreq, sizeof(arpreq));
924
925     /*
926      * Get the hardware address of an interface on the same subnet
927      * as our local address.
928      */
929     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
930         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
931         return 0;
932     }
933
934     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
935     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
936     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
937     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
938         syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
939         return 0;
940     }
941
942     proxy_arp_addr = hisaddr;
943     return 1;
944 }
945
946 /*
947  * cifproxyarp - Delete the proxy ARP entry for the peer.
948  */
949 int
950 cifproxyarp(unit, hisaddr)
951     int unit;
952     u_int32_t hisaddr;
953 {
954     struct arpreq arpreq;
955
956     BZERO(&arpreq, sizeof(arpreq));
957     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
958     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
959     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
960         syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m");
961         return 0;
962     }
963     proxy_arp_addr = 0;
964     return 1;
965 }
966
967 /*
968  * get_ether_addr - get the hardware address of an interface on the
969  * the same subnet as ipaddr.
970  */
971 #define MAX_IFS         32
972
973 static int
974 get_ether_addr(ipaddr, hwaddr)
975     u_int32_t ipaddr;
976     struct sockaddr *hwaddr;
977 {
978     struct ifreq *ifr, *ifend;
979     u_int32_t ina, mask;
980     struct ifreq ifreq;
981     struct ifconf ifc;
982     struct ifreq ifs[MAX_IFS];
983     struct ifdevea ifdevea;
984
985     ifc.ifc_len = sizeof(ifs);
986     ifc.ifc_req = ifs;
987     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
988         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
989         return 0;
990     }
991
992     /*
993      * Scan through looking for an interface with an Internet
994      * address on the same subnet as `ipaddr'.
995      */
996     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
997     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
998             ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
999         if (ifr->ifr_addr.sa_family == AF_INET) {
1000             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1001             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1002             /*
1003              * Check that the interface is up, and not point-to-point
1004              * or loopback.
1005              */
1006             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1007                 continue;
1008             if ((ifreq.ifr_flags &
1009                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1010                  != (IFF_UP|IFF_BROADCAST))
1011                 continue;
1012             /*
1013              * Get its netmask and check that it's on the right subnet.
1014              */
1015             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1016                 continue;
1017             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1018             if ((ipaddr & mask) != (ina & mask))
1019                 continue;
1020
1021             break;
1022         }
1023     }
1024
1025     if (ifr >= ifend)
1026         return 0;
1027     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1028
1029     /*
1030      * Grab the physical address for this interface.
1031      */
1032     strncpy(ifdevea.ifr_name, ifr->ifr_name, sizeof(ifdevea.ifr_name));
1033     if (ioctl(sockfd, SIOCRPHYSADDR, &ifdevea) < 0) {
1034         syslog(LOG_ERR, "Couldn't get h/w address for %s: %m", ifr->ifr_name);
1035         return 0;
1036     }
1037
1038     hwaddr->sa_family = AF_UNSPEC;
1039     BCOPY(ifdevea.current_pa, hwaddr->sa_data, 6);
1040     return 1;
1041 }
1042
1043 /*
1044  * Return user specified netmask, modified by any mask we might determine
1045  * for address `addr' (in network byte order).
1046  * Here we scan through the system's list of interfaces, looking for
1047  * any non-point-to-point interfaces which might appear to be on the same
1048  * network as `addr'.  If we find any, we OR in their netmask to the
1049  * user-specified netmask.
1050  */
1051 u_int32_t
1052 GetMask(addr)
1053     u_int32_t addr;
1054 {
1055     u_int32_t mask, nmask, ina;
1056     struct ifreq *ifr, *ifend, ifreq;
1057     struct ifconf ifc;
1058     struct ifreq ifs[MAX_IFS];
1059
1060     addr = ntohl(addr);
1061     if (IN_CLASSA(addr))        /* determine network mask for address class */
1062         nmask = IN_CLASSA_NET;
1063     else if (IN_CLASSB(addr))
1064         nmask = IN_CLASSB_NET;
1065     else
1066         nmask = IN_CLASSC_NET;
1067     /* class D nets are disallowed by bad_ip_adrs */
1068     mask = netmask | htonl(nmask);
1069
1070     /*
1071      * Scan through the system's network interfaces.
1072      */
1073     ifc.ifc_len = sizeof(ifs);
1074     ifc.ifc_req = ifs;
1075     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1076         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1077         return mask;
1078     }
1079     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1080     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1081                 ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1082         /*
1083          * Check the interface's internet address.
1084          */
1085         if (ifr->ifr_addr.sa_family != AF_INET)
1086             continue;
1087         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1088         if ((ntohl(ina) & nmask) != (addr & nmask))
1089             continue;
1090         /*
1091          * Check that the interface is up, and not point-to-point or loopback.
1092          */
1093         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1094         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1095             continue;
1096         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1097             != IFF_UP)
1098             continue;
1099         /*
1100          * Get its netmask and OR it into our mask.
1101          */
1102         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1103             continue;
1104         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1105     }
1106
1107     return mask;
1108 }
1109
1110
1111 /*
1112   Seems like strdup() is not part of string package in Ultrix.
1113   If I understood the man-page on the sun this should work.
1114
1115   Robert Olsson
1116 */
1117
1118 char *strdup( in ) char *in;
1119 {
1120   char* dup;
1121   if(! (dup = (char *) malloc( strlen( in ) +1 ))) return NULL;
1122   (void) strcpy( dup, in );
1123   return dup;
1124 }
1125
1126 /*
1127  * This logwtmp() implementation is subject to the following copyright:
1128  *
1129  * Copyright (c) 1988 The Regents of the University of California.
1130  * All rights reserved.
1131  *
1132  * Redistribution and use in source and binary forms are permitted
1133  * provided that the above copyright notice and this paragraph are
1134  * duplicated in all such forms and that any documentation,
1135  * advertising materials, and other materials related to such
1136  * distribution and use acknowledge that the software was developed
1137  * by the University of California, Berkeley.  The name of the
1138  * University may not be used to endorse or promote products derived
1139  * from this software without specific prior written permission.
1140  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1141  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1142  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1143  */
1144
1145 #define WTMPFILE        "/usr/adm/wtmp"
1146
1147 int
1148 logwtmp(line, name, host)
1149     char *line, *name, *host;
1150 {
1151     int fd;
1152     struct stat buf;
1153     struct utmp ut;
1154
1155     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1156         return;
1157     if (!fstat(fd, &buf)) {
1158         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1159         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1160         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1161         (void)time(&ut.ut_time);
1162         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1163             (void)ftruncate(fd, buf.st_size);
1164     }
1165     close(fd);
1166 }
1167
1168 /*
1169  * Routines for locking and unlocking the serial device, moved here
1170  * from chat.c.
1171  */
1172
1173 #define LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1174
1175 /*
1176  * lock - create a lock file for the named device
1177  */
1178 int
1179 lock(dev)
1180     char *dev;
1181 {
1182     int fd, pid, n;
1183     char *p;
1184
1185     if ((p = strrchr(dev, '/')) != NULL)
1186         dev = p + 1;
1187     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1188     if (lock_file == NULL)
1189         novm("lock file name");
1190     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1191
1192     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1193         if (errno == EEXIST
1194             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1195             /* Read the lock file to find out who has the device locked */
1196             n = read(fd, &pid, sizeof(pid));
1197             if (n <= 0) {
1198                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1199                 close(fd);
1200             } else {
1201                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1202                     /* pid no longer exists - remove the lock file */
1203                     if (unlink(lock_file) == 0) {
1204                         close(fd);
1205                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1206                                dev, pid);
1207                         continue;
1208                     } else
1209                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1210                                dev);
1211                 } else
1212                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1213                            dev, pid);
1214             }
1215             close(fd);
1216         } else
1217             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1218         free(lock_file);
1219         lock_file = NULL;
1220         return -1;
1221     }
1222
1223     pid = getpid();
1224     write(fd, &pid, sizeof pid);
1225
1226     close(fd);
1227     return 0;
1228 }
1229
1230 /*
1231  * unlock - remove our lockfile
1232  */
1233 void
1234 unlock()
1235 {
1236     if (lock_file) {
1237         unlink(lock_file);
1238         free(lock_file);
1239         lock_file = NULL;
1240     }
1241 }