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