Bug Summary

File:src/usr.sbin/pppd/sys-bsd.c
Warning:line 615, column 5
Attempt to free released memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sys-bsd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/pppd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I . -I /usr/src/usr.sbin/pppd/../../lib/libpcap -D HAVE_PATHS_H -D PPP_FILTER -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/pppd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/pppd/sys-bsd.c
1/* $OpenBSD: sys-bsd.c,v 1.32 2021/10/24 21:24:19 deraadt 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/*
78 * TODO:
79 */
80
81#include <sys/types.h>
82#include <sys/ioctl.h>
83#include <sys/socket.h>
84#include <sys/time.h>
85#include <sys/stat.h>
86
87#include <stdio.h>
88#include <syslog.h>
89#include <string.h>
90#include <stdlib.h>
91#include <unistd.h>
92#include <err.h>
93#include <errno(*__errno()).h>
94#include <fcntl.h>
95#include <termios.h>
96#include <signal.h>
97#include <util.h>
98#include <ifaddrs.h>
99
100#ifdef PPP_FILTER1
101#include <net/bpf.h>
102#endif
103#include <net/if.h>
104#include <net/ppp_defs.h>
105#include <net/if_ppp.h>
106#include <net/route.h>
107#include <net/if_dl.h>
108#include <netinet/in.h>
109#include <netinet/if_ether.h>
110
111#include "pppd.h"
112#include "fsm.h"
113#include "ipcp.h"
114
115#define ok_error(num)((num)==5) ((num)==EIO5)
116
117static int initdisc = -1; /* Initial TTY discipline for ppp_fd */
118static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */
119static int ppp_fd = -1; /* fd which is set to PPP discipline */
120static int rtm_seq;
121
122static int restore_term; /* 1 => we've munged the terminal */
123static struct termios inittermios; /* Initial TTY termios */
124static struct winsize wsinfo; /* Initial window size info */
125
126static char *lock_file; /* name of lock file created */
127
128static int loop_slave = -1;
129static int loop_master;
130static char loop_name[20];
131
132static unsigned char inbuf[512]; /* buffer for chars read from loopback */
133
134static int sockfd; /* socket for doing interface ioctls */
135
136static int if_is_up; /* the interface is currently up */
137static u_int32_t ifaddrs[2]; /* local and remote addresses we set */
138static u_int32_t default_route_gateway; /* gateway addr for default route */
139static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */
140
141/* Prototypes for procedures local to this file. */
142static int dodefaultroute(u_int32_t, int);
143static int get_ether_addr(u_int32_t, struct sockaddr_dl *);
144
145
146/*
147 * sys_init - System-dependent initialization.
148 */
149void
150sys_init()
151{
152 /* Get an internet socket for doing socket ioctl's on. */
153 if ((sockfd = socket(AF_INET2, SOCK_DGRAM2, 0)) == -1) {
154 syslog(LOG_ERR3, "Couldn't create IP socket: %m");
155 die(1);
156 }
157}
158
159/*
160 * sys_cleanup - restore any system state we modified before exiting:
161 * mark the interface down, delete default route and/or proxy arp entry.
162 * This should call die() because it's called from die().
163 */
164void
165sys_cleanup()
166{
167 struct ifreq ifr;
168
169 if (if_is_up) {
170 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
171 if (ioctl(sockfd, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, &ifr) == 0
172 && ((ifr.ifr_flagsifr_ifru.ifru_flags & IFF_UP0x1) != 0)) {
173 ifr.ifr_flagsifr_ifru.ifru_flags &= ~IFF_UP0x1;
174 ioctl(sockfd, SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
, &ifr);
175 }
176 }
177 if (ifaddrs[0] != 0)
178 cifaddr(0, ifaddrs[0], ifaddrs[1]);
179 if (default_route_gateway)
180 cifdefaultroute(0, 0, default_route_gateway);
181 if (proxy_arp_addr)
182 cifproxyarp(0, proxy_arp_addr);
183}
184
185/*
186 * sys_close - Clean up in a child process before execing.
187 */
188void
189sys_close()
190{
191 close(sockfd);
192 if (loop_slave >= 0) {
193 close(loop_slave);
194 close(loop_master);
195 }
196}
197
198/*
199 * sys_check_options - check the options that the user specified
200 */
201void
202sys_check_options()
203{
204}
205
206/*
207 * ppp_available - check whether the system has any ppp interfaces
208 * (in fact we check whether we can do an ioctl on ppp0).
209 */
210int
211ppp_available()
212{
213 int s, ok;
214 struct ifreq ifr;
215 extern char *no_ppp_msg;
216
217 if ((s = socket(AF_INET2, SOCK_DGRAM2, 0)) == -1)
218 return 1; /* can't tell */
219
220 strlcpy(ifr.ifr_name, "ppp0", sizeof(ifr.ifr_name));
221 ok = ioctl(s, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, (caddr_t) &ifr) == 0;
222 close(s);
223
224 no_ppp_msg = "\
225PPP device not available. Make sure the device is created with\n\
226ifconfig and that the kernel supports PPP. See ifconfig(8) and ppp(4).";
227 return ok;
228}
229
230/*
231 * establish_ppp - Turn the serial port into a ppp interface.
232 */
233void
234establish_ppp(fd)
235 int fd;
236{
237 int pppdisc = PPPDISC5;
238 int x;
239
240 if (demand) {
241 /*
242 * Demand mode - prime the old ppp device to relinquish the unit.
243 */
244 if (ioctl(ppp_fd, PPPIOCXFERUNIT((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('t')) << 8) | ((78)))
, 0) == -1) {
245 syslog(LOG_ERR3, "ioctl(transfer ppp unit): %m");
246 die(1);
247 }
248 }
249
250 /*
251 * Save the old line discipline of fd, and set it to PPP.
252 */
253 if (ioctl(fd, TIOCGETD((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((26)))
, &initdisc) == -1) {
254 syslog(LOG_ERR3, "ioctl(TIOCGETD): %m");
255 die(1);
256 }
257 if (ioctl(fd, TIOCSETD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((27)))
, &pppdisc) == -1) {
258 syslog(LOG_ERR3, "ioctl(TIOCSETD): %m");
259 die(1);
260 }
261
262 if (!demand) {
263 /*
264 * Find out which interface we were given.
265 */
266 if (ioctl(fd, PPPIOCGUNIT((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((86)))
, &ifunit) == -1) {
267 syslog(LOG_ERR3, "ioctl(PPPIOCGUNIT): %m");
268 die(1);
269 }
270 } else {
271 /*
272 * Check that we got the same unit again.
273 */
274 if (ioctl(fd, PPPIOCGUNIT((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((86)))
, &x) == -1) {
275 syslog(LOG_ERR3, "ioctl(PPPIOCGUNIT): %m");
276 die(1);
277 }
278 if (x != ifunit) {
279 syslog(LOG_ERR3, "transfer_ppp failed: wanted unit %d, got %d",
280 ifunit, x);
281 die(1);
282 }
283 x = TTYDISC0;
284 ioctl(loop_slave, TIOCSETD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((27)))
, &x);
285 }
286
287 ppp_fd = fd;
288
289 /*
290 * Enable debug in the driver if requested.
291 */
292 if (kdebugflag) {
293 if (ioctl(fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &x) == -1) {
294 syslog(LOG_WARNING4, "ioctl (PPPIOCGFLAGS): %m");
295 } else {
296 x |= (kdebugflag & 0xFF) * SC_DEBUG0x00010000;
297 if (ioctl(fd, PPPIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((89)))
, (caddr_t) &x) == -1)
298 syslog(LOG_WARNING4, "ioctl(PPPIOCSFLAGS): %m");
299 }
300 }
301
302 /*
303 * Set device for non-blocking reads.
304 */
305 if ((initfdflags = fcntl(fd, F_GETFL3)) == -1
306 || fcntl(fd, F_SETFL4, initfdflags | O_NONBLOCK0x0004) == -1) {
307 syslog(LOG_WARNING4, "Couldn't set device to non-blocking mode: %m");
308 }
309}
310
311/*
312 * restore_loop - reattach the ppp unit to the loopback.
313 */
314void
315restore_loop()
316{
317 int x;
318
319 /*
320 * Transfer the ppp interface back to the loopback.
321 */
322 if (ioctl(ppp_fd, PPPIOCXFERUNIT((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('t')) << 8) | ((78)))
, 0) == -1) {
323 syslog(LOG_ERR3, "ioctl(transfer ppp unit): %m");
324 die(1);
325 }
326 x = PPPDISC5;
327 if (ioctl(loop_slave, TIOCSETD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((27)))
, &x) == -1) {
328 syslog(LOG_ERR3, "ioctl(TIOCSETD): %m");
329 die(1);
330 }
331
332 /*
333 * Check that we got the same unit again.
334 */
335 if (ioctl(loop_slave, PPPIOCGUNIT((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((86)))
, &x) == -1) {
336 syslog(LOG_ERR3, "ioctl(PPPIOCGUNIT): %m");
337 die(1);
338 }
339 if (x != ifunit) {
340 syslog(LOG_ERR3, "transfer_ppp failed: wanted unit %d, got %d",
341 ifunit, x);
342 die(1);
343 }
344 ppp_fd = loop_slave;
345}
346
347/*
348 * disestablish_ppp - Restore the serial port to normal operation.
349 * This shouldn't call die() because it's called from die().
350 */
351void
352disestablish_ppp(fd)
353 int fd;
354{
355 /* Reset non-blocking mode on fd. */
356 if (initfdflags != -1 && fcntl(fd, F_SETFL4, initfdflags) == -1)
357 syslog(LOG_WARNING4, "Couldn't restore device fd flags: %m");
358 initfdflags = -1;
359
360 /* Restore old line discipline. */
361 if (initdisc >= 0 && ioctl(fd, TIOCSETD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((27)))
, &initdisc) == -1)
362 syslog(LOG_ERR3, "ioctl(TIOCSETD): %m");
363 initdisc = -1;
364
365 if (fd == ppp_fd)
366 ppp_fd = -1;
367}
368
369/*
370 * Check whether the link seems not to be 8-bit clean.
371 */
372void
373clean_check()
374{
375 int x;
376 char *s;
377
378 if (ioctl(ppp_fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &x) == 0) {
379 s = NULL((void *)0);
380 switch (~x & (SC_RCV_B7_00x01000000|SC_RCV_B7_10x02000000|SC_RCV_EVNP0x04000000|SC_RCV_ODDP0x08000000)) {
381 case SC_RCV_B7_00x01000000:
382 s = "bit 7 set to 1";
383 break;
384 case SC_RCV_B7_10x02000000:
385 s = "bit 7 set to 0";
386 break;
387 case SC_RCV_EVNP0x04000000:
388 s = "odd parity";
389 break;
390 case SC_RCV_ODDP0x08000000:
391 s = "even parity";
392 break;
393 }
394 if (s != NULL((void *)0)) {
395 syslog(LOG_WARNING4, "Serial link is not 8-bit clean:");
396 syslog(LOG_WARNING4, "All received characters had %s", s);
397 }
398 }
399}
400
401/*
402 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
403 * at the requested speed, etc. If `local' is true, set CLOCAL
404 * regardless of whether the modem option was specified.
405 *
406 * For *BSD, we assume that speed_t values numerically equal bits/second.
407 */
408void
409set_up_tty(fd, local)
410 int fd, local;
411{
412 struct termios tios;
413
414 if (tcgetattr(fd, &tios) == -1) {
415 syslog(LOG_ERR3, "tcgetattr: %m");
416 die(1);
417 }
418
419 if (!restore_term) {
420 inittermios = tios;
421 ioctl(fd, TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff
) << 16) | ((('t')) << 8) | ((104)))
, &wsinfo);
422 }
423
424 tios.c_cflag &= ~(CSIZE0x00000300 | CSTOPB0x00000400 | PARENB0x00001000 | CLOCAL0x00008000);
425 if (crtscts > 0 && modem)
426 tios.c_cflag |= CRTSCTS0x00010000;
427 else if (crtscts < 0)
428 tios.c_cflag &= ~CRTSCTS0x00010000;
429
430 tios.c_cflag |= CS80x00000300 | CREAD0x00000800 | HUPCL0x00004000;
431 if (local || !modem)
432 tios.c_cflag |= CLOCAL0x00008000;
433 tios.c_iflag = IGNBRK0x00000001 | IGNPAR0x00000004;
434 tios.c_oflag = 0;
435 tios.c_lflag = 0;
436 tios.c_cc[VMIN16] = 1;
437 tios.c_cc[VTIME17] = 0;
438
439 if (crtscts == -2) {
440 tios.c_iflag |= IXON0x00000200 | IXOFF0x00000400;
441 tios.c_cc[VSTOP13] = 0x13; /* DC3 = XOFF = ^S */
442 tios.c_cc[VSTART12] = 0x11; /* DC1 = XON = ^Q */
443 }
444
445 if (inspeed) {
446 cfsetospeed(&tios, inspeed);
447 cfsetispeed(&tios, inspeed);
448 } else {
449 inspeed = cfgetospeed(&tios);
450 /*
451 * We can't proceed if the serial port speed is 0,
452 * since that implies that the serial port is disabled.
453 */
454 if (inspeed == 0) {
455 syslog(LOG_ERR3, "Baud rate for %s is 0; need explicit baud rate",
456 devnam);
457 die(1);
458 }
459 }
460 baud_rate = inspeed;
461
462 if (tcsetattr(fd, TCSAFLUSH2, &tios) == -1) {
463 syslog(LOG_ERR3, "tcsetattr: %m");
464 die(1);
465 }
466
467 restore_term = 1;
468}
469
470/*
471 * restore_tty - restore the terminal to the saved settings.
472 */
473void
474restore_tty(fd)
475 int fd;
476{
477 if (restore_term) {
478 if (!default_device) {
479 /*
480 * Turn off echoing, because otherwise we can get into
481 * a loop with the tty and the modem echoing to each other.
482 * We presume we are the sole user of this tty device, so
483 * when we close it, it will revert to its defaults anyway.
484 */
485 inittermios.c_lflag &= ~(ECHO0x00000008 | ECHONL0x00000010);
486 }
487 if (tcsetattr(fd, TCSAFLUSH2, &inittermios) == -1)
488 if (errno(*__errno()) != ENXIO6)
489 syslog(LOG_WARNING4, "tcsetattr: %m");
490 ioctl(fd, TIOCSWINSZ((unsigned long)0x80000000 | ((sizeof(struct winsize) & 0x1fff
) << 16) | ((('t')) << 8) | ((103)))
, &wsinfo);
491 restore_term = 0;
492 }
493}
494
495/*
496 * setdtr - control the DTR line on the serial port.
497 * This is called from die(), so it shouldn't call die().
498 */
499void
500setdtr(fd, on)
501int fd, on;
502{
503 int modembits = TIOCM_DTR0002;
504
505 ioctl(fd, (on? TIOCMBIS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((108)))
: TIOCMBIC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((107)))
), &modembits);
506}
507
508
509/*
510 * open_ppp_loopback - open the device we use for getting
511 * packets in demand mode, and connect it to a ppp interface.
512 * Here we use a pty.
513 */
514void
515open_ppp_loopback()
516{
517 int flags;
518 struct termios tios;
519 int pppdisc = PPPDISC5;
520
521 if (openpty(&loop_master, &loop_slave, loop_name, NULL((void *)0), NULL((void *)0)) == -1) {
522 syslog(LOG_ERR3, "No free pty for loopback");
523 die(1);
524 }
525 SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
526
527 if (tcgetattr(loop_slave, &tios) == 0) {
528 tios.c_cflag &= ~(CSIZE0x00000300 | CSTOPB0x00000400 | PARENB0x00001000);
529 tios.c_cflag |= CS80x00000300 | CREAD0x00000800;
530 tios.c_iflag = IGNPAR0x00000004;
531 tios.c_oflag = 0;
532 tios.c_lflag = 0;
533 if (tcsetattr(loop_slave, TCSAFLUSH2, &tios) == -1)
534 syslog(LOG_WARNING4, "couldn't set attributes on loopback: %m");
535 }
536
537 if ((flags = fcntl(loop_master, F_GETFL3)) != -1)
538 if (fcntl(loop_master, F_SETFL4, flags | O_NONBLOCK0x0004) == -1)
539 syslog(LOG_WARNING4, "couldn't set loopback to nonblock: %m");
540
541 ppp_fd = loop_slave;
542 if (ioctl(ppp_fd, TIOCSETD((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((27)))
, &pppdisc) == -1) {
543 syslog(LOG_ERR3, "ioctl(TIOCSETD): %m");
544 die(1);
545 }
546
547 /*
548 * Find out which interface we were given.
549 */
550 if (ioctl(ppp_fd, PPPIOCGUNIT((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((86)))
, &ifunit) == -1) {
551 syslog(LOG_ERR3, "ioctl(PPPIOCGUNIT): %m");
552 die(1);
553 }
554
555 /*
556 * Enable debug in the driver if requested.
557 */
558 if (kdebugflag) {
559 if (ioctl(ppp_fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &flags) == -1) {
560 syslog(LOG_WARNING4, "ioctl (PPPIOCGFLAGS): %m");
561 } else {
562 flags |= (kdebugflag & 0xFF) * SC_DEBUG0x00010000;
563 if (ioctl(ppp_fd, PPPIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((89)))
, (caddr_t) &flags) == -1)
564 syslog(LOG_WARNING4, "ioctl(PPPIOCSFLAGS): %m");
565 }
566 }
567
568}
569
570
571/*
572 * output - Output PPP packet.
573 */
574void
575output(unit, p, len)
576 int unit;
577 u_char *p;
578 int len;
579{
580 if (debug)
581 log_packet(p, len, "sent ", LOG_DEBUG7);
582
583 if (write(ttyfd, p, len) == -1) {
584 if (errno(*__errno()) != EIO5)
585 syslog(LOG_ERR3, "write: %m");
586 }
587}
588
589
590/*
591 * wait_input - wait until there is data available on ttyfd,
592 * for the length of time specified by *timo (indefinite
593 * if timo is NULL).
594 */
595void
596wait_input(timo)
597 struct timeval *timo;
598{
599 fd_set *fdsp = NULL((void *)0);
600 int fdsn;
601 int n;
602
603 fdsn = howmany(ttyfd+1, NFDBITS)(((ttyfd+1) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (
((unsigned)(sizeof(__fd_mask) * 8))))
* sizeof(fd_mask__fd_mask);
604 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL((void *)0))
1
Memory is allocated
2
Assuming the condition is false
3
Taking false branch
605 err(1, "malloc");
606 memset(fdsp, 0, fdsn);
607 FD_SET(ttyfd, fdsp)__fd_set((ttyfd), (fdsp));
608
609 n = select(ttyfd+1, fdsp, NULL((void *)0), fdsp, timo);
610 if (n == -1 && errno(*__errno()) != EINTR4) {
4
Assuming the condition is true
5
Assuming the condition is true
6
Taking true branch
611 syslog(LOG_ERR3, "select: %m");
612 free(fdsp);
7
Memory is released
613 die(1);
614 }
615 free(fdsp);
8
Attempt to free released memory
616}
617
618
619/*
620 * wait_loop_output - wait until there is data available on the
621 * loopback, for the length of time specified by *timo (indefinite
622 * if timo is NULL).
623 */
624void
625wait_loop_output(timo)
626 struct timeval *timo;
627{
628 fd_set *fdsp = NULL((void *)0);
629 int fdsn;
630 int n;
631
632 fdsn = howmany(loop_master+1, NFDBITS)(((loop_master+1) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1
)) / (((unsigned)(sizeof(__fd_mask) * 8))))
* sizeof(fd_mask__fd_mask);
633 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL((void *)0))
634 err(1, "malloc");
635 memset(fdsp, 0, fdsn);
636 FD_SET(loop_master, fdsp)__fd_set((loop_master), (fdsp));
637
638 n = select(loop_master + 1, fdsp, NULL((void *)0), fdsp, timo);
639 if (n == -1 && errno(*__errno()) != EINTR4) {
640 syslog(LOG_ERR3, "select: %m");
641 free(fdsp);
642 die(1);
643 }
644 free(fdsp);
645}
646
647
648/*
649 * wait_time - wait for a given length of time or until a
650 * signal is received.
651 */
652void
653wait_time(timo)
654 struct timeval *timo;
655{
656 int n;
657
658 n = select(0, NULL((void *)0), NULL((void *)0), NULL((void *)0), timo);
659 if (n == -1 && errno(*__errno()) != EINTR4) {
660 syslog(LOG_ERR3, "select: %m");
661 die(1);
662 }
663}
664
665
666/*
667 * read_packet - get a PPP packet from the serial device.
668 */
669int
670read_packet(buf)
671 u_char *buf;
672{
673 int len;
674
675 if ((len = read(ttyfd, buf, PPP_MTU1500 + PPP_HDRLEN4)) == -1) {
676 if (errno(*__errno()) == EWOULDBLOCK35 || errno(*__errno()) == EINTR4)
677 return -1;
678 syslog(LOG_ERR3, "read: %m");
679 die(1);
680 }
681 return len;
682}
683
684
685/*
686 * get_loop_output - read characters from the loopback, form them
687 * into frames, and detect when we want to bring the real link up.
688 * Return value is 1 if we need to bring up the link, 0 otherwise.
689 */
690int
691get_loop_output()
692{
693 int rv = 0;
694 int n;
695
696 while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
697 if (loop_chars(inbuf, n))
698 rv = 1;
699 }
700
701 if (n == 0) {
702 syslog(LOG_ERR3, "eof on loopback");
703 die(1);
704 } else if (errno(*__errno()) != EWOULDBLOCK35){
705 syslog(LOG_ERR3, "read from loopback: %m");
706 die(1);
707 }
708
709 return rv;
710}
711
712
713/*
714 * ppp_send_config - configure the transmit characteristics of
715 * the ppp interface.
716 */
717void
718ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
719 int unit, mtu;
720 u_int32_t asyncmap;
721 int pcomp, accomp;
722{
723 u_int x;
724 struct ifreq ifr;
725
726 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
727 ifr.ifr_mtuifr_ifru.ifru_metric = mtu;
728 if (ioctl(sockfd, SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((127)))
, (caddr_t) &ifr) == -1) {
729 syslog(LOG_ERR3, "ioctl(SIOCSIFMTU): %m");
730 quit();
731 }
732
733 if (ioctl(ppp_fd, PPPIOCSASYNCMAP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((87)))
, (caddr_t) &asyncmap) == -1) {
734 syslog(LOG_ERR3, "ioctl(PPPIOCSASYNCMAP): %m");
735 quit();
736 }
737
738 if (ioctl(ppp_fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &x) == -1) {
739 syslog(LOG_ERR3, "ioctl (PPPIOCGFLAGS): %m");
740 quit();
741 }
742 x = pcomp? x | SC_COMP_PROT0x00000001: x &~ SC_COMP_PROT0x00000001;
743 x = accomp? x | SC_COMP_AC0x00000002: x &~ SC_COMP_AC0x00000002;
744 if (ioctl(ppp_fd, PPPIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((89)))
, (caddr_t) &x) == -1) {
745 syslog(LOG_ERR3, "ioctl(PPPIOCSFLAGS): %m");
746 quit();
747 }
748}
749
750
751/*
752 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
753 */
754void
755ppp_set_xaccm(unit, accm)
756 int unit;
757 ext_accm accm;
758{
759 if (ioctl(ppp_fd, PPPIOCSXASYNCMAP((unsigned long)0x80000000 | ((sizeof(ext_accm) & 0x1fff)
<< 16) | ((('t')) << 8) | ((79)))
, accm) == -1 && errno(*__errno()) != ENOTTY25)
760 syslog(LOG_WARNING4, "ioctl(set extended ACCM): %m");
761}
762
763
764/*
765 * ppp_recv_config - configure the receive-side characteristics of
766 * the ppp interface.
767 */
768void
769ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
770 int unit, mru;
771 u_int32_t asyncmap;
772 int pcomp, accomp;
773{
774 int x;
775
776 if (ioctl(ppp_fd, PPPIOCSMRU((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((82)))
, (caddr_t) &mru) == -1) {
777 syslog(LOG_ERR3, "ioctl(PPPIOCSMRU): %m");
778 quit();
779 }
780 if (ioctl(ppp_fd, PPPIOCSRASYNCMAP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((84)))
, (caddr_t) &asyncmap) == -1) {
781 syslog(LOG_ERR3, "ioctl(PPPIOCSRASYNCMAP): %m");
782 quit();
783 }
784 if (ioctl(ppp_fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &x) == -1) {
785 syslog(LOG_ERR3, "ioctl (PPPIOCGFLAGS): %m");
786 quit();
787 }
788 x = !accomp? x | SC_REJ_COMP_AC0x00000010: x &~ SC_REJ_COMP_AC0x00000010;
789 if (ioctl(ppp_fd, PPPIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((89)))
, (caddr_t) &x) == -1) {
790 syslog(LOG_ERR3, "ioctl(PPPIOCSFLAGS): %m");
791 quit();
792 }
793}
794
795/*
796 * ccp_test - ask kernel whether a given compression method
797 * is acceptable for use. Returns 1 if the method and parameters
798 * are OK, 0 if the method is known but the parameters are not OK
799 * (e.g. code size should be reduced), or -1 if the method is unknown.
800 */
801int
802ccp_test(unit, opt_ptr, opt_len, for_transmit)
803 int unit, opt_len, for_transmit;
804 u_char *opt_ptr;
805{
806 struct ppp_option_data data;
807
808 data.ptr = opt_ptr;
809 data.length = opt_len;
810 data.transmit = for_transmit;
811 if (ioctl(ttyfd, PPPIOCSCOMPRESS((unsigned long)0x80000000 | ((sizeof(struct ppp_option_data)
& 0x1fff) << 16) | ((('t')) << 8) | ((77)))
, (caddr_t) &data) >= 0)
812 return 1;
813 return (errno(*__errno()) == ENOBUFS55)? 0: -1;
814}
815
816/*
817 * ccp_flags_set - inform kernel about the current state of CCP.
818 */
819void
820ccp_flags_set(unit, isopen, isup)
821 int unit, isopen, isup;
822{
823 int x;
824
825 if (ioctl(ppp_fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &x) == -1) {
826 syslog(LOG_ERR3, "ioctl (PPPIOCGFLAGS): %m");
827 return;
828 }
829 x = isopen? x | SC_CCP_OPEN0x00000040: x &~ SC_CCP_OPEN0x00000040;
830 x = isup? x | SC_CCP_UP0x00000080: x &~ SC_CCP_UP0x00000080;
831 if (ioctl(ppp_fd, PPPIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((89)))
, (caddr_t) &x) == -1)
832 syslog(LOG_ERR3, "ioctl(PPPIOCSFLAGS): %m");
833}
834
835/*
836 * ccp_fatal_error - returns 1 if decompression was disabled as a
837 * result of an error detected after decompression of a packet,
838 * 0 otherwise. This is necessary because of patent nonsense.
839 */
840int
841ccp_fatal_error(unit)
842 int unit;
843{
844 int x;
845
846 if (ioctl(ppp_fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &x) == -1) {
847 syslog(LOG_ERR3, "ioctl(PPPIOCGFLAGS): %m");
848 return 0;
849 }
850 return x & SC_DC_FERROR0x00008000;
851}
852
853/*
854 * get_idle_time - return how long the link has been idle.
855 */
856int
857get_idle_time(u, ip)
858 int u;
859 struct ppp_idle *ip;
860{
861 return ioctl(ppp_fd, PPPIOCGIDLE((unsigned long)0x40000000 | ((sizeof(struct ppp_idle) & 0x1fff
) << 16) | ((('t')) << 8) | ((74)))
, ip) >= 0;
862}
863
864
865#ifdef PPP_FILTER1
866/*
867 * set_filters - transfer the pass and active filters to the kernel.
868 */
869int
870set_filters(pass, active)
871 struct bpf_program *pass, *active;
872{
873 int ret = 1;
874
875 if (pass->bf_len > 0) {
876 if (ioctl(ppp_fd, PPPIOCSPASS((unsigned long)0x80000000 | ((sizeof(struct bpf_program) &
0x1fff) << 16) | ((('t')) << 8) | ((71)))
, pass) == -1) {
877 syslog(LOG_ERR3, "Couldn't set pass-filter in kernel: %m");
878 ret = 0;
879 }
880 }
881 if (active->bf_len > 0) {
882 if (ioctl(ppp_fd, PPPIOCSACTIVE((unsigned long)0x80000000 | ((sizeof(struct bpf_program) &
0x1fff) << 16) | ((('t')) << 8) | ((70)))
, active) == -1) {
883 syslog(LOG_ERR3, "Couldn't set active-filter in kernel: %m");
884 ret = 0;
885 }
886 }
887 return ret;
888}
889#endif
890
891/*
892 * sifvjcomp - config tcp header compression
893 */
894int
895sifvjcomp(u, vjcomp, cidcomp, maxcid)
896 int u, vjcomp, cidcomp, maxcid;
897{
898 u_int x;
899
900 if (ioctl(ppp_fd, PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
, (caddr_t) &x) == -1) {
901 syslog(LOG_ERR3, "ioctl (PPPIOCGFLAGS): %m");
902 return 0;
903 }
904 x = vjcomp ? x | SC_COMP_TCP0x00000004: x &~ SC_COMP_TCP0x00000004;
905 x = cidcomp? x & ~SC_NO_TCP_CCID0x00000008: x | SC_NO_TCP_CCID0x00000008;
906 if (ioctl(ppp_fd, PPPIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((89)))
, (caddr_t) &x) == -1) {
907 syslog(LOG_ERR3, "ioctl(PPPIOCSFLAGS): %m");
908 return 0;
909 }
910 if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((81)))
, (caddr_t) &maxcid) == -1) {
911 syslog(LOG_ERR3, "ioctl(PPPIOCSFLAGS): %m");
912 return 0;
913 }
914 return 1;
915}
916
917/*
918 * sifup - Config the interface up and enable IP packets to pass.
919 */
920int
921sifup(u)
922 int u;
923{
924 struct ifreq ifr;
925
926 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
927 if (ioctl(sockfd, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, (caddr_t) &ifr) == -1) {
928 syslog(LOG_ERR3, "ioctl (SIOCGIFFLAGS): %m");
929 return 0;
930 }
931 ifr.ifr_flagsifr_ifru.ifru_flags |= IFF_UP0x1;
932 if (ioctl(sockfd, SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
, (caddr_t) &ifr) == -1) {
933 syslog(LOG_ERR3, "ioctl(SIOCSIFFLAGS): %m");
934 return 0;
935 }
936 if_is_up = 1;
937 return 1;
938}
939
940/*
941 * sifnpmode - Set the mode for handling packets for a given NP.
942 */
943int
944sifnpmode(u, proto, mode)
945 int u;
946 int proto;
947 enum NPmode mode;
948{
949 struct npioctl npi;
950
951 npi.protocol = proto;
952 npi.mode = mode;
953 if (ioctl(ppp_fd, PPPIOCSNPMODE((unsigned long)0x80000000 | ((sizeof(struct npioctl) & 0x1fff
) << 16) | ((('t')) << 8) | ((75)))
, &npi) == -1) {
954 syslog(LOG_ERR3, "ioctl(set NP %d mode to %d): %m", proto, mode);
955 return 0;
956 }
957 return 1;
958}
959
960/*
961 * sifdown - Config the interface down and disable IP.
962 */
963int
964sifdown(u)
965 int u;
966{
967 struct ifreq ifr;
968 int rv;
969 struct npioctl npi;
970
971 rv = 1;
972 npi.protocol = PPP_IP0x21;
973 npi.mode = NPMODE_ERROR;
974 ioctl(ppp_fd, PPPIOCSNPMODE((unsigned long)0x80000000 | ((sizeof(struct npioctl) & 0x1fff
) << 16) | ((('t')) << 8) | ((75)))
, (caddr_t) &npi);
975 /* ignore errors, because ppp_fd might have been closed by now. */
976
977 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
978 if (ioctl(sockfd, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, (caddr_t) &ifr) == -1) {
979 syslog(LOG_ERR3, "ioctl (SIOCGIFFLAGS): %m");
980 rv = 0;
981 } else {
982 ifr.ifr_flagsifr_ifru.ifru_flags &= ~IFF_UP0x1;
983 if (ioctl(sockfd, SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
, (caddr_t) &ifr) == -1) {
984 syslog(LOG_ERR3, "ioctl(SIOCSIFFLAGS): %m");
985 rv = 0;
986 } else
987 if_is_up = 0;
988 }
989 return rv;
990}
991
992/*
993 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
994 * if it exists.
995 */
996#define SET_SA_FAMILY(addr, family)memset((char *) &(addr), 0, sizeof(addr)); addr.sa_family
= (family); addr.sa_len = sizeof(addr);
\
997 BZERO((char *) &(addr), sizeof(addr))memset((char *) &(addr), 0, sizeof(addr)); \
998 addr.sa_family = (family); \
999 addr.sa_len = sizeof(addr);
1000
1001/*
1002 * sifaddr - Config the interface IP addresses and netmask.
1003 */
1004int
1005sifaddr(u, o, h, m)
1006 int u;
1007 u_int32_t o, h, m;
1008{
1009 struct ifaliasreq ifra;
1010 struct ifreq ifr;
1011 char s1[64], s2[64];
1012
1013 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1014 SET_SA_FAMILY(ifra.ifra_addr, AF_INET)memset((char *) &(ifra.ifra_ifrau.ifrau_addr), 0, sizeof(
ifra.ifra_ifrau.ifrau_addr)); ifra.ifra_ifrau.ifrau_addr.sa_family
= (2); ifra.ifra_ifrau.ifrau_addr.sa_len = sizeof(ifra.ifra_ifrau
.ifrau_addr);
;
1015 ((struct sockaddr_in *) &ifra.ifra_addrifra_ifrau.ifrau_addr)->sin_addr.s_addr = o;
1016 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET)memset((char *) &(ifra.ifra_dstaddr), 0, sizeof(ifra.ifra_dstaddr
)); ifra.ifra_dstaddr.sa_family = (2); ifra.ifra_dstaddr.sa_len
= sizeof(ifra.ifra_dstaddr);
;
1017 ((struct sockaddr_in *) &ifra.ifra_broadaddrifra_dstaddr)->sin_addr.s_addr = h;
1018 if (m != 0) {
1019 SET_SA_FAMILY(ifra.ifra_mask, AF_INET)memset((char *) &(ifra.ifra_mask), 0, sizeof(ifra.ifra_mask
)); ifra.ifra_mask.sa_family = (2); ifra.ifra_mask.sa_len = sizeof
(ifra.ifra_mask);
;
1020 ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
1021 } else
1022 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask))memset(&ifra.ifra_mask, 0, sizeof(ifra.ifra_mask));
1023 BZERO(&ifr, sizeof(ifr))memset(&ifr, 0, sizeof(ifr));
1024 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1025 if (ioctl(sockfd, SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((25)))
, (caddr_t) &ifr) == -1) {
1026 if (errno(*__errno()) != EADDRNOTAVAIL49)
1027 syslog(LOG_WARNING4, "Couldn't remove interface address: %m");
1028 }
1029 if (ioctl(sockfd, SIOCAIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifaliasreq) &
0x1fff) << 16) | ((('i')) << 8) | ((26)))
, (caddr_t) &ifra) == -1) {
1030 if (errno(*__errno()) != EEXIST17) {
1031 syslog(LOG_ERR3, "Couldn't set interface address: %m");
1032 return 0;
1033 }
1034 strlcpy(s1, ip_ntoa(o), sizeof(s1));
1035 strlcpy(s2, ip_ntoa(h), sizeof(s2));
1036 syslog(LOG_WARNING4,
1037 "Couldn't set interface address: "
1038 "Address %s or destination %s already exists", s1, s2);
1039 }
1040 ifaddrs[0] = o;
1041 ifaddrs[1] = h;
1042 return 1;
1043}
1044
1045/*
1046 * cifaddr - Clear the interface IP addresses, and delete routes
1047 * through the interface if possible.
1048 */
1049int
1050cifaddr(u, o, h)
1051 int u;
1052 u_int32_t o, h;
1053{
1054 struct ifaliasreq ifra;
1055
1056 ifaddrs[0] = 0;
1057 strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1058 SET_SA_FAMILY(ifra.ifra_addr, AF_INET)memset((char *) &(ifra.ifra_ifrau.ifrau_addr), 0, sizeof(
ifra.ifra_ifrau.ifrau_addr)); ifra.ifra_ifrau.ifrau_addr.sa_family
= (2); ifra.ifra_ifrau.ifrau_addr.sa_len = sizeof(ifra.ifra_ifrau
.ifrau_addr);
;
1059 ((struct sockaddr_in *) &ifra.ifra_addrifra_ifrau.ifrau_addr)->sin_addr.s_addr = o;
1060 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET)memset((char *) &(ifra.ifra_dstaddr), 0, sizeof(ifra.ifra_dstaddr
)); ifra.ifra_dstaddr.sa_family = (2); ifra.ifra_dstaddr.sa_len
= sizeof(ifra.ifra_dstaddr);
;
1061 ((struct sockaddr_in *) &ifra.ifra_broadaddrifra_dstaddr)->sin_addr.s_addr = h;
1062 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask))memset(&ifra.ifra_mask, 0, sizeof(ifra.ifra_mask));
1063 if (ioctl(sockfd, SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((25)))
, (caddr_t) &ifra) == -1) {
1064 if (errno(*__errno()) != EADDRNOTAVAIL49)
1065 syslog(LOG_WARNING4, "Couldn't delete interface address: %m");
1066 return 0;
1067 }
1068 return 1;
1069}
1070
1071/*
1072 * sifdefaultroute - assign a default route through the address given.
1073 */
1074int
1075sifdefaultroute(u, l, g)
1076 int u;
1077 u_int32_t l, g;
1078{
1079 return dodefaultroute(g, 's');
1080}
1081
1082/*
1083 * cifdefaultroute - delete a default route through the address given.
1084 */
1085int
1086cifdefaultroute(u, l, g)
1087 int u;
1088 u_int32_t l, g;
1089{
1090 return dodefaultroute(g, 'c');
1091}
1092
1093/*
1094 * dodefaultroute - talk to a routing socket to add/delete a default route.
1095 */
1096static int
1097dodefaultroute(g, cmd)
1098 u_int32_t g;
1099 int cmd;
1100{
1101 int routes;
1102 struct {
1103 struct rt_msghdr hdr;
1104 struct sockaddr_in dst;
1105 struct sockaddr_in gway;
1106 struct sockaddr_in mask;
1107 } rtmsg;
1108
1109 if ((routes = socket(AF_ROUTE17, SOCK_RAW3, AF_INET2)) == -1) {
1110 syslog(LOG_ERR3, "Couldn't %s default route: socket: %m",
1111 cmd=='s'? "add": "delete");
1112 return 0;
1113 }
1114
1115 memset(&rtmsg, 0, sizeof(rtmsg));
1116 rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD0x1: RTM_DELETE0x2;
1117 rtmsg.hdr.rtm_flags = RTF_UP0x1 | RTF_GATEWAY0x2;
1118 rtmsg.hdr.rtm_version = RTM_VERSION5;
1119 rtmsg.hdr.rtm_seq = ++rtm_seq;
1120 rtmsg.hdr.rtm_addrs = RTA_DST0x1 | RTA_GATEWAY0x2 | RTA_NETMASK0x4;
1121 rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1122 rtmsg.dst.sin_family = AF_INET2;
1123 rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1124 rtmsg.gway.sin_family = AF_INET2;
1125 rtmsg.gway.sin_addr.s_addr = g;
1126 rtmsg.mask.sin_len = sizeof(rtmsg.dst);
1127 rtmsg.mask.sin_family = AF_INET2;
1128
1129 rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
1130 if (write(routes, &rtmsg, sizeof(rtmsg)) == -1) {
1131 syslog(LOG_ERR3, "Couldn't %s default route: %m",
1132 cmd=='s'? "add": "delete");
1133 close(routes);
1134 return 0;
1135 }
1136
1137 close(routes);
1138 default_route_gateway = (cmd == 's')? g: 0;
1139 return 1;
1140}
1141
1142#if RTM_VERSION5 >= 3
1143
1144/*
1145 * sifproxyarp - Make a proxy ARP entry for the peer.
1146 */
1147static struct {
1148 struct rt_msghdr hdr;
1149 struct sockaddr_inarp dst;
1150 struct sockaddr_dl hwa;
1151 char extra[128];
1152} arpmsg;
1153
1154static int arpmsg_valid;
1155
1156int
1157sifproxyarp(unit, hisaddr)
1158 int unit;
1159 u_int32_t hisaddr;
1160{
1161 int routes;
1162
1163 /*
1164 * Get the hardware address of an interface on the same subnet
1165 * as our local address.
1166 */
1167 memset(&arpmsg, 0, sizeof(arpmsg));
1168 if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1169 syslog(LOG_ERR3, "Cannot determine ethernet address for proxy ARP");
1170 return 0;
1171 }
1172
1173 if ((routes = socket(AF_ROUTE17, SOCK_RAW3, AF_INET2)) == -1) {
1174 syslog(LOG_ERR3, "Couldn't add proxy arp entry: socket: %m");
1175 return 0;
1176 }
1177
1178 arpmsg.hdr.rtm_type = RTM_ADD0x1;
1179 arpmsg.hdr.rtm_flags = RTF_ANNOUNCE0x4000 | RTF_HOST0x4 | RTF_STATIC0x800;
1180 arpmsg.hdr.rtm_version = RTM_VERSION5;
1181 arpmsg.hdr.rtm_seq = ++rtm_seq;
1182 arpmsg.hdr.rtm_addrs = RTA_DST0x1 | RTA_GATEWAY0x2;
1183 arpmsg.hdr.rtm_inits = RTV_EXPIRE0x4;
1184 arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1185 arpmsg.dst.sin_family = AF_INET2;
1186 arpmsg.dst.sin_addr.s_addr = hisaddr;
1187 arpmsg.dst.sin_other = SIN_PROXY1;
1188
1189 arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1190 + arpmsg.hwa.sdl_len;
1191 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) == -1) {
1192 syslog(LOG_ERR3, "Couldn't add proxy arp entry: %m");
1193 close(routes);
1194 return 0;
1195 }
1196
1197 close(routes);
1198 arpmsg_valid = 1;
1199 proxy_arp_addr = hisaddr;
1200 return 1;
1201}
1202
1203/*
1204 * cifproxyarp - Delete the proxy ARP entry for the peer.
1205 */
1206int
1207cifproxyarp(unit, hisaddr)
1208 int unit;
1209 u_int32_t hisaddr;
1210{
1211 int routes;
1212
1213 if (!arpmsg_valid)
1214 return 0;
1215 arpmsg_valid = 0;
1216
1217 arpmsg.hdr.rtm_type = RTM_DELETE0x2;
1218 arpmsg.hdr.rtm_seq = ++rtm_seq;
1219
1220 if ((routes = socket(AF_ROUTE17, SOCK_RAW3, AF_INET2)) == -1) {
1221 syslog(LOG_ERR3, "Couldn't delete proxy arp entry: socket: %m");
1222 return 0;
1223 }
1224
1225 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) == -1) {
1226 syslog(LOG_ERR3, "Couldn't delete proxy arp entry: %m");
1227 close(routes);
1228 return 0;
1229 }
1230
1231 close(routes);
1232 proxy_arp_addr = 0;
1233 return 1;
1234}
1235
1236#else /* RTM_VERSION */
1237
1238/*
1239 * sifproxyarp - Make a proxy ARP entry for the peer.
1240 */
1241int
1242sifproxyarp(unit, hisaddr)
1243 int unit;
1244 u_int32_t hisaddr;
1245{
1246 struct arpreq arpreq;
1247 struct {
1248 struct sockaddr_dl sdl;
1249 char space[128];
1250 } dls;
1251
1252 BZERO(&arpreq, sizeof(arpreq))memset(&arpreq, 0, sizeof(arpreq));
1253
1254 /*
1255 * Get the hardware address of an interface on the same subnet
1256 * as our local address.
1257 */
1258 if (!get_ether_addr(hisaddr, &dls.sdl)) {
1259 syslog(LOG_ERR3, "Cannot determine ethernet address for proxy ARP");
1260 return 0;
1261 }
1262
1263 arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1264 arpreq.arp_ha.sa_family = AF_UNSPEC0;
1265 BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen)memcpy(arpreq.arp_ha.sa_data, ((caddr_t)((&dls.sdl)->sdl_data
+ (&dls.sdl)->sdl_nlen)), dls.sdl.sdl_alen)
;
1266 SET_SA_FAMILY(arpreq.arp_pa, AF_INET)memset((char *) &(arpreq.arp_pa), 0, sizeof(arpreq.arp_pa
)); arpreq.arp_pa.sa_family = (2); arpreq.arp_pa.sa_len = sizeof
(arpreq.arp_pa);
;
1267 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1268 arpreq.arp_flags = ATF_PERM0x04 | ATF_PUBL0x08;
1269 if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) == -1) {
1270 syslog(LOG_ERR3, "Couldn't add proxy arp entry: %m");
1271 return 0;
1272 }
1273
1274 proxy_arp_addr = hisaddr;
1275 return 1;
1276}
1277
1278/*
1279 * cifproxyarp - Delete the proxy ARP entry for the peer.
1280 */
1281int
1282cifproxyarp(unit, hisaddr)
1283 int unit;
1284 u_int32_t hisaddr;
1285{
1286 struct arpreq arpreq;
1287
1288 BZERO(&arpreq, sizeof(arpreq))memset(&arpreq, 0, sizeof(arpreq));
1289 SET_SA_FAMILY(arpreq.arp_pa, AF_INET)memset((char *) &(arpreq.arp_pa), 0, sizeof(arpreq.arp_pa
)); arpreq.arp_pa.sa_family = (2); arpreq.arp_pa.sa_len = sizeof
(arpreq.arp_pa);
;
1290 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1291 if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) == -1) {
1292 syslog(LOG_WARNING4, "Couldn't delete proxy arp entry: %m");
1293 return 0;
1294 }
1295 proxy_arp_addr = 0;
1296 return 1;
1297}
1298#endif /* RTM_VERSION */
1299
1300
1301/*
1302 * get_ether_addr - get the hardware address of an interface on the
1303 * the same subnet as ipaddr.
1304 */
1305#define MAX_IFS32 32
1306
1307static int
1308get_ether_addr(ipaddr, hwaddr)
1309 u_int32_t ipaddr;
1310 struct sockaddr_dl *hwaddr;
1311{
1312 u_int32_t ina, mask;
1313 struct sockaddr_dl *dla;
1314 struct ifaddrs *ifap, *ifa, *ifp;
1315
1316 if (getifaddrs(&ifap) != 0) {
1317 syslog(LOG_ERR3, "getifaddrs: %m");
1318 return 0;
1319 }
1320
1321 /*
1322 * Scan through looking for an interface with an Internet
1323 * address on the same subnet as `ipaddr'.
1324 */
1325 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1326 if (ifa->ifa_addr == NULL((void *)0))
1327 continue;
1328 if (ifa->ifa_addr->sa_family == AF_INET2) {
1329 ina = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
1330 /*
1331 * Check that the interface is up, and not point-to-point
1332 * or loopback.
1333 */
1334 if ((ifa->ifa_flags &
1335 (IFF_UP0x1|IFF_BROADCAST0x2|IFF_POINTOPOINT0x10|IFF_LOOPBACK0x8|IFF_NOARP0x80))
1336 != (IFF_UP0x1|IFF_BROADCAST0x2))
1337 continue;
1338 /*
1339 * Get its netmask and check that it's on the right subnet.
1340 */
1341 mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
1342 if ((ipaddr & mask) != (ina & mask))
1343 continue;
1344
1345 break;
1346 }
1347 }
1348
1349 if (ifa == NULL((void *)0)) {
1350 freeifaddrs(ifap);
1351 return 0;
1352 }
1353 syslog(LOG_INFO6, "found interface %s for proxy arp", ifa->ifa_name);
1354
1355 /*
1356 * Now scan through again looking for a link-level address
1357 * for this interface.
1358 */
1359 ifp = ifa;
1360 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1361 if (ifa->ifa_addr == NULL((void *)0))
1362 continue;
1363 if (strcmp(ifp->ifa_name, ifa->ifa_name) == 0
1364 && ifa->ifa_addr->sa_family == AF_LINK18) {
1365 /*
1366 * Found the link-level address - copy it out
1367 */
1368 dla = (struct sockaddr_dl *)ifa->ifa_addr;
1369 BCOPY(dla, hwaddr, dla->sdl_len)memcpy(hwaddr, dla, dla->sdl_len);
1370 return 1;
1371 }
1372 }
1373
1374 freeifaddrs(ifap);
1375 return 0;
1376}
1377
1378/*
1379 * Return user specified netmask, modified by any mask we might determine
1380 * for address `addr' (in network byte order).
1381 * Here we scan through the system's list of interfaces, looking for
1382 * any non-point-to-point interfaces which might appear to be on the same
1383 * network as `addr'. If we find any, we OR in their netmask to the
1384 * user-specified netmask.
1385 */
1386u_int32_t
1387GetMask(addr)
1388 u_int32_t addr;
1389{
1390 u_int32_t mask, nmask, ina;
1391 struct ifaddrs *ifap, *ifa;
1392
1393 addr = ntohl(addr)(__uint32_t)(__builtin_constant_p(addr) ? (__uint32_t)(((__uint32_t
)(addr) & 0xff) << 24 | ((__uint32_t)(addr) & 0xff00
) << 8 | ((__uint32_t)(addr) & 0xff0000) >> 8
| ((__uint32_t)(addr) & 0xff000000) >> 24) : __swap32md
(addr))
;
1394 if (IN_CLASSA(addr)(((u_int32_t)(addr) & ((u_int32_t)(0x80000000))) == ((u_int32_t
)(0x00000000)))
) /* determine network mask for address class */
1395 nmask = IN_CLASSA_NET((u_int32_t)(0xff000000));
1396 else if (IN_CLASSB(addr)(((u_int32_t)(addr) & ((u_int32_t)(0xc0000000))) == ((u_int32_t
)(0x80000000)))
)
1397 nmask = IN_CLASSB_NET((u_int32_t)(0xffff0000));
1398 else
1399 nmask = IN_CLASSC_NET((u_int32_t)(0xffffff00));
1400 /* class D nets are disallowed by bad_ip_adrs */
1401 mask = netmask | htonl(nmask)(__uint32_t)(__builtin_constant_p(nmask) ? (__uint32_t)(((__uint32_t
)(nmask) & 0xff) << 24 | ((__uint32_t)(nmask) &
0xff00) << 8 | ((__uint32_t)(nmask) & 0xff0000) >>
8 | ((__uint32_t)(nmask) & 0xff000000) >> 24) : __swap32md
(nmask))
;
1402
1403 /*
1404 * Scan through the system's network interfaces.
1405 */
1406 if (getifaddrs(&ifap) != 0) {
1407 syslog(LOG_WARNING4, "getifaddrs: %m");
1408 return mask;
1409 }
1410 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1411 /*
1412 * Check the interface's internet address.
1413 */
1414 if (ifa->ifa_addr == NULL((void *)0) ||
1415 ifa->ifa_addr->sa_family != AF_INET2)
1416 continue;
1417 ina = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
1418 if ((ntohl(ina)(__uint32_t)(__builtin_constant_p(ina) ? (__uint32_t)(((__uint32_t
)(ina) & 0xff) << 24 | ((__uint32_t)(ina) & 0xff00
) << 8 | ((__uint32_t)(ina) & 0xff0000) >> 8 |
((__uint32_t)(ina) & 0xff000000) >> 24) : __swap32md
(ina))
& nmask) != (addr & nmask))
1419 continue;
1420 /*
1421 * Check that the interface is up, and not point-to-point or loopback.
1422 */
1423 if ((ifa->ifa_flags & (IFF_UP0x1|IFF_POINTOPOINT0x10|IFF_LOOPBACK0x8))
1424 != IFF_UP0x1)
1425 continue;
1426 /*
1427 * Get its netmask and OR it into our mask.
1428 */
1429 mask |= ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
1430 }
1431
1432 freeifaddrs(ifap);
1433 return mask;
1434}
1435
1436/*
1437 * lock - create a lock file for the named lock device
1438 */
1439#define LOCK_PREFIX"/var/spool/lock/LCK.." "/var/spool/lock/LCK.."
1440
1441int
1442lock(dev)
1443 char *dev;
1444{
1445 char hdb_lock_buffer[12];
1446 int fd, n;
1447 pid_t pid;
1448 char *p;
1449
1450 if ((p = strrchr(dev, '/')) != NULL((void *)0))
1451 dev = p + 1;
1452 if (asprintf(&lock_file, "%s%s", LOCK_PREFIX"/var/spool/lock/LCK..", dev) == -1)
1453 novm("lock file name");
1454
1455 while ((fd = open(lock_file, O_EXCL0x0800 | O_CREAT0x0200 | O_RDWR0x0002, 0644)) == -1) {
1456 if (errno(*__errno()) == EEXIST17
1457 && (fd = open(lock_file, O_RDONLY0x0000)) >= 0) {
1458 /* Read the lock file to find out who has the device locked */
1459 n = read(fd, hdb_lock_buffer, 11);
1460 if (n <= 0) {
1461 syslog(LOG_ERR3, "Can't read pid from lock file %s", lock_file);
1462 close(fd);
1463 } else {
1464 hdb_lock_buffer[n] = 0;
1465 pid = atoi(hdb_lock_buffer);
1466 if (kill(pid, 0) == -1 && errno(*__errno()) == ESRCH3) {
1467 /* pid no longer exists - remove the lock file */
1468 if (unlink(lock_file) == 0) {
1469 close(fd);
1470 syslog(LOG_NOTICE5, "Removed stale lock on %s (pid %ld)",
1471 dev, (long)pid);
1472 continue;
1473 } else
1474 syslog(LOG_WARNING4, "Couldn't remove stale lock on %s",
1475 dev);
1476 } else
1477 syslog(LOG_NOTICE5, "Device %s is locked by pid %ld",
1478 dev, (long)pid);
1479 }
1480 close(fd);
1481 } else
1482 syslog(LOG_ERR3, "Can't create lock file %s: %m", lock_file);
1483 free(lock_file);
1484 lock_file = NULL((void *)0);
1485 return -1;
1486 }
1487
1488 snprintf(hdb_lock_buffer, sizeof hdb_lock_buffer, "%10ld\n", (long)getpid());
1489 write(fd, hdb_lock_buffer, 11);
1490
1491 close(fd);
1492 return 0;
1493}
1494
1495/*
1496 * unlock - remove our lockfile
1497 */
1498void
1499unlock()
1500{
1501 if (lock_file) {
1502 unlink(lock_file);
1503 free(lock_file);
1504 lock_file = NULL((void *)0);
1505 }
1506}