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