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