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