]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-ultrix.c
syslog -> notice/error/etc.
[ppp.git] / pppd / sys-ultrix.c
1 /*
2  * sys-ultrix.c - System-dependent procedures for setting up
3  * PPP interfaces on Ultrix systems.
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-ultrix.c,v 1.26 1999/03/16 02:57:08 paulus Exp $";
25 #endif
26
27 /*
28  * TODO:
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <termios.h>
38 #include <utmp.h>
39 #include <sys/types.h>
40 #include <sys/file.h>
41 #include <sys/socket.h>
42 #include <sys/ioctl.h>
43 #include <sys/time.h>
44 #include <sys/errno.h>
45 #include <sys/stat.h>
46
47 #include <net/if.h>
48 #include <net/ppp_defs.h>
49 #include <net/if_ppp.h>
50 #include <net/route.h>
51 #include <netinet/in.h>
52
53 #include "pppd.h"
54
55 static int initdisc = -1;       /* Initial TTY discipline for ppp_fd */
56 static int initfdflags = -1;    /* Initial file descriptor flags for ppp_fd */
57 static int ppp_fd = -1;         /* fd which is set to PPP discipline */
58
59 static int restore_term;        /* 1 => we've munged the terminal */
60 static struct termios inittermios; /* Initial TTY termios */
61 static struct winsize wsinfo;   /* Initial window size info */
62
63 static char *lock_file;         /* name of lock file created */
64
65 static int loop_slave = -1;
66 static int loop_master;
67 static char loop_name[20];
68
69 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
70
71 static int sockfd;              /* socket for doing interface ioctls */
72
73 static fd_set in_fds;           /* set of fds that wait_input waits for */
74 static int max_in_fd;           /* highest fd set in in_fds */
75
76 static int if_is_up;            /* the interface is currently up */
77 static u_int32_t ifaddrs[2];    /* local and remote addresses */
78 static u_int32_t default_route_gateway; /* gateway addr for default route */
79 static u_int32_t proxy_arp_addr;        /* remote addr for proxy arp */
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         error("Couldn't create IP socket: %m");
96         die(1);
97     }
98
99     FD_ZERO(&in_fds);
100     max_in_fd = 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  * sys_close - Clean up in a child process before execing.
131  */
132 void
133 sys_close()
134 {
135     close(sockfd);
136     if (loop_slave >= 0) {
137         close(loop_slave);
138         close(loop_master);
139     }
140 }
141
142 /*
143  * sys_check_options - check the options that the user specified
144  */
145 int
146 sys_check_options()
147 {
148     if (demand) {
149         option_error("Sorry - demand-dialling is not supported under Ultrix\n");
150         return 0;
151     }
152     return 1;
153 }
154
155
156 /*
157  * daemon - Detach us from the terminal session.
158  */
159 int
160 daemon(nochdir, noclose)
161     int nochdir, noclose;
162 {
163     int pid;
164
165     if ((pid = fork()) < 0)
166         return -1;
167     if (pid != 0)
168         exit(0);                /* parent dies */
169     setsid();
170     if (!nochdir)
171         chdir("/");
172     if (!noclose) {
173         fclose(stdin);          /* don't need stdin, stdout, stderr */
174         fclose(stdout);
175         fclose(stderr);
176     }
177     return 0;
178 }
179
180 /*
181  * ppp_available - check whether the system has any ppp interfaces
182  * (in fact we check whether we can do an ioctl on ppp0).
183  */
184 int
185 ppp_available()
186 {
187     int s, ok;
188     struct ifreq ifr;
189     extern char *no_ppp_msg;
190
191     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
192         return 1;               /* can't tell */
193
194     strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), "ppp0");
195     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
196     close(s);
197
198     no_ppp_msg = "\
199 This system lacks kernel support for PPP.  To include PPP support\n\
200 in the kernel, please follow the steps detailed in the README.ultrix\n\
201 file in the ppp-2.2 distribution.\n";
202     return ok;
203 }
204
205 /*
206  * establish_ppp - Turn the serial port into a ppp interface.
207  */
208 void
209 establish_ppp(fd)
210     int fd;
211 {
212     int pppdisc = PPPDISC;
213     int x;
214
215     /*
216      * Save the old line discipline of fd, and set it to PPP.
217      */
218     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
219         error("ioctl(TIOCGETD): %m");
220         die(1);
221     }
222     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
223         error("ioctl(TIOCSETD): %m");
224         die(1);
225     }
226
227     /*
228      * Find out which interface we were given.
229      */
230     if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {  
231         error("ioctl(PPPIOCGUNIT): %m");
232         die(1);
233     }
234
235     ppp_fd = fd;
236
237     /*
238      * Enable debug in the driver if requested.
239      */
240     if (kdebugflag) {
241         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
242             warn("ioctl (PPPIOCGFLAGS): %m");
243         } else {
244             x |= (kdebugflag & 0xFF) * SC_DEBUG;
245             if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
246                 warn("ioctl(PPPIOCSFLAGS): %m");
247         }
248     }
249
250     /*
251      * Set device for non-blocking reads.
252      */
253     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
254         || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
255         warn("Couldn't set device to non-blocking mode: %m");
256     }
257 }
258
259 /*
260  * restore_loop - reattach the ppp unit to the loopback.
261  */
262 void
263 restore_loop()
264 {
265 }
266
267 /*
268  * disestablish_ppp - Restore the serial port to normal operation.
269  * This shouldn't call die() because it's called from die().
270  */
271 void
272 disestablish_ppp(fd)
273      int fd;
274 {
275     /* Reset non-blocking mode on fd. */
276     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
277         warn("Couldn't restore device fd flags: %m");
278     initfdflags = -1;
279
280     /* Restore old line discipline. */
281     if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
282         error("ioctl(TIOCSETD): %m");
283     initdisc = -1;
284
285     if (fd == ppp_fd)
286         ppp_fd = -1;
287 }
288
289 /*
290  * Check whether the link seems not to be 8-bit clean.
291  */
292 void
293 clean_check()
294 {
295     int x;
296     char *s;
297
298     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
299         s = NULL;
300         switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
301         case SC_RCV_B7_0:
302             s = "bit 7 set to 1";
303             break;
304         case SC_RCV_B7_1:
305             s = "bit 7 set to 0";
306             break;
307         case SC_RCV_EVNP:
308             s = "odd parity";
309             break;
310         case SC_RCV_ODDP:
311             s = "even parity";
312             break;
313         }
314         if (s != NULL) {
315             warn("Serial link is not 8-bit clean:");
316             warn("All received characters had %s", s);
317         }
318     }
319 }
320
321
322 /*
323  * List of valid speeds.
324  */
325 struct speed {
326     int speed_int, speed_val;
327 } speeds[] = {
328 #ifdef B50
329     { 50, B50 },
330 #endif
331 #ifdef B75
332     { 75, B75 },
333 #endif
334 #ifdef B110
335     { 110, B110 },
336 #endif
337 #ifdef B134
338     { 134, B134 },
339 #endif
340 #ifdef B150
341     { 150, B150 },
342 #endif
343 #ifdef B200
344     { 200, B200 },
345 #endif
346 #ifdef B300
347     { 300, B300 },
348 #endif
349 #ifdef B600
350     { 600, B600 },
351 #endif
352 #ifdef B1200
353     { 1200, B1200 },
354 #endif
355 #ifdef B1800
356     { 1800, B1800 },
357 #endif
358 #ifdef B2000
359     { 2000, B2000 },
360 #endif
361 #ifdef B2400
362     { 2400, B2400 },
363 #endif
364 #ifdef B3600
365     { 3600, B3600 },
366 #endif
367 #ifdef B4800
368     { 4800, B4800 },
369 #endif
370 #ifdef B7200
371     { 7200, B7200 },
372 #endif
373 #ifdef B9600
374     { 9600, B9600 },
375 #endif
376 #ifdef B19200
377     { 19200, B19200 },
378 #endif
379 #ifdef B38400
380     { 38400, B38400 },
381 #endif
382 #ifdef EXTA
383     { 19200, EXTA },
384 #endif
385 #ifdef EXTB
386     { 38400, EXTB },
387 #endif
388 #ifdef B57600
389     { 57600, B57600 },
390 #endif
391 #ifdef B115200
392     { 115200, B115200 },
393 #endif
394     { 0, 0 }
395 };
396
397 /*
398  * Translate from bits/second to a speed_t.
399  */
400 int
401 translate_speed(bps)
402     int bps;
403 {
404     struct speed *speedp;
405
406     if (bps == 0)
407         return 0;
408     for (speedp = speeds; speedp->speed_int; speedp++)
409         if (bps == speedp->speed_int)
410             return speedp->speed_val;
411     warn("speed %d not supported", bps);
412     return 0;
413 }
414
415 /*
416  * Translate from a speed_t to bits/second.
417  */
418 int
419 baud_rate_of(speed)
420     int speed;
421 {
422     struct speed *speedp;
423
424     if (speed == 0)
425         return 0;
426     for (speedp = speeds; speedp->speed_int; speedp++)
427         if (speed == speedp->speed_val)
428             return speedp->speed_int;
429     return 0;
430 }
431
432 /*
433  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
434  * at the requested speed, etc.  If `local' is true, set CLOCAL
435  * regardless of whether the modem option was specified.
436  */
437 void
438 set_up_tty(fd, local)
439     int fd, local;
440 {
441     int speed, x;
442     struct termios tios;
443
444     if (tcgetattr(fd, &tios) < 0) {
445         error("tcgetattr: %m");
446         die(1);
447     }
448
449     if (!restore_term) {
450         inittermios = tios;
451         ioctl(fd, TIOCGWINSZ, &wsinfo);
452     }
453
454     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
455 #ifdef CRTSCTS
456     if (crtscts > 0 && !local)
457         tios.c_cflag |= CRTSCTS;
458     else if (crtscts < 0)
459         tios.c_cflag &= ~CRTSCTS;
460 #endif  /* CRTSCTS */
461
462     tios.c_cflag |= CS8 | CREAD | HUPCL;
463     if (local || !modem)
464         tios.c_cflag |= CLOCAL;
465     tios.c_iflag = IGNBRK | IGNPAR;
466     tios.c_oflag = 0;
467     tios.c_lflag = 0;
468     tios.c_cc[VMIN] = 1;
469     tios.c_cc[VTIME] = 0;
470
471     if (crtscts == -2) {
472         tios.c_iflag |= IXON | IXOFF;
473         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
474         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
475     }
476
477     speed = translate_speed(inspeed);
478     if (speed) {
479         cfsetospeed(&tios, speed);
480         cfsetispeed(&tios, speed);
481     } else {
482         speed = cfgetospeed(&tios);
483         /*
484          * We can't proceed if the serial port speed is B0,
485          * since that implies that the serial port is disabled.
486          */
487         if (speed == B0) {
488             error("Baud rate for %s is 0; need explicit baud rate",
489                    devnam);
490             die(1);
491         }
492     }
493
494     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
495         error("tcsetattr: %m");
496         die(1);
497     }
498
499     x = 0;
500     if (ioctl(fd, (crtscts > 0 || modem)? TIOCMODEM: TIOCNMODEM, &x) < 0)
501         warn("TIOC(N)MODEM: %m");
502     if (ioctl(fd, (local || !modem)? TIOCNCAR: TIOCCAR) < 0)
503         warn("TIOC(N)CAR: %m");
504
505     baud_rate = inspeed = baud_rate_of(speed);
506     restore_term = TRUE;
507 }
508
509 /*
510  * restore_tty - restore the terminal to the saved settings.
511  */
512 void
513 restore_tty(fd)
514     int fd;
515 {
516     if (restore_term) {
517         if (!default_device) {
518             /*
519              * Turn off echoing, because otherwise we can get into
520              * a loop with the tty and the modem echoing to each other.
521              * We presume we are the sole user of this tty device, so
522              * when we close it, it will revert to its defaults anyway.
523              */
524             inittermios.c_lflag &= ~(ECHO | ECHONL);
525         }
526         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
527             if (errno != ENXIO)
528                 warn("tcsetattr: %m");
529         ioctl(fd, TIOCSWINSZ, &wsinfo);
530         restore_term = FALSE;
531     }
532 }
533
534 /*
535  * setdtr - control the DTR line on the serial port.
536  * This is called from die(), so it shouldn't call die().
537  */
538 void
539 setdtr(fd, on)
540 int fd, on;
541 {
542     int modembits = TIOCM_DTR;
543
544     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
545 }
546
547
548 /*
549  * open_ppp_loopback - open the device we use for getting
550  * packets in demand mode, and connect it to a ppp interface.
551  * Here we use would use a pty, except that Ultrix ptys are brain-dead.
552  */
553 void
554 open_ppp_loopback()
555 {
556     error("open_ppp_loopback called!");
557     die(1);
558 }
559
560
561 /*
562  * output - Output PPP packet.
563  */
564 void
565 output(unit, p, len)
566     int unit;
567     u_char *p;
568     int len;
569 {
570     if (debug)
571         dbglog("sent %P", p, len);
572
573     if (write(ttyfd, p, len) < 0) {
574         if (errno != EIO)
575             error("write: %m");
576     }
577 }
578
579
580 /*
581  * wait_input - wait until there is data available,
582  * for the length of time specified by *timo (indefinite
583  * if timo is NULL).
584  */
585 void
586 wait_input(timo)
587     struct timeval *timo;
588 {
589     fd_set ready;
590     int n;
591
592     ready = in_fds;
593     n = select(ttyfd+1, &ready, NULL, &ready, timo);
594     if (n < 0 && errno != EINTR)
595         fatal("select: %m");
596 }
597
598
599 /*
600  * add_fd - add an fd to the set that wait_input waits for.
601  */
602 void add_fd(int fd)
603 {
604     FD_SET(fd, &in_fds);
605     if (fd > max_in_fd)
606         max_in_fd = fd;
607 }
608
609 /*
610  * remove_fd - remove an fd from the set that wait_input waits for.
611  */
612 void remove_fd(int fd)
613 {
614     FD_CLR(fd, &in_fds);
615 }
616
617 #if 0
618 /*
619  * wait_loop_output - wait until there is data available on the
620  * loopback, for the length of time specified by *timo (indefinite
621  * if timo is NULL).
622  */
623 void
624 wait_loop_output(timo)
625     struct timeval *timo;
626 {
627     wait_time(timo);
628 }
629
630
631 /*
632  * wait_time - wait for a given length of time or until a
633  * signal is received.
634  */
635 void
636 wait_time(timo)
637     struct timeval *timo;
638 {
639     int n;
640
641     n = select(0, NULL, NULL, NULL, timo);
642     if (n < 0 && errno != EINTR) {
643         error("select: %m");
644         die(1);
645     }
646 }
647 #endif
648
649 /*
650  * read_packet - get a PPP packet from the serial device.
651  */
652 int
653 read_packet(buf)
654     u_char *buf;
655 {
656     int len;
657
658     if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
659         if (errno == EWOULDBLOCK || errno == EINTR)
660             return -1;
661         error("read(fd): %m");
662         die(1);
663     }
664     return len;
665 }
666
667
668 /*
669  * get_loop_output - read characters from the loopback, form them
670  * into frames, and detect when we want to bring the real link up.
671  * Return value is 1 if we need to bring up the link, 0 otherwise.
672  */
673 int
674 get_loop_output()
675 {
676     return 0;
677 }
678
679
680 /*
681  * ppp_send_config - configure the transmit characteristics of
682  * the ppp interface.
683  */
684 void
685 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
686     int unit, mtu;
687     u_int32_t asyncmap;
688     int pcomp, accomp;
689 {
690     u_int x;
691
692     if (ioctl(ppp_fd, PPPIOCSMTU, &mtu) < 0) {
693         error("ioctl(PPPIOCSMTU): %m");
694         quit();
695     }
696
697     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
698         error("ioctl(PPPIOCSASYNCMAP): %m");
699         quit();
700     }
701
702     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
703         error("ioctl (PPPIOCGFLAGS): %m");
704         quit();
705     }
706     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
707     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
708     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
709         error("ioctl(PPPIOCSFLAGS): %m");
710         quit();
711     }
712 }
713
714
715 /*
716  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
717  */
718 void
719 ppp_set_xaccm(unit, accm)
720     int unit;
721     ext_accm accm;
722 {
723     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
724         warn("ioctl(set extended ACCM): %m");
725 }
726
727
728 /*
729  * ppp_recv_config - configure the receive-side characteristics of
730  * the ppp interface.
731  */
732 void
733 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
734     int unit, mru;
735     u_int32_t asyncmap;
736     int pcomp, accomp;
737 {
738     int x;
739
740     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
741         error("ioctl(PPPIOCSMRU): %m");
742         quit();
743     }
744     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
745         error("ioctl(PPPIOCSRASYNCMAP): %m");
746         quit();
747     }
748     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
749         error("ioctl (PPPIOCGFLAGS): %m");
750         quit();
751     }
752     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
753     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
754         error("ioctl(PPPIOCSFLAGS): %m");
755         quit();
756     }
757 }
758
759 /*
760  * ccp_test - ask kernel whether a given compression method
761  * is acceptable for use.  Returns 1 if the method and parameters
762  * are OK, 0 if the method is known but the parameters are not OK
763  * (e.g. code size should be reduced), or -1 if the method is unknown.
764  */
765 int
766 ccp_test(unit, opt_ptr, opt_len, for_transmit)
767     int unit, opt_len, for_transmit;
768     u_char *opt_ptr;
769 {
770     struct ppp_option_data data;
771
772     data.ptr = opt_ptr;
773     data.length = opt_len;
774     data.transmit = for_transmit;
775     if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
776         return 1;
777     return (errno == ENOBUFS)? 0: -1;
778 }
779
780 /*
781  * ccp_flags_set - inform kernel about the current state of CCP.
782  */
783 void
784 ccp_flags_set(unit, isopen, isup)
785     int unit, isopen, isup;
786 {
787     int x;
788
789     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
790         error("ioctl (PPPIOCGFLAGS): %m");
791         return;
792     }
793     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
794     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
795     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
796         error("ioctl(PPPIOCSFLAGS): %m");
797 }
798
799 /*
800  * ccp_fatal_error - returns 1 if decompression was disabled as a
801  * result of an error detected after decompression of a packet,
802  * 0 otherwise.  This is necessary because of patent nonsense.
803  */
804 int
805 ccp_fatal_error(unit)
806     int unit;
807 {
808     int x;
809
810     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
811         error("ioctl(PPPIOCGFLAGS): %m");
812         return 0;
813     }
814     return x & SC_DC_FERROR;
815 }
816
817 /*
818  * get_idle_time - return how long the link has been idle.
819  */
820 int
821 get_idle_time(u, ip)
822     int u;
823     struct ppp_idle *ip;
824 {
825     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
826 }
827
828
829 /*
830  * sifvjcomp - config tcp header compression
831  */
832 int
833 sifvjcomp(u, vjcomp, cidcomp, maxcid)
834     int u, vjcomp, cidcomp, maxcid;
835 {
836     u_int x;
837
838     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
839         error("ioctl (PPPIOCGFLAGS): %m");
840         return 0;
841     }
842     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
843     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
844     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
845         error("ioctl(PPPIOCSFLAGS): %m");
846         return 0;
847     }
848     if (ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
849         error("ioctl(PPPIOCSFLAGS): %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, sizeof (ifr.ifr_name), ifname);
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     if_is_up = 1;
875     return 1;
876 }
877
878 /*
879  * sifnpmode - Set the mode for handling packets for a given NP.
880  */
881 int
882 sifnpmode(u, proto, mode)
883     int u;
884     int proto;
885     enum NPmode mode;
886 {
887     struct npioctl npi;
888
889     npi.protocol = proto;
890     npi.mode = mode;
891     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
892         error("ioctl(set NP %d mode to %d): %m", proto, mode);
893         return 0;
894     }
895     return 1;
896 }
897
898 /*
899  * sifdown - Config the interface down and disable IP.
900  */
901 int
902 sifdown(u)
903     int u;
904 {
905     struct ifreq ifr;
906     int rv;
907     struct npioctl npi;
908
909     rv = 1;
910     npi.protocol = PPP_IP;
911     npi.mode = NPMODE_ERROR;
912     ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
913     /* ignore errors, because ppp_fd might have been closed by now. */
914
915     strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
916     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
917         error("ioctl (SIOCGIFFLAGS): %m");
918         rv = 0;
919     } else {
920         ifr.ifr_flags &= ~IFF_UP;
921         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
922             error("ioctl(SIOCSIFFLAGS): %m");
923             rv = 0;
924         } else
925             if_is_up = 0;
926     }
927     return rv;
928 }
929
930 /*
931  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
932  * if it exists.
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, sizeof (ifr.ifr_name), ifname);
951     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
952     if (m != 0) {
953         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
954         info("Setting interface mask to %s\n", ip_ntoa(m));
955         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
956             error("ioctl(SIOCSIFNETMASK): %m");
957             ret = 0;
958         }
959     }
960     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
961     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
962         error("ioctl(SIOCSIFADDR): %m");
963         ret = 0;
964     }
965     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
966     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
967         error("ioctl(SIOCSIFDSTADDR): %m");
968         ret = 0;
969     }
970     ifaddrs[0] = o;
971     ifaddrs[1] = h;
972     return ret;
973 }
974
975 /*
976  * cifaddr - Clear the interface IP addresses, and delete routes
977  * through the interface if possible.
978  */
979 int
980 cifaddr(u, o, h)
981     int u;
982     u_int32_t o, h;
983 {
984     struct rtentry rt;
985
986     ifaddrs[0] = 0;
987     BZERO(&rt, sizeof(rt));
988     SET_SA_FAMILY(rt.rt_dst, AF_INET);
989     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
990     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
991     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
992     rt.rt_flags = RTF_HOST;
993     if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
994         error("ioctl(SIOCDELRT): %m");
995         return 0;
996     }
997     return 1;
998 }
999
1000 /*
1001  * sifdefaultroute - assign a default route through the address given.
1002  */
1003 int
1004 sifdefaultroute(u, l, g)
1005     int u;
1006     u_int32_t l, g;
1007 {
1008     struct rtentry rt;
1009
1010     BZERO(&rt, sizeof(rt));
1011     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1012     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1013     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1014     rt.rt_flags = RTF_GATEWAY;
1015     if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
1016         error("default route ioctl(SIOCADDRT): %m");
1017         return 0;
1018     }
1019     default_route_gateway = g;
1020     return 1;
1021 }
1022
1023 /*
1024  * cifdefaultroute - delete a default route through the address given.
1025  */
1026 int
1027 cifdefaultroute(u, l, g)
1028     int u;
1029     u_int32_t l, g;
1030 {
1031     struct rtentry rt;
1032
1033     BZERO(&rt, sizeof(rt));
1034     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1035     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1036     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1037     rt.rt_flags = RTF_GATEWAY;
1038     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
1039         warn("default route ioctl(SIOCDELRT): %m");
1040     default_route_gateway = 0;
1041     return 1;
1042 }
1043
1044 /*
1045  * sifproxyarp - Make a proxy ARP entry for the peer.
1046  */
1047 int
1048 sifproxyarp(unit, hisaddr)
1049     int unit;
1050     u_int32_t hisaddr;
1051 {
1052     struct arpreq arpreq;
1053
1054     BZERO(&arpreq, sizeof(arpreq));
1055
1056     /*
1057      * Get the hardware address of an interface on the same subnet
1058      * as our local address.
1059      */
1060     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
1061         error("Cannot determine ethernet address for proxy ARP");
1062         return 0;
1063     }
1064
1065     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1066     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1067     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1068     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1069         error("Couldn't add proxy arp entry: %m");
1070         return 0;
1071     }
1072
1073     proxy_arp_addr = hisaddr;
1074     return 1;
1075 }
1076
1077 /*
1078  * cifproxyarp - Delete the proxy ARP entry for the peer.
1079  */
1080 int
1081 cifproxyarp(unit, hisaddr)
1082     int unit;
1083     u_int32_t hisaddr;
1084 {
1085     struct arpreq arpreq;
1086
1087     BZERO(&arpreq, sizeof(arpreq));
1088     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1089     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1090     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1091         warn("Couldn't delete proxy arp entry: %m");
1092         return 0;
1093     }
1094     proxy_arp_addr = 0;
1095     return 1;
1096 }
1097
1098 /*
1099  * get_ether_addr - get the hardware address of an interface on the
1100  * the same subnet as ipaddr.
1101  */
1102 #define MAX_IFS         32
1103
1104 static int
1105 get_ether_addr(ipaddr, hwaddr)
1106     u_int32_t ipaddr;
1107     struct sockaddr *hwaddr;
1108 {
1109     struct ifreq *ifr, *ifend;
1110     u_int32_t ina, mask;
1111     struct ifreq ifreq;
1112     struct ifconf ifc;
1113     struct ifreq ifs[MAX_IFS];
1114     struct ifdevea ifdevea;
1115
1116     ifc.ifc_len = sizeof(ifs);
1117     ifc.ifc_req = ifs;
1118     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1119         error("ioctl(SIOCGIFCONF): %m");
1120         return 0;
1121     }
1122
1123     /*
1124      * Scan through looking for an interface with an Internet
1125      * address on the same subnet as `ipaddr'.
1126      */
1127     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1128     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1129             ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1130         if (ifr->ifr_addr.sa_family == AF_INET) {
1131             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1132             strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
1133             /*
1134              * Check that the interface is up, and not point-to-point
1135              * or loopback.
1136              */
1137             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1138                 continue;
1139             if ((ifreq.ifr_flags &
1140                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1141                  != (IFF_UP|IFF_BROADCAST))
1142                 continue;
1143             /*
1144              * Get its netmask and check that it's on the right subnet.
1145              */
1146             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1147                 continue;
1148             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1149             if ((ipaddr & mask) != (ina & mask))
1150                 continue;
1151
1152             break;
1153         }
1154     }
1155
1156     if (ifr >= ifend)
1157         return 0;
1158     info("found interface %s for proxy arp", ifr->ifr_name);
1159
1160     /*
1161      * Grab the physical address for this interface.
1162      */
1163     strlcpy(ifdevea.ifr_name, sizeof(ifdevea.ifr_name), ifr->ifr_name);
1164     if (ioctl(sockfd, SIOCRPHYSADDR, &ifdevea) < 0) {
1165         error("Couldn't get h/w address for %s: %m", ifr->ifr_name);
1166         return 0;
1167     }
1168
1169     hwaddr->sa_family = AF_UNSPEC;
1170     BCOPY(ifdevea.current_pa, hwaddr->sa_data, 6);
1171     return 1;
1172 }
1173
1174 /*
1175  * Return user specified netmask, modified by any mask we might determine
1176  * for address `addr' (in network byte order).
1177  * Here we scan through the system's list of interfaces, looking for
1178  * any non-point-to-point interfaces which might appear to be on the same
1179  * network as `addr'.  If we find any, we OR in their netmask to the
1180  * user-specified netmask.
1181  */
1182 u_int32_t
1183 GetMask(addr)
1184     u_int32_t addr;
1185 {
1186     u_int32_t mask, nmask, ina;
1187     struct ifreq *ifr, *ifend, ifreq;
1188     struct ifconf ifc;
1189     struct ifreq ifs[MAX_IFS];
1190
1191     addr = ntohl(addr);
1192     if (IN_CLASSA(addr))        /* determine network mask for address class */
1193         nmask = IN_CLASSA_NET;
1194     else if (IN_CLASSB(addr))
1195         nmask = IN_CLASSB_NET;
1196     else
1197         nmask = IN_CLASSC_NET;
1198     /* class D nets are disallowed by bad_ip_adrs */
1199     mask = netmask | htonl(nmask);
1200
1201     /*
1202      * Scan through the system's network interfaces.
1203      */
1204     ifc.ifc_len = sizeof(ifs);
1205     ifc.ifc_req = ifs;
1206     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1207         warn("ioctl(SIOCGIFCONF): %m");
1208         return mask;
1209     }
1210     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1211     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1212                 ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1213         /*
1214          * Check the interface's internet address.
1215          */
1216         if (ifr->ifr_addr.sa_family != AF_INET)
1217             continue;
1218         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1219         if ((ntohl(ina) & nmask) != (addr & nmask))
1220             continue;
1221         /*
1222          * Check that the interface is up, and not point-to-point or loopback.
1223          */
1224         strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
1225         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1226             continue;
1227         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1228             != IFF_UP)
1229             continue;
1230         /*
1231          * Get its netmask and OR it into our mask.
1232          */
1233         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1234             continue;
1235         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1236     }
1237
1238     return mask;
1239 }
1240
1241 /*
1242  * have_route_to - determine if the system has any route to
1243  * a given IP address.
1244  * For demand mode to work properly, we have to ignore routes
1245  * through our own interface.
1246  */
1247 int have_route_to(u_int32_t addr)
1248 {
1249     return -1;
1250 }
1251
1252
1253 /*
1254  * Use the hostid as part of the random number seed.
1255  */
1256 int
1257 get_host_seed()
1258 {
1259     return gethostid();
1260 }
1261
1262
1263 /*
1264   Seems like strdup() is not part of string package in Ultrix.
1265   If I understood the man-page on the sun this should work.
1266
1267   Robert Olsson
1268 */
1269
1270 char *strdup( in ) char *in;
1271 {
1272   char* dup;
1273   if(! (dup = (char *) malloc( strlen( in ) +1 ))) return NULL;
1274   (void) strcpy( dup, in );
1275   return dup;
1276 }
1277
1278 /*
1279  * This logwtmp() implementation is subject to the following copyright:
1280  *
1281  * Copyright (c) 1988 The Regents of the University of California.
1282  * All rights reserved.
1283  *
1284  * Redistribution and use in source and binary forms are permitted
1285  * provided that the above copyright notice and this paragraph are
1286  * duplicated in all such forms and that any documentation,
1287  * advertising materials, and other materials related to such
1288  * distribution and use acknowledge that the software was developed
1289  * by the University of California, Berkeley.  The name of the
1290  * University may not be used to endorse or promote products derived
1291  * from this software without specific prior written permission.
1292  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1293  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1294  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1295  */
1296
1297 #define WTMPFILE        "/usr/adm/wtmp"
1298
1299 void
1300 logwtmp(line, name, host)
1301     const char *line, *name, *host;
1302 {
1303     int fd;
1304     struct stat buf;
1305     struct utmp ut;
1306
1307     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1308         return;
1309     if (!fstat(fd, &buf)) {
1310         strlcpy(ut.ut_line, sizeof(ut.ut_line), line);
1311         strlcpy(ut.ut_name, sizeof(ut.ut_name), name);
1312         strlcpy(ut.ut_host, sizeof(ut.ut_host), host);
1313         (void)time(&ut.ut_time);
1314         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1315             (void)ftruncate(fd, buf.st_size);
1316     }
1317     close(fd);
1318 }
1319
1320 /*
1321  * Routines for locking and unlocking the serial device, moved here
1322  * from chat.c.
1323  */
1324
1325 #define LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1326
1327 /*
1328  * lock - create a lock file for the named device
1329  */
1330 int
1331 lock(dev)
1332     char *dev;
1333 {
1334     int fd, pid, n;
1335     char *p;
1336     size_t l;
1337
1338     if ((p = strrchr(dev, '/')) != NULL)
1339         dev = p + 1;
1340     l = strlen(LOCK_PREFIX) + strlen(dev) + 1;
1341     lock_file = malloc(l);
1342     if (lock_file == NULL)
1343         novm("lock file name");
1344     slprintf(lock_file, l, "%s%s, LOCK_PREFIX, dev);
1345
1346     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1347         if (errno == EEXIST
1348             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1349             /* Read the lock file to find out who has the device locked */
1350             n = read(fd, &pid, sizeof(pid));
1351             if (n <= 0) {
1352                 error("Can't read pid from lock file %s", lock_file);
1353                 close(fd);
1354             } else {
1355                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1356                     /* pid no longer exists - remove the lock file */
1357                     if (unlink(lock_file) == 0) {
1358                         close(fd);
1359                         notice("Removed stale lock on %s (pid %d)",
1360                                dev, pid);
1361                         continue;
1362                     } else
1363                         warn("Couldn't remove stale lock on %s",
1364                                dev);
1365                 } else
1366                     notice("Device %s is locked by pid %d",
1367                            dev, pid);
1368             }
1369             close(fd);
1370         } else
1371             error("Can't create lock file %s: %m", lock_file);
1372         free(lock_file);
1373         lock_file = NULL;
1374         return -1;
1375     }
1376
1377     pid = getpid();
1378     write(fd, &pid, sizeof pid);
1379
1380     close(fd);
1381     return 0;
1382 }
1383
1384 /*
1385  * unlock - remove our lockfile
1386  */
1387 void
1388 unlock()
1389 {
1390     if (lock_file) {
1391         unlink(lock_file);
1392         free(lock_file);
1393         lock_file = NULL;
1394     }
1395 }