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