1/*
2 * sys-linux.c - System-dependent procedures for setting up
3 * PPP interfaces on Linux systems
4 *
5 * Copyright (c) 1994-2004 Paul Mackerras. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
14 * 2. The name(s) of the authors of this software must not be used to
15 *    endorse or promote products derived from this software without
16 *    prior written permission.
17 *
18 * 3. Redistributions of any form whatsoever must retain the following
19 *    acknowledgment:
20 *    "This product includes software developed by Paul Mackerras
21 *     <paulus@samba.org>".
22 *
23 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
24 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
26 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
28 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
29 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 *
31 * Derived from main.c and pppd.h, which are:
32 *
33 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 *
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 *
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in
44 *    the documentation and/or other materials provided with the
45 *    distribution.
46 *
47 * 3. The name "Carnegie Mellon University" must not be used to
48 *    endorse or promote products derived from this software without
49 *    prior written permission. For permission or any legal
50 *    details, please contact
51 *      Office of Technology Transfer
52 *      Carnegie Mellon University
53 *      5000 Forbes Avenue
54 *      Pittsburgh, PA  15213-3890
55 *      (412) 268-4387, fax: (412) 268-7395
56 *      tech-transfer@andrew.cmu.edu
57 *
58 * 4. Redistributions of any form whatsoever must retain the following
59 *    acknowledgment:
60 *    "This product includes software developed by Computing Services
61 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
62 *
63 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
64 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
65 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
66 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
67 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
68 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
69 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
70 */
71
72#include <sys/ioctl.h>
73#include <sys/types.h>
74#include <sys/socket.h>
75#include <sys/time.h>
76#include <sys/errno.h>
77#include <sys/file.h>
78#include <sys/stat.h>
79#include <sys/utsname.h>
80#include <sys/sysmacros.h>
81
82#include <stdio.h>
83#include <stdlib.h>
84#include <syslog.h>
85#include <string.h>
86#include <time.h>
87#include <memory.h>
88#include <utmp.h>
89#include <mntent.h>
90#include <signal.h>
91#include <fcntl.h>
92#include <ctype.h>
93#include <termios.h>
94#include <unistd.h>
95
96/* This is in netdevice.h. However, this compile will fail miserably if
97   you attempt to include netdevice.h because it has so many references
98   to __memcpy functions which it should not attempt to do. So, since I
99   really don't use it, but it must be defined, define it now. */
100
101#ifndef MAX_ADDR_LEN
102#define MAX_ADDR_LEN 7
103#endif
104
105#if __GLIBC__ >= 2
106#include <asm/types.h>		/* glibc 2 conflicts with linux/types.h */
107#include <net/if.h>
108#include <net/if_arp.h>
109#include <net/route.h>
110#include <netinet/if_ether.h>
111#else
112#include <linux/types.h>
113#include <linux/if.h>
114#include <linux/if_arp.h>
115#include <linux/route.h>
116#include <linux/if_ether.h>
117#endif
118#include <netinet/in.h>
119#include <arpa/inet.h>
120
121#include <linux/ppp_defs.h>
122#include <linux/if_ppp.h>
123
124#include "pppd.h"
125#include "fsm.h"
126#include "ipcp.h"
127
128#ifdef IPX_CHANGE
129#include "ipxcp.h"
130#if __GLIBC__ >= 2 && \
131    !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
132#include <netipx/ipx.h>
133#else
134#include <linux/ipx.h>
135#endif
136#endif /* IPX_CHANGE */
137
138#ifdef PPP_FILTER
139#include <pcap-bpf.h>
140#include <linux/filter.h>
141#endif /* PPP_FILTER */
142
143#ifdef LOCKLIB
144#include <sys/locks.h>
145#endif
146
147#ifdef INET6
148#ifndef _LINUX_IN6_H
149/*
150 *    This is in linux/include/net/ipv6.h.
151 */
152
153struct in6_ifreq {
154    struct in6_addr ifr6_addr;
155    __u32 ifr6_prefixlen;
156    unsigned int ifr6_ifindex;
157};
158#endif
159
160#define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {			\
161	memset(&sin6.s6_addr, 0, sizeof(struct in6_addr));	\
162	sin6.s6_addr16[0] = htons(0xfe80);			\
163	eui64_copy(eui64, sin6.s6_addr32[2]);			\
164	} while (0)
165
166#endif /* INET6 */
167
168/* We can get an EIO error on an ioctl if the modem has hung up */
169#define ok_error(num) ((num)==EIO)
170
171static int tty_disc = N_TTY;	/* The TTY discipline */
172static int ppp_disc = N_PPP;	/* The PPP discpline */
173static int initfdflags = -1;	/* Initial file descriptor flags for fd */
174static int ppp_fd = -1;		/* fd which is set to PPP discipline */
175static int sock_fd = -1;	/* socket for doing interface ioctls */
176static int slave_fd = -1;	/* pty for old-style demand mode, slave */
177static int master_fd = -1;	/* pty for old-style demand mode, master */
178#ifdef INET6
179static int sock6_fd = -1;
180#endif /* INET6 */
181
182/*
183 * For the old-style kernel driver, this is the same as ppp_fd.
184 * For the new-style driver, it is the fd of an instance of /dev/ppp
185 * which is attached to the ppp unit and is used for controlling it.
186 */
187int ppp_dev_fd = -1;		/* fd for /dev/ppp (new style driver) */
188
189static int chindex;		/* channel index (new style driver) */
190
191static fd_set in_fds;		/* set of fds that wait_input waits for */
192static int max_in_fd;		/* highest fd set in in_fds */
193
194static int has_proxy_arp       = 0;
195static int driver_version      = 0;
196static int driver_modification = 0;
197static int driver_patch        = 0;
198static int driver_is_old       = 0;
199static int restore_term        = 0;	/* 1 => we've munged the terminal */
200static struct termios inittermios;	/* Initial TTY termios */
201
202int new_style_driver = 0;
203
204static char loop_name[20];
205static unsigned char inbuf[512]; /* buffer for chars read from loopback */
206
207static int	if_is_up;	/* Interface has been marked up */
208static int	if6_is_up;	/* Interface has been marked up for IPv6, to help differentiate */
209static int	have_default_route;	/* Gateway for default route added */
210static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
211static char proxy_arp_dev[16];		/* Device for proxy arp entry */
212static u_int32_t our_old_addr;		/* for detecting address changes */
213static int	dynaddr_set;		/* 1 if ip_dynaddr set */
214static int	looped;			/* 1 if using loop */
215static int	link_mtu;		/* mtu for the link (not bundle) */
216
217static struct utsname utsname;	/* for the kernel version */
218static int kernel_version;
219#define KVERSION(j,n,p)	((j)*1000000 + (n)*1000 + (p))
220
221#define MAX_IFS		100
222
223#define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
224#define FLAGS_MASK (IFF_UP          | IFF_BROADCAST | \
225		    IFF_POINTOPOINT | IFF_LOOPBACK  | IFF_NOARP)
226
227#define SIN_ADDR(x)	(((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
228
229/* Prototypes for procedures local to this file. */
230static int modify_flags(int fd, int clear_bits, int set_bits);
231static int translate_speed (int bps);
232static int baud_rate_of (int speed);
233static void close_route_table (void);
234static int open_route_table (void);
235static int read_route_table (struct rtentry *rt);
236static int defaultroute_exists (struct rtentry *rt);
237static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
238			   char *name, int namelen);
239static void decode_version (char *buf, int *version, int *mod, int *patch);
240static int set_kdebugflag(int level);
241static int ppp_registered(void);
242static int make_ppp_unit(void);
243static int setifstate (int u, int state);
244
245extern u_char	inpacket_buf[];	/* borrowed from main.c */
246
247/*
248 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
249 * if it exists.
250 */
251
252#define SET_SA_FAMILY(addr, family)			\
253    memset ((char *) &(addr), '\0', sizeof(addr));	\
254    addr.sa_family = (family);
255
256/*
257 * Determine if the PPP connection should still be present.
258 */
259
260extern int hungup;
261
262/* new_fd is the fd of a tty */
263static void set_ppp_fd (int new_fd)
264{
265	ppp_fd = new_fd;
266	if (!new_style_driver)
267		ppp_dev_fd = new_fd;
268}
269
270static int still_ppp(void)
271{
272	if (new_style_driver)
273		return !hungup && ppp_fd >= 0;
274	if (!hungup || ppp_fd == slave_fd)
275		return 1;
276	if (slave_fd >= 0) {
277		set_ppp_fd(slave_fd);
278		return 1;
279	}
280	return 0;
281}
282
283/*
284 * modify_flags - set and clear flag bits controlling the kernel
285 * PPP driver.
286 */
287static int modify_flags(int fd, int clear_bits, int set_bits)
288{
289	int flags;
290
291	if (ioctl(fd, PPPIOCGFLAGS, &flags) == -1)
292		goto err;
293	flags = (flags & ~clear_bits) | set_bits;
294	if (ioctl(fd, PPPIOCSFLAGS, &flags) == -1)
295		goto err;
296
297	return 0;
298
299 err:
300	if (errno != EIO)
301		error("Failed to set PPP kernel option flags: %m");
302	return -1;
303}
304
305/********************************************************************
306 *
307 * sys_init - System-dependent initialization.
308 */
309
310void sys_init(void)
311{
312    /* Get an internet socket for doing socket ioctls. */
313    sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
314    if (sock_fd < 0)
315	fatal("Couldn't create IP socket: %m(%d)", errno);
316
317#ifdef INET6
318    sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
319    if (sock6_fd < 0)
320	sock6_fd = -errno;	/* save errno for later */
321#endif
322
323    FD_ZERO(&in_fds);
324    max_in_fd = 0;
325}
326
327/********************************************************************
328 *
329 * sys_cleanup - restore any system state we modified before exiting:
330 * mark the interface down, delete default route and/or proxy arp entry.
331 * This shouldn't call die() because it's called from die().
332 */
333
334void sys_cleanup(void)
335{
336/*
337 * Take down the device
338 */
339    if (if_is_up) {
340	if_is_up = 0;
341	sifdown(0);
342    }
343#ifdef INET6
344    if (if6_is_up)
345	sif6down(0);
346#endif /* INET6 */
347
348/*
349 * Delete any routes through the device.
350 */
351    if (have_default_route)
352	cifdefaultroute(0, 0, 0);
353
354    if (has_proxy_arp)
355	cifproxyarp(0, proxy_arp_addr);
356}
357
358/********************************************************************
359 *
360 * sys_close - Clean up in a child process before execing.
361 */
362void
363sys_close(void)
364{
365    if (new_style_driver && ppp_dev_fd >= 0)
366	close(ppp_dev_fd);
367    if (sock_fd >= 0)
368	close(sock_fd);
369#ifdef INET6
370    if (sock6_fd >= 0)
371	close(sock6_fd);
372#endif
373    if (slave_fd >= 0)
374	close(slave_fd);
375    if (master_fd >= 0)
376	close(master_fd);
377}
378
379/********************************************************************
380 *
381 * set_kdebugflag - Define the debugging level for the kernel
382 */
383
384static int set_kdebugflag (int requested_level)
385{
386    if (ppp_dev_fd < 0)
387	return 1;
388    if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
389	if ( ! ok_error (errno) )
390	    error("ioctl(PPPIOCSDEBUG): %m (line %d)", __LINE__);
391	return (0);
392    }
393    return (1);
394}
395
396/********************************************************************
397 *
398 * tty_establish_ppp - Turn the serial port into a ppp interface.
399 */
400
401int tty_establish_ppp (int tty_fd)
402{
403    int ret_fd;
404
405/*
406 * Ensure that the tty device is in exclusive mode.
407 */
408    if (ioctl(tty_fd, TIOCEXCL, 0) < 0) {
409	if ( ! ok_error ( errno ))
410	    warn("Couldn't make tty exclusive: %m");
411    }
412/*
413 * Demand mode - prime the old ppp device to relinquish the unit.
414 */
415    if (!new_style_driver && looped
416	&& ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
417	error("ioctl(transfer ppp unit): %m, line %d", __LINE__);
418	return -1;
419    }
420/*
421 * Set the current tty to the PPP discpline
422 */
423
424#ifndef N_SYNC_PPP
425#define N_SYNC_PPP 14
426#endif
427    ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
428    if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
429	if ( ! ok_error (errno) ) {
430	    error("Couldn't set tty to PPP discipline: %m");
431	    return -1;
432	}
433    }
434
435    ret_fd = generic_establish_ppp(tty_fd);
436
437#define SC_RCVB	(SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP)
438#define SC_LOGB	(SC_DEBUG | SC_LOG_INPKT | SC_LOG_OUTPKT | SC_LOG_RAWIN \
439		 | SC_LOG_FLUSH)
440
441    if (ret_fd >= 0) {
442	modify_flags(ppp_fd, SC_RCVB | SC_LOGB,
443		     (kdebugflag * SC_DEBUG) & SC_LOGB);
444    } else {
445	if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
446	    warn("Couldn't reset tty to normal line discipline: %m");
447    }
448
449    return ret_fd;
450}
451
452/********************************************************************
453 *
454 * generic_establish_ppp - Turn the fd into a ppp interface.
455 */
456int generic_establish_ppp (int fd)
457{
458    int x;
459
460    if (new_style_driver) {
461	int flags;
462
463        /* if a ppp_fd is already open, close it first */
464        if(ppp_fd > 0) {
465          close(ppp_fd);
466          remove_fd(ppp_fd);
467          ppp_fd = -1;
468        }
469
470	/* Open an instance of /dev/ppp and connect the channel to it */
471	if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
472	    error("Couldn't get channel number: %m");
473	    goto err;
474	}
475	dbglog("using channel %d", chindex);
476	fd = open("/dev/ppp", O_RDWR);
477	if (fd < 0) {
478	    error("Couldn't reopen /dev/ppp: %m");
479	    goto err;
480	}
481	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
482	if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
483	    error("Couldn't attach to channel %d: %m", chindex);
484	    goto err_close;
485	}
486	flags = fcntl(fd, F_GETFL);
487	if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
488	    warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
489	set_ppp_fd(fd);
490
491	if (!looped)
492	    ifunit = -1;
493	if (!looped && !multilink) {
494	    /*
495	     * Create a new PPP unit.
496	     */
497	    if (make_ppp_unit() < 0)
498		goto err_close;
499	}
500
501	if (looped)
502	    modify_flags(ppp_dev_fd, SC_LOOP_TRAFFIC, 0);
503
504	if (!multilink) {
505	    add_fd(ppp_dev_fd);
506	    if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
507		error("Couldn't attach to PPP unit %d: %m", ifunit);
508		goto err_close;
509	    }
510	}
511
512    } else {
513	/*
514	 * Old-style driver: find out which interface we were given.
515	 */
516	set_ppp_fd (fd);
517	if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
518	    if (ok_error (errno))
519		goto err;
520	    fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
521	}
522	/* Check that we got the same unit again. */
523	if (looped && x != ifunit)
524	    fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
525	ifunit = x;
526
527	/*
528	 * Fetch the initial file flags and reset blocking mode on the file.
529	 */
530	initfdflags = fcntl(fd, F_GETFL);
531	if (initfdflags == -1 ||
532	    fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
533	    if ( ! ok_error (errno))
534		warn("Couldn't set device to non-blocking mode: %m");
535	}
536    }
537
538    /*
539     * Enable debug in the driver if requested.
540     */
541    if (!looped)
542	set_kdebugflag (kdebugflag);
543
544    looped = 0;
545
546    return ppp_fd;
547
548 err_close:
549    close(fd);
550 err:
551    return -1;
552}
553
554/********************************************************************
555 *
556 * tty_disestablish_ppp - Restore the serial port to normal operation.
557 * This shouldn't call die() because it's called from die().
558 */
559
560void tty_disestablish_ppp(int tty_fd)
561{
562    if (!hungup) {
563/*
564 * Flush the tty output buffer so that the TIOCSETD doesn't hang.
565 */
566	if (tcflush(tty_fd, TCIOFLUSH) < 0)
567	{
568	    warn("tcflush failed: %m");
569	    goto flushfailed;
570	}
571/*
572 * Restore the previous line discipline
573 */
574	if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0) {
575	    if ( ! ok_error (errno))
576		error("ioctl(TIOCSETD, N_TTY): %m (line %d)", __LINE__);
577	}
578
579	if (ioctl(tty_fd, TIOCNXCL, 0) < 0) {
580	    if ( ! ok_error (errno))
581		warn("ioctl(TIOCNXCL): %m (line %d)", __LINE__);
582	}
583
584	/* Reset non-blocking mode on fd. */
585	if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0) {
586	    if ( ! ok_error (errno))
587		warn("Couldn't restore device fd flags: %m");
588	}
589    }
590flushfailed:
591    initfdflags = -1;
592
593    generic_disestablish_ppp(tty_fd);
594}
595
596/********************************************************************
597 *
598 * generic_disestablish_ppp - Restore device components to normal
599 * operation, and reconnect the ppp unit to the loopback if in demand
600 * mode.  This shouldn't call die() because it's called from die().
601 */
602void generic_disestablish_ppp(int dev_fd)
603{
604    if (new_style_driver) {
605	close(ppp_fd);
606	ppp_fd = -1;
607	if (demand) {
608	    modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
609	    looped = 1;
610	} else if (!doing_multilink && ppp_dev_fd >= 0) {
611	    close(ppp_dev_fd);
612	    remove_fd(ppp_dev_fd);
613	    ppp_dev_fd = -1;
614	}
615    } else {
616	/* old-style driver */
617	if (demand)
618	    set_ppp_fd(slave_fd);
619	else
620	    ppp_dev_fd = -1;
621    }
622}
623
624/*
625 * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
626 * Assumes new_style_driver.
627 */
628static int make_ppp_unit()
629{
630	int x, flags;
631
632	if (ppp_dev_fd >= 0) {
633		dbglog("in make_ppp_unit, already had /dev/ppp open?");
634		close(ppp_dev_fd);
635	}
636	ppp_dev_fd = open("/dev/ppp", O_RDWR);
637	if (ppp_dev_fd < 0)
638		fatal("Couldn't open /dev/ppp: %m");
639	flags = fcntl(ppp_dev_fd, F_GETFL);
640	if (flags == -1
641	    || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
642		warn("Couldn't set /dev/ppp to nonblock: %m");
643
644	ifunit = (req_unit >= 0) ? req_unit : req_minunit;
645	do {
646		x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
647		if (x < 0 && errno == EEXIST) {
648			warn("Couldn't allocate PPP unit %d as it is already in use", ifunit);
649			ifunit = (req_unit >= 0) ? -1 : ++req_minunit;
650		} else break;
651	} while (ifunit < MAXUNIT);
652
653	if (x < 0)
654		error("Couldn't create new ppp unit: %m");
655	return x;
656}
657
658/*
659 * cfg_bundle - configure the existing bundle.
660 * Used in demand mode.
661 */
662void cfg_bundle(int mrru, int mtru, int rssn, int tssn)
663{
664	if (!new_style_driver)
665		return;
666
667	/* set the mrru, mtu and flags */
668	if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
669		error("Couldn't set MRRU: %m");
670
671	modify_flags(ppp_dev_fd, SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ|SC_MULTILINK,
672		     ((rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
673		      | (mrru? SC_MULTILINK: 0)));
674
675	/* connect up the channel */
676	if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
677		fatal("Couldn't attach to PPP unit %d: %m", ifunit);
678	add_fd(ppp_dev_fd);
679}
680
681/*
682 * make_new_bundle - create a new PPP unit (i.e. a bundle)
683 * and connect our channel to it.  This should only get called
684 * if `multilink' was set at the time establish_ppp was called.
685 * In demand mode this uses our existing bundle instead of making
686 * a new one.
687 */
688void make_new_bundle(int mrru, int mtru, int rssn, int tssn)
689{
690	if (!new_style_driver)
691		return;
692
693	/* make us a ppp unit */
694	if (make_ppp_unit() < 0)
695		die(1);
696
697	/* set the mrru and flags */
698	cfg_bundle(mrru, mtru, rssn, tssn);
699}
700
701/*
702 * bundle_attach - attach our link to a given PPP unit.
703 * We assume the unit is controlled by another pppd.
704 */
705int bundle_attach(int ifnum)
706{
707	int master_fd;
708
709	if (!new_style_driver)
710		return -1;
711
712	master_fd = open("/dev/ppp", O_RDWR);
713	if (master_fd < 0)
714		fatal("Couldn't open /dev/ppp: %m");
715	if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) {
716		if (errno == ENXIO) {
717			close(master_fd);
718			return 0;	/* doesn't still exist */
719		}
720		fatal("Couldn't attach to interface unit %d: %m\n", ifnum);
721	}
722	if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
723		fatal("Couldn't connect to interface unit %d: %m", ifnum);
724	modify_flags(master_fd, 0, SC_MULTILINK);
725	close(master_fd);
726
727	ifunit = ifnum;
728	return 1;
729}
730
731/*
732 * destroy_bundle - tell the driver to destroy our bundle.
733 */
734void destroy_bundle(void)
735{
736	if (ppp_dev_fd >= 0) {
737		close(ppp_dev_fd);
738		remove_fd(ppp_dev_fd);
739		ppp_dev_fd = -1;
740	}
741}
742
743/********************************************************************
744 *
745 * clean_check - Fetch the flags for the device and generate
746 * appropriate error messages.
747 */
748void clean_check(void)
749{
750    int x;
751    char *s;
752
753    if (still_ppp()) {
754	if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
755	    s = NULL;
756	    switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
757	    case SC_RCV_B7_0:
758		s = "all had bit 7 set to 1";
759		break;
760
761	    case SC_RCV_B7_1:
762		s = "all had bit 7 set to 0";
763		break;
764
765	    case SC_RCV_EVNP:
766		s = "all had odd parity";
767		break;
768
769	    case SC_RCV_ODDP:
770		s = "all had even parity";
771		break;
772	    }
773
774	    if (s != NULL) {
775		warn("Receive serial link is not 8-bit clean:");
776		warn("Problem: %s", s);
777	    }
778	}
779    }
780}
781
782
783/*
784 * List of valid speeds.
785 */
786
787struct speed {
788    int speed_int, speed_val;
789} speeds[] = {
790#ifdef B50
791    { 50, B50 },
792#endif
793#ifdef B75
794    { 75, B75 },
795#endif
796#ifdef B110
797    { 110, B110 },
798#endif
799#ifdef B134
800    { 134, B134 },
801#endif
802#ifdef B150
803    { 150, B150 },
804#endif
805#ifdef B200
806    { 200, B200 },
807#endif
808#ifdef B300
809    { 300, B300 },
810#endif
811#ifdef B600
812    { 600, B600 },
813#endif
814#ifdef B1200
815    { 1200, B1200 },
816#endif
817#ifdef B1800
818    { 1800, B1800 },
819#endif
820#ifdef B2000
821    { 2000, B2000 },
822#endif
823#ifdef B2400
824    { 2400, B2400 },
825#endif
826#ifdef B3600
827    { 3600, B3600 },
828#endif
829#ifdef B4800
830    { 4800, B4800 },
831#endif
832#ifdef B7200
833    { 7200, B7200 },
834#endif
835#ifdef B9600
836    { 9600, B9600 },
837#endif
838#ifdef B19200
839    { 19200, B19200 },
840#endif
841#ifdef B38400
842    { 38400, B38400 },
843#endif
844#ifdef B57600
845    { 57600, B57600 },
846#endif
847#ifdef B76800
848    { 76800, B76800 },
849#endif
850#ifdef B115200
851    { 115200, B115200 },
852#endif
853#ifdef EXTA
854    { 19200, EXTA },
855#endif
856#ifdef EXTB
857    { 38400, EXTB },
858#endif
859#ifdef B230400
860    { 230400, B230400 },
861#endif
862#ifdef B460800
863    { 460800, B460800 },
864#endif
865#ifdef B921600
866    { 921600, B921600 },
867#endif
868#ifdef B1000000
869    { 1000000, B1000000 },
870#endif
871#ifdef B1152000
872    { 1152000, B1152000 },
873#endif
874#ifdef B1500000
875    { 1500000, B1500000 },
876#endif
877#ifdef B2000000
878    { 2000000, B2000000 },
879#endif
880#ifdef B2500000
881    { 2500000, B2500000 },
882#endif
883#ifdef B3000000
884    { 3000000, B3000000 },
885#endif
886#ifdef B3500000
887    { 3500000, B3500000 },
888#endif
889#ifdef B4000000
890    { 4000000, B4000000 },
891#endif
892    { 0, 0 }
893};
894
895/********************************************************************
896 *
897 * Translate from bits/second to a speed_t.
898 */
899
900static int translate_speed (int bps)
901{
902    struct speed *speedp;
903
904    if (bps != 0) {
905	for (speedp = speeds; speedp->speed_int; speedp++) {
906	    if (bps == speedp->speed_int)
907		return speedp->speed_val;
908	}
909	warn("speed %d not supported", bps);
910    }
911    return 0;
912}
913
914/********************************************************************
915 *
916 * Translate from a speed_t to bits/second.
917 */
918
919static int baud_rate_of (int speed)
920{
921    struct speed *speedp;
922
923    if (speed != 0) {
924	for (speedp = speeds; speedp->speed_int; speedp++) {
925	    if (speed == speedp->speed_val)
926		return speedp->speed_int;
927	}
928    }
929    return 0;
930}
931
932/********************************************************************
933 *
934 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
935 * at the requested speed, etc.  If `local' is true, set CLOCAL
936 * regardless of whether the modem option was specified.
937 */
938
939void set_up_tty(int tty_fd, int local)
940{
941    int speed;
942    struct termios tios;
943
944    setdtr(tty_fd, 1);
945    if (tcgetattr(tty_fd, &tios) < 0) {
946	if (!ok_error(errno))
947	    fatal("tcgetattr: %m (line %d)", __LINE__);
948	return;
949    }
950
951    if (!restore_term)
952	inittermios = tios;
953
954    tios.c_cflag     &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
955    tios.c_cflag     |= CS8 | CREAD | HUPCL;
956
957    tios.c_iflag      = IGNBRK | IGNPAR;
958    tios.c_oflag      = 0;
959    tios.c_lflag      = 0;
960    tios.c_cc[VMIN]   = 1;
961    tios.c_cc[VTIME]  = 0;
962
963    if (local || !modem)
964	tios.c_cflag ^= (CLOCAL | HUPCL);
965
966    switch (crtscts) {
967    case 1:
968	tios.c_cflag |= CRTSCTS;
969	break;
970
971    case -2:
972	tios.c_iflag     |= IXON | IXOFF;
973	tios.c_cc[VSTOP]  = 0x13;	/* DC3 = XOFF = ^S */
974	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
975	break;
976
977    case -1:
978	tios.c_cflag &= ~CRTSCTS;
979	break;
980
981    default:
982	break;
983    }
984
985    if (stop_bits >= 2)
986	tios.c_cflag |= CSTOPB;
987
988    speed = translate_speed(inspeed);
989    if (speed) {
990	cfsetospeed (&tios, speed);
991	cfsetispeed (&tios, speed);
992    }
993/*
994 * We can't proceed if the serial port speed is B0,
995 * since that implies that the serial port is disabled.
996 */
997    else {
998	speed = cfgetospeed(&tios);
999	if (speed == B0)
1000	    fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
1001    }
1002
1003    while (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0 && !ok_error(errno))
1004	if (errno != EINTR)
1005	    fatal("tcsetattr: %m (line %d)", __LINE__);
1006
1007    baud_rate    = baud_rate_of(speed);
1008    restore_term = 1;
1009}
1010
1011/********************************************************************
1012 *
1013 * setdtr - control the DTR line on the serial port.
1014 * This is called from die(), so it shouldn't call die().
1015 */
1016
1017void setdtr (int tty_fd, int on)
1018{
1019    int modembits = TIOCM_DTR;
1020
1021    ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
1022}
1023
1024/********************************************************************
1025 *
1026 * restore_tty - restore the terminal to the saved settings.
1027 */
1028
1029void restore_tty (int tty_fd)
1030{
1031    if (restore_term) {
1032	restore_term = 0;
1033/*
1034 * Turn off echoing, because otherwise we can get into
1035 * a loop with the tty and the modem echoing to each other.
1036 * We presume we are the sole user of this tty device, so
1037 * when we close it, it will revert to its defaults anyway.
1038 */
1039	if (!default_device)
1040	    inittermios.c_lflag &= ~(ECHO | ECHONL);
1041
1042	if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0) {
1043	    if (! ok_error (errno))
1044		warn("tcsetattr: %m (line %d)", __LINE__);
1045	}
1046    }
1047}
1048
1049/********************************************************************
1050 *
1051 * output - Output PPP packet.
1052 */
1053
1054void output (int unit, unsigned char *p, int len)
1055{
1056    int fd = ppp_fd;
1057    int proto;
1058
1059    dump_packet("sent", p, len);
1060    if (snoop_send_hook) snoop_send_hook(p, len);
1061
1062    if (len < PPP_HDRLEN)
1063	return;
1064    if (new_style_driver) {
1065	p += 2;
1066	len -= 2;
1067	proto = (p[0] << 8) + p[1];
1068	if (ppp_dev_fd >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
1069	    fd = ppp_dev_fd;
1070    }
1071    if (write(fd, p, len) < 0) {
1072	if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOBUFS
1073	    || errno == ENXIO || errno == EIO || errno == EINTR)
1074	    warn("write: warning: %m (%d)", errno);
1075	else
1076	    error("write: %m (%d)", errno);
1077    }
1078}
1079
1080/********************************************************************
1081 *
1082 * wait_input - wait until there is data available,
1083 * for the length of time specified by *timo (indefinite
1084 * if timo is NULL).
1085 */
1086
1087void wait_input(struct timeval *timo)
1088{
1089    fd_set ready, exc;
1090    int n;
1091
1092    ready = in_fds;
1093    exc = in_fds;
1094    n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
1095    if (n < 0 && errno != EINTR)
1096	fatal("select: %m");
1097}
1098
1099/*
1100 * add_fd - add an fd to the set that wait_input waits for.
1101 */
1102void add_fd(int fd)
1103{
1104    if (fd >= FD_SETSIZE)
1105	fatal("internal error: file descriptor too large (%d)", fd);
1106    FD_SET(fd, &in_fds);
1107    if (fd > max_in_fd)
1108	max_in_fd = fd;
1109}
1110
1111/*
1112 * remove_fd - remove an fd from the set that wait_input waits for.
1113 */
1114void remove_fd(int fd)
1115{
1116    FD_CLR(fd, &in_fds);
1117}
1118
1119
1120/********************************************************************
1121 *
1122 * read_packet - get a PPP packet from the serial device.
1123 */
1124
1125int read_packet (unsigned char *buf)
1126{
1127    int len, nr;
1128
1129    len = PPP_MRU + PPP_HDRLEN;
1130    if (new_style_driver) {
1131	*buf++ = PPP_ALLSTATIONS;
1132	*buf++ = PPP_UI;
1133	len -= 2;
1134    }
1135    nr = -1;
1136    if (ppp_fd >= 0) {
1137	nr = read(ppp_fd, buf, len);
1138	if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1139	    && errno != EIO && errno != EINTR)
1140	    error("read: %m");
1141	if (nr < 0 && errno == ENXIO)
1142	    return 0;
1143    }
1144    if (nr < 0 && new_style_driver && ppp_dev_fd >= 0 && !bundle_eof) {
1145	/* N.B. we read ppp_fd first since LCP packets come in there. */
1146	nr = read(ppp_dev_fd, buf, len);
1147	if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1148	    && errno != EIO && errno != EINTR)
1149	    error("read /dev/ppp: %m");
1150	if (nr < 0 && errno == ENXIO)
1151	    nr = 0;
1152	if (nr == 0 && doing_multilink) {
1153	    remove_fd(ppp_dev_fd);
1154	    bundle_eof = 1;
1155	}
1156    }
1157    if (new_style_driver && ppp_fd < 0 && ppp_dev_fd < 0)
1158	nr = 0;
1159    return (new_style_driver && nr > 0)? nr+2: nr;
1160}
1161
1162/********************************************************************
1163 *
1164 * get_loop_output - get outgoing packets from the ppp device,
1165 * and detect when we want to bring the real link up.
1166 * Return value is 1 if we need to bring up the link, 0 otherwise.
1167 */
1168int
1169get_loop_output(void)
1170{
1171    int rv = 0;
1172    int n;
1173
1174    if (new_style_driver) {
1175	while ((n = read_packet(inpacket_buf)) > 0)
1176	    if (loop_frame(inpacket_buf, n))
1177		rv = 1;
1178	return rv;
1179    }
1180
1181    while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0)
1182	if (loop_chars(inbuf, n))
1183	    rv = 1;
1184
1185    if (n == 0)
1186	fatal("eof on loopback");
1187
1188    if (errno != EWOULDBLOCK && errno != EAGAIN)
1189	fatal("read from loopback: %m(%d)", errno);
1190
1191    return rv;
1192}
1193
1194/*
1195 * netif_set_mtu - set the MTU on the PPP network interface.
1196 */
1197void
1198netif_set_mtu(int unit, int mtu)
1199{
1200    struct ifreq ifr;
1201
1202    memset (&ifr, '\0', sizeof (ifr));
1203    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1204    ifr.ifr_mtu = mtu;
1205
1206    if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
1207	error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);
1208}
1209
1210/*
1211 * netif_get_mtu - get the MTU on the PPP network interface.
1212 */
1213int
1214netif_get_mtu(int unit)
1215{
1216    struct ifreq ifr;
1217
1218    memset (&ifr, '\0', sizeof (ifr));
1219    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1220
1221    if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
1222	error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__);
1223	return 0;
1224    }
1225    return ifr.ifr_mtu;
1226}
1227
1228/********************************************************************
1229 *
1230 * tty_send_config - configure the transmit characteristics of
1231 * the ppp interface.
1232 */
1233
1234void tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
1235{
1236	int x;
1237
1238	if (!still_ppp())
1239		return;
1240	link_mtu = mtu;
1241	if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
1242		if (errno != EIO && errno != ENOTTY)
1243			error("Couldn't set transmit async character map: %m");
1244		++error_count;
1245		return;
1246	}
1247
1248	x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0)
1249	    | (sync_serial? SC_SYNC: 0);
1250	modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x);
1251}
1252
1253/********************************************************************
1254 *
1255 * tty_set_xaccm - set the extended transmit ACCM for the interface.
1256 */
1257
1258void tty_set_xaccm (ext_accm accm)
1259{
1260    if (!still_ppp())
1261	return;
1262    if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) {
1263	if ( ! ok_error (errno))
1264	    warn("ioctl(set extended ACCM): %m (line %d)", __LINE__);
1265    }
1266}
1267
1268/********************************************************************
1269 *
1270 * tty_recv_config - configure the receive-side characteristics of
1271 * the ppp interface.
1272 */
1273
1274void tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
1275{
1276/*
1277 * If we were called because the link has gone down then there is nothing
1278 * which may be done. Just return without incident.
1279 */
1280	if (!still_ppp())
1281		return;
1282/*
1283 * Set the receiver parameters
1284 */
1285	if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
1286		if (errno != EIO && errno != ENOTTY)
1287			error("Couldn't set channel receive MRU: %m");
1288	}
1289	if (new_style_driver && ppp_dev_fd >= 0
1290	    && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
1291		error("Couldn't set MRU in generic PPP layer: %m");
1292
1293	if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
1294		if (errno != EIO && errno != ENOTTY)
1295			error("Couldn't set channel receive asyncmap: %m");
1296	}
1297}
1298
1299/********************************************************************
1300 *
1301 * ccp_test - ask kernel whether a given compression method
1302 * is acceptable for use.
1303 */
1304
1305int
1306ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
1307{
1308    struct ppp_option_data data;
1309
1310    memset (&data, '\0', sizeof (data));
1311    data.ptr      = opt_ptr;
1312    data.length   = opt_len;
1313    data.transmit = for_transmit;
1314
1315    if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1316	return 1;
1317
1318    return (errno == ENOBUFS)? 0: -1;
1319}
1320
1321/********************************************************************
1322 *
1323 * ccp_flags_set - inform kernel about the current state of CCP.
1324 */
1325
1326void ccp_flags_set (int unit, int isopen, int isup)
1327{
1328	int x;
1329
1330	x = (isopen? SC_CCP_OPEN: 0) | (isup? SC_CCP_UP: 0);
1331	if (still_ppp() && ppp_dev_fd >= 0)
1332		modify_flags(ppp_dev_fd, SC_CCP_OPEN|SC_CCP_UP, x);
1333}
1334
1335#ifdef PPP_FILTER
1336/*
1337 * set_filters - set the active and pass filters in the kernel driver.
1338 */
1339int set_filters(struct bpf_program *pass, struct bpf_program *active)
1340{
1341	struct sock_fprog fp;
1342
1343	fp.len = pass->bf_len;
1344	fp.filter = (struct sock_filter *) pass->bf_insns;
1345	if (ioctl(ppp_dev_fd, PPPIOCSPASS, &fp) < 0) {
1346		if (errno == ENOTTY)
1347			warn("kernel does not support PPP filtering");
1348		else
1349			error("Couldn't set pass-filter in kernel: %m");
1350		return 0;
1351	}
1352	fp.len = active->bf_len;
1353	fp.filter = (struct sock_filter *) active->bf_insns;
1354	if (ioctl(ppp_dev_fd, PPPIOCSACTIVE, &fp) < 0) {
1355		error("Couldn't set active-filter in kernel: %m");
1356		return 0;
1357	}
1358	return 1;
1359}
1360#endif /* PPP_FILTER */
1361
1362/********************************************************************
1363 *
1364 * get_idle_time - return how long the link has been idle.
1365 */
1366int
1367get_idle_time(u, ip)
1368    int u;
1369    struct ppp_idle *ip;
1370{
1371    return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;
1372}
1373
1374/********************************************************************
1375 *
1376 * get_ppp_stats - return statistics for the link.
1377 */
1378int
1379get_ppp_stats(u, stats)
1380    int u;
1381    struct pppd_stats *stats;
1382{
1383    struct ifpppstatsreq req;
1384
1385    memset (&req, 0, sizeof (req));
1386
1387    req.stats_ptr = (caddr_t) &req.stats;
1388    strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
1389    if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
1390	error("Couldn't get PPP statistics: %m");
1391	return 0;
1392    }
1393    stats->bytes_in = req.stats.p.ppp_ibytes;
1394    stats->bytes_out = req.stats.p.ppp_obytes;
1395    stats->pkts_in = req.stats.p.ppp_ipackets;
1396    stats->pkts_out = req.stats.p.ppp_opackets;
1397    return 1;
1398}
1399
1400/********************************************************************
1401 *
1402 * ccp_fatal_error - returns 1 if decompression was disabled as a
1403 * result of an error detected after decompression of a packet,
1404 * 0 otherwise.  This is necessary because of patent nonsense.
1405 */
1406
1407int ccp_fatal_error (int unit)
1408{
1409	int flags;
1410
1411	if (ioctl(ppp_dev_fd, PPPIOCGFLAGS, &flags) < 0) {
1412		error("Couldn't read compression error flags: %m");
1413		flags = 0;
1414	}
1415	return flags & SC_DC_FERROR;
1416}
1417
1418/********************************************************************
1419 *
1420 * path_to_procfs - find the path to the proc file system mount point
1421 */
1422static char proc_path[MAXPATHLEN];
1423static int proc_path_len;
1424
1425static char *path_to_procfs(const char *tail)
1426{
1427    struct mntent *mntent;
1428    FILE *fp;
1429
1430    if (proc_path_len == 0) {
1431	/* Default the mount location of /proc */
1432	strlcpy (proc_path, "/proc", sizeof(proc_path));
1433	proc_path_len = 5;
1434	fp = fopen(MOUNTED, "r");
1435	if (fp != NULL) {
1436	    while ((mntent = getmntent(fp)) != NULL) {
1437		if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
1438		    continue;
1439		if (strcmp(mntent->mnt_type, "proc") == 0) {
1440		    strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path));
1441		    proc_path_len = strlen(proc_path);
1442		    break;
1443		}
1444	    }
1445	    fclose (fp);
1446	}
1447    }
1448
1449    strlcpy(proc_path + proc_path_len, tail,
1450	    sizeof(proc_path) - proc_path_len);
1451    return proc_path;
1452}
1453
1454/*
1455 * /proc/net/route parsing stuff.
1456 */
1457#define ROUTE_MAX_COLS	12
1458FILE *route_fd = (FILE *) 0;
1459static char route_buffer[512];
1460static int route_dev_col, route_dest_col, route_gw_col;
1461static int route_flags_col, route_mask_col;
1462static int route_num_cols;
1463
1464static int open_route_table (void);
1465static void close_route_table (void);
1466static int read_route_table (struct rtentry *rt);
1467
1468/********************************************************************
1469 *
1470 * close_route_table - close the interface to the route table
1471 */
1472
1473static void close_route_table (void)
1474{
1475    if (route_fd != (FILE *) 0) {
1476	fclose (route_fd);
1477	route_fd = (FILE *) 0;
1478    }
1479}
1480
1481/********************************************************************
1482 *
1483 * open_route_table - open the interface to the route table
1484 */
1485static char route_delims[] = " \t\n";
1486
1487static int open_route_table (void)
1488{
1489    char *path;
1490
1491    close_route_table();
1492
1493    path = path_to_procfs("/net/route");
1494    route_fd = fopen (path, "r");
1495    if (route_fd == NULL) {
1496	error("can't open routing table %s: %m", path);
1497	return 0;
1498    }
1499
1500    route_dev_col = 0;		/* default to usual columns */
1501    route_dest_col = 1;
1502    route_gw_col = 2;
1503    route_flags_col = 3;
1504    route_mask_col = 7;
1505    route_num_cols = 8;
1506
1507    /* parse header line */
1508    if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
1509	char *p = route_buffer, *q;
1510	int col;
1511	for (col = 0; col < ROUTE_MAX_COLS; ++col) {
1512	    int used = 1;
1513	    if ((q = strtok(p, route_delims)) == 0)
1514		break;
1515	    if (strcasecmp(q, "iface") == 0)
1516		route_dev_col = col;
1517	    else if (strcasecmp(q, "destination") == 0)
1518		route_dest_col = col;
1519	    else if (strcasecmp(q, "gateway") == 0)
1520		route_gw_col = col;
1521	    else if (strcasecmp(q, "flags") == 0)
1522		route_flags_col = col;
1523	    else if (strcasecmp(q, "mask") == 0)
1524		route_mask_col = col;
1525	    else
1526		used = 0;
1527	    if (used && col >= route_num_cols)
1528		route_num_cols = col + 1;
1529	    p = NULL;
1530	}
1531    }
1532
1533    return 1;
1534}
1535
1536/********************************************************************
1537 *
1538 * read_route_table - read the next entry from the route table
1539 */
1540
1541static int read_route_table(struct rtentry *rt)
1542{
1543    char *cols[ROUTE_MAX_COLS], *p;
1544    int col;
1545
1546    memset (rt, '\0', sizeof (struct rtentry));
1547
1548    if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
1549	return 0;
1550
1551    p = route_buffer;
1552    for (col = 0; col < route_num_cols; ++col) {
1553	cols[col] = strtok(p, route_delims);
1554	if (cols[col] == NULL)
1555	    return 0;		/* didn't get enough columns */
1556	p = NULL;
1557    }
1558
1559    SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
1560    SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
1561    SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
1562
1563    rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
1564    rt->rt_dev   = cols[route_dev_col];
1565
1566    return 1;
1567}
1568
1569/********************************************************************
1570 *
1571 * defaultroute_exists - determine if there is a default route
1572 */
1573
1574static int defaultroute_exists (struct rtentry *rt)
1575{
1576    int result = 0;
1577
1578    if (!open_route_table())
1579	return 0;
1580
1581    while (read_route_table(rt) != 0) {
1582	if ((rt->rt_flags & RTF_UP) == 0)
1583	    continue;
1584
1585	if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
1586	    continue;
1587	if (SIN_ADDR(rt->rt_dst) == 0L) {
1588	    result = 1;
1589	    break;
1590	}
1591    }
1592
1593    close_route_table();
1594    return result;
1595}
1596
1597/*
1598 * have_route_to - determine if the system has any route to
1599 * a given IP address.  `addr' is in network byte order.
1600 * Return value is 1 if yes, 0 if no, -1 if don't know.
1601 * For demand mode to work properly, we have to ignore routes
1602 * through our own interface.
1603 */
1604int have_route_to(u_int32_t addr)
1605{
1606    struct rtentry rt;
1607    int result = 0;
1608
1609    if (!open_route_table())
1610	return -1;		/* don't know */
1611
1612    while (read_route_table(&rt)) {
1613	if ((rt.rt_flags & RTF_UP) == 0 || strcmp(rt.rt_dev, ifname) == 0)
1614	    continue;
1615	if ((addr & SIN_ADDR(rt.rt_genmask)) == SIN_ADDR(rt.rt_dst)) {
1616	    result = 1;
1617	    break;
1618	}
1619    }
1620
1621    close_route_table();
1622    return result;
1623}
1624
1625/********************************************************************
1626 *
1627 * sifdefaultroute - assign a default route through the address given.
1628 */
1629
1630int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
1631{
1632    struct rtentry rt;
1633
1634    if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
1635	if (rt.rt_flags & RTF_GATEWAY)
1636	    error("not replacing existing default route via %I",
1637		  SIN_ADDR(rt.rt_gateway));
1638	else
1639	    error("not replacing existing default route through %s",
1640		  rt.rt_dev);
1641	return 0;
1642    }
1643
1644    memset (&rt, 0, sizeof (rt));
1645    SET_SA_FAMILY (rt.rt_dst, AF_INET);
1646
1647    rt.rt_dev = ifname;
1648
1649    if (kernel_version > KVERSION(2,1,0)) {
1650	SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1651	SIN_ADDR(rt.rt_genmask) = 0L;
1652    }
1653
1654    rt.rt_flags = RTF_UP;
1655    if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
1656	if ( ! ok_error ( errno ))
1657	    error("default route ioctl(SIOCADDRT): %m");
1658	return 0;
1659    }
1660
1661    have_default_route = 1;
1662    return 1;
1663}
1664
1665/********************************************************************
1666 *
1667 * cifdefaultroute - delete a default route through the address given.
1668 */
1669
1670int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
1671{
1672    struct rtentry rt;
1673
1674    have_default_route = 0;
1675
1676    memset (&rt, '\0', sizeof (rt));
1677    SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1678    SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1679
1680    rt.rt_dev = ifname;
1681
1682    if (kernel_version > KVERSION(2,1,0)) {
1683	SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1684	SIN_ADDR(rt.rt_genmask) = 0L;
1685    }
1686
1687    rt.rt_flags = RTF_UP;
1688    if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
1689	if (still_ppp()) {
1690	    if ( ! ok_error ( errno ))
1691		error("default route ioctl(SIOCDELRT): %m");
1692	    return 0;
1693	}
1694    }
1695
1696    return 1;
1697}
1698
1699/********************************************************************
1700 *
1701 * sifproxyarp - Make a proxy ARP entry for the peer.
1702 */
1703
1704int sifproxyarp (int unit, u_int32_t his_adr)
1705{
1706    struct arpreq arpreq;
1707    char *forw_path;
1708
1709    if (has_proxy_arp == 0) {
1710	memset (&arpreq, '\0', sizeof(arpreq));
1711
1712	SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1713	SIN_ADDR(arpreq.arp_pa) = his_adr;
1714	arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1715/*
1716 * Get the hardware address of an interface on the same subnet
1717 * as our local address.
1718 */
1719	if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,
1720			    sizeof(proxy_arp_dev))) {
1721	    error("Cannot determine ethernet address for proxy ARP");
1722	    return 0;
1723	}
1724	strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
1725
1726	if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1727	    if ( ! ok_error ( errno ))
1728		error("ioctl(SIOCSARP): %m");
1729	    return 0;
1730	}
1731	proxy_arp_addr = his_adr;
1732	has_proxy_arp = 1;
1733
1734	if (tune_kernel) {
1735	    forw_path = path_to_procfs("/sys/net/ipv4/ip_forward");
1736	    if (forw_path != 0) {
1737		int fd = open(forw_path, O_WRONLY);
1738		if (fd >= 0) {
1739		    if (write(fd, "1", 1) != 1)
1740			error("Couldn't enable IP forwarding: %m");
1741		    close(fd);
1742		}
1743	    }
1744	}
1745    }
1746
1747    return 1;
1748}
1749
1750/********************************************************************
1751 *
1752 * cifproxyarp - Delete the proxy ARP entry for the peer.
1753 */
1754
1755int cifproxyarp (int unit, u_int32_t his_adr)
1756{
1757    struct arpreq arpreq;
1758
1759    if (has_proxy_arp) {
1760	has_proxy_arp = 0;
1761	memset (&arpreq, '\0', sizeof(arpreq));
1762	SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1763	SIN_ADDR(arpreq.arp_pa) = his_adr;
1764	arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1765	strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
1766
1767	if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1768	    if ( ! ok_error ( errno ))
1769		warn("ioctl(SIOCDARP): %m");
1770	    return 0;
1771	}
1772    }
1773    return 1;
1774}
1775
1776/********************************************************************
1777 *
1778 * get_ether_addr - get the hardware address of an interface on the
1779 * the same subnet as ipaddr.
1780 */
1781
1782static int get_ether_addr (u_int32_t ipaddr,
1783			   struct sockaddr *hwaddr,
1784			   char *name, int namelen)
1785{
1786    struct ifreq *ifr, *ifend;
1787    u_int32_t ina, mask;
1788    char *aliasp;
1789    struct ifreq ifreq, bestifreq;
1790    struct ifconf ifc;
1791    struct ifreq ifs[MAX_IFS];
1792
1793    u_int32_t bestmask=0;
1794    int found_interface = 0;
1795
1796    ifc.ifc_len = sizeof(ifs);
1797    ifc.ifc_req = ifs;
1798    if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
1799	if ( ! ok_error ( errno ))
1800	    error("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
1801	return 0;
1802    }
1803
1804/*
1805 * Scan through looking for an interface with an Internet
1806 * address on the same subnet as `ipaddr'.
1807 */
1808    ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1809    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1810	if (ifr->ifr_addr.sa_family == AF_INET) {
1811	    ina = SIN_ADDR(ifr->ifr_addr);
1812	    strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1813/*
1814 * Check that the interface is up, and not point-to-point
1815 * nor loopback.
1816 */
1817	    if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1818		continue;
1819
1820	    if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1821		continue;
1822/*
1823 * Get its netmask and check that it's on the right subnet.
1824 */
1825	    if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1826		continue;
1827
1828	    mask = SIN_ADDR(ifreq.ifr_addr);
1829
1830	    if (((ipaddr ^ ina) & mask) != 0)
1831		continue; /* no match */
1832	    /* matched */
1833	    if (mask >= bestmask) {
1834		/* Compare using >= instead of > -- it is possible for
1835		   an interface to have a netmask of 0.0.0.0 */
1836		found_interface = 1;
1837		bestifreq = ifreq;
1838		bestmask = mask;
1839	    }
1840	}
1841    }
1842
1843    if (!found_interface) return 0;
1844
1845    strlcpy(name, bestifreq.ifr_name, namelen);
1846
1847    /* trim off the :1 in eth0:1 */
1848    aliasp = strchr(name, ':');
1849    if (aliasp != 0)
1850	*aliasp = 0;
1851
1852    info("found interface %s for proxy arp", name);
1853/*
1854 * Now get the hardware address.
1855 */
1856    memset (&bestifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
1857    if (ioctl (sock_fd, SIOCGIFHWADDR, &bestifreq) < 0) {
1858	error("SIOCGIFHWADDR(%s): %m", bestifreq.ifr_name);
1859	return 0;
1860    }
1861
1862    memcpy (hwaddr,
1863	    &bestifreq.ifr_hwaddr,
1864	    sizeof (struct sockaddr));
1865
1866    return 1;
1867}
1868
1869/*
1870 * get_if_hwaddr - get the hardware address for the specified
1871 * network interface device.
1872 */
1873int
1874get_if_hwaddr(u_char *addr, char *name)
1875{
1876	struct ifreq ifreq;
1877	int ret, sock_fd;
1878
1879	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
1880	if (sock_fd < 0)
1881		return 0;
1882	memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
1883	strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
1884	ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
1885	close(sock_fd);
1886	if (ret >= 0)
1887		memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6);
1888	return ret;
1889}
1890
1891/*
1892 * get_first_ethernet - return the name of the first ethernet-style
1893 * interface on this system.
1894 */
1895char *
1896get_first_ethernet()
1897{
1898	return "eth0";
1899}
1900
1901/********************************************************************
1902 *
1903 * Return user specified netmask, modified by any mask we might determine
1904 * for address `addr' (in network byte order).
1905 * Here we scan through the system's list of interfaces, looking for
1906 * any non-point-to-point interfaces which might appear to be on the same
1907 * network as `addr'.  If we find any, we OR in their netmask to the
1908 * user-specified netmask.
1909 */
1910
1911u_int32_t GetMask (u_int32_t addr)
1912{
1913    u_int32_t mask, nmask, ina;
1914    struct ifreq *ifr, *ifend, ifreq;
1915    struct ifconf ifc;
1916    struct ifreq ifs[MAX_IFS];
1917
1918    addr = ntohl(addr);
1919
1920    if (IN_CLASSA(addr))	/* determine network mask for address class */
1921	nmask = IN_CLASSA_NET;
1922    else if (IN_CLASSB(addr))
1923	    nmask = IN_CLASSB_NET;
1924    else
1925	    nmask = IN_CLASSC_NET;
1926
1927    /* class D nets are disallowed by bad_ip_adrs */
1928    mask = netmask | htonl(nmask);
1929/*
1930 * Scan through the system's network interfaces.
1931 */
1932    ifc.ifc_len = sizeof(ifs);
1933    ifc.ifc_req = ifs;
1934    if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
1935	if ( ! ok_error ( errno ))
1936	    warn("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
1937	return mask;
1938    }
1939
1940    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1941    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1942/*
1943 * Check the interface's internet address.
1944 */
1945	if (ifr->ifr_addr.sa_family != AF_INET)
1946	    continue;
1947	ina = SIN_ADDR(ifr->ifr_addr);
1948	if (((ntohl(ina) ^ addr) & nmask) != 0)
1949	    continue;
1950/*
1951 * Check that the interface is up, and not point-to-point nor loopback.
1952 */
1953	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1954	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1955	    continue;
1956
1957	if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1958	    continue;
1959/*
1960 * Get its netmask and OR it into our mask.
1961 */
1962	if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1963	    continue;
1964	mask |= SIN_ADDR(ifreq.ifr_addr);
1965	break;
1966    }
1967    return mask;
1968}
1969
1970/********************************************************************
1971 *
1972 * Internal routine to decode the version.modification.patch level
1973 */
1974
1975static void decode_version (char *buf, int *version,
1976			    int *modification, int *patch)
1977{
1978    char *endp;
1979
1980    *version      = (int) strtoul (buf, &endp, 10);
1981    *modification = 0;
1982    *patch        = 0;
1983
1984    if (endp != buf && *endp == '.') {
1985	buf = endp + 1;
1986	*modification = (int) strtoul (buf, &endp, 10);
1987	if (endp != buf && *endp == '.') {
1988	    buf = endp + 1;
1989	    *patch = (int) strtoul (buf, &buf, 10);
1990	}
1991    }
1992}
1993
1994/********************************************************************
1995 *
1996 * Procedure to determine if the PPP line discipline is registered.
1997 */
1998
1999static int
2000ppp_registered(void)
2001{
2002    int local_fd;
2003    int mfd = -1;
2004    int ret = 0;
2005    char slave[16];
2006
2007    /*
2008     * We used to open the serial device and set it to the ppp line
2009     * discipline here, in order to create a ppp unit.  But that is
2010     * not a good idea - the user might have specified a device that
2011     * they can't open (permission, or maybe it doesn't really exist).
2012     * So we grab a pty master/slave pair and use that.
2013     */
2014    if (!get_pty(&mfd, &local_fd, slave, 0)) {
2015	no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";
2016	return 0;
2017    }
2018
2019    /*
2020     * Try to put the device into the PPP discipline.
2021     */
2022    if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
2023	error("ioctl(TIOCSETD(PPP)): %m (line %d)", __LINE__);
2024    } else
2025	ret = 1;
2026
2027    close(local_fd);
2028    close(mfd);
2029    return ret;
2030}
2031
2032/********************************************************************
2033 *
2034 * ppp_available - check whether the system has any ppp interfaces
2035 * (in fact we check whether we can do an ioctl on ppp0).
2036 */
2037
2038int ppp_available(void)
2039{
2040    int s, ok, fd;
2041    struct ifreq ifr;
2042    int    size;
2043    int    my_version, my_modification, my_patch;
2044    int osmaj, osmin, ospatch;
2045
2046    /* get the kernel version now, since we are called before sys_init */
2047    uname(&utsname);
2048    osmaj = osmin = ospatch = 0;
2049    sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
2050    kernel_version = KVERSION(osmaj, osmin, ospatch);
2051
2052    fd = open("/dev/ppp", O_RDWR);
2053    if (fd >= 0) {
2054	new_style_driver = 1;
2055
2056	/* XXX should get from driver */
2057	driver_version = 2;
2058	driver_modification = 4;
2059	driver_patch = 0;
2060	close(fd);
2061	return 1;
2062    }
2063
2064    if (kernel_version >= KVERSION(2,3,13)) {
2065	error("Couldn't open the /dev/ppp device: %m");
2066	if (errno == ENOENT)
2067	    no_ppp_msg =
2068		"You need to create the /dev/ppp device node by\n"
2069		"executing the following command as root:\n"
2070		"	mknod /dev/ppp c 108 0\n";
2071	else if (errno == ENODEV || errno == ENXIO)
2072	    no_ppp_msg =
2073		"Please load the ppp_generic kernel module.\n";
2074	return 0;
2075    }
2076
2077    /* we are running on a really really old kernel */
2078    no_ppp_msg =
2079	"This system lacks kernel support for PPP.  This could be because\n"
2080	"the PPP kernel module could not be loaded, or because PPP was not\n"
2081	"included in the kernel configuration.  If PPP was included as a\n"
2082	"module, try `/sbin/modprobe -v ppp'.  If that fails, check that\n"
2083	"ppp.o exists in /lib/modules/`uname -r`/net.\n"
2084	"See README.linux file in the ppp distribution for more details.\n";
2085
2086/*
2087 * Open a socket for doing the ioctl operations.
2088 */
2089    s = socket(AF_INET, SOCK_DGRAM, 0);
2090    if (s < 0)
2091	return 0;
2092
2093    strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2094    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2095/*
2096 * If the device did not exist then attempt to create one by putting the
2097 * current tty into the PPP discipline. If this works then obtain the
2098 * flags for the device again.
2099 */
2100    if (!ok) {
2101	if (ppp_registered()) {
2102	    strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2103	    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2104	}
2105    }
2106/*
2107 * Ensure that the hardware address is for PPP and not something else
2108 */
2109    if (ok)
2110	ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
2111
2112    if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
2113	ok = 0;
2114
2115/*
2116 *  This is the PPP device. Validate the version of the driver at this
2117 *  point to ensure that this program will work with the driver.
2118 */
2119    if (ok) {
2120	char   abBuffer [1024];
2121
2122	ifr.ifr_data = abBuffer;
2123	size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
2124	if (size < 0) {
2125	    error("Couldn't read driver version: %m");
2126	    ok = 0;
2127	    no_ppp_msg = "Sorry, couldn't verify kernel driver version\n";
2128
2129	} else {
2130	    decode_version(abBuffer,
2131			   &driver_version,
2132			   &driver_modification,
2133			   &driver_patch);
2134/*
2135 * Validate the version of the driver against the version that we used.
2136 */
2137	    decode_version(VERSION,
2138			   &my_version,
2139			   &my_modification,
2140			   &my_patch);
2141
2142	    /* The version numbers must match */
2143	    if (driver_version != my_version)
2144		ok = 0;
2145
2146	    /* The modification levels must be legal */
2147	    if (driver_modification < 3) {
2148		if (driver_modification >= 2) {
2149		    /* we can cope with 2.2.0 and above */
2150		    driver_is_old = 1;
2151		} else {
2152		    ok = 0;
2153		}
2154	    }
2155
2156	    close (s);
2157	    if (!ok) {
2158		slprintf(route_buffer, sizeof(route_buffer),
2159			 "Sorry - PPP driver version %d.%d.%d is out of date\n",
2160			 driver_version, driver_modification, driver_patch);
2161
2162		no_ppp_msg = route_buffer;
2163	    }
2164	}
2165    }
2166    return ok;
2167}
2168
2169#ifndef HAVE_LOGWTMP
2170/********************************************************************
2171 *
2172 * Update the wtmp file with the appropriate user name and tty device.
2173 */
2174
2175void logwtmp (const char *line, const char *name, const char *host)
2176{
2177#if 0
2178    struct utmp ut, *utp;
2179    pid_t  mypid = getpid();
2180#if __GLIBC__ < 2
2181    int    wtmp;
2182#endif
2183
2184/*
2185 * Update the signon database for users.
2186 * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
2187 */
2188    utmpname(_PATH_UTMP);
2189    setutent();
2190    while ((utp = getutent()) && (utp->ut_pid != mypid))
2191	/* nothing */;
2192
2193    if (utp)
2194	memcpy(&ut, utp, sizeof(ut));
2195    else
2196	/* some gettys/telnetds don't initialize utmp... */
2197	memset(&ut, 0, sizeof(ut));
2198
2199    if (ut.ut_id[0] == 0)
2200	strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
2201
2202    strncpy(ut.ut_user, name, sizeof(ut.ut_user));
2203    strncpy(ut.ut_line, line, sizeof(ut.ut_line));
2204
2205    time(&ut.ut_time);
2206
2207    ut.ut_type = USER_PROCESS;
2208    ut.ut_pid  = mypid;
2209
2210    /* Insert the host name if one is supplied */
2211    if (*host)
2212	strncpy (ut.ut_host, host, sizeof(ut.ut_host));
2213
2214    /* Insert the IP address of the remote system if IP is enabled */
2215    if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
2216	memcpy(&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
2217		 sizeof(ut.ut_addr));
2218
2219    /* CL: Makes sure that the logout works */
2220    if (*host == 0 && *name==0)
2221	ut.ut_host[0]=0;
2222
2223    pututline(&ut);
2224    endutent();
2225/*
2226 * Update the wtmp file.
2227 */
2228#if __GLIBC__ >= 2
2229    updwtmp(_PATH_WTMP, &ut);
2230#else
2231    wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
2232    if (wtmp >= 0) {
2233	flock(wtmp, LOCK_EX);
2234
2235	if (write (wtmp, (char *)&ut, sizeof(ut)) != sizeof(ut))
2236	    warn("error writing %s: %m", _PATH_WTMP);
2237
2238	flock(wtmp, LOCK_UN);
2239
2240	close (wtmp);
2241    }
2242#endif
2243#endif
2244}
2245#endif /* HAVE_LOGWTMP */
2246
2247/********************************************************************
2248 *
2249 * sifvjcomp - config tcp header compression
2250 */
2251
2252int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
2253{
2254	u_int x;
2255
2256	if (vjcomp) {
2257		if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
2258			error("Couldn't set up TCP header compression: %m");
2259			vjcomp = 0;
2260		}
2261	}
2262
2263	x = (vjcomp? SC_COMP_TCP: 0) | (cidcomp? 0: SC_NO_TCP_CCID);
2264	modify_flags(ppp_dev_fd, SC_COMP_TCP|SC_NO_TCP_CCID, x);
2265
2266	return 1;
2267}
2268
2269/********************************************************************
2270 *
2271 * sifname - Config the interface name.
2272 */
2273int sifname (int unit, const char *newname)
2274{
2275    struct ifreq ifr;
2276    int ifindex;
2277
2278    if (strcmp(ifname, newname) == 0)
2279	return 1;
2280
2281    memset(&ifr, 0, sizeof(ifr));
2282    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2283
2284    /* Get and keep interface index */
2285    if (ioctl(sock_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
2286	error("ioctl (SIOCGIFINDEX): %m (line %d)", __LINE__);
2287	return 0;
2288    }
2289    ifindex = ifr.ifr_ifindex;
2290
2291    /* Set new interface name, patterns such as "vpn%d" are allowed
2292     * by kernel, the lowest available slot will be used */
2293    strlcpy(ifr.ifr_newname, newname, sizeof(ifr.ifr_newname));
2294    if (ioctl(sock_fd, SIOCSIFNAME, (caddr_t) &ifr) < 0) {
2295	error("Couldn't set interface name %s: %m", ifr.ifr_newname);
2296	return 0;
2297    }
2298
2299    /* Get new interface name back */
2300    ifr.ifr_ifindex = ifindex;
2301    if (ioctl(sock_fd, SIOCGIFNAME, (caddr_t) &ifr) < 0) {
2302	error("ioctl (SIOCGIFNAME): %m (line %d)", __LINE__);
2303        return 0;
2304    }
2305
2306    strcpy(ifname, ifr.ifr_name);
2307    return 1;
2308}
2309
2310/********************************************************************
2311 *
2312 * sifup - Config the interface up and enable IP packets to pass.
2313 */
2314
2315int sifup(int u)
2316{
2317    int ret;
2318
2319    if ((ret = setifstate(u, 1)))
2320	if_is_up++;
2321
2322    return ret;
2323}
2324
2325/********************************************************************
2326 *
2327 * sifdown - Disable the indicated protocol and config the interface
2328 *	     down if there are no remaining protocols.
2329 */
2330
2331int sifdown (int u)
2332{
2333    if (if_is_up && --if_is_up > 0)
2334	return 1;
2335
2336#ifdef INET6
2337    if (if6_is_up)
2338	return 1;
2339#endif /* INET6 */
2340
2341    return setifstate(u, 0);
2342}
2343
2344#ifdef INET6
2345/********************************************************************
2346 *
2347 * sif6up - Config the interface up for IPv6
2348 */
2349
2350int sif6up(int u)
2351{
2352    int ret;
2353
2354    if ((ret = setifstate(u, 1)))
2355	if6_is_up = 1;
2356
2357    return ret;
2358}
2359
2360/********************************************************************
2361 *
2362 * sif6down - Disable the IPv6CP protocol and config the interface
2363 *	      down if there are no remaining protocols.
2364 */
2365
2366int sif6down (int u)
2367{
2368    if6_is_up = 0;
2369
2370    if (if_is_up)
2371	return 1;
2372
2373    return setifstate(u, 0);
2374}
2375#endif /* INET6 */
2376
2377/********************************************************************
2378 *
2379 * setifstate - Config the interface up or down
2380 */
2381
2382static int setifstate (int u, int state)
2383{
2384    struct ifreq ifr;
2385
2386    memset (&ifr, '\0', sizeof (ifr));
2387    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2388    if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
2389	if (! ok_error (errno))
2390	    error("ioctl (SIOCGIFFLAGS): %m (line %d)", __LINE__);
2391	return 0;
2392    }
2393
2394    if (state)
2395	ifr.ifr_flags |= IFF_UP;
2396    else
2397	ifr.ifr_flags &= ~IFF_UP;
2398    ifr.ifr_flags |= IFF_POINTOPOINT;
2399    if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
2400	if (! ok_error (errno))
2401	    error("ioctl(SIOCSIFFLAGS): %m (line %d)", __LINE__);
2402	return 0;
2403    }
2404    return 1;
2405}
2406
2407/********************************************************************
2408 *
2409 * sifaddr - Config the interface IP addresses and netmask.
2410 */
2411
2412int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
2413	     u_int32_t net_mask)
2414{
2415    struct ifreq   ifr;
2416    struct rtentry rt;
2417
2418    memset (&ifr, '\0', sizeof (ifr));
2419    memset (&rt,  '\0', sizeof (rt));
2420
2421    SET_SA_FAMILY (ifr.ifr_addr,    AF_INET);
2422    SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
2423    SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
2424
2425    strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2426/*
2427 *  Set our IP address
2428 */
2429    SIN_ADDR(ifr.ifr_addr) = our_adr;
2430    if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2431	if (errno != EEXIST) {
2432	    if (! ok_error (errno))
2433		error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2434	}
2435	else {
2436	    warn("ioctl(SIOCSIFADDR): Address already exists");
2437	}
2438	return (0);
2439    }
2440/*
2441 *  Set the gateway address
2442 */
2443    if (his_adr != 0) {
2444	SIN_ADDR(ifr.ifr_dstaddr) = his_adr;
2445	if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
2446	    if (! ok_error (errno))
2447		error("ioctl(SIOCSIFDSTADDR): %m (line %d)", __LINE__);
2448	    return (0);
2449	}
2450    }
2451/*
2452 *  Set the netmask.
2453 *  For recent kernels, force the netmask to 255.255.255.255.
2454 */
2455    if (kernel_version >= KVERSION(2,1,16))
2456	net_mask = ~0L;
2457    if (net_mask != 0) {
2458	SIN_ADDR(ifr.ifr_netmask) = net_mask;
2459	if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
2460	    if (! ok_error (errno))
2461		error("ioctl(SIOCSIFNETMASK): %m (line %d)", __LINE__);
2462	    return (0);
2463	}
2464    }
2465/*
2466 *  Add the device route
2467 */
2468    if (kernel_version < KVERSION(2,1,16)) {
2469	SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2470	SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2471	rt.rt_dev = ifname;
2472
2473	SIN_ADDR(rt.rt_gateway) = 0L;
2474	SIN_ADDR(rt.rt_dst)     = his_adr;
2475	rt.rt_flags = RTF_UP | RTF_HOST;
2476
2477	if (kernel_version > KVERSION(2,1,0)) {
2478	    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2479	    SIN_ADDR(rt.rt_genmask) = -1L;
2480	}
2481
2482	if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
2483	    if (! ok_error (errno))
2484		error("ioctl(SIOCADDRT) device route: %m (line %d)", __LINE__);
2485	    return (0);
2486	}
2487    }
2488
2489    /* set ip_dynaddr in demand mode if address changes */
2490    if (demand && tune_kernel && !dynaddr_set
2491	&& our_old_addr && our_old_addr != our_adr) {
2492	/* set ip_dynaddr if possible */
2493	char *path;
2494	int fd;
2495
2496	path = path_to_procfs("/sys/net/ipv4/ip_dynaddr");
2497	if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
2498	    if (write(fd, "1", 1) != 1)
2499		error("Couldn't enable dynamic IP addressing: %m");
2500	    close(fd);
2501	}
2502	dynaddr_set = 1;	/* only 1 attempt */
2503    }
2504    our_old_addr = 0;
2505
2506    return 1;
2507}
2508
2509/********************************************************************
2510 *
2511 * cifaddr - Clear the interface IP addresses, and delete routes
2512 * through the interface if possible.
2513 */
2514
2515int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
2516{
2517    struct ifreq ifr;
2518
2519    if (kernel_version < KVERSION(2,1,16)) {
2520/*
2521 *  Delete the route through the device
2522 */
2523	struct rtentry rt;
2524	memset (&rt, '\0', sizeof (rt));
2525
2526	SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2527	SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2528	rt.rt_dev = ifname;
2529
2530	SIN_ADDR(rt.rt_gateway) = 0;
2531	SIN_ADDR(rt.rt_dst)     = his_adr;
2532	rt.rt_flags = RTF_UP | RTF_HOST;
2533
2534	if (kernel_version > KVERSION(2,1,0)) {
2535	    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2536	    SIN_ADDR(rt.rt_genmask) = -1L;
2537	}
2538
2539	if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
2540	    if (still_ppp() && ! ok_error (errno))
2541		error("ioctl(SIOCDELRT) device route: %m (line %d)", __LINE__);
2542	    return (0);
2543	}
2544    }
2545
2546    /* This way it is possible to have an IPX-only or IPv6-only interface */
2547    memset(&ifr, 0, sizeof(ifr));
2548    SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
2549    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2550
2551    if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2552	if (! ok_error (errno)) {
2553	    error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2554	    return 0;
2555	}
2556    }
2557
2558    our_old_addr = our_adr;
2559
2560    return 1;
2561}
2562
2563#ifdef INET6
2564/********************************************************************
2565 *
2566 * sif6addr - Config the interface with an IPv6 link-local address
2567 */
2568int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
2569{
2570    struct in6_ifreq ifr6;
2571    struct ifreq ifr;
2572    struct in6_rtmsg rt6;
2573
2574    if (sock6_fd < 0) {
2575	errno = -sock6_fd;
2576	error("IPv6 socket creation failed: %m");
2577	return 0;
2578    }
2579    memset(&ifr, 0, sizeof (ifr));
2580    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2581    if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
2582	error("sif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
2583	return 0;
2584    }
2585
2586    /* Local interface */
2587    memset(&ifr6, 0, sizeof(ifr6));
2588    IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
2589    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
2590    ifr6.ifr6_prefixlen = 10;
2591
2592    if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
2593	error("sif6addr: ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
2594	return 0;
2595    }
2596
2597    /* Route to remote host */
2598    memset(&rt6, 0, sizeof(rt6));
2599    IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
2600    rt6.rtmsg_flags = RTF_UP;
2601    rt6.rtmsg_dst_len = 10;
2602    rt6.rtmsg_ifindex = ifr.ifr_ifindex;
2603    rt6.rtmsg_metric = 1;
2604
2605    if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
2606	error("sif6addr: ioctl(SIOCADDRT): %m (line %d)", __LINE__);
2607	return 0;
2608    }
2609
2610    return 1;
2611}
2612
2613
2614/********************************************************************
2615 *
2616 * cif6addr - Remove IPv6 address from interface
2617 */
2618int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
2619{
2620    struct ifreq ifr;
2621    struct in6_ifreq ifr6;
2622
2623    if (sock6_fd < 0) {
2624	errno = -sock6_fd;
2625	error("IPv6 socket creation failed: %m");
2626	return 0;
2627    }
2628    memset(&ifr, 0, sizeof(ifr));
2629    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2630    if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
2631	error("cif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
2632	return 0;
2633    }
2634
2635    memset(&ifr6, 0, sizeof(ifr6));
2636    IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
2637    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
2638    ifr6.ifr6_prefixlen = 10;
2639
2640    if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
2641	if (errno != EADDRNOTAVAIL) {
2642	    if (! ok_error (errno))
2643		error("cif6addr: ioctl(SIOCDIFADDR): %m (line %d)", __LINE__);
2644	}
2645	else {
2646	    warn("cif6addr: ioctl(SIOCDIFADDR): No such address");
2647	}
2648	return (0);
2649    }
2650    return 1;
2651}
2652#endif /* INET6 */
2653
2654/*
2655 * get_pty - get a pty master/slave pair and chown the slave side
2656 * to the uid given.  Assumes slave_name points to >= 16 bytes of space.
2657 */
2658int
2659get_pty(master_fdp, slave_fdp, slave_name, uid)
2660    int *master_fdp;
2661    int *slave_fdp;
2662    char *slave_name;
2663    int uid;
2664{
2665    int i, mfd, sfd = -1;
2666    char pty_name[16];
2667    struct termios tios;
2668
2669#ifdef TIOCGPTN
2670    /*
2671     * Try the unix98 way first.
2672     */
2673    mfd = open("/dev/ptmx", O_RDWR);
2674    if (mfd >= 0) {
2675	int ptn;
2676	if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) {
2677	    slprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn);
2678	    chmod(pty_name, S_IRUSR | S_IWUSR);
2679#ifdef TIOCSPTLCK
2680	    ptn = 0;
2681	    if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0)
2682		warn("Couldn't unlock pty slave %s: %m", pty_name);
2683#endif
2684	    if ((sfd = open(pty_name, O_RDWR | O_NOCTTY)) < 0)
2685		warn("Couldn't open pty slave %s: %m", pty_name);
2686	}
2687    }
2688#endif /* TIOCGPTN */
2689
2690    if (sfd < 0) {
2691	/* the old way - scan through the pty name space */
2692	for (i = 0; i < 64; ++i) {
2693	    slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
2694		     'p' + i / 16, i % 16);
2695	    mfd = open(pty_name, O_RDWR, 0);
2696	    if (mfd >= 0) {
2697		pty_name[5] = 't';
2698		sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
2699		if (sfd >= 0) {
2700		    fchown(sfd, uid, -1);
2701		    fchmod(sfd, S_IRUSR | S_IWUSR);
2702		    break;
2703		}
2704		close(mfd);
2705	    }
2706	}
2707    }
2708
2709    if (sfd < 0)
2710	return 0;
2711
2712    strlcpy(slave_name, pty_name, 16);
2713    *master_fdp = mfd;
2714    *slave_fdp = sfd;
2715    if (tcgetattr(sfd, &tios) == 0) {
2716	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
2717	tios.c_cflag |= CS8 | CREAD | CLOCAL;
2718	tios.c_iflag  = IGNPAR;
2719	tios.c_oflag  = 0;
2720	tios.c_lflag  = 0;
2721	if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
2722	    warn("couldn't set attributes on pty: %m");
2723    } else
2724	warn("couldn't get attributes on pty: %m");
2725
2726    return 1;
2727}
2728
2729/********************************************************************
2730 *
2731 * open_loopback - open the device we use for getting packets
2732 * in demand mode.  Under Linux, we use a pty master/slave pair.
2733 */
2734int
2735open_ppp_loopback(void)
2736{
2737    int flags;
2738
2739    looped = 1;
2740    if (new_style_driver) {
2741	/* allocate ourselves a ppp unit */
2742	if (make_ppp_unit() < 0)
2743	    die(1);
2744	modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
2745	set_kdebugflag(kdebugflag);
2746	ppp_fd = -1;
2747	return ppp_dev_fd;
2748    }
2749
2750    if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
2751	fatal("No free pty for loopback");
2752
2753    set_ppp_fd(slave_fd);
2754
2755    flags = fcntl(master_fd, F_GETFL);
2756    if (flags == -1 ||
2757	fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2758	warn("couldn't set master loopback to nonblock: %m");
2759
2760    flags = fcntl(ppp_fd, F_GETFL);
2761    if (flags == -1 ||
2762	fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2763	warn("couldn't set slave loopback to nonblock: %m");
2764
2765    if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
2766	fatal("ioctl(TIOCSETD): %m (line %d)", __LINE__);
2767/*
2768 * Find out which interface we were given.
2769 */
2770    if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
2771	fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
2772/*
2773 * Enable debug in the driver if requested.
2774 */
2775    set_kdebugflag (kdebugflag);
2776
2777    return master_fd;
2778}
2779
2780/********************************************************************
2781 *
2782 * sifnpmode - Set the mode for handling packets for a given NP.
2783 */
2784
2785int
2786sifnpmode(u, proto, mode)
2787    int u;
2788    int proto;
2789    enum NPmode mode;
2790{
2791    struct npioctl npi;
2792
2793    npi.protocol = proto;
2794    npi.mode     = mode;
2795    if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
2796	if (! ok_error (errno))
2797	    error("ioctl(PPPIOCSNPMODE, %d, %d): %m", proto, mode);
2798	return 0;
2799    }
2800    return 1;
2801}
2802
2803
2804/********************************************************************
2805 *
2806 * sipxfaddr - Config the interface IPX networknumber
2807 */
2808
2809int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
2810{
2811    int    result = 1;
2812
2813#ifdef IPX_CHANGE
2814    int    skfd;
2815    struct ifreq         ifr;
2816    struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2817
2818    skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2819    if (skfd < 0) {
2820	if (! ok_error (errno))
2821	    dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
2822	result = 0;
2823    }
2824    else {
2825	memset (&ifr, '\0', sizeof (ifr));
2826	strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2827
2828	memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
2829	sipx->sipx_family  = AF_IPX;
2830	sipx->sipx_port    = 0;
2831	sipx->sipx_network = htonl (network);
2832	sipx->sipx_type    = IPX_FRAME_ETHERII;
2833	sipx->sipx_action  = IPX_CRTITF;
2834/*
2835 *  Set the IPX device
2836 */
2837	if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2838	    result = 0;
2839	    if (errno != EEXIST) {
2840		if (! ok_error (errno))
2841		    dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (line %d)", __LINE__);
2842	    }
2843	    else {
2844		warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists");
2845	    }
2846	}
2847	close (skfd);
2848    }
2849#endif
2850    return result;
2851}
2852
2853/********************************************************************
2854 *
2855 * cipxfaddr - Clear the information for the IPX network. The IPX routes
2856 *	       are removed and the device is no longer able to pass IPX
2857 *	       frames.
2858 */
2859
2860int cipxfaddr (int unit)
2861{
2862    int    result = 1;
2863
2864#ifdef IPX_CHANGE
2865    int    skfd;
2866    struct ifreq         ifr;
2867    struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2868
2869    skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2870    if (skfd < 0) {
2871	if (! ok_error (errno))
2872	    dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
2873	result = 0;
2874    }
2875    else {
2876	memset (&ifr, '\0', sizeof (ifr));
2877	strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
2878
2879	sipx->sipx_type    = IPX_FRAME_ETHERII;
2880	sipx->sipx_action  = IPX_DLTITF;
2881	sipx->sipx_family  = AF_IPX;
2882/*
2883 *  Set the IPX device
2884 */
2885	if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
2886	    if (! ok_error (errno))
2887		info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (line %d)", __LINE__);
2888	    result = 0;
2889	}
2890	close (skfd);
2891    }
2892#endif
2893    return result;
2894}
2895
2896/*
2897 * Use the hostname as part of the random number seed.
2898 */
2899int
2900get_host_seed()
2901{
2902    int h;
2903    char *p = hostname;
2904
2905    h = 407;
2906    for (p = hostname; *p != 0; ++p)
2907	h = h * 37 + *p;
2908    return h;
2909}
2910
2911/********************************************************************
2912 *
2913 * sys_check_options - check the options that the user specified
2914 */
2915
2916int
2917sys_check_options(void)
2918{
2919#ifdef IPX_CHANGE
2920/*
2921 * Disable the IPX protocol if the support is not present in the kernel.
2922 */
2923    char *path;
2924
2925    if (ipxcp_protent.enabled_flag) {
2926	struct stat stat_buf;
2927	if (  ((path = path_to_procfs("/net/ipx/interface")) == NULL
2928	    && (path = path_to_procfs("/net/ipx_interface")) == NULL)
2929	    || lstat(path, &stat_buf) < 0) {
2930	    error("IPX support is not present in the kernel\n");
2931	    ipxcp_protent.enabled_flag = 0;
2932	}
2933    }
2934#endif
2935    if (demand && driver_is_old) {
2936	option_error("demand dialling is not supported by kernel driver "
2937		     "version %d.%d.%d", driver_version, driver_modification,
2938		     driver_patch);
2939	return 0;
2940    }
2941    if (multilink && !new_style_driver) {
2942	warn("Warning: multilink is not supported by the kernel driver");
2943	multilink = 0;
2944    }
2945    return 1;
2946}
2947
2948#ifdef INET6
2949/*
2950 * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
2951 *
2952 * convert the 48-bit MAC address of eth0 into EUI 64. caller also assumes
2953 * that the system has a properly configured Ethernet interface for this
2954 * function to return non-zero.
2955 */
2956int
2957ether_to_eui64(eui64_t *p_eui64)
2958{
2959    struct ifreq ifr;
2960    int skfd;
2961    const unsigned char *ptr;
2962
2963    skfd = socket(PF_INET6, SOCK_DGRAM, 0);
2964    if(skfd == -1)
2965    {
2966        warn("could not open IPv6 socket");
2967        return 0;
2968    }
2969
2970    strcpy(ifr.ifr_name, "eth0");
2971    if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
2972    {
2973        close(skfd);
2974        warn("could not obtain hardware address for eth0");
2975        return 0;
2976    }
2977    close(skfd);
2978
2979    /*
2980     * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
2981     */
2982    ptr = (unsigned char *) ifr.ifr_hwaddr.sa_data;
2983    p_eui64->e8[0] = ptr[0] | 0x02;
2984    p_eui64->e8[1] = ptr[1];
2985    p_eui64->e8[2] = ptr[2];
2986    p_eui64->e8[3] = 0xFF;
2987    p_eui64->e8[4] = 0xFE;
2988    p_eui64->e8[5] = ptr[3];
2989    p_eui64->e8[6] = ptr[4];
2990    p_eui64->e8[7] = ptr[5];
2991
2992    return 1;
2993}
2994#endif
2995