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