GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/pppd/sys-bsd.c Lines: 0 521 0.0 %
Date: 2017-11-07 Branches: 0 289 0.0 %

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