Home | History | Annotate | Line # | Download | only in pppd
      1   1.1  christos /*	NetBSD: sys-bsd.c,v 1.68 2013/06/24 20:43:48 christos Exp 	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * sys-bsd.c - System-dependent procedures for setting up
      5   1.1  christos  * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
      6   1.1  christos  *
      7   1.1  christos  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
      8   1.1  christos  *
      9   1.1  christos  * Redistribution and use in source and binary forms, with or without
     10   1.1  christos  * modification, are permitted provided that the following conditions
     11   1.1  christos  * are met:
     12   1.1  christos  *
     13   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     14   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     15   1.1  christos  *
     16   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     17   1.1  christos  *    notice, this list of conditions and the following disclaimer in
     18   1.1  christos  *    the documentation and/or other materials provided with the
     19   1.1  christos  *    distribution.
     20   1.1  christos  *
     21   1.1  christos  * 3. The name "Carnegie Mellon University" must not be used to
     22   1.1  christos  *    endorse or promote products derived from this software without
     23   1.1  christos  *    prior written permission. For permission or any legal
     24   1.1  christos  *    details, please contact
     25   1.1  christos  *      Office of Technology Transfer
     26   1.1  christos  *      Carnegie Mellon University
     27   1.1  christos  *      5000 Forbes Avenue
     28   1.1  christos  *      Pittsburgh, PA  15213-3890
     29   1.1  christos  *      (412) 268-4387, fax: (412) 268-7395
     30   1.1  christos  *      tech-transfer (at) andrew.cmu.edu
     31   1.1  christos  *
     32   1.1  christos  * 4. Redistributions of any form whatsoever must retain the following
     33   1.1  christos  *    acknowledgment:
     34   1.1  christos  *    "This product includes software developed by Computing Services
     35   1.1  christos  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
     36   1.1  christos  *
     37   1.1  christos  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
     38   1.1  christos  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     39   1.1  christos  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
     40   1.1  christos  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     41   1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     42   1.1  christos  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     43   1.1  christos  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     44   1.1  christos  *
     45   1.1  christos  * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved.
     46   1.1  christos  *
     47   1.1  christos  * Redistribution and use in source and binary forms, with or without
     48   1.1  christos  * modification, are permitted provided that the following conditions
     49   1.1  christos  * are met:
     50   1.1  christos  *
     51   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     52   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     53   1.1  christos  *
     54   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     55   1.1  christos  *    notice, this list of conditions and the following disclaimer in
     56   1.1  christos  *    the documentation and/or other materials provided with the
     57   1.1  christos  *    distribution.
     58   1.1  christos  *
     59   1.1  christos  * 3. The name(s) of the authors of this software must not be used to
     60   1.1  christos  *    endorse or promote products derived from this software without
     61   1.1  christos  *    prior written permission.
     62   1.1  christos  *
     63   1.1  christos  * 4. Redistributions of any form whatsoever must retain the following
     64   1.1  christos  *    acknowledgment:
     65   1.1  christos  *    "This product includes software developed by Paul Mackerras
     66   1.1  christos  *     <paulus (at) samba.org>".
     67   1.1  christos  *
     68   1.1  christos  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
     69   1.1  christos  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     70   1.1  christos  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
     71   1.1  christos  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     72   1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     73   1.1  christos  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     74   1.1  christos  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     75   1.1  christos  */
     76   1.1  christos 
     77   1.1  christos #include <sys/cdefs.h>
     78   1.1  christos #ifndef lint
     79   1.1  christos #if 0
     80   1.1  christos #define RCSID	"Id: sys-bsd.c,v 1.47 2000/04/13 12:04:23 paulus Exp "
     81   1.1  christos #else
     82   1.1  christos __RCSID("NetBSD: sys-bsd.c,v 1.68 2013/06/24 20:43:48 christos Exp ");
     83   1.1  christos #endif
     84   1.1  christos #endif
     85   1.1  christos 
     86   1.1  christos /*
     87   1.1  christos  * TODO:
     88   1.1  christos  */
     89   1.1  christos 
     90  1.10  christos #ifdef HAVE_CONFIG_H
     91  1.10  christos #include "config.h"
     92  1.10  christos #endif
     93  1.10  christos 
     94   1.1  christos #include <stdio.h>
     95   1.1  christos #include <string.h>
     96   1.1  christos #include <stdlib.h>
     97   1.1  christos #include <unistd.h>
     98   1.1  christos #include <errno.h>
     99   1.1  christos #include <fcntl.h>
    100   1.1  christos #include <termios.h>
    101   1.1  christos #include <signal.h>
    102   1.1  christos #include <vis.h>
    103   1.1  christos #include <sys/ioctl.h>
    104   1.1  christos #include <sys/types.h>
    105   1.1  christos #include <sys/socket.h>
    106   1.1  christos #include <sys/time.h>
    107   1.1  christos #include <sys/stat.h>
    108   1.1  christos #include <sys/param.h>
    109   1.1  christos #if defined(NetBSD1_2) || defined(__NetBSD_Version__)
    110   1.1  christos #include <util.h>
    111   1.1  christos #endif
    112  1.10  christos #ifdef PPP_WITH_FILTER
    113   1.1  christos #include <net/bpf.h>
    114   1.1  christos #endif
    115   1.1  christos 
    116   1.1  christos #include <net/if.h>
    117   1.1  christos #include <net/ppp_defs.h>
    118   1.1  christos #include <net/if_ppp.h>
    119   1.1  christos #include <net/route.h>
    120   1.1  christos #include <net/if_dl.h>
    121   1.1  christos #include <netinet/in.h>
    122   1.1  christos #ifdef __KAME__
    123   1.1  christos #include <netinet6/in6_var.h>
    124   1.1  christos #include <netinet6/nd6.h>
    125   1.1  christos #endif
    126   1.1  christos #include <ifaddrs.h>
    127   1.1  christos 
    128   1.9  christos #ifdef INET6
    129   1.9  christos 
    130   1.8  christos #define s6_addr32 __u6_addr.__u6_addr32	/* Non-standard */
    131   1.8  christos 
    132   1.8  christos #define IN6_SOCKADDR_FROM_EUI64(s, eui64) do { \
    133   1.8  christos 	(s)->sin6_family = AF_INET6; \
    134   1.8  christos 	(s)->sin6_addr.s6_addr32[0] = htonl(0xfe800000); \
    135   1.8  christos 	eui64_copy(eui64, (s)->sin6_addr.s6_addr32[2]); \
    136   1.8  christos 	} while(0)
    137   1.1  christos #ifndef IN6_LLADDR_FROM_EUI64
    138   1.1  christos #ifdef __KAME__
    139   1.1  christos #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {			\
    140   1.1  christos 	sin6.sin6_family = AF_INET6;				\
    141   1.1  christos 	sin6.sin6_len = sizeof(struct sockaddr_in6);		\
    142   1.1  christos 	sin6.sin6_addr.s6_addr[0] = 0xfe;			\
    143   1.1  christos 	sin6.sin6_addr.s6_addr[1] = 0x80;			\
    144   1.1  christos 	eui64_copy(eui64, sin6.sin6_addr.s6_addr[8]);		\
    145   1.1  christos } while (/*CONSTCOND*/0)
    146   1.1  christos #define IN6_IFINDEX(sin6, ifindex)	 			\
    147   1.1  christos     /* KAME ifindex hack */					\
    148   1.1  christos     *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] = htons(ifindex)
    149   1.1  christos #else
    150   1.1  christos #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do {			\
    151   1.1  christos 	memset(&sin6.s6_addr, 0, sizeof(struct in6_addr));	\
    152   1.1  christos 	sin6.s6_addr16[0] = htons(0xfe80);			\
    153   1.1  christos 	eui64_copy(eui64, sin6.s6_addr32[2]);			\
    154   1.1  christos } while (/*CONSTCOND*/0)
    155   1.9  christos #endif /* __KAME__ */
    156   1.9  christos #endif /* IN6_LLADDR_FROM_EUI64 */
    157   1.9  christos 
    158   1.9  christos #endif /* INET6 */
    159   1.1  christos 
    160   1.1  christos #if RTM_VERSION >= 3
    161   1.1  christos #include <sys/param.h>
    162   1.1  christos #if defined(NetBSD) && (NetBSD >= 199703)
    163   1.1  christos #include <netinet/if_inarp.h>
    164   1.1  christos #else	/* NetBSD 1.2D or later */
    165   1.1  christos #ifdef __FreeBSD__
    166   1.1  christos #include <netinet/if_ether.h>
    167   1.1  christos #else
    168   1.1  christos #include <net/if_ether.h>
    169   1.1  christos #endif
    170   1.1  christos #endif
    171   1.1  christos #endif
    172   1.1  christos 
    173   1.1  christos #include "pppd.h"
    174  1.10  christos #include "pppd-private.h"
    175   1.1  christos #include "fsm.h"
    176   1.1  christos #include "ipcp.h"
    177   1.1  christos 
    178   1.1  christos #ifdef RCSID
    179   1.1  christos static const char rcsid[] = RCSID;
    180   1.1  christos #endif
    181   1.1  christos 
    182   1.1  christos static int initdisc = -1;	/* Initial TTY discipline for ppp_fd */
    183   1.1  christos static int initfdflags = -1;	/* Initial file descriptor flags for ppp_fd */
    184   1.1  christos static int ppp_fd = -1;		/* fd which is set to PPP discipline */
    185   1.1  christos static int rtm_seq;
    186   1.1  christos 
    187   1.1  christos static int restore_term;	/* 1 => we've munged the terminal */
    188   1.1  christos static struct termios inittermios; /* Initial TTY termios */
    189   1.1  christos static struct winsize wsinfo;	/* Initial window size info */
    190   1.1  christos 
    191   1.1  christos static int loop_slave = -1;
    192   1.1  christos static int loop_master = -1;
    193   1.1  christos static int doing_cleanup = 0;
    194   1.1  christos static char loop_name[20];
    195   1.1  christos 
    196   1.1  christos static unsigned char inbuf[512]; /* buffer for chars read from loopback */
    197   1.1  christos 
    198   1.1  christos static int sock_fd;		/* socket for doing interface ioctls */
    199   1.1  christos #ifdef INET6
    200   1.1  christos static int sock6_fd = -1;	/* socket for doing ipv6 interface ioctls */
    201   1.1  christos #endif /* INET6 */
    202   1.1  christos static int ttyfd = -1;		/* the file descriptor of the tty */
    203   1.1  christos 
    204   1.1  christos static fd_set in_fds;		/* set of fds that wait_input waits for */
    205   1.1  christos static int max_in_fd;		/* highest fd set in in_fds */
    206   1.1  christos 
    207   1.1  christos static int if_is_up;		/* the interface is currently up */
    208   1.3     prlw1 #ifdef INET6
    209   1.2  christos static int if6_is_up;		/* the interface is currently up */
    210   1.3     prlw1 #endif /* INET6 */
    211   1.1  christos static u_int32_t ifaddrs[2];	/* local and remote addresses we set */
    212   1.1  christos static u_int32_t default_route_gateway;	/* gateway addr for default route */
    213   1.9  christos #ifdef INET6
    214   1.9  christos static eui64_t  default_route_gateway6; /* Gateway for default IPv6 route added */
    215   1.9  christos #endif /* INET6 */
    216   1.1  christos static u_int32_t proxy_arp_addr;	/* remote addr for proxy arp */
    217   1.1  christos 
    218   1.1  christos /* Prototypes for procedures local to this file. */
    219   1.1  christos static int get_flags(int);
    220   1.1  christos static void set_flags(int, int);
    221   1.1  christos static int dodefaultroute(u_int32_t, int);
    222   1.1  christos static int get_ether_addr(u_int32_t, struct sockaddr_dl *);
    223   1.1  christos static void restore_loop(void);	/* Transfer ppp unit back to loopback */
    224   1.2  christos static int setifstate(int, int);
    225   1.1  christos 
    226   1.1  christos 
    227   1.1  christos static void
    228   1.1  christos set_queue_size(const char *fmt, int fd) {
    229   1.1  christos #ifdef TIOCSQSIZE
    230   1.1  christos     int oqsize, qsize = 32768;
    231   1.1  christos 
    232   1.1  christos     /* Only for ptys */
    233   1.1  christos     if (ioctl(fd, TIOCGQSIZE, &oqsize) == -1)
    234   1.1  christos 	return;
    235   1.1  christos 
    236   1.1  christos     if (oqsize >= qsize)
    237   1.1  christos 	return;
    238   1.1  christos 
    239   1.1  christos     if (ioctl(fd, TIOCSQSIZE, &qsize) == -1)
    240   1.1  christos 	warn("%s: Cannot set tty queue size for %d from %d to %d", fmt, fd,
    241   1.1  christos 	    oqsize, qsize);
    242   1.1  christos     else
    243   1.1  christos 	notice("%s: Changed queue size of %d from %d to %d", fmt, fd, oqsize,
    244   1.1  christos 	    qsize);
    245   1.1  christos #endif
    246   1.1  christos }
    247   1.1  christos 
    248   1.1  christos /********************************************************************
    249   1.1  christos  *
    250   1.1  christos  * Functions to read and set the flags value in the device driver
    251   1.1  christos  */
    252   1.1  christos 
    253   1.1  christos static int
    254   1.1  christos get_flags(int fd)
    255   1.1  christos {
    256   1.1  christos     int flags;
    257   1.1  christos 
    258   1.1  christos     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) == -1)
    259   1.1  christos 	fatal("%s: ioctl(PPPIOCGFLAGS): %m", __func__);
    260   1.1  christos 
    261   1.1  christos     SYSDEBUG((LOG_DEBUG, "get flags = %x\n", flags));
    262   1.1  christos     return flags;
    263   1.1  christos }
    264   1.1  christos 
    265   1.1  christos /********************************************************************/
    266   1.1  christos 
    267   1.1  christos static void
    268   1.1  christos set_flags(int fd, int flags)
    269   1.1  christos {
    270   1.1  christos     SYSDEBUG((LOG_DEBUG, "set flags = %x\n", flags));
    271   1.1  christos 
    272   1.1  christos     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) == -1)
    273   1.1  christos 	fatal("%s: ioctl(PPPIOCSFLAGS, %x): %m", __func__, flags, errno);
    274   1.1  christos }
    275   1.1  christos 
    276   1.1  christos /*
    277   1.1  christos  * sys_init - System-dependent initialization.
    278   1.1  christos  */
    279   1.1  christos void
    280   1.1  christos sys_init(void)
    281   1.1  christos {
    282   1.1  christos     /* Get an internet socket for doing socket ioctl's on. */
    283   1.1  christos     if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    284   1.1  christos 	fatal("%s: Couldn't create IP socket: %m", __func__);
    285   1.1  christos 
    286   1.1  christos #ifdef INET6
    287   1.1  christos     if ((sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
    288   1.1  christos 	/* check it at runtime */
    289   1.1  christos 	sock6_fd = -1;
    290   1.1  christos     }
    291   1.1  christos #endif
    292   1.1  christos 
    293   1.1  christos     FD_ZERO(&in_fds);
    294   1.1  christos     max_in_fd = 0;
    295   1.1  christos }
    296   1.1  christos 
    297   1.1  christos /*
    298   1.1  christos  * sys_cleanup - restore any system state we modified before exiting:
    299   1.1  christos  * mark the interface down, delete default route and/or proxy arp entry.
    300   1.1  christos  * This should call die() because it's called from die().
    301   1.1  christos  */
    302   1.1  christos void
    303   1.1  christos sys_cleanup(void)
    304   1.1  christos {
    305   1.1  christos     struct ifreq ifr;
    306   1.1  christos 
    307   1.1  christos     doing_cleanup = 1;
    308   1.1  christos     if (if_is_up) {
    309   1.1  christos 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
    310   1.1  christos 	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) >= 0
    311   1.1  christos 	    && ((ifr.ifr_flags & IFF_UP) != 0)) {
    312   1.1  christos 	    ifr.ifr_flags &= ~IFF_UP;
    313   1.1  christos 	    ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
    314   1.1  christos 	}
    315   1.1  christos     }
    316   1.1  christos     if (ifaddrs[0] != 0)
    317   1.1  christos 	cifaddr(0, ifaddrs[0], ifaddrs[1]);
    318   1.1  christos     if (default_route_gateway)
    319   1.1  christos 	cifdefaultroute(0, 0, default_route_gateway);
    320   1.9  christos #ifdef INET6
    321   1.8  christos     if (default_route_gateway6.e32[0] != 0 || default_route_gateway6.e32[1] != 0)
    322   1.8  christos 	cif6defaultroute(0, default_route_gateway6, default_route_gateway6);
    323   1.9  christos #endif
    324   1.1  christos     if (proxy_arp_addr)
    325   1.1  christos 	cifproxyarp(0, proxy_arp_addr);
    326   1.1  christos     doing_cleanup = 0;
    327   1.1  christos }
    328   1.1  christos 
    329   1.1  christos /*
    330   1.1  christos  * sys_close - Clean up in a child process before execing.
    331   1.1  christos  */
    332   1.1  christos void
    333  1.10  christos ppp_sys_close()
    334   1.1  christos {
    335   1.1  christos     if (sock_fd >= 0)
    336   1.1  christos 	close(sock_fd);
    337   1.1  christos #ifdef INET6
    338   1.1  christos     if (sock6_fd >= 0)
    339   1.1  christos 	close(sock6_fd);
    340   1.1  christos #endif
    341   1.1  christos     if (loop_slave >= 0)
    342   1.1  christos 	close(loop_slave);
    343   1.1  christos     if (loop_master >= 0)
    344   1.1  christos 	close(loop_master);
    345   1.1  christos }
    346   1.1  christos 
    347   1.1  christos /*
    348   1.1  christos  * sys_check_options - check the options that the user specified
    349   1.1  christos  */
    350   1.1  christos int
    351   1.1  christos sys_check_options(void)
    352   1.1  christos {
    353   1.1  christos #ifndef CDTRCTS
    354   1.1  christos     if (crtscts == 2) {
    355   1.1  christos 	warn("%s: DTR/CTS flow control is not supported on this system",
    356   1.1  christos 	    __func__);
    357   1.1  christos 	return 0;
    358   1.1  christos     }
    359   1.1  christos #endif
    360   1.1  christos     return 1;
    361   1.1  christos }
    362   1.1  christos 
    363   1.1  christos /*
    364  1.10  christos  * ppp_check_kernel_support - check whether the system has any ppp interfaces
    365   1.4  christos  * (in fact we check whether we can create one)
    366   1.1  christos  */
    367   1.1  christos int
    368  1.10  christos ppp_check_kernel_support(void)
    369   1.1  christos {
    370   1.4  christos     int s;
    371   1.1  christos     extern char *no_ppp_msg;
    372   1.4  christos     struct ifreq ifr;
    373   1.1  christos 
    374   1.1  christos 
    375   1.1  christos     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    376   1.1  christos 	fatal("%s: socket: %m", __func__);
    377   1.1  christos 
    378   1.4  christos     (void)memset(&ifr, 0, sizeof(ifr));
    379   1.4  christos     strlcpy(ifr.ifr_name, "ppp0", sizeof(ifr.ifr_name));
    380   1.4  christos     if (ioctl(s, SIOCIFCREATE, &ifr) == -1) {
    381   1.4  christos 	int notmine = errno == EEXIST;
    382   1.4  christos 	(void)close(s);
    383   1.4  christos 	if (notmine)
    384   1.4  christos 	    return 1;
    385   1.4  christos 	goto out;
    386   1.4  christos     }
    387   1.4  christos     (void)ioctl(s, SIOCIFDESTROY, &ifr);
    388   1.1  christos     (void)close(s);
    389   1.4  christos     return 1;
    390   1.1  christos 
    391   1.4  christos out:
    392   1.1  christos     no_ppp_msg = "\
    393   1.1  christos This system lacks kernel support for PPP.  To include PPP support\n\
    394   1.1  christos in the kernel, please read the ppp(4) manual page.\n";
    395   1.4  christos     return 0;
    396   1.1  christos }
    397   1.1  christos 
    398   1.1  christos /*
    399   1.1  christos  * tty_establish_ppp - Turn the serial port into a ppp interface.
    400   1.1  christos  */
    401   1.1  christos int
    402   1.1  christos tty_establish_ppp(int fd)
    403   1.1  christos {
    404   1.1  christos     int pppdisc = PPPDISC;
    405   1.1  christos     int x;
    406   1.1  christos     ttyfd = fd;
    407   1.1  christos 
    408   1.1  christos     if (demand) {
    409   1.1  christos 	/*
    410   1.1  christos 	 * Demand mode - prime the old ppp device to relinquish the unit.
    411   1.1  christos 	 */
    412   1.1  christos 	if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
    413   1.1  christos 	    fatal("%s: ioctl(transfer ppp unit): %m", __func__);
    414   1.1  christos     }
    415   1.1  christos 
    416   1.1  christos     set_queue_size(__func__, fd);
    417   1.1  christos     /*
    418   1.1  christos      * Save the old line discipline of fd, and set it to PPP.
    419   1.1  christos      */
    420   1.1  christos     if (ioctl(fd, TIOCGETD, &initdisc) < 0)
    421   1.1  christos 	fatal("%s: ioctl(TIOCGETD): %m", __func__);
    422   1.1  christos     if (ioctl(fd, TIOCSETD, &pppdisc) < 0)
    423   1.1  christos 	fatal("%s: ioctl(TIOCSETD): %m", __func__);
    424   1.1  christos 
    425   1.1  christos     if (ioctl(fd, PPPIOCGUNIT, &x) < 0)
    426   1.1  christos 	fatal("%s: ioctl(PPPIOCGUNIT): %m", __func__);
    427   1.1  christos     if (!demand) {
    428   1.1  christos 	/*
    429   1.1  christos 	 * Find out which interface we were given.
    430   1.1  christos 	 */
    431   1.1  christos 	ifunit = x;
    432   1.1  christos     } else {
    433   1.1  christos 	/*
    434   1.1  christos 	 * Check that we got the same unit again.
    435   1.1  christos 	 */
    436   1.1  christos 	if (x != ifunit)
    437   1.1  christos 	    fatal("%s: transfer_ppp failed: wanted unit %d, got %d",
    438   1.1  christos 		__func__, ifunit, x);
    439   1.1  christos 	x = TTYDISC;
    440   1.1  christos 	if (ioctl(loop_slave, TIOCSETD, &x) == -1)
    441   1.1  christos 	    fatal("%s: ioctl(TIOCGETD): %m", __func__);
    442   1.1  christos     }
    443   1.1  christos 
    444   1.1  christos     ppp_fd = fd;
    445   1.1  christos 
    446   1.1  christos     /*
    447   1.1  christos      * Enable debug in the driver if requested.
    448   1.1  christos      */
    449   1.1  christos     if (kdebugflag) {
    450   1.1  christos 	x = get_flags(fd);
    451   1.1  christos 	x |= (kdebugflag & 0xFF) * SC_DEBUG;
    452   1.1  christos 	set_flags(fd, x);
    453   1.1  christos     }
    454   1.1  christos 
    455   1.1  christos     /*
    456   1.1  christos      * Set device for non-blocking reads.
    457   1.1  christos      */
    458   1.1  christos     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
    459   1.1  christos 	|| fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
    460   1.1  christos 	warn("%s: Couldn't set device to non-blocking mode: %m", __func__);
    461   1.1  christos     }
    462   1.1  christos 
    463   1.1  christos     return fd;
    464   1.1  christos }
    465   1.1  christos 
    466   1.1  christos /*
    467   1.1  christos  * restore_loop - reattach the ppp unit to the loopback.
    468   1.1  christos  */
    469   1.1  christos static void
    470   1.1  christos restore_loop(void)
    471   1.1  christos {
    472   1.1  christos     int x;
    473   1.1  christos 
    474   1.1  christos     set_queue_size(__func__, loop_slave);
    475   1.1  christos     /*
    476   1.1  christos      * Transfer the ppp interface back to the loopback.
    477   1.1  christos      */
    478   1.1  christos     if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
    479   1.1  christos 	fatal("%s: ioctl(transfer ppp unit): %m", __func__);
    480   1.1  christos     x = PPPDISC;
    481   1.1  christos     if (ioctl(loop_slave, TIOCSETD, &x) < 0)
    482   1.1  christos 	fatal("%s: ioctl(TIOCSETD): %m", __func__);
    483   1.1  christos 
    484   1.1  christos     /*
    485   1.1  christos      * Check that we got the same unit again.
    486   1.1  christos      */
    487   1.1  christos     if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0)
    488   1.1  christos 	fatal("%s: ioctl(PPPIOCGUNIT): %m", __func__);
    489   1.1  christos     if (x != ifunit)
    490   1.1  christos 	fatal("%s: transfer_ppp failed: wanted unit %d, got %d", __func__,
    491   1.1  christos 	    ifunit, x);
    492   1.1  christos     ppp_fd = loop_slave;
    493   1.1  christos }
    494   1.1  christos 
    495   1.1  christos 
    496   1.1  christos /*
    497   1.1  christos  * Determine if the PPP connection should still be present.
    498   1.1  christos  */
    499   1.1  christos extern int hungup;
    500   1.1  christos 
    501   1.1  christos /*
    502   1.1  christos  * tty_disestablish_ppp - Restore the serial port to normal operation.
    503   1.1  christos  * and reconnect the ppp unit to the loopback if in demand mode.
    504   1.1  christos  * This shouldn't call die() because it's called from die().
    505   1.1  christos  */
    506   1.1  christos void
    507   1.1  christos tty_disestablish_ppp(fd)
    508   1.1  christos     int fd;
    509   1.1  christos {
    510   1.1  christos     if (!doing_cleanup && demand)
    511   1.1  christos 	restore_loop();
    512   1.1  christos 
    513   1.1  christos     if (!hungup || demand) {
    514   1.1  christos 
    515   1.1  christos 	/* Flush the tty output buffer so that the TIOCSETD doesn't hang.  */
    516   1.1  christos 	if (tcflush(fd, TCIOFLUSH) < 0)
    517   1.1  christos 	    if (!doing_cleanup)
    518   1.1  christos 		warn("%s: tcflush failed: %m", __func__);
    519   1.1  christos 
    520   1.1  christos 	/* Restore old line discipline. */
    521   1.1  christos 	if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
    522   1.1  christos 	    if (!doing_cleanup)
    523   1.1  christos 		error("%s: ioctl(TIOCSETD): %m", __func__);
    524   1.1  christos 	initdisc = -1;
    525   1.1  christos 
    526   1.1  christos 	/* Reset non-blocking mode on fd. */
    527   1.1  christos 	if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
    528   1.1  christos 	    if (!doing_cleanup)
    529   1.1  christos 		warn("%s: Couldn't restore device fd flags: %m", __func__);
    530   1.1  christos     }
    531   1.1  christos     initfdflags = -1;
    532   1.1  christos 
    533   1.1  christos     if (fd == ppp_fd)
    534   1.1  christos 	ppp_fd = -1;
    535   1.1  christos }
    536   1.1  christos 
    537   1.1  christos /*
    538   1.1  christos  * cfg_bundle - configure the existing bundle.
    539   1.1  christos  * Used in demand mode.
    540   1.1  christos  */
    541   1.1  christos void
    542   1.1  christos cfg_bundle(int mrru, int mtru, int rssn, int tssn)
    543   1.1  christos {
    544   1.1  christos     abort();
    545   1.1  christos #ifdef notyet
    546   1.1  christos     int flags;
    547   1.1  christos     struct ifreq ifr;
    548   1.1  christos 
    549   1.1  christos     if (!new_style_driver)
    550   1.1  christos 	return;
    551   1.1  christos 
    552   1.1  christos     /* set the mrru, mtu and flags */
    553   1.1  christos     if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
    554   1.1  christos 	error("%s: Couldn't set MRRU: %m", __func__);
    555   1.1  christos     flags = get_flags(ppp_dev_fd);
    556   1.1  christos     flags &= ~(SC_MP_SHORTSEQ | SC_MP_XSHORTSEQ);
    557   1.1  christos     flags |= (rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
    558   1.1  christos 	    | (mrru? SC_MULTILINK: 0);
    559   1.1  christos 
    560   1.1  christos     set_flags(ppp_dev_fd, flags);
    561   1.1  christos 
    562   1.1  christos     /* connect up the channel */
    563   1.1  christos     if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
    564   1.1  christos 	fatal("%s: Couldn't attach to PPP unit %d: %m", __func__, ifunit);
    565   1.1  christos     add_fd(ppp_dev_fd);
    566   1.1  christos #endif
    567   1.1  christos }
    568   1.1  christos 
    569   1.1  christos /*
    570   1.1  christos  * make_new_bundle - create a new PPP unit (i.e. a bundle)
    571   1.1  christos  * and connect our channel to it.  This should only get called
    572   1.1  christos  * if `multilink' was set at the time establish_ppp was called.
    573   1.1  christos  * In demand mode this uses our existing bundle instead of making
    574   1.1  christos  * a new one.
    575   1.1  christos  */
    576   1.1  christos void
    577   1.1  christos make_new_bundle(int mrru, int mtru, int rssn, int tssn)
    578   1.1  christos {
    579   1.1  christos     abort();
    580   1.1  christos #ifdef notyet
    581   1.1  christos     if (!new_style_driver)
    582   1.1  christos 	return;
    583   1.1  christos 
    584   1.1  christos     /* make us a ppp unit */
    585   1.1  christos     if (make_ppp_unit() < 0)
    586   1.1  christos 	die(1);
    587   1.1  christos 
    588   1.1  christos     /* set the mrru, mtu and flags */
    589   1.1  christos     cfg_bundle(mrru, mtru, rssn, tssn);
    590   1.1  christos #endif
    591   1.1  christos }
    592   1.1  christos 
    593   1.1  christos /*
    594   1.1  christos  * bundle_attach - attach our link to a given PPP unit.
    595   1.1  christos  * We assume the unit is controlled by another pppd.
    596   1.1  christos  */
    597   1.1  christos int
    598   1.1  christos bundle_attach(int ifnum)
    599   1.1  christos {
    600   1.1  christos     abort();
    601   1.1  christos #ifdef notyet
    602   1.1  christos     if (!new_style_driver)
    603   1.1  christos 	return -1;
    604   1.1  christos 
    605   1.1  christos     if (ioctl(ppp_dev_fd, PPPIOCATTACH, &ifnum) < 0) {
    606   1.1  christos 	if (errno == ENXIO)
    607   1.1  christos 	    return 0;	/* doesn't still exist */
    608   1.1  christos 	fatal("%s: Couldn't attach to interface unit %d: %m", __func__, ifnum);
    609   1.1  christos     }
    610   1.1  christos     if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
    611   1.1  christos 	fatal("%s: Couldn't connect to interface unit %d: %m", __func__, ifnum);
    612   1.1  christos     set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_MULTILINK);
    613   1.1  christos 
    614   1.1  christos     ifunit = ifnum;
    615   1.1  christos #endif
    616   1.1  christos     return 1;
    617   1.1  christos }
    618   1.1  christos 
    619   1.1  christos /*
    620   1.1  christos  * destroy_bundle - tell the driver to destroy our bundle.
    621   1.1  christos  */
    622   1.1  christos void destroy_bundle(void)
    623   1.1  christos {
    624   1.1  christos #if notyet
    625   1.1  christos 	if (ppp_dev_fd >= 0) {
    626   1.1  christos 		close(ppp_dev_fd);
    627   1.1  christos 		remove_fd(ppp_dev_fd);
    628   1.1  christos 		ppp_dev_fd = -1;
    629   1.1  christos 	}
    630   1.1  christos #endif
    631   1.1  christos }
    632   1.1  christos 
    633   1.1  christos /*
    634   1.1  christos  * Check whether the link seems not to be 8-bit clean.
    635   1.1  christos  */
    636   1.1  christos void
    637   1.1  christos clean_check(void)
    638   1.1  christos {
    639   1.1  christos     int x;
    640   1.1  christos     char *s;
    641   1.1  christos 
    642   1.1  christos     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
    643   1.1  christos 	s = NULL;
    644   1.1  christos 	switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
    645   1.1  christos 	case SC_RCV_B7_0:
    646   1.1  christos 	    s = "bit 7 set to 1";
    647   1.1  christos 	    break;
    648   1.1  christos 	case SC_RCV_B7_1:
    649   1.1  christos 	    s = "bit 7 set to 0";
    650   1.1  christos 	    break;
    651   1.1  christos 	case SC_RCV_EVNP:
    652   1.1  christos 	    s = "odd parity";
    653   1.1  christos 	    break;
    654   1.1  christos 	case SC_RCV_ODDP:
    655   1.1  christos 	    s = "even parity";
    656   1.1  christos 	    break;
    657   1.1  christos 	}
    658   1.1  christos 	if (s != NULL) {
    659   1.1  christos 	    struct ppp_rawin win;
    660   1.1  christos 	    char buf[4 * sizeof(win.buf) + 1];
    661   1.1  christos 	    int i;
    662   1.1  christos 	    warn("%s: Serial link is not 8-bit clean:", __func__);
    663   1.1  christos 	    warn("%s: All received characters had %s", __func__, s);
    664   1.1  christos 	    if (ioctl(ppp_fd, PPPIOCGRAWIN, &win) == -1) {
    665   1.1  christos 		warn("%s: ioctl(PPPIOCGRAWIN): %s", __func__, strerror(errno));
    666   1.1  christos 		return;
    667   1.1  christos 	    }
    668   1.1  christos 	    for (i = 0; i < sizeof(win.buf); i++)
    669   1.1  christos 		win.buf[i] = win.buf[i] & 0x7f;
    670   1.1  christos 	    strvisx(buf, (char *)win.buf, win.count, VIS_CSTYLE);
    671   1.1  christos 	    warn("%s: Last %d characters were: %s", __func__, (int)win.count,
    672   1.1  christos 		buf);
    673   1.1  christos 	}
    674   1.1  christos     }
    675   1.1  christos }
    676   1.1  christos 
    677   1.1  christos 
    678   1.1  christos /*
    679   1.1  christos  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
    680   1.1  christos  * at the requested speed, etc.  If `local' is true, set CLOCAL
    681   1.1  christos  * regardless of whether the modem option was specified.
    682   1.1  christos  *
    683   1.1  christos  * For *BSD, we assume that speed_t values numerically equal bits/second.
    684   1.1  christos  */
    685   1.1  christos void
    686   1.1  christos set_up_tty(int fd, int local)
    687   1.1  christos {
    688   1.1  christos     struct termios tios;
    689   1.1  christos 
    690   1.1  christos     if (tcgetattr(fd, &tios) < 0)
    691   1.1  christos 	fatal("%s: tcgetattr: %m", __func__);
    692   1.1  christos 
    693   1.1  christos     if (!restore_term) {
    694   1.1  christos 	inittermios = tios;
    695   1.1  christos 	ioctl(fd, TIOCGWINSZ, &wsinfo);
    696   1.1  christos     }
    697   1.1  christos 
    698   1.1  christos     set_queue_size(__func__, fd);
    699   1.1  christos 
    700   1.1  christos     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
    701   1.1  christos     if (crtscts > 0 && !local) {
    702   1.1  christos         if (crtscts == 2) {
    703   1.1  christos #ifdef CDTRCTS
    704   1.1  christos             tios.c_cflag |= CDTRCTS;
    705   1.1  christos #endif
    706   1.1  christos 	} else
    707   1.1  christos 	    tios.c_cflag |= CRTSCTS;
    708   1.1  christos     } else if (crtscts < 0) {
    709   1.1  christos 	tios.c_cflag &= ~CRTSCTS;
    710   1.1  christos #ifdef CDTRCTS
    711   1.1  christos 	tios.c_cflag &= ~CDTRCTS;
    712   1.1  christos #endif
    713   1.1  christos     }
    714   1.1  christos 
    715   1.1  christos     tios.c_cflag |= CS8 | CREAD | HUPCL;
    716   1.1  christos     if (local || !modem)
    717   1.1  christos 	tios.c_cflag |= CLOCAL;
    718   1.1  christos     tios.c_iflag = IGNBRK | IGNPAR;
    719   1.1  christos     tios.c_oflag = 0;
    720   1.1  christos     tios.c_lflag = 0;
    721   1.1  christos     tios.c_cc[VMIN] = 1;
    722   1.1  christos     tios.c_cc[VTIME] = 0;
    723   1.1  christos 
    724   1.1  christos     if (crtscts == -2) {
    725   1.1  christos 	tios.c_iflag |= IXON | IXOFF;
    726   1.1  christos 	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
    727   1.1  christos 	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
    728   1.1  christos     }
    729   1.1  christos 
    730   1.1  christos     if (inspeed) {
    731   1.1  christos 	cfsetospeed(&tios, inspeed);
    732   1.1  christos 	cfsetispeed(&tios, inspeed);
    733   1.1  christos     } else {
    734   1.1  christos 	inspeed = cfgetospeed(&tios);
    735   1.1  christos 	/*
    736   1.1  christos 	 * We can't proceed if the serial port speed is 0,
    737   1.1  christos 	 * since that implies that the serial port is disabled.
    738   1.1  christos 	 */
    739   1.1  christos 	if (inspeed == 0)
    740   1.1  christos 	    fatal("%s: Baud rate for %s is 0; need explicit baud rate",
    741   1.1  christos 		__func__, devnam);
    742   1.1  christos     }
    743   1.1  christos     baud_rate = inspeed;
    744   1.1  christos 
    745   1.1  christos     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0)
    746   1.1  christos 	fatal("%s: tcsetattr: %m", __func__);
    747   1.1  christos 
    748   1.1  christos     restore_term = 1;
    749   1.1  christos }
    750   1.1  christos 
    751   1.1  christos /*
    752   1.1  christos  * restore_tty - restore the terminal to the saved settings.
    753   1.1  christos  */
    754   1.1  christos void
    755   1.1  christos restore_tty(int fd)
    756   1.1  christos {
    757   1.1  christos     if (restore_term) {
    758   1.1  christos 	if (!default_device) {
    759   1.1  christos 	    /*
    760   1.1  christos 	     * Turn off echoing, because otherwise we can get into
    761   1.1  christos 	     * a loop with the tty and the modem echoing to each other.
    762   1.1  christos 	     * We presume we are the sole user of this tty device, so
    763   1.1  christos 	     * when we close it, it will revert to its defaults anyway.
    764   1.1  christos 	     */
    765   1.1  christos 	    inittermios.c_lflag &= ~(ECHO | ECHONL);
    766   1.1  christos 	}
    767   1.1  christos 	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
    768   1.1  christos 	    if (errno != ENXIO)
    769   1.1  christos 		warn("%s: tcsetattr: %m", __func__);
    770   1.1  christos 	ioctl(fd, TIOCSWINSZ, &wsinfo);
    771   1.1  christos 	restore_term = 0;
    772   1.1  christos     }
    773   1.1  christos }
    774   1.1  christos 
    775   1.1  christos /*
    776   1.1  christos  * setdtr - control the DTR line on the serial port.
    777   1.1  christos  * This is called from die(), so it shouldn't call die().
    778   1.1  christos  */
    779   1.1  christos void
    780   1.1  christos setdtr(int fd, int on)
    781   1.1  christos {
    782   1.1  christos     int modembits = TIOCM_DTR;
    783   1.1  christos 
    784   1.1  christos     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
    785   1.1  christos }
    786   1.1  christos 
    787   1.1  christos #ifdef INET6
    788   1.1  christos /*
    789   1.1  christos  * sif6addr - Config the interface with an IPv6 link-local address
    790   1.1  christos  */
    791   1.1  christos int
    792   1.1  christos sif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
    793   1.1  christos {
    794   1.1  christos #ifdef __KAME__
    795   1.1  christos     int ifindex;
    796   1.1  christos     struct in6_aliasreq addreq6;
    797   1.1  christos 
    798   1.1  christos     if (sock6_fd < 0) {
    799   1.1  christos 	fatal("%s: No IPv6 socket available", __func__);
    800   1.1  christos 	/*NOTREACHED*/
    801   1.1  christos     }
    802   1.1  christos 
    803   1.1  christos     /* actually, this part is not kame local - RFC2553 conformant */
    804   1.1  christos     ifindex = if_nametoindex(ifname);
    805   1.1  christos     if (ifindex == 0) {
    806   1.1  christos 	error("%s: sifaddr6: no interface %s", __func__, ifname);
    807   1.1  christos 	return 0;
    808   1.1  christos     }
    809   1.1  christos 
    810   1.1  christos     memset(&addreq6, 0, sizeof(addreq6));
    811   1.1  christos     strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name));
    812   1.1  christos 
    813   1.1  christos     /* my addr */
    814   1.1  christos     IN6_LLADDR_FROM_EUI64(addreq6.ifra_addr, our_eui64);
    815   1.1  christos     IN6_IFINDEX(addreq6.ifra_addr, ifindex);
    816   1.1  christos 
    817   1.1  christos #ifdef notdef
    818   1.1  christos     /* his addr */
    819   1.1  christos     IN6_LLADDR_FROM_EUI64(addreq6.ifra_dstaddr, his_eui64);
    820   1.1  christos     IN6_IFINDEX(addreq6.ifra_dstaddr, ifindex);
    821   1.1  christos #endif
    822   1.1  christos 
    823   1.1  christos     /* prefix mask: 72bit */
    824   1.1  christos     addreq6.ifra_prefixmask.sin6_family = AF_INET6;
    825   1.1  christos     addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
    826   1.1  christos     memset(&addreq6.ifra_prefixmask.sin6_addr, 0xff,
    827   1.1  christos 	sizeof(addreq6.ifra_prefixmask.sin6_addr) - sizeof(our_eui64));
    828   1.1  christos     memset((char *)&addreq6.ifra_prefixmask.sin6_addr +
    829   1.1  christos 	sizeof(addreq6.ifra_prefixmask.sin6_addr) - sizeof(our_eui64), 0x00,
    830   1.1  christos 	sizeof(our_eui64));
    831   1.1  christos 
    832   1.1  christos     /* address lifetime (infty) */
    833   1.1  christos     addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
    834   1.1  christos     addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
    835   1.1  christos 
    836   1.1  christos     if (ioctl(sock6_fd, SIOCAIFADDR_IN6, &addreq6) < 0) {
    837   1.1  christos 	error("%s: sif6addr: ioctl(SIOCAIFADDR_IN6): %m", __func__);
    838   1.1  christos 	return 0;
    839   1.1  christos     }
    840   1.1  christos 
    841   1.1  christos     return 1;
    842   1.1  christos #else
    843   1.1  christos     struct in6_ifreq ifr6;
    844   1.1  christos     struct ifreq ifr;
    845   1.1  christos     struct in6_rtmsg rt6;
    846   1.1  christos 
    847   1.1  christos     if (sock6_fd < 0) {
    848   1.1  christos 	fatal("%s: No IPv6 socket available", __func__);
    849   1.1  christos 	/*NOTREACHED*/
    850   1.1  christos     }
    851   1.1  christos 
    852   1.1  christos     memset(&ifr, 0, sizeof (ifr));
    853   1.1  christos     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
    854   1.1  christos     if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
    855   1.1  christos 	error("%s: sif6addr: ioctl(SIOCGIFINDEX): %m", __func__);
    856   1.1  christos 	return 0;
    857   1.1  christos     }
    858   1.1  christos 
    859   1.1  christos     /* Local interface */
    860   1.1  christos     memset(&ifr6, 0, sizeof(ifr6));
    861   1.1  christos     IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
    862   1.1  christos     ifr6.ifr6_ifindex = ifindex;
    863   1.1  christos     ifr6.ifr6_prefixlen = 10;
    864   1.1  christos 
    865   1.1  christos     if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
    866   1.1  christos 	error("%s: sif6addr: ioctl(SIOCSIFADDR): %m", __func__);
    867   1.1  christos 	return 0;
    868   1.1  christos     }
    869   1.1  christos 
    870   1.1  christos     /* Route to remote host */
    871   1.1  christos     memset(&rt6, 0, sizeof(rt6));
    872   1.1  christos     IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
    873   1.1  christos     rt6.rtmsg_flags = RTF_UP;
    874   1.1  christos     rt6.rtmsg_dst_len = 10;
    875   1.1  christos     rt6.rtmsg_ifindex = ifr.ifr_ifindex;
    876   1.1  christos     rt6.rtmsg_metric = 1;
    877   1.1  christos 
    878   1.1  christos     if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
    879   1.1  christos 	error("%s: sif6addr: ioctl(SIOCADDRT): %m", __func__);
    880   1.1  christos 	return 0;
    881   1.1  christos     }
    882   1.1  christos 
    883   1.1  christos     return 1;
    884   1.1  christos #endif
    885   1.1  christos }
    886   1.1  christos 
    887   1.1  christos 
    888   1.1  christos /*
    889   1.1  christos  * cif6addr - Remove IPv6 address from interface
    890   1.1  christos  */
    891   1.1  christos int
    892   1.1  christos cif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
    893   1.1  christos {
    894   1.1  christos #ifdef __KAME__
    895   1.1  christos     int ifindex;
    896   1.1  christos     struct in6_ifreq delreq6;
    897   1.1  christos 
    898   1.1  christos     if (sock6_fd < 0) {
    899   1.1  christos 	fatal("%s: No IPv6 socket available", __func__);
    900   1.1  christos 	/*NOTREACHED*/
    901   1.1  christos     }
    902   1.1  christos 
    903   1.1  christos     /* actually, this part is not kame local - RFC2553 conformant */
    904   1.1  christos     ifindex = if_nametoindex(ifname);
    905   1.1  christos     if (ifindex == 0) {
    906   1.1  christos 	error("%s: cifaddr6: no interface %s", __func__, ifname);
    907   1.1  christos 	return 0;
    908   1.1  christos     }
    909   1.1  christos 
    910   1.1  christos     memset(&delreq6, 0, sizeof(delreq6));
    911   1.1  christos     strlcpy(delreq6.ifr_name, ifname, sizeof(delreq6.ifr_name));
    912   1.1  christos 
    913   1.1  christos     /* my addr */
    914   1.1  christos     IN6_LLADDR_FROM_EUI64(delreq6.ifr_ifru.ifru_addr, our_eui64);
    915   1.1  christos     IN6_IFINDEX(delreq6.ifr_ifru.ifru_addr, ifindex);
    916   1.1  christos 
    917   1.1  christos     if (ioctl(sock6_fd, SIOCDIFADDR_IN6, &delreq6) < 0) {
    918   1.1  christos 	error("%s: cif6addr: ioctl(SIOCDIFADDR_IN6): %m", __func__);
    919   1.1  christos 	return 0;
    920   1.1  christos     }
    921   1.1  christos 
    922   1.1  christos     return 1;
    923   1.1  christos #else
    924   1.1  christos     struct ifreq ifr;
    925   1.1  christos     struct in6_ifreq ifr6;
    926   1.1  christos 
    927   1.1  christos     if (sock6_fd < 0) {
    928   1.1  christos 	fatal("%s: No IPv6 socket available", __func__);
    929   1.1  christos 	/*NOTREACHED*/
    930   1.1  christos     }
    931   1.1  christos 
    932   1.1  christos     memset(&ifr, 0, sizeof(ifr));
    933   1.1  christos     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
    934   1.1  christos     if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
    935   1.1  christos 	error("%s: cif6addr: ioctl(SIOCGIFINDEX): %m", __func__);
    936   1.1  christos 	return 0;
    937   1.1  christos     }
    938   1.1  christos 
    939   1.1  christos     memset(&ifr6, 0, sizeof(ifr6));
    940   1.1  christos     IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
    941   1.1  christos     ifr6.ifr6_ifindex = ifr.ifr_ifindex;
    942   1.1  christos     ifr6.ifr6_prefixlen = 10;
    943   1.1  christos 
    944   1.1  christos     if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
    945   1.1  christos 	if (errno != EADDRNOTAVAIL) {
    946   1.1  christos 	    if (! ok_error (errno))
    947   1.1  christos 		error("%s: cif6addr: ioctl(SIOCDIFADDR): %m", __func__);
    948   1.1  christos 	}
    949   1.1  christos         else {
    950   1.1  christos 	    warn("%s: cif6addr: ioctl(SIOCDIFADDR): No such address", __func__);
    951   1.1  christos 	}
    952   1.1  christos         return (0);
    953   1.1  christos     }
    954   1.1  christos     return 1;
    955   1.1  christos #endif
    956   1.1  christos }
    957   1.1  christos #endif /* INET6 */
    958   1.1  christos 
    959   1.1  christos /*
    960   1.1  christos  * get_pty - get a pty master/slave pair and chown the slave side
    961   1.1  christos  * to the uid given.  Assumes slave_name points to >= 12 bytes of space.
    962   1.1  christos  */
    963   1.1  christos int
    964   1.1  christos get_pty(int *master_fdp, int *slave_fdp, char *slave_name, int uid)
    965   1.1  christos {
    966   1.1  christos     struct termios tios;
    967   1.1  christos 
    968   1.1  christos     if (openpty(master_fdp, slave_fdp, slave_name, NULL, NULL) < 0)
    969   1.1  christos 	return 0;
    970   1.1  christos 
    971   1.1  christos     set_queue_size(__func__, *master_fdp);
    972   1.1  christos     set_queue_size(__func__, *slave_fdp);
    973   1.1  christos     fchown(*slave_fdp, uid, -1);
    974   1.1  christos     fchmod(*slave_fdp, S_IRUSR | S_IWUSR);
    975   1.1  christos     if (tcgetattr(*slave_fdp, &tios) == 0) {
    976   1.1  christos 	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
    977   1.1  christos 	tios.c_cflag |= CS8 | CREAD | CLOCAL;
    978   1.1  christos 	tios.c_iflag  = IGNPAR;
    979   1.1  christos 	tios.c_oflag  = 0;
    980   1.1  christos 	tios.c_lflag  = 0;
    981   1.1  christos 	if (tcsetattr(*slave_fdp, TCSAFLUSH, &tios) < 0)
    982   1.1  christos 	    warn("%s: couldn't set attributes on pty: %m", __func__);
    983   1.1  christos     } else
    984   1.1  christos 	warn("%s: couldn't get attributes on pty: %m", __func__);
    985   1.1  christos 
    986   1.1  christos     return 1;
    987   1.1  christos }
    988   1.1  christos 
    989   1.1  christos 
    990   1.1  christos /*
    991   1.1  christos  * open_ppp_loopback - open the device we use for getting
    992   1.1  christos  * packets in demand mode, and connect it to a ppp interface.
    993   1.1  christos  * Here we use a pty.
    994   1.1  christos  */
    995   1.1  christos int
    996   1.1  christos open_ppp_loopback(void)
    997   1.1  christos {
    998   1.1  christos     int flags;
    999   1.1  christos     struct termios tios;
   1000   1.1  christos     int pppdisc = PPPDISC;
   1001   1.1  christos 
   1002   1.1  christos     if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0)
   1003   1.1  christos 	fatal("%s: No free pty for loopback", __func__);
   1004   1.1  christos     SYSDEBUG(("using %s for loopback", loop_name));
   1005   1.1  christos 
   1006   1.1  christos     if (tcgetattr(loop_slave, &tios) == 0) {
   1007   1.1  christos 	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
   1008   1.1  christos 	tios.c_cflag |= CS8 | CREAD | CLOCAL;
   1009   1.1  christos 	tios.c_iflag = IGNPAR;
   1010   1.1  christos 	tios.c_oflag = 0;
   1011   1.1  christos 	tios.c_lflag = 0;
   1012   1.1  christos 	if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
   1013   1.1  christos 	    warn("%s: couldn't set attributes on loopback: %m", __func__);
   1014   1.1  christos     }
   1015   1.1  christos 
   1016   1.1  christos     flags = fcntl(loop_master, F_GETFL);
   1017   1.1  christos     if (flags == -1 || fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
   1018   1.1  christos 	    warn("%s: couldn't set master loopback to nonblock: %m", __func__);
   1019   1.1  christos 
   1020   1.1  christos     flags = fcntl(loop_slave, F_GETFL);
   1021   1.1  christos     if (flags == -1 || fcntl(loop_slave, F_SETFL, flags | O_NONBLOCK) == -1)
   1022   1.1  christos 	    warn("%s: couldn't set slave loopback to nonblock: %m", __func__);
   1023   1.1  christos 
   1024   1.1  christos     ppp_fd = loop_slave;
   1025   1.1  christos     if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0)
   1026   1.1  christos 	fatal("%s: ioctl(TIOCSETD): %m", __func__);
   1027   1.1  christos 
   1028   1.1  christos     /*
   1029   1.1  christos      * Find out which interface we were given.
   1030   1.1  christos      */
   1031   1.1  christos     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
   1032   1.1  christos 	fatal("%s: ioctl(PPPIOCGUNIT): %m", __func__);
   1033   1.1  christos 
   1034   1.1  christos     /*
   1035   1.1  christos      * Enable debug in the driver if requested.
   1036   1.1  christos      */
   1037   1.1  christos     if (kdebugflag) {
   1038   1.1  christos 	flags = get_flags(ppp_fd);
   1039   1.1  christos 	flags |= (kdebugflag & 0xFF) * SC_DEBUG;
   1040   1.1  christos 	set_flags(ppp_fd, flags);
   1041   1.1  christos     }
   1042   1.1  christos 
   1043   1.1  christos     return loop_master;
   1044   1.1  christos }
   1045   1.1  christos 
   1046   1.1  christos 
   1047   1.1  christos /*
   1048   1.1  christos  * output - Output PPP packet.
   1049   1.1  christos  */
   1050   1.1  christos void
   1051   1.1  christos output(int unit, u_char *p, int len)
   1052   1.1  christos {
   1053   1.1  christos     if (debug)
   1054   1.1  christos 	dbglog("sent %P", p, len);
   1055   1.1  christos 
   1056   1.1  christos     if (write(ttyfd, p, len) < 0) {
   1057   1.1  christos 	if (errno != EIO)
   1058   1.1  christos 	    error("%s: write: %m", __func__);
   1059   1.1  christos     }
   1060   1.1  christos }
   1061   1.1  christos 
   1062   1.1  christos 
   1063   1.1  christos /*
   1064   1.1  christos  * wait_input - wait until there is data available,
   1065   1.1  christos  * for the length of time specified by *timo (indefinite
   1066   1.1  christos  * if timo is NULL).
   1067   1.1  christos  */
   1068   1.1  christos void
   1069   1.1  christos wait_input(struct timeval *timo)
   1070   1.1  christos {
   1071   1.6       mrg     fd_set ready, eready;
   1072   1.1  christos     int n;
   1073   1.1  christos 
   1074   1.1  christos     ready = in_fds;
   1075   1.6       mrg     eready = in_fds;
   1076   1.6       mrg     n = select(max_in_fd + 1, &ready, NULL, &eready, timo);
   1077   1.1  christos     if (n < 0 && errno != EINTR)
   1078   1.1  christos 	fatal("%s: select: %m", __func__);
   1079   1.1  christos }
   1080   1.1  christos 
   1081   1.1  christos 
   1082   1.1  christos /*
   1083   1.1  christos  * add_fd - add an fd to the set that wait_input waits for.
   1084   1.1  christos  */
   1085   1.1  christos void add_fd(int fd)
   1086   1.1  christos {
   1087   1.1  christos     if (fd >= FD_SETSIZE)
   1088   1.1  christos 	fatal("%s: descriptor too big", __func__);
   1089   1.1  christos     FD_SET(fd, &in_fds);
   1090   1.1  christos     if (fd > max_in_fd)
   1091   1.1  christos 	max_in_fd = fd;
   1092   1.1  christos }
   1093   1.1  christos 
   1094   1.1  christos /*
   1095   1.1  christos  * remove_fd - remove an fd from the set that wait_input waits for.
   1096   1.1  christos  */
   1097   1.1  christos void remove_fd(int fd)
   1098   1.1  christos {
   1099   1.1  christos     FD_CLR(fd, &in_fds);
   1100   1.1  christos }
   1101   1.1  christos 
   1102   1.1  christos #if 0
   1103   1.1  christos /*
   1104   1.1  christos  * wait_loop_output - wait until there is data available on the
   1105   1.1  christos  * loopback, for the length of time specified by *timo (indefinite
   1106   1.1  christos  * if timo is NULL).
   1107   1.1  christos  */
   1108   1.1  christos void
   1109   1.1  christos wait_loop_output(struct timeval *timo)
   1110   1.1  christos {
   1111   1.1  christos     fd_set ready;
   1112   1.1  christos     int n;
   1113   1.1  christos 
   1114   1.1  christos     FD_ZERO(&ready);
   1115   1.1  christos     if (loop_master >= FD_SETSIZE)
   1116   1.1  christos 	fatal("%s: descriptor too big", __func__);
   1117   1.1  christos     FD_SET(loop_master, &ready);
   1118   1.1  christos     n = select(loop_master + 1, &ready, NULL, &ready, timo);
   1119   1.1  christos     if (n < 0 && errno != EINTR)
   1120   1.1  christos 	fatal("%s: select: %m", __func__);
   1121   1.1  christos }
   1122   1.1  christos 
   1123   1.1  christos 
   1124   1.1  christos /*
   1125   1.1  christos  * wait_time - wait for a given length of time or until a
   1126   1.1  christos  * signal is received.
   1127   1.1  christos  */
   1128   1.1  christos void
   1129   1.1  christos wait_time(struct timeval *timo)
   1130   1.1  christos {
   1131   1.1  christos     int n;
   1132   1.1  christos 
   1133   1.1  christos     n = select(0, NULL, NULL, NULL, timo);
   1134   1.1  christos     if (n < 0 && errno != EINTR)
   1135   1.1  christos 	fatal("%s: select: %m", __func__);
   1136   1.1  christos }
   1137   1.1  christos #endif
   1138   1.1  christos 
   1139   1.1  christos 
   1140   1.1  christos /*
   1141   1.1  christos  * read_packet - get a PPP packet from the serial device.
   1142   1.1  christos  */
   1143   1.1  christos int
   1144   1.1  christos read_packet(u_char *buf)
   1145   1.1  christos {
   1146   1.1  christos     int len;
   1147   1.1  christos 
   1148   1.1  christos     if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
   1149   1.1  christos 	if (errno == EWOULDBLOCK || errno == EINTR)
   1150   1.1  christos 	    return -1;
   1151   1.1  christos 	fatal("%s: read: %m", __func__);
   1152   1.1  christos     }
   1153   1.1  christos     return len;
   1154   1.1  christos }
   1155   1.1  christos 
   1156   1.1  christos 
   1157   1.1  christos /*
   1158   1.1  christos  * get_loop_output - read characters from the loopback, form them
   1159   1.1  christos  * into frames, and detect when we want to bring the real link up.
   1160   1.1  christos  * Return value is 1 if we need to bring up the link, 0 otherwise.
   1161   1.1  christos  */
   1162   1.1  christos int
   1163   1.1  christos get_loop_output(void)
   1164   1.1  christos {
   1165   1.1  christos     int rv = 0;
   1166   1.1  christos     int n;
   1167   1.1  christos 
   1168   1.1  christos     while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
   1169   1.1  christos 	if (loop_chars(inbuf, n))
   1170   1.1  christos 	    rv = 1;
   1171   1.1  christos     }
   1172   1.1  christos 
   1173   1.1  christos     if (n == 0)
   1174   1.1  christos 	fatal("%s: eof on loopback", __func__);
   1175   1.1  christos     if (n == -1 && errno != EWOULDBLOCK)
   1176   1.1  christos 	fatal("%s: read from loopback: %m", __func__);
   1177   1.1  christos 
   1178   1.1  christos     return rv;
   1179   1.1  christos }
   1180   1.1  christos 
   1181   1.1  christos 
   1182   1.1  christos /*
   1183  1.10  christos  * ppp_set_mtu - set the MTU on the PPP network interface.
   1184   1.1  christos  */
   1185   1.1  christos void
   1186  1.10  christos ppp_set_mtu(int unit, int mtu)
   1187   1.1  christos {
   1188   1.1  christos     struct ifreq ifr;
   1189   1.1  christos 
   1190   1.1  christos     SYSDEBUG((LOG_DEBUG, "netif_set_mtu: mtu = %d\n", mtu));
   1191   1.1  christos 
   1192   1.1  christos     memset(&ifr, '\0', sizeof (ifr));
   1193   1.1  christos     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   1194   1.1  christos     ifr.ifr_mtu = mtu;
   1195   1.1  christos 
   1196   1.1  christos     if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
   1197   1.1  christos 	fatal("%s: ioctl(SIOCSIFMTU): %m", __func__);
   1198   1.1  christos }
   1199   1.1  christos 
   1200   1.1  christos /*
   1201  1.10  christos  * ppp_get_mtu - get the MTU on the PPP network interface.
   1202   1.1  christos  */
   1203   1.1  christos int
   1204  1.10  christos ppp_get_mtu(int unit)
   1205   1.1  christos {
   1206   1.1  christos     struct ifreq ifr;
   1207   1.1  christos 
   1208   1.1  christos     memset (&ifr, '\0', sizeof (ifr));
   1209   1.1  christos     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   1210   1.1  christos 
   1211   1.1  christos     if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
   1212   1.1  christos 	error("%s: ioctl(SIOCGIFMTU): %m", __func__);
   1213   1.1  christos 	return 0;
   1214   1.1  christos     }
   1215   1.1  christos     return ifr.ifr_mtu;
   1216   1.1  christos }
   1217   1.1  christos 
   1218   1.1  christos /*
   1219   1.1  christos  * tty_send_config - configure the transmit characteristics of
   1220   1.1  christos  * the ppp interface.
   1221   1.1  christos  */
   1222   1.1  christos void
   1223   1.1  christos tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
   1224   1.1  christos {
   1225   1.1  christos     u_int x;
   1226   1.1  christos #if 0
   1227   1.1  christos     /* Linux code does not do anything with the mtu here */
   1228   1.1  christos     ifnet_set_mtu(-1, mtu);
   1229   1.1  christos #endif
   1230   1.1  christos 
   1231   1.1  christos     if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
   1232   1.1  christos 	fatal("%s: ioctl(PPPIOCSASYNCMAP): %m", __func__);
   1233   1.1  christos 
   1234   1.1  christos     x = get_flags(ppp_fd);
   1235   1.1  christos     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
   1236   1.1  christos     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
   1237  1.10  christos     x = ppp_sync_serial() ? x | SC_SYNC : x & ~SC_SYNC;
   1238   1.1  christos     set_flags(ppp_fd, x);
   1239   1.1  christos }
   1240   1.1  christos 
   1241   1.1  christos 
   1242   1.1  christos /*
   1243   1.1  christos  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
   1244   1.1  christos  */
   1245   1.1  christos void
   1246   1.1  christos tty_set_xaccm(ext_accm accm)
   1247   1.1  christos {
   1248   1.1  christos     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
   1249   1.1  christos 	warn("%s: ioctl(set extended ACCM): %m", __func__);
   1250   1.1  christos }
   1251   1.1  christos 
   1252   1.1  christos 
   1253   1.1  christos /*
   1254   1.1  christos  * ppp_recv_config - configure the receive-side characteristics of
   1255   1.1  christos  * the ppp interface.
   1256   1.1  christos  */
   1257   1.1  christos void
   1258   1.1  christos tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
   1259   1.1  christos {
   1260   1.1  christos     int x;
   1261   1.1  christos 
   1262   1.1  christos     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
   1263   1.1  christos 	fatal("%s: ioctl(PPPIOCSMRU): %m", __func__);
   1264   1.1  christos     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
   1265   1.1  christos 	fatal("%s: ioctl(PPPIOCSRASYNCMAP): %m", __func__);
   1266   1.1  christos     x = get_flags(ppp_fd);
   1267   1.1  christos     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
   1268   1.1  christos     set_flags(ppp_fd, x);
   1269   1.1  christos }
   1270   1.1  christos 
   1271   1.1  christos /*
   1272   1.1  christos  * ccp_test - ask kernel whether a given compression method
   1273   1.1  christos  * is acceptable for use.  Returns 1 if the method and parameters
   1274   1.1  christos  * are OK, 0 if the method is known but the parameters are not OK
   1275   1.1  christos  * (e.g. code size should be reduced), or -1 if the method is unknown.
   1276   1.1  christos  */
   1277   1.1  christos int
   1278   1.1  christos ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
   1279   1.1  christos {
   1280   1.1  christos     struct ppp_option_data data;
   1281   1.1  christos 
   1282   1.1  christos     data.ptr = opt_ptr;
   1283   1.1  christos     data.length = opt_len;
   1284   1.1  christos     data.transmit = for_transmit;
   1285   1.1  christos     if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
   1286   1.1  christos 	return 1;
   1287   1.1  christos     return (errno == ENOBUFS)? 0: -1;
   1288   1.1  christos }
   1289   1.1  christos 
   1290   1.1  christos /*
   1291   1.1  christos  * ccp_flags_set - inform kernel about the current state of CCP.
   1292   1.1  christos  */
   1293   1.1  christos void
   1294   1.1  christos ccp_flags_set(int unit, int isopen, int isup)
   1295   1.1  christos {
   1296   1.1  christos     int x;
   1297   1.1  christos 
   1298   1.1  christos     x = get_flags(ppp_fd);
   1299   1.1  christos     x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
   1300   1.1  christos     x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
   1301   1.1  christos     set_flags(ppp_fd, x);
   1302   1.1  christos }
   1303   1.1  christos 
   1304   1.1  christos /*
   1305   1.1  christos  * ccp_fatal_error - returns 1 if decompression was disabled as a
   1306   1.1  christos  * result of an error detected after decompression of a packet,
   1307   1.1  christos  * 0 otherwise.  This is necessary because of patent nonsense.
   1308   1.1  christos  */
   1309   1.1  christos int
   1310   1.1  christos ccp_fatal_error(int unit)
   1311   1.1  christos {
   1312   1.1  christos     int x;
   1313   1.1  christos 
   1314   1.1  christos     x = get_flags(ppp_fd);
   1315   1.1  christos     return x & SC_DC_FERROR;
   1316   1.1  christos }
   1317   1.1  christos 
   1318   1.1  christos /*
   1319   1.1  christos  * get_idle_time - return how long the link has been idle.
   1320   1.1  christos  */
   1321   1.1  christos int
   1322   1.1  christos get_idle_time(int u, struct ppp_idle *ip)
   1323   1.1  christos {
   1324   1.1  christos     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
   1325   1.1  christos }
   1326   1.1  christos 
   1327   1.1  christos /*
   1328   1.1  christos  * get_ppp_stats - return statistics for the link.
   1329   1.1  christos  */
   1330   1.1  christos int
   1331   1.1  christos get_ppp_stats(int u, struct pppd_stats *stats)
   1332   1.1  christos {
   1333   1.1  christos     struct ifpppstatsreq req;
   1334   1.1  christos 
   1335   1.1  christos     memset (&req, 0, sizeof (req));
   1336   1.1  christos     strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name));
   1337   1.1  christos     if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
   1338   1.1  christos 	error("%s: Couldn't get PPP statistics: %m", __func__);
   1339   1.1  christos 	return 0;
   1340   1.1  christos     }
   1341   1.1  christos     stats->bytes_in = req.stats.p.ppp_ibytes;
   1342   1.1  christos     stats->bytes_out = req.stats.p.ppp_obytes;
   1343   1.1  christos     stats->pkts_in = req.stats.p.ppp_ipackets;
   1344   1.1  christos     stats->pkts_out = req.stats.p.ppp_opackets;
   1345   1.1  christos     return 1;
   1346   1.1  christos }
   1347   1.1  christos 
   1348   1.1  christos 
   1349  1.10  christos #ifdef PPP_WITH_FILTER
   1350   1.1  christos /*
   1351   1.1  christos  * set_filters - transfer the pass and active filters to the kernel.
   1352   1.1  christos  */
   1353   1.1  christos int
   1354   1.1  christos set_filters(struct bpf_program *pass_in, struct bpf_program *pass_out,
   1355   1.1  christos     struct bpf_program *active_in, struct bpf_program *active_out)
   1356   1.1  christos {
   1357   1.1  christos     int ret = 1;
   1358   1.1  christos 
   1359   1.1  christos     if (pass_in->bf_len > 0) {
   1360   1.1  christos 	if (ioctl(ppp_fd, PPPIOCSIPASS, pass_in) < 0) {
   1361   1.1  christos 	    error("%s: Couldn't set pass-filter-in in kernel: %m", __func__);
   1362   1.1  christos 	    ret = 0;
   1363   1.1  christos 	}
   1364   1.1  christos     }
   1365   1.1  christos 
   1366   1.1  christos     if (pass_out->bf_len > 0) {
   1367   1.1  christos 	if (ioctl(ppp_fd, PPPIOCSOPASS, pass_out) < 0) {
   1368   1.1  christos 	    error("%s: Couldn't set pass-filter-out in kernel: %m", __func__);
   1369   1.1  christos 	    ret = 0;
   1370   1.1  christos 	}
   1371   1.1  christos     }
   1372   1.1  christos 
   1373   1.1  christos     if (active_in->bf_len > 0) {
   1374   1.1  christos 	if (ioctl(ppp_fd, PPPIOCSIACTIVE, active_in) < 0) {
   1375   1.1  christos 	    error("%s: Couldn't set active-filter-in in kernel: %m", __func__);
   1376   1.1  christos 	    ret = 0;
   1377   1.1  christos 	}
   1378   1.1  christos     }
   1379   1.1  christos 
   1380   1.1  christos     if (active_out->bf_len > 0) {
   1381   1.1  christos 	if (ioctl(ppp_fd, PPPIOCSOACTIVE, active_out) < 0) {
   1382   1.1  christos 	    error("%s: Couldn't set active-filter-out in kernel: %m", __func__);
   1383   1.1  christos 	    ret = 0;
   1384   1.1  christos 	}
   1385   1.1  christos     }
   1386   1.1  christos 
   1387   1.1  christos     return ret;
   1388   1.1  christos }
   1389   1.1  christos #endif
   1390   1.1  christos 
   1391   1.1  christos /*
   1392   1.1  christos  * sifvjcomp - config tcp header compression
   1393   1.1  christos  */
   1394   1.1  christos int
   1395   1.1  christos sifvjcomp(int u, int vjcomp, int cidcomp, int maxcid)
   1396   1.1  christos {
   1397   1.1  christos     u_int x;
   1398   1.1  christos 
   1399   1.1  christos     x = get_flags(ppp_fd);
   1400   1.1  christos     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
   1401   1.1  christos     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
   1402   1.1  christos     set_flags(ppp_fd, x);
   1403   1.1  christos     if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
   1404   1.1  christos 	error("%s: ioctl(PPPIOCSMAXCID): %m", __func__);
   1405   1.1  christos 	return 0;
   1406   1.1  christos     }
   1407   1.1  christos     return 1;
   1408   1.1  christos }
   1409   1.1  christos 
   1410   1.2  christos /********************************************************************
   1411   1.2  christos  *
   1412   1.1  christos  * sifup - Config the interface up and enable IP packets to pass.
   1413   1.1  christos  */
   1414   1.2  christos 
   1415   1.2  christos int sifup(int u)
   1416   1.2  christos {
   1417   1.2  christos     int ret;
   1418   1.2  christos 
   1419   1.2  christos     if ((ret = setifstate(u, 1)))
   1420   1.2  christos 	if_is_up++;
   1421   1.2  christos 
   1422   1.2  christos     return ret;
   1423   1.2  christos }
   1424   1.2  christos 
   1425   1.2  christos /********************************************************************
   1426   1.2  christos  *
   1427   1.2  christos  * sifdown - Disable the indicated protocol and config the interface
   1428   1.2  christos  *	     down if there are no remaining protocols.
   1429   1.2  christos  */
   1430   1.2  christos 
   1431   1.2  christos int sifdown (int u)
   1432   1.2  christos {
   1433   1.2  christos     if (if_is_up && --if_is_up > 0)
   1434   1.2  christos 	return 1;
   1435   1.2  christos 
   1436   1.2  christos #ifdef INET6
   1437   1.2  christos     if (if6_is_up)
   1438   1.2  christos 	return 1;
   1439   1.2  christos #endif /* INET6 */
   1440   1.2  christos 
   1441   1.2  christos     return setifstate(u, 0);
   1442   1.2  christos }
   1443   1.2  christos 
   1444   1.2  christos #ifdef INET6
   1445   1.2  christos /********************************************************************
   1446   1.2  christos  *
   1447   1.2  christos  * sif6up - Config the interface up for IPv6
   1448   1.2  christos  */
   1449   1.2  christos 
   1450   1.2  christos int sif6up(int u)
   1451   1.2  christos {
   1452   1.2  christos     int ret;
   1453   1.2  christos 
   1454   1.2  christos     if ((ret = setifstate(u, 1)))
   1455   1.2  christos 	if6_is_up = 1;
   1456   1.2  christos 
   1457   1.2  christos     return ret;
   1458   1.2  christos }
   1459   1.2  christos 
   1460   1.2  christos /********************************************************************
   1461   1.2  christos  *
   1462   1.2  christos  * sif6down - Disable the IPv6CP protocol and config the interface
   1463   1.2  christos  *	      down if there are no remaining protocols.
   1464   1.2  christos  */
   1465   1.2  christos 
   1466   1.2  christos int sif6down (int u)
   1467   1.2  christos {
   1468   1.2  christos     if6_is_up = 0;
   1469   1.2  christos 
   1470   1.2  christos     if (if_is_up)
   1471   1.2  christos 	return 1;
   1472   1.2  christos 
   1473   1.2  christos     return setifstate(u, 0);
   1474   1.2  christos }
   1475   1.2  christos #endif /* INET6 */
   1476   1.2  christos 
   1477   1.2  christos /********************************************************************
   1478   1.2  christos  *
   1479   1.2  christos  * setifstate - Config the interface up or down
   1480   1.2  christos  */
   1481   1.2  christos 
   1482   1.2  christos static int setifstate (int u, int state)
   1483   1.1  christos {
   1484   1.1  christos     struct ifreq ifr;
   1485   1.1  christos 
   1486   1.1  christos     strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   1487   1.1  christos     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
   1488   1.1  christos 	error("%s: ioctl (SIOCGIFFLAGS): %m", __func__);
   1489   1.1  christos 	return 0;
   1490   1.1  christos     }
   1491   1.2  christos     if (state)
   1492   1.2  christos 	ifr.ifr_flags |= IFF_UP;
   1493   1.2  christos     else
   1494   1.2  christos 	ifr.ifr_flags &= ~IFF_UP;
   1495   1.1  christos     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
   1496   1.1  christos 	error("%s: ioctl(SIOCSIFFLAGS): %m", __func__);
   1497   1.1  christos 	return 0;
   1498   1.1  christos     }
   1499   1.1  christos     if_is_up = 1;
   1500   1.1  christos     return 1;
   1501   1.1  christos }
   1502   1.1  christos 
   1503   1.1  christos /*
   1504   1.1  christos  * sifnpmode - Set the mode for handling packets for a given NP.
   1505   1.1  christos  */
   1506   1.1  christos int
   1507   1.1  christos sifnpmode(int u, int proto, enum NPmode mode)
   1508   1.1  christos {
   1509   1.1  christos     struct npioctl npi;
   1510   1.1  christos 
   1511   1.1  christos     npi.protocol = proto;
   1512   1.1  christos     npi.mode = mode;
   1513   1.1  christos     if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
   1514   1.1  christos 	error("%s: ioctl(set NP %d mode to %d): %m", __func__, proto, mode);
   1515   1.1  christos 	return 0;
   1516   1.1  christos     }
   1517   1.1  christos     return 1;
   1518   1.1  christos }
   1519   1.1  christos 
   1520   1.1  christos /*
   1521   1.1  christos  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
   1522   1.1  christos  * if it exists.
   1523   1.1  christos  */
   1524   1.1  christos #define SET_SA_FAMILY(addr, family)		\
   1525   1.1  christos     BZERO((char *) &(addr), sizeof(addr));	\
   1526   1.1  christos     addr.sa_family = (family); 			\
   1527   1.1  christos     addr.sa_len = sizeof(addr);
   1528   1.1  christos 
   1529   1.1  christos /*
   1530   1.1  christos  * sifaddr - Config the interface IP addresses and netmask.
   1531   1.1  christos  */
   1532   1.1  christos int
   1533   1.1  christos sifaddr(int u, u_int32_t o, u_int32_t h, u_int32_t m)
   1534   1.1  christos {
   1535   1.1  christos     struct ifaliasreq ifra;
   1536   1.1  christos     struct ifreq ifr;
   1537   1.1  christos 
   1538   1.1  christos     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
   1539   1.1  christos     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
   1540   1.1  christos     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
   1541   1.1  christos     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
   1542   1.1  christos     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
   1543   1.1  christos     if (m != 0) {
   1544   1.1  christos 	SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
   1545   1.1  christos 	((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
   1546   1.1  christos     } else
   1547   1.1  christos 	BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
   1548   1.1  christos     BZERO(&ifr, sizeof(ifr));
   1549   1.1  christos     strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   1550   1.1  christos     if (ioctl(sock_fd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
   1551   1.1  christos 	if (errno != EADDRNOTAVAIL)
   1552   1.1  christos 	    warn("%s: Couldn't remove interface address: %m", __func__);
   1553   1.1  christos     }
   1554   1.1  christos     if (ioctl(sock_fd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
   1555   1.1  christos 	if (errno != EEXIST) {
   1556   1.1  christos 	    error("%s: Couldn't set interface address: %m", __func__);
   1557   1.1  christos 	    return 0;
   1558   1.1  christos 	}
   1559   1.1  christos 	warn("%s: Couldn't set interface address: Address %I already exists",
   1560   1.1  christos 	    __func__, o);
   1561   1.1  christos     }
   1562   1.1  christos     ifaddrs[0] = o;
   1563   1.1  christos     ifaddrs[1] = h;
   1564   1.1  christos     return 1;
   1565   1.1  christos }
   1566   1.1  christos 
   1567   1.1  christos /*
   1568   1.1  christos  * cifaddr - Clear the interface IP addresses, and delete routes
   1569   1.1  christos  * through the interface if possible.
   1570   1.1  christos  */
   1571   1.1  christos int
   1572   1.1  christos cifaddr(int u, u_int32_t o, u_int32_t h)
   1573   1.1  christos {
   1574   1.1  christos     struct ifaliasreq ifra;
   1575   1.1  christos 
   1576   1.1  christos     ifaddrs[0] = 0;
   1577   1.1  christos     strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
   1578   1.1  christos     SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
   1579   1.1  christos     ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
   1580   1.1  christos     SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
   1581   1.1  christos     ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
   1582   1.1  christos     BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
   1583   1.1  christos     if (ioctl(sock_fd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
   1584   1.1  christos 	if (!doing_cleanup && errno != EADDRNOTAVAIL)
   1585   1.1  christos 	    warn("%s: Couldn't delete interface address: %m", __func__);
   1586   1.1  christos 	return 0;
   1587   1.1  christos     }
   1588   1.1  christos     return 1;
   1589   1.1  christos }
   1590   1.1  christos 
   1591   1.1  christos /*
   1592   1.1  christos  * sifdefaultroute - assign a default route through the address given.
   1593   1.1  christos  */
   1594   1.1  christos int
   1595   1.8  christos sifdefaultroute(int u, u_int32_t l, u_int32_t g, bool replace)
   1596   1.1  christos {
   1597   1.8  christos     if (replace)
   1598   1.8  christos 	dodefaultroute(g, 'c');
   1599   1.1  christos     return dodefaultroute(g, 's');
   1600   1.1  christos }
   1601   1.1  christos 
   1602   1.1  christos /*
   1603   1.1  christos  * cifdefaultroute - delete a default route through the address given.
   1604   1.1  christos  */
   1605   1.1  christos int
   1606   1.1  christos cifdefaultroute(int u, u_int32_t l, u_int32_t g)
   1607   1.1  christos {
   1608   1.1  christos     return dodefaultroute(g, 'c');
   1609   1.1  christos }
   1610   1.1  christos 
   1611   1.1  christos /*
   1612   1.1  christos  * dodefaultroute - talk to a routing socket to add/delete a default route.
   1613   1.1  christos  */
   1614   1.1  christos static int
   1615   1.1  christos dodefaultroute(u_int32_t g, int cmd)
   1616   1.1  christos {
   1617   1.1  christos     int routes;
   1618   1.1  christos     struct {
   1619   1.1  christos 	struct rt_msghdr	hdr;
   1620   1.1  christos 	struct sockaddr_in	dst;
   1621   1.1  christos 	struct sockaddr_in	gway;
   1622   1.1  christos 	struct sockaddr_in	netmask;
   1623   1.1  christos 	struct sockaddr_dl	ifp;
   1624   1.1  christos     } rtmsg;
   1625   1.1  christos 
   1626   1.1  christos     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
   1627   1.1  christos 	if (!doing_cleanup)
   1628   1.1  christos 	    error("%s: Couldn't %s default route: socket: %m", __func__,
   1629   1.1  christos 		cmd == 's' ? "add" : "delete");
   1630   1.1  christos 	return 0;
   1631   1.1  christos     }
   1632   1.1  christos 
   1633   1.1  christos     memset(&rtmsg, 0, sizeof(rtmsg));
   1634   1.1  christos 
   1635   1.1  christos     rtmsg.hdr.rtm_type = cmd == 's' ? RTM_ADD : RTM_DELETE;
   1636   1.1  christos     rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
   1637   1.1  christos     rtmsg.hdr.rtm_version = RTM_VERSION;
   1638   1.1  christos     rtmsg.hdr.rtm_seq = ++rtm_seq;
   1639   1.1  christos     rtmsg.hdr.rtm_addrs =
   1640   1.1  christos 	RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP;
   1641   1.1  christos 
   1642   1.1  christos     rtmsg.dst.sin_len = sizeof(rtmsg.dst);
   1643   1.1  christos     rtmsg.dst.sin_family = AF_INET;
   1644   1.1  christos     rtmsg.dst.sin_addr.s_addr = 0;
   1645   1.1  christos 
   1646   1.1  christos     rtmsg.gway.sin_len = sizeof(rtmsg.gway);
   1647   1.1  christos     rtmsg.gway.sin_family = AF_INET;
   1648   1.1  christos     rtmsg.gway.sin_addr.s_addr = g;
   1649   1.1  christos 
   1650   1.1  christos     rtmsg.netmask.sin_len = sizeof(rtmsg.netmask);
   1651   1.1  christos     rtmsg.netmask.sin_family = AF_INET;
   1652   1.1  christos     rtmsg.netmask.sin_addr.s_addr = 0;
   1653   1.1  christos 
   1654   1.1  christos     rtmsg.ifp.sdl_family = AF_LINK;
   1655   1.1  christos     rtmsg.ifp.sdl_len = sizeof(rtmsg.ifp);
   1656   1.1  christos     link_addr(ifname, &rtmsg.ifp);
   1657   1.1  christos 
   1658   1.1  christos     rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
   1659   1.1  christos 
   1660   1.1  christos     if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
   1661   1.1  christos 	if (!doing_cleanup)
   1662   1.1  christos 	    error("%s: Couldn't %s default route: %m", __func__,
   1663   1.1  christos 		cmd == 's' ? "add" : "delete");
   1664   1.1  christos 	close(routes);
   1665   1.1  christos 	return 0;
   1666   1.1  christos     }
   1667   1.1  christos 
   1668   1.1  christos     close(routes);
   1669   1.1  christos     default_route_gateway = (cmd == 's') ? g : 0;
   1670   1.1  christos     return 1;
   1671   1.1  christos }
   1672   1.1  christos 
   1673   1.8  christos 
   1674   1.9  christos #ifdef INET6
   1675   1.8  christos /*
   1676   1.8  christos  * dodefaultroute - assign/clear a default route through the address given.
   1677   1.8  christos  */
   1678   1.8  christos static int
   1679   1.8  christos dodefaultroute6(int u, eui64_t l, eui64_t g, char cmd)
   1680   1.8  christos {
   1681   1.8  christos     struct {
   1682   1.8  christos 	struct rt_msghdr rtm;
   1683   1.8  christos 	struct sockaddr_in6 dst;
   1684   1.8  christos 	struct sockaddr_in6 gw;
   1685   1.8  christos     } rmsg;
   1686   1.8  christos     static int seq;
   1687   1.8  christos     int rtsock;
   1688   1.8  christos 
   1689   1.8  christos #if defined(__USLC__)
   1690   1.8  christos     g = l;			/* use the local address as gateway */
   1691   1.8  christos #endif
   1692   1.8  christos     memset(&rmsg, 0, sizeof(rmsg));
   1693   1.8  christos 
   1694   1.8  christos     rmsg.rtm.rtm_msglen = sizeof (rmsg);
   1695   1.8  christos     rmsg.rtm.rtm_version = RTM_VERSION;
   1696   1.8  christos     rmsg.rtm.rtm_type = cmd == 's' ? RTM_ADD : RTM_DELETE;
   1697   1.8  christos     rmsg.rtm.rtm_flags = RTF_GATEWAY;
   1698   1.8  christos     rmsg.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
   1699   1.8  christos     rmsg.rtm.rtm_pid = getpid();
   1700   1.8  christos     rmsg.rtm.rtm_seq = seq++;
   1701   1.8  christos 
   1702   1.8  christos     rmsg.dst.sin6_family = AF_INET6;
   1703   1.8  christos 
   1704   1.8  christos     rmsg.gw.sin6_family = AF_INET6;
   1705   1.8  christos     IN6_SOCKADDR_FROM_EUI64(&rmsg.gw, g);
   1706   1.8  christos 
   1707   1.8  christos     rtsock = socket(PF_ROUTE, SOCK_RAW, 0);
   1708   1.8  christos 
   1709   1.8  christos     if (rtsock < 0) {
   1710   1.8  christos 	error("Can't %s default route: %m", cmd == 's' ? "add" : "remove");
   1711   1.8  christos 	return 0;
   1712   1.8  christos     }
   1713   1.8  christos 
   1714   1.8  christos     if (write(rtsock, &rmsg, sizeof(rmsg)) < 0)
   1715   1.8  christos 	error("Can't %s default route: %m", cmd == 's' ? "add" : "remove");
   1716   1.8  christos 
   1717   1.8  christos     close(rtsock);
   1718   1.8  christos 
   1719   1.8  christos     default_route_gateway6 = g;
   1720   1.8  christos     return 1;
   1721   1.8  christos }
   1722   1.8  christos 
   1723   1.8  christos /*
   1724   1.8  christos  * sif6defaultroute - assign a default route through the address given.
   1725   1.8  christos  */
   1726   1.8  christos int
   1727   1.8  christos sif6defaultroute(int u, eui64_t l, eui64_t g)
   1728   1.8  christos {
   1729   1.8  christos 	return dodefaultroute6(u, l, g, 's');
   1730   1.8  christos }
   1731   1.8  christos 
   1732   1.8  christos /*
   1733   1.8  christos  * cif6defaultroute - delete a default route through the address given.
   1734   1.8  christos  */
   1735   1.8  christos int
   1736   1.8  christos cif6defaultroute(int u, eui64_t l, eui64_t g)
   1737   1.8  christos {
   1738   1.8  christos 	return dodefaultroute6(u, l, g, 'c');
   1739   1.8  christos }
   1740   1.8  christos 
   1741   1.9  christos #endif
   1742   1.9  christos 
   1743   1.1  christos #if RTM_VERSION >= 3
   1744   1.1  christos 
   1745   1.1  christos /*
   1746   1.1  christos  * sifproxyarp - Make a proxy ARP entry for the peer.
   1747   1.1  christos  */
   1748   1.1  christos static struct {
   1749   1.1  christos     struct rt_msghdr		hdr;
   1750   1.1  christos     struct sockaddr_inarp	dst;
   1751   1.1  christos     struct sockaddr_dl		hwa;
   1752   1.1  christos     char			extra[128];
   1753   1.1  christos } arpmsg;
   1754   1.1  christos 
   1755   1.1  christos static int arpmsg_valid;
   1756   1.1  christos 
   1757   1.1  christos int
   1758   1.1  christos sifproxyarp(int unit, u_int32_t hisaddr)
   1759   1.1  christos {
   1760   1.1  christos     int routes;
   1761   1.1  christos 
   1762   1.1  christos     /*
   1763   1.1  christos      * Get the hardware address of an interface on the same subnet
   1764   1.1  christos      * as our local address.
   1765   1.1  christos      */
   1766   1.1  christos     memset(&arpmsg, 0, sizeof(arpmsg));
   1767   1.1  christos     if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
   1768   1.1  christos 	error("%s: Cannot determine ethernet address for proxy ARP", __func__);
   1769   1.1  christos 	return 0;
   1770   1.1  christos     }
   1771   1.1  christos 
   1772   1.1  christos     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
   1773   1.1  christos 	error("%s: Couldn't add proxy arp entry: socket: %m", __func__);
   1774   1.1  christos 	return 0;
   1775   1.1  christos     }
   1776   1.1  christos 
   1777   1.1  christos     arpmsg.hdr.rtm_type = RTM_ADD;
   1778   1.5  christos     arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC | RTF_LLDATA;
   1779   1.1  christos     arpmsg.hdr.rtm_version = RTM_VERSION;
   1780   1.1  christos     arpmsg.hdr.rtm_seq = ++rtm_seq;
   1781   1.1  christos     arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
   1782   1.1  christos     arpmsg.hdr.rtm_inits = RTV_EXPIRE;
   1783   1.1  christos     arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
   1784   1.1  christos     arpmsg.dst.sin_family = AF_INET;
   1785   1.1  christos     arpmsg.dst.sin_addr.s_addr = hisaddr;
   1786   1.1  christos     arpmsg.dst.sin_other = SIN_PROXY;
   1787   1.1  christos 
   1788   1.1  christos     arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
   1789   1.1  christos 	+ RT_ROUNDUP(arpmsg.hwa.sdl_len);
   1790   1.1  christos     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
   1791   1.1  christos 	error("%s: Couldn't add proxy arp entry: %m", __func__);
   1792   1.1  christos 	close(routes);
   1793   1.1  christos 	return 0;
   1794   1.1  christos     }
   1795   1.1  christos 
   1796   1.1  christos     close(routes);
   1797   1.1  christos     arpmsg_valid = 1;
   1798   1.1  christos     proxy_arp_addr = hisaddr;
   1799   1.1  christos     return 1;
   1800   1.1  christos }
   1801   1.1  christos 
   1802   1.1  christos /*
   1803   1.1  christos  * cifproxyarp - Delete the proxy ARP entry for the peer.
   1804   1.1  christos  */
   1805   1.1  christos int
   1806   1.1  christos cifproxyarp(int unit, u_int32_t hisaddr)
   1807   1.1  christos {
   1808   1.1  christos     int routes;
   1809   1.1  christos 
   1810   1.1  christos     if (!arpmsg_valid)
   1811   1.1  christos 	return 0;
   1812   1.1  christos     arpmsg_valid = 0;
   1813   1.1  christos 
   1814   1.1  christos     arpmsg.hdr.rtm_type = RTM_DELETE;
   1815   1.1  christos     arpmsg.hdr.rtm_seq = ++rtm_seq;
   1816   1.1  christos 
   1817   1.1  christos     if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
   1818   1.1  christos 	if (!doing_cleanup)
   1819   1.1  christos 	    error("%s: Couldn't delete proxy arp entry: socket: %m", __func__);
   1820   1.1  christos 	return 0;
   1821   1.1  christos     }
   1822   1.1  christos 
   1823   1.1  christos     if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
   1824   1.1  christos 	if (!doing_cleanup)
   1825   1.1  christos 	    error("%s: Couldn't delete proxy arp entry: %m", __func__);
   1826   1.1  christos 	close(routes);
   1827   1.1  christos 	return 0;
   1828   1.1  christos     }
   1829   1.1  christos 
   1830   1.1  christos     close(routes);
   1831   1.1  christos     proxy_arp_addr = 0;
   1832   1.1  christos     return 1;
   1833   1.1  christos }
   1834   1.1  christos 
   1835   1.1  christos #else	/* RTM_VERSION */
   1836   1.1  christos 
   1837   1.1  christos /*
   1838   1.1  christos  * sifproxyarp - Make a proxy ARP entry for the peer.
   1839   1.1  christos  */
   1840   1.1  christos int
   1841   1.1  christos sifproxyarp(int unit, u_int32_t hisaddr)
   1842   1.1  christos {
   1843   1.1  christos     struct arpreq arpreq;
   1844   1.1  christos     struct {
   1845   1.1  christos 	struct sockaddr_dl	sdl;
   1846   1.1  christos 	char			space[128];
   1847   1.1  christos     } dls;
   1848   1.1  christos 
   1849   1.1  christos     BZERO(&arpreq, sizeof(arpreq));
   1850   1.1  christos 
   1851   1.1  christos     /*
   1852   1.1  christos      * Get the hardware address of an interface on the same subnet
   1853   1.1  christos      * as our local address.
   1854   1.1  christos      */
   1855   1.1  christos     if (!get_ether_addr(hisaddr, &dls.sdl)) {
   1856   1.1  christos 	error("%s: Cannot determine ethernet address for proxy ARP", __func__);
   1857   1.1  christos 	return 0;
   1858   1.1  christos     }
   1859   1.1  christos 
   1860   1.1  christos     arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
   1861   1.1  christos     arpreq.arp_ha.sa_family = AF_UNSPEC;
   1862   1.1  christos     BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
   1863   1.1  christos     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
   1864   1.1  christos     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
   1865   1.1  christos     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
   1866   1.1  christos     if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
   1867   1.1  christos 	error("%s: Couldn't add proxy arp entry: %m", __func__);
   1868   1.1  christos 	return 0;
   1869   1.1  christos     }
   1870   1.1  christos 
   1871   1.1  christos     proxy_arp_addr = hisaddr;
   1872   1.1  christos     return 1;
   1873   1.1  christos }
   1874   1.1  christos 
   1875   1.1  christos /*
   1876   1.1  christos  * cifproxyarp - Delete the proxy ARP entry for the peer.
   1877   1.1  christos  */
   1878   1.1  christos int
   1879   1.1  christos cifproxyarp(int unit, u_int32_t hisaddr)
   1880   1.1  christos {
   1881   1.1  christos     struct arpreq arpreq;
   1882   1.1  christos 
   1883   1.1  christos     BZERO(&arpreq, sizeof(arpreq));
   1884   1.1  christos     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
   1885   1.1  christos     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
   1886   1.1  christos     if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
   1887   1.1  christos 	warn("%s: Couldn't delete proxy arp entry: %m", __func__);
   1888   1.1  christos 	return 0;
   1889   1.1  christos     }
   1890   1.1  christos     proxy_arp_addr = 0;
   1891   1.1  christos     return 1;
   1892   1.1  christos }
   1893   1.1  christos #endif	/* RTM_VERSION */
   1894   1.1  christos 
   1895   1.1  christos 
   1896   1.1  christos /*
   1897   1.1  christos  * get_ether_addr - get the hardware address of an interface on the
   1898   1.1  christos  * the same subnet as ipaddr.
   1899   1.1  christos  */
   1900   1.1  christos static int
   1901   1.1  christos get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr)
   1902   1.1  christos {
   1903   1.1  christos     u_int32_t ina, mask;
   1904   1.1  christos     struct sockaddr_dl *dla;
   1905   1.1  christos     struct ifaddrs *ifap, *ifa, *ifp;
   1906   1.1  christos 
   1907   1.1  christos     /*
   1908   1.1  christos      * Scan through looking for an interface with an Internet
   1909   1.1  christos      * address on the same subnet as `ipaddr'.
   1910   1.1  christos      */
   1911   1.1  christos     if (getifaddrs(&ifap) != 0) {
   1912   1.1  christos 	error("%s: getifaddrs: %m", __func__);
   1913   1.1  christos 	return 0;
   1914   1.1  christos     }
   1915   1.1  christos 
   1916   1.1  christos     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
   1917   1.1  christos 	if (ifa->ifa_addr->sa_family != AF_INET)
   1918   1.1  christos 	    continue;
   1919   1.1  christos 	ina = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
   1920   1.1  christos 	/*
   1921   1.1  christos 	 * Check that the interface is up, and not point-to-point
   1922   1.1  christos 	 * or loopback.
   1923   1.1  christos 	 */
   1924   1.1  christos 	if ((ifa->ifa_flags &
   1925   1.1  christos 	     (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
   1926   1.1  christos 	     != (IFF_UP|IFF_BROADCAST))
   1927   1.1  christos 	    continue;
   1928   1.1  christos 	/*
   1929   1.1  christos 	 * Get its netmask and check that it's on the right subnet.
   1930   1.1  christos 	 */
   1931   1.1  christos 	mask = ((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr;
   1932   1.1  christos 	if ((ipaddr & mask) != (ina & mask))
   1933   1.1  christos 	    continue;
   1934   1.1  christos 	break;
   1935   1.1  christos     }
   1936   1.1  christos 
   1937   1.1  christos     if (!ifa) {
   1938   1.1  christos 	freeifaddrs(ifap);
   1939   1.1  christos 	return 0;
   1940   1.1  christos     }
   1941   1.1  christos     info("found interface %s for proxy arp", ifa->ifa_name);
   1942   1.1  christos 
   1943   1.1  christos     ifp = ifa;
   1944   1.1  christos 
   1945   1.1  christos     /*
   1946   1.1  christos      * Now scan through again looking for a link-level address
   1947   1.1  christos      * for this interface.
   1948   1.1  christos      */
   1949   1.1  christos     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
   1950   1.1  christos 	if (strcmp(ifp->ifa_name, ifa->ifa_name) != 0)
   1951   1.1  christos 	    continue;
   1952   1.1  christos 	if (ifa->ifa_addr->sa_family != AF_LINK)
   1953   1.1  christos 	    continue;
   1954   1.1  christos 	/*
   1955   1.1  christos 	 * Found the link-level address - copy it out
   1956   1.1  christos 	 */
   1957   1.1  christos 	dla = (struct sockaddr_dl *) ifa->ifa_addr;
   1958   1.1  christos 	BCOPY(dla, hwaddr, dla->sdl_len);
   1959   1.1  christos 	freeifaddrs(ifap);
   1960   1.1  christos 	return 1;
   1961   1.1  christos     }
   1962   1.1  christos 
   1963   1.1  christos     freeifaddrs(ifap);
   1964   1.1  christos     return 0;
   1965   1.1  christos }
   1966   1.1  christos 
   1967   1.1  christos /*
   1968   1.1  christos  * get_if_hwaddr - get the hardware address for the specified
   1969   1.1  christos  * network interface device.
   1970   1.1  christos  */
   1971   1.1  christos int
   1972   1.1  christos get_if_hwaddr(u_char *addr, char *name)
   1973   1.1  christos {
   1974   1.1  christos 
   1975   1.1  christos #define IFREQ_SAFE (sizeof(struct ifreq) + sizeof(struct sockaddr_dl))
   1976   1.1  christos     /* XXX sockaddr_dl is larger than the sockaddr in struct ifreq! */
   1977   1.7       mrg     union {				/* XXX */
   1978   1.7       mrg     	struct ifreq _ifreq;		/* XXX */
   1979   1.7       mrg 	char _X[IFREQ_SAFE]; 		/* XXX */
   1980   1.7       mrg     } _ifreq_dontsmashstack = {0};	/* XXX */
   1981   1.1  christos #define ifreq_xxx _ifreq_dontsmashstack._ifreq			/* XXX */
   1982   1.1  christos 
   1983   1.1  christos     struct sockaddr_dl *sdl = (struct sockaddr_dl *) &ifreq_xxx.ifr_addr;
   1984   1.1  christos     int fd;
   1985   1.1  christos 
   1986   1.1  christos     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
   1987   1.1  christos 	return 0;
   1988   1.1  christos     sdl->sdl_family = AF_LINK;
   1989   1.1  christos     (void)strlcpy(ifreq_xxx.ifr_name, name, sizeof(ifreq_xxx.ifr_name));
   1990   1.1  christos     if (ioctl(fd, SIOCGIFADDR, &ifreq_xxx) == -1) {
   1991   1.1  christos 	(void)close(fd);
   1992   1.1  christos 	return 0;
   1993   1.1  christos     }
   1994   1.1  christos     (void)close(fd);
   1995   1.1  christos     (void)memcpy(addr, LLADDR(sdl), sdl->sdl_alen);
   1996   1.1  christos     return sdl->sdl_nlen;
   1997   1.1  christos }
   1998   1.1  christos 
   1999   1.1  christos /*
   2000   1.8  christos  * get_first_ether_hwaddr - get the hardware address for the first
   2001   1.8  christos  * ethernet-style interface on this system.
   2002   1.1  christos  */
   2003   1.8  christos int
   2004   1.8  christos get_first_ether_hwaddr(u_char *addr)
   2005   1.1  christos {
   2006   1.8  christos 	struct if_nameindex *if_ni, *i;
   2007   1.8  christos 	struct ifreq ifreq;
   2008   1.8  christos 	int ret, sock_fd;
   2009   1.8  christos 
   2010   1.8  christos 	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
   2011   1.8  christos 	if (sock_fd < 0)
   2012   1.8  christos 		return -1;
   2013   1.8  christos 
   2014   1.8  christos 	if_ni = if_nameindex();
   2015   1.8  christos 	if (!if_ni) {
   2016   1.8  christos 		close(sock_fd);
   2017   1.8  christos 		return -1;
   2018   1.8  christos 	}
   2019   1.8  christos 
   2020   1.8  christos 	ret = -1;
   2021   1.1  christos 
   2022   1.8  christos 	for (i = if_ni; !(i->if_index == 0 && i->if_name == NULL); i++) {
   2023   1.8  christos 		struct sockaddr_dl *sdl = (struct sockaddr_dl *)
   2024   1.8  christos 		    &ifreq.ifr_addr;
   2025   1.8  christos 		sdl->sdl_family = AF_LINK;
   2026   1.8  christos 		strlcpy(ifreq.ifr_name, i->if_name, sizeof(ifreq.ifr_name));
   2027   1.8  christos 		ret = ioctl(sock_fd, SIOCGIFADDR, &ifreq);
   2028   1.8  christos 		if (ret >= 0 && sdl->sdl_family == AF_LINK) {
   2029   1.8  christos 			memcpy(addr, LLADDR(sdl), sdl->sdl_alen);
   2030   1.8  christos 			break;
   2031   1.8  christos 		}
   2032   1.8  christos 		ret = -1;
   2033   1.1  christos 	}
   2034   1.8  christos 
   2035   1.8  christos 	if_freenameindex(if_ni);
   2036   1.8  christos 	close(sock_fd);
   2037   1.8  christos 
   2038   1.8  christos 	return ret;
   2039   1.1  christos }
   2040   1.1  christos 
   2041   1.1  christos /*
   2042   1.1  christos  * Return user specified netmask, modified by any mask we might determine
   2043   1.1  christos  * for address `addr' (in network byte order).
   2044   1.1  christos  * Here we scan through the system's list of interfaces, looking for
   2045   1.1  christos  * any non-point-to-point interfaces which might appear to be on the same
   2046   1.1  christos  * network as `addr'.  If we find any, we OR in their netmask to the
   2047   1.1  christos  * user-specified netmask.
   2048   1.1  christos  */
   2049   1.1  christos u_int32_t
   2050   1.1  christos GetMask(u_int32_t addr)
   2051   1.1  christos {
   2052   1.1  christos     u_int32_t mask, nmask, ina;
   2053   1.1  christos     struct ifaddrs *ifap, *ifa;
   2054   1.1  christos 
   2055   1.1  christos     addr = ntohl(addr);
   2056   1.1  christos     if (IN_CLASSA(addr))	/* determine network mask for address class */
   2057   1.1  christos 	nmask = IN_CLASSA_NET;
   2058   1.1  christos     else if (IN_CLASSB(addr))
   2059   1.1  christos 	nmask = IN_CLASSB_NET;
   2060   1.1  christos     else
   2061   1.1  christos 	nmask = IN_CLASSC_NET;
   2062   1.1  christos     /* class D nets are disallowed by bad_ip_adrs */
   2063   1.1  christos     mask = netmask | htonl(nmask);
   2064   1.1  christos 
   2065   1.1  christos     /*
   2066   1.1  christos      * Scan through the system's network interfaces.
   2067   1.1  christos      */
   2068   1.1  christos     if (getifaddrs(&ifap) != 0) {
   2069   1.1  christos 	warn("%s: getifaddrs: %m", __func__);
   2070   1.1  christos 	return 0;
   2071   1.1  christos     }
   2072   1.1  christos 
   2073   1.1  christos     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
   2074   1.1  christos 	/*
   2075   1.1  christos 	 * Check the interface's internet address.
   2076   1.1  christos 	 */
   2077   1.1  christos 	if (ifa->ifa_addr->sa_family != AF_INET)
   2078   1.1  christos 	    continue;
   2079   1.1  christos 	ina = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
   2080   1.1  christos 	if ((ntohl(ina) & nmask) != (addr & nmask))
   2081   1.1  christos 	    continue;
   2082   1.1  christos 	/*
   2083   1.1  christos 	 * Check that the interface is up, and not point-to-point or loopback.
   2084   1.1  christos 	 */
   2085   1.1  christos 	if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP)
   2086   1.1  christos 	    continue;
   2087   1.1  christos 	/*
   2088   1.1  christos 	 * Get its netmask and OR it into our mask.
   2089   1.1  christos 	 */
   2090   1.1  christos 	mask |= ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
   2091   1.1  christos     }
   2092   1.1  christos 
   2093   1.1  christos     freeifaddrs(ifap);
   2094   1.1  christos     return mask;
   2095   1.1  christos }
   2096   1.1  christos 
   2097   1.1  christos /*
   2098   1.1  christos  * have_route_to - determine if the system has any route to
   2099   1.1  christos  * a given IP address.
   2100   1.1  christos  * For demand mode to work properly, we have to ignore routes
   2101   1.1  christos  * through our own interface.
   2102   1.1  christos  */
   2103   1.1  christos int have_route_to(u_int32_t addr)
   2104   1.1  christos {
   2105   1.1  christos     return -1;
   2106   1.1  christos }
   2107   1.1  christos 
   2108   1.1  christos /*
   2109   1.1  christos  * Use the hostid as part of the random number seed.
   2110   1.1  christos  */
   2111   1.1  christos int
   2112   1.1  christos get_host_seed(void)
   2113   1.1  christos {
   2114   1.1  christos     return gethostid();
   2115   1.1  christos }
   2116   1.1  christos 
   2117   1.1  christos #if 0
   2118   1.1  christos /*
   2119   1.1  christos  * lock - create a lock file for the named lock device
   2120   1.1  christos  */
   2121   1.1  christos #define	LOCK_PREFIX	"/var/spool/lock/LCK.."
   2122   1.1  christos 
   2123   1.1  christos static char *lock_file;		/* name of lock file created */
   2124   1.1  christos 
   2125   1.1  christos int
   2126   1.1  christos lock(char *dev)
   2127   1.1  christos {
   2128   1.1  christos     char hdb_lock_buffer[12];
   2129   1.1  christos     int fd, pid, n;
   2130   1.1  christos     char *p;
   2131   1.1  christos     size_t l;
   2132   1.1  christos 
   2133   1.1  christos     if ((p = strrchr(dev, '/')) != NULL)
   2134   1.1  christos 	dev = p + 1;
   2135   1.1  christos     l = strlen(LOCK_PREFIX) + strlen(dev) + 1;
   2136   1.1  christos     lock_file = malloc(l);
   2137   1.1  christos     if (lock_file == NULL)
   2138   1.1  christos 	novm("lock file name");
   2139   1.1  christos     slprintf(lock_file, l, "%s%s", LOCK_PREFIX, dev);
   2140   1.1  christos 
   2141   1.1  christos     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
   2142   1.1  christos 	if (errno == EEXIST
   2143   1.1  christos 	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
   2144   1.1  christos 	    /* Read the lock file to find out who has the device locked */
   2145   1.1  christos 	    n = read(fd, hdb_lock_buffer, 11);
   2146   1.1  christos 	    if (n <= 0) {
   2147   1.1  christos 		error("%s: Can't read pid from lock file %s", __func__,
   2148   1.1  christos 		    lock_file);
   2149   1.1  christos 		close(fd);
   2150   1.1  christos 	    } else {
   2151   1.1  christos 		hdb_lock_buffer[n] = 0;
   2152   1.1  christos 		pid = atoi(hdb_lock_buffer);
   2153   1.1  christos 		if (kill(pid, 0) == -1 && errno == ESRCH) {
   2154   1.1  christos 		    /* pid no longer exists - remove the lock file */
   2155   1.1  christos 		    if (unlink(lock_file) == 0) {
   2156   1.1  christos 			close(fd);
   2157   1.1  christos 			notice("%s: Removed stale lock on %s (pid %d)",
   2158   1.1  christos 			    __func__, dev, pid);
   2159   1.1  christos 			continue;
   2160   1.1  christos 		    } else
   2161   1.1  christos 			warn("%s: Couldn't remove stale lock on %s", __func__,
   2162   1.1  christos 			    dev);
   2163   1.1  christos 		} else
   2164   1.1  christos 		    notice("%s: Device %s is locked by pid %d", __func__,
   2165   1.1  christos 			   dev, pid);
   2166   1.1  christos 	    }
   2167   1.1  christos 	    close(fd);
   2168   1.1  christos 	} else
   2169   1.1  christos 	    error("%s: Can't create lock file %s: %m", __func__, lock_file);
   2170   1.1  christos 	free(lock_file);
   2171   1.1  christos 	lock_file = NULL;
   2172   1.1  christos 	return -1;
   2173   1.1  christos     }
   2174   1.1  christos 
   2175   1.1  christos     slprintf(hdb_lock_buffer, sizeof(hdb_lock_buffer), "%10d\n", getpid());
   2176   1.1  christos     write(fd, hdb_lock_buffer, 11);
   2177   1.1  christos 
   2178   1.1  christos     close(fd);
   2179   1.1  christos     return 0;
   2180   1.1  christos }
   2181   1.1  christos 
   2182   1.1  christos /*
   2183   1.1  christos  * unlock - remove our lockfile
   2184   1.1  christos  */
   2185   1.1  christos void
   2186   1.1  christos unlock(void)
   2187   1.1  christos {
   2188   1.1  christos     if (lock_file) {
   2189   1.1  christos 	unlink(lock_file);
   2190   1.1  christos 	free(lock_file);
   2191   1.1  christos 	lock_file = NULL;
   2192   1.1  christos     }
   2193   1.1  christos }
   2194   1.1  christos #endif
   2195   1.2  christos 
   2196   1.8  christos 
   2197   1.8  christos /********************************************************************
   2198   1.2  christos  *
   2199   1.8  christos  * get_time - Get current time, monotonic if possible.
   2200   1.2  christos  */
   2201   1.2  christos int
   2202  1.10  christos ppp_get_time(struct timeval *tv)
   2203   1.2  christos {
   2204   1.8  christos     return gettimeofday(tv, NULL);
   2205   1.2  christos }
   2206