]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-ultrix.c
Initial revision
[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  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by Carnegie Mellon University.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 #ifndef lint
22 static char rcsid[] = "$Id: sys-ultrix.c,v 1.12 1995/06/30 00:40:06 paulus Exp $";
23 #endif
24
25 /*
26  * TODO:
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <syslog.h>
32 #include <string.h>
33 #include <termios.h>
34 #include <utmp.h>
35 #include <sys/types.h>
36 #include <sys/file.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
39 #include <sys/time.h>
40 #include <sys/errno.h>
41 #include <sys/stat.h>
42
43 #include <net/if.h>
44 #include <net/ppp_defs.h>
45 #include <net/if_ppp.h>
46 #include <net/route.h>
47 #include <netinet/in.h>
48
49 #include "pppd.h"
50
51 static int initdisc = -1;       /* Initial TTY discipline */
52
53 static int      restore_term;   /* 1 => we've munged the terminal */
54 static struct termios inittermios; /* Initial TTY termios */
55
56 static char *lock_file;
57
58 int sockfd;                     /* socket for doing interface ioctls */
59
60 /*
61  * sys_init - System-dependent initialization.
62  */
63 void
64 sys_init()
65 {
66     openlog("pppd", LOG_PID);
67
68     /* Get an internet socket for doing socket ioctl's on. */
69     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
70         syslog(LOG_ERR, "Couldn't create IP socket: %m");
71         die(1);
72     }
73 }
74
75 /*
76  * note_debug_level - note a change in the debug level.
77  */
78 void
79 note_debug_level()
80 {
81 }
82
83
84 /*
85  * daemon - Detach us from the terminal session.
86  */
87 int
88 daemon(nochdir, noclose)
89     int nochdir, noclose;
90 {
91     int pid;
92
93     if ((pid = fork()) < 0)
94         return -1;
95     if (pid != 0)
96         exit(0);                /* parent dies */
97     setsid();
98     if (!nochdir)
99         chdir("/");
100     if (!noclose) {
101         fclose(stdin);          /* don't need stdin, stdout, stderr */
102         fclose(stdout);
103         fclose(stderr);
104     }
105     return 0;
106 }
107
108
109 /*
110  * ppp_available - check whether the system has any ppp interfaces
111  * (in fact we check whether we can do an ioctl on ppp0).
112  */
113
114 int
115 ppp_available()
116 {
117     int s, ok;
118     struct ifreq ifr;
119
120     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
121         return 1;               /* can't tell - maybe we're not root */
122
123     strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
124     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
125     close(s);
126
127     return ok;
128 }
129
130
131 /*
132  * establish_ppp - Turn the serial port into a ppp interface.
133  */
134 void
135 establish_ppp()
136 {
137     int pppdisc = PPPDISC;
138     int x;
139
140     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
141         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
142         die(1);
143     }
144     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
145         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
146         die(1);
147     }
148
149     /*
150      * Find out which interface we were given.
151      */
152     if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {  
153         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
154         die(1);
155     }
156
157     /*
158      * Enable debug in the driver if requested.
159      */
160     if (kdebugflag) {
161         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
162             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
163         } else {
164             x |= (kdebugflag & 0xFF) * SC_DEBUG;
165             if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
166                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
167         }
168     }
169 }
170
171
172 /*
173  * disestablish_ppp - Restore the serial port to normal operation.
174  * This shouldn't call die() because it's called from die().
175  */
176 void
177 disestablish_ppp()
178 {
179     int x;
180     char *s;
181
182     if (initdisc >= 0) {
183         /*
184          * Check whether the link seems not to be 8-bit clean.
185          */
186         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
187             s = NULL;
188             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
189             case SC_RCV_B7_0:
190                 s = "bit 7 set to 1";
191                 break;
192             case SC_RCV_B7_1:
193                 s = "bit 7 set to 0";
194                 break;
195             case SC_RCV_EVNP:
196                 s = "odd parity";
197                 break;
198             case SC_RCV_ODDP:
199                 s = "even parity";
200                 break;
201             }
202             if (s != NULL) {
203                 syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
204                 syslog(LOG_WARNING, "All received characters had %s", s);
205             }
206         }
207         if (ioctl(fd, TIOCSETD, &initdisc) < 0)
208             syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
209     }
210 }
211
212
213 /*
214  * List of valid speeds.
215  */
216 struct speed {
217     int speed_int, speed_val;
218 } speeds[] = {
219 #ifdef B50
220     { 50, B50 },
221 #endif
222 #ifdef B75
223     { 75, B75 },
224 #endif
225 #ifdef B110
226     { 110, B110 },
227 #endif
228 #ifdef B134
229     { 134, B134 },
230 #endif
231 #ifdef B150
232     { 150, B150 },
233 #endif
234 #ifdef B200
235     { 200, B200 },
236 #endif
237 #ifdef B300
238     { 300, B300 },
239 #endif
240 #ifdef B600
241     { 600, B600 },
242 #endif
243 #ifdef B1200
244     { 1200, B1200 },
245 #endif
246 #ifdef B1800
247     { 1800, B1800 },
248 #endif
249 #ifdef B2000
250     { 2000, B2000 },
251 #endif
252 #ifdef B2400
253     { 2400, B2400 },
254 #endif
255 #ifdef B3600
256     { 3600, B3600 },
257 #endif
258 #ifdef B4800
259     { 4800, B4800 },
260 #endif
261 #ifdef B7200
262     { 7200, B7200 },
263 #endif
264 #ifdef B9600
265     { 9600, B9600 },
266 #endif
267 #ifdef B19200
268     { 19200, B19200 },
269 #endif
270 #ifdef B38400
271     { 38400, B38400 },
272 #endif
273 #ifdef EXTA
274     { 19200, EXTA },
275 #endif
276 #ifdef EXTB
277     { 38400, EXTB },
278 #endif
279 #ifdef B57600
280     { 57600, B57600 },
281 #endif
282 #ifdef B115200
283     { 115200, B115200 },
284 #endif
285     { 0, 0 }
286 };
287
288 /*
289  * Translate from bits/second to a speed_t.
290  */
291 int
292 translate_speed(bps)
293     int bps;
294 {
295     struct speed *speedp;
296
297     if (bps == 0)
298         return 0;
299     for (speedp = speeds; speedp->speed_int; speedp++)
300         if (bps == speedp->speed_int)
301             return speedp->speed_val;
302     syslog(LOG_WARNING, "speed %d not supported", bps);
303     return 0;
304 }
305
306 /*
307  * Translate from a speed_t to bits/second.
308  */
309 int
310 baud_rate_of(speed)
311     int speed;
312 {
313     struct speed *speedp;
314
315     if (speed == 0)
316         return 0;
317     for (speedp = speeds; speedp->speed_int; speedp++)
318         if (speed == speedp->speed_val)
319             return speedp->speed_int;
320     return 0;
321 }
322
323 /*
324  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
325  * at the requested speed, etc.  If `local' is true, set CLOCAL
326  * regardless of whether the modem option was specified.
327  */
328 set_up_tty(fd, local)
329     int fd, local;
330 {
331     int speed, x;
332     struct termios tios;
333
334     if (tcgetattr(fd, &tios) < 0) {
335         syslog(LOG_ERR, "tcgetattr: %m");
336         die(1);
337     }
338
339     if (!restore_term)
340         inittermios = tios;
341
342     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
343 #ifdef CRTSCTS
344     if (crtscts > 0)
345         tios.c_cflag |= CRTSCTS;
346     else if (crtscts < 0)
347         tios.c_cflag &= ~CRTSCTS;
348 #endif  /* CRTSCTS */
349
350     tios.c_cflag |= CS8 | CREAD | HUPCL;
351     if (local || !modem)
352         tios.c_cflag |= CLOCAL;
353     tios.c_iflag = IGNBRK | IGNPAR;
354     tios.c_oflag = 0;
355     tios.c_lflag = 0;
356     tios.c_cc[VMIN] = 1;
357     tios.c_cc[VTIME] = 0;
358
359     if (crtscts == 2) {
360         tios.c_iflag |= IXOFF;
361         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
362         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
363     }
364
365     speed = translate_speed(inspeed);
366     if (speed) {
367         cfsetospeed(&tios, speed);
368         cfsetispeed(&tios, speed);
369     } else {
370         speed = cfgetospeed(&tios);
371         /*
372          * We can't proceed if the serial port speed is B0,
373          * since that implies that the serial port is disabled.
374          */
375         if (speed == B0) {
376             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
377                    devnam);
378             die(1);
379         }
380     }
381
382     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
383         syslog(LOG_ERR, "tcsetattr: %m");
384         die(1);
385     }
386
387     x = 0;
388     if (ioctl(fd, (crtscts || modem)? TIOCMODEM: TIOCNMODEM, &x) < 0)
389         syslog(LOG_WARNING, "TIOC(N)MODEM: %m");
390     if (ioctl(fd, (local || !modem)? TIOCNCAR: TIOCCAR) < 0)
391         syslog(LOG_WARNING, "TIOC(N)CAR: %m");
392
393     baud_rate = inspeed = baud_rate_of(speed);
394     restore_term = TRUE;
395 }
396
397 /*
398  * restore_tty - restore the terminal to the saved settings.
399  */
400 void
401 restore_tty()
402 {
403     if (restore_term) {
404         if (!default_device) {
405             /*
406              * Turn off echoing, because otherwise we can get into
407              * a loop with the tty and the modem echoing to each other.
408              * We presume we are the sole user of this tty device, so
409              * when we close it, it will revert to its defaults anyway.
410              */
411             inittermios.c_lflag &= ~(ECHO | ECHONL);
412         }
413         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
414             if (errno != ENXIO)
415                 syslog(LOG_WARNING, "tcsetattr: %m");
416         restore_term = FALSE;
417     }
418 }
419
420 /*
421  * setdtr - control the DTR line on the serial port.
422  * This is called from die(), so it shouldn't call die().
423  */
424 setdtr(fd, on)
425 int fd, on;
426 {
427     int modembits = TIOCM_DTR;
428
429     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
430 }
431
432
433 /*
434  * output - Output PPP packet.
435  */
436 void
437 output(unit, p, len)
438     int unit;
439     u_char *p;
440     int len;
441 {
442     if (unit != 0)
443         MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
444     if (debug)
445         log_packet(p, len, "sent ");
446
447     if (write(fd, p, len) < 0) {
448         syslog(LOG_ERR, "write: %m");
449         die(1);
450     }
451 }
452
453
454 /*
455  * wait_input - wait until there is data available on fd,
456  * for the length of time specified by *timo (indefinite
457  * if timo is NULL).
458  */
459 wait_input(timo)
460     struct timeval *timo;
461 {
462     fd_set ready;
463     int n;
464
465     FD_ZERO(&ready);
466     FD_SET(fd, &ready);
467     n = select(fd+1, &ready, NULL, &ready, timo);
468     if (n < 0 && errno != EINTR) {
469         syslog(LOG_ERR, "select: %m");
470         die(1);
471     }
472 }
473
474
475 /*
476  * read_packet - get a PPP packet from the serial device.
477  */
478 int
479 read_packet(buf)
480     u_char *buf;
481 {
482     int len;
483
484     if ((len = read(fd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
485         if (errno == EWOULDBLOCK || errno == EINTR) {
486             MAINDEBUG((LOG_DEBUG, "read(fd): %m"));
487             return -1;
488         }
489         syslog(LOG_ERR, "read(fd): %m");
490         die(1);
491     }
492     return len;
493 }
494
495
496 /*
497  * ppp_send_config - configure the transmit characteristics of
498  * the ppp interface.
499  */
500 void
501 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
502     int unit, mtu;
503     u_int32_t asyncmap;
504     int pcomp, accomp;
505 {
506     u_int x;
507
508     if (ioctl(fd, PPPIOCSMTU, &mtu) < 0) {
509         syslog(LOG_ERR, "ioctl(PPPIOCSMTU): %m");
510         quit();
511     }
512
513     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
514         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
515         quit();
516     }
517
518     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
519         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
520         quit();
521     }
522     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
523     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
524     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
525         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
526         quit();
527     }
528 }
529
530
531 /*
532  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
533  */
534 void
535 ppp_set_xaccm(unit, accm)
536     int unit;
537     ext_accm accm;
538 {
539     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
540         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
541 }
542
543
544 /*
545  * ppp_recv_config - configure the receive-side characteristics of
546  * the ppp interface.
547  */
548 void
549 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
550     int unit, mru;
551     u_int32_t asyncmap;
552     int pcomp, accomp;
553 {
554     int x;
555
556     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
557         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
558         quit();
559     }
560     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
561         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
562         quit();
563     }
564     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
565         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
566         quit();
567     }
568     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
569     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
570         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
571         quit();
572     }
573 }
574
575 /*
576  * ccp_test - ask kernel whether a given compression method
577  * is acceptable for use.
578  */
579 ccp_test(unit, opt_ptr, opt_len, for_transmit)
580     int unit, opt_len, for_transmit;
581     u_char *opt_ptr;
582 {
583     struct ppp_option_data data;
584
585     data.ptr = opt_ptr;
586     data.length = opt_len;
587     data.transmit = for_transmit;
588     return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
589 }
590
591 /*
592  * ccp_flags_set - inform kernel about the current state of CCP.
593  */
594 void
595 ccp_flags_set(unit, isopen, isup)
596     int unit, isopen, isup;
597 {
598     int x;
599
600     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
601         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
602         return;
603     }
604     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
605     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
606     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
607         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
608 }
609
610 /*
611  * ccp_fatal_error - returns 1 if decompression was disabled as a
612  * result of an error detected after decompression of a packet,
613  * 0 otherwise.  This is necessary because of patent nonsense.
614  */
615 int
616 ccp_fatal_error(unit)
617     int unit;
618 {
619     int x;
620
621     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
622         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
623         return 0;
624     }
625     return x & SC_DC_FERROR;
626 }
627
628 /*
629  * sifvjcomp - config tcp header compression
630  */
631 int
632 sifvjcomp(u, vjcomp, cidcomp, maxcid)
633     int u, vjcomp, cidcomp, maxcid;
634 {
635     u_int x;
636
637     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
638         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
639         return 0;
640     }
641     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
642     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
643     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
644         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
645         return 0;
646     }
647     if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
648         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
649         return 0;
650     }
651     return 1;
652 }
653
654 /*
655  * sifup - Config the interface up and enable IP packets to pass.
656  */
657 #ifndef SC_ENABLE_IP
658 #define SC_ENABLE_IP    0x100   /* compat for old versions of kernel code */
659 #endif
660
661 int
662 sifup(u)
663     int u;
664 {
665     struct ifreq ifr;
666     u_int x;
667     struct npioctl npi;
668
669     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
670     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
671         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
672         return 0;
673     }
674     ifr.ifr_flags |= IFF_UP;
675     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
676         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
677         return 0;
678     }
679     npi.protocol = PPP_IP;
680     npi.mode = NPMODE_PASS;
681     if (ioctl(fd, PPPIOCSNPMODE, &npi) < 0) {
682         if (errno != ENOTTY) {
683             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
684             return 0;
685         }
686         /* for backwards compatibility */
687         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
688             syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
689             return 0;
690         }
691         x |= SC_ENABLE_IP;
692         if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
693             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
694             return 0;
695         }
696     }
697     return 1;
698 }
699
700 /*
701  * sifdown - Config the interface down and disable IP.
702  */
703 int
704 sifdown(u)
705     int u;
706 {
707     struct ifreq ifr;
708     u_int x;
709     int rv;
710     struct npioctl npi;
711
712     rv = 1;
713     npi.protocol = PPP_IP;
714     npi.mode = NPMODE_ERROR;
715     if (ioctl(fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
716         if (errno != ENOTTY) {
717             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
718             rv = 0;
719         } else {
720             /* backwards compatibility */
721             if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
722                 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
723                 rv = 0;
724             } else {
725                 x &= ~SC_ENABLE_IP;
726                 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
727                     syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
728                     rv = 0;
729                 }
730             }
731         }
732     }
733
734     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
735     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
736         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
737         rv = 0;
738     } else {
739         ifr.ifr_flags &= ~IFF_UP;
740         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
741             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
742             rv = 0;
743         }
744     }
745     return rv;
746 }
747
748 /*
749  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
750  * if it exists.
751  */
752 #define SET_SA_FAMILY(addr, family)             \
753     BZERO((char *) &(addr), sizeof(addr));      \
754     addr.sa_family = (family); 
755
756 /*
757  * sifaddr - Config the interface IP addresses and netmask.
758  */
759 int
760 sifaddr(u, o, h, m)
761     int u;
762     u_int32_t o, h, m;
763 {
764     int ret;
765     struct ifreq ifr;
766
767     ret = 1;
768     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
769     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
770     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
771     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
772         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
773         ret = 0;
774     }
775     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
776     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
777         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
778         ret = 0;
779     }
780     if (m != 0) {
781         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
782         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
783         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
784             syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
785             ret = 0;
786         }
787     }
788     return ret;
789 }
790
791 /*
792  * cifaddr - Clear the interface IP addresses, and delete routes
793  * through the interface if possible.
794  */
795 int
796 cifaddr(u, o, h)
797     int u;
798     u_int32_t o, h;
799 {
800     struct rtentry rt;
801
802     SET_SA_FAMILY(rt.rt_dst, AF_INET);
803     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
804     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
805     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
806     rt.rt_flags = RTF_HOST;
807     if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
808         syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
809         return 0;
810     }
811     return 1;
812 }
813
814 /*
815  * sifdefaultroute - assign a default route through the address given.
816  */
817 int
818 sifdefaultroute(u, g)
819 {
820     struct rtentry rt;
821
822     SET_SA_FAMILY(rt.rt_dst, AF_INET);
823     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
824     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
825     rt.rt_flags = RTF_GATEWAY;
826     if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
827         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
828         return 0;
829     }
830     return 1;
831 }
832
833 /*
834  * cifdefaultroute - delete a default route through the address given.
835  */
836 int
837 cifdefaultroute(u, g)
838 {
839     struct rtentry rt;
840
841     SET_SA_FAMILY(rt.rt_dst, AF_INET);
842     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
843     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
844     rt.rt_flags = RTF_GATEWAY;
845     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
846         syslog(LOG_WARNING, "default route ioctl(SIOCDELRT): %m");
847 }
848
849 /*
850  * sifproxyarp - Make a proxy ARP entry for the peer.
851  */
852 int
853 sifproxyarp(unit, hisaddr)
854     int unit;
855     u_int32_t hisaddr;
856 {
857     struct arpreq arpreq;
858
859     BZERO(&arpreq, sizeof(arpreq));
860
861     /*
862      * Get the hardware address of an interface on the same subnet
863      * as our local address.
864      */
865     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
866         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
867         return 0;
868     }
869
870     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
871     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
872     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
873     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
874         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
875         return 0;
876     }
877
878     return 1;
879 }
880
881 /*
882  * cifproxyarp - Delete the proxy ARP entry for the peer.
883  */
884 int
885 cifproxyarp(unit, hisaddr)
886     int unit;
887     u_int32_t hisaddr;
888 {
889     struct arpreq arpreq;
890
891     BZERO(&arpreq, sizeof(arpreq));
892     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
893     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
894     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
895         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
896         return 0;
897     }
898     return 1;
899 }
900
901 /*
902  * get_ether_addr - get the hardware address of an interface on the
903  * the same subnet as ipaddr.
904  */
905 #define MAX_IFS         32
906
907 int
908 get_ether_addr(ipaddr, hwaddr)
909     u_int32_t ipaddr;
910     struct sockaddr *hwaddr;
911 {
912     struct ifreq *ifr, *ifend, *ifp;
913     u_int32_t ina, mask;
914     struct sockaddr_dl *dla;
915     struct ifreq ifreq;
916     struct ifconf ifc;
917     struct ifreq ifs[MAX_IFS];
918     struct ifdevea ifdevea;
919
920     ifc.ifc_len = sizeof(ifs);
921     ifc.ifc_req = ifs;
922     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
923         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
924         return 0;
925     }
926
927     /*
928      * Scan through looking for an interface with an Internet
929      * address on the same subnet as `ipaddr'.
930      */
931     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
932     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
933             ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
934         if (ifr->ifr_addr.sa_family == AF_INET) {
935             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
936             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
937             /*
938              * Check that the interface is up, and not point-to-point
939              * or loopback.
940              */
941             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
942                 continue;
943             if ((ifreq.ifr_flags &
944                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
945                  != (IFF_UP|IFF_BROADCAST))
946                 continue;
947             /*
948              * Get its netmask and check that it's on the right subnet.
949              */
950             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
951                 continue;
952             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
953             if ((ipaddr & mask) != (ina & mask))
954                 continue;
955
956             break;
957         }
958     }
959
960     if (ifr >= ifend)
961         return 0;
962     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
963
964     /*
965      * Grab the physical address for this interface.
966      */
967     strncpy(ifdevea.ifr_name, ifr->ifr_name, sizeof(ifdevea.ifr_name));
968     if (ioctl(sockfd, SIOCRPHYSADDR, &ifdevea) < 0) {
969         syslog(LOG_ERR, "Couldn't get h/w address for %s: %m", ifr->ifr_name);
970         return 0;
971     }
972
973     hwaddr->sa_family = AF_UNSPEC;
974     BCOPY(ifdevea.current_pa, hwaddr->sa_data, 6);
975     return 1;
976 }
977
978 /*
979  * Return user specified netmask, modified by any mask we might determine
980  * for address `addr' (in network byte order).
981  * Here we scan through the system's list of interfaces, looking for
982  * any non-point-to-point interfaces which might appear to be on the same
983  * network as `addr'.  If we find any, we OR in their netmask to the
984  * user-specified netmask.
985  */
986 u_int32_t
987 GetMask(addr)
988     u_int32_t addr;
989 {
990     u_int32_t mask, nmask, ina;
991     struct ifreq *ifr, *ifend, ifreq;
992     struct ifconf ifc;
993     struct ifreq ifs[MAX_IFS];
994
995     addr = ntohl(addr);
996     if (IN_CLASSA(addr))        /* determine network mask for address class */
997         nmask = IN_CLASSA_NET;
998     else if (IN_CLASSB(addr))
999         nmask = IN_CLASSB_NET;
1000     else
1001         nmask = IN_CLASSC_NET;
1002     /* class D nets are disallowed by bad_ip_adrs */
1003     mask = netmask | htonl(nmask);
1004
1005     /*
1006      * Scan through the system's network interfaces.
1007      */
1008     ifc.ifc_len = sizeof(ifs);
1009     ifc.ifc_req = ifs;
1010     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1011         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1012         return mask;
1013     }
1014     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1015     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1016                 ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1017         /*
1018          * Check the interface's internet address.
1019          */
1020         if (ifr->ifr_addr.sa_family != AF_INET)
1021             continue;
1022         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1023         if ((ntohl(ina) & nmask) != (addr & nmask))
1024             continue;
1025         /*
1026          * Check that the interface is up, and not point-to-point or loopback.
1027          */
1028         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1029         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1030             continue;
1031         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1032             != IFF_UP)
1033             continue;
1034         /*
1035          * Get its netmask and OR it into our mask.
1036          */
1037         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1038             continue;
1039         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1040     }
1041
1042     return mask;
1043 }
1044
1045
1046 /*
1047   Seems like strdup() is not part of string package in Ultrix.
1048   If I understood the man-page on the sun this should work.
1049
1050   Robert Olsson
1051 */
1052
1053 char *strdup( in ) char *in;
1054 {
1055   char* dup;
1056   if(! (dup = (char *) malloc( strlen( in ) +1 ))) return NULL;
1057   (void) strcpy( dup, in );
1058   return dup;
1059 }
1060
1061 /*
1062  * This logwtmp() implementation is subject to the following copyright:
1063  *
1064  * Copyright (c) 1988 The Regents of the University of California.
1065  * All rights reserved.
1066  *
1067  * Redistribution and use in source and binary forms are permitted
1068  * provided that the above copyright notice and this paragraph are
1069  * duplicated in all such forms and that any documentation,
1070  * advertising materials, and other materials related to such
1071  * distribution and use acknowledge that the software was developed
1072  * by the University of California, Berkeley.  The name of the
1073  * University may not be used to endorse or promote products derived
1074  * from this software without specific prior written permission.
1075  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1076  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1077  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1078  */
1079
1080 #define WTMPFILE        "/usr/adm/wtmp"
1081
1082 int
1083 logwtmp(line, name, host)
1084     char *line, *name, *host;
1085 {
1086     int fd;
1087     struct stat buf;
1088     struct utmp ut;
1089
1090     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1091         return;
1092     if (!fstat(fd, &buf)) {
1093         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1094         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1095         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1096         (void)time(&ut.ut_time);
1097         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1098             (void)ftruncate(fd, buf.st_size);
1099     }
1100     close(fd);
1101 }
1102
1103 /*
1104  * Routines for locking and unlocking the serial device, moved here
1105  * from chat.c.
1106  */
1107
1108 #define LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1109
1110 /*
1111  * lock - create a lock file for the named device
1112  */
1113 int
1114 lock(dev)
1115     char *dev;
1116 {
1117     int fd, pid, n;
1118     char *p;
1119
1120     if ((p = strrchr(dev, '/')) != NULL)
1121         dev = p + 1;
1122     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1123     if (lock_file == NULL)
1124         novm("lock file name");
1125     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1126
1127     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1128         if (errno == EEXIST
1129             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1130             /* Read the lock file to find out who has the device locked */
1131             n = read(fd, &pid, sizeof(pid));
1132             if (n <= 0) {
1133                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1134                 close(fd);
1135             } else {
1136                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1137                     /* pid no longer exists - remove the lock file */
1138                     if (unlink(lock_file) == 0) {
1139                         close(fd);
1140                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1141                                dev, pid);
1142                         continue;
1143                     } else
1144                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1145                                dev);
1146                 } else
1147                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1148                            dev, pid);
1149             }
1150             close(fd);
1151         } else
1152             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1153         free(lock_file);
1154         lock_file = NULL;
1155         return -1;
1156     }
1157
1158     pid = getpid();
1159     write(fd, &pid, sizeof pid);
1160
1161     close(fd);
1162     return 0;
1163 }
1164
1165 /*
1166  * unlock - remove our lockfile
1167  */
1168 void
1169 unlock()
1170 {
1171     if (lock_file) {
1172         unlink(lock_file);
1173         free(lock_file);
1174         lock_file = NULL;
1175     }
1176 }