182c907af479178801a7a8701341b22c9d20fdb7Upstream/*
282c907af479178801a7a8701341b22c9d20fdb7Upstream * sys-linux.c - System-dependent procedures for setting up
382c907af479178801a7a8701341b22c9d20fdb7Upstream * PPP interfaces on Linux systems
482c907af479178801a7a8701341b22c9d20fdb7Upstream *
582c907af479178801a7a8701341b22c9d20fdb7Upstream * Copyright (c) 1994-2004 Paul Mackerras. All rights reserved.
682c907af479178801a7a8701341b22c9d20fdb7Upstream *
782c907af479178801a7a8701341b22c9d20fdb7Upstream * Redistribution and use in source and binary forms, with or without
882c907af479178801a7a8701341b22c9d20fdb7Upstream * modification, are permitted provided that the following conditions
982c907af479178801a7a8701341b22c9d20fdb7Upstream * are met:
1082c907af479178801a7a8701341b22c9d20fdb7Upstream *
1182c907af479178801a7a8701341b22c9d20fdb7Upstream * 1. Redistributions of source code must retain the above copyright
1282c907af479178801a7a8701341b22c9d20fdb7Upstream *    notice, this list of conditions and the following disclaimer.
1382c907af479178801a7a8701341b22c9d20fdb7Upstream *
1482c907af479178801a7a8701341b22c9d20fdb7Upstream * 2. The name(s) of the authors of this software must not be used to
1582c907af479178801a7a8701341b22c9d20fdb7Upstream *    endorse or promote products derived from this software without
1682c907af479178801a7a8701341b22c9d20fdb7Upstream *    prior written permission.
1782c907af479178801a7a8701341b22c9d20fdb7Upstream *
1882c907af479178801a7a8701341b22c9d20fdb7Upstream * 3. Redistributions of any form whatsoever must retain the following
1982c907af479178801a7a8701341b22c9d20fdb7Upstream *    acknowledgment:
2082c907af479178801a7a8701341b22c9d20fdb7Upstream *    "This product includes software developed by Paul Mackerras
2182c907af479178801a7a8701341b22c9d20fdb7Upstream *     <paulus@samba.org>".
2282c907af479178801a7a8701341b22c9d20fdb7Upstream *
2382c907af479178801a7a8701341b22c9d20fdb7Upstream * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
2482c907af479178801a7a8701341b22c9d20fdb7Upstream * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
2582c907af479178801a7a8701341b22c9d20fdb7Upstream * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
2682c907af479178801a7a8701341b22c9d20fdb7Upstream * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2782c907af479178801a7a8701341b22c9d20fdb7Upstream * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
2882c907af479178801a7a8701341b22c9d20fdb7Upstream * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
2982c907af479178801a7a8701341b22c9d20fdb7Upstream * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3082c907af479178801a7a8701341b22c9d20fdb7Upstream *
3182c907af479178801a7a8701341b22c9d20fdb7Upstream * Derived from main.c and pppd.h, which are:
3282c907af479178801a7a8701341b22c9d20fdb7Upstream *
3382c907af479178801a7a8701341b22c9d20fdb7Upstream * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
3482c907af479178801a7a8701341b22c9d20fdb7Upstream *
3582c907af479178801a7a8701341b22c9d20fdb7Upstream * Redistribution and use in source and binary forms, with or without
3682c907af479178801a7a8701341b22c9d20fdb7Upstream * modification, are permitted provided that the following conditions
3782c907af479178801a7a8701341b22c9d20fdb7Upstream * are met:
3882c907af479178801a7a8701341b22c9d20fdb7Upstream *
3982c907af479178801a7a8701341b22c9d20fdb7Upstream * 1. Redistributions of source code must retain the above copyright
4082c907af479178801a7a8701341b22c9d20fdb7Upstream *    notice, this list of conditions and the following disclaimer.
4182c907af479178801a7a8701341b22c9d20fdb7Upstream *
4282c907af479178801a7a8701341b22c9d20fdb7Upstream * 2. Redistributions in binary form must reproduce the above copyright
4382c907af479178801a7a8701341b22c9d20fdb7Upstream *    notice, this list of conditions and the following disclaimer in
4482c907af479178801a7a8701341b22c9d20fdb7Upstream *    the documentation and/or other materials provided with the
4582c907af479178801a7a8701341b22c9d20fdb7Upstream *    distribution.
4682c907af479178801a7a8701341b22c9d20fdb7Upstream *
4782c907af479178801a7a8701341b22c9d20fdb7Upstream * 3. The name "Carnegie Mellon University" must not be used to
4882c907af479178801a7a8701341b22c9d20fdb7Upstream *    endorse or promote products derived from this software without
4982c907af479178801a7a8701341b22c9d20fdb7Upstream *    prior written permission. For permission or any legal
5082c907af479178801a7a8701341b22c9d20fdb7Upstream *    details, please contact
5182c907af479178801a7a8701341b22c9d20fdb7Upstream *      Office of Technology Transfer
5282c907af479178801a7a8701341b22c9d20fdb7Upstream *      Carnegie Mellon University
5382c907af479178801a7a8701341b22c9d20fdb7Upstream *      5000 Forbes Avenue
5482c907af479178801a7a8701341b22c9d20fdb7Upstream *      Pittsburgh, PA  15213-3890
5582c907af479178801a7a8701341b22c9d20fdb7Upstream *      (412) 268-4387, fax: (412) 268-7395
5682c907af479178801a7a8701341b22c9d20fdb7Upstream *      tech-transfer@andrew.cmu.edu
5782c907af479178801a7a8701341b22c9d20fdb7Upstream *
5882c907af479178801a7a8701341b22c9d20fdb7Upstream * 4. Redistributions of any form whatsoever must retain the following
5982c907af479178801a7a8701341b22c9d20fdb7Upstream *    acknowledgment:
6082c907af479178801a7a8701341b22c9d20fdb7Upstream *    "This product includes software developed by Computing Services
6182c907af479178801a7a8701341b22c9d20fdb7Upstream *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
6282c907af479178801a7a8701341b22c9d20fdb7Upstream *
6382c907af479178801a7a8701341b22c9d20fdb7Upstream * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
6482c907af479178801a7a8701341b22c9d20fdb7Upstream * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
6582c907af479178801a7a8701341b22c9d20fdb7Upstream * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
6682c907af479178801a7a8701341b22c9d20fdb7Upstream * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
6782c907af479178801a7a8701341b22c9d20fdb7Upstream * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
6882c907af479178801a7a8701341b22c9d20fdb7Upstream * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
6982c907af479178801a7a8701341b22c9d20fdb7Upstream * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
7082c907af479178801a7a8701341b22c9d20fdb7Upstream */
7182c907af479178801a7a8701341b22c9d20fdb7Upstream
7282c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/ioctl.h>
7382c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/types.h>
7482c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/socket.h>
7582c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/time.h>
7682c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/errno.h>
7782c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/file.h>
7882c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/stat.h>
7982c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/utsname.h>
8082c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/sysmacros.h>
8182c907af479178801a7a8701341b22c9d20fdb7Upstream
8282c907af479178801a7a8701341b22c9d20fdb7Upstream#include <stdio.h>
8382c907af479178801a7a8701341b22c9d20fdb7Upstream#include <stdlib.h>
8482c907af479178801a7a8701341b22c9d20fdb7Upstream#include <syslog.h>
8582c907af479178801a7a8701341b22c9d20fdb7Upstream#include <string.h>
8682c907af479178801a7a8701341b22c9d20fdb7Upstream#include <time.h>
8782c907af479178801a7a8701341b22c9d20fdb7Upstream#include <memory.h>
8882c907af479178801a7a8701341b22c9d20fdb7Upstream#include <utmp.h>
8982c907af479178801a7a8701341b22c9d20fdb7Upstream#include <mntent.h>
9082c907af479178801a7a8701341b22c9d20fdb7Upstream#include <signal.h>
9182c907af479178801a7a8701341b22c9d20fdb7Upstream#include <fcntl.h>
9282c907af479178801a7a8701341b22c9d20fdb7Upstream#include <ctype.h>
9382c907af479178801a7a8701341b22c9d20fdb7Upstream#include <termios.h>
9482c907af479178801a7a8701341b22c9d20fdb7Upstream#include <unistd.h>
95dab68864983c4a0c6ef9e6d7e5834472c4c75f9cThe Android Open Source Project#include <paths.h>
9682c907af479178801a7a8701341b22c9d20fdb7Upstream
9782c907af479178801a7a8701341b22c9d20fdb7Upstream/* This is in netdevice.h. However, this compile will fail miserably if
9882c907af479178801a7a8701341b22c9d20fdb7Upstream   you attempt to include netdevice.h because it has so many references
9982c907af479178801a7a8701341b22c9d20fdb7Upstream   to __memcpy functions which it should not attempt to do. So, since I
10082c907af479178801a7a8701341b22c9d20fdb7Upstream   really don't use it, but it must be defined, define it now. */
10182c907af479178801a7a8701341b22c9d20fdb7Upstream
10282c907af479178801a7a8701341b22c9d20fdb7Upstream#ifndef MAX_ADDR_LEN
103dab68864983c4a0c6ef9e6d7e5834472c4c75f9cThe Android Open Source Project#define xxMAX_ADDR_LEN 7
10482c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
10582c907af479178801a7a8701341b22c9d20fdb7Upstream
10682c907af479178801a7a8701341b22c9d20fdb7Upstream#if __GLIBC__ >= 2
10782c907af479178801a7a8701341b22c9d20fdb7Upstream#include <asm/types.h>		/* glibc 2 conflicts with linux/types.h */
10882c907af479178801a7a8701341b22c9d20fdb7Upstream#include <net/if.h>
10982c907af479178801a7a8701341b22c9d20fdb7Upstream#include <net/if_arp.h>
11082c907af479178801a7a8701341b22c9d20fdb7Upstream#include <net/route.h>
11182c907af479178801a7a8701341b22c9d20fdb7Upstream#include <netinet/if_ether.h>
11282c907af479178801a7a8701341b22c9d20fdb7Upstream#else
11382c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/types.h>
1145e0738a2d8667ec1ea629649edc4fc5ae453f4a1Elliott Hughes#include <linux/tty.h>
11582c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/if.h>
11682c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/if_arp.h>
11782c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/route.h>
11882c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/if_ether.h>
11982c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
120dab68864983c4a0c6ef9e6d7e5834472c4c75f9cThe Android Open Source Project#include <linux/sockios.h>
12182c907af479178801a7a8701341b22c9d20fdb7Upstream#include <netinet/in.h>
12282c907af479178801a7a8701341b22c9d20fdb7Upstream#include <arpa/inet.h>
12382c907af479178801a7a8701341b22c9d20fdb7Upstream
12482c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/ppp_defs.h>
12582c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/if_ppp.h>
12682c907af479178801a7a8701341b22c9d20fdb7Upstream
12782c907af479178801a7a8701341b22c9d20fdb7Upstream#include "pppd.h"
12882c907af479178801a7a8701341b22c9d20fdb7Upstream#include "fsm.h"
12982c907af479178801a7a8701341b22c9d20fdb7Upstream#include "ipcp.h"
13082c907af479178801a7a8701341b22c9d20fdb7Upstream
13182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef IPX_CHANGE
13282c907af479178801a7a8701341b22c9d20fdb7Upstream#include "ipxcp.h"
13382c907af479178801a7a8701341b22c9d20fdb7Upstream#if __GLIBC__ >= 2 && \
13482c907af479178801a7a8701341b22c9d20fdb7Upstream    !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
13582c907af479178801a7a8701341b22c9d20fdb7Upstream#include <netipx/ipx.h>
13682c907af479178801a7a8701341b22c9d20fdb7Upstream#else
13782c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/ipx.h>
13882c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
13982c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* IPX_CHANGE */
14082c907af479178801a7a8701341b22c9d20fdb7Upstream
14182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef PPP_FILTER
14282c907af479178801a7a8701341b22c9d20fdb7Upstream#include <pcap-bpf.h>
14382c907af479178801a7a8701341b22c9d20fdb7Upstream#include <linux/filter.h>
14482c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* PPP_FILTER */
14582c907af479178801a7a8701341b22c9d20fdb7Upstream
14682c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef LOCKLIB
14782c907af479178801a7a8701341b22c9d20fdb7Upstream#include <sys/locks.h>
14882c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
14982c907af479178801a7a8701341b22c9d20fdb7Upstream
15082c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef INET6
15182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifndef _LINUX_IN6_H
15282c907af479178801a7a8701341b22c9d20fdb7Upstream/*
15382c907af479178801a7a8701341b22c9d20fdb7Upstream *    This is in linux/include/net/ipv6.h.
15482c907af479178801a7a8701341b22c9d20fdb7Upstream */
15582c907af479178801a7a8701341b22c9d20fdb7Upstream
15682c907af479178801a7a8701341b22c9d20fdb7Upstreamstruct in6_ifreq {
15782c907af479178801a7a8701341b22c9d20fdb7Upstream    struct in6_addr ifr6_addr;
15882c907af479178801a7a8701341b22c9d20fdb7Upstream    __u32 ifr6_prefixlen;
15982c907af479178801a7a8701341b22c9d20fdb7Upstream    unsigned int ifr6_ifindex;
16082c907af479178801a7a8701341b22c9d20fdb7Upstream};
16182c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
16282c907af479178801a7a8701341b22c9d20fdb7Upstream
16382c907af479178801a7a8701341b22c9d20fdb7Upstream#define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {			\
16482c907af479178801a7a8701341b22c9d20fdb7Upstream	memset(&sin6.s6_addr, 0, sizeof(struct in6_addr));	\
16582c907af479178801a7a8701341b22c9d20fdb7Upstream	sin6.s6_addr16[0] = htons(0xfe80);			\
16682c907af479178801a7a8701341b22c9d20fdb7Upstream	eui64_copy(eui64, sin6.s6_addr32[2]);			\
16782c907af479178801a7a8701341b22c9d20fdb7Upstream	} while (0)
16882c907af479178801a7a8701341b22c9d20fdb7Upstream
16982c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* INET6 */
17082c907af479178801a7a8701341b22c9d20fdb7Upstream
17182c907af479178801a7a8701341b22c9d20fdb7Upstream/* We can get an EIO error on an ioctl if the modem has hung up */
17282c907af479178801a7a8701341b22c9d20fdb7Upstream#define ok_error(num) ((num)==EIO)
17382c907af479178801a7a8701341b22c9d20fdb7Upstream
17482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int tty_disc = N_TTY;	/* The TTY discipline */
17582c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int ppp_disc = N_PPP;	/* The PPP discpline */
17682c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int initfdflags = -1;	/* Initial file descriptor flags for fd */
17782c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int ppp_fd = -1;		/* fd which is set to PPP discipline */
17882c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int sock_fd = -1;	/* socket for doing interface ioctls */
17982c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int slave_fd = -1;	/* pty for old-style demand mode, slave */
18082c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int master_fd = -1;	/* pty for old-style demand mode, master */
18182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef INET6
18282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int sock6_fd = -1;
18382c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* INET6 */
18482c907af479178801a7a8701341b22c9d20fdb7Upstream
18582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
18682c907af479178801a7a8701341b22c9d20fdb7Upstream * For the old-style kernel driver, this is the same as ppp_fd.
18782c907af479178801a7a8701341b22c9d20fdb7Upstream * For the new-style driver, it is the fd of an instance of /dev/ppp
18882c907af479178801a7a8701341b22c9d20fdb7Upstream * which is attached to the ppp unit and is used for controlling it.
18982c907af479178801a7a8701341b22c9d20fdb7Upstream */
19082c907af479178801a7a8701341b22c9d20fdb7Upstreamint ppp_dev_fd = -1;		/* fd for /dev/ppp (new style driver) */
19182c907af479178801a7a8701341b22c9d20fdb7Upstream
19282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int chindex;		/* channel index (new style driver) */
19382c907af479178801a7a8701341b22c9d20fdb7Upstream
19482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic fd_set in_fds;		/* set of fds that wait_input waits for */
19582c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int max_in_fd;		/* highest fd set in in_fds */
19682c907af479178801a7a8701341b22c9d20fdb7Upstream
19782c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int has_proxy_arp       = 0;
19882c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int driver_version      = 0;
19982c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int driver_modification = 0;
20082c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int driver_patch        = 0;
20182c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int driver_is_old       = 0;
20282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int restore_term        = 0;	/* 1 => we've munged the terminal */
20382c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic struct termios inittermios;	/* Initial TTY termios */
20482c907af479178801a7a8701341b22c9d20fdb7Upstream
20582c907af479178801a7a8701341b22c9d20fdb7Upstreamint new_style_driver = 0;
20682c907af479178801a7a8701341b22c9d20fdb7Upstream
20782c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic char loop_name[20];
20882c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic unsigned char inbuf[512]; /* buffer for chars read from loopback */
20982c907af479178801a7a8701341b22c9d20fdb7Upstream
21082c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int	if_is_up;	/* Interface has been marked up */
21182c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic u_int32_t default_route_gateway;	/* Gateway for default route added */
21282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
21382c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic char proxy_arp_dev[16];		/* Device for proxy arp entry */
21482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic u_int32_t our_old_addr;		/* for detecting address changes */
21582c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int	dynaddr_set;		/* 1 if ip_dynaddr set */
21682c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int	looped;			/* 1 if using loop */
21782c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int	link_mtu;		/* mtu for the link (not bundle) */
21882c907af479178801a7a8701341b22c9d20fdb7Upstream
21982c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic struct utsname utsname;	/* for the kernel version */
22082c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int kernel_version;
22182c907af479178801a7a8701341b22c9d20fdb7Upstream#define KVERSION(j,n,p)	((j)*1000000 + (n)*1000 + (p))
22282c907af479178801a7a8701341b22c9d20fdb7Upstream
22382c907af479178801a7a8701341b22c9d20fdb7Upstream#define MAX_IFS		100
22482c907af479178801a7a8701341b22c9d20fdb7Upstream
22582c907af479178801a7a8701341b22c9d20fdb7Upstream#define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
22682c907af479178801a7a8701341b22c9d20fdb7Upstream#define FLAGS_MASK (IFF_UP          | IFF_BROADCAST | \
22782c907af479178801a7a8701341b22c9d20fdb7Upstream		    IFF_POINTOPOINT | IFF_LOOPBACK  | IFF_NOARP)
22882c907af479178801a7a8701341b22c9d20fdb7Upstream
22982c907af479178801a7a8701341b22c9d20fdb7Upstream#define SIN_ADDR(x)	(((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
23082c907af479178801a7a8701341b22c9d20fdb7Upstream
23182c907af479178801a7a8701341b22c9d20fdb7Upstream/* Prototypes for procedures local to this file. */
23282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int modify_flags(int fd, int clear_bits, int set_bits);
23382c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int translate_speed (int bps);
23482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int baud_rate_of (int speed);
23582c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic void close_route_table (void);
23682c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int open_route_table (void);
23782c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int read_route_table (struct rtentry *rt);
23882c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int defaultroute_exists (struct rtentry *rt);
23982c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
24082c907af479178801a7a8701341b22c9d20fdb7Upstream			   char *name, int namelen);
24182c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic void decode_version (char *buf, int *version, int *mod, int *patch);
24282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int set_kdebugflag(int level);
24382c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int ppp_registered(void);
24482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int make_ppp_unit(void);
24582c907af479178801a7a8701341b22c9d20fdb7Upstream
24682c907af479178801a7a8701341b22c9d20fdb7Upstreamextern u_char	inpacket_buf[];	/* borrowed from main.c */
24782c907af479178801a7a8701341b22c9d20fdb7Upstream
24882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
24982c907af479178801a7a8701341b22c9d20fdb7Upstream * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
25082c907af479178801a7a8701341b22c9d20fdb7Upstream * if it exists.
25182c907af479178801a7a8701341b22c9d20fdb7Upstream */
25282c907af479178801a7a8701341b22c9d20fdb7Upstream
25382c907af479178801a7a8701341b22c9d20fdb7Upstream#define SET_SA_FAMILY(addr, family)			\
25482c907af479178801a7a8701341b22c9d20fdb7Upstream    memset ((char *) &(addr), '\0', sizeof(addr));	\
25582c907af479178801a7a8701341b22c9d20fdb7Upstream    addr.sa_family = (family);
25682c907af479178801a7a8701341b22c9d20fdb7Upstream
25782c907af479178801a7a8701341b22c9d20fdb7Upstream/*
25882c907af479178801a7a8701341b22c9d20fdb7Upstream * Determine if the PPP connection should still be present.
25982c907af479178801a7a8701341b22c9d20fdb7Upstream */
26082c907af479178801a7a8701341b22c9d20fdb7Upstream
26182c907af479178801a7a8701341b22c9d20fdb7Upstreamextern int hungup;
26282c907af479178801a7a8701341b22c9d20fdb7Upstream
26382c907af479178801a7a8701341b22c9d20fdb7Upstream/* new_fd is the fd of a tty */
26482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic void set_ppp_fd (int new_fd)
26582c907af479178801a7a8701341b22c9d20fdb7Upstream{
26682c907af479178801a7a8701341b22c9d20fdb7Upstream	ppp_fd = new_fd;
26782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!new_style_driver)
26882c907af479178801a7a8701341b22c9d20fdb7Upstream		ppp_dev_fd = new_fd;
26982c907af479178801a7a8701341b22c9d20fdb7Upstream}
27082c907af479178801a7a8701341b22c9d20fdb7Upstream
27182c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int still_ppp(void)
27282c907af479178801a7a8701341b22c9d20fdb7Upstream{
27382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (new_style_driver)
27482c907af479178801a7a8701341b22c9d20fdb7Upstream		return !hungup && ppp_fd >= 0;
27582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!hungup || ppp_fd == slave_fd)
27682c907af479178801a7a8701341b22c9d20fdb7Upstream		return 1;
27782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (slave_fd >= 0) {
27882c907af479178801a7a8701341b22c9d20fdb7Upstream		set_ppp_fd(slave_fd);
27982c907af479178801a7a8701341b22c9d20fdb7Upstream		return 1;
28082c907af479178801a7a8701341b22c9d20fdb7Upstream	}
28182c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
28282c907af479178801a7a8701341b22c9d20fdb7Upstream}
28382c907af479178801a7a8701341b22c9d20fdb7Upstream
28482c907af479178801a7a8701341b22c9d20fdb7Upstream/*
28582c907af479178801a7a8701341b22c9d20fdb7Upstream * modify_flags - set and clear flag bits controlling the kernel
28682c907af479178801a7a8701341b22c9d20fdb7Upstream * PPP driver.
28782c907af479178801a7a8701341b22c9d20fdb7Upstream */
28882c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int modify_flags(int fd, int clear_bits, int set_bits)
28982c907af479178801a7a8701341b22c9d20fdb7Upstream{
29082c907af479178801a7a8701341b22c9d20fdb7Upstream	int flags;
29182c907af479178801a7a8701341b22c9d20fdb7Upstream
29282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(fd, PPPIOCGFLAGS, &flags) == -1)
29382c907af479178801a7a8701341b22c9d20fdb7Upstream		goto err;
29482c907af479178801a7a8701341b22c9d20fdb7Upstream	flags = (flags & ~clear_bits) | set_bits;
29582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(fd, PPPIOCSFLAGS, &flags) == -1)
29682c907af479178801a7a8701341b22c9d20fdb7Upstream		goto err;
29782c907af479178801a7a8701341b22c9d20fdb7Upstream
29882c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
29982c907af479178801a7a8701341b22c9d20fdb7Upstream
30082c907af479178801a7a8701341b22c9d20fdb7Upstream err:
30182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (errno != EIO)
30282c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Failed to set PPP kernel option flags: %m");
30382c907af479178801a7a8701341b22c9d20fdb7Upstream	return -1;
30482c907af479178801a7a8701341b22c9d20fdb7Upstream}
30582c907af479178801a7a8701341b22c9d20fdb7Upstream
30682c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
30782c907af479178801a7a8701341b22c9d20fdb7Upstream *
30882c907af479178801a7a8701341b22c9d20fdb7Upstream * sys_init - System-dependent initialization.
30982c907af479178801a7a8701341b22c9d20fdb7Upstream */
31082c907af479178801a7a8701341b22c9d20fdb7Upstream
31182c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid sys_init(void)
31282c907af479178801a7a8701341b22c9d20fdb7Upstream{
31382c907af479178801a7a8701341b22c9d20fdb7Upstream    /* Get an internet socket for doing socket ioctls. */
31482c907af479178801a7a8701341b22c9d20fdb7Upstream    sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
31582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sock_fd < 0)
31682c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("Couldn't create IP socket: %m(%d)", errno);
31782c907af479178801a7a8701341b22c9d20fdb7Upstream
31882c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef INET6
31982c907af479178801a7a8701341b22c9d20fdb7Upstream    sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
32082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sock6_fd < 0)
32182c907af479178801a7a8701341b22c9d20fdb7Upstream	sock6_fd = -errno;	/* save errno for later */
32282c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
32382c907af479178801a7a8701341b22c9d20fdb7Upstream
32482c907af479178801a7a8701341b22c9d20fdb7Upstream    FD_ZERO(&in_fds);
32582c907af479178801a7a8701341b22c9d20fdb7Upstream    max_in_fd = 0;
32682c907af479178801a7a8701341b22c9d20fdb7Upstream}
32782c907af479178801a7a8701341b22c9d20fdb7Upstream
32882c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
32982c907af479178801a7a8701341b22c9d20fdb7Upstream *
33082c907af479178801a7a8701341b22c9d20fdb7Upstream * sys_cleanup - restore any system state we modified before exiting:
33182c907af479178801a7a8701341b22c9d20fdb7Upstream * mark the interface down, delete default route and/or proxy arp entry.
33282c907af479178801a7a8701341b22c9d20fdb7Upstream * This shouldn't call die() because it's called from die().
33382c907af479178801a7a8701341b22c9d20fdb7Upstream */
33482c907af479178801a7a8701341b22c9d20fdb7Upstream
33582c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid sys_cleanup(void)
33682c907af479178801a7a8701341b22c9d20fdb7Upstream{
33782c907af479178801a7a8701341b22c9d20fdb7Upstream/*
33882c907af479178801a7a8701341b22c9d20fdb7Upstream * Take down the device
33982c907af479178801a7a8701341b22c9d20fdb7Upstream */
34082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (if_is_up) {
34182c907af479178801a7a8701341b22c9d20fdb7Upstream	if_is_up = 0;
34282c907af479178801a7a8701341b22c9d20fdb7Upstream	sifdown(0);
34382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
34482c907af479178801a7a8701341b22c9d20fdb7Upstream/*
34582c907af479178801a7a8701341b22c9d20fdb7Upstream * Delete any routes through the device.
34682c907af479178801a7a8701341b22c9d20fdb7Upstream */
34782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (default_route_gateway != 0)
34882c907af479178801a7a8701341b22c9d20fdb7Upstream	cifdefaultroute(0, 0, default_route_gateway);
34982c907af479178801a7a8701341b22c9d20fdb7Upstream
35082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (has_proxy_arp)
35182c907af479178801a7a8701341b22c9d20fdb7Upstream	cifproxyarp(0, proxy_arp_addr);
35282c907af479178801a7a8701341b22c9d20fdb7Upstream}
35382c907af479178801a7a8701341b22c9d20fdb7Upstream
35482c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
35582c907af479178801a7a8701341b22c9d20fdb7Upstream *
35682c907af479178801a7a8701341b22c9d20fdb7Upstream * sys_close - Clean up in a child process before execing.
35782c907af479178801a7a8701341b22c9d20fdb7Upstream */
35882c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid
35982c907af479178801a7a8701341b22c9d20fdb7Upstreamsys_close(void)
36082c907af479178801a7a8701341b22c9d20fdb7Upstream{
36182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver && ppp_dev_fd >= 0)
36282c907af479178801a7a8701341b22c9d20fdb7Upstream	close(ppp_dev_fd);
36382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sock_fd >= 0)
36482c907af479178801a7a8701341b22c9d20fdb7Upstream	close(sock_fd);
36582c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef INET6
36682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sock6_fd >= 0)
36782c907af479178801a7a8701341b22c9d20fdb7Upstream	close(sock6_fd);
36882c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
36982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (slave_fd >= 0)
37082c907af479178801a7a8701341b22c9d20fdb7Upstream	close(slave_fd);
37182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (master_fd >= 0)
37282c907af479178801a7a8701341b22c9d20fdb7Upstream	close(master_fd);
37382c907af479178801a7a8701341b22c9d20fdb7Upstream}
37482c907af479178801a7a8701341b22c9d20fdb7Upstream
37582c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
37682c907af479178801a7a8701341b22c9d20fdb7Upstream *
37782c907af479178801a7a8701341b22c9d20fdb7Upstream * set_kdebugflag - Define the debugging level for the kernel
37882c907af479178801a7a8701341b22c9d20fdb7Upstream */
37982c907af479178801a7a8701341b22c9d20fdb7Upstream
38082c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int set_kdebugflag (int requested_level)
38182c907af479178801a7a8701341b22c9d20fdb7Upstream{
38282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ppp_dev_fd < 0)
38382c907af479178801a7a8701341b22c9d20fdb7Upstream	return 1;
38482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
38582c907af479178801a7a8701341b22c9d20fdb7Upstream	if ( ! ok_error (errno) )
38682c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl(PPPIOCSDEBUG): %m (line %d)", __LINE__);
38782c907af479178801a7a8701341b22c9d20fdb7Upstream	return (0);
38882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
38982c907af479178801a7a8701341b22c9d20fdb7Upstream    return (1);
39082c907af479178801a7a8701341b22c9d20fdb7Upstream}
39182c907af479178801a7a8701341b22c9d20fdb7Upstream
39282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
39382c907af479178801a7a8701341b22c9d20fdb7Upstream *
39482c907af479178801a7a8701341b22c9d20fdb7Upstream * tty_establish_ppp - Turn the serial port into a ppp interface.
39582c907af479178801a7a8701341b22c9d20fdb7Upstream */
39682c907af479178801a7a8701341b22c9d20fdb7Upstream
39782c907af479178801a7a8701341b22c9d20fdb7Upstreamint tty_establish_ppp (int tty_fd)
39882c907af479178801a7a8701341b22c9d20fdb7Upstream{
39982c907af479178801a7a8701341b22c9d20fdb7Upstream    int ret_fd;
40082c907af479178801a7a8701341b22c9d20fdb7Upstream
40182c907af479178801a7a8701341b22c9d20fdb7Upstream/*
40282c907af479178801a7a8701341b22c9d20fdb7Upstream * Ensure that the tty device is in exclusive mode.
40382c907af479178801a7a8701341b22c9d20fdb7Upstream */
40482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(tty_fd, TIOCEXCL, 0) < 0) {
40582c907af479178801a7a8701341b22c9d20fdb7Upstream	if ( ! ok_error ( errno ))
40682c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("Couldn't make tty exclusive: %m");
40782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
40882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
40982c907af479178801a7a8701341b22c9d20fdb7Upstream * Demand mode - prime the old ppp device to relinquish the unit.
41082c907af479178801a7a8701341b22c9d20fdb7Upstream */
41182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!new_style_driver && looped
41282c907af479178801a7a8701341b22c9d20fdb7Upstream	&& ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
41382c907af479178801a7a8701341b22c9d20fdb7Upstream	error("ioctl(transfer ppp unit): %m, line %d", __LINE__);
41482c907af479178801a7a8701341b22c9d20fdb7Upstream	return -1;
41582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
41682c907af479178801a7a8701341b22c9d20fdb7Upstream/*
41782c907af479178801a7a8701341b22c9d20fdb7Upstream * Set the current tty to the PPP discpline
41882c907af479178801a7a8701341b22c9d20fdb7Upstream */
41982c907af479178801a7a8701341b22c9d20fdb7Upstream
42082c907af479178801a7a8701341b22c9d20fdb7Upstream#ifndef N_SYNC_PPP
42182c907af479178801a7a8701341b22c9d20fdb7Upstream#define N_SYNC_PPP 14
42282c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
42382c907af479178801a7a8701341b22c9d20fdb7Upstream    ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
42482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
42582c907af479178801a7a8701341b22c9d20fdb7Upstream	if ( ! ok_error (errno) ) {
42682c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("Couldn't set tty to PPP discipline: %m");
42782c907af479178801a7a8701341b22c9d20fdb7Upstream	    return -1;
42882c907af479178801a7a8701341b22c9d20fdb7Upstream	}
42982c907af479178801a7a8701341b22c9d20fdb7Upstream    }
43082c907af479178801a7a8701341b22c9d20fdb7Upstream
43182c907af479178801a7a8701341b22c9d20fdb7Upstream    ret_fd = generic_establish_ppp(tty_fd);
43282c907af479178801a7a8701341b22c9d20fdb7Upstream
43382c907af479178801a7a8701341b22c9d20fdb7Upstream#define SC_RCVB	(SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP)
43482c907af479178801a7a8701341b22c9d20fdb7Upstream#define SC_LOGB	(SC_DEBUG | SC_LOG_INPKT | SC_LOG_OUTPKT | SC_LOG_RAWIN \
43582c907af479178801a7a8701341b22c9d20fdb7Upstream		 | SC_LOG_FLUSH)
43682c907af479178801a7a8701341b22c9d20fdb7Upstream
43782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ret_fd >= 0) {
43882c907af479178801a7a8701341b22c9d20fdb7Upstream	modify_flags(ppp_fd, SC_RCVB | SC_LOGB,
43982c907af479178801a7a8701341b22c9d20fdb7Upstream		     (kdebugflag * SC_DEBUG) & SC_LOGB);
44082c907af479178801a7a8701341b22c9d20fdb7Upstream    } else {
44182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
44282c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("Couldn't reset tty to normal line discipline: %m");
44382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
44482c907af479178801a7a8701341b22c9d20fdb7Upstream
44582c907af479178801a7a8701341b22c9d20fdb7Upstream    return ret_fd;
44682c907af479178801a7a8701341b22c9d20fdb7Upstream}
44782c907af479178801a7a8701341b22c9d20fdb7Upstream
44882c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
44982c907af479178801a7a8701341b22c9d20fdb7Upstream *
45082c907af479178801a7a8701341b22c9d20fdb7Upstream * generic_establish_ppp - Turn the fd into a ppp interface.
45182c907af479178801a7a8701341b22c9d20fdb7Upstream */
45282c907af479178801a7a8701341b22c9d20fdb7Upstreamint generic_establish_ppp (int fd)
45382c907af479178801a7a8701341b22c9d20fdb7Upstream{
45482c907af479178801a7a8701341b22c9d20fdb7Upstream    int x;
45582c907af479178801a7a8701341b22c9d20fdb7Upstream
45682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver) {
45782c907af479178801a7a8701341b22c9d20fdb7Upstream	int flags;
45882c907af479178801a7a8701341b22c9d20fdb7Upstream
45982c907af479178801a7a8701341b22c9d20fdb7Upstream	/* Open an instance of /dev/ppp and connect the channel to it */
46082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
46182c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("Couldn't get channel number: %m");
46282c907af479178801a7a8701341b22c9d20fdb7Upstream	    goto err;
46382c907af479178801a7a8701341b22c9d20fdb7Upstream	}
46482c907af479178801a7a8701341b22c9d20fdb7Upstream	dbglog("using channel %d", chindex);
46582c907af479178801a7a8701341b22c9d20fdb7Upstream	fd = open("/dev/ppp", O_RDWR);
46682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (fd < 0) {
46782c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("Couldn't reopen /dev/ppp: %m");
46882c907af479178801a7a8701341b22c9d20fdb7Upstream	    goto err;
46982c907af479178801a7a8701341b22c9d20fdb7Upstream	}
47082c907af479178801a7a8701341b22c9d20fdb7Upstream	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
47182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
47282c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("Couldn't attach to channel %d: %m", chindex);
47382c907af479178801a7a8701341b22c9d20fdb7Upstream	    goto err_close;
47482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
47582c907af479178801a7a8701341b22c9d20fdb7Upstream	flags = fcntl(fd, F_GETFL);
47682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
47782c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
47882c907af479178801a7a8701341b22c9d20fdb7Upstream	set_ppp_fd(fd);
47982c907af479178801a7a8701341b22c9d20fdb7Upstream
48082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!looped)
48182c907af479178801a7a8701341b22c9d20fdb7Upstream	    ifunit = -1;
48282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!looped && !multilink) {
48382c907af479178801a7a8701341b22c9d20fdb7Upstream	    /*
48482c907af479178801a7a8701341b22c9d20fdb7Upstream	     * Create a new PPP unit.
48582c907af479178801a7a8701341b22c9d20fdb7Upstream	     */
48682c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (make_ppp_unit() < 0)
48782c907af479178801a7a8701341b22c9d20fdb7Upstream		goto err_close;
48882c907af479178801a7a8701341b22c9d20fdb7Upstream	}
48982c907af479178801a7a8701341b22c9d20fdb7Upstream
49082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (looped)
49182c907af479178801a7a8701341b22c9d20fdb7Upstream	    modify_flags(ppp_dev_fd, SC_LOOP_TRAFFIC, 0);
49282c907af479178801a7a8701341b22c9d20fdb7Upstream
49382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!multilink) {
49482c907af479178801a7a8701341b22c9d20fdb7Upstream	    add_fd(ppp_dev_fd);
49582c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
49682c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Couldn't attach to PPP unit %d: %m", ifunit);
49782c907af479178801a7a8701341b22c9d20fdb7Upstream		goto err_close;
49882c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
49982c907af479178801a7a8701341b22c9d20fdb7Upstream	}
50082c907af479178801a7a8701341b22c9d20fdb7Upstream
50182c907af479178801a7a8701341b22c9d20fdb7Upstream    } else {
50282c907af479178801a7a8701341b22c9d20fdb7Upstream	/*
50382c907af479178801a7a8701341b22c9d20fdb7Upstream	 * Old-style driver: find out which interface we were given.
50482c907af479178801a7a8701341b22c9d20fdb7Upstream	 */
50582c907af479178801a7a8701341b22c9d20fdb7Upstream	set_ppp_fd (fd);
50682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
50782c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (ok_error (errno))
50882c907af479178801a7a8701341b22c9d20fdb7Upstream		goto err;
50982c907af479178801a7a8701341b22c9d20fdb7Upstream	    fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
51082c907af479178801a7a8701341b22c9d20fdb7Upstream	}
51182c907af479178801a7a8701341b22c9d20fdb7Upstream	/* Check that we got the same unit again. */
51282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (looped && x != ifunit)
51382c907af479178801a7a8701341b22c9d20fdb7Upstream	    fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
51482c907af479178801a7a8701341b22c9d20fdb7Upstream	ifunit = x;
51582c907af479178801a7a8701341b22c9d20fdb7Upstream
51682c907af479178801a7a8701341b22c9d20fdb7Upstream	/*
51782c907af479178801a7a8701341b22c9d20fdb7Upstream	 * Fetch the initial file flags and reset blocking mode on the file.
51882c907af479178801a7a8701341b22c9d20fdb7Upstream	 */
51982c907af479178801a7a8701341b22c9d20fdb7Upstream	initfdflags = fcntl(fd, F_GETFL);
52082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (initfdflags == -1 ||
52182c907af479178801a7a8701341b22c9d20fdb7Upstream	    fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
52282c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ( ! ok_error (errno))
52382c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Couldn't set device to non-blocking mode: %m");
52482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
52582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
52682c907af479178801a7a8701341b22c9d20fdb7Upstream
52782c907af479178801a7a8701341b22c9d20fdb7Upstream    /*
52882c907af479178801a7a8701341b22c9d20fdb7Upstream     * Enable debug in the driver if requested.
52982c907af479178801a7a8701341b22c9d20fdb7Upstream     */
53082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!looped)
53182c907af479178801a7a8701341b22c9d20fdb7Upstream	set_kdebugflag (kdebugflag);
53282c907af479178801a7a8701341b22c9d20fdb7Upstream
53382c907af479178801a7a8701341b22c9d20fdb7Upstream    looped = 0;
53482c907af479178801a7a8701341b22c9d20fdb7Upstream
53582c907af479178801a7a8701341b22c9d20fdb7Upstream    return ppp_fd;
53682c907af479178801a7a8701341b22c9d20fdb7Upstream
53782c907af479178801a7a8701341b22c9d20fdb7Upstream err_close:
53882c907af479178801a7a8701341b22c9d20fdb7Upstream    close(fd);
53982c907af479178801a7a8701341b22c9d20fdb7Upstream err:
54082c907af479178801a7a8701341b22c9d20fdb7Upstream    return -1;
54182c907af479178801a7a8701341b22c9d20fdb7Upstream}
54282c907af479178801a7a8701341b22c9d20fdb7Upstream
54382c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
54482c907af479178801a7a8701341b22c9d20fdb7Upstream *
54582c907af479178801a7a8701341b22c9d20fdb7Upstream * tty_disestablish_ppp - Restore the serial port to normal operation.
54682c907af479178801a7a8701341b22c9d20fdb7Upstream * This shouldn't call die() because it's called from die().
54782c907af479178801a7a8701341b22c9d20fdb7Upstream */
54882c907af479178801a7a8701341b22c9d20fdb7Upstream
54982c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid tty_disestablish_ppp(int tty_fd)
55082c907af479178801a7a8701341b22c9d20fdb7Upstream{
55182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!hungup) {
55282c907af479178801a7a8701341b22c9d20fdb7Upstream/*
55382c907af479178801a7a8701341b22c9d20fdb7Upstream * Flush the tty output buffer so that the TIOCSETD doesn't hang.
55482c907af479178801a7a8701341b22c9d20fdb7Upstream */
55582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (tcflush(tty_fd, TCIOFLUSH) < 0)
55682c907af479178801a7a8701341b22c9d20fdb7Upstream	{
55782c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("tcflush failed: %m");
55882c907af479178801a7a8701341b22c9d20fdb7Upstream	    goto flushfailed;
55982c907af479178801a7a8701341b22c9d20fdb7Upstream	}
56082c907af479178801a7a8701341b22c9d20fdb7Upstream/*
56182c907af479178801a7a8701341b22c9d20fdb7Upstream * Restore the previous line discipline
56282c907af479178801a7a8701341b22c9d20fdb7Upstream */
56382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0) {
56482c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ( ! ok_error (errno))
56582c907af479178801a7a8701341b22c9d20fdb7Upstream		error("ioctl(TIOCSETD, N_TTY): %m (line %d)", __LINE__);
56682c907af479178801a7a8701341b22c9d20fdb7Upstream	}
56782c907af479178801a7a8701341b22c9d20fdb7Upstream
56882c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(tty_fd, TIOCNXCL, 0) < 0) {
56982c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ( ! ok_error (errno))
57082c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("ioctl(TIOCNXCL): %m (line %d)", __LINE__);
57182c907af479178801a7a8701341b22c9d20fdb7Upstream	}
57282c907af479178801a7a8701341b22c9d20fdb7Upstream
57382c907af479178801a7a8701341b22c9d20fdb7Upstream	/* Reset non-blocking mode on fd. */
57482c907af479178801a7a8701341b22c9d20fdb7Upstream	if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0) {
57582c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ( ! ok_error (errno))
57682c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Couldn't restore device fd flags: %m");
57782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
57882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
57982c907af479178801a7a8701341b22c9d20fdb7Upstreamflushfailed:
58082c907af479178801a7a8701341b22c9d20fdb7Upstream    initfdflags = -1;
58182c907af479178801a7a8701341b22c9d20fdb7Upstream
58282c907af479178801a7a8701341b22c9d20fdb7Upstream    generic_disestablish_ppp(tty_fd);
58382c907af479178801a7a8701341b22c9d20fdb7Upstream}
58482c907af479178801a7a8701341b22c9d20fdb7Upstream
58582c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
58682c907af479178801a7a8701341b22c9d20fdb7Upstream *
58782c907af479178801a7a8701341b22c9d20fdb7Upstream * generic_disestablish_ppp - Restore device components to normal
58882c907af479178801a7a8701341b22c9d20fdb7Upstream * operation, and reconnect the ppp unit to the loopback if in demand
58982c907af479178801a7a8701341b22c9d20fdb7Upstream * mode.  This shouldn't call die() because it's called from die().
59082c907af479178801a7a8701341b22c9d20fdb7Upstream */
59182c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid generic_disestablish_ppp(int dev_fd)
59282c907af479178801a7a8701341b22c9d20fdb7Upstream{
59382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver) {
59482c907af479178801a7a8701341b22c9d20fdb7Upstream	close(ppp_fd);
59582c907af479178801a7a8701341b22c9d20fdb7Upstream	ppp_fd = -1;
59682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (demand) {
59782c907af479178801a7a8701341b22c9d20fdb7Upstream	    modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
59882c907af479178801a7a8701341b22c9d20fdb7Upstream	    looped = 1;
59982c907af479178801a7a8701341b22c9d20fdb7Upstream	} else if (!doing_multilink && ppp_dev_fd >= 0) {
60082c907af479178801a7a8701341b22c9d20fdb7Upstream	    close(ppp_dev_fd);
60182c907af479178801a7a8701341b22c9d20fdb7Upstream	    remove_fd(ppp_dev_fd);
60282c907af479178801a7a8701341b22c9d20fdb7Upstream	    ppp_dev_fd = -1;
60382c907af479178801a7a8701341b22c9d20fdb7Upstream	}
60482c907af479178801a7a8701341b22c9d20fdb7Upstream    } else {
60582c907af479178801a7a8701341b22c9d20fdb7Upstream	/* old-style driver */
60682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (demand)
60782c907af479178801a7a8701341b22c9d20fdb7Upstream	    set_ppp_fd(slave_fd);
60882c907af479178801a7a8701341b22c9d20fdb7Upstream	else
60982c907af479178801a7a8701341b22c9d20fdb7Upstream	    ppp_dev_fd = -1;
61082c907af479178801a7a8701341b22c9d20fdb7Upstream    }
61182c907af479178801a7a8701341b22c9d20fdb7Upstream}
61282c907af479178801a7a8701341b22c9d20fdb7Upstream
61382c907af479178801a7a8701341b22c9d20fdb7Upstream/*
61482c907af479178801a7a8701341b22c9d20fdb7Upstream * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
61582c907af479178801a7a8701341b22c9d20fdb7Upstream * Assumes new_style_driver.
61682c907af479178801a7a8701341b22c9d20fdb7Upstream */
61782c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int make_ppp_unit()
61882c907af479178801a7a8701341b22c9d20fdb7Upstream{
61982c907af479178801a7a8701341b22c9d20fdb7Upstream	int x, flags;
62082c907af479178801a7a8701341b22c9d20fdb7Upstream
62182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ppp_dev_fd >= 0) {
62282c907af479178801a7a8701341b22c9d20fdb7Upstream		dbglog("in make_ppp_unit, already had /dev/ppp open?");
62382c907af479178801a7a8701341b22c9d20fdb7Upstream		close(ppp_dev_fd);
62482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
62582c907af479178801a7a8701341b22c9d20fdb7Upstream	ppp_dev_fd = open("/dev/ppp", O_RDWR);
62682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ppp_dev_fd < 0)
62782c907af479178801a7a8701341b22c9d20fdb7Upstream		fatal("Couldn't open /dev/ppp: %m");
62882c907af479178801a7a8701341b22c9d20fdb7Upstream	flags = fcntl(ppp_dev_fd, F_GETFL);
62982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (flags == -1
63082c907af479178801a7a8701341b22c9d20fdb7Upstream	    || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
63182c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Couldn't set /dev/ppp to nonblock: %m");
63282c907af479178801a7a8701341b22c9d20fdb7Upstream
63382c907af479178801a7a8701341b22c9d20fdb7Upstream	ifunit = req_unit;
63482c907af479178801a7a8701341b22c9d20fdb7Upstream	x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
63582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (x < 0 && req_unit >= 0 && errno == EEXIST) {
63682c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Couldn't allocate PPP unit %d as it is already in use", req_unit);
63782c907af479178801a7a8701341b22c9d20fdb7Upstream		ifunit = -1;
63882c907af479178801a7a8701341b22c9d20fdb7Upstream		x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
63982c907af479178801a7a8701341b22c9d20fdb7Upstream	}
64082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (x < 0)
64182c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Couldn't create new ppp unit: %m");
64282c907af479178801a7a8701341b22c9d20fdb7Upstream	return x;
64382c907af479178801a7a8701341b22c9d20fdb7Upstream}
64482c907af479178801a7a8701341b22c9d20fdb7Upstream
64582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
64682c907af479178801a7a8701341b22c9d20fdb7Upstream * cfg_bundle - configure the existing bundle.
64782c907af479178801a7a8701341b22c9d20fdb7Upstream * Used in demand mode.
64882c907af479178801a7a8701341b22c9d20fdb7Upstream */
64982c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid cfg_bundle(int mrru, int mtru, int rssn, int tssn)
65082c907af479178801a7a8701341b22c9d20fdb7Upstream{
65182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!new_style_driver)
65282c907af479178801a7a8701341b22c9d20fdb7Upstream		return;
65382c907af479178801a7a8701341b22c9d20fdb7Upstream
65482c907af479178801a7a8701341b22c9d20fdb7Upstream	/* set the mrru, mtu and flags */
65582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
65682c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Couldn't set MRRU: %m");
65782c907af479178801a7a8701341b22c9d20fdb7Upstream
65882c907af479178801a7a8701341b22c9d20fdb7Upstream	modify_flags(ppp_dev_fd, SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ|SC_MULTILINK,
65982c907af479178801a7a8701341b22c9d20fdb7Upstream		     ((rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
66082c907af479178801a7a8701341b22c9d20fdb7Upstream		      | (mrru? SC_MULTILINK: 0)));
66182c907af479178801a7a8701341b22c9d20fdb7Upstream
66282c907af479178801a7a8701341b22c9d20fdb7Upstream	/* connect up the channel */
66382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
66482c907af479178801a7a8701341b22c9d20fdb7Upstream		fatal("Couldn't attach to PPP unit %d: %m", ifunit);
66582c907af479178801a7a8701341b22c9d20fdb7Upstream	add_fd(ppp_dev_fd);
66682c907af479178801a7a8701341b22c9d20fdb7Upstream}
66782c907af479178801a7a8701341b22c9d20fdb7Upstream
66882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
66982c907af479178801a7a8701341b22c9d20fdb7Upstream * make_new_bundle - create a new PPP unit (i.e. a bundle)
67082c907af479178801a7a8701341b22c9d20fdb7Upstream * and connect our channel to it.  This should only get called
67182c907af479178801a7a8701341b22c9d20fdb7Upstream * if `multilink' was set at the time establish_ppp was called.
67282c907af479178801a7a8701341b22c9d20fdb7Upstream * In demand mode this uses our existing bundle instead of making
67382c907af479178801a7a8701341b22c9d20fdb7Upstream * a new one.
67482c907af479178801a7a8701341b22c9d20fdb7Upstream */
67582c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid make_new_bundle(int mrru, int mtru, int rssn, int tssn)
67682c907af479178801a7a8701341b22c9d20fdb7Upstream{
67782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!new_style_driver)
67882c907af479178801a7a8701341b22c9d20fdb7Upstream		return;
67982c907af479178801a7a8701341b22c9d20fdb7Upstream
68082c907af479178801a7a8701341b22c9d20fdb7Upstream	/* make us a ppp unit */
68182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (make_ppp_unit() < 0)
68282c907af479178801a7a8701341b22c9d20fdb7Upstream		die(1);
68382c907af479178801a7a8701341b22c9d20fdb7Upstream
68482c907af479178801a7a8701341b22c9d20fdb7Upstream	/* set the mrru and flags */
68582c907af479178801a7a8701341b22c9d20fdb7Upstream	cfg_bundle(mrru, mtru, rssn, tssn);
68682c907af479178801a7a8701341b22c9d20fdb7Upstream}
68782c907af479178801a7a8701341b22c9d20fdb7Upstream
68882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
68982c907af479178801a7a8701341b22c9d20fdb7Upstream * bundle_attach - attach our link to a given PPP unit.
69082c907af479178801a7a8701341b22c9d20fdb7Upstream * We assume the unit is controlled by another pppd.
69182c907af479178801a7a8701341b22c9d20fdb7Upstream */
69282c907af479178801a7a8701341b22c9d20fdb7Upstreamint bundle_attach(int ifnum)
69382c907af479178801a7a8701341b22c9d20fdb7Upstream{
69482c907af479178801a7a8701341b22c9d20fdb7Upstream	int master_fd;
69582c907af479178801a7a8701341b22c9d20fdb7Upstream
69682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!new_style_driver)
69782c907af479178801a7a8701341b22c9d20fdb7Upstream		return -1;
69882c907af479178801a7a8701341b22c9d20fdb7Upstream
69982c907af479178801a7a8701341b22c9d20fdb7Upstream	master_fd = open("/dev/ppp", O_RDWR);
70082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (master_fd < 0)
70182c907af479178801a7a8701341b22c9d20fdb7Upstream		fatal("Couldn't open /dev/ppp: %m");
70282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) {
70382c907af479178801a7a8701341b22c9d20fdb7Upstream		if (errno == ENXIO) {
70482c907af479178801a7a8701341b22c9d20fdb7Upstream			close(master_fd);
70582c907af479178801a7a8701341b22c9d20fdb7Upstream			return 0;	/* doesn't still exist */
70682c907af479178801a7a8701341b22c9d20fdb7Upstream		}
70782c907af479178801a7a8701341b22c9d20fdb7Upstream		fatal("Couldn't attach to interface unit %d: %m\n", ifnum);
70882c907af479178801a7a8701341b22c9d20fdb7Upstream	}
70982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
71082c907af479178801a7a8701341b22c9d20fdb7Upstream		fatal("Couldn't connect to interface unit %d: %m", ifnum);
71182c907af479178801a7a8701341b22c9d20fdb7Upstream	modify_flags(master_fd, 0, SC_MULTILINK);
71282c907af479178801a7a8701341b22c9d20fdb7Upstream	close(master_fd);
71382c907af479178801a7a8701341b22c9d20fdb7Upstream
71482c907af479178801a7a8701341b22c9d20fdb7Upstream	ifunit = ifnum;
71582c907af479178801a7a8701341b22c9d20fdb7Upstream	return 1;
71682c907af479178801a7a8701341b22c9d20fdb7Upstream}
71782c907af479178801a7a8701341b22c9d20fdb7Upstream
71882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
71982c907af479178801a7a8701341b22c9d20fdb7Upstream * destroy_bundle - tell the driver to destroy our bundle.
72082c907af479178801a7a8701341b22c9d20fdb7Upstream */
72182c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid destroy_bundle(void)
72282c907af479178801a7a8701341b22c9d20fdb7Upstream{
72382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ppp_dev_fd >= 0) {
72482c907af479178801a7a8701341b22c9d20fdb7Upstream		close(ppp_dev_fd);
72582c907af479178801a7a8701341b22c9d20fdb7Upstream		remove_fd(ppp_dev_fd);
72682c907af479178801a7a8701341b22c9d20fdb7Upstream		ppp_dev_fd = -1;
72782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
72882c907af479178801a7a8701341b22c9d20fdb7Upstream}
72982c907af479178801a7a8701341b22c9d20fdb7Upstream
73082c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
73182c907af479178801a7a8701341b22c9d20fdb7Upstream *
73282c907af479178801a7a8701341b22c9d20fdb7Upstream * clean_check - Fetch the flags for the device and generate
73382c907af479178801a7a8701341b22c9d20fdb7Upstream * appropriate error messages.
73482c907af479178801a7a8701341b22c9d20fdb7Upstream */
73582c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid clean_check(void)
73682c907af479178801a7a8701341b22c9d20fdb7Upstream{
73782c907af479178801a7a8701341b22c9d20fdb7Upstream    int x;
73882c907af479178801a7a8701341b22c9d20fdb7Upstream    char *s;
73982c907af479178801a7a8701341b22c9d20fdb7Upstream
74082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (still_ppp()) {
74182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
74282c907af479178801a7a8701341b22c9d20fdb7Upstream	    s = NULL;
74382c907af479178801a7a8701341b22c9d20fdb7Upstream	    switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
74482c907af479178801a7a8701341b22c9d20fdb7Upstream	    case SC_RCV_B7_0:
74582c907af479178801a7a8701341b22c9d20fdb7Upstream		s = "all had bit 7 set to 1";
74682c907af479178801a7a8701341b22c9d20fdb7Upstream		break;
74782c907af479178801a7a8701341b22c9d20fdb7Upstream
74882c907af479178801a7a8701341b22c9d20fdb7Upstream	    case SC_RCV_B7_1:
74982c907af479178801a7a8701341b22c9d20fdb7Upstream		s = "all had bit 7 set to 0";
75082c907af479178801a7a8701341b22c9d20fdb7Upstream		break;
75182c907af479178801a7a8701341b22c9d20fdb7Upstream
75282c907af479178801a7a8701341b22c9d20fdb7Upstream	    case SC_RCV_EVNP:
75382c907af479178801a7a8701341b22c9d20fdb7Upstream		s = "all had odd parity";
75482c907af479178801a7a8701341b22c9d20fdb7Upstream		break;
75582c907af479178801a7a8701341b22c9d20fdb7Upstream
75682c907af479178801a7a8701341b22c9d20fdb7Upstream	    case SC_RCV_ODDP:
75782c907af479178801a7a8701341b22c9d20fdb7Upstream		s = "all had even parity";
75882c907af479178801a7a8701341b22c9d20fdb7Upstream		break;
75982c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
76082c907af479178801a7a8701341b22c9d20fdb7Upstream
76182c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (s != NULL) {
76282c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Receive serial link is not 8-bit clean:");
76382c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Problem: %s", s);
76482c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
76582c907af479178801a7a8701341b22c9d20fdb7Upstream	}
76682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
76782c907af479178801a7a8701341b22c9d20fdb7Upstream}
76882c907af479178801a7a8701341b22c9d20fdb7Upstream
76982c907af479178801a7a8701341b22c9d20fdb7Upstream
77082c907af479178801a7a8701341b22c9d20fdb7Upstream/*
77182c907af479178801a7a8701341b22c9d20fdb7Upstream * List of valid speeds.
77282c907af479178801a7a8701341b22c9d20fdb7Upstream */
77382c907af479178801a7a8701341b22c9d20fdb7Upstream
77482c907af479178801a7a8701341b22c9d20fdb7Upstreamstruct speed {
77582c907af479178801a7a8701341b22c9d20fdb7Upstream    int speed_int, speed_val;
77682c907af479178801a7a8701341b22c9d20fdb7Upstream} speeds[] = {
77782c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B50
77882c907af479178801a7a8701341b22c9d20fdb7Upstream    { 50, B50 },
77982c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
78082c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B75
78182c907af479178801a7a8701341b22c9d20fdb7Upstream    { 75, B75 },
78282c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
78382c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B110
78482c907af479178801a7a8701341b22c9d20fdb7Upstream    { 110, B110 },
78582c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
78682c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B134
78782c907af479178801a7a8701341b22c9d20fdb7Upstream    { 134, B134 },
78882c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
78982c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B150
79082c907af479178801a7a8701341b22c9d20fdb7Upstream    { 150, B150 },
79182c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
79282c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B200
79382c907af479178801a7a8701341b22c9d20fdb7Upstream    { 200, B200 },
79482c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
79582c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B300
79682c907af479178801a7a8701341b22c9d20fdb7Upstream    { 300, B300 },
79782c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
79882c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B600
79982c907af479178801a7a8701341b22c9d20fdb7Upstream    { 600, B600 },
80082c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
80182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B1200
80282c907af479178801a7a8701341b22c9d20fdb7Upstream    { 1200, B1200 },
80382c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
80482c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B1800
80582c907af479178801a7a8701341b22c9d20fdb7Upstream    { 1800, B1800 },
80682c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
80782c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B2000
80882c907af479178801a7a8701341b22c9d20fdb7Upstream    { 2000, B2000 },
80982c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
81082c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B2400
81182c907af479178801a7a8701341b22c9d20fdb7Upstream    { 2400, B2400 },
81282c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
81382c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B3600
81482c907af479178801a7a8701341b22c9d20fdb7Upstream    { 3600, B3600 },
81582c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
81682c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B4800
81782c907af479178801a7a8701341b22c9d20fdb7Upstream    { 4800, B4800 },
81882c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
81982c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B7200
82082c907af479178801a7a8701341b22c9d20fdb7Upstream    { 7200, B7200 },
82182c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
82282c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B9600
82382c907af479178801a7a8701341b22c9d20fdb7Upstream    { 9600, B9600 },
82482c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
82582c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B19200
82682c907af479178801a7a8701341b22c9d20fdb7Upstream    { 19200, B19200 },
82782c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
82882c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B38400
82982c907af479178801a7a8701341b22c9d20fdb7Upstream    { 38400, B38400 },
83082c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
83182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B57600
83282c907af479178801a7a8701341b22c9d20fdb7Upstream    { 57600, B57600 },
83382c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
83482c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B76800
83582c907af479178801a7a8701341b22c9d20fdb7Upstream    { 76800, B76800 },
83682c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
83782c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B115200
83882c907af479178801a7a8701341b22c9d20fdb7Upstream    { 115200, B115200 },
83982c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
84082c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef EXTA
84182c907af479178801a7a8701341b22c9d20fdb7Upstream    { 19200, EXTA },
84282c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
84382c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef EXTB
84482c907af479178801a7a8701341b22c9d20fdb7Upstream    { 38400, EXTB },
84582c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
84682c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B230400
84782c907af479178801a7a8701341b22c9d20fdb7Upstream    { 230400, B230400 },
84882c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
84982c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B460800
85082c907af479178801a7a8701341b22c9d20fdb7Upstream    { 460800, B460800 },
85182c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
85282c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef B921600
85382c907af479178801a7a8701341b22c9d20fdb7Upstream    { 921600, B921600 },
85482c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
85582c907af479178801a7a8701341b22c9d20fdb7Upstream    { 0, 0 }
85682c907af479178801a7a8701341b22c9d20fdb7Upstream};
85782c907af479178801a7a8701341b22c9d20fdb7Upstream
85882c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
85982c907af479178801a7a8701341b22c9d20fdb7Upstream *
86082c907af479178801a7a8701341b22c9d20fdb7Upstream * Translate from bits/second to a speed_t.
86182c907af479178801a7a8701341b22c9d20fdb7Upstream */
86282c907af479178801a7a8701341b22c9d20fdb7Upstream
86382c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int translate_speed (int bps)
86482c907af479178801a7a8701341b22c9d20fdb7Upstream{
86582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct speed *speedp;
86682c907af479178801a7a8701341b22c9d20fdb7Upstream
86782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (bps != 0) {
86882c907af479178801a7a8701341b22c9d20fdb7Upstream	for (speedp = speeds; speedp->speed_int; speedp++) {
86982c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (bps == speedp->speed_int)
87082c907af479178801a7a8701341b22c9d20fdb7Upstream		return speedp->speed_val;
87182c907af479178801a7a8701341b22c9d20fdb7Upstream	}
87282c907af479178801a7a8701341b22c9d20fdb7Upstream	warn("speed %d not supported", bps);
87382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
87482c907af479178801a7a8701341b22c9d20fdb7Upstream    return 0;
87582c907af479178801a7a8701341b22c9d20fdb7Upstream}
87682c907af479178801a7a8701341b22c9d20fdb7Upstream
87782c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
87882c907af479178801a7a8701341b22c9d20fdb7Upstream *
87982c907af479178801a7a8701341b22c9d20fdb7Upstream * Translate from a speed_t to bits/second.
88082c907af479178801a7a8701341b22c9d20fdb7Upstream */
88182c907af479178801a7a8701341b22c9d20fdb7Upstream
88282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int baud_rate_of (int speed)
88382c907af479178801a7a8701341b22c9d20fdb7Upstream{
88482c907af479178801a7a8701341b22c9d20fdb7Upstream    struct speed *speedp;
88582c907af479178801a7a8701341b22c9d20fdb7Upstream
88682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (speed != 0) {
88782c907af479178801a7a8701341b22c9d20fdb7Upstream	for (speedp = speeds; speedp->speed_int; speedp++) {
88882c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (speed == speedp->speed_val)
88982c907af479178801a7a8701341b22c9d20fdb7Upstream		return speedp->speed_int;
89082c907af479178801a7a8701341b22c9d20fdb7Upstream	}
89182c907af479178801a7a8701341b22c9d20fdb7Upstream    }
89282c907af479178801a7a8701341b22c9d20fdb7Upstream    return 0;
89382c907af479178801a7a8701341b22c9d20fdb7Upstream}
89482c907af479178801a7a8701341b22c9d20fdb7Upstream
89582c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
89682c907af479178801a7a8701341b22c9d20fdb7Upstream *
89782c907af479178801a7a8701341b22c9d20fdb7Upstream * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
89882c907af479178801a7a8701341b22c9d20fdb7Upstream * at the requested speed, etc.  If `local' is true, set CLOCAL
89982c907af479178801a7a8701341b22c9d20fdb7Upstream * regardless of whether the modem option was specified.
90082c907af479178801a7a8701341b22c9d20fdb7Upstream */
90182c907af479178801a7a8701341b22c9d20fdb7Upstream
90282c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid set_up_tty(int tty_fd, int local)
90382c907af479178801a7a8701341b22c9d20fdb7Upstream{
90482c907af479178801a7a8701341b22c9d20fdb7Upstream    int speed;
90582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct termios tios;
90682c907af479178801a7a8701341b22c9d20fdb7Upstream
90782c907af479178801a7a8701341b22c9d20fdb7Upstream    setdtr(tty_fd, 1);
90882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (tcgetattr(tty_fd, &tios) < 0) {
90982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!ok_error(errno))
91082c907af479178801a7a8701341b22c9d20fdb7Upstream	    fatal("tcgetattr: %m (line %d)", __LINE__);
91182c907af479178801a7a8701341b22c9d20fdb7Upstream	return;
91282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
91382c907af479178801a7a8701341b22c9d20fdb7Upstream
91482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!restore_term)
91582c907af479178801a7a8701341b22c9d20fdb7Upstream	inittermios = tios;
91682c907af479178801a7a8701341b22c9d20fdb7Upstream
91782c907af479178801a7a8701341b22c9d20fdb7Upstream    tios.c_cflag     &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
91882c907af479178801a7a8701341b22c9d20fdb7Upstream    tios.c_cflag     |= CS8 | CREAD | HUPCL;
91982c907af479178801a7a8701341b22c9d20fdb7Upstream
92082c907af479178801a7a8701341b22c9d20fdb7Upstream    tios.c_iflag      = IGNBRK | IGNPAR;
92182c907af479178801a7a8701341b22c9d20fdb7Upstream    tios.c_oflag      = 0;
92282c907af479178801a7a8701341b22c9d20fdb7Upstream    tios.c_lflag      = 0;
92382c907af479178801a7a8701341b22c9d20fdb7Upstream    tios.c_cc[VMIN]   = 1;
92482c907af479178801a7a8701341b22c9d20fdb7Upstream    tios.c_cc[VTIME]  = 0;
92582c907af479178801a7a8701341b22c9d20fdb7Upstream
92682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (local || !modem)
92782c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_cflag ^= (CLOCAL | HUPCL);
92882c907af479178801a7a8701341b22c9d20fdb7Upstream
92982c907af479178801a7a8701341b22c9d20fdb7Upstream    switch (crtscts) {
93082c907af479178801a7a8701341b22c9d20fdb7Upstream    case 1:
93182c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_cflag |= CRTSCTS;
93282c907af479178801a7a8701341b22c9d20fdb7Upstream	break;
93382c907af479178801a7a8701341b22c9d20fdb7Upstream
93482c907af479178801a7a8701341b22c9d20fdb7Upstream    case -2:
93582c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_iflag     |= IXON | IXOFF;
93682c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_cc[VSTOP]  = 0x13;	/* DC3 = XOFF = ^S */
93782c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
93882c907af479178801a7a8701341b22c9d20fdb7Upstream	break;
93982c907af479178801a7a8701341b22c9d20fdb7Upstream
94082c907af479178801a7a8701341b22c9d20fdb7Upstream    case -1:
94182c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_cflag &= ~CRTSCTS;
94282c907af479178801a7a8701341b22c9d20fdb7Upstream	break;
94382c907af479178801a7a8701341b22c9d20fdb7Upstream
94482c907af479178801a7a8701341b22c9d20fdb7Upstream    default:
94582c907af479178801a7a8701341b22c9d20fdb7Upstream	break;
94682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
94782c907af479178801a7a8701341b22c9d20fdb7Upstream
94882c907af479178801a7a8701341b22c9d20fdb7Upstream    speed = translate_speed(inspeed);
94982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (speed) {
95082c907af479178801a7a8701341b22c9d20fdb7Upstream	cfsetospeed (&tios, speed);
95182c907af479178801a7a8701341b22c9d20fdb7Upstream	cfsetispeed (&tios, speed);
95282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
95382c907af479178801a7a8701341b22c9d20fdb7Upstream/*
95482c907af479178801a7a8701341b22c9d20fdb7Upstream * We can't proceed if the serial port speed is B0,
95582c907af479178801a7a8701341b22c9d20fdb7Upstream * since that implies that the serial port is disabled.
95682c907af479178801a7a8701341b22c9d20fdb7Upstream */
95782c907af479178801a7a8701341b22c9d20fdb7Upstream    else {
95882c907af479178801a7a8701341b22c9d20fdb7Upstream	speed = cfgetospeed(&tios);
95982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (speed == B0)
96082c907af479178801a7a8701341b22c9d20fdb7Upstream	    fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
96182c907af479178801a7a8701341b22c9d20fdb7Upstream    }
96282c907af479178801a7a8701341b22c9d20fdb7Upstream
96382c907af479178801a7a8701341b22c9d20fdb7Upstream    while (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0 && !ok_error(errno))
96482c907af479178801a7a8701341b22c9d20fdb7Upstream	if (errno != EINTR)
96582c907af479178801a7a8701341b22c9d20fdb7Upstream	    fatal("tcsetattr: %m (line %d)", __LINE__);
96682c907af479178801a7a8701341b22c9d20fdb7Upstream
96782c907af479178801a7a8701341b22c9d20fdb7Upstream    baud_rate    = baud_rate_of(speed);
96882c907af479178801a7a8701341b22c9d20fdb7Upstream    restore_term = 1;
96982c907af479178801a7a8701341b22c9d20fdb7Upstream}
97082c907af479178801a7a8701341b22c9d20fdb7Upstream
97182c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
97282c907af479178801a7a8701341b22c9d20fdb7Upstream *
97382c907af479178801a7a8701341b22c9d20fdb7Upstream * setdtr - control the DTR line on the serial port.
97482c907af479178801a7a8701341b22c9d20fdb7Upstream * This is called from die(), so it shouldn't call die().
97582c907af479178801a7a8701341b22c9d20fdb7Upstream */
97682c907af479178801a7a8701341b22c9d20fdb7Upstream
97782c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid setdtr (int tty_fd, int on)
97882c907af479178801a7a8701341b22c9d20fdb7Upstream{
97982c907af479178801a7a8701341b22c9d20fdb7Upstream    int modembits = TIOCM_DTR;
98082c907af479178801a7a8701341b22c9d20fdb7Upstream
98182c907af479178801a7a8701341b22c9d20fdb7Upstream    ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
98282c907af479178801a7a8701341b22c9d20fdb7Upstream}
98382c907af479178801a7a8701341b22c9d20fdb7Upstream
98482c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
98582c907af479178801a7a8701341b22c9d20fdb7Upstream *
98682c907af479178801a7a8701341b22c9d20fdb7Upstream * restore_tty - restore the terminal to the saved settings.
98782c907af479178801a7a8701341b22c9d20fdb7Upstream */
98882c907af479178801a7a8701341b22c9d20fdb7Upstream
98982c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid restore_tty (int tty_fd)
99082c907af479178801a7a8701341b22c9d20fdb7Upstream{
99182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (restore_term) {
99282c907af479178801a7a8701341b22c9d20fdb7Upstream	restore_term = 0;
99382c907af479178801a7a8701341b22c9d20fdb7Upstream/*
99482c907af479178801a7a8701341b22c9d20fdb7Upstream * Turn off echoing, because otherwise we can get into
99582c907af479178801a7a8701341b22c9d20fdb7Upstream * a loop with the tty and the modem echoing to each other.
99682c907af479178801a7a8701341b22c9d20fdb7Upstream * We presume we are the sole user of this tty device, so
99782c907af479178801a7a8701341b22c9d20fdb7Upstream * when we close it, it will revert to its defaults anyway.
99882c907af479178801a7a8701341b22c9d20fdb7Upstream */
99982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!default_device)
100082c907af479178801a7a8701341b22c9d20fdb7Upstream	    inittermios.c_lflag &= ~(ECHO | ECHONL);
100182c907af479178801a7a8701341b22c9d20fdb7Upstream
100282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0) {
100382c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (! ok_error (errno))
100482c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("tcsetattr: %m (line %d)", __LINE__);
100582c907af479178801a7a8701341b22c9d20fdb7Upstream	}
100682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
100782c907af479178801a7a8701341b22c9d20fdb7Upstream}
100882c907af479178801a7a8701341b22c9d20fdb7Upstream
100982c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
101082c907af479178801a7a8701341b22c9d20fdb7Upstream *
101182c907af479178801a7a8701341b22c9d20fdb7Upstream * output - Output PPP packet.
101282c907af479178801a7a8701341b22c9d20fdb7Upstream */
101382c907af479178801a7a8701341b22c9d20fdb7Upstream
101482c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid output (int unit, unsigned char *p, int len)
101582c907af479178801a7a8701341b22c9d20fdb7Upstream{
101682c907af479178801a7a8701341b22c9d20fdb7Upstream    int fd = ppp_fd;
101782c907af479178801a7a8701341b22c9d20fdb7Upstream    int proto;
101882c907af479178801a7a8701341b22c9d20fdb7Upstream
101982c907af479178801a7a8701341b22c9d20fdb7Upstream    dump_packet("sent", p, len);
102082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (snoop_send_hook) snoop_send_hook(p, len);
102182c907af479178801a7a8701341b22c9d20fdb7Upstream
102282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (len < PPP_HDRLEN)
102382c907af479178801a7a8701341b22c9d20fdb7Upstream	return;
102482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver) {
102582c907af479178801a7a8701341b22c9d20fdb7Upstream	p += 2;
102682c907af479178801a7a8701341b22c9d20fdb7Upstream	len -= 2;
102782c907af479178801a7a8701341b22c9d20fdb7Upstream	proto = (p[0] << 8) + p[1];
102882c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ppp_dev_fd >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
102982c907af479178801a7a8701341b22c9d20fdb7Upstream	    fd = ppp_dev_fd;
103082c907af479178801a7a8701341b22c9d20fdb7Upstream    }
103182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (write(fd, p, len) < 0) {
103282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOBUFS
103382c907af479178801a7a8701341b22c9d20fdb7Upstream	    || errno == ENXIO || errno == EIO || errno == EINTR)
103482c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("write: warning: %m (%d)", errno);
103582c907af479178801a7a8701341b22c9d20fdb7Upstream	else
103682c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("write: %m (%d)", errno);
103782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
103882c907af479178801a7a8701341b22c9d20fdb7Upstream}
103982c907af479178801a7a8701341b22c9d20fdb7Upstream
104082c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
104182c907af479178801a7a8701341b22c9d20fdb7Upstream *
104282c907af479178801a7a8701341b22c9d20fdb7Upstream * wait_input - wait until there is data available,
104382c907af479178801a7a8701341b22c9d20fdb7Upstream * for the length of time specified by *timo (indefinite
104482c907af479178801a7a8701341b22c9d20fdb7Upstream * if timo is NULL).
104582c907af479178801a7a8701341b22c9d20fdb7Upstream */
104682c907af479178801a7a8701341b22c9d20fdb7Upstream
104782c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid wait_input(struct timeval *timo)
104882c907af479178801a7a8701341b22c9d20fdb7Upstream{
104982c907af479178801a7a8701341b22c9d20fdb7Upstream    fd_set ready, exc;
105082c907af479178801a7a8701341b22c9d20fdb7Upstream    int n;
105182c907af479178801a7a8701341b22c9d20fdb7Upstream
105282c907af479178801a7a8701341b22c9d20fdb7Upstream    ready = in_fds;
105382c907af479178801a7a8701341b22c9d20fdb7Upstream    exc = in_fds;
105482c907af479178801a7a8701341b22c9d20fdb7Upstream    n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
105582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (n < 0 && errno != EINTR)
105682c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("select: %m");
105782c907af479178801a7a8701341b22c9d20fdb7Upstream}
105882c907af479178801a7a8701341b22c9d20fdb7Upstream
105982c907af479178801a7a8701341b22c9d20fdb7Upstream/*
106082c907af479178801a7a8701341b22c9d20fdb7Upstream * add_fd - add an fd to the set that wait_input waits for.
106182c907af479178801a7a8701341b22c9d20fdb7Upstream */
106282c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid add_fd(int fd)
106382c907af479178801a7a8701341b22c9d20fdb7Upstream{
106482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (fd >= FD_SETSIZE)
106582c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("internal error: file descriptor too large (%d)", fd);
106682c907af479178801a7a8701341b22c9d20fdb7Upstream    FD_SET(fd, &in_fds);
106782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (fd > max_in_fd)
106882c907af479178801a7a8701341b22c9d20fdb7Upstream	max_in_fd = fd;
106982c907af479178801a7a8701341b22c9d20fdb7Upstream}
107082c907af479178801a7a8701341b22c9d20fdb7Upstream
107182c907af479178801a7a8701341b22c9d20fdb7Upstream/*
107282c907af479178801a7a8701341b22c9d20fdb7Upstream * remove_fd - remove an fd from the set that wait_input waits for.
107382c907af479178801a7a8701341b22c9d20fdb7Upstream */
107482c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid remove_fd(int fd)
107582c907af479178801a7a8701341b22c9d20fdb7Upstream{
107682c907af479178801a7a8701341b22c9d20fdb7Upstream    FD_CLR(fd, &in_fds);
107782c907af479178801a7a8701341b22c9d20fdb7Upstream}
107882c907af479178801a7a8701341b22c9d20fdb7Upstream
107982c907af479178801a7a8701341b22c9d20fdb7Upstream
108082c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
108182c907af479178801a7a8701341b22c9d20fdb7Upstream *
108282c907af479178801a7a8701341b22c9d20fdb7Upstream * read_packet - get a PPP packet from the serial device.
108382c907af479178801a7a8701341b22c9d20fdb7Upstream */
108482c907af479178801a7a8701341b22c9d20fdb7Upstream
108582c907af479178801a7a8701341b22c9d20fdb7Upstreamint read_packet (unsigned char *buf)
108682c907af479178801a7a8701341b22c9d20fdb7Upstream{
108782c907af479178801a7a8701341b22c9d20fdb7Upstream    int len, nr;
108882c907af479178801a7a8701341b22c9d20fdb7Upstream
108982c907af479178801a7a8701341b22c9d20fdb7Upstream    len = PPP_MRU + PPP_HDRLEN;
109082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver) {
109182c907af479178801a7a8701341b22c9d20fdb7Upstream	*buf++ = PPP_ALLSTATIONS;
109282c907af479178801a7a8701341b22c9d20fdb7Upstream	*buf++ = PPP_UI;
109382c907af479178801a7a8701341b22c9d20fdb7Upstream	len -= 2;
109482c907af479178801a7a8701341b22c9d20fdb7Upstream    }
109582c907af479178801a7a8701341b22c9d20fdb7Upstream    nr = -1;
1096dab68864983c4a0c6ef9e6d7e5834472c4c75f9cThe Android Open Source Project
109782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ppp_fd >= 0) {
109882c907af479178801a7a8701341b22c9d20fdb7Upstream	nr = read(ppp_fd, buf, len);
109982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
110082c907af479178801a7a8701341b22c9d20fdb7Upstream	    && errno != EIO && errno != EINTR)
110182c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("read: %m");
110282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (nr < 0 && errno == ENXIO)
110382c907af479178801a7a8701341b22c9d20fdb7Upstream	    return 0;
110482c907af479178801a7a8701341b22c9d20fdb7Upstream    }
110582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (nr < 0 && new_style_driver && ppp_dev_fd >= 0 && !bundle_eof) {
110682c907af479178801a7a8701341b22c9d20fdb7Upstream	/* N.B. we read ppp_fd first since LCP packets come in there. */
110782c907af479178801a7a8701341b22c9d20fdb7Upstream	nr = read(ppp_dev_fd, buf, len);
110882c907af479178801a7a8701341b22c9d20fdb7Upstream	if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
110982c907af479178801a7a8701341b22c9d20fdb7Upstream	    && errno != EIO && errno != EINTR)
111082c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("read /dev/ppp: %m");
111182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (nr < 0 && errno == ENXIO)
111282c907af479178801a7a8701341b22c9d20fdb7Upstream	    nr = 0;
111382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (nr == 0 && doing_multilink) {
111482c907af479178801a7a8701341b22c9d20fdb7Upstream	    remove_fd(ppp_dev_fd);
111582c907af479178801a7a8701341b22c9d20fdb7Upstream	    bundle_eof = 1;
111682c907af479178801a7a8701341b22c9d20fdb7Upstream	}
111782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
111882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver && ppp_fd < 0 && ppp_dev_fd < 0)
111982c907af479178801a7a8701341b22c9d20fdb7Upstream	nr = 0;
112082c907af479178801a7a8701341b22c9d20fdb7Upstream    return (new_style_driver && nr > 0)? nr+2: nr;
112182c907af479178801a7a8701341b22c9d20fdb7Upstream}
112282c907af479178801a7a8701341b22c9d20fdb7Upstream
112382c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
112482c907af479178801a7a8701341b22c9d20fdb7Upstream *
112582c907af479178801a7a8701341b22c9d20fdb7Upstream * get_loop_output - get outgoing packets from the ppp device,
112682c907af479178801a7a8701341b22c9d20fdb7Upstream * and detect when we want to bring the real link up.
112782c907af479178801a7a8701341b22c9d20fdb7Upstream * Return value is 1 if we need to bring up the link, 0 otherwise.
112882c907af479178801a7a8701341b22c9d20fdb7Upstream */
112982c907af479178801a7a8701341b22c9d20fdb7Upstreamint
113082c907af479178801a7a8701341b22c9d20fdb7Upstreamget_loop_output(void)
113182c907af479178801a7a8701341b22c9d20fdb7Upstream{
113282c907af479178801a7a8701341b22c9d20fdb7Upstream    int rv = 0;
113382c907af479178801a7a8701341b22c9d20fdb7Upstream    int n;
113482c907af479178801a7a8701341b22c9d20fdb7Upstream
113582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver) {
113682c907af479178801a7a8701341b22c9d20fdb7Upstream	while ((n = read_packet(inpacket_buf)) > 0)
113782c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (loop_frame(inpacket_buf, n))
113882c907af479178801a7a8701341b22c9d20fdb7Upstream		rv = 1;
113982c907af479178801a7a8701341b22c9d20fdb7Upstream	return rv;
114082c907af479178801a7a8701341b22c9d20fdb7Upstream    }
114182c907af479178801a7a8701341b22c9d20fdb7Upstream
114282c907af479178801a7a8701341b22c9d20fdb7Upstream    while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0)
114382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (loop_chars(inbuf, n))
114482c907af479178801a7a8701341b22c9d20fdb7Upstream	    rv = 1;
114582c907af479178801a7a8701341b22c9d20fdb7Upstream
114682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (n == 0)
114782c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("eof on loopback");
114882c907af479178801a7a8701341b22c9d20fdb7Upstream
114982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (errno != EWOULDBLOCK && errno != EAGAIN)
115082c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("read from loopback: %m(%d)", errno);
115182c907af479178801a7a8701341b22c9d20fdb7Upstream
115282c907af479178801a7a8701341b22c9d20fdb7Upstream    return rv;
115382c907af479178801a7a8701341b22c9d20fdb7Upstream}
115482c907af479178801a7a8701341b22c9d20fdb7Upstream
115582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
115682c907af479178801a7a8701341b22c9d20fdb7Upstream * netif_set_mtu - set the MTU on the PPP network interface.
115782c907af479178801a7a8701341b22c9d20fdb7Upstream */
115882c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid
115982c907af479178801a7a8701341b22c9d20fdb7Upstreamnetif_set_mtu(int unit, int mtu)
116082c907af479178801a7a8701341b22c9d20fdb7Upstream{
116182c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
116282c907af479178801a7a8701341b22c9d20fdb7Upstream
116382c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&ifr, '\0', sizeof (ifr));
116482c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
116582c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr.ifr_mtu = mtu;
116682c907af479178801a7a8701341b22c9d20fdb7Upstream
116782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
116882c907af479178801a7a8701341b22c9d20fdb7Upstream	error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);
116982c907af479178801a7a8701341b22c9d20fdb7Upstream}
117082c907af479178801a7a8701341b22c9d20fdb7Upstream
117182c907af479178801a7a8701341b22c9d20fdb7Upstream/*
117282c907af479178801a7a8701341b22c9d20fdb7Upstream * netif_get_mtu - get the MTU on the PPP network interface.
117382c907af479178801a7a8701341b22c9d20fdb7Upstream */
117482c907af479178801a7a8701341b22c9d20fdb7Upstreamint
117582c907af479178801a7a8701341b22c9d20fdb7Upstreamnetif_get_mtu(int unit)
117682c907af479178801a7a8701341b22c9d20fdb7Upstream{
117782c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
117882c907af479178801a7a8701341b22c9d20fdb7Upstream
117982c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&ifr, '\0', sizeof (ifr));
118082c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
118182c907af479178801a7a8701341b22c9d20fdb7Upstream
118282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
118382c907af479178801a7a8701341b22c9d20fdb7Upstream	error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__);
118482c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
118582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
118682c907af479178801a7a8701341b22c9d20fdb7Upstream    return ifr.ifr_mtu;
118782c907af479178801a7a8701341b22c9d20fdb7Upstream}
118882c907af479178801a7a8701341b22c9d20fdb7Upstream
118982c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
119082c907af479178801a7a8701341b22c9d20fdb7Upstream *
119182c907af479178801a7a8701341b22c9d20fdb7Upstream * tty_send_config - configure the transmit characteristics of
119282c907af479178801a7a8701341b22c9d20fdb7Upstream * the ppp interface.
119382c907af479178801a7a8701341b22c9d20fdb7Upstream */
119482c907af479178801a7a8701341b22c9d20fdb7Upstream
119582c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
119682c907af479178801a7a8701341b22c9d20fdb7Upstream{
119782c907af479178801a7a8701341b22c9d20fdb7Upstream	int x;
119882c907af479178801a7a8701341b22c9d20fdb7Upstream
119982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!still_ppp())
120082c907af479178801a7a8701341b22c9d20fdb7Upstream		return;
120182c907af479178801a7a8701341b22c9d20fdb7Upstream	link_mtu = mtu;
120282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
120382c907af479178801a7a8701341b22c9d20fdb7Upstream		if (errno != EIO && errno != ENOTTY)
120482c907af479178801a7a8701341b22c9d20fdb7Upstream			error("Couldn't set transmit async character map: %m");
120582c907af479178801a7a8701341b22c9d20fdb7Upstream		++error_count;
120682c907af479178801a7a8701341b22c9d20fdb7Upstream		return;
120782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
120882c907af479178801a7a8701341b22c9d20fdb7Upstream
120982c907af479178801a7a8701341b22c9d20fdb7Upstream	x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0)
121082c907af479178801a7a8701341b22c9d20fdb7Upstream	    | (sync_serial? SC_SYNC: 0);
121182c907af479178801a7a8701341b22c9d20fdb7Upstream	modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x);
121282c907af479178801a7a8701341b22c9d20fdb7Upstream}
121382c907af479178801a7a8701341b22c9d20fdb7Upstream
121482c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
121582c907af479178801a7a8701341b22c9d20fdb7Upstream *
121682c907af479178801a7a8701341b22c9d20fdb7Upstream * tty_set_xaccm - set the extended transmit ACCM for the interface.
121782c907af479178801a7a8701341b22c9d20fdb7Upstream */
121882c907af479178801a7a8701341b22c9d20fdb7Upstream
121982c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid tty_set_xaccm (ext_accm accm)
122082c907af479178801a7a8701341b22c9d20fdb7Upstream{
122182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!still_ppp())
122282c907af479178801a7a8701341b22c9d20fdb7Upstream	return;
122382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) {
122482c907af479178801a7a8701341b22c9d20fdb7Upstream	if ( ! ok_error (errno))
122582c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("ioctl(set extended ACCM): %m (line %d)", __LINE__);
122682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
122782c907af479178801a7a8701341b22c9d20fdb7Upstream}
122882c907af479178801a7a8701341b22c9d20fdb7Upstream
122982c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
123082c907af479178801a7a8701341b22c9d20fdb7Upstream *
123182c907af479178801a7a8701341b22c9d20fdb7Upstream * tty_recv_config - configure the receive-side characteristics of
123282c907af479178801a7a8701341b22c9d20fdb7Upstream * the ppp interface.
123382c907af479178801a7a8701341b22c9d20fdb7Upstream */
123482c907af479178801a7a8701341b22c9d20fdb7Upstream
123582c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
123682c907af479178801a7a8701341b22c9d20fdb7Upstream{
123782c907af479178801a7a8701341b22c9d20fdb7Upstream/*
123882c907af479178801a7a8701341b22c9d20fdb7Upstream * If we were called because the link has gone down then there is nothing
123982c907af479178801a7a8701341b22c9d20fdb7Upstream * which may be done. Just return without incident.
124082c907af479178801a7a8701341b22c9d20fdb7Upstream */
124182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!still_ppp())
124282c907af479178801a7a8701341b22c9d20fdb7Upstream		return;
124382c907af479178801a7a8701341b22c9d20fdb7Upstream/*
124482c907af479178801a7a8701341b22c9d20fdb7Upstream * Set the receiver parameters
124582c907af479178801a7a8701341b22c9d20fdb7Upstream */
124682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
124782c907af479178801a7a8701341b22c9d20fdb7Upstream		if (errno != EIO && errno != ENOTTY)
124882c907af479178801a7a8701341b22c9d20fdb7Upstream			error("Couldn't set channel receive MRU: %m");
124982c907af479178801a7a8701341b22c9d20fdb7Upstream	}
125082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (new_style_driver && ppp_dev_fd >= 0
125182c907af479178801a7a8701341b22c9d20fdb7Upstream	    && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
125282c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Couldn't set MRU in generic PPP layer: %m");
125382c907af479178801a7a8701341b22c9d20fdb7Upstream
125482c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
125582c907af479178801a7a8701341b22c9d20fdb7Upstream		if (errno != EIO && errno != ENOTTY)
125682c907af479178801a7a8701341b22c9d20fdb7Upstream			error("Couldn't set channel receive asyncmap: %m");
125782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
125882c907af479178801a7a8701341b22c9d20fdb7Upstream}
125982c907af479178801a7a8701341b22c9d20fdb7Upstream
126082c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
126182c907af479178801a7a8701341b22c9d20fdb7Upstream *
126282c907af479178801a7a8701341b22c9d20fdb7Upstream * ccp_test - ask kernel whether a given compression method
126382c907af479178801a7a8701341b22c9d20fdb7Upstream * is acceptable for use.
126482c907af479178801a7a8701341b22c9d20fdb7Upstream */
126582c907af479178801a7a8701341b22c9d20fdb7Upstream
126682c907af479178801a7a8701341b22c9d20fdb7Upstreamint
126782c907af479178801a7a8701341b22c9d20fdb7Upstreamccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
126882c907af479178801a7a8701341b22c9d20fdb7Upstream{
126982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ppp_option_data data;
127082c907af479178801a7a8701341b22c9d20fdb7Upstream
127182c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&data, '\0', sizeof (data));
127282c907af479178801a7a8701341b22c9d20fdb7Upstream    data.ptr      = opt_ptr;
127382c907af479178801a7a8701341b22c9d20fdb7Upstream    data.length   = opt_len;
127482c907af479178801a7a8701341b22c9d20fdb7Upstream    data.transmit = for_transmit;
127582c907af479178801a7a8701341b22c9d20fdb7Upstream
127682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
127782c907af479178801a7a8701341b22c9d20fdb7Upstream	return 1;
127882c907af479178801a7a8701341b22c9d20fdb7Upstream
127982c907af479178801a7a8701341b22c9d20fdb7Upstream    return (errno == ENOBUFS)? 0: -1;
128082c907af479178801a7a8701341b22c9d20fdb7Upstream}
128182c907af479178801a7a8701341b22c9d20fdb7Upstream
128282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
128382c907af479178801a7a8701341b22c9d20fdb7Upstream *
128482c907af479178801a7a8701341b22c9d20fdb7Upstream * ccp_flags_set - inform kernel about the current state of CCP.
128582c907af479178801a7a8701341b22c9d20fdb7Upstream */
128682c907af479178801a7a8701341b22c9d20fdb7Upstream
128782c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid ccp_flags_set (int unit, int isopen, int isup)
128882c907af479178801a7a8701341b22c9d20fdb7Upstream{
128982c907af479178801a7a8701341b22c9d20fdb7Upstream	int x;
129082c907af479178801a7a8701341b22c9d20fdb7Upstream
129182c907af479178801a7a8701341b22c9d20fdb7Upstream	x = (isopen? SC_CCP_OPEN: 0) | (isup? SC_CCP_UP: 0);
129282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (still_ppp() && ppp_dev_fd >= 0)
129382c907af479178801a7a8701341b22c9d20fdb7Upstream		modify_flags(ppp_dev_fd, SC_CCP_OPEN|SC_CCP_UP, x);
129482c907af479178801a7a8701341b22c9d20fdb7Upstream}
129582c907af479178801a7a8701341b22c9d20fdb7Upstream
129682c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef PPP_FILTER
129782c907af479178801a7a8701341b22c9d20fdb7Upstream/*
129882c907af479178801a7a8701341b22c9d20fdb7Upstream * set_filters - set the active and pass filters in the kernel driver.
129982c907af479178801a7a8701341b22c9d20fdb7Upstream */
130082c907af479178801a7a8701341b22c9d20fdb7Upstreamint set_filters(struct bpf_program *pass, struct bpf_program *active)
130182c907af479178801a7a8701341b22c9d20fdb7Upstream{
130282c907af479178801a7a8701341b22c9d20fdb7Upstream	struct sock_fprog fp;
130382c907af479178801a7a8701341b22c9d20fdb7Upstream
130482c907af479178801a7a8701341b22c9d20fdb7Upstream	fp.len = pass->bf_len;
130582c907af479178801a7a8701341b22c9d20fdb7Upstream	fp.filter = (struct sock_filter *) pass->bf_insns;
130682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_dev_fd, PPPIOCSPASS, &fp) < 0) {
130782c907af479178801a7a8701341b22c9d20fdb7Upstream		if (errno == ENOTTY)
130882c907af479178801a7a8701341b22c9d20fdb7Upstream			warn("kernel does not support PPP filtering");
130982c907af479178801a7a8701341b22c9d20fdb7Upstream		else
131082c907af479178801a7a8701341b22c9d20fdb7Upstream			error("Couldn't set pass-filter in kernel: %m");
131182c907af479178801a7a8701341b22c9d20fdb7Upstream		return 0;
131282c907af479178801a7a8701341b22c9d20fdb7Upstream	}
131382c907af479178801a7a8701341b22c9d20fdb7Upstream	fp.len = active->bf_len;
131482c907af479178801a7a8701341b22c9d20fdb7Upstream	fp.filter = (struct sock_filter *) active->bf_insns;
131582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_dev_fd, PPPIOCSACTIVE, &fp) < 0) {
131682c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Couldn't set active-filter in kernel: %m");
131782c907af479178801a7a8701341b22c9d20fdb7Upstream		return 0;
131882c907af479178801a7a8701341b22c9d20fdb7Upstream	}
131982c907af479178801a7a8701341b22c9d20fdb7Upstream	return 1;
132082c907af479178801a7a8701341b22c9d20fdb7Upstream}
132182c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* PPP_FILTER */
132282c907af479178801a7a8701341b22c9d20fdb7Upstream
132382c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
132482c907af479178801a7a8701341b22c9d20fdb7Upstream *
132582c907af479178801a7a8701341b22c9d20fdb7Upstream * get_idle_time - return how long the link has been idle.
132682c907af479178801a7a8701341b22c9d20fdb7Upstream */
132782c907af479178801a7a8701341b22c9d20fdb7Upstreamint
132882c907af479178801a7a8701341b22c9d20fdb7Upstreamget_idle_time(u, ip)
132982c907af479178801a7a8701341b22c9d20fdb7Upstream    int u;
133082c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ppp_idle *ip;
133182c907af479178801a7a8701341b22c9d20fdb7Upstream{
133282c907af479178801a7a8701341b22c9d20fdb7Upstream    return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;
133382c907af479178801a7a8701341b22c9d20fdb7Upstream}
133482c907af479178801a7a8701341b22c9d20fdb7Upstream
133582c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
133682c907af479178801a7a8701341b22c9d20fdb7Upstream *
133782c907af479178801a7a8701341b22c9d20fdb7Upstream * get_ppp_stats - return statistics for the link.
133882c907af479178801a7a8701341b22c9d20fdb7Upstream */
133982c907af479178801a7a8701341b22c9d20fdb7Upstreamint
134082c907af479178801a7a8701341b22c9d20fdb7Upstreamget_ppp_stats(u, stats)
134182c907af479178801a7a8701341b22c9d20fdb7Upstream    int u;
134282c907af479178801a7a8701341b22c9d20fdb7Upstream    struct pppd_stats *stats;
134382c907af479178801a7a8701341b22c9d20fdb7Upstream{
134482c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifpppstatsreq req;
134582c907af479178801a7a8701341b22c9d20fdb7Upstream
134682c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&req, 0, sizeof (req));
134782c907af479178801a7a8701341b22c9d20fdb7Upstream
134882c907af479178801a7a8701341b22c9d20fdb7Upstream    req.stats_ptr = (caddr_t) &req.stats;
134982c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
135082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
135182c907af479178801a7a8701341b22c9d20fdb7Upstream	error("Couldn't get PPP statistics: %m");
135282c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
135382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
135482c907af479178801a7a8701341b22c9d20fdb7Upstream    stats->bytes_in = req.stats.p.ppp_ibytes;
135582c907af479178801a7a8701341b22c9d20fdb7Upstream    stats->bytes_out = req.stats.p.ppp_obytes;
135682c907af479178801a7a8701341b22c9d20fdb7Upstream    stats->pkts_in = req.stats.p.ppp_ipackets;
135782c907af479178801a7a8701341b22c9d20fdb7Upstream    stats->pkts_out = req.stats.p.ppp_opackets;
135882c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
135982c907af479178801a7a8701341b22c9d20fdb7Upstream}
136082c907af479178801a7a8701341b22c9d20fdb7Upstream
136182c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
136282c907af479178801a7a8701341b22c9d20fdb7Upstream *
136382c907af479178801a7a8701341b22c9d20fdb7Upstream * ccp_fatal_error - returns 1 if decompression was disabled as a
136482c907af479178801a7a8701341b22c9d20fdb7Upstream * result of an error detected after decompression of a packet,
136582c907af479178801a7a8701341b22c9d20fdb7Upstream * 0 otherwise.  This is necessary because of patent nonsense.
136682c907af479178801a7a8701341b22c9d20fdb7Upstream */
136782c907af479178801a7a8701341b22c9d20fdb7Upstream
136882c907af479178801a7a8701341b22c9d20fdb7Upstreamint ccp_fatal_error (int unit)
136982c907af479178801a7a8701341b22c9d20fdb7Upstream{
137082c907af479178801a7a8701341b22c9d20fdb7Upstream	int flags;
137182c907af479178801a7a8701341b22c9d20fdb7Upstream
137282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(ppp_dev_fd, PPPIOCGFLAGS, &flags) < 0) {
137382c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Couldn't read compression error flags: %m");
137482c907af479178801a7a8701341b22c9d20fdb7Upstream		flags = 0;
137582c907af479178801a7a8701341b22c9d20fdb7Upstream	}
137682c907af479178801a7a8701341b22c9d20fdb7Upstream	return flags & SC_DC_FERROR;
137782c907af479178801a7a8701341b22c9d20fdb7Upstream}
137882c907af479178801a7a8701341b22c9d20fdb7Upstream
137982c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
138082c907af479178801a7a8701341b22c9d20fdb7Upstream *
138182c907af479178801a7a8701341b22c9d20fdb7Upstream * path_to_procfs - find the path to the proc file system mount point
138282c907af479178801a7a8701341b22c9d20fdb7Upstream */
138382c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic char proc_path[MAXPATHLEN];
138482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int proc_path_len;
138582c907af479178801a7a8701341b22c9d20fdb7Upstream
138682c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic char *path_to_procfs(const char *tail)
138782c907af479178801a7a8701341b22c9d20fdb7Upstream{
138882c907af479178801a7a8701341b22c9d20fdb7Upstream    struct mntent *mntent;
138982c907af479178801a7a8701341b22c9d20fdb7Upstream    FILE *fp;
139082c907af479178801a7a8701341b22c9d20fdb7Upstream
139182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (proc_path_len == 0) {
139282c907af479178801a7a8701341b22c9d20fdb7Upstream	/* Default the mount location of /proc */
139382c907af479178801a7a8701341b22c9d20fdb7Upstream	strlcpy (proc_path, "/proc", sizeof(proc_path));
139482c907af479178801a7a8701341b22c9d20fdb7Upstream	proc_path_len = 5;
1395dab68864983c4a0c6ef9e6d7e5834472c4c75f9cThe Android Open Source Project	fp = fopen(_PATH_MOUNTED, "r");
139682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (fp != NULL) {
139782c907af479178801a7a8701341b22c9d20fdb7Upstream	    while ((mntent = getmntent(fp)) != NULL) {
139882c907af479178801a7a8701341b22c9d20fdb7Upstream		if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
139982c907af479178801a7a8701341b22c9d20fdb7Upstream		    continue;
140082c907af479178801a7a8701341b22c9d20fdb7Upstream		if (strcmp(mntent->mnt_type, "proc") == 0) {
140182c907af479178801a7a8701341b22c9d20fdb7Upstream		    strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path));
140282c907af479178801a7a8701341b22c9d20fdb7Upstream		    proc_path_len = strlen(proc_path);
140382c907af479178801a7a8701341b22c9d20fdb7Upstream		    break;
140482c907af479178801a7a8701341b22c9d20fdb7Upstream		}
140582c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
140682c907af479178801a7a8701341b22c9d20fdb7Upstream	    fclose (fp);
140782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
140882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
140982c907af479178801a7a8701341b22c9d20fdb7Upstream
141082c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(proc_path + proc_path_len, tail,
141182c907af479178801a7a8701341b22c9d20fdb7Upstream	    sizeof(proc_path) - proc_path_len);
141282c907af479178801a7a8701341b22c9d20fdb7Upstream    return proc_path;
141382c907af479178801a7a8701341b22c9d20fdb7Upstream}
141482c907af479178801a7a8701341b22c9d20fdb7Upstream
141582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
141682c907af479178801a7a8701341b22c9d20fdb7Upstream * /proc/net/route parsing stuff.
141782c907af479178801a7a8701341b22c9d20fdb7Upstream */
141882c907af479178801a7a8701341b22c9d20fdb7Upstream#define ROUTE_MAX_COLS	12
141982c907af479178801a7a8701341b22c9d20fdb7UpstreamFILE *route_fd = (FILE *) 0;
142082c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic char route_buffer[512];
142182c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int route_dev_col, route_dest_col, route_gw_col;
142282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int route_flags_col, route_mask_col;
142382c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int route_num_cols;
142482c907af479178801a7a8701341b22c9d20fdb7Upstream
142582c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int open_route_table (void);
142682c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic void close_route_table (void);
142782c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int read_route_table (struct rtentry *rt);
142882c907af479178801a7a8701341b22c9d20fdb7Upstream
142982c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
143082c907af479178801a7a8701341b22c9d20fdb7Upstream *
143182c907af479178801a7a8701341b22c9d20fdb7Upstream * close_route_table - close the interface to the route table
143282c907af479178801a7a8701341b22c9d20fdb7Upstream */
143382c907af479178801a7a8701341b22c9d20fdb7Upstream
143482c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic void close_route_table (void)
143582c907af479178801a7a8701341b22c9d20fdb7Upstream{
143682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (route_fd != (FILE *) 0) {
143782c907af479178801a7a8701341b22c9d20fdb7Upstream	fclose (route_fd);
143882c907af479178801a7a8701341b22c9d20fdb7Upstream	route_fd = (FILE *) 0;
143982c907af479178801a7a8701341b22c9d20fdb7Upstream    }
144082c907af479178801a7a8701341b22c9d20fdb7Upstream}
144182c907af479178801a7a8701341b22c9d20fdb7Upstream
144282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
144382c907af479178801a7a8701341b22c9d20fdb7Upstream *
144482c907af479178801a7a8701341b22c9d20fdb7Upstream * open_route_table - open the interface to the route table
144582c907af479178801a7a8701341b22c9d20fdb7Upstream */
144682c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic char route_delims[] = " \t\n";
144782c907af479178801a7a8701341b22c9d20fdb7Upstream
144882c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int open_route_table (void)
144982c907af479178801a7a8701341b22c9d20fdb7Upstream{
145082c907af479178801a7a8701341b22c9d20fdb7Upstream    char *path;
145182c907af479178801a7a8701341b22c9d20fdb7Upstream
145282c907af479178801a7a8701341b22c9d20fdb7Upstream    close_route_table();
145382c907af479178801a7a8701341b22c9d20fdb7Upstream
145482c907af479178801a7a8701341b22c9d20fdb7Upstream    path = path_to_procfs("/net/route");
145582c907af479178801a7a8701341b22c9d20fdb7Upstream    route_fd = fopen (path, "r");
145682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (route_fd == NULL) {
145782c907af479178801a7a8701341b22c9d20fdb7Upstream	error("can't open routing table %s: %m", path);
145882c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
145982c907af479178801a7a8701341b22c9d20fdb7Upstream    }
146082c907af479178801a7a8701341b22c9d20fdb7Upstream
146182c907af479178801a7a8701341b22c9d20fdb7Upstream    route_dev_col = 0;		/* default to usual columns */
146282c907af479178801a7a8701341b22c9d20fdb7Upstream    route_dest_col = 1;
146382c907af479178801a7a8701341b22c9d20fdb7Upstream    route_gw_col = 2;
146482c907af479178801a7a8701341b22c9d20fdb7Upstream    route_flags_col = 3;
146582c907af479178801a7a8701341b22c9d20fdb7Upstream    route_mask_col = 7;
146682c907af479178801a7a8701341b22c9d20fdb7Upstream    route_num_cols = 8;
146782c907af479178801a7a8701341b22c9d20fdb7Upstream
146882c907af479178801a7a8701341b22c9d20fdb7Upstream    /* parse header line */
146982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
147082c907af479178801a7a8701341b22c9d20fdb7Upstream	char *p = route_buffer, *q;
147182c907af479178801a7a8701341b22c9d20fdb7Upstream	int col;
147282c907af479178801a7a8701341b22c9d20fdb7Upstream	for (col = 0; col < ROUTE_MAX_COLS; ++col) {
147382c907af479178801a7a8701341b22c9d20fdb7Upstream	    int used = 1;
147482c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ((q = strtok(p, route_delims)) == 0)
147582c907af479178801a7a8701341b22c9d20fdb7Upstream		break;
147682c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (strcasecmp(q, "iface") == 0)
147782c907af479178801a7a8701341b22c9d20fdb7Upstream		route_dev_col = col;
147882c907af479178801a7a8701341b22c9d20fdb7Upstream	    else if (strcasecmp(q, "destination") == 0)
147982c907af479178801a7a8701341b22c9d20fdb7Upstream		route_dest_col = col;
148082c907af479178801a7a8701341b22c9d20fdb7Upstream	    else if (strcasecmp(q, "gateway") == 0)
148182c907af479178801a7a8701341b22c9d20fdb7Upstream		route_gw_col = col;
148282c907af479178801a7a8701341b22c9d20fdb7Upstream	    else if (strcasecmp(q, "flags") == 0)
148382c907af479178801a7a8701341b22c9d20fdb7Upstream		route_flags_col = col;
148482c907af479178801a7a8701341b22c9d20fdb7Upstream	    else if (strcasecmp(q, "mask") == 0)
148582c907af479178801a7a8701341b22c9d20fdb7Upstream		route_mask_col = col;
148682c907af479178801a7a8701341b22c9d20fdb7Upstream	    else
148782c907af479178801a7a8701341b22c9d20fdb7Upstream		used = 0;
148882c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (used && col >= route_num_cols)
148982c907af479178801a7a8701341b22c9d20fdb7Upstream		route_num_cols = col + 1;
149082c907af479178801a7a8701341b22c9d20fdb7Upstream	    p = NULL;
149182c907af479178801a7a8701341b22c9d20fdb7Upstream	}
149282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
149382c907af479178801a7a8701341b22c9d20fdb7Upstream
149482c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
149582c907af479178801a7a8701341b22c9d20fdb7Upstream}
149682c907af479178801a7a8701341b22c9d20fdb7Upstream
149782c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
149882c907af479178801a7a8701341b22c9d20fdb7Upstream *
149982c907af479178801a7a8701341b22c9d20fdb7Upstream * read_route_table - read the next entry from the route table
150082c907af479178801a7a8701341b22c9d20fdb7Upstream */
150182c907af479178801a7a8701341b22c9d20fdb7Upstream
150282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int read_route_table(struct rtentry *rt)
150382c907af479178801a7a8701341b22c9d20fdb7Upstream{
150482c907af479178801a7a8701341b22c9d20fdb7Upstream    char *cols[ROUTE_MAX_COLS], *p;
150582c907af479178801a7a8701341b22c9d20fdb7Upstream    int col;
150682c907af479178801a7a8701341b22c9d20fdb7Upstream
150782c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (rt, '\0', sizeof (struct rtentry));
150882c907af479178801a7a8701341b22c9d20fdb7Upstream
150982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
151082c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
151182c907af479178801a7a8701341b22c9d20fdb7Upstream
151282c907af479178801a7a8701341b22c9d20fdb7Upstream    p = route_buffer;
151382c907af479178801a7a8701341b22c9d20fdb7Upstream    for (col = 0; col < route_num_cols; ++col) {
151482c907af479178801a7a8701341b22c9d20fdb7Upstream	cols[col] = strtok(p, route_delims);
151582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (cols[col] == NULL)
151682c907af479178801a7a8701341b22c9d20fdb7Upstream	    return 0;		/* didn't get enough columns */
151782c907af479178801a7a8701341b22c9d20fdb7Upstream	p = NULL;
151882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
151982c907af479178801a7a8701341b22c9d20fdb7Upstream
152082c907af479178801a7a8701341b22c9d20fdb7Upstream    SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
152182c907af479178801a7a8701341b22c9d20fdb7Upstream    SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
152282c907af479178801a7a8701341b22c9d20fdb7Upstream    SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
152382c907af479178801a7a8701341b22c9d20fdb7Upstream
152482c907af479178801a7a8701341b22c9d20fdb7Upstream    rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
152582c907af479178801a7a8701341b22c9d20fdb7Upstream    rt->rt_dev   = cols[route_dev_col];
152682c907af479178801a7a8701341b22c9d20fdb7Upstream
152782c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
152882c907af479178801a7a8701341b22c9d20fdb7Upstream}
152982c907af479178801a7a8701341b22c9d20fdb7Upstream
153082c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
153182c907af479178801a7a8701341b22c9d20fdb7Upstream *
153282c907af479178801a7a8701341b22c9d20fdb7Upstream * defaultroute_exists - determine if there is a default route
153382c907af479178801a7a8701341b22c9d20fdb7Upstream */
153482c907af479178801a7a8701341b22c9d20fdb7Upstream
153582c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int defaultroute_exists (struct rtentry *rt)
153682c907af479178801a7a8701341b22c9d20fdb7Upstream{
153782c907af479178801a7a8701341b22c9d20fdb7Upstream    int result = 0;
153882c907af479178801a7a8701341b22c9d20fdb7Upstream
153982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!open_route_table())
154082c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
154182c907af479178801a7a8701341b22c9d20fdb7Upstream
154282c907af479178801a7a8701341b22c9d20fdb7Upstream    while (read_route_table(rt) != 0) {
154382c907af479178801a7a8701341b22c9d20fdb7Upstream	if ((rt->rt_flags & RTF_UP) == 0)
154482c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
154582c907af479178801a7a8701341b22c9d20fdb7Upstream
154682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
154782c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
154882c907af479178801a7a8701341b22c9d20fdb7Upstream	if (SIN_ADDR(rt->rt_dst) == 0L) {
154982c907af479178801a7a8701341b22c9d20fdb7Upstream	    result = 1;
155082c907af479178801a7a8701341b22c9d20fdb7Upstream	    break;
155182c907af479178801a7a8701341b22c9d20fdb7Upstream	}
155282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
155382c907af479178801a7a8701341b22c9d20fdb7Upstream
155482c907af479178801a7a8701341b22c9d20fdb7Upstream    close_route_table();
155582c907af479178801a7a8701341b22c9d20fdb7Upstream    return result;
155682c907af479178801a7a8701341b22c9d20fdb7Upstream}
155782c907af479178801a7a8701341b22c9d20fdb7Upstream
155882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
155982c907af479178801a7a8701341b22c9d20fdb7Upstream * have_route_to - determine if the system has any route to
156082c907af479178801a7a8701341b22c9d20fdb7Upstream * a given IP address.  `addr' is in network byte order.
156182c907af479178801a7a8701341b22c9d20fdb7Upstream * Return value is 1 if yes, 0 if no, -1 if don't know.
156282c907af479178801a7a8701341b22c9d20fdb7Upstream * For demand mode to work properly, we have to ignore routes
156382c907af479178801a7a8701341b22c9d20fdb7Upstream * through our own interface.
156482c907af479178801a7a8701341b22c9d20fdb7Upstream */
156582c907af479178801a7a8701341b22c9d20fdb7Upstreamint have_route_to(u_int32_t addr)
156682c907af479178801a7a8701341b22c9d20fdb7Upstream{
156782c907af479178801a7a8701341b22c9d20fdb7Upstream    struct rtentry rt;
156882c907af479178801a7a8701341b22c9d20fdb7Upstream    int result = 0;
156982c907af479178801a7a8701341b22c9d20fdb7Upstream
157082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!open_route_table())
157182c907af479178801a7a8701341b22c9d20fdb7Upstream	return -1;		/* don't know */
157282c907af479178801a7a8701341b22c9d20fdb7Upstream
157382c907af479178801a7a8701341b22c9d20fdb7Upstream    while (read_route_table(&rt)) {
157482c907af479178801a7a8701341b22c9d20fdb7Upstream	if ((rt.rt_flags & RTF_UP) == 0 || strcmp(rt.rt_dev, ifname) == 0)
157582c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
157682c907af479178801a7a8701341b22c9d20fdb7Upstream	if ((addr & SIN_ADDR(rt.rt_genmask)) == SIN_ADDR(rt.rt_dst)) {
157782c907af479178801a7a8701341b22c9d20fdb7Upstream	    result = 1;
157882c907af479178801a7a8701341b22c9d20fdb7Upstream	    break;
157982c907af479178801a7a8701341b22c9d20fdb7Upstream	}
158082c907af479178801a7a8701341b22c9d20fdb7Upstream    }
158182c907af479178801a7a8701341b22c9d20fdb7Upstream
158282c907af479178801a7a8701341b22c9d20fdb7Upstream    close_route_table();
158382c907af479178801a7a8701341b22c9d20fdb7Upstream    return result;
158482c907af479178801a7a8701341b22c9d20fdb7Upstream}
158582c907af479178801a7a8701341b22c9d20fdb7Upstream
158682c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
158782c907af479178801a7a8701341b22c9d20fdb7Upstream *
158882c907af479178801a7a8701341b22c9d20fdb7Upstream * sifdefaultroute - assign a default route through the address given.
158982c907af479178801a7a8701341b22c9d20fdb7Upstream */
159082c907af479178801a7a8701341b22c9d20fdb7Upstream
159182c907af479178801a7a8701341b22c9d20fdb7Upstreamint sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
159282c907af479178801a7a8701341b22c9d20fdb7Upstream{
159382c907af479178801a7a8701341b22c9d20fdb7Upstream    struct rtentry rt;
159482c907af479178801a7a8701341b22c9d20fdb7Upstream
159582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
159682c907af479178801a7a8701341b22c9d20fdb7Upstream	u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway);
159782c907af479178801a7a8701341b22c9d20fdb7Upstream
159882c907af479178801a7a8701341b22c9d20fdb7Upstream	if (old_gateway != gateway)
159982c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("not replacing existing default route to %s [%I]",
160082c907af479178801a7a8701341b22c9d20fdb7Upstream		  rt.rt_dev, old_gateway);
160182c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
160282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
160382c907af479178801a7a8701341b22c9d20fdb7Upstream
160482c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&rt, '\0', sizeof (rt));
160582c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY (rt.rt_dst,     AF_INET);
160682c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY (rt.rt_gateway, AF_INET);
160782c907af479178801a7a8701341b22c9d20fdb7Upstream
160882c907af479178801a7a8701341b22c9d20fdb7Upstream    rt.rt_dev = ifname;
160982c907af479178801a7a8701341b22c9d20fdb7Upstream
161082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (kernel_version > KVERSION(2,1,0)) {
161182c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY (rt.rt_genmask, AF_INET);
161282c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(rt.rt_genmask) = 0L;
161382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
161482c907af479178801a7a8701341b22c9d20fdb7Upstream
161582c907af479178801a7a8701341b22c9d20fdb7Upstream    SIN_ADDR(rt.rt_gateway) = gateway;
161682c907af479178801a7a8701341b22c9d20fdb7Upstream
161782c907af479178801a7a8701341b22c9d20fdb7Upstream    rt.rt_flags = RTF_UP | RTF_GATEWAY;
161882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
161982c907af479178801a7a8701341b22c9d20fdb7Upstream	if ( ! ok_error ( errno ))
162082c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("default route ioctl(SIOCADDRT): %m");
162182c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
162282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
162382c907af479178801a7a8701341b22c9d20fdb7Upstream
162482c907af479178801a7a8701341b22c9d20fdb7Upstream    default_route_gateway = gateway;
162582c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
162682c907af479178801a7a8701341b22c9d20fdb7Upstream}
162782c907af479178801a7a8701341b22c9d20fdb7Upstream
162882c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
162982c907af479178801a7a8701341b22c9d20fdb7Upstream *
163082c907af479178801a7a8701341b22c9d20fdb7Upstream * cifdefaultroute - delete a default route through the address given.
163182c907af479178801a7a8701341b22c9d20fdb7Upstream */
163282c907af479178801a7a8701341b22c9d20fdb7Upstream
163382c907af479178801a7a8701341b22c9d20fdb7Upstreamint cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
163482c907af479178801a7a8701341b22c9d20fdb7Upstream{
163582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct rtentry rt;
163682c907af479178801a7a8701341b22c9d20fdb7Upstream
163782c907af479178801a7a8701341b22c9d20fdb7Upstream    default_route_gateway = 0;
163882c907af479178801a7a8701341b22c9d20fdb7Upstream
163982c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&rt, '\0', sizeof (rt));
164082c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY (rt.rt_dst,     AF_INET);
164182c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY (rt.rt_gateway, AF_INET);
164282c907af479178801a7a8701341b22c9d20fdb7Upstream
164382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (kernel_version > KVERSION(2,1,0)) {
164482c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY (rt.rt_genmask, AF_INET);
164582c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(rt.rt_genmask) = 0L;
164682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
164782c907af479178801a7a8701341b22c9d20fdb7Upstream
164882c907af479178801a7a8701341b22c9d20fdb7Upstream    SIN_ADDR(rt.rt_gateway) = gateway;
164982c907af479178801a7a8701341b22c9d20fdb7Upstream
165082c907af479178801a7a8701341b22c9d20fdb7Upstream    rt.rt_flags = RTF_UP | RTF_GATEWAY;
165182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
165282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (still_ppp()) {
165382c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ( ! ok_error ( errno ))
165482c907af479178801a7a8701341b22c9d20fdb7Upstream		error("default route ioctl(SIOCDELRT): %m");
165582c907af479178801a7a8701341b22c9d20fdb7Upstream	    return 0;
165682c907af479178801a7a8701341b22c9d20fdb7Upstream	}
165782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
165882c907af479178801a7a8701341b22c9d20fdb7Upstream
165982c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
166082c907af479178801a7a8701341b22c9d20fdb7Upstream}
166182c907af479178801a7a8701341b22c9d20fdb7Upstream
166282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
166382c907af479178801a7a8701341b22c9d20fdb7Upstream *
166482c907af479178801a7a8701341b22c9d20fdb7Upstream * sifproxyarp - Make a proxy ARP entry for the peer.
166582c907af479178801a7a8701341b22c9d20fdb7Upstream */
166682c907af479178801a7a8701341b22c9d20fdb7Upstream
166782c907af479178801a7a8701341b22c9d20fdb7Upstreamint sifproxyarp (int unit, u_int32_t his_adr)
166882c907af479178801a7a8701341b22c9d20fdb7Upstream{
166982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct arpreq arpreq;
167082c907af479178801a7a8701341b22c9d20fdb7Upstream    char *forw_path;
167182c907af479178801a7a8701341b22c9d20fdb7Upstream
167282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (has_proxy_arp == 0) {
167382c907af479178801a7a8701341b22c9d20fdb7Upstream	memset (&arpreq, '\0', sizeof(arpreq));
167482c907af479178801a7a8701341b22c9d20fdb7Upstream
167582c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
167682c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(arpreq.arp_pa) = his_adr;
167782c907af479178801a7a8701341b22c9d20fdb7Upstream	arpreq.arp_flags = ATF_PERM | ATF_PUBL;
167882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
167982c907af479178801a7a8701341b22c9d20fdb7Upstream * Get the hardware address of an interface on the same subnet
168082c907af479178801a7a8701341b22c9d20fdb7Upstream * as our local address.
168182c907af479178801a7a8701341b22c9d20fdb7Upstream */
168282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,
168382c907af479178801a7a8701341b22c9d20fdb7Upstream			    sizeof(proxy_arp_dev))) {
168482c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("Cannot determine ethernet address for proxy ARP");
168582c907af479178801a7a8701341b22c9d20fdb7Upstream	    return 0;
168682c907af479178801a7a8701341b22c9d20fdb7Upstream	}
168782c907af479178801a7a8701341b22c9d20fdb7Upstream	strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
168882c907af479178801a7a8701341b22c9d20fdb7Upstream
168982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
169082c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ( ! ok_error ( errno ))
169182c907af479178801a7a8701341b22c9d20fdb7Upstream		error("ioctl(SIOCSARP): %m");
169282c907af479178801a7a8701341b22c9d20fdb7Upstream	    return 0;
169382c907af479178801a7a8701341b22c9d20fdb7Upstream	}
169482c907af479178801a7a8701341b22c9d20fdb7Upstream	proxy_arp_addr = his_adr;
169582c907af479178801a7a8701341b22c9d20fdb7Upstream	has_proxy_arp = 1;
169682c907af479178801a7a8701341b22c9d20fdb7Upstream
169782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (tune_kernel) {
169882c907af479178801a7a8701341b22c9d20fdb7Upstream	    forw_path = path_to_procfs("/sys/net/ipv4/ip_forward");
169982c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (forw_path != 0) {
170082c907af479178801a7a8701341b22c9d20fdb7Upstream		int fd = open(forw_path, O_WRONLY);
170182c907af479178801a7a8701341b22c9d20fdb7Upstream		if (fd >= 0) {
170282c907af479178801a7a8701341b22c9d20fdb7Upstream		    if (write(fd, "1", 1) != 1)
170382c907af479178801a7a8701341b22c9d20fdb7Upstream			error("Couldn't enable IP forwarding: %m");
170482c907af479178801a7a8701341b22c9d20fdb7Upstream		    close(fd);
170582c907af479178801a7a8701341b22c9d20fdb7Upstream		}
170682c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
170782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
170882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
170982c907af479178801a7a8701341b22c9d20fdb7Upstream
171082c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
171182c907af479178801a7a8701341b22c9d20fdb7Upstream}
171282c907af479178801a7a8701341b22c9d20fdb7Upstream
171382c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
171482c907af479178801a7a8701341b22c9d20fdb7Upstream *
171582c907af479178801a7a8701341b22c9d20fdb7Upstream * cifproxyarp - Delete the proxy ARP entry for the peer.
171682c907af479178801a7a8701341b22c9d20fdb7Upstream */
171782c907af479178801a7a8701341b22c9d20fdb7Upstream
171882c907af479178801a7a8701341b22c9d20fdb7Upstreamint cifproxyarp (int unit, u_int32_t his_adr)
171982c907af479178801a7a8701341b22c9d20fdb7Upstream{
172082c907af479178801a7a8701341b22c9d20fdb7Upstream    struct arpreq arpreq;
172182c907af479178801a7a8701341b22c9d20fdb7Upstream
172282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (has_proxy_arp) {
172382c907af479178801a7a8701341b22c9d20fdb7Upstream	has_proxy_arp = 0;
172482c907af479178801a7a8701341b22c9d20fdb7Upstream	memset (&arpreq, '\0', sizeof(arpreq));
172582c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
172682c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(arpreq.arp_pa) = his_adr;
172782c907af479178801a7a8701341b22c9d20fdb7Upstream	arpreq.arp_flags = ATF_PERM | ATF_PUBL;
172882c907af479178801a7a8701341b22c9d20fdb7Upstream	strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
172982c907af479178801a7a8701341b22c9d20fdb7Upstream
173082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
173182c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ( ! ok_error ( errno ))
173282c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("ioctl(SIOCDARP): %m");
173382c907af479178801a7a8701341b22c9d20fdb7Upstream	    return 0;
173482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
173582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
173682c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
173782c907af479178801a7a8701341b22c9d20fdb7Upstream}
173882c907af479178801a7a8701341b22c9d20fdb7Upstream
173982c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
174082c907af479178801a7a8701341b22c9d20fdb7Upstream *
174182c907af479178801a7a8701341b22c9d20fdb7Upstream * get_ether_addr - get the hardware address of an interface on the
174282c907af479178801a7a8701341b22c9d20fdb7Upstream * the same subnet as ipaddr.
174382c907af479178801a7a8701341b22c9d20fdb7Upstream */
174482c907af479178801a7a8701341b22c9d20fdb7Upstream
174582c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int get_ether_addr (u_int32_t ipaddr,
174682c907af479178801a7a8701341b22c9d20fdb7Upstream			   struct sockaddr *hwaddr,
174782c907af479178801a7a8701341b22c9d20fdb7Upstream			   char *name, int namelen)
174882c907af479178801a7a8701341b22c9d20fdb7Upstream{
174982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq *ifr, *ifend;
175082c907af479178801a7a8701341b22c9d20fdb7Upstream    u_int32_t ina, mask;
175182c907af479178801a7a8701341b22c9d20fdb7Upstream    char *aliasp;
175282c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifreq, bestifreq;
175382c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifconf ifc;
175482c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifs[MAX_IFS];
175582c907af479178801a7a8701341b22c9d20fdb7Upstream
175682c907af479178801a7a8701341b22c9d20fdb7Upstream    u_int32_t bestmask=0;
175782c907af479178801a7a8701341b22c9d20fdb7Upstream    int found_interface = 0;
175882c907af479178801a7a8701341b22c9d20fdb7Upstream
175982c907af479178801a7a8701341b22c9d20fdb7Upstream    ifc.ifc_len = sizeof(ifs);
176082c907af479178801a7a8701341b22c9d20fdb7Upstream    ifc.ifc_req = ifs;
176182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
176282c907af479178801a7a8701341b22c9d20fdb7Upstream	if ( ! ok_error ( errno ))
176382c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
176482c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
176582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
176682c907af479178801a7a8701341b22c9d20fdb7Upstream
176782c907af479178801a7a8701341b22c9d20fdb7Upstream/*
176882c907af479178801a7a8701341b22c9d20fdb7Upstream * Scan through looking for an interface with an Internet
176982c907af479178801a7a8701341b22c9d20fdb7Upstream * address on the same subnet as `ipaddr'.
177082c907af479178801a7a8701341b22c9d20fdb7Upstream */
177182c907af479178801a7a8701341b22c9d20fdb7Upstream    ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
177282c907af479178801a7a8701341b22c9d20fdb7Upstream    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
177382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ifr->ifr_addr.sa_family == AF_INET) {
177482c907af479178801a7a8701341b22c9d20fdb7Upstream	    ina = SIN_ADDR(ifr->ifr_addr);
177582c907af479178801a7a8701341b22c9d20fdb7Upstream	    strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
177682c907af479178801a7a8701341b22c9d20fdb7Upstream/*
177782c907af479178801a7a8701341b22c9d20fdb7Upstream * Check that the interface is up, and not point-to-point
177882c907af479178801a7a8701341b22c9d20fdb7Upstream * nor loopback.
177982c907af479178801a7a8701341b22c9d20fdb7Upstream */
178082c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
178182c907af479178801a7a8701341b22c9d20fdb7Upstream		continue;
178282c907af479178801a7a8701341b22c9d20fdb7Upstream
178382c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
178482c907af479178801a7a8701341b22c9d20fdb7Upstream		continue;
178582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
178682c907af479178801a7a8701341b22c9d20fdb7Upstream * Get its netmask and check that it's on the right subnet.
178782c907af479178801a7a8701341b22c9d20fdb7Upstream */
178882c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
178982c907af479178801a7a8701341b22c9d20fdb7Upstream		continue;
179082c907af479178801a7a8701341b22c9d20fdb7Upstream
179182c907af479178801a7a8701341b22c9d20fdb7Upstream	    mask = SIN_ADDR(ifreq.ifr_addr);
179282c907af479178801a7a8701341b22c9d20fdb7Upstream
179382c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (((ipaddr ^ ina) & mask) != 0)
179482c907af479178801a7a8701341b22c9d20fdb7Upstream		continue; /* no match */
179582c907af479178801a7a8701341b22c9d20fdb7Upstream	    /* matched */
179682c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (mask >= bestmask) {
179782c907af479178801a7a8701341b22c9d20fdb7Upstream		/* Compare using >= instead of > -- it is possible for
179882c907af479178801a7a8701341b22c9d20fdb7Upstream		   an interface to have a netmask of 0.0.0.0 */
179982c907af479178801a7a8701341b22c9d20fdb7Upstream		found_interface = 1;
180082c907af479178801a7a8701341b22c9d20fdb7Upstream		bestifreq = ifreq;
180182c907af479178801a7a8701341b22c9d20fdb7Upstream		bestmask = mask;
180282c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
180382c907af479178801a7a8701341b22c9d20fdb7Upstream	}
180482c907af479178801a7a8701341b22c9d20fdb7Upstream    }
180582c907af479178801a7a8701341b22c9d20fdb7Upstream
180682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!found_interface) return 0;
180782c907af479178801a7a8701341b22c9d20fdb7Upstream
180882c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(name, bestifreq.ifr_name, namelen);
180982c907af479178801a7a8701341b22c9d20fdb7Upstream
181082c907af479178801a7a8701341b22c9d20fdb7Upstream    /* trim off the :1 in eth0:1 */
181182c907af479178801a7a8701341b22c9d20fdb7Upstream    aliasp = strchr(name, ':');
181282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (aliasp != 0)
181382c907af479178801a7a8701341b22c9d20fdb7Upstream	*aliasp = 0;
181482c907af479178801a7a8701341b22c9d20fdb7Upstream
181582c907af479178801a7a8701341b22c9d20fdb7Upstream    info("found interface %s for proxy arp", name);
181682c907af479178801a7a8701341b22c9d20fdb7Upstream/*
181782c907af479178801a7a8701341b22c9d20fdb7Upstream * Now get the hardware address.
181882c907af479178801a7a8701341b22c9d20fdb7Upstream */
181982c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&bestifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
182082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl (sock_fd, SIOCGIFHWADDR, &bestifreq) < 0) {
182182c907af479178801a7a8701341b22c9d20fdb7Upstream	error("SIOCGIFHWADDR(%s): %m", bestifreq.ifr_name);
182282c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
182382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
182482c907af479178801a7a8701341b22c9d20fdb7Upstream
182582c907af479178801a7a8701341b22c9d20fdb7Upstream    memcpy (hwaddr,
182682c907af479178801a7a8701341b22c9d20fdb7Upstream	    &bestifreq.ifr_hwaddr,
182782c907af479178801a7a8701341b22c9d20fdb7Upstream	    sizeof (struct sockaddr));
182882c907af479178801a7a8701341b22c9d20fdb7Upstream
182982c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
183082c907af479178801a7a8701341b22c9d20fdb7Upstream}
183182c907af479178801a7a8701341b22c9d20fdb7Upstream
183282c907af479178801a7a8701341b22c9d20fdb7Upstream/*
183382c907af479178801a7a8701341b22c9d20fdb7Upstream * get_if_hwaddr - get the hardware address for the specified
183482c907af479178801a7a8701341b22c9d20fdb7Upstream * network interface device.
183582c907af479178801a7a8701341b22c9d20fdb7Upstream */
183682c907af479178801a7a8701341b22c9d20fdb7Upstreamint
183782c907af479178801a7a8701341b22c9d20fdb7Upstreamget_if_hwaddr(u_char *addr, char *name)
183882c907af479178801a7a8701341b22c9d20fdb7Upstream{
183982c907af479178801a7a8701341b22c9d20fdb7Upstream	struct ifreq ifreq;
184082c907af479178801a7a8701341b22c9d20fdb7Upstream	int ret, sock_fd;
184182c907af479178801a7a8701341b22c9d20fdb7Upstream
184282c907af479178801a7a8701341b22c9d20fdb7Upstream	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
184382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (sock_fd < 0)
184482c907af479178801a7a8701341b22c9d20fdb7Upstream		return 0;
184582c907af479178801a7a8701341b22c9d20fdb7Upstream	memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
184682c907af479178801a7a8701341b22c9d20fdb7Upstream	strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
184782c907af479178801a7a8701341b22c9d20fdb7Upstream	ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
184882c907af479178801a7a8701341b22c9d20fdb7Upstream	close(sock_fd);
184982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ret >= 0)
185082c907af479178801a7a8701341b22c9d20fdb7Upstream		memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6);
185182c907af479178801a7a8701341b22c9d20fdb7Upstream	return ret;
185282c907af479178801a7a8701341b22c9d20fdb7Upstream}
185382c907af479178801a7a8701341b22c9d20fdb7Upstream
185482c907af479178801a7a8701341b22c9d20fdb7Upstream/*
185582c907af479178801a7a8701341b22c9d20fdb7Upstream * get_first_ethernet - return the name of the first ethernet-style
185682c907af479178801a7a8701341b22c9d20fdb7Upstream * interface on this system.
185782c907af479178801a7a8701341b22c9d20fdb7Upstream */
185882c907af479178801a7a8701341b22c9d20fdb7Upstreamchar *
185982c907af479178801a7a8701341b22c9d20fdb7Upstreamget_first_ethernet()
186082c907af479178801a7a8701341b22c9d20fdb7Upstream{
186182c907af479178801a7a8701341b22c9d20fdb7Upstream	return "eth0";
186282c907af479178801a7a8701341b22c9d20fdb7Upstream}
186382c907af479178801a7a8701341b22c9d20fdb7Upstream
186482c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
186582c907af479178801a7a8701341b22c9d20fdb7Upstream *
186682c907af479178801a7a8701341b22c9d20fdb7Upstream * Return user specified netmask, modified by any mask we might determine
186782c907af479178801a7a8701341b22c9d20fdb7Upstream * for address `addr' (in network byte order).
186882c907af479178801a7a8701341b22c9d20fdb7Upstream * Here we scan through the system's list of interfaces, looking for
186982c907af479178801a7a8701341b22c9d20fdb7Upstream * any non-point-to-point interfaces which might appear to be on the same
187082c907af479178801a7a8701341b22c9d20fdb7Upstream * network as `addr'.  If we find any, we OR in their netmask to the
187182c907af479178801a7a8701341b22c9d20fdb7Upstream * user-specified netmask.
187282c907af479178801a7a8701341b22c9d20fdb7Upstream */
187382c907af479178801a7a8701341b22c9d20fdb7Upstream
187482c907af479178801a7a8701341b22c9d20fdb7Upstreamu_int32_t GetMask (u_int32_t addr)
187582c907af479178801a7a8701341b22c9d20fdb7Upstream{
187682c907af479178801a7a8701341b22c9d20fdb7Upstream    u_int32_t mask, nmask, ina;
187782c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq *ifr, *ifend, ifreq;
187882c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifconf ifc;
187982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifs[MAX_IFS];
188082c907af479178801a7a8701341b22c9d20fdb7Upstream
188182c907af479178801a7a8701341b22c9d20fdb7Upstream    addr = ntohl(addr);
188282c907af479178801a7a8701341b22c9d20fdb7Upstream
188382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (IN_CLASSA(addr))	/* determine network mask for address class */
188482c907af479178801a7a8701341b22c9d20fdb7Upstream	nmask = IN_CLASSA_NET;
188582c907af479178801a7a8701341b22c9d20fdb7Upstream    else if (IN_CLASSB(addr))
188682c907af479178801a7a8701341b22c9d20fdb7Upstream	    nmask = IN_CLASSB_NET;
188782c907af479178801a7a8701341b22c9d20fdb7Upstream    else
188882c907af479178801a7a8701341b22c9d20fdb7Upstream	    nmask = IN_CLASSC_NET;
188982c907af479178801a7a8701341b22c9d20fdb7Upstream
189082c907af479178801a7a8701341b22c9d20fdb7Upstream    /* class D nets are disallowed by bad_ip_adrs */
189182c907af479178801a7a8701341b22c9d20fdb7Upstream    mask = netmask | htonl(nmask);
189282c907af479178801a7a8701341b22c9d20fdb7Upstream/*
189382c907af479178801a7a8701341b22c9d20fdb7Upstream * Scan through the system's network interfaces.
189482c907af479178801a7a8701341b22c9d20fdb7Upstream */
189582c907af479178801a7a8701341b22c9d20fdb7Upstream    ifc.ifc_len = sizeof(ifs);
189682c907af479178801a7a8701341b22c9d20fdb7Upstream    ifc.ifc_req = ifs;
189782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
189882c907af479178801a7a8701341b22c9d20fdb7Upstream	if ( ! ok_error ( errno ))
189982c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
190082c907af479178801a7a8701341b22c9d20fdb7Upstream	return mask;
190182c907af479178801a7a8701341b22c9d20fdb7Upstream    }
190282c907af479178801a7a8701341b22c9d20fdb7Upstream
190382c907af479178801a7a8701341b22c9d20fdb7Upstream    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
190482c907af479178801a7a8701341b22c9d20fdb7Upstream    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
190582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
190682c907af479178801a7a8701341b22c9d20fdb7Upstream * Check the interface's internet address.
190782c907af479178801a7a8701341b22c9d20fdb7Upstream */
190882c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ifr->ifr_addr.sa_family != AF_INET)
190982c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
191082c907af479178801a7a8701341b22c9d20fdb7Upstream	ina = SIN_ADDR(ifr->ifr_addr);
191182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (((ntohl(ina) ^ addr) & nmask) != 0)
191282c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
191382c907af479178801a7a8701341b22c9d20fdb7Upstream/*
191482c907af479178801a7a8701341b22c9d20fdb7Upstream * Check that the interface is up, and not point-to-point nor loopback.
191582c907af479178801a7a8701341b22c9d20fdb7Upstream */
191682c907af479178801a7a8701341b22c9d20fdb7Upstream	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
191782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
191882c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
191982c907af479178801a7a8701341b22c9d20fdb7Upstream
192082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
192182c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
192282c907af479178801a7a8701341b22c9d20fdb7Upstream/*
192382c907af479178801a7a8701341b22c9d20fdb7Upstream * Get its netmask and OR it into our mask.
192482c907af479178801a7a8701341b22c9d20fdb7Upstream */
192582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
192682c907af479178801a7a8701341b22c9d20fdb7Upstream	    continue;
192782c907af479178801a7a8701341b22c9d20fdb7Upstream	mask |= SIN_ADDR(ifreq.ifr_addr);
192882c907af479178801a7a8701341b22c9d20fdb7Upstream	break;
192982c907af479178801a7a8701341b22c9d20fdb7Upstream    }
193082c907af479178801a7a8701341b22c9d20fdb7Upstream    return mask;
193182c907af479178801a7a8701341b22c9d20fdb7Upstream}
193282c907af479178801a7a8701341b22c9d20fdb7Upstream
193382c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
193482c907af479178801a7a8701341b22c9d20fdb7Upstream *
193582c907af479178801a7a8701341b22c9d20fdb7Upstream * Internal routine to decode the version.modification.patch level
193682c907af479178801a7a8701341b22c9d20fdb7Upstream */
193782c907af479178801a7a8701341b22c9d20fdb7Upstream
193882c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic void decode_version (char *buf, int *version,
193982c907af479178801a7a8701341b22c9d20fdb7Upstream			    int *modification, int *patch)
194082c907af479178801a7a8701341b22c9d20fdb7Upstream{
194182c907af479178801a7a8701341b22c9d20fdb7Upstream    char *endp;
194282c907af479178801a7a8701341b22c9d20fdb7Upstream
194382c907af479178801a7a8701341b22c9d20fdb7Upstream    *version      = (int) strtoul (buf, &endp, 10);
194482c907af479178801a7a8701341b22c9d20fdb7Upstream    *modification = 0;
194582c907af479178801a7a8701341b22c9d20fdb7Upstream    *patch        = 0;
194682c907af479178801a7a8701341b22c9d20fdb7Upstream
194782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (endp != buf && *endp == '.') {
194882c907af479178801a7a8701341b22c9d20fdb7Upstream	buf = endp + 1;
194982c907af479178801a7a8701341b22c9d20fdb7Upstream	*modification = (int) strtoul (buf, &endp, 10);
195082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (endp != buf && *endp == '.') {
195182c907af479178801a7a8701341b22c9d20fdb7Upstream	    buf = endp + 1;
195282c907af479178801a7a8701341b22c9d20fdb7Upstream	    *patch = (int) strtoul (buf, &buf, 10);
195382c907af479178801a7a8701341b22c9d20fdb7Upstream	}
195482c907af479178801a7a8701341b22c9d20fdb7Upstream    }
195582c907af479178801a7a8701341b22c9d20fdb7Upstream}
195682c907af479178801a7a8701341b22c9d20fdb7Upstream
195782c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
195882c907af479178801a7a8701341b22c9d20fdb7Upstream *
195982c907af479178801a7a8701341b22c9d20fdb7Upstream * Procedure to determine if the PPP line discipline is registered.
196082c907af479178801a7a8701341b22c9d20fdb7Upstream */
196182c907af479178801a7a8701341b22c9d20fdb7Upstream
196282c907af479178801a7a8701341b22c9d20fdb7Upstreamstatic int
196382c907af479178801a7a8701341b22c9d20fdb7Upstreamppp_registered(void)
196482c907af479178801a7a8701341b22c9d20fdb7Upstream{
196582c907af479178801a7a8701341b22c9d20fdb7Upstream    int local_fd;
196682c907af479178801a7a8701341b22c9d20fdb7Upstream    int mfd = -1;
196782c907af479178801a7a8701341b22c9d20fdb7Upstream    int ret = 0;
196882c907af479178801a7a8701341b22c9d20fdb7Upstream    char slave[16];
196982c907af479178801a7a8701341b22c9d20fdb7Upstream
197082c907af479178801a7a8701341b22c9d20fdb7Upstream    /*
197182c907af479178801a7a8701341b22c9d20fdb7Upstream     * We used to open the serial device and set it to the ppp line
197282c907af479178801a7a8701341b22c9d20fdb7Upstream     * discipline here, in order to create a ppp unit.  But that is
197382c907af479178801a7a8701341b22c9d20fdb7Upstream     * not a good idea - the user might have specified a device that
197482c907af479178801a7a8701341b22c9d20fdb7Upstream     * they can't open (permission, or maybe it doesn't really exist).
197582c907af479178801a7a8701341b22c9d20fdb7Upstream     * So we grab a pty master/slave pair and use that.
197682c907af479178801a7a8701341b22c9d20fdb7Upstream     */
197782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!get_pty(&mfd, &local_fd, slave, 0)) {
197882c907af479178801a7a8701341b22c9d20fdb7Upstream	no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";
197982c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
198082c907af479178801a7a8701341b22c9d20fdb7Upstream    }
198182c907af479178801a7a8701341b22c9d20fdb7Upstream
198282c907af479178801a7a8701341b22c9d20fdb7Upstream    /*
198382c907af479178801a7a8701341b22c9d20fdb7Upstream     * Try to put the device into the PPP discipline.
198482c907af479178801a7a8701341b22c9d20fdb7Upstream     */
198582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
198682c907af479178801a7a8701341b22c9d20fdb7Upstream	error("ioctl(TIOCSETD(PPP)): %m (line %d)", __LINE__);
198782c907af479178801a7a8701341b22c9d20fdb7Upstream    } else
198882c907af479178801a7a8701341b22c9d20fdb7Upstream	ret = 1;
198982c907af479178801a7a8701341b22c9d20fdb7Upstream
199082c907af479178801a7a8701341b22c9d20fdb7Upstream    close(local_fd);
199182c907af479178801a7a8701341b22c9d20fdb7Upstream    close(mfd);
199282c907af479178801a7a8701341b22c9d20fdb7Upstream    return ret;
199382c907af479178801a7a8701341b22c9d20fdb7Upstream}
199482c907af479178801a7a8701341b22c9d20fdb7Upstream
199582c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
199682c907af479178801a7a8701341b22c9d20fdb7Upstream *
199782c907af479178801a7a8701341b22c9d20fdb7Upstream * ppp_available - check whether the system has any ppp interfaces
199882c907af479178801a7a8701341b22c9d20fdb7Upstream * (in fact we check whether we can do an ioctl on ppp0).
199982c907af479178801a7a8701341b22c9d20fdb7Upstream */
200082c907af479178801a7a8701341b22c9d20fdb7Upstream
200182c907af479178801a7a8701341b22c9d20fdb7Upstreamint ppp_available(void)
200282c907af479178801a7a8701341b22c9d20fdb7Upstream{
200382c907af479178801a7a8701341b22c9d20fdb7Upstream    int s, ok, fd;
200482c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
200582c907af479178801a7a8701341b22c9d20fdb7Upstream    int    size;
200682c907af479178801a7a8701341b22c9d20fdb7Upstream    int    my_version, my_modification, my_patch;
200782c907af479178801a7a8701341b22c9d20fdb7Upstream    int osmaj, osmin, ospatch;
200882c907af479178801a7a8701341b22c9d20fdb7Upstream
200982c907af479178801a7a8701341b22c9d20fdb7Upstream    no_ppp_msg =
201082c907af479178801a7a8701341b22c9d20fdb7Upstream	"This system lacks kernel support for PPP.  This could be because\n"
201182c907af479178801a7a8701341b22c9d20fdb7Upstream	"the PPP kernel module could not be loaded, or because PPP was not\n"
201282c907af479178801a7a8701341b22c9d20fdb7Upstream	"included in the kernel configuration.  If PPP was included as a\n"
201382c907af479178801a7a8701341b22c9d20fdb7Upstream	"module, try `/sbin/modprobe -v ppp'.  If that fails, check that\n"
201482c907af479178801a7a8701341b22c9d20fdb7Upstream	"ppp.o exists in /lib/modules/`uname -r`/net.\n"
201582c907af479178801a7a8701341b22c9d20fdb7Upstream	"See README.linux file in the ppp distribution for more details.\n";
201682c907af479178801a7a8701341b22c9d20fdb7Upstream
201782c907af479178801a7a8701341b22c9d20fdb7Upstream    /* get the kernel version now, since we are called before sys_init */
201882c907af479178801a7a8701341b22c9d20fdb7Upstream    uname(&utsname);
201982c907af479178801a7a8701341b22c9d20fdb7Upstream    osmaj = osmin = ospatch = 0;
202082c907af479178801a7a8701341b22c9d20fdb7Upstream    sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
202182c907af479178801a7a8701341b22c9d20fdb7Upstream    kernel_version = KVERSION(osmaj, osmin, ospatch);
202282c907af479178801a7a8701341b22c9d20fdb7Upstream
202382c907af479178801a7a8701341b22c9d20fdb7Upstream    fd = open("/dev/ppp", O_RDWR);
202482c907af479178801a7a8701341b22c9d20fdb7Upstream#if 0
202582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (fd < 0 && errno == ENOENT) {
202682c907af479178801a7a8701341b22c9d20fdb7Upstream	/* try making it and see if that helps. */
202782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR,
202882c907af479178801a7a8701341b22c9d20fdb7Upstream		  makedev(108, 0)) >= 0) {
202982c907af479178801a7a8701341b22c9d20fdb7Upstream	    fd = open("/dev/ppp", O_RDWR);
203082c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (fd >= 0)
203182c907af479178801a7a8701341b22c9d20fdb7Upstream		info("Created /dev/ppp device node");
203282c907af479178801a7a8701341b22c9d20fdb7Upstream	    else
203382c907af479178801a7a8701341b22c9d20fdb7Upstream		unlink("/dev/ppp");	/* didn't work, undo the mknod */
203482c907af479178801a7a8701341b22c9d20fdb7Upstream	} else if (errno == EEXIST) {
203582c907af479178801a7a8701341b22c9d20fdb7Upstream	    fd = open("/dev/ppp", O_RDWR);
203682c907af479178801a7a8701341b22c9d20fdb7Upstream	}
203782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
203882c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* 0 */
203982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (fd >= 0) {
204082c907af479178801a7a8701341b22c9d20fdb7Upstream	new_style_driver = 1;
204182c907af479178801a7a8701341b22c9d20fdb7Upstream
204282c907af479178801a7a8701341b22c9d20fdb7Upstream	/* XXX should get from driver */
204382c907af479178801a7a8701341b22c9d20fdb7Upstream	driver_version = 2;
204482c907af479178801a7a8701341b22c9d20fdb7Upstream	driver_modification = 4;
204582c907af479178801a7a8701341b22c9d20fdb7Upstream	driver_patch = 0;
204682c907af479178801a7a8701341b22c9d20fdb7Upstream	close(fd);
204782c907af479178801a7a8701341b22c9d20fdb7Upstream	return 1;
204882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
204982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (kernel_version >= KVERSION(2,3,13)) {
205082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (errno == ENOENT)
205182c907af479178801a7a8701341b22c9d20fdb7Upstream	    no_ppp_msg =
205282c907af479178801a7a8701341b22c9d20fdb7Upstream		"pppd is unable to open the /dev/ppp device.\n"
205382c907af479178801a7a8701341b22c9d20fdb7Upstream		"You need to create the /dev/ppp device node by\n"
205482c907af479178801a7a8701341b22c9d20fdb7Upstream		"executing the following command as root:\n"
205582c907af479178801a7a8701341b22c9d20fdb7Upstream		"	mknod /dev/ppp c 108 0\n";
205682c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
205782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
205882c907af479178801a7a8701341b22c9d20fdb7Upstream
205982c907af479178801a7a8701341b22c9d20fdb7Upstream/*
206082c907af479178801a7a8701341b22c9d20fdb7Upstream * Open a socket for doing the ioctl operations.
206182c907af479178801a7a8701341b22c9d20fdb7Upstream */
206282c907af479178801a7a8701341b22c9d20fdb7Upstream    s = socket(AF_INET, SOCK_DGRAM, 0);
206382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (s < 0)
206482c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
206582c907af479178801a7a8701341b22c9d20fdb7Upstream
206682c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
206782c907af479178801a7a8701341b22c9d20fdb7Upstream    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
206882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
206982c907af479178801a7a8701341b22c9d20fdb7Upstream * If the device did not exist then attempt to create one by putting the
207082c907af479178801a7a8701341b22c9d20fdb7Upstream * current tty into the PPP discipline. If this works then obtain the
207182c907af479178801a7a8701341b22c9d20fdb7Upstream * flags for the device again.
207282c907af479178801a7a8701341b22c9d20fdb7Upstream */
207382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!ok) {
207482c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ppp_registered()) {
207582c907af479178801a7a8701341b22c9d20fdb7Upstream	    strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
207682c907af479178801a7a8701341b22c9d20fdb7Upstream	    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
207782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
207882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
207982c907af479178801a7a8701341b22c9d20fdb7Upstream/*
208082c907af479178801a7a8701341b22c9d20fdb7Upstream * Ensure that the hardware address is for PPP and not something else
208182c907af479178801a7a8701341b22c9d20fdb7Upstream */
208282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ok)
208382c907af479178801a7a8701341b22c9d20fdb7Upstream	ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
208482c907af479178801a7a8701341b22c9d20fdb7Upstream
208582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
208682c907af479178801a7a8701341b22c9d20fdb7Upstream	ok = 0;
208782c907af479178801a7a8701341b22c9d20fdb7Upstream
208882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
208982c907af479178801a7a8701341b22c9d20fdb7Upstream *  This is the PPP device. Validate the version of the driver at this
209082c907af479178801a7a8701341b22c9d20fdb7Upstream *  point to ensure that this program will work with the driver.
209182c907af479178801a7a8701341b22c9d20fdb7Upstream */
209282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ok) {
209382c907af479178801a7a8701341b22c9d20fdb7Upstream	char   abBuffer [1024];
209482c907af479178801a7a8701341b22c9d20fdb7Upstream
209582c907af479178801a7a8701341b22c9d20fdb7Upstream	ifr.ifr_data = abBuffer;
209682c907af479178801a7a8701341b22c9d20fdb7Upstream	size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
209782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (size < 0) {
209882c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("Couldn't read driver version: %m");
209982c907af479178801a7a8701341b22c9d20fdb7Upstream	    ok = 0;
210082c907af479178801a7a8701341b22c9d20fdb7Upstream	    no_ppp_msg = "Sorry, couldn't verify kernel driver version\n";
210182c907af479178801a7a8701341b22c9d20fdb7Upstream
210282c907af479178801a7a8701341b22c9d20fdb7Upstream	} else {
210382c907af479178801a7a8701341b22c9d20fdb7Upstream	    decode_version(abBuffer,
210482c907af479178801a7a8701341b22c9d20fdb7Upstream			   &driver_version,
210582c907af479178801a7a8701341b22c9d20fdb7Upstream			   &driver_modification,
210682c907af479178801a7a8701341b22c9d20fdb7Upstream			   &driver_patch);
210782c907af479178801a7a8701341b22c9d20fdb7Upstream/*
210882c907af479178801a7a8701341b22c9d20fdb7Upstream * Validate the version of the driver against the version that we used.
210982c907af479178801a7a8701341b22c9d20fdb7Upstream */
211082c907af479178801a7a8701341b22c9d20fdb7Upstream	    decode_version(VERSION,
211182c907af479178801a7a8701341b22c9d20fdb7Upstream			   &my_version,
211282c907af479178801a7a8701341b22c9d20fdb7Upstream			   &my_modification,
211382c907af479178801a7a8701341b22c9d20fdb7Upstream			   &my_patch);
211482c907af479178801a7a8701341b22c9d20fdb7Upstream
211582c907af479178801a7a8701341b22c9d20fdb7Upstream	    /* The version numbers must match */
211682c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (driver_version != my_version)
211782c907af479178801a7a8701341b22c9d20fdb7Upstream		ok = 0;
211882c907af479178801a7a8701341b22c9d20fdb7Upstream
211982c907af479178801a7a8701341b22c9d20fdb7Upstream	    /* The modification levels must be legal */
212082c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (driver_modification < 3) {
212182c907af479178801a7a8701341b22c9d20fdb7Upstream		if (driver_modification >= 2) {
212282c907af479178801a7a8701341b22c9d20fdb7Upstream		    /* we can cope with 2.2.0 and above */
212382c907af479178801a7a8701341b22c9d20fdb7Upstream		    driver_is_old = 1;
212482c907af479178801a7a8701341b22c9d20fdb7Upstream		} else {
212582c907af479178801a7a8701341b22c9d20fdb7Upstream		    ok = 0;
212682c907af479178801a7a8701341b22c9d20fdb7Upstream		}
212782c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
212882c907af479178801a7a8701341b22c9d20fdb7Upstream
212982c907af479178801a7a8701341b22c9d20fdb7Upstream	    close (s);
213082c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (!ok) {
213182c907af479178801a7a8701341b22c9d20fdb7Upstream		slprintf(route_buffer, sizeof(route_buffer),
213282c907af479178801a7a8701341b22c9d20fdb7Upstream			 "Sorry - PPP driver version %d.%d.%d is out of date\n",
213382c907af479178801a7a8701341b22c9d20fdb7Upstream			 driver_version, driver_modification, driver_patch);
213482c907af479178801a7a8701341b22c9d20fdb7Upstream
213582c907af479178801a7a8701341b22c9d20fdb7Upstream		no_ppp_msg = route_buffer;
213682c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
213782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
213882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
213982c907af479178801a7a8701341b22c9d20fdb7Upstream    return ok;
214082c907af479178801a7a8701341b22c9d20fdb7Upstream}
214182c907af479178801a7a8701341b22c9d20fdb7Upstream
214282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
214382c907af479178801a7a8701341b22c9d20fdb7Upstream *
214482c907af479178801a7a8701341b22c9d20fdb7Upstream * Update the wtmp file with the appropriate user name and tty device.
214582c907af479178801a7a8701341b22c9d20fdb7Upstream */
214682c907af479178801a7a8701341b22c9d20fdb7Upstream
214782c907af479178801a7a8701341b22c9d20fdb7Upstreamvoid logwtmp (const char *line, const char *name, const char *host)
214882c907af479178801a7a8701341b22c9d20fdb7Upstream{
214982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct utmp ut, *utp;
215082c907af479178801a7a8701341b22c9d20fdb7Upstream    pid_t  mypid = getpid();
215182c907af479178801a7a8701341b22c9d20fdb7Upstream#if __GLIBC__ < 2
215282c907af479178801a7a8701341b22c9d20fdb7Upstream    int    wtmp;
215382c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
215482c907af479178801a7a8701341b22c9d20fdb7Upstream
215582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
215682c907af479178801a7a8701341b22c9d20fdb7Upstream * Update the signon database for users.
215782c907af479178801a7a8701341b22c9d20fdb7Upstream * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
215882c907af479178801a7a8701341b22c9d20fdb7Upstream */
215982c907af479178801a7a8701341b22c9d20fdb7Upstream    utmpname(_PATH_UTMP);
216082c907af479178801a7a8701341b22c9d20fdb7Upstream    setutent();
216182c907af479178801a7a8701341b22c9d20fdb7Upstream    while ((utp = getutent()) && (utp->ut_pid != mypid))
216282c907af479178801a7a8701341b22c9d20fdb7Upstream	/* nothing */;
216382c907af479178801a7a8701341b22c9d20fdb7Upstream
216482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (utp)
216582c907af479178801a7a8701341b22c9d20fdb7Upstream	memcpy(&ut, utp, sizeof(ut));
216682c907af479178801a7a8701341b22c9d20fdb7Upstream    else
216782c907af479178801a7a8701341b22c9d20fdb7Upstream	/* some gettys/telnetds don't initialize utmp... */
216882c907af479178801a7a8701341b22c9d20fdb7Upstream	memset(&ut, 0, sizeof(ut));
216982c907af479178801a7a8701341b22c9d20fdb7Upstream
217082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ut.ut_id[0] == 0)
217182c907af479178801a7a8701341b22c9d20fdb7Upstream	strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
217282c907af479178801a7a8701341b22c9d20fdb7Upstream
217382c907af479178801a7a8701341b22c9d20fdb7Upstream    strncpy(ut.ut_user, name, sizeof(ut.ut_user));
217482c907af479178801a7a8701341b22c9d20fdb7Upstream    strncpy(ut.ut_line, line, sizeof(ut.ut_line));
217582c907af479178801a7a8701341b22c9d20fdb7Upstream
217682c907af479178801a7a8701341b22c9d20fdb7Upstream    time(&ut.ut_time);
217782c907af479178801a7a8701341b22c9d20fdb7Upstream
217882c907af479178801a7a8701341b22c9d20fdb7Upstream    ut.ut_type = USER_PROCESS;
217982c907af479178801a7a8701341b22c9d20fdb7Upstream    ut.ut_pid  = mypid;
218082c907af479178801a7a8701341b22c9d20fdb7Upstream
218182c907af479178801a7a8701341b22c9d20fdb7Upstream    /* Insert the host name if one is supplied */
218282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (*host)
218382c907af479178801a7a8701341b22c9d20fdb7Upstream	strncpy (ut.ut_host, host, sizeof(ut.ut_host));
218482c907af479178801a7a8701341b22c9d20fdb7Upstream
218582c907af479178801a7a8701341b22c9d20fdb7Upstream    /* Insert the IP address of the remote system if IP is enabled */
218682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
218782c907af479178801a7a8701341b22c9d20fdb7Upstream	memcpy(&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
218882c907af479178801a7a8701341b22c9d20fdb7Upstream		 sizeof(ut.ut_addr));
218982c907af479178801a7a8701341b22c9d20fdb7Upstream
219082c907af479178801a7a8701341b22c9d20fdb7Upstream    /* CL: Makes sure that the logout works */
219182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (*host == 0 && *name==0)
219282c907af479178801a7a8701341b22c9d20fdb7Upstream	ut.ut_host[0]=0;
219382c907af479178801a7a8701341b22c9d20fdb7Upstream
219482c907af479178801a7a8701341b22c9d20fdb7Upstream    pututline(&ut);
219582c907af479178801a7a8701341b22c9d20fdb7Upstream    endutent();
219682c907af479178801a7a8701341b22c9d20fdb7Upstream/*
219782c907af479178801a7a8701341b22c9d20fdb7Upstream * Update the wtmp file.
219882c907af479178801a7a8701341b22c9d20fdb7Upstream */
219982c907af479178801a7a8701341b22c9d20fdb7Upstream#if __GLIBC__ >= 2
220082c907af479178801a7a8701341b22c9d20fdb7Upstream    updwtmp(_PATH_WTMP, &ut);
220182c907af479178801a7a8701341b22c9d20fdb7Upstream#else
220282c907af479178801a7a8701341b22c9d20fdb7Upstream    wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
220382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (wtmp >= 0) {
220482c907af479178801a7a8701341b22c9d20fdb7Upstream	flock(wtmp, LOCK_EX);
220582c907af479178801a7a8701341b22c9d20fdb7Upstream
220682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (write (wtmp, (char *)&ut, sizeof(ut)) != sizeof(ut))
220782c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("error writing %s: %m", _PATH_WTMP);
220882c907af479178801a7a8701341b22c9d20fdb7Upstream
220982c907af479178801a7a8701341b22c9d20fdb7Upstream	flock(wtmp, LOCK_UN);
221082c907af479178801a7a8701341b22c9d20fdb7Upstream
221182c907af479178801a7a8701341b22c9d20fdb7Upstream	close (wtmp);
221282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
221382c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
221482c907af479178801a7a8701341b22c9d20fdb7Upstream}
221582c907af479178801a7a8701341b22c9d20fdb7Upstream
221682c907af479178801a7a8701341b22c9d20fdb7Upstream
221782c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
221882c907af479178801a7a8701341b22c9d20fdb7Upstream *
221982c907af479178801a7a8701341b22c9d20fdb7Upstream * sifvjcomp - config tcp header compression
222082c907af479178801a7a8701341b22c9d20fdb7Upstream */
222182c907af479178801a7a8701341b22c9d20fdb7Upstream
222282c907af479178801a7a8701341b22c9d20fdb7Upstreamint sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
222382c907af479178801a7a8701341b22c9d20fdb7Upstream{
222482c907af479178801a7a8701341b22c9d20fdb7Upstream	u_int x;
222582c907af479178801a7a8701341b22c9d20fdb7Upstream
222682c907af479178801a7a8701341b22c9d20fdb7Upstream	if (vjcomp) {
222782c907af479178801a7a8701341b22c9d20fdb7Upstream		if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
222882c907af479178801a7a8701341b22c9d20fdb7Upstream			error("Couldn't set up TCP header compression: %m");
222982c907af479178801a7a8701341b22c9d20fdb7Upstream		vjcomp = 0;
223082c907af479178801a7a8701341b22c9d20fdb7Upstream	}
223182c907af479178801a7a8701341b22c9d20fdb7Upstream
223282c907af479178801a7a8701341b22c9d20fdb7Upstream	x = (vjcomp? SC_COMP_TCP: 0) | (cidcomp? 0: SC_NO_TCP_CCID);
223382c907af479178801a7a8701341b22c9d20fdb7Upstream	modify_flags(ppp_dev_fd, SC_COMP_TCP|SC_NO_TCP_CCID, x);
223482c907af479178801a7a8701341b22c9d20fdb7Upstream
223582c907af479178801a7a8701341b22c9d20fdb7Upstream	return 1;
223682c907af479178801a7a8701341b22c9d20fdb7Upstream}
223782c907af479178801a7a8701341b22c9d20fdb7Upstream
223882c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
223982c907af479178801a7a8701341b22c9d20fdb7Upstream *
224082c907af479178801a7a8701341b22c9d20fdb7Upstream * sifup - Config the interface up and enable IP packets to pass.
224182c907af479178801a7a8701341b22c9d20fdb7Upstream */
224282c907af479178801a7a8701341b22c9d20fdb7Upstream
224382c907af479178801a7a8701341b22c9d20fdb7Upstreamint sifup(int u)
224482c907af479178801a7a8701341b22c9d20fdb7Upstream{
224582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
224682c907af479178801a7a8701341b22c9d20fdb7Upstream
224782c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&ifr, '\0', sizeof (ifr));
224882c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
224982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
225082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
225182c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl (SIOCGIFFLAGS): %m (line %d)", __LINE__);
225282c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
225382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
225482c907af479178801a7a8701341b22c9d20fdb7Upstream
225582c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
225682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
225782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
225882c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl(SIOCSIFFLAGS): %m (line %d)", __LINE__);
225982c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
226082c907af479178801a7a8701341b22c9d20fdb7Upstream    }
226182c907af479178801a7a8701341b22c9d20fdb7Upstream    if_is_up++;
226282c907af479178801a7a8701341b22c9d20fdb7Upstream
226382c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
226482c907af479178801a7a8701341b22c9d20fdb7Upstream}
226582c907af479178801a7a8701341b22c9d20fdb7Upstream
226682c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
226782c907af479178801a7a8701341b22c9d20fdb7Upstream *
226882c907af479178801a7a8701341b22c9d20fdb7Upstream * sifdown - Disable the indicated protocol and config the interface
226982c907af479178801a7a8701341b22c9d20fdb7Upstream *	     down if there are no remaining protocols.
227082c907af479178801a7a8701341b22c9d20fdb7Upstream */
227182c907af479178801a7a8701341b22c9d20fdb7Upstream
227282c907af479178801a7a8701341b22c9d20fdb7Upstreamint sifdown (int u)
227382c907af479178801a7a8701341b22c9d20fdb7Upstream{
227482c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
227582c907af479178801a7a8701341b22c9d20fdb7Upstream
227682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (if_is_up && --if_is_up > 0)
227782c907af479178801a7a8701341b22c9d20fdb7Upstream	return 1;
227882c907af479178801a7a8701341b22c9d20fdb7Upstream
227982c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&ifr, '\0', sizeof (ifr));
228082c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
228182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
228282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
228382c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl (SIOCGIFFLAGS): %m (line %d)", __LINE__);
228482c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
228582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
228682c907af479178801a7a8701341b22c9d20fdb7Upstream
228782c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr.ifr_flags &= ~IFF_UP;
228882c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr.ifr_flags |= IFF_POINTOPOINT;
228982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
229082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
229182c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl(SIOCSIFFLAGS): %m (line %d)", __LINE__);
229282c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
229382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
229482c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
229582c907af479178801a7a8701341b22c9d20fdb7Upstream}
229682c907af479178801a7a8701341b22c9d20fdb7Upstream
229782c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
229882c907af479178801a7a8701341b22c9d20fdb7Upstream *
229982c907af479178801a7a8701341b22c9d20fdb7Upstream * sifaddr - Config the interface IP addresses and netmask.
230082c907af479178801a7a8701341b22c9d20fdb7Upstream */
230182c907af479178801a7a8701341b22c9d20fdb7Upstream
230282c907af479178801a7a8701341b22c9d20fdb7Upstreamint sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
230382c907af479178801a7a8701341b22c9d20fdb7Upstream	     u_int32_t net_mask)
230482c907af479178801a7a8701341b22c9d20fdb7Upstream{
230582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq   ifr;
230682c907af479178801a7a8701341b22c9d20fdb7Upstream    struct rtentry rt;
230782c907af479178801a7a8701341b22c9d20fdb7Upstream
230882c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&ifr, '\0', sizeof (ifr));
230982c907af479178801a7a8701341b22c9d20fdb7Upstream    memset (&rt,  '\0', sizeof (rt));
231082c907af479178801a7a8701341b22c9d20fdb7Upstream
231182c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY (ifr.ifr_addr,    AF_INET);
231282c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
231382c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
231482c907af479178801a7a8701341b22c9d20fdb7Upstream
231582c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
231682c907af479178801a7a8701341b22c9d20fdb7Upstream/*
231782c907af479178801a7a8701341b22c9d20fdb7Upstream *  Set our IP address
231882c907af479178801a7a8701341b22c9d20fdb7Upstream */
231982c907af479178801a7a8701341b22c9d20fdb7Upstream    SIN_ADDR(ifr.ifr_addr) = our_adr;
232082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
232182c907af479178801a7a8701341b22c9d20fdb7Upstream	if (errno != EEXIST) {
232282c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (! ok_error (errno))
232382c907af479178801a7a8701341b22c9d20fdb7Upstream		error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
232482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
232582c907af479178801a7a8701341b22c9d20fdb7Upstream	else {
232682c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("ioctl(SIOCSIFADDR): Address already exists");
232782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
232882c907af479178801a7a8701341b22c9d20fdb7Upstream	return (0);
232982c907af479178801a7a8701341b22c9d20fdb7Upstream    }
233082c907af479178801a7a8701341b22c9d20fdb7Upstream/*
233182c907af479178801a7a8701341b22c9d20fdb7Upstream *  Set the gateway address
233282c907af479178801a7a8701341b22c9d20fdb7Upstream */
233382c907af479178801a7a8701341b22c9d20fdb7Upstream    SIN_ADDR(ifr.ifr_dstaddr) = his_adr;
233482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
233582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
233682c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl(SIOCSIFDSTADDR): %m (line %d)", __LINE__);
233782c907af479178801a7a8701341b22c9d20fdb7Upstream	return (0);
233882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
233982c907af479178801a7a8701341b22c9d20fdb7Upstream/*
234082c907af479178801a7a8701341b22c9d20fdb7Upstream *  Set the netmask.
234182c907af479178801a7a8701341b22c9d20fdb7Upstream *  For recent kernels, force the netmask to 255.255.255.255.
234282c907af479178801a7a8701341b22c9d20fdb7Upstream */
234382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (kernel_version >= KVERSION(2,1,16))
234482c907af479178801a7a8701341b22c9d20fdb7Upstream	net_mask = ~0L;
234582c907af479178801a7a8701341b22c9d20fdb7Upstream    if (net_mask != 0) {
234682c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(ifr.ifr_netmask) = net_mask;
234782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
234882c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (! ok_error (errno))
234982c907af479178801a7a8701341b22c9d20fdb7Upstream		error("ioctl(SIOCSIFNETMASK): %m (line %d)", __LINE__);
235082c907af479178801a7a8701341b22c9d20fdb7Upstream	    return (0);
235182c907af479178801a7a8701341b22c9d20fdb7Upstream	}
235282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
235382c907af479178801a7a8701341b22c9d20fdb7Upstream/*
235482c907af479178801a7a8701341b22c9d20fdb7Upstream *  Add the device route
235582c907af479178801a7a8701341b22c9d20fdb7Upstream */
235682c907af479178801a7a8701341b22c9d20fdb7Upstream    if (kernel_version < KVERSION(2,1,16)) {
235782c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY (rt.rt_dst,     AF_INET);
235882c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY (rt.rt_gateway, AF_INET);
235982c907af479178801a7a8701341b22c9d20fdb7Upstream	rt.rt_dev = ifname;
236082c907af479178801a7a8701341b22c9d20fdb7Upstream
236182c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(rt.rt_gateway) = 0L;
236282c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(rt.rt_dst)     = his_adr;
236382c907af479178801a7a8701341b22c9d20fdb7Upstream	rt.rt_flags = RTF_UP | RTF_HOST;
236482c907af479178801a7a8701341b22c9d20fdb7Upstream
236582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (kernel_version > KVERSION(2,1,0)) {
236682c907af479178801a7a8701341b22c9d20fdb7Upstream	    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
236782c907af479178801a7a8701341b22c9d20fdb7Upstream	    SIN_ADDR(rt.rt_genmask) = -1L;
236882c907af479178801a7a8701341b22c9d20fdb7Upstream	}
236982c907af479178801a7a8701341b22c9d20fdb7Upstream
237082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
237182c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (! ok_error (errno))
237282c907af479178801a7a8701341b22c9d20fdb7Upstream		error("ioctl(SIOCADDRT) device route: %m (line %d)", __LINE__);
237382c907af479178801a7a8701341b22c9d20fdb7Upstream	    return (0);
237482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
237582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
237682c907af479178801a7a8701341b22c9d20fdb7Upstream
237782c907af479178801a7a8701341b22c9d20fdb7Upstream    /* set ip_dynaddr in demand mode if address changes */
237882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (demand && tune_kernel && !dynaddr_set
237982c907af479178801a7a8701341b22c9d20fdb7Upstream	&& our_old_addr && our_old_addr != our_adr) {
238082c907af479178801a7a8701341b22c9d20fdb7Upstream	/* set ip_dynaddr if possible */
238182c907af479178801a7a8701341b22c9d20fdb7Upstream	char *path;
238282c907af479178801a7a8701341b22c9d20fdb7Upstream	int fd;
238382c907af479178801a7a8701341b22c9d20fdb7Upstream
238482c907af479178801a7a8701341b22c9d20fdb7Upstream	path = path_to_procfs("/sys/net/ipv4/ip_dynaddr");
238582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
238682c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (write(fd, "1", 1) != 1)
238782c907af479178801a7a8701341b22c9d20fdb7Upstream		error("Couldn't enable dynamic IP addressing: %m");
238882c907af479178801a7a8701341b22c9d20fdb7Upstream	    close(fd);
238982c907af479178801a7a8701341b22c9d20fdb7Upstream	}
239082c907af479178801a7a8701341b22c9d20fdb7Upstream	dynaddr_set = 1;	/* only 1 attempt */
239182c907af479178801a7a8701341b22c9d20fdb7Upstream    }
239282c907af479178801a7a8701341b22c9d20fdb7Upstream    our_old_addr = 0;
239382c907af479178801a7a8701341b22c9d20fdb7Upstream
239482c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
239582c907af479178801a7a8701341b22c9d20fdb7Upstream}
239682c907af479178801a7a8701341b22c9d20fdb7Upstream
239782c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
239882c907af479178801a7a8701341b22c9d20fdb7Upstream *
239982c907af479178801a7a8701341b22c9d20fdb7Upstream * cifaddr - Clear the interface IP addresses, and delete routes
240082c907af479178801a7a8701341b22c9d20fdb7Upstream * through the interface if possible.
240182c907af479178801a7a8701341b22c9d20fdb7Upstream */
240282c907af479178801a7a8701341b22c9d20fdb7Upstream
240382c907af479178801a7a8701341b22c9d20fdb7Upstreamint cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
240482c907af479178801a7a8701341b22c9d20fdb7Upstream{
240582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
240682c907af479178801a7a8701341b22c9d20fdb7Upstream
240782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (kernel_version < KVERSION(2,1,16)) {
240882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
240982c907af479178801a7a8701341b22c9d20fdb7Upstream *  Delete the route through the device
241082c907af479178801a7a8701341b22c9d20fdb7Upstream */
241182c907af479178801a7a8701341b22c9d20fdb7Upstream	struct rtentry rt;
241282c907af479178801a7a8701341b22c9d20fdb7Upstream	memset (&rt, '\0', sizeof (rt));
241382c907af479178801a7a8701341b22c9d20fdb7Upstream
241482c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY (rt.rt_dst,     AF_INET);
241582c907af479178801a7a8701341b22c9d20fdb7Upstream	SET_SA_FAMILY (rt.rt_gateway, AF_INET);
241682c907af479178801a7a8701341b22c9d20fdb7Upstream	rt.rt_dev = ifname;
241782c907af479178801a7a8701341b22c9d20fdb7Upstream
241882c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(rt.rt_gateway) = 0;
241982c907af479178801a7a8701341b22c9d20fdb7Upstream	SIN_ADDR(rt.rt_dst)     = his_adr;
242082c907af479178801a7a8701341b22c9d20fdb7Upstream	rt.rt_flags = RTF_UP | RTF_HOST;
242182c907af479178801a7a8701341b22c9d20fdb7Upstream
242282c907af479178801a7a8701341b22c9d20fdb7Upstream	if (kernel_version > KVERSION(2,1,0)) {
242382c907af479178801a7a8701341b22c9d20fdb7Upstream	    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
242482c907af479178801a7a8701341b22c9d20fdb7Upstream	    SIN_ADDR(rt.rt_genmask) = -1L;
242582c907af479178801a7a8701341b22c9d20fdb7Upstream	}
242682c907af479178801a7a8701341b22c9d20fdb7Upstream
242782c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
242882c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (still_ppp() && ! ok_error (errno))
242982c907af479178801a7a8701341b22c9d20fdb7Upstream		error("ioctl(SIOCDELRT) device route: %m (line %d)", __LINE__);
243082c907af479178801a7a8701341b22c9d20fdb7Upstream	    return (0);
243182c907af479178801a7a8701341b22c9d20fdb7Upstream	}
243282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
243382c907af479178801a7a8701341b22c9d20fdb7Upstream
243482c907af479178801a7a8701341b22c9d20fdb7Upstream    /* This way it is possible to have an IPX-only or IPv6-only interface */
243582c907af479178801a7a8701341b22c9d20fdb7Upstream    memset(&ifr, 0, sizeof(ifr));
243682c907af479178801a7a8701341b22c9d20fdb7Upstream    SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
243782c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
243882c907af479178801a7a8701341b22c9d20fdb7Upstream
243982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
244082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno)) {
244182c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
244282c907af479178801a7a8701341b22c9d20fdb7Upstream	    return 0;
244382c907af479178801a7a8701341b22c9d20fdb7Upstream	}
244482c907af479178801a7a8701341b22c9d20fdb7Upstream    }
244582c907af479178801a7a8701341b22c9d20fdb7Upstream
244682c907af479178801a7a8701341b22c9d20fdb7Upstream    our_old_addr = our_adr;
244782c907af479178801a7a8701341b22c9d20fdb7Upstream
244882c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
244982c907af479178801a7a8701341b22c9d20fdb7Upstream}
245082c907af479178801a7a8701341b22c9d20fdb7Upstream
245182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef INET6
245282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
245382c907af479178801a7a8701341b22c9d20fdb7Upstream *
245482c907af479178801a7a8701341b22c9d20fdb7Upstream * sif6addr - Config the interface with an IPv6 link-local address
245582c907af479178801a7a8701341b22c9d20fdb7Upstream */
245682c907af479178801a7a8701341b22c9d20fdb7Upstreamint sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
245782c907af479178801a7a8701341b22c9d20fdb7Upstream{
245882c907af479178801a7a8701341b22c9d20fdb7Upstream    struct in6_ifreq ifr6;
245982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
246082c907af479178801a7a8701341b22c9d20fdb7Upstream    struct in6_rtmsg rt6;
246182c907af479178801a7a8701341b22c9d20fdb7Upstream
246282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sock6_fd < 0) {
246382c907af479178801a7a8701341b22c9d20fdb7Upstream	errno = -sock6_fd;
246482c907af479178801a7a8701341b22c9d20fdb7Upstream	error("IPv6 socket creation failed: %m");
246582c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
246682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
246782c907af479178801a7a8701341b22c9d20fdb7Upstream    memset(&ifr, 0, sizeof (ifr));
246882c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
246982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
247082c907af479178801a7a8701341b22c9d20fdb7Upstream	error("sif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
247182c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
247282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
247382c907af479178801a7a8701341b22c9d20fdb7Upstream
247482c907af479178801a7a8701341b22c9d20fdb7Upstream    /* Local interface */
247582c907af479178801a7a8701341b22c9d20fdb7Upstream    memset(&ifr6, 0, sizeof(ifr6));
247682c907af479178801a7a8701341b22c9d20fdb7Upstream    IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
247782c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
247882c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr6.ifr6_prefixlen = 10;
247982c907af479178801a7a8701341b22c9d20fdb7Upstream
248082c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
248182c907af479178801a7a8701341b22c9d20fdb7Upstream	error("sif6addr: ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
248282c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
248382c907af479178801a7a8701341b22c9d20fdb7Upstream    }
248482c907af479178801a7a8701341b22c9d20fdb7Upstream
248582c907af479178801a7a8701341b22c9d20fdb7Upstream    /* Route to remote host */
248682c907af479178801a7a8701341b22c9d20fdb7Upstream    memset(&rt6, 0, sizeof(rt6));
248782c907af479178801a7a8701341b22c9d20fdb7Upstream    IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
248882c907af479178801a7a8701341b22c9d20fdb7Upstream    rt6.rtmsg_flags = RTF_UP;
248982c907af479178801a7a8701341b22c9d20fdb7Upstream    rt6.rtmsg_dst_len = 10;
249082c907af479178801a7a8701341b22c9d20fdb7Upstream    rt6.rtmsg_ifindex = ifr.ifr_ifindex;
249182c907af479178801a7a8701341b22c9d20fdb7Upstream    rt6.rtmsg_metric = 1;
249282c907af479178801a7a8701341b22c9d20fdb7Upstream
249382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
249482c907af479178801a7a8701341b22c9d20fdb7Upstream	error("sif6addr: ioctl(SIOCADDRT): %m (line %d)", __LINE__);
249582c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
249682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
249782c907af479178801a7a8701341b22c9d20fdb7Upstream
249882c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
249982c907af479178801a7a8701341b22c9d20fdb7Upstream}
250082c907af479178801a7a8701341b22c9d20fdb7Upstream
250182c907af479178801a7a8701341b22c9d20fdb7Upstream
250282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
250382c907af479178801a7a8701341b22c9d20fdb7Upstream *
250482c907af479178801a7a8701341b22c9d20fdb7Upstream * cif6addr - Remove IPv6 address from interface
250582c907af479178801a7a8701341b22c9d20fdb7Upstream */
250682c907af479178801a7a8701341b22c9d20fdb7Upstreamint cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
250782c907af479178801a7a8701341b22c9d20fdb7Upstream{
250882c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
250982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct in6_ifreq ifr6;
251082c907af479178801a7a8701341b22c9d20fdb7Upstream
251182c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sock6_fd < 0) {
251282c907af479178801a7a8701341b22c9d20fdb7Upstream	errno = -sock6_fd;
251382c907af479178801a7a8701341b22c9d20fdb7Upstream	error("IPv6 socket creation failed: %m");
251482c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
251582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
251682c907af479178801a7a8701341b22c9d20fdb7Upstream    memset(&ifr, 0, sizeof(ifr));
251782c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
251882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
251982c907af479178801a7a8701341b22c9d20fdb7Upstream	error("cif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
252082c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
252182c907af479178801a7a8701341b22c9d20fdb7Upstream    }
252282c907af479178801a7a8701341b22c9d20fdb7Upstream
252382c907af479178801a7a8701341b22c9d20fdb7Upstream    memset(&ifr6, 0, sizeof(ifr6));
252482c907af479178801a7a8701341b22c9d20fdb7Upstream    IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
252582c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
252682c907af479178801a7a8701341b22c9d20fdb7Upstream    ifr6.ifr6_prefixlen = 10;
252782c907af479178801a7a8701341b22c9d20fdb7Upstream
252882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
252982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (errno != EADDRNOTAVAIL) {
253082c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (! ok_error (errno))
253182c907af479178801a7a8701341b22c9d20fdb7Upstream		error("cif6addr: ioctl(SIOCDIFADDR): %m (line %d)", __LINE__);
253282c907af479178801a7a8701341b22c9d20fdb7Upstream	}
253382c907af479178801a7a8701341b22c9d20fdb7Upstream	else {
253482c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("cif6addr: ioctl(SIOCDIFADDR): No such address");
253582c907af479178801a7a8701341b22c9d20fdb7Upstream	}
253682c907af479178801a7a8701341b22c9d20fdb7Upstream	return (0);
253782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
253882c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
253982c907af479178801a7a8701341b22c9d20fdb7Upstream}
254082c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* INET6 */
254182c907af479178801a7a8701341b22c9d20fdb7Upstream
254282c907af479178801a7a8701341b22c9d20fdb7Upstream/*
254382c907af479178801a7a8701341b22c9d20fdb7Upstream * get_pty - get a pty master/slave pair and chown the slave side
254482c907af479178801a7a8701341b22c9d20fdb7Upstream * to the uid given.  Assumes slave_name points to >= 16 bytes of space.
254582c907af479178801a7a8701341b22c9d20fdb7Upstream */
254682c907af479178801a7a8701341b22c9d20fdb7Upstreamint
254782c907af479178801a7a8701341b22c9d20fdb7Upstreamget_pty(master_fdp, slave_fdp, slave_name, uid)
254882c907af479178801a7a8701341b22c9d20fdb7Upstream    int *master_fdp;
254982c907af479178801a7a8701341b22c9d20fdb7Upstream    int *slave_fdp;
255082c907af479178801a7a8701341b22c9d20fdb7Upstream    char *slave_name;
255182c907af479178801a7a8701341b22c9d20fdb7Upstream    int uid;
255282c907af479178801a7a8701341b22c9d20fdb7Upstream{
255382c907af479178801a7a8701341b22c9d20fdb7Upstream    int i, mfd, sfd = -1;
255482c907af479178801a7a8701341b22c9d20fdb7Upstream    char pty_name[16];
255582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct termios tios;
255682c907af479178801a7a8701341b22c9d20fdb7Upstream
255782c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef TIOCGPTN
255882c907af479178801a7a8701341b22c9d20fdb7Upstream    /*
255982c907af479178801a7a8701341b22c9d20fdb7Upstream     * Try the unix98 way first.
256082c907af479178801a7a8701341b22c9d20fdb7Upstream     */
256182c907af479178801a7a8701341b22c9d20fdb7Upstream    mfd = open("/dev/ptmx", O_RDWR);
256282c907af479178801a7a8701341b22c9d20fdb7Upstream    if (mfd >= 0) {
256382c907af479178801a7a8701341b22c9d20fdb7Upstream	int ptn;
256482c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) {
256511088bb1896dff9caae1378d463bd349f96520aaPeter Enderborg	    slprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn);
256682c907af479178801a7a8701341b22c9d20fdb7Upstream	    chmod(pty_name, S_IRUSR | S_IWUSR);
256782c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef TIOCSPTLCK
256882c907af479178801a7a8701341b22c9d20fdb7Upstream	    ptn = 0;
256982c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0)
257082c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Couldn't unlock pty slave %s: %m", pty_name);
257182c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
257282c907af479178801a7a8701341b22c9d20fdb7Upstream	    if ((sfd = open(pty_name, O_RDWR | O_NOCTTY)) < 0)
257382c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("Couldn't open pty slave %s: %m", pty_name);
257482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
257582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
257682c907af479178801a7a8701341b22c9d20fdb7Upstream#endif /* TIOCGPTN */
257782c907af479178801a7a8701341b22c9d20fdb7Upstream
257882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sfd < 0) {
257982c907af479178801a7a8701341b22c9d20fdb7Upstream	/* the old way - scan through the pty name space */
258082c907af479178801a7a8701341b22c9d20fdb7Upstream	for (i = 0; i < 64; ++i) {
258182c907af479178801a7a8701341b22c9d20fdb7Upstream	    slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
258282c907af479178801a7a8701341b22c9d20fdb7Upstream		     'p' + i / 16, i % 16);
258382c907af479178801a7a8701341b22c9d20fdb7Upstream	    mfd = open(pty_name, O_RDWR, 0);
258482c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (mfd >= 0) {
258582c907af479178801a7a8701341b22c9d20fdb7Upstream		pty_name[5] = 't';
258682c907af479178801a7a8701341b22c9d20fdb7Upstream		sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
258782c907af479178801a7a8701341b22c9d20fdb7Upstream		if (sfd >= 0) {
258882c907af479178801a7a8701341b22c9d20fdb7Upstream		    fchown(sfd, uid, -1);
258982c907af479178801a7a8701341b22c9d20fdb7Upstream		    fchmod(sfd, S_IRUSR | S_IWUSR);
259082c907af479178801a7a8701341b22c9d20fdb7Upstream		    break;
259182c907af479178801a7a8701341b22c9d20fdb7Upstream		}
259282c907af479178801a7a8701341b22c9d20fdb7Upstream		close(mfd);
259382c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
259482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
259582c907af479178801a7a8701341b22c9d20fdb7Upstream    }
259682c907af479178801a7a8701341b22c9d20fdb7Upstream
259782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (sfd < 0)
259882c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
259982c907af479178801a7a8701341b22c9d20fdb7Upstream
260082c907af479178801a7a8701341b22c9d20fdb7Upstream    strlcpy(slave_name, pty_name, 16);
260182c907af479178801a7a8701341b22c9d20fdb7Upstream    *master_fdp = mfd;
260282c907af479178801a7a8701341b22c9d20fdb7Upstream    *slave_fdp = sfd;
260382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (tcgetattr(sfd, &tios) == 0) {
260482c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
260582c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_cflag |= CS8 | CREAD | CLOCAL;
260682c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_iflag  = IGNPAR;
260782c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_oflag  = 0;
260882c907af479178801a7a8701341b22c9d20fdb7Upstream	tios.c_lflag  = 0;
260982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
261082c907af479178801a7a8701341b22c9d20fdb7Upstream	    warn("couldn't set attributes on pty: %m");
261182c907af479178801a7a8701341b22c9d20fdb7Upstream    } else
261282c907af479178801a7a8701341b22c9d20fdb7Upstream	warn("couldn't get attributes on pty: %m");
261382c907af479178801a7a8701341b22c9d20fdb7Upstream
261482c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
261582c907af479178801a7a8701341b22c9d20fdb7Upstream}
261682c907af479178801a7a8701341b22c9d20fdb7Upstream
261782c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
261882c907af479178801a7a8701341b22c9d20fdb7Upstream *
261982c907af479178801a7a8701341b22c9d20fdb7Upstream * open_loopback - open the device we use for getting packets
262082c907af479178801a7a8701341b22c9d20fdb7Upstream * in demand mode.  Under Linux, we use a pty master/slave pair.
262182c907af479178801a7a8701341b22c9d20fdb7Upstream */
262282c907af479178801a7a8701341b22c9d20fdb7Upstreamint
262382c907af479178801a7a8701341b22c9d20fdb7Upstreamopen_ppp_loopback(void)
262482c907af479178801a7a8701341b22c9d20fdb7Upstream{
262582c907af479178801a7a8701341b22c9d20fdb7Upstream    int flags;
262682c907af479178801a7a8701341b22c9d20fdb7Upstream
262782c907af479178801a7a8701341b22c9d20fdb7Upstream    looped = 1;
262882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (new_style_driver) {
262982c907af479178801a7a8701341b22c9d20fdb7Upstream	/* allocate ourselves a ppp unit */
263082c907af479178801a7a8701341b22c9d20fdb7Upstream	if (make_ppp_unit() < 0)
263182c907af479178801a7a8701341b22c9d20fdb7Upstream	    die(1);
263282c907af479178801a7a8701341b22c9d20fdb7Upstream	modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
263382c907af479178801a7a8701341b22c9d20fdb7Upstream	set_kdebugflag(kdebugflag);
263482c907af479178801a7a8701341b22c9d20fdb7Upstream	ppp_fd = -1;
263582c907af479178801a7a8701341b22c9d20fdb7Upstream	return ppp_dev_fd;
263682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
263782c907af479178801a7a8701341b22c9d20fdb7Upstream
263882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
263982c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("No free pty for loopback");
264082c907af479178801a7a8701341b22c9d20fdb7Upstream
264182c907af479178801a7a8701341b22c9d20fdb7Upstream    set_ppp_fd(slave_fd);
264282c907af479178801a7a8701341b22c9d20fdb7Upstream
264382c907af479178801a7a8701341b22c9d20fdb7Upstream    flags = fcntl(master_fd, F_GETFL);
264482c907af479178801a7a8701341b22c9d20fdb7Upstream    if (flags == -1 ||
264582c907af479178801a7a8701341b22c9d20fdb7Upstream	fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
264682c907af479178801a7a8701341b22c9d20fdb7Upstream	warn("couldn't set master loopback to nonblock: %m");
264782c907af479178801a7a8701341b22c9d20fdb7Upstream
264882c907af479178801a7a8701341b22c9d20fdb7Upstream    flags = fcntl(ppp_fd, F_GETFL);
264982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (flags == -1 ||
265082c907af479178801a7a8701341b22c9d20fdb7Upstream	fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
265182c907af479178801a7a8701341b22c9d20fdb7Upstream	warn("couldn't set slave loopback to nonblock: %m");
265282c907af479178801a7a8701341b22c9d20fdb7Upstream
265382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
265482c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("ioctl(TIOCSETD): %m (line %d)", __LINE__);
265582c907af479178801a7a8701341b22c9d20fdb7Upstream/*
265682c907af479178801a7a8701341b22c9d20fdb7Upstream * Find out which interface we were given.
265782c907af479178801a7a8701341b22c9d20fdb7Upstream */
265882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
265982c907af479178801a7a8701341b22c9d20fdb7Upstream	fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
266082c907af479178801a7a8701341b22c9d20fdb7Upstream/*
266182c907af479178801a7a8701341b22c9d20fdb7Upstream * Enable debug in the driver if requested.
266282c907af479178801a7a8701341b22c9d20fdb7Upstream */
266382c907af479178801a7a8701341b22c9d20fdb7Upstream    set_kdebugflag (kdebugflag);
266482c907af479178801a7a8701341b22c9d20fdb7Upstream
266582c907af479178801a7a8701341b22c9d20fdb7Upstream    return master_fd;
266682c907af479178801a7a8701341b22c9d20fdb7Upstream}
266782c907af479178801a7a8701341b22c9d20fdb7Upstream
266882c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
266982c907af479178801a7a8701341b22c9d20fdb7Upstream *
267082c907af479178801a7a8701341b22c9d20fdb7Upstream * sifnpmode - Set the mode for handling packets for a given NP.
267182c907af479178801a7a8701341b22c9d20fdb7Upstream */
267282c907af479178801a7a8701341b22c9d20fdb7Upstream
267382c907af479178801a7a8701341b22c9d20fdb7Upstreamint
267482c907af479178801a7a8701341b22c9d20fdb7Upstreamsifnpmode(u, proto, mode)
267582c907af479178801a7a8701341b22c9d20fdb7Upstream    int u;
267682c907af479178801a7a8701341b22c9d20fdb7Upstream    int proto;
267782c907af479178801a7a8701341b22c9d20fdb7Upstream    enum NPmode mode;
267882c907af479178801a7a8701341b22c9d20fdb7Upstream{
267982c907af479178801a7a8701341b22c9d20fdb7Upstream    struct npioctl npi;
268082c907af479178801a7a8701341b22c9d20fdb7Upstream
268182c907af479178801a7a8701341b22c9d20fdb7Upstream    npi.protocol = proto;
268282c907af479178801a7a8701341b22c9d20fdb7Upstream    npi.mode     = mode;
268382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
268482c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
268582c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("ioctl(PPPIOCSNPMODE, %d, %d): %m", proto, mode);
268682c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
268782c907af479178801a7a8701341b22c9d20fdb7Upstream    }
268882c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
268982c907af479178801a7a8701341b22c9d20fdb7Upstream}
269082c907af479178801a7a8701341b22c9d20fdb7Upstream
269182c907af479178801a7a8701341b22c9d20fdb7Upstream
269282c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
269382c907af479178801a7a8701341b22c9d20fdb7Upstream *
269482c907af479178801a7a8701341b22c9d20fdb7Upstream * sipxfaddr - Config the interface IPX networknumber
269582c907af479178801a7a8701341b22c9d20fdb7Upstream */
269682c907af479178801a7a8701341b22c9d20fdb7Upstream
269782c907af479178801a7a8701341b22c9d20fdb7Upstreamint sipxfaddr (int unit, unsigned long int network, unsigned char * node )
269882c907af479178801a7a8701341b22c9d20fdb7Upstream{
269982c907af479178801a7a8701341b22c9d20fdb7Upstream    int    result = 1;
270082c907af479178801a7a8701341b22c9d20fdb7Upstream
270182c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef IPX_CHANGE
270282c907af479178801a7a8701341b22c9d20fdb7Upstream    int    skfd;
270382c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq         ifr;
270482c907af479178801a7a8701341b22c9d20fdb7Upstream    struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
270582c907af479178801a7a8701341b22c9d20fdb7Upstream
270682c907af479178801a7a8701341b22c9d20fdb7Upstream    skfd = socket (AF_IPX, SOCK_DGRAM, 0);
270782c907af479178801a7a8701341b22c9d20fdb7Upstream    if (skfd < 0) {
270882c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
270982c907af479178801a7a8701341b22c9d20fdb7Upstream	    dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
271082c907af479178801a7a8701341b22c9d20fdb7Upstream	result = 0;
271182c907af479178801a7a8701341b22c9d20fdb7Upstream    }
271282c907af479178801a7a8701341b22c9d20fdb7Upstream    else {
271382c907af479178801a7a8701341b22c9d20fdb7Upstream	memset (&ifr, '\0', sizeof (ifr));
271482c907af479178801a7a8701341b22c9d20fdb7Upstream	strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
271582c907af479178801a7a8701341b22c9d20fdb7Upstream
271682c907af479178801a7a8701341b22c9d20fdb7Upstream	memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
271782c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_family  = AF_IPX;
271882c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_port    = 0;
271982c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_network = htonl (network);
272082c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_type    = IPX_FRAME_ETHERII;
272182c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_action  = IPX_CRTITF;
272282c907af479178801a7a8701341b22c9d20fdb7Upstream/*
272382c907af479178801a7a8701341b22c9d20fdb7Upstream *  Set the IPX device
272482c907af479178801a7a8701341b22c9d20fdb7Upstream */
272582c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
272682c907af479178801a7a8701341b22c9d20fdb7Upstream	    result = 0;
272782c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (errno != EEXIST) {
272882c907af479178801a7a8701341b22c9d20fdb7Upstream		if (! ok_error (errno))
272982c907af479178801a7a8701341b22c9d20fdb7Upstream		    dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (line %d)", __LINE__);
273082c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
273182c907af479178801a7a8701341b22c9d20fdb7Upstream	    else {
273282c907af479178801a7a8701341b22c9d20fdb7Upstream		warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists");
273382c907af479178801a7a8701341b22c9d20fdb7Upstream	    }
273482c907af479178801a7a8701341b22c9d20fdb7Upstream	}
273582c907af479178801a7a8701341b22c9d20fdb7Upstream	close (skfd);
273682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
273782c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
273882c907af479178801a7a8701341b22c9d20fdb7Upstream    return result;
273982c907af479178801a7a8701341b22c9d20fdb7Upstream}
274082c907af479178801a7a8701341b22c9d20fdb7Upstream
274182c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
274282c907af479178801a7a8701341b22c9d20fdb7Upstream *
274382c907af479178801a7a8701341b22c9d20fdb7Upstream * cipxfaddr - Clear the information for the IPX network. The IPX routes
274482c907af479178801a7a8701341b22c9d20fdb7Upstream *	       are removed and the device is no longer able to pass IPX
274582c907af479178801a7a8701341b22c9d20fdb7Upstream *	       frames.
274682c907af479178801a7a8701341b22c9d20fdb7Upstream */
274782c907af479178801a7a8701341b22c9d20fdb7Upstream
274882c907af479178801a7a8701341b22c9d20fdb7Upstreamint cipxfaddr (int unit)
274982c907af479178801a7a8701341b22c9d20fdb7Upstream{
275082c907af479178801a7a8701341b22c9d20fdb7Upstream    int    result = 1;
275182c907af479178801a7a8701341b22c9d20fdb7Upstream
275282c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef IPX_CHANGE
275382c907af479178801a7a8701341b22c9d20fdb7Upstream    int    skfd;
275482c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq         ifr;
275582c907af479178801a7a8701341b22c9d20fdb7Upstream    struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
275682c907af479178801a7a8701341b22c9d20fdb7Upstream
275782c907af479178801a7a8701341b22c9d20fdb7Upstream    skfd = socket (AF_IPX, SOCK_DGRAM, 0);
275882c907af479178801a7a8701341b22c9d20fdb7Upstream    if (skfd < 0) {
275982c907af479178801a7a8701341b22c9d20fdb7Upstream	if (! ok_error (errno))
276082c907af479178801a7a8701341b22c9d20fdb7Upstream	    dbglog("socket(AF_IPX): %m (line %d)", __LINE__);
276182c907af479178801a7a8701341b22c9d20fdb7Upstream	result = 0;
276282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
276382c907af479178801a7a8701341b22c9d20fdb7Upstream    else {
276482c907af479178801a7a8701341b22c9d20fdb7Upstream	memset (&ifr, '\0', sizeof (ifr));
276582c907af479178801a7a8701341b22c9d20fdb7Upstream	strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
276682c907af479178801a7a8701341b22c9d20fdb7Upstream
276782c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_type    = IPX_FRAME_ETHERII;
276882c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_action  = IPX_DLTITF;
276982c907af479178801a7a8701341b22c9d20fdb7Upstream	sipx->sipx_family  = AF_IPX;
277082c907af479178801a7a8701341b22c9d20fdb7Upstream/*
277182c907af479178801a7a8701341b22c9d20fdb7Upstream *  Set the IPX device
277282c907af479178801a7a8701341b22c9d20fdb7Upstream */
277382c907af479178801a7a8701341b22c9d20fdb7Upstream	if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
277482c907af479178801a7a8701341b22c9d20fdb7Upstream	    if (! ok_error (errno))
277582c907af479178801a7a8701341b22c9d20fdb7Upstream		info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (line %d)", __LINE__);
277682c907af479178801a7a8701341b22c9d20fdb7Upstream	    result = 0;
277782c907af479178801a7a8701341b22c9d20fdb7Upstream	}
277882c907af479178801a7a8701341b22c9d20fdb7Upstream	close (skfd);
277982c907af479178801a7a8701341b22c9d20fdb7Upstream    }
278082c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
278182c907af479178801a7a8701341b22c9d20fdb7Upstream    return result;
278282c907af479178801a7a8701341b22c9d20fdb7Upstream}
278382c907af479178801a7a8701341b22c9d20fdb7Upstream
278482c907af479178801a7a8701341b22c9d20fdb7Upstream/*
278582c907af479178801a7a8701341b22c9d20fdb7Upstream * Use the hostname as part of the random number seed.
278682c907af479178801a7a8701341b22c9d20fdb7Upstream */
278782c907af479178801a7a8701341b22c9d20fdb7Upstreamint
278882c907af479178801a7a8701341b22c9d20fdb7Upstreamget_host_seed()
278982c907af479178801a7a8701341b22c9d20fdb7Upstream{
279082c907af479178801a7a8701341b22c9d20fdb7Upstream    int h;
279182c907af479178801a7a8701341b22c9d20fdb7Upstream    char *p = hostname;
279282c907af479178801a7a8701341b22c9d20fdb7Upstream
279382c907af479178801a7a8701341b22c9d20fdb7Upstream    h = 407;
279482c907af479178801a7a8701341b22c9d20fdb7Upstream    for (p = hostname; *p != 0; ++p)
279582c907af479178801a7a8701341b22c9d20fdb7Upstream	h = h * 37 + *p;
279682c907af479178801a7a8701341b22c9d20fdb7Upstream    return h;
279782c907af479178801a7a8701341b22c9d20fdb7Upstream}
279882c907af479178801a7a8701341b22c9d20fdb7Upstream
279982c907af479178801a7a8701341b22c9d20fdb7Upstream/********************************************************************
280082c907af479178801a7a8701341b22c9d20fdb7Upstream *
280182c907af479178801a7a8701341b22c9d20fdb7Upstream * sys_check_options - check the options that the user specified
280282c907af479178801a7a8701341b22c9d20fdb7Upstream */
280382c907af479178801a7a8701341b22c9d20fdb7Upstream
280482c907af479178801a7a8701341b22c9d20fdb7Upstreamint
280582c907af479178801a7a8701341b22c9d20fdb7Upstreamsys_check_options(void)
280682c907af479178801a7a8701341b22c9d20fdb7Upstream{
280782c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef IPX_CHANGE
280882c907af479178801a7a8701341b22c9d20fdb7Upstream/*
280982c907af479178801a7a8701341b22c9d20fdb7Upstream * Disable the IPX protocol if the support is not present in the kernel.
281082c907af479178801a7a8701341b22c9d20fdb7Upstream */
281182c907af479178801a7a8701341b22c9d20fdb7Upstream    char *path;
281282c907af479178801a7a8701341b22c9d20fdb7Upstream
281382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (ipxcp_protent.enabled_flag) {
281482c907af479178801a7a8701341b22c9d20fdb7Upstream	struct stat stat_buf;
281582c907af479178801a7a8701341b22c9d20fdb7Upstream	if ((path = path_to_procfs("/net/ipx/interface")) == 0
281682c907af479178801a7a8701341b22c9d20fdb7Upstream	    || (path = path_to_procfs("/net/ipx_interface")) == 0
281782c907af479178801a7a8701341b22c9d20fdb7Upstream	    || lstat(path, &stat_buf) < 0) {
281882c907af479178801a7a8701341b22c9d20fdb7Upstream	    error("IPX support is not present in the kernel\n");
281982c907af479178801a7a8701341b22c9d20fdb7Upstream	    ipxcp_protent.enabled_flag = 0;
282082c907af479178801a7a8701341b22c9d20fdb7Upstream	}
282182c907af479178801a7a8701341b22c9d20fdb7Upstream    }
282282c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
282382c907af479178801a7a8701341b22c9d20fdb7Upstream    if (demand && driver_is_old) {
282482c907af479178801a7a8701341b22c9d20fdb7Upstream	option_error("demand dialling is not supported by kernel driver "
282582c907af479178801a7a8701341b22c9d20fdb7Upstream		     "version %d.%d.%d", driver_version, driver_modification,
282682c907af479178801a7a8701341b22c9d20fdb7Upstream		     driver_patch);
282782c907af479178801a7a8701341b22c9d20fdb7Upstream	return 0;
282882c907af479178801a7a8701341b22c9d20fdb7Upstream    }
282982c907af479178801a7a8701341b22c9d20fdb7Upstream    if (multilink && !new_style_driver) {
283082c907af479178801a7a8701341b22c9d20fdb7Upstream	warn("Warning: multilink is not supported by the kernel driver");
283182c907af479178801a7a8701341b22c9d20fdb7Upstream	multilink = 0;
283282c907af479178801a7a8701341b22c9d20fdb7Upstream    }
283382c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
283482c907af479178801a7a8701341b22c9d20fdb7Upstream}
283582c907af479178801a7a8701341b22c9d20fdb7Upstream
283682c907af479178801a7a8701341b22c9d20fdb7Upstream#ifdef INET6
283782c907af479178801a7a8701341b22c9d20fdb7Upstream/*
283882c907af479178801a7a8701341b22c9d20fdb7Upstream * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
283982c907af479178801a7a8701341b22c9d20fdb7Upstream *
284082c907af479178801a7a8701341b22c9d20fdb7Upstream * convert the 48-bit MAC address of eth0 into EUI 64. caller also assumes
284182c907af479178801a7a8701341b22c9d20fdb7Upstream * that the system has a properly configured Ethernet interface for this
284282c907af479178801a7a8701341b22c9d20fdb7Upstream * function to return non-zero.
284382c907af479178801a7a8701341b22c9d20fdb7Upstream */
284482c907af479178801a7a8701341b22c9d20fdb7Upstreamint
284582c907af479178801a7a8701341b22c9d20fdb7Upstreamether_to_eui64(eui64_t *p_eui64)
284682c907af479178801a7a8701341b22c9d20fdb7Upstream{
284782c907af479178801a7a8701341b22c9d20fdb7Upstream    struct ifreq ifr;
284882c907af479178801a7a8701341b22c9d20fdb7Upstream    int skfd;
284982c907af479178801a7a8701341b22c9d20fdb7Upstream    const unsigned char *ptr;
285082c907af479178801a7a8701341b22c9d20fdb7Upstream
285182c907af479178801a7a8701341b22c9d20fdb7Upstream    skfd = socket(PF_INET6, SOCK_DGRAM, 0);
285282c907af479178801a7a8701341b22c9d20fdb7Upstream    if(skfd == -1)
285382c907af479178801a7a8701341b22c9d20fdb7Upstream    {
285482c907af479178801a7a8701341b22c9d20fdb7Upstream        warn("could not open IPv6 socket");
285582c907af479178801a7a8701341b22c9d20fdb7Upstream        return 0;
285682c907af479178801a7a8701341b22c9d20fdb7Upstream    }
285782c907af479178801a7a8701341b22c9d20fdb7Upstream
285882c907af479178801a7a8701341b22c9d20fdb7Upstream    strcpy(ifr.ifr_name, "eth0");
285982c907af479178801a7a8701341b22c9d20fdb7Upstream    if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
286082c907af479178801a7a8701341b22c9d20fdb7Upstream    {
286182c907af479178801a7a8701341b22c9d20fdb7Upstream        close(skfd);
286282c907af479178801a7a8701341b22c9d20fdb7Upstream        warn("could not obtain hardware address for eth0");
286382c907af479178801a7a8701341b22c9d20fdb7Upstream        return 0;
286482c907af479178801a7a8701341b22c9d20fdb7Upstream    }
286582c907af479178801a7a8701341b22c9d20fdb7Upstream    close(skfd);
286682c907af479178801a7a8701341b22c9d20fdb7Upstream
286782c907af479178801a7a8701341b22c9d20fdb7Upstream    /*
286882c907af479178801a7a8701341b22c9d20fdb7Upstream     * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
286982c907af479178801a7a8701341b22c9d20fdb7Upstream     */
287082c907af479178801a7a8701341b22c9d20fdb7Upstream    ptr = ifr.ifr_hwaddr.sa_data;
287182c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[0] = ptr[0] | 0x02;
287282c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[1] = ptr[1];
287382c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[2] = ptr[2];
287482c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[3] = 0xFF;
287582c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[4] = 0xFE;
287682c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[5] = ptr[3];
287782c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[6] = ptr[4];
287882c907af479178801a7a8701341b22c9d20fdb7Upstream    p_eui64->e8[7] = ptr[5];
287982c907af479178801a7a8701341b22c9d20fdb7Upstream
288082c907af479178801a7a8701341b22c9d20fdb7Upstream    return 1;
288182c907af479178801a7a8701341b22c9d20fdb7Upstream}
288282c907af479178801a7a8701341b22c9d20fdb7Upstream#endif
2883