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