added GetMask
[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.9 1995/04/27 00:45:24 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 (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
405             if (errno != ENXIO)
406                 syslog(LOG_WARNING, "tcsetattr: %m");
407         restore_term = FALSE;
408     }
409 }
410
411 /*
412  * setdtr - control the DTR line on the serial port.
413  * This is called from die(), so it shouldn't call die().
414  */
415 setdtr(fd, on)
416 int fd, on;
417 {
418     int modembits = TIOCM_DTR;
419
420     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
421 }
422
423
424 /*
425  * output - Output PPP packet.
426  */
427 void
428 output(unit, p, len)
429     int unit;
430     u_char *p;
431     int len;
432 {
433     if (unit != 0)
434         MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
435     if (debug)
436         log_packet(p, len, "sent ");
437
438     if (write(fd, p, len) < 0) {
439         syslog(LOG_ERR, "write: %m");
440         die(1);
441     }
442 }
443
444
445 /*
446  * wait_input - wait until there is data available on fd,
447  * for the length of time specified by *timo (indefinite
448  * if timo is NULL).
449  */
450 wait_input(timo)
451     struct timeval *timo;
452 {
453     fd_set ready;
454     int n;
455
456     FD_ZERO(&ready);
457     FD_SET(fd, &ready);
458     n = select(fd+1, &ready, NULL, &ready, timo);
459     if (n < 0 && errno != EINTR) {
460         syslog(LOG_ERR, "select: %m");
461         die(1);
462     }
463 }
464
465
466 /*
467  * read_packet - get a PPP packet from the serial device.
468  */
469 int
470 read_packet(buf)
471     u_char *buf;
472 {
473     int len;
474
475     if ((len = read(fd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
476         if (errno == EWOULDBLOCK || errno == EINTR) {
477             MAINDEBUG((LOG_DEBUG, "read(fd): %m"));
478             return -1;
479         }
480         syslog(LOG_ERR, "read(fd): %m");
481         die(1);
482     }
483     return len;
484 }
485
486
487 /*
488  * ppp_send_config - configure the transmit characteristics of
489  * the ppp interface.
490  */
491 void
492 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
493     int unit, mtu;
494     u_int32_t asyncmap;
495     int pcomp, accomp;
496 {
497     u_int x;
498
499     if (ioctl(fd, PPPIOCSMTU, &mtu) < 0) {
500         syslog(LOG_ERR, "ioctl(PPPIOCSMTU): %m");
501         quit();
502     }
503
504     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
505         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
506         quit();
507     }
508
509     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
510         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
511         quit();
512     }
513     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
514     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
515     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
516         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
517         quit();
518     }
519 }
520
521
522 /*
523  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
524  */
525 void
526 ppp_set_xaccm(unit, accm)
527     int unit;
528     ext_accm accm;
529 {
530     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
531         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
532 }
533
534
535 /*
536  * ppp_recv_config - configure the receive-side characteristics of
537  * the ppp interface.
538  */
539 void
540 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
541     int unit, mru;
542     u_int32_t asyncmap;
543     int pcomp, accomp;
544 {
545     int x;
546
547     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
548         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
549         quit();
550     }
551     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
552         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
553         quit();
554     }
555     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
556         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
557         quit();
558     }
559     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
560     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
561         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
562         quit();
563     }
564 }
565
566 /*
567  * ccp_test - ask kernel whether a given compression method
568  * is acceptable for use.
569  */
570 ccp_test(unit, opt_ptr, opt_len, for_transmit)
571     int unit, opt_len, for_transmit;
572     u_char *opt_ptr;
573 {
574     struct ppp_option_data data;
575
576     data.ptr = opt_ptr;
577     data.length = opt_len;
578     data.transmit = for_transmit;
579     return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
580 }
581
582 /*
583  * ccp_flags_set - inform kernel about the current state of CCP.
584  */
585 void
586 ccp_flags_set(unit, isopen, isup)
587     int unit, isopen, isup;
588 {
589     int x;
590
591     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
592         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
593         return;
594     }
595     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
596     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
597     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
598         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
599 }
600
601 /*
602  * ccp_fatal_error - returns 1 if decompression was disabled as a
603  * result of an error detected after decompression of a packet,
604  * 0 otherwise.  This is necessary because of patent nonsense.
605  */
606 int
607 ccp_fatal_error(unit)
608     int unit;
609 {
610     int x;
611
612     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
613         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
614         return 0;
615     }
616     return x & SC_DC_FERROR;
617 }
618
619 /*
620  * sifvjcomp - config tcp header compression
621  */
622 int
623 sifvjcomp(u, vjcomp, cidcomp, maxcid)
624     int u, vjcomp, cidcomp, maxcid;
625 {
626     u_int x;
627
628     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
629         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
630         return 0;
631     }
632     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
633     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
634     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
635         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
636         return 0;
637     }
638     if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
639         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
640         return 0;
641     }
642     return 1;
643 }
644
645 /*
646  * sifup - Config the interface up and enable IP packets to pass.
647  */
648 #ifndef SC_ENABLE_IP
649 #define SC_ENABLE_IP    0x100   /* compat for old versions of kernel code */
650 #endif
651
652 int
653 sifup(u)
654     int u;
655 {
656     struct ifreq ifr;
657     u_int x;
658     struct npioctl npi;
659
660     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
661     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
662         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
663         return 0;
664     }
665     ifr.ifr_flags |= IFF_UP;
666     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
667         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
668         return 0;
669     }
670     npi.protocol = PPP_IP;
671     npi.mode = NPMODE_PASS;
672     if (ioctl(fd, PPPIOCSNPMODE, &npi) < 0) {
673         if (errno != ENOTTY) {
674             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
675             return 0;
676         }
677         /* for backwards compatibility */
678         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
679             syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
680             return 0;
681         }
682         x |= SC_ENABLE_IP;
683         if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
684             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
685             return 0;
686         }
687     }
688     return 1;
689 }
690
691 /*
692  * sifdown - Config the interface down and disable IP.
693  */
694 int
695 sifdown(u)
696     int u;
697 {
698     struct ifreq ifr;
699     u_int x;
700     int rv;
701     struct npioctl npi;
702
703     rv = 1;
704     npi.protocol = PPP_IP;
705     npi.mode = NPMODE_ERROR;
706     if (ioctl(fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
707         if (errno != ENOTTY) {
708             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
709             rv = 0;
710         } else {
711             /* backwards compatibility */
712             if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
713                 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
714                 rv = 0;
715             } else {
716                 x &= ~SC_ENABLE_IP;
717                 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
718                     syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
719                     rv = 0;
720                 }
721             }
722         }
723     }
724
725     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
726     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
727         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
728         rv = 0;
729     } else {
730         ifr.ifr_flags &= ~IFF_UP;
731         if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
732             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
733             rv = 0;
734         }
735     }
736     return rv;
737 }
738
739 /*
740  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
741  * if it exists.
742  */
743 #define SET_SA_FAMILY(addr, family)             \
744     BZERO((char *) &(addr), sizeof(addr));      \
745     addr.sa_family = (family); 
746
747 /*
748  * sifaddr - Config the interface IP addresses and netmask.
749  */
750 int
751 sifaddr(u, o, h, m)
752     int u;
753     u_int32_t o, h, m;
754 {
755     int ret;
756     struct ifreq ifr;
757
758     ret = 1;
759     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
760     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
761     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
762     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
763         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
764         ret = 0;
765     }
766     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
767     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
768         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
769         ret = 0;
770     }
771     if (m != 0) {
772         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
773         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
774         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
775             syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
776             ret = 0;
777         }
778     }
779     return ret;
780 }
781
782 /*
783  * cifaddr - Clear the interface IP addresses, and delete routes
784  * through the interface if possible.
785  */
786 int
787 cifaddr(u, o, h)
788     int u;
789     u_int32_t o, h;
790 {
791     struct rtentry rt;
792
793     SET_SA_FAMILY(rt.rt_dst, AF_INET);
794     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
795     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
796     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
797     rt.rt_flags = RTF_HOST;
798     if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
799         syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
800         return 0;
801     }
802     return 1;
803 }
804
805 /*
806  * sifdefaultroute - assign a default route through the address given.
807  */
808 int
809 sifdefaultroute(u, g)
810 {
811     struct rtentry rt;
812
813     SET_SA_FAMILY(rt.rt_dst, AF_INET);
814     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
815     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
816     rt.rt_flags = RTF_GATEWAY;
817     if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
818         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
819         return 0;
820     }
821     return 1;
822 }
823
824 /*
825  * cifdefaultroute - delete a default route through the address given.
826  */
827 int
828 cifdefaultroute(u, g)
829 {
830     struct rtentry rt;
831
832     SET_SA_FAMILY(rt.rt_dst, AF_INET);
833     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
834     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
835     rt.rt_flags = RTF_GATEWAY;
836     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
837         syslog(LOG_WARNING, "default route ioctl(SIOCDELRT): %m");
838 }
839
840 /*
841  * sifproxyarp - Make a proxy ARP entry for the peer.
842  */
843 int
844 sifproxyarp(unit, hisaddr)
845     int unit;
846     u_int32_t hisaddr;
847 {
848     struct arpreq arpreq;
849
850     BZERO(&arpreq, sizeof(arpreq));
851
852     /*
853      * Get the hardware address of an interface on the same subnet
854      * as our local address.
855      */
856     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
857         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
858         return 0;
859     }
860
861     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
862     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
863     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
864     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
865         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
866         return 0;
867     }
868
869     return 1;
870 }
871
872 /*
873  * cifproxyarp - Delete the proxy ARP entry for the peer.
874  */
875 int
876 cifproxyarp(unit, hisaddr)
877     int unit;
878     u_int32_t hisaddr;
879 {
880     struct arpreq arpreq;
881
882     BZERO(&arpreq, sizeof(arpreq));
883     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
884     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
885     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
886         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
887         return 0;
888     }
889     return 1;
890 }
891
892 /*
893  * get_ether_addr - get the hardware address of an interface on the
894  * the same subnet as ipaddr.
895  */
896 #define MAX_IFS         32
897
898 int
899 get_ether_addr(ipaddr, hwaddr)
900     u_int32_t ipaddr;
901     struct sockaddr *hwaddr;
902 {
903     struct ifreq *ifr, *ifend, *ifp;
904     u_int32_t ina, mask;
905     struct sockaddr_dl *dla;
906     struct ifreq ifreq;
907     struct ifconf ifc;
908     struct ifreq ifs[MAX_IFS];
909
910     ifc.ifc_len = sizeof(ifs);
911     ifc.ifc_req = ifs;
912     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
913         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
914         return 0;
915     }
916
917     /*
918      * Scan through looking for an interface with an Internet
919      * address on the same subnet as `ipaddr'.
920      */
921     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
922     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
923             ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
924         if (ifr->ifr_addr.sa_family == AF_INET) {
925             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
926             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
927             /*
928              * Check that the interface is up, and not point-to-point
929              * or loopback.
930              */
931             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
932                 continue;
933             if ((ifreq.ifr_flags &
934                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
935                  != (IFF_UP|IFF_BROADCAST))
936                 continue;
937             /*
938              * Get its netmask and check that it's on the right subnet.
939              */
940             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
941                 continue;
942             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
943             if ((ipaddr & mask) != (ina & mask))
944                 continue;
945
946             break;
947         }
948     }
949
950     if (ifr >= ifend)
951         return 0;
952     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
953
954     /*
955      * Now scan through again looking for a link-level address
956      * for this interface.
957      */
958     ifp = ifr;
959     for (ifr = ifc.ifc_req; ifr < ifend; ) {
960         if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
961             && ifr->ifr_addr.sa_family == AF_DLI) {
962             /*
963              * Found the link-level address - copy it out
964              */
965             dla = (struct sockaddr_dl *)&ifr->ifr_addr;
966             hwaddr->sa_family = AF_UNSPEC;
967             BCOPY(dla, hwaddr->sa_data, sizeof(hwaddr->sa_data));
968             return 1;
969         }
970         ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + sizeof(struct sockaddr)
971 );
972     }
973
974     return 0;
975 }
976
977 /*
978  * Return user specified netmask, modified by any mask we might determine
979  * for address `addr' (in network byte order).
980  * Here we scan through the system's list of interfaces, looking for
981  * any non-point-to-point interfaces which might appear to be on the same
982  * network as `addr'.  If we find any, we OR in their netmask to the
983  * user-specified netmask.
984  */
985 u_int32_t
986 GetMask(addr)
987     u_int32_t addr;
988 {
989     u_int32_t mask, nmask, ina;
990     struct ifreq *ifr, *ifend, ifreq;
991     struct ifconf ifc;
992     struct ifreq ifs[MAX_IFS];
993
994     addr = ntohl(addr);
995     if (IN_CLASSA(addr))        /* determine network mask for address class */
996         nmask = IN_CLASSA_NET;
997     else if (IN_CLASSB(addr))
998         nmask = IN_CLASSB_NET;
999     else
1000         nmask = IN_CLASSC_NET;
1001     /* class D nets are disallowed by bad_ip_adrs */
1002     mask = netmask | htonl(nmask);
1003
1004     /*
1005      * Scan through the system's network interfaces.
1006      */
1007     ifc.ifc_len = sizeof(ifs);
1008     ifc.ifc_req = ifs;
1009     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1010         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1011         return mask;
1012     }
1013     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1014     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1015                 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
1016         /*
1017          * Check the interface's internet address.
1018          */
1019         if (ifr->ifr_addr.sa_family != AF_INET)
1020             continue;
1021         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1022         if ((ntohl(ina) & nmask) != (addr & nmask))
1023             continue;
1024         /*
1025          * Check that the interface is up, and not point-to-point or loopback.
1026          */
1027         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1028         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1029             continue;
1030         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1031             != IFF_UP)
1032             continue;
1033         /*
1034          * Get its netmask and OR it into our mask.
1035          */
1036         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1037             continue;
1038         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1039     }
1040
1041     return mask;
1042 }
1043
1044
1045 /*
1046   Seems like strdup() is not part of string package in Ultrix.
1047   If I understood the man-page on the sun this should work.
1048
1049   Robert Olsson
1050 */
1051
1052 char *strdup( in ) char *in;
1053 {
1054   char* dup;
1055   if(! (dup = (char *) malloc( strlen( in ) +1 ))) return NULL;
1056   (void) strcpy( dup, in );
1057   return dup;
1058 }
1059
1060 /*
1061  * This logwtmp() implementation is subject to the following copyright:
1062  *
1063  * Copyright (c) 1988 The Regents of the University of California.
1064  * All rights reserved.
1065  *
1066  * Redistribution and use in source and binary forms are permitted
1067  * provided that the above copyright notice and this paragraph are
1068  * duplicated in all such forms and that any documentation,
1069  * advertising materials, and other materials related to such
1070  * distribution and use acknowledge that the software was developed
1071  * by the University of California, Berkeley.  The name of the
1072  * University may not be used to endorse or promote products derived
1073  * from this software without specific prior written permission.
1074  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1075  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1076  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1077  */
1078
1079 #define WTMPFILE        "/usr/adm/wtmp"
1080
1081 int
1082 logwtmp(line, name, host)
1083     char *line, *name, *host;
1084 {
1085     int fd;
1086     struct stat buf;
1087     struct utmp ut;
1088
1089     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1090         return;
1091     if (!fstat(fd, &buf)) {
1092         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1093         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1094         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1095         (void)time(&ut.ut_time);
1096         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1097             (void)ftruncate(fd, buf.st_size);
1098     }
1099     close(fd);
1100 }
1101
1102 /*
1103  * Routines for locking and unlocking the serial device, moved here
1104  * from chat.c.
1105  */
1106
1107 #define LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1108
1109 /*
1110  * lock - create a lock file for the named device
1111  */
1112 int
1113 lock(dev)
1114     char *dev;
1115 {
1116     int fd, pid, n;
1117     char *p;
1118
1119     if ((p = strrchr(dev, '/')) != NULL)
1120         dev = p + 1;
1121     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1122     if (lock_file == NULL)
1123         novm("lock file name");
1124     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1125
1126     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1127         if (errno == EEXIST
1128             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1129             /* Read the lock file to find out who has the device locked */
1130             n = read(fd, &pid, sizeof(pid));
1131             if (n <= 0) {
1132                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1133                 close(fd);
1134             } else {
1135                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1136                     /* pid no longer exists - remove the lock file */
1137                     if (unlink(lock_file) == 0) {
1138                         close(fd);
1139                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1140                                dev, pid);
1141                         continue;
1142                     } else
1143                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1144                                dev);
1145                 } else
1146                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1147                            dev, pid);
1148             }
1149             close(fd);
1150         } else
1151             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1152         free(lock_file);
1153         lock_file = NULL;
1154         return -1;
1155     }
1156
1157     pid = getpid();
1158     write(fd, &pid, sizeof pid);
1159
1160     close(fd);
1161     return 0;
1162 }
1163
1164 /*
1165  * unlock - remove our lockfile
1166  */
1167 void
1168 unlock()
1169 {
1170     if (lock_file) {
1171         unlink(lock_file);
1172         free(lock_file);
1173         lock_file = NULL;
1174     }
1175 }