1 /*	$OpenBSD: sys-bsd.c,v 1.23 2004/05/26 14:22:54 otto Exp $	*/
2 
3 /*
4  * sys-bsd.c - System-dependent procedures for setting up
5  * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
6  *
7  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. The name "Carnegie Mellon University" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For permission or any legal
24  *    details, please contact
25  *      Office of Technology Transfer
26  *      Carnegie Mellon University
27  *      5000 Forbes Avenue
28  *      Pittsburgh, PA  15213-3890
29  *      (412) 268-4387, fax: (412) 268-7395
30  *      tech-transfer@andrew.cmu.edu
31  *
32  * 4. Redistributions of any form whatsoever must retain the following
33  *    acknowledgment:
34  *    "This product includes software developed by Computing Services
35  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
36  *
37  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
38  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
40  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
43  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44  *
45  * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved.
46  *
47  * Redistribution and use in source and binary forms, with or without
48  * modification, are permitted provided that the following conditions
49  * are met:
50  *
51  * 1. Redistributions of source code must retain the above copyright
52  *    notice, this list of conditions and the following disclaimer.
53  *
54  * 2. Redistributions in binary form must reproduce the above copyright
55  *    notice, this list of conditions and the following disclaimer in
56  *    the documentation and/or other materials provided with the
57  *    distribution.
58  *
59  * 3. The name(s) of the authors of this software must not be used to
60  *    endorse or promote products derived from this software without
61  *    prior written permission.
62  *
63  * 4. Redistributions of any form whatsoever must retain the following
64  *    acknowledgment:
65  *    "This product includes software developed by Paul Mackerras
66  *     <paulus@samba.org>".
67  *
68  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
69  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
70  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
71  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
72  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
73  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
74  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
75  */
76 
77 #ifndef lint
78 #if 0
79 static char rcsid[] = "Id: sys-bsd.c,v 1.31 1998/04/02 12:04:19 paulus Exp $";
80 #else
81 static char rcsid[] = "$OpenBSD: sys-bsd.c,v 1.23 2004/05/26 14:22:54 otto Exp $";
82 #endif
83 #endif
84 
85 /*
86  * TODO:
87  */
88 
89 #include <stdio.h>
90 #include <syslog.h>
91 #include <string.h>
92 #include <stdlib.h>
93 #include <unistd.h>
94 #include <err.h>
95 #include <errno.h>
96 #include <fcntl.h>
97 #include <termios.h>
98 #include <signal.h>
99 #include <util.h>
100 #include <sys/ioctl.h>
101 #include <sys/types.h>
102 #include <sys/socket.h>
103 #include <sys/time.h>
104 #include <sys/stat.h>
105 #include <ifaddrs.h>
106 
107 #ifdef PPP_FILTER
108 #include <net/bpf.h>
109 #endif
110 #include <net/if.h>
111 #include <net/ppp_defs.h>
112 #include <net/if_ppp.h>
113 #include <net/route.h>
114 #include <net/if_dl.h>
115 #include <netinet/in.h>
116 
117 #if RTM_VERSION >= 3
118 #include <sys/param.h>
119 #if defined(NetBSD) && (NetBSD >= 199703)
120 #include <netinet/if_inarp.h>
121 #else	/* NetBSD 1.2D or later */
122 #if defined(__FreeBSD__) || defined(__OpenBSD__)
123 #include <netinet/if_ether.h>
124 #else
125 #include <net/if_ether.h>
126 #endif
127 #endif
128 #endif
129 
130 #include "pppd.h"
131 #include "fsm.h"
132 #include "ipcp.h"
133 
134 #ifdef IPX_CHANGE
135 #include <netipx/ipx.h>
136 #include <netipx/ipx_if.h>
137 #include "ipxcp.h"
138 #endif
139 
140 #define ok_error(num) ((num)==EIO)
141 
142 static int initdisc = -1;	/* Initial TTY discipline for ppp_fd */
143 static int initfdflags = -1;	/* Initial file descriptor flags for ppp_fd */
144 static int ppp_fd = -1;		/* fd which is set to PPP discipline */
145 static int rtm_seq;
146 
147 static int restore_term;	/* 1 => we've munged the terminal */
148 static struct termios inittermios; /* Initial TTY termios */
149 static struct winsize wsinfo;	/* Initial window size info */
150 
151 static char *lock_file;		/* name of lock file created */
152 
153 static int loop_slave = -1;
154 static int loop_master;
155 static char loop_name[20];
156 
157 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
158 
159 static int sockfd;		/* socket for doing interface ioctls */
160 
161 static int if_is_up;		/* the interface is currently up */
162 static u_int32_t ifaddrs[2];	/* local and remote addresses we set */
163 static u_int32_t default_route_gateway;	/* gateway addr for default route */
164 static u_int32_t proxy_arp_addr;	/* remote addr for proxy arp */
165 
166 /* Prototypes for procedures local to this file. */
167 static int dodefaultroute(u_int32_t, int);
168 static int get_ether_addr(u_int32_t, struct sockaddr_dl *);
169 
170 
171 /*
172  * sys_init - System-dependent initialization.
173  */
174 void
sys_init()175 sys_init()
176 {
177     /* Get an internet socket for doing socket ioctl's on. */
178     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
179 	syslog(LOG_ERR, "Couldn't create IP socket: %m");
180 	die(1);
181     }
182 }
183 
184 /*
185  * sys_cleanup - restore any system state we modified before exiting:
186  * mark the interface down, delete default route and/or proxy arp entry.
187  * This should call die() because it's called from die().
188  */
189 void
sys_cleanup()190 sys_cleanup()
191 {
192     struct ifreq ifr;
193 
194     if (if_is_up) {
195 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
196 	if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
197 	    && ((ifr.ifr_flags & IFF_UP) != 0)) {
198 	    ifr.ifr_flags &= ~IFF_UP;
199 	    ioctl(sockfd, SIOCSIFFLAGS, &ifr);
200 	}
201     }
202     if (ifaddrs[0] != 0)
203 	cifaddr(0, ifaddrs[0], ifaddrs[1]);
204     if (default_route_gateway)
205 	cifdefaultroute(0, 0, default_route_gateway);
206     if (proxy_arp_addr)
207 	cifproxyarp(0, proxy_arp_addr);
208 }
209 
210 /*
211  * sys_close - Clean up in a child process before execing.
212  */
213 void
sys_close()214 sys_close()
215 {
216     close(sockfd);
217     if (loop_slave >= 0) {
218 	close(loop_slave);
219 	close(loop_master);
220     }
221 }
222 
223 /*
224  * sys_check_options - check the options that the user specified
225  */
226 void
sys_check_options()227 sys_check_options()
228 {
229 }
230 
231 /*
232  * ppp_available - check whether the system has any ppp interfaces
233  * (in fact we check whether we can do an ioctl on ppp0).
234  */
235 int
ppp_available()236 ppp_available()
237 {
238     int s, ok;
239     struct ifreq ifr;
240     extern char *no_ppp_msg;
241 
242     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
243 	return 1;		/* can't tell */
244 
245     strlcpy(ifr.ifr_name, "ppp0", sizeof(ifr.ifr_name));
246     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
247     close(s);
248 
249     no_ppp_msg = "\
250 PPP device not available. Make sure the device is created with\n\
251 ifconfig and that the kernel supports PPP. See ifconfig(8) and ppp(4).";
252     return ok;
253 }
254 
255 /*
256  * establish_ppp - Turn the serial port into a ppp interface.
257  */
258 void
establish_ppp(fd)259 establish_ppp(fd)
260     int fd;
261 {
262     int pppdisc = PPPDISC;
263     int x;
264 
265     if (demand) {
266 	/*
267 	 * Demand mode - prime the old ppp device to relinquish the unit.
268 	 */
269 	if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
270 	    syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
271 	    die(1);
272 	}
273     }
274 
275     /*
276      * Save the old line discipline of fd, and set it to PPP.
277      */
278     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
279 	syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
280 	die(1);
281     }
282     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
283 	syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
284 	die(1);
285     }
286 
287     if (!demand) {
288 	/*
289 	 * Find out which interface we were given.
290 	 */
291 	if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {
292 	    syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
293 	    die(1);
294 	}
295     } else {
296 	/*
297 	 * Check that we got the same unit again.
298 	 */
299 	if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
300 	    syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
301 	    die(1);
302 	}
303 	if (x != ifunit) {
304 	    syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
305 		   ifunit, x);
306 	    die(1);
307 	}
308 	x = TTYDISC;
309 	ioctl(loop_slave, TIOCSETD, &x);
310     }
311 
312     ppp_fd = fd;
313 
314     /*
315      * Enable debug in the driver if requested.
316      */
317     if (kdebugflag) {
318 	if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
319 	    syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
320 	} else {
321 	    x |= (kdebugflag & 0xFF) * SC_DEBUG;
322 	    if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
323 		syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
324 	}
325     }
326 
327     /*
328      * Set device for non-blocking reads.
329      */
330     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
331 	|| fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
332 	syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
333     }
334 }
335 
336 /*
337  * restore_loop - reattach the ppp unit to the loopback.
338  */
339 void
restore_loop()340 restore_loop()
341 {
342     int x;
343 
344     /*
345      * Transfer the ppp interface back to the loopback.
346      */
347     if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
348 	syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
349 	die(1);
350     }
351     x = PPPDISC;
352     if (ioctl(loop_slave, TIOCSETD, &x) < 0) {
353 	syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
354 	die(1);
355     }
356 
357     /*
358      * Check that we got the same unit again.
359      */
360     if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) {
361 	syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
362 	die(1);
363     }
364     if (x != ifunit) {
365 	syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
366 	       ifunit, x);
367 	die(1);
368     }
369     ppp_fd = loop_slave;
370 }
371 
372 #ifdef IPX_CHANGE
373 /*
374  * sipxfaddr - Config the interface IPX networknumber
375  */
376 int
sipxfaddr(unit,network,node)377 sipxfaddr(unit, network, node)
378 	  int unit;
379 	  u_int32_t network;
380 	  u_char * node;
381 {
382 	int    skfd;
383 	int    result = 1;
384 	struct ifreq         ifr;
385 	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
386 
387 	skfd = socket (AF_IPX, SOCK_DGRAM, 0);
388 	if (skfd < 0) {
389 		if (!ok_error (errno))
390 			syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
391 		result = 0;
392 	} else {
393 		bzero (&ifr, sizeof(ifr));
394 		strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
395 
396 		sipx->sipx_len     = sizeof(*sipx);
397 		sipx->sipx_family  = AF_IPX;
398 		sipx->sipx_type    = IPX_ETHERTYPE_II;
399 		sipx->sipx_port    = 0;
400 		sipx->sipx_network = htonl (network);
401 		memcpy (sipx->sipx_node, node, IPX_HOSTADDRLEN);
402 
403 		/*
404 		 *  Set the IPX device
405 		 */
406 		if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
407 			result = 0;
408 			if (errno != EEXIST && !ok_error (errno)) {
409 				syslog (LOG_DEBUG,
410 					"ioctl(SIOCAIFADDR, CRTITF): %m(%d)",
411 					errno);
412 			} else {
413 				syslog (LOG_WARNING,
414 					"ioctl(SIOCAIFADDR, CRTITF): Address already exists");
415 			}
416 		}
417 		close (skfd);
418 	}
419 
420 	return result;
421 }
422 
423 /*
424  * cipxfaddr - Clear the information for the IPX network. The IPX routes
425  *	       are removed and the device is no longer able to pass IPX
426  *	       frames.
427  */
428 int
cipxfaddr(unit)429 cipxfaddr(unit)
430 	int unit;
431 {
432 	int    skfd;
433 	int    result = 1;
434 	struct ifreq         ifr;
435 	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
436 
437 	skfd = socket (AF_IPX, SOCK_DGRAM, 0);
438 	if (skfd < 0) {
439 		if (! ok_error (errno))
440 			syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
441 		result = 0;
442 	} else {
443 		bzero (&ifr, sizeof(ifr));
444 		strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
445 
446 		sipx->sipx_len     = sizeof(*sipx);
447 		sipx->sipx_family  = AF_IPX;
448 		sipx->sipx_type    = IPX_ETHERTYPE_II;
449 
450 		/*
451 		 *  Set the IPX device
452 		 */
453 		if (ioctl(skfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
454 			if (!ok_error (errno))
455 				syslog (LOG_INFO,
456 					"ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)",
457 					errno);
458 			result = 0;
459 		}
460 		close (skfd);
461 	}
462 
463 	return result;
464 }
465 #endif
466 
467 /*
468  * disestablish_ppp - Restore the serial port to normal operation.
469  * This shouldn't call die() because it's called from die().
470  */
471 void
disestablish_ppp(fd)472 disestablish_ppp(fd)
473     int fd;
474 {
475     /* Reset non-blocking mode on fd. */
476     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
477 	syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
478     initfdflags = -1;
479 
480     /* Restore old line discipline. */
481     if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
482 	syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
483     initdisc = -1;
484 
485     if (fd == ppp_fd)
486 	ppp_fd = -1;
487 }
488 
489 /*
490  * Check whether the link seems not to be 8-bit clean.
491  */
492 void
clean_check()493 clean_check()
494 {
495     int x;
496     char *s;
497 
498     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
499 	s = NULL;
500 	switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
501 	case SC_RCV_B7_0:
502 	    s = "bit 7 set to 1";
503 	    break;
504 	case SC_RCV_B7_1:
505 	    s = "bit 7 set to 0";
506 	    break;
507 	case SC_RCV_EVNP:
508 	    s = "odd parity";
509 	    break;
510 	case SC_RCV_ODDP:
511 	    s = "even parity";
512 	    break;
513 	}
514 	if (s != NULL) {
515 	    syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
516 	    syslog(LOG_WARNING, "All received characters had %s", s);
517 	}
518     }
519 }
520 
521 /*
522  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
523  * at the requested speed, etc.  If `local' is true, set CLOCAL
524  * regardless of whether the modem option was specified.
525  *
526  * For *BSD, we assume that speed_t values numerically equal bits/second.
527  */
528 void
set_up_tty(fd,local)529 set_up_tty(fd, local)
530     int fd, local;
531 {
532     struct termios tios;
533 
534     if (tcgetattr(fd, &tios) < 0) {
535 	syslog(LOG_ERR, "tcgetattr: %m");
536 	die(1);
537     }
538 
539     if (!restore_term) {
540 	inittermios = tios;
541 	ioctl(fd, TIOCGWINSZ, &wsinfo);
542     }
543 
544     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
545     if (crtscts > 0 && modem)
546 	tios.c_cflag |= CRTSCTS;
547     else if (crtscts < 0)
548 	tios.c_cflag &= ~CRTSCTS;
549 
550     tios.c_cflag |= CS8 | CREAD | HUPCL;
551     if (local || !modem)
552 	tios.c_cflag |= CLOCAL;
553     tios.c_iflag = IGNBRK | IGNPAR;
554     tios.c_oflag = 0;
555     tios.c_lflag = 0;
556     tios.c_cc[VMIN] = 1;
557     tios.c_cc[VTIME] = 0;
558 
559     if (crtscts == -2) {
560 	tios.c_iflag |= IXON | IXOFF;
561 	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
562 	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
563     }
564 
565     if (inspeed) {
566 	cfsetospeed(&tios, inspeed);
567 	cfsetispeed(&tios, inspeed);
568     } else {
569 	inspeed = cfgetospeed(&tios);
570 	/*
571 	 * We can't proceed if the serial port speed is 0,
572 	 * since that implies that the serial port is disabled.
573 	 */
574 	if (inspeed == 0) {
575 	    syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
576 		   devnam);
577 	    die(1);
578 	}
579     }
580     baud_rate = inspeed;
581 
582     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
583 	syslog(LOG_ERR, "tcsetattr: %m");
584 	die(1);
585     }
586 
587     restore_term = 1;
588 }
589 
590 /*
591  * restore_tty - restore the terminal to the saved settings.
592  */
593 void
restore_tty(fd)594 restore_tty(fd)
595     int fd;
596 {
597     if (restore_term) {
598 	if (!default_device) {
599 	    /*
600 	     * Turn off echoing, because otherwise we can get into
601 	     * a loop with the tty and the modem echoing to each other.
602 	     * We presume we are the sole user of this tty device, so
603 	     * when we close it, it will revert to its defaults anyway.
604 	     */
605 	    inittermios.c_lflag &= ~(ECHO | ECHONL);
606 	}
607 	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
608 	    if (errno != ENXIO)
609 		syslog(LOG_WARNING, "tcsetattr: %m");
610 	ioctl(fd, TIOCSWINSZ, &wsinfo);
611 	restore_term = 0;
612     }
613 }
614 
615 /*
616  * setdtr - control the DTR line on the serial port.
617  * This is called from die(), so it shouldn't call die().
618  */
619 void
setdtr(fd,on)620 setdtr(fd, on)
621 int fd, on;
622 {
623     int modembits = TIOCM_DTR;
624 
625     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
626 }
627 
628 
629 /*
630  * open_ppp_loopback - open the device we use for getting
631  * packets in demand mode, and connect it to a ppp interface.
632  * Here we use a pty.
633  */
634 void
open_ppp_loopback()635 open_ppp_loopback()
636 {
637     int flags;
638     struct termios tios;
639     int pppdisc = PPPDISC;
640 
641     if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) {
642 	syslog(LOG_ERR, "No free pty for loopback");
643 	die(1);
644     }
645     SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
646 
647     if (tcgetattr(loop_slave, &tios) == 0) {
648 	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
649 	tios.c_cflag |= CS8 | CREAD;
650 	tios.c_iflag = IGNPAR;
651 	tios.c_oflag = 0;
652 	tios.c_lflag = 0;
653 	if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
654 	    syslog(LOG_WARNING, "couldn't set attributes on loopback: %m");
655     }
656 
657     if ((flags = fcntl(loop_master, F_GETFL)) != -1)
658 	if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
659 	    syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m");
660 
661     ppp_fd = loop_slave;
662     if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0) {
663 	syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
664 	die(1);
665     }
666 
667     /*
668      * Find out which interface we were given.
669      */
670     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) {
671 	syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
672 	die(1);
673     }
674 
675     /*
676      * Enable debug in the driver if requested.
677      */
678     if (kdebugflag) {
679 	if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
680 	    syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
681 	} else {
682 	    flags |= (kdebugflag & 0xFF) * SC_DEBUG;
683 	    if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
684 		syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
685 	}
686     }
687 
688 }
689 
690 
691 /*
692  * output - Output PPP packet.
693  */
694 void
output(unit,p,len)695 output(unit, p, len)
696     int unit;
697     u_char *p;
698     int len;
699 {
700     if (debug)
701 	log_packet(p, len, "sent ", LOG_DEBUG);
702 
703     if (write(ttyfd, p, len) < 0) {
704 	if (errno != EIO)
705 	    syslog(LOG_ERR, "write: %m");
706     }
707 }
708 
709 
710 /*
711  * wait_input - wait until there is data available on ttyfd,
712  * for the length of time specified by *timo (indefinite
713  * if timo is NULL).
714  */
715 void
wait_input(timo)716 wait_input(timo)
717     struct timeval *timo;
718 {
719     fd_set *fdsp = NULL;
720     int fdsn;
721     int n;
722 
723     fdsn = howmany(ttyfd+1, NFDBITS) * sizeof(fd_mask);
724     if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
725 	err(1, "malloc");
726     memset(fdsp, 0, fdsn);
727     FD_SET(ttyfd, fdsp);
728 
729     n = select(ttyfd+1, fdsp, NULL, fdsp, timo);
730     if (n < 0 && errno != EINTR) {
731 	syslog(LOG_ERR, "select: %m");
732 	free(fdsp);
733 	die(1);
734     }
735     free(fdsp);
736 }
737 
738 
739 /*
740  * wait_loop_output - wait until there is data available on the
741  * loopback, for the length of time specified by *timo (indefinite
742  * if timo is NULL).
743  */
744 void
wait_loop_output(timo)745 wait_loop_output(timo)
746     struct timeval *timo;
747 {
748     fd_set *fdsp = NULL;
749     int fdsn;
750     int n;
751 
752     fdsn = howmany(loop_master+1, NFDBITS) * sizeof(fd_mask);
753     if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
754 	err(1, "malloc");
755     memset(fdsp, 0, fdsn);
756     FD_SET(loop_master, fdsp);
757 
758     n = select(loop_master + 1, fdsp, NULL, fdsp, timo);
759     if (n < 0 && errno != EINTR) {
760 	syslog(LOG_ERR, "select: %m");
761 	free(fdsp);
762 	die(1);
763     }
764     free(fdsp);
765 }
766 
767 
768 /*
769  * wait_time - wait for a given length of time or until a
770  * signal is received.
771  */
772 void
wait_time(timo)773 wait_time(timo)
774     struct timeval *timo;
775 {
776     int n;
777 
778     n = select(0, NULL, NULL, NULL, timo);
779     if (n < 0 && errno != EINTR) {
780 	syslog(LOG_ERR, "select: %m");
781 	die(1);
782     }
783 }
784 
785 
786 /*
787  * read_packet - get a PPP packet from the serial device.
788  */
789 int
read_packet(buf)790 read_packet(buf)
791     u_char *buf;
792 {
793     int len;
794 
795     if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
796 	if (errno == EWOULDBLOCK || errno == EINTR)
797 	    return -1;
798 	syslog(LOG_ERR, "read: %m");
799 	die(1);
800     }
801     return len;
802 }
803 
804 
805 /*
806  * get_loop_output - read characters from the loopback, form them
807  * into frames, and detect when we want to bring the real link up.
808  * Return value is 1 if we need to bring up the link, 0 otherwise.
809  */
810 int
get_loop_output()811 get_loop_output()
812 {
813     int rv = 0;
814     int n;
815 
816     while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
817 	if (loop_chars(inbuf, n))
818 	    rv = 1;
819     }
820 
821     if (n == 0) {
822 	syslog(LOG_ERR, "eof on loopback");
823 	die(1);
824     } else if (errno != EWOULDBLOCK){
825 	syslog(LOG_ERR, "read from loopback: %m");
826 	die(1);
827     }
828 
829     return rv;
830 }
831 
832 
833 /*
834  * ppp_send_config - configure the transmit characteristics of
835  * the ppp interface.
836  */
837 void
ppp_send_config(unit,mtu,asyncmap,pcomp,accomp)838 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
839     int unit, mtu;
840     u_int32_t asyncmap;
841     int pcomp, accomp;
842 {
843     u_int x;
844     struct ifreq ifr;
845 
846     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
847     ifr.ifr_mtu = mtu;
848     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
849 	syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
850 	quit();
851     }
852 
853     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
854 	syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
855 	quit();
856     }
857 
858     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
859 	syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
860 	quit();
861     }
862     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
863     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
864     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
865 	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
866 	quit();
867     }
868 }
869 
870 
871 /*
872  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
873  */
874 void
ppp_set_xaccm(unit,accm)875 ppp_set_xaccm(unit, accm)
876     int unit;
877     ext_accm accm;
878 {
879     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
880 	syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
881 }
882 
883 
884 /*
885  * ppp_recv_config - configure the receive-side characteristics of
886  * the ppp interface.
887  */
888 void
ppp_recv_config(unit,mru,asyncmap,pcomp,accomp)889 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
890     int unit, mru;
891     u_int32_t asyncmap;
892     int pcomp, accomp;
893 {
894     int x;
895 
896     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
897 	syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
898 	quit();
899     }
900     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
901 	syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
902 	quit();
903     }
904     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
905 	syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
906 	quit();
907     }
908     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
909     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
910 	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
911 	quit();
912     }
913 }
914 
915 /*
916  * ccp_test - ask kernel whether a given compression method
917  * is acceptable for use.  Returns 1 if the method and parameters
918  * are OK, 0 if the method is known but the parameters are not OK
919  * (e.g. code size should be reduced), or -1 if the method is unknown.
920  */
921 int
ccp_test(unit,opt_ptr,opt_len,for_transmit)922 ccp_test(unit, opt_ptr, opt_len, for_transmit)
923     int unit, opt_len, for_transmit;
924     u_char *opt_ptr;
925 {
926     struct ppp_option_data data;
927 
928     data.ptr = opt_ptr;
929     data.length = opt_len;
930     data.transmit = for_transmit;
931     if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
932 	return 1;
933     return (errno == ENOBUFS)? 0: -1;
934 }
935 
936 /*
937  * ccp_flags_set - inform kernel about the current state of CCP.
938  */
939 void
ccp_flags_set(unit,isopen,isup)940 ccp_flags_set(unit, isopen, isup)
941     int unit, isopen, isup;
942 {
943     int x;
944 
945     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
946 	syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
947 	return;
948     }
949     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
950     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
951     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
952 	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
953 }
954 
955 /*
956  * ccp_fatal_error - returns 1 if decompression was disabled as a
957  * result of an error detected after decompression of a packet,
958  * 0 otherwise.  This is necessary because of patent nonsense.
959  */
960 int
ccp_fatal_error(unit)961 ccp_fatal_error(unit)
962     int unit;
963 {
964     int x;
965 
966     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
967 	syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
968 	return 0;
969     }
970     return x & SC_DC_FERROR;
971 }
972 
973 /*
974  * get_idle_time - return how long the link has been idle.
975  */
976 int
get_idle_time(u,ip)977 get_idle_time(u, ip)
978     int u;
979     struct ppp_idle *ip;
980 {
981     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
982 }
983 
984 
985 #ifdef PPP_FILTER
986 /*
987  * set_filters - transfer the pass and active filters to the kernel.
988  */
989 int
set_filters(pass,active)990 set_filters(pass, active)
991     struct bpf_program *pass, *active;
992 {
993     int ret = 1;
994 
995     if (pass->bf_len > 0) {
996 	if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
997 	    syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
998 	    ret = 0;
999 	}
1000     }
1001     if (active->bf_len > 0) {
1002 	if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
1003 	    syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
1004 	    ret = 0;
1005 	}
1006     }
1007     return ret;
1008 }
1009 #endif
1010 
1011 /*
1012  * sifvjcomp - config tcp header compression
1013  */
1014 int
sifvjcomp(u,vjcomp,cidcomp,maxcid)1015 sifvjcomp(u, vjcomp, cidcomp, maxcid)
1016     int u, vjcomp, cidcomp, maxcid;
1017 {
1018     u_int x;
1019 
1020     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
1021 	syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
1022 	return 0;
1023     }
1024     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
1025     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
1026     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
1027 	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
1028 	return 0;
1029     }
1030     if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
1031 	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
1032 	return 0;
1033     }
1034     return 1;
1035 }
1036 
1037 /*
1038  * sifup - Config the interface up and enable IP packets to pass.
1039  */
1040 int
sifup(u)1041 sifup(u)
1042     int u;
1043 {
1044     struct ifreq ifr;
1045 
1046     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1047     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1048 	syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1049 	return 0;
1050     }
1051     ifr.ifr_flags |= IFF_UP;
1052     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1053 	syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1054 	return 0;
1055     }
1056     if_is_up = 1;
1057     return 1;
1058 }
1059 
1060 /*
1061  * sifnpmode - Set the mode for handling packets for a given NP.
1062  */
1063 int
sifnpmode(u,proto,mode)1064 sifnpmode(u, proto, mode)
1065     int u;
1066     int proto;
1067     enum NPmode mode;
1068 {
1069     struct npioctl npi;
1070 
1071     npi.protocol = proto;
1072     npi.mode = mode;
1073     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
1074 	syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
1075 	return 0;
1076     }
1077     return 1;
1078 }
1079 
1080 /*
1081  * sifdown - Config the interface down and disable IP.
1082  */
1083 int
sifdown(u)1084 sifdown(u)
1085     int u;
1086 {
1087     struct ifreq ifr;
1088     int rv;
1089     struct npioctl npi;
1090 
1091     rv = 1;
1092     npi.protocol = PPP_IP;
1093     npi.mode = NPMODE_ERROR;
1094     ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
1095     /* ignore errors, because ppp_fd might have been closed by now. */
1096 
1097     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1098     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1099 	syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1100 	rv = 0;
1101     } else {
1102 	ifr.ifr_flags &= ~IFF_UP;
1103 	if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1104 	    syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1105 	    rv = 0;
1106 	} else
1107 	    if_is_up = 0;
1108     }
1109     return rv;
1110 }
1111 
1112 /*
1113  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
1114  * if it exists.
1115  */
1116 #define SET_SA_FAMILY(addr, family)		\
1117     BZERO((char *) &(addr), sizeof(addr));	\
1118     addr.sa_family = (family); 			\
1119     addr.sa_len = sizeof(addr);
1120 
1121 /*
1122  * sifaddr - Config the interface IP addresses and netmask.
1123  */
1124 int
sifaddr(u,o,h,m)1125 sifaddr(u, o, h, m)
1126     int u;
1127     u_int32_t o, h, m;
1128 {
1129     struct ifaliasreq ifra;
1130     struct ifreq ifr;
1131 
1132     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1133     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1134     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1135     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1136     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1137     if (m != 0) {
1138 	SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
1139 	((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
1140     } else
1141 	BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1142     BZERO(&ifr, sizeof(ifr));
1143     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1144     if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1145 	if (errno != EADDRNOTAVAIL)
1146 	    syslog(LOG_WARNING, "Couldn't remove interface address: %m");
1147     }
1148     if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
1149 	if (errno != EEXIST) {
1150 	    syslog(LOG_ERR, "Couldn't set interface address: %m");
1151 	    return 0;
1152 	}
1153 	syslog(LOG_WARNING,
1154 	       "Couldn't set interface address: Address %s already exists",
1155 	       ip_ntoa(o));
1156     }
1157     ifaddrs[0] = o;
1158     ifaddrs[1] = h;
1159     return 1;
1160 }
1161 
1162 /*
1163  * cifaddr - Clear the interface IP addresses, and delete routes
1164  * through the interface if possible.
1165  */
1166 int
cifaddr(u,o,h)1167 cifaddr(u, o, h)
1168     int u;
1169     u_int32_t o, h;
1170 {
1171     struct ifaliasreq ifra;
1172 
1173     ifaddrs[0] = 0;
1174     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1175     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1176     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1177     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1178     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1179     BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1180     if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
1181 	if (errno != EADDRNOTAVAIL)
1182 	    syslog(LOG_WARNING, "Couldn't delete interface address: %m");
1183 	return 0;
1184     }
1185     return 1;
1186 }
1187 
1188 /*
1189  * sifdefaultroute - assign a default route through the address given.
1190  */
1191 int
sifdefaultroute(u,l,g)1192 sifdefaultroute(u, l, g)
1193     int u;
1194     u_int32_t l, g;
1195 {
1196     return dodefaultroute(g, 's');
1197 }
1198 
1199 /*
1200  * cifdefaultroute - delete a default route through the address given.
1201  */
1202 int
cifdefaultroute(u,l,g)1203 cifdefaultroute(u, l, g)
1204     int u;
1205     u_int32_t l, g;
1206 {
1207     return dodefaultroute(g, 'c');
1208 }
1209 
1210 /*
1211  * dodefaultroute - talk to a routing socket to add/delete a default route.
1212  */
1213 static int
dodefaultroute(g,cmd)1214 dodefaultroute(g, cmd)
1215     u_int32_t g;
1216     int cmd;
1217 {
1218     int routes;
1219     struct {
1220 	struct rt_msghdr	hdr;
1221 	struct sockaddr_in	dst;
1222 	struct sockaddr_in	gway;
1223 	struct sockaddr_in	mask;
1224     } rtmsg;
1225 
1226     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1227 	syslog(LOG_ERR, "Couldn't %s default route: socket: %m",
1228 	       cmd=='s'? "add": "delete");
1229 	return 0;
1230     }
1231 
1232     memset(&rtmsg, 0, sizeof(rtmsg));
1233     rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE;
1234     rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY;
1235     rtmsg.hdr.rtm_version = RTM_VERSION;
1236     rtmsg.hdr.rtm_seq = ++rtm_seq;
1237     rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
1238     rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1239     rtmsg.dst.sin_family = AF_INET;
1240     rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1241     rtmsg.gway.sin_family = AF_INET;
1242     rtmsg.gway.sin_addr.s_addr = g;
1243     rtmsg.mask.sin_len = sizeof(rtmsg.dst);
1244     rtmsg.mask.sin_family = AF_INET;
1245 
1246     rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
1247     if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
1248 	syslog(LOG_ERR, "Couldn't %s default route: %m",
1249 	       cmd=='s'? "add": "delete");
1250 	close(routes);
1251 	return 0;
1252     }
1253 
1254     close(routes);
1255     default_route_gateway = (cmd == 's')? g: 0;
1256     return 1;
1257 }
1258 
1259 #if RTM_VERSION >= 3
1260 
1261 /*
1262  * sifproxyarp - Make a proxy ARP entry for the peer.
1263  */
1264 static struct {
1265     struct rt_msghdr		hdr;
1266     struct sockaddr_inarp	dst;
1267     struct sockaddr_dl		hwa;
1268     char			extra[128];
1269 } arpmsg;
1270 
1271 static int arpmsg_valid;
1272 
1273 int
sifproxyarp(unit,hisaddr)1274 sifproxyarp(unit, hisaddr)
1275     int unit;
1276     u_int32_t hisaddr;
1277 {
1278     int routes;
1279 
1280     /*
1281      * Get the hardware address of an interface on the same subnet
1282      * as our local address.
1283      */
1284     memset(&arpmsg, 0, sizeof(arpmsg));
1285     if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1286 	syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1287 	return 0;
1288     }
1289 
1290     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1291 	syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m");
1292 	return 0;
1293     }
1294 
1295     arpmsg.hdr.rtm_type = RTM_ADD;
1296     arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
1297     arpmsg.hdr.rtm_version = RTM_VERSION;
1298     arpmsg.hdr.rtm_seq = ++rtm_seq;
1299     arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
1300     arpmsg.hdr.rtm_inits = RTV_EXPIRE;
1301     arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1302     arpmsg.dst.sin_family = AF_INET;
1303     arpmsg.dst.sin_addr.s_addr = hisaddr;
1304     arpmsg.dst.sin_other = SIN_PROXY;
1305 
1306     arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1307 	+ arpmsg.hwa.sdl_len;
1308     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1309 	syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1310 	close(routes);
1311 	return 0;
1312     }
1313 
1314     close(routes);
1315     arpmsg_valid = 1;
1316     proxy_arp_addr = hisaddr;
1317     return 1;
1318 }
1319 
1320 /*
1321  * cifproxyarp - Delete the proxy ARP entry for the peer.
1322  */
1323 int
cifproxyarp(unit,hisaddr)1324 cifproxyarp(unit, hisaddr)
1325     int unit;
1326     u_int32_t hisaddr;
1327 {
1328     int routes;
1329 
1330     if (!arpmsg_valid)
1331 	return 0;
1332     arpmsg_valid = 0;
1333 
1334     arpmsg.hdr.rtm_type = RTM_DELETE;
1335     arpmsg.hdr.rtm_seq = ++rtm_seq;
1336 
1337     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1338 	syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m");
1339 	return 0;
1340     }
1341 
1342     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1343 	syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m");
1344 	close(routes);
1345 	return 0;
1346     }
1347 
1348     close(routes);
1349     proxy_arp_addr = 0;
1350     return 1;
1351 }
1352 
1353 #else	/* RTM_VERSION */
1354 
1355 /*
1356  * sifproxyarp - Make a proxy ARP entry for the peer.
1357  */
1358 int
sifproxyarp(unit,hisaddr)1359 sifproxyarp(unit, hisaddr)
1360     int unit;
1361     u_int32_t hisaddr;
1362 {
1363     struct arpreq arpreq;
1364     struct {
1365 	struct sockaddr_dl	sdl;
1366 	char			space[128];
1367     } dls;
1368 
1369     BZERO(&arpreq, sizeof(arpreq));
1370 
1371     /*
1372      * Get the hardware address of an interface on the same subnet
1373      * as our local address.
1374      */
1375     if (!get_ether_addr(hisaddr, &dls.sdl)) {
1376 	syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1377 	return 0;
1378     }
1379 
1380     arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1381     arpreq.arp_ha.sa_family = AF_UNSPEC;
1382     BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1383     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1384     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1385     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1386     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1387 	syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1388 	return 0;
1389     }
1390 
1391     proxy_arp_addr = hisaddr;
1392     return 1;
1393 }
1394 
1395 /*
1396  * cifproxyarp - Delete the proxy ARP entry for the peer.
1397  */
1398 int
cifproxyarp(unit,hisaddr)1399 cifproxyarp(unit, hisaddr)
1400     int unit;
1401     u_int32_t hisaddr;
1402 {
1403     struct arpreq arpreq;
1404 
1405     BZERO(&arpreq, sizeof(arpreq));
1406     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1407     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1408     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1409 	syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m");
1410 	return 0;
1411     }
1412     proxy_arp_addr = 0;
1413     return 1;
1414 }
1415 #endif	/* RTM_VERSION */
1416 
1417 
1418 /*
1419  * get_ether_addr - get the hardware address of an interface on the
1420  * the same subnet as ipaddr.
1421  */
1422 #define MAX_IFS		32
1423 
1424 static int
get_ether_addr(ipaddr,hwaddr)1425 get_ether_addr(ipaddr, hwaddr)
1426     u_int32_t ipaddr;
1427     struct sockaddr_dl *hwaddr;
1428 {
1429     u_int32_t ina, mask;
1430     struct sockaddr_dl *dla;
1431     struct ifaddrs *ifap, *ifa, *ifp;
1432 
1433     if (getifaddrs(&ifap) != 0) {
1434 	syslog(LOG_ERR, "getifaddrs: %m");
1435 	return 0;
1436     }
1437 
1438     /*
1439      * Scan through looking for an interface with an Internet
1440      * address on the same subnet as `ipaddr'.
1441      */
1442     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1443 	if (ifa->ifa_addr->sa_family == AF_INET) {
1444 	    ina = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
1445 	    /*
1446 	     * Check that the interface is up, and not point-to-point
1447 	     * or loopback.
1448 	     */
1449 	    if ((ifa->ifa_flags &
1450 		 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1451 		 != (IFF_UP|IFF_BROADCAST))
1452 		continue;
1453 	    /*
1454 	     * Get its netmask and check that it's on the right subnet.
1455 	     */
1456 	    mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
1457 	    if ((ipaddr & mask) != (ina & mask))
1458 		continue;
1459 
1460 	    break;
1461 	}
1462     }
1463 
1464     if (ifa == NULL) {
1465 	freeifaddrs(ifap);
1466 	return 0;
1467     }
1468     syslog(LOG_INFO, "found interface %s for proxy arp", ifa->ifa_name);
1469 
1470     /*
1471      * Now scan through again looking for a link-level address
1472      * for this interface.
1473      */
1474     ifp = ifa;
1475     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1476 	if (strcmp(ifp->ifa_name, ifa->ifa_name) == 0
1477 	    && ifa->ifa_addr->sa_family == AF_LINK) {
1478 	    /*
1479 	     * Found the link-level address - copy it out
1480 	     */
1481 	    dla = (struct sockaddr_dl *)ifa->ifa_addr;
1482 	    BCOPY(dla, hwaddr, dla->sdl_len);
1483 	    return 1;
1484 	}
1485     }
1486 
1487     freeifaddrs(ifap);
1488     return 0;
1489 }
1490 
1491 /*
1492  * Return user specified netmask, modified by any mask we might determine
1493  * for address `addr' (in network byte order).
1494  * Here we scan through the system's list of interfaces, looking for
1495  * any non-point-to-point interfaces which might appear to be on the same
1496  * network as `addr'.  If we find any, we OR in their netmask to the
1497  * user-specified netmask.
1498  */
1499 u_int32_t
GetMask(addr)1500 GetMask(addr)
1501     u_int32_t addr;
1502 {
1503     u_int32_t mask, nmask, ina;
1504     struct ifaddrs *ifap, *ifa;
1505 
1506     addr = ntohl(addr);
1507     if (IN_CLASSA(addr))	/* determine network mask for address class */
1508 	nmask = IN_CLASSA_NET;
1509     else if (IN_CLASSB(addr))
1510 	nmask = IN_CLASSB_NET;
1511     else
1512 	nmask = IN_CLASSC_NET;
1513     /* class D nets are disallowed by bad_ip_adrs */
1514     mask = netmask | htonl(nmask);
1515 
1516     /*
1517      * Scan through the system's network interfaces.
1518      */
1519     if (getifaddrs(&ifap) != 0) {
1520 	syslog(LOG_WARNING, "getifaddrs: %m");
1521 	return mask;
1522     }
1523     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1524 	/*
1525 	 * Check the interface's internet address.
1526 	 */
1527 	if (ifa->ifa_addr->sa_family != AF_INET)
1528 	    continue;
1529 	ina = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
1530 	if ((ntohl(ina) & nmask) != (addr & nmask))
1531 	    continue;
1532 	/*
1533 	 * Check that the interface is up, and not point-to-point or loopback.
1534 	 */
1535 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1536 	    != IFF_UP)
1537 	    continue;
1538 	/*
1539 	 * Get its netmask and OR it into our mask.
1540 	 */
1541 	mask |= ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
1542     }
1543 
1544     freeifaddrs(ifap);
1545     return mask;
1546 }
1547 
1548 /*
1549  * Use the hostid as part of the random number seed.
1550  */
1551 int
get_host_seed()1552 get_host_seed()
1553 {
1554     return gethostid();
1555 }
1556 
1557 /*
1558  * lock - create a lock file for the named lock device
1559  */
1560 #define	LOCK_PREFIX	"/var/spool/lock/LCK.."
1561 
1562 int
lock(dev)1563 lock(dev)
1564     char *dev;
1565 {
1566     char hdb_lock_buffer[12];
1567     int fd, n;
1568     pid_t pid;
1569     char *p;
1570 
1571     if ((p = strrchr(dev, '/')) != NULL)
1572 	dev = p + 1;
1573     if (asprintf(&lock_file, "%s%s", LOCK_PREFIX, dev) == -1)
1574 	novm("lock file name");
1575 
1576     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1577 	if (errno == EEXIST
1578 	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1579 	    /* Read the lock file to find out who has the device locked */
1580 	    n = read(fd, hdb_lock_buffer, 11);
1581 	    if (n <= 0) {
1582 		syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1583 		close(fd);
1584 	    } else {
1585 		hdb_lock_buffer[n] = 0;
1586 		pid = atoi(hdb_lock_buffer);
1587 		if (kill(pid, 0) == -1 && errno == ESRCH) {
1588 		    /* pid no longer exists - remove the lock file */
1589 		    if (unlink(lock_file) == 0) {
1590 			close(fd);
1591 			syslog(LOG_NOTICE, "Removed stale lock on %s (pid %ld)",
1592 			       dev, (long)pid);
1593 			continue;
1594 		    } else
1595 			syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1596 			       dev);
1597 		} else
1598 		    syslog(LOG_NOTICE, "Device %s is locked by pid %ld",
1599 			   dev, (long)pid);
1600 	    }
1601 	    close(fd);
1602 	} else
1603 	    syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1604 	free(lock_file);
1605 	lock_file = NULL;
1606 	return -1;
1607     }
1608 
1609     snprintf(hdb_lock_buffer, sizeof hdb_lock_buffer, "%10ld\n", (long)getpid());
1610     write(fd, hdb_lock_buffer, 11);
1611 
1612     close(fd);
1613     return 0;
1614 }
1615 
1616 /*
1617  * unlock - remove our lockfile
1618  */
1619 void
unlock()1620 unlock()
1621 {
1622     if (lock_file) {
1623 	unlink(lock_file);
1624 	free(lock_file);
1625 	lock_file = NULL;
1626     }
1627 }
1628