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