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