2 * sys-linux.c - System-dependent procedures for setting up
3 * PPP interfaces on Linux systems
5 * Copyright (c) 1994-2004 Paul Mackerras. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. The name(s) of the authors of this software must not be used to
15 * endorse or promote products derived from this software without
16 * prior written permission.
18 * 3. Redistributions of any form whatsoever must retain the following
20 * "This product includes software developed by Paul Mackerras
21 * <paulus@samba.org>".
23 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
24 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
26 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
28 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
29 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 * Derived from main.c and pppd.h, which are:
33 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
47 * 3. The name "Carnegie Mellon University" must not be used to
48 * endorse or promote products derived from this software without
49 * prior written permission. For permission or any legal
50 * details, please contact
51 * Office of Technology Transfer
52 * Carnegie Mellon University
54 * Pittsburgh, PA 15213-3890
55 * (412) 268-4387, fax: (412) 268-7395
56 * tech-transfer@andrew.cmu.edu
58 * 4. Redistributions of any form whatsoever must retain the following
60 * "This product includes software developed by Computing Services
61 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
63 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
64 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
65 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
66 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
67 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
68 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
69 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
76 #include <sys/ioctl.h>
77 #include <sys/types.h>
78 #include <sys/socket.h>
82 #include <sys/utsname.h>
83 #include <sys/sysmacros.h>
84 #include <sys/param.h>
104 /* This is in netdevice.h. However, this compile will fail miserably if
105 you attempt to include netdevice.h because it has so many references
106 to __memcpy functions which it should not attempt to do. So, since I
107 really don't use it, but it must be defined, define it now. */
110 #define MAX_ADDR_LEN 7
113 #if !defined(__GLIBC__) || __GLIBC__ >= 2
114 #include <asm/types.h> /* glibc 2 conflicts with linux/types.h */
116 #include <net/if_arp.h>
117 #include <net/route.h>
118 #include <netinet/if_ether.h>
120 #include <linux/types.h>
121 #include <linux/if.h>
122 #include <linux/if_arp.h>
123 #include <linux/route.h>
124 #include <linux/if_ether.h>
126 #include <netinet/in.h>
127 #include <arpa/inet.h>
129 #include <linux/ppp-ioctl.h>
131 #include <linux/netlink.h>
132 #include <linux/rtnetlink.h>
133 #include <linux/if_link.h>
135 /* Attempt at retaining compile-support with older than 4.7 kernels, or kernels
136 * where RTM_NEWSTATS isn't defined for whatever reason.
139 #define RTM_NEWSTATS 92
140 #define RTM_GETSTATS 94
141 #define IFLA_STATS_LINK_64 1
144 #include <linux/if_addr.h>
146 /* glibc versions prior to 2.24 do not define SOL_NETLINK */
148 #define SOL_NETLINK 270
151 /* linux kernel versions prior to 4.3 do not define/support NETLINK_CAP_ACK */
152 #ifndef NETLINK_CAP_ACK
153 #define NETLINK_CAP_ACK 10
156 /* linux kernel versions prior to 4.7 do not define/support IFLA_PPP_DEV_FD */
158 /* IFLA_PPP_DEV_FD is declared as enum when IFLA_PPP_MAX is defined */
159 #define IFLA_PPP_DEV_FD 1
166 #ifdef PPP_WITH_IPV6CP
168 #endif /* PPP_WITH_IPV6CP */
170 #ifdef PPP_WITH_FILTER
171 #include <pcap-bpf.h>
172 #include <linux/filter.h>
173 #endif /* PPP_WITH_FILTER */
176 #include <sys/locks.h>
180 * Instead of system header file <termios.h> use local "termios_linux.h" header
181 * file as it provides additional support for arbitrary baud rates via BOTHER.
183 #include "termios_linux.h"
185 #ifdef PPP_WITH_IPV6CP
188 * This is in linux/include/net/ipv6.h.
192 struct in6_addr ifr6_addr;
193 __u32 ifr6_prefixlen;
194 unsigned int ifr6_ifindex;
198 #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do { \
199 memset(&(sin6).s6_addr, 0, sizeof(struct in6_addr)); \
200 (sin6).s6_addr16[0] = htons(0xfe80); \
201 eui64_copy(eui64, (sin6).s6_addr32[2]); \
204 static const eui64_t nulleui64;
205 #endif /* PPP_WITH_IPV6CP */
207 /* We can get an EIO error on an ioctl if the modem has hung up */
208 #define ok_error(num) ((num)==EIO)
210 static int tty_disc = N_TTY; /* The TTY discipline */
211 static int ppp_disc = N_PPP; /* The PPP discpline */
212 static int initfdflags = -1; /* Initial file descriptor flags for fd */
213 static int ppp_fd = -1; /* fd which is set to PPP discipline */
214 static int sock_fd = -1; /* socket for doing interface ioctls */
215 static int slave_fd = -1; /* pty for old-style demand mode, slave */
216 static int master_fd = -1; /* pty for old-style demand mode, master */
217 #ifdef PPP_WITH_IPV6CP
218 static int sock6_fd = -1;
219 #endif /* PPP_WITH_IPV6CP */
222 * For the old-style kernel driver, this is the same as ppp_fd.
223 * For the new-style driver, it is the fd of an instance of /dev/ppp
224 * which is attached to the ppp unit and is used for controlling it.
226 int ppp_dev_fd = -1; /* fd for /dev/ppp (new style driver) */
228 static int chindex; /* channel index (new style driver) */
230 static fd_set in_fds; /* set of fds that wait_input waits for */
231 static int max_in_fd; /* highest fd set in in_fds */
233 static int has_proxy_arp = 0;
234 static int driver_version = 0;
235 static int driver_modification = 0;
236 static int driver_patch = 0;
237 static int driver_is_old = 0;
238 static int restore_term = 0; /* 1 => we've munged the terminal */
239 static struct termios inittermios; /* Initial TTY termios */
241 int new_style_driver = 0;
243 static char loop_name[20];
244 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
246 static int if_is_up; /* Interface has been marked up */
247 static int if6_is_up; /* Interface has been marked up for IPv6, to help differentiate */
248 static int have_default_route; /* Gateway for default route added */
249 static int have_default_route6; /* Gateway for default IPv6 route added */
250 static struct rtentry old_def_rt; /* Old default route */
251 static int default_rt_repl_rest; /* replace and restore old default rt */
252 static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
253 static char proxy_arp_dev[16]; /* Device for proxy arp entry */
254 static u_int32_t our_old_addr; /* for detecting address changes */
255 static int dynaddr_set; /* 1 if ip_dynaddr set */
256 static int looped; /* 1 if using loop */
257 static int link_mtu; /* mtu for the link (not bundle) */
259 static struct utsname utsname; /* for the kernel version */
260 static int kernel_version;
261 #define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p))
265 #define FLAGS_GOOD (IFF_UP | IFF_BROADCAST)
266 #define FLAGS_MASK (IFF_UP | IFF_BROADCAST | \
267 IFF_POINTOPOINT | IFF_LOOPBACK | IFF_NOARP)
269 #define SIN_ADDR(x) (((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
271 /* Prototypes for procedures local to this file. */
272 static int modify_flags(int fd, int clear_bits, int set_bits);
273 static int translate_speed (int bps);
274 static int baud_rate_of (int speed);
275 static void close_route_table (void);
276 static int open_route_table (void);
277 static int read_route_table (struct rtentry *rt);
278 static int defaultroute_exists (struct rtentry *rt, int metric);
279 static int defaultroute6_exists (struct in6_rtmsg *rt, int metric);
280 static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
281 char *name, int namelen);
282 static void decode_version (char *buf, int *version, int *mod, int *patch);
283 static int set_kdebugflag(int level);
284 static int ppp_registered(void);
285 static int make_ppp_unit(void);
286 static int setifstate (int u, int state);
288 extern u_char inpacket_buf[]; /* borrowed from main.c */
290 extern int dfl_route_metric;
293 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
297 #define SET_SA_FAMILY(addr, family) \
298 memset ((char *) &(addr), '\0', sizeof(addr)); \
299 addr.sa_family = (family);
303 * rtnetlink_msg - send rtnetlink message, receive response
304 * and return received error code:
306 * positive value - error during sending / receiving message
307 * negative value - rtnetlink responce error code
309 static int rtnetlink_msg(const char *desc, int *shared_fd, void *nlreq, size_t nlreq_len, void *nlresp_data, size_t *nlresp_size, unsigned nlresp_type)
313 struct nlmsgerr nlerr;
315 struct sockaddr_nl nladdr;
322 if (shared_fd && *shared_fd >= 0) {
325 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
327 error("rtnetlink_msg: socket(NETLINK_ROUTE): %m (line %d)", __LINE__);
332 * Tell kernel to not send to us payload of acknowledgment error message.
333 * NETLINK_CAP_ACK option is supported since Linux kernel version 4.3 and
334 * older kernel versions always send full payload in acknowledgment netlink
335 * message. We ignore payload of this message as we need only error code,
336 * to check if our set remote peer address request succeeded or failed.
337 * So ignore return value from the following setsockopt() call as setting
338 * option NETLINK_CAP_ACK means for us just a kernel hint / optimization.
341 setsockopt(fd, SOL_NETLINK, NETLINK_CAP_ACK, &one, sizeof(one));
343 memset(&nladdr, 0, sizeof(nladdr));
344 nladdr.nl_family = AF_NETLINK;
346 if (bind(fd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) {
347 error("rtnetlink_msg: bind(AF_NETLINK): %m (line %d)", __LINE__);
356 memset(&nladdr, 0, sizeof(nladdr));
357 nladdr.nl_family = AF_NETLINK;
359 memset(&iov[0], 0, sizeof(iov[0]));
360 iov[0].iov_base = nlreq;
361 iov[0].iov_len = nlreq_len;
363 memset(&msg, 0, sizeof(msg));
364 msg.msg_name = &nladdr;
365 msg.msg_namelen = sizeof(nladdr);
366 msg.msg_iov = &iov[0];
369 if (sendmsg(fd, &msg, 0) < 0) {
370 error("rtnetlink_msg: sendmsg(%s): %m (line %d)", desc, __LINE__);
376 memset(iov, 0, sizeof(iov));
377 iov[0].iov_base = &nlresp_hdr;
378 if (nlresp_size && *nlresp_size > sizeof(nlresp_hdr)) {
379 iov[0].iov_len = offsetof(struct nlresp_hdr, nlerr);
380 iov[1].iov_base = nlresp_data;
381 iov[1].iov_len = *nlresp_size;
383 iov[0].iov_len = sizeof(nlresp_hdr);
386 memset(&msg, 0, sizeof(msg));
387 msg.msg_name = &nladdr;
388 msg.msg_namelen = sizeof(nladdr);
390 msg.msg_iovlen = (nlresp_size && *nlresp_size > sizeof(nlresp_hdr)) ? 2 : 1;
392 nlresp_len = recvmsg(fd, &msg, 0);
397 if (nlresp_len < 0) {
398 error("rtnetlink_msg: recvmsg(%s): %m (line %d)", desc, __LINE__);
402 if (nladdr.nl_family != AF_NETLINK) {
403 error("rtnetlink_msg: recvmsg(%s): Not a netlink packet (line %d)", desc, __LINE__);
408 if ((size_t)nlresp_len < sizeof(nlresp_hdr) || nlresp_hdr.nlh.nlmsg_len < sizeof(nlresp_hdr)) {
409 error("rtnetlink_msg: recvmsg(%s): Acknowledgment netlink packet too short (line %d)", desc, __LINE__);
413 /* acknowledgment packet for NLM_F_ACK is NLMSG_ERROR */
414 if (nlresp_hdr.nlh.nlmsg_type != NLMSG_ERROR) {
415 error("rtnetlink_msg: recvmsg(%s): Not an acknowledgment netlink packet (line %d)", desc, __LINE__);
421 if (*nlresp_size > sizeof(nlresp_hdr))
422 memcpy((unsigned char *)&nlresp_hdr + offsetof(struct nlresp_hdr, nlerr), nlresp_data, sizeof(nlresp_hdr.nlerr));
424 memcpy(nlresp_data, (unsigned char *)&nlresp_hdr + offsetof(struct nlresp_hdr, nlerr), *nlresp_size);
427 /* error == 0 indicates success, negative value is errno code */
428 if (nlresp_hdr.nlh.nlmsg_type == NLMSG_ERROR && nlresp_hdr.nlerr.error)
429 return nlresp_hdr.nlerr.error;
432 if (nlresp_hdr.nlh.nlmsg_type != nlresp_type) {
433 error("rtnetlink_msg: recvmsg(%s): Not a netlink packet of type 0x%x (line %d)", desc, nlresp_type, __LINE__);
436 *nlresp_size = nlresp_len - offsetof(struct nlresp_hdr, nlerr);
443 * Determine if the PPP connection should still be present.
448 /* new_fd is the fd of a tty */
449 static void set_ppp_fd (int new_fd)
452 if (!new_style_driver)
456 static int still_ppp(void)
458 if (new_style_driver)
459 return !hungup && ppp_fd >= 0;
460 if (!hungup || ppp_fd == slave_fd)
463 set_ppp_fd(slave_fd);
470 * modify_flags - set and clear flag bits controlling the kernel
473 static int modify_flags(int fd, int clear_bits, int set_bits)
477 if (ioctl(fd, PPPIOCGFLAGS, &flags) == -1)
479 flags = (flags & ~clear_bits) | set_bits;
480 if (ioctl(fd, PPPIOCSFLAGS, &flags) == -1)
487 error("Failed to set PPP kernel option flags: %m");
491 /********************************************************************
493 * sys_init - System-dependent initialization.
498 /* Get an internet socket for doing socket ioctls. */
499 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
501 fatal("Couldn't create IP socket: %m(%d)", errno);
503 #ifdef PPP_WITH_IPV6CP
504 sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
506 sock6_fd = -errno; /* save errno for later */
513 /********************************************************************
515 * sys_cleanup - restore any system state we modified before exiting:
516 * mark the interface down, delete default route and/or proxy arp entry.
517 * This shouldn't call die() because it's called from die().
520 void sys_cleanup(void)
523 * Take down the device
529 #ifdef PPP_WITH_IPV6CP
535 * Delete any routes through the device.
537 if (have_default_route)
538 cifdefaultroute(0, 0, 0);
539 #ifdef PPP_WITH_IPV6CP
540 if (have_default_route6)
541 cif6defaultroute(0, nulleui64, nulleui64);
545 cifproxyarp(0, proxy_arp_addr);
548 /********************************************************************
550 * sys_close - Clean up in a child process before execing.
555 if (new_style_driver && ppp_dev_fd >= 0)
559 #ifdef PPP_WITH_IPV6CP
569 /********************************************************************
571 * set_kdebugflag - Define the debugging level for the kernel
574 static int set_kdebugflag (int requested_level)
578 if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
579 if ( ! ok_error (errno) )
580 error("ioctl(PPPIOCSDEBUG): %m (line %d)", __LINE__);
586 /********************************************************************
588 * tty_establish_ppp - Turn the serial port into a ppp interface.
591 int tty_establish_ppp (int tty_fd)
596 * Ensure that the tty device is in exclusive mode.
598 if (ioctl(tty_fd, TIOCEXCL, 0) < 0) {
599 if ( ! ok_error ( errno ))
600 warn("Couldn't make tty exclusive: %m");
603 * Demand mode - prime the old ppp device to relinquish the unit.
605 if (!new_style_driver && looped
606 && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
607 error("ioctl(transfer ppp unit): %m, line %d", __LINE__);
611 * Set the current tty to the PPP discpline
615 #define N_SYNC_PPP 14
617 ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
618 if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
619 if ( ! ok_error (errno) ) {
620 error("Couldn't set tty to PPP discipline: %m");
625 ret_fd = generic_establish_ppp(tty_fd);
627 #define SC_RCVB (SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP)
628 #define SC_LOGB (SC_DEBUG | SC_LOG_INPKT | SC_LOG_OUTPKT | SC_LOG_RAWIN \
632 modify_flags(ppp_fd, SC_RCVB | SC_LOGB,
633 (kdebugflag * SC_DEBUG) & SC_LOGB);
635 if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
636 warn("Couldn't reset tty to normal line discipline: %m");
642 /********************************************************************
644 * generic_establish_ppp - Turn the fd into a ppp interface.
646 int generic_establish_ppp (int fd)
650 if (new_style_driver) {
653 /* If a ppp_fd is already open, close it first */
660 /* Open an instance of /dev/ppp and connect the channel to it */
661 if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
662 error("Couldn't get channel number: %m");
665 dbglog("using channel %d", chindex);
666 fd = open("/dev/ppp", O_RDWR);
668 error("Couldn't reopen /dev/ppp: %m");
671 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
672 if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
673 error("Couldn't attach to channel %d: %m", chindex);
676 flags = fcntl(fd, F_GETFL);
677 if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
678 warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
683 if (!looped && !multilink) {
685 * Create a new PPP unit.
687 if (make_ppp_unit() < 0)
692 modify_flags(ppp_dev_fd, SC_LOOP_TRAFFIC, 0);
696 if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
697 error("Couldn't attach to PPP unit %d: %m", ifunit);
704 * Old-style driver: find out which interface we were given.
707 if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
708 if (ok_error (errno))
710 fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
712 /* Check that we got the same unit again. */
713 if (looped && x != ifunit)
714 fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
718 * Fetch the initial file flags and reset blocking mode on the file.
720 initfdflags = fcntl(fd, F_GETFL);
721 if (initfdflags == -1 ||
722 fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
723 if ( ! ok_error (errno))
724 warn("Couldn't set device to non-blocking mode: %m");
729 * Enable debug in the driver if requested.
732 set_kdebugflag (kdebugflag);
744 /********************************************************************
746 * tty_disestablish_ppp - Restore the serial port to normal operation.
747 * This shouldn't call die() because it's called from die().
750 void tty_disestablish_ppp(int tty_fd)
754 * Flush the tty output buffer so that the TIOCSETD doesn't hang.
756 if (tcflush(tty_fd, TCIOFLUSH) < 0)
758 warn("tcflush failed: %m");
762 * Restore the previous line discipline
764 if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0) {
765 if ( ! ok_error (errno))
766 error("ioctl(TIOCSETD, N_TTY): %m (line %d)", __LINE__);
769 if (ioctl(tty_fd, TIOCNXCL, 0) < 0) {
770 if ( ! ok_error (errno))
771 warn("ioctl(TIOCNXCL): %m (line %d)", __LINE__);
774 /* Reset non-blocking mode on fd. */
775 if (initfdflags != -1 && fcntl(tty_fd, F_SETFL, initfdflags) < 0) {
776 if ( ! ok_error (errno))
777 warn("Couldn't restore device fd flags: %m");
783 generic_disestablish_ppp(tty_fd);
786 /********************************************************************
788 * generic_disestablish_ppp - Restore device components to normal
789 * operation, and reconnect the ppp unit to the loopback if in demand
790 * mode. This shouldn't call die() because it's called from die().
792 void generic_disestablish_ppp(int dev_fd)
794 if (new_style_driver) {
798 modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
800 } else if (!doing_multilink && ppp_dev_fd >= 0) {
802 remove_fd(ppp_dev_fd);
806 /* old-style driver */
808 set_ppp_fd(slave_fd);
815 * make_ppp_unit_rtnetlink - register a new ppp network interface for ppp_dev_fd
816 * with specified req_ifname via rtnetlink. Interface name req_ifname must not
817 * be empty. Custom ppp unit id req_unit is ignored and kernel choose some free.
819 static int make_ppp_unit_rtnetlink(void)
823 struct ifinfomsg ifm;
826 char ifname[IFNAMSIZ];
832 char ifkind[sizeof("ppp")];
847 memset(&nlreq, 0, sizeof(nlreq));
848 nlreq.nlh.nlmsg_len = sizeof(nlreq);
849 nlreq.nlh.nlmsg_type = RTM_NEWLINK;
850 nlreq.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
851 nlreq.ifm.ifi_family = AF_UNSPEC;
852 nlreq.ifm.ifi_type = ARPHRD_NETROM;
853 nlreq.ifn.rta.rta_len = sizeof(nlreq.ifn);
854 nlreq.ifn.rta.rta_type = IFLA_IFNAME;
855 strlcpy(nlreq.ifn.ifname, req_ifname, sizeof(nlreq.ifn.ifname));
856 nlreq.ifli.rta.rta_len = sizeof(nlreq.ifli);
857 nlreq.ifli.rta.rta_type = IFLA_LINKINFO;
858 nlreq.ifli.ifik.rta.rta_len = sizeof(nlreq.ifli.ifik);
859 nlreq.ifli.ifik.rta.rta_type = IFLA_INFO_KIND;
860 strcpy(nlreq.ifli.ifik.ifkind, "ppp");
861 nlreq.ifli.ifid.rta.rta_len = sizeof(nlreq.ifli.ifid);
862 nlreq.ifli.ifid.rta.rta_type = IFLA_INFO_DATA;
863 nlreq.ifli.ifid.ifdata[0].rta.rta_len = sizeof(nlreq.ifli.ifid.ifdata[0]);
864 nlreq.ifli.ifid.ifdata[0].rta.rta_type = IFLA_PPP_DEV_FD;
865 nlreq.ifli.ifid.ifdata[0].ppp.ppp_dev_fd = ppp_dev_fd;
868 * See kernel function ppp_nl_newlink(), which may return -EBUSY to prevent
869 * possible deadlock in kernel and ask userspace to retry request again.
872 resp = rtnetlink_msg("RTM_NEWLINK/NLM_F_CREATE", NULL, &nlreq, sizeof(nlreq), NULL, NULL, 0);
873 } while (resp == -EBUSY);
877 * Linux kernel versions prior to 4.7 do not support creating ppp
878 * interfaces via rtnetlink API and therefore error response is
879 * expected. On older kernel versions do not show this error message.
880 * When error is different than EEXIST then pppd tries to fallback to
881 * the old ioctl method.
883 errno = (resp < 0) ? -resp : EINVAL;
884 if (kernel_version >= KVERSION(4,7,0))
885 error("Couldn't create ppp interface %s: %m", req_ifname);
893 * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
894 * Assumes new_style_driver.
896 static int make_ppp_unit(void)
900 if (ppp_dev_fd >= 0) {
901 dbglog("in make_ppp_unit, already had /dev/ppp open?");
904 ppp_dev_fd = open("/dev/ppp", O_RDWR);
906 fatal("Couldn't open /dev/ppp: %m");
907 flags = fcntl(ppp_dev_fd, F_GETFL);
909 || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
910 warn("Couldn't set /dev/ppp to nonblock: %m");
913 * Via rtnetlink it is possible to create ppp network interface with
914 * custom ifname atomically. But it is not possible to specify custom
917 * Tools like systemd, udev or NetworkManager are trying to query
918 * interface attributes based on interface name immediately when new
919 * network interface is created. And therefore immediate interface
920 * renaming is causing issues.
922 * So use rtnetlink API only when user requested custom ifname. It will
923 * avoid system issues with interface renaming.
925 if (req_unit == -1 && req_ifname[0] != '\0' && kernel_version >= KVERSION(2,1,16)) {
926 if (make_ppp_unit_rtnetlink()) {
927 if (ioctl(ppp_dev_fd, PPPIOCGUNIT, &ifunit))
928 fatal("Couldn't retrieve PPP unit id: %m");
932 * If interface with requested name already exist return error
933 * otherwise fallback to old ioctl method.
940 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
941 if (x < 0 && req_unit >= 0 && errno == EEXIST) {
942 warn("Couldn't allocate PPP unit %d as it is already in use", req_unit);
944 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
946 if (x < 0 && errno == EEXIST) {
947 srand(time(NULL) * getpid());
948 ifunit = rand() % 10000;
949 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
952 error("Couldn't create new ppp unit: %m");
954 if (x == 0 && req_ifname[0] != '\0') {
957 memset(&ifr, 0, sizeof(struct ifreq));
958 slprintf(t, sizeof(t), "%s%d", PPP_DRV_NAME, ifunit);
959 strlcpy(ifr.ifr_name, t, IFNAMSIZ);
960 strlcpy(ifr.ifr_newname, req_ifname, IFNAMSIZ);
961 x = ioctl(sock_fd, SIOCSIFNAME, &ifr);
963 error("Couldn't rename interface %s to %s: %m", t, req_ifname);
965 info("Renamed interface %s to %s", t, req_ifname);
972 * cfg_bundle - configure the existing bundle.
973 * Used in demand mode.
975 void cfg_bundle(int mrru, int mtru, int rssn, int tssn)
977 if (!new_style_driver)
980 /* set the mrru, mtu and flags */
981 if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
982 error("Couldn't set MRRU: %m");
984 modify_flags(ppp_dev_fd, SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ|SC_MULTILINK,
985 ((rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0)
986 | (mrru? SC_MULTILINK: 0)));
988 /* connect up the channel */
989 if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0)
990 fatal("Couldn't attach to PPP unit %d: %m", ifunit);
995 * make_new_bundle - create a new PPP unit (i.e. a bundle)
996 * and connect our channel to it. This should only get called
997 * if `multilink' was set at the time establish_ppp was called.
998 * In demand mode this uses our existing bundle instead of making
1001 void make_new_bundle(int mrru, int mtru, int rssn, int tssn)
1003 if (!new_style_driver)
1006 /* make us a ppp unit */
1007 if (make_ppp_unit() < 0)
1010 /* set the mrru and flags */
1011 cfg_bundle(mrru, mtru, rssn, tssn);
1015 * bundle_attach - attach our link to a given PPP unit.
1016 * We assume the unit is controlled by another pppd.
1018 int bundle_attach(int ifnum)
1022 if (!new_style_driver)
1025 master_fd = open("/dev/ppp", O_RDWR);
1027 fatal("Couldn't open /dev/ppp: %m");
1028 if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) {
1029 if (errno == ENXIO) {
1031 return 0; /* doesn't still exist */
1033 fatal("Couldn't attach to interface unit %d: %m\n", ifnum);
1035 if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0)
1036 fatal("Couldn't connect to interface unit %d: %m", ifnum);
1037 modify_flags(master_fd, 0, SC_MULTILINK);
1045 * destroy_bundle - tell the driver to destroy our bundle.
1047 void destroy_bundle(void)
1049 if (ppp_dev_fd >= 0) {
1051 remove_fd(ppp_dev_fd);
1056 /********************************************************************
1058 * clean_check - Fetch the flags for the device and generate
1059 * appropriate error messages.
1061 void clean_check(void)
1067 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
1069 switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
1071 s = "all had bit 7 set to 1";
1075 s = "all had bit 7 set to 0";
1079 s = "all had odd parity";
1083 s = "all had even parity";
1088 warn("Receive serial link is not 8-bit clean:");
1089 warn("Problem: %s", s);
1097 * List of valid speeds.
1101 int speed_int, speed_val;
1164 { 115200, B115200 },
1167 { 153600, B153600 },
1176 { 230400, B230400 },
1179 { 307200, B307200 },
1182 { 460800, B460800 },
1185 { 500000, B500000 },
1188 { 576000, B576000 },
1191 { 614400, B614400 },
1194 { 921600, B921600 },
1197 { 1000000, B1000000 },
1200 { 1152000, B1152000 },
1203 { 1500000, B1500000 },
1206 { 2000000, B2000000 },
1209 { 2500000, B2500000 },
1212 { 3000000, B3000000 },
1215 { 3500000, B3500000 },
1218 { 4000000, B4000000 },
1223 /********************************************************************
1225 * Translate from bits/second to a speed_t.
1228 static int translate_speed (int bps)
1230 struct speed *speedp;
1233 for (speedp = speeds; speedp->speed_int; speedp++) {
1234 if (bps == speedp->speed_int)
1235 return speedp->speed_val;
1241 /********************************************************************
1243 * Translate from a speed_t to bits/second.
1246 static int baud_rate_of (int speed)
1248 struct speed *speedp;
1251 for (speedp = speeds; speedp->speed_int; speedp++) {
1252 if (speed == speedp->speed_val)
1253 return speedp->speed_int;
1259 /********************************************************************
1261 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
1262 * at the requested speed, etc. If `local' is true, set CLOCAL
1263 * regardless of whether the modem option was specified.
1266 void set_up_tty(int tty_fd, int local)
1269 struct termios tios;
1272 if (tcgetattr(tty_fd, &tios) < 0) {
1273 if (!ok_error(errno))
1274 fatal("tcgetattr: %m (line %d)", __LINE__);
1281 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
1282 tios.c_cflag |= CS8 | CREAD | HUPCL;
1284 tios.c_iflag = IGNBRK | IGNPAR;
1287 tios.c_cc[VMIN] = 1;
1288 tios.c_cc[VTIME] = 0;
1290 if (local || !modem)
1291 tios.c_cflag ^= (CLOCAL | HUPCL);
1295 tios.c_cflag |= CRTSCTS;
1299 tios.c_iflag |= IXON | IXOFF;
1300 tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
1301 tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
1305 tios.c_cflag &= ~CRTSCTS;
1313 tios.c_cflag |= CSTOPB;
1316 speed = translate_speed(inspeed);
1318 cfsetospeed (&tios, speed);
1319 cfsetispeed (&tios, speed);
1320 speed = cfgetospeed(&tios);
1321 baud_rate = baud_rate_of(speed);
1324 tios.c_cflag &= ~CBAUD;
1325 tios.c_cflag |= BOTHER;
1326 tios.c_ospeed = inspeed;
1328 /* B0 sets input baudrate to the output baudrate */
1329 tios.c_cflag &= ~(CBAUD << IBSHIFT);
1330 tios.c_cflag |= B0 << IBSHIFT;
1331 tios.c_ispeed = inspeed;
1333 baud_rate = inspeed;
1340 speed = cfgetospeed(&tios);
1341 baud_rate = baud_rate_of(speed);
1344 baud_rate = tios.c_ospeed;
1349 * We can't proceed if the serial port baud rate is unknown,
1350 * since that implies that the serial port is disabled.
1354 fatal("speed %d not supported", inspeed);
1356 fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
1359 while (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0 && !ok_error(errno))
1361 fatal("tcsetattr: %m (line %d)", __LINE__);
1365 /********************************************************************
1367 * setdtr - control the DTR line on the serial port.
1368 * This is called from die(), so it shouldn't call die().
1371 void setdtr (int tty_fd, int on)
1373 int modembits = TIOCM_DTR;
1375 ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
1378 /********************************************************************
1380 * restore_tty - restore the terminal to the saved settings.
1383 void restore_tty (int tty_fd)
1388 * Turn off echoing, because otherwise we can get into
1389 * a loop with the tty and the modem echoing to each other.
1390 * We presume we are the sole user of this tty device, so
1391 * when we close it, it will revert to its defaults anyway.
1393 if (!default_device)
1394 inittermios.c_lflag &= ~(ECHO | ECHONL);
1396 if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0) {
1397 if (! ok_error (errno))
1398 warn("tcsetattr: %m (line %d)", __LINE__);
1403 /********************************************************************
1405 * output - Output PPP packet.
1408 void output (int unit, unsigned char *p, int len)
1413 dump_packet("sent", p, len);
1414 if (snoop_send_hook) snoop_send_hook(p, len);
1416 if (len < PPP_HDRLEN)
1418 if (new_style_driver) {
1421 proto = (p[0] << 8) + p[1];
1422 if (ppp_dev_fd >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
1425 if (write(fd, p, len) < 0) {
1426 if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOBUFS
1427 || errno == ENXIO || errno == EIO || errno == EINTR)
1428 warn("write: warning: %m (%d)", errno);
1430 error("write: %m (%d)", errno);
1434 /********************************************************************
1436 * wait_input - wait until there is data available,
1437 * for the length of time specified by *timo (indefinite
1441 void wait_input(struct timeval *timo)
1448 n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
1449 if (n < 0 && errno != EINTR)
1450 fatal("select: %m");
1454 * add_fd - add an fd to the set that wait_input waits for.
1458 if (fd >= FD_SETSIZE)
1459 fatal("internal error: file descriptor too large (%d)", fd);
1460 FD_SET(fd, &in_fds);
1466 * remove_fd - remove an fd from the set that wait_input waits for.
1468 void remove_fd(int fd)
1470 FD_CLR(fd, &in_fds);
1474 /********************************************************************
1476 * read_packet - get a PPP packet from the serial device.
1479 int read_packet (unsigned char *buf)
1483 len = PPP_MRU + PPP_HDRLEN;
1484 if (new_style_driver) {
1485 *buf++ = PPP_ALLSTATIONS;
1491 nr = read(ppp_fd, buf, len);
1492 if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1493 && errno != EIO && errno != EINTR)
1495 if (nr < 0 && errno == ENXIO)
1498 if (nr < 0 && new_style_driver && ppp_dev_fd >= 0 && !bundle_eof) {
1499 /* N.B. we read ppp_fd first since LCP packets come in there. */
1500 nr = read(ppp_dev_fd, buf, len);
1501 if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN
1502 && errno != EIO && errno != EINTR)
1503 error("read /dev/ppp: %m");
1504 if (nr < 0 && errno == ENXIO)
1506 if (nr == 0 && doing_multilink) {
1507 remove_fd(ppp_dev_fd);
1511 if (new_style_driver && ppp_fd < 0 && ppp_dev_fd < 0)
1513 return (new_style_driver && nr > 0)? nr+2: nr;
1516 /********************************************************************
1518 * get_loop_output - get outgoing packets from the ppp device,
1519 * and detect when we want to bring the real link up.
1520 * Return value is 1 if we need to bring up the link, 0 otherwise.
1523 get_loop_output(void)
1528 if (new_style_driver) {
1529 while ((n = read_packet(inpacket_buf)) > 0)
1530 if (loop_frame(inpacket_buf, n))
1535 while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0)
1536 if (loop_chars(inbuf, n))
1540 fatal("eof on loopback");
1542 if (errno != EWOULDBLOCK && errno != EAGAIN)
1543 fatal("read from loopback: %m(%d)", errno);
1549 * netif_set_mtu - set the MTU on the PPP network interface.
1552 netif_set_mtu(int unit, int mtu)
1556 memset (&ifr, '\0', sizeof (ifr));
1557 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1560 if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
1561 error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);
1565 * netif_get_mtu - get the MTU on the PPP network interface.
1568 netif_get_mtu(int unit)
1572 memset (&ifr, '\0', sizeof (ifr));
1573 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1575 if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
1576 error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__);
1582 /********************************************************************
1584 * tty_send_config - configure the transmit characteristics of
1585 * the ppp interface.
1588 void tty_send_config(int mtu, u_int32_t asyncmap, int pcomp, int accomp)
1595 if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
1596 if (errno != EIO && errno != ENOTTY)
1597 error("Couldn't set transmit async character map: %m");
1602 x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0)
1603 | (sync_serial? SC_SYNC: 0);
1604 modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x);
1607 /********************************************************************
1609 * tty_set_xaccm - set the extended transmit ACCM for the interface.
1612 void tty_set_xaccm (ext_accm accm)
1616 if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) {
1617 if ( ! ok_error (errno))
1618 warn("ioctl(set extended ACCM): %m (line %d)", __LINE__);
1622 /********************************************************************
1624 * tty_recv_config - configure the receive-side characteristics of
1625 * the ppp interface.
1628 void tty_recv_config(int mru, u_int32_t asyncmap, int pcomp, int accomp)
1631 * If we were called because the link has gone down then there is nothing
1632 * which may be done. Just return without incident.
1637 * Set the receiver parameters
1639 if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
1640 if (errno != EIO && errno != ENOTTY)
1641 error("Couldn't set channel receive MRU: %m");
1643 if (new_style_driver && ppp_dev_fd >= 0
1644 && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
1645 error("Couldn't set MRU in generic PPP layer: %m");
1647 if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
1648 if (errno != EIO && errno != ENOTTY)
1649 error("Couldn't set channel receive asyncmap: %m");
1653 /********************************************************************
1655 * ccp_test - ask kernel whether a given compression method
1656 * is acceptable for use.
1660 ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
1662 struct ppp_option_data data;
1664 memset (&data, '\0', sizeof (data));
1666 data.length = opt_len;
1667 data.transmit = for_transmit;
1669 if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1672 return (errno == ENOBUFS)? 0: -1;
1675 /********************************************************************
1677 * ccp_flags_set - inform kernel about the current state of CCP.
1680 void ccp_flags_set (int unit, int isopen, int isup)
1684 x = (isopen? SC_CCP_OPEN: 0) | (isup? SC_CCP_UP: 0);
1685 if (still_ppp() && ppp_dev_fd >= 0)
1686 modify_flags(ppp_dev_fd, SC_CCP_OPEN|SC_CCP_UP, x);
1689 #ifdef PPP_WITH_FILTER
1691 * set_filters - set the active and pass filters in the kernel driver.
1693 int set_filters(struct bpf_program *pass, struct bpf_program *active)
1695 struct sock_fprog fp;
1697 fp.len = pass->bf_len;
1698 fp.filter = (struct sock_filter *) pass->bf_insns;
1699 if (ioctl(ppp_dev_fd, PPPIOCSPASS, &fp) < 0) {
1700 if (errno == ENOTTY)
1701 warn("kernel does not support PPP filtering");
1703 error("Couldn't set pass-filter in kernel: %m");
1706 fp.len = active->bf_len;
1707 fp.filter = (struct sock_filter *) active->bf_insns;
1708 if (ioctl(ppp_dev_fd, PPPIOCSACTIVE, &fp) < 0) {
1709 error("Couldn't set active-filter in kernel: %m");
1714 #endif /* PPP_WITH_FILTER */
1716 /********************************************************************
1718 * get_idle_time - return how long the link has been idle.
1721 get_idle_time(int u, struct ppp_idle *ip)
1723 return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;
1726 /********************************************************************
1728 * get_ppp_stats_iocl - return statistics for the link, using the ioctl() method,
1729 * this only supports 32-bit counters, so need to count the wraps.
1732 get_ppp_stats_ioctl(int u, struct pppd_stats *stats)
1734 static u_int32_t previbytes = 0;
1735 static u_int32_t prevobytes = 0;
1736 static u_int32_t iwraps = 0;
1737 static u_int32_t owraps = 0;
1740 struct ppp_stats data;
1742 memset (&req, 0, sizeof (req));
1744 req.ifr_data = (caddr_t) &data;
1745 strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name));
1746 if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
1747 error("Couldn't get PPP statistics: %m");
1750 stats->bytes_in = data.p.ppp_ibytes;
1751 stats->bytes_out = data.p.ppp_obytes;
1752 stats->pkts_in = data.p.ppp_ipackets;
1753 stats->pkts_out = data.p.ppp_opackets;
1755 if (stats->bytes_in < previbytes)
1757 if (stats->bytes_out < prevobytes)
1760 previbytes = stats->bytes_in;
1761 prevobytes = stats->bytes_out;
1763 stats->bytes_in += (uint64_t)iwraps << 32;
1764 stats->bytes_out += (uint64_t)owraps << 32;
1769 /********************************************************************
1770 * get_ppp_stats_rtnetlink - return statistics for the link, using rtnetlink
1771 * This provides native 64-bit counters.
1774 get_ppp_stats_rtnetlink(int u, struct pppd_stats *stats)
1779 struct nlmsghdr nlh;
1780 struct if_stats_msg ifsm;
1785 /* We only case about these first fields from rtnl_link_stats64 */
1786 uint64_t rx_packets;
1787 uint64_t tx_packets;
1795 memset(&nlreq, 0, sizeof(nlreq));
1796 nlreq.nlh.nlmsg_len = sizeof(nlreq);
1797 nlreq.nlh.nlmsg_type = RTM_GETSTATS;
1798 nlreq.nlh.nlmsg_flags = NLM_F_REQUEST;
1799 nlreq.ifsm.ifindex = if_nametoindex(ifname);
1800 nlreq.ifsm.filter_mask = IFLA_STATS_LINK_64;
1802 nlresp_size = sizeof(nlresp_data);
1803 resp = rtnetlink_msg("RTM_GETSTATS/NLM_F_REQUEST", &fd, &nlreq, sizeof(nlreq), &nlresp_data, &nlresp_size, RTM_NEWSTATS);
1805 errno = (resp < 0) ? -resp : EINVAL;
1806 if (kernel_version >= KVERSION(4,7,0))
1807 error("get_ppp_stats_rtnetlink: %m (line %d)", __LINE__);
1811 if (nlresp_size < sizeof(nlresp_data)) {
1812 error("get_ppp_stats_rtnetlink: Obtained an insufficiently sized rtnl_link_stats64 struct from the kernel (line %d).", __LINE__);
1816 stats->bytes_in = nlresp_data.stats.rx_bytes;
1817 stats->bytes_out = nlresp_data.stats.tx_bytes;
1818 stats->pkts_in = nlresp_data.stats.rx_packets;
1819 stats->pkts_out = nlresp_data.stats.tx_packets;
1828 /********************************************************************
1829 * get_ppp_stats_sysfs - return statistics for the link, using the files in sysfs,
1830 * this provides native 64-bit counters.
1833 get_ppp_stats_sysfs(int u, struct pppd_stats *stats)
1835 char fname[PATH_MAX+1];
1836 char buf[21], *err; /* 2^64 < 10^20 */
1838 unsigned long long val;
1845 #define statfield(fn, field) { .fname = #fn, .ptr = &stats->field, .size = sizeof(stats->field) }
1846 statfield(rx_bytes, bytes_in),
1847 statfield(tx_bytes, bytes_out),
1848 statfield(rx_packets, pkts_in),
1849 statfield(tx_packets, pkts_out),
1853 blen = snprintf(fname, sizeof(fname), "/sys/class/net/%s/statistics/", ifname);
1854 if (blen >= sizeof(fname))
1855 return 0; /* ifname max 15, so this should be impossible */
1857 for (int i = 0; i < sizeof(slist) / sizeof(*slist); ++i) {
1858 if (snprintf(fname + blen, sizeof(fname) - blen, "%s", slist[i].fname) >= sizeof(fname) - blen) {
1860 error("sysfs stats: filename %s/%s overflowed PATH_MAX", fname, slist[i].fname);
1864 fd = open(fname, O_RDONLY);
1866 error("%s: %m", fname);
1870 rlen = read(fd, buf, sizeof(buf) - 1);
1873 error("%s: %m", fname);
1876 /* trim trailing \n if present */
1877 while (rlen > 0 && buf[rlen-1] == '\n')
1882 val = strtoull(buf, &err, 10);
1883 if (*buf < '0' || *buf > '9' || errno != 0 || *err) {
1884 error("string to number conversion error converting %s (from %s) for remaining string %s%s%s",
1885 buf, fname, err, errno ? ": " : "", errno ? strerror(errno) : "");
1888 switch (slist[i].size) {
1889 #define stattype(type) case sizeof(type): *(type*)slist[i].ptr = (type)val; break
1896 error("Don't know how to store stats for %s of size %u", slist[i].fname, slist[i].size);
1904 /********************************************************************
1905 * Periodic timer function to be used to keep stats up to date in case of ioctl
1908 * Given the 25s interval this should be fine up to data rates of 1.37Gbps.
1909 * If you do change the timer, remember to also bring the get_ppp_stats (which
1910 * sets up the initial trigger) as well.
1913 ppp_stats_poller(void* u)
1915 struct pppd_stats dummy;
1916 get_ppp_stats_ioctl((long)u, &dummy);
1917 TIMEOUT(ppp_stats_poller, u, 25);
1920 /********************************************************************
1921 * get_ppp_stats - return statistics for the link.
1923 int get_ppp_stats(int u, struct pppd_stats *stats)
1925 static int (*func)(int, struct pppd_stats*) = NULL;
1928 if (get_ppp_stats_rtnetlink(u, stats)) {
1929 func = get_ppp_stats_rtnetlink;
1932 if (get_ppp_stats_sysfs(u, stats)) {
1933 func = get_ppp_stats_sysfs;
1936 warn("statistics falling back to ioctl which only supports 32-bit counters");
1937 func = get_ppp_stats_ioctl;
1938 TIMEOUT(ppp_stats_poller, (void*)(long)u, 25);
1941 return func(u, stats);
1944 /********************************************************************
1946 * ccp_fatal_error - returns 1 if decompression was disabled as a
1947 * result of an error detected after decompression of a packet,
1948 * 0 otherwise. This is necessary because of patent nonsense.
1951 int ccp_fatal_error (int unit)
1955 if (ioctl(ppp_dev_fd, PPPIOCGFLAGS, &flags) < 0) {
1956 error("Couldn't read compression error flags: %m");
1959 return flags & SC_DC_FERROR;
1962 /********************************************************************
1964 * path_to_procfs - find the path to the proc file system mount point
1966 static char proc_path[MAXPATHLEN];
1967 static int proc_path_len;
1969 static char *path_to_procfs(const char *tail)
1971 struct mntent *mntent;
1974 if (proc_path_len == 0) {
1975 /* Default the mount location of /proc */
1976 strlcpy (proc_path, "/proc", sizeof(proc_path));
1978 fp = fopen(MOUNTED, "r");
1980 while ((mntent = getmntent(fp)) != NULL) {
1981 if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
1983 if (strcmp(mntent->mnt_type, "proc") == 0) {
1984 strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path));
1985 proc_path_len = strlen(proc_path);
1993 strlcpy(proc_path + proc_path_len, tail,
1994 sizeof(proc_path) - proc_path_len);
1999 * /proc/net/route parsing stuff.
2001 #define ROUTE_MAX_COLS 12
2002 FILE *route_fd = (FILE *) 0;
2003 static char route_buffer[512];
2004 static int route_dev_col, route_dest_col, route_gw_col;
2005 static int route_flags_col, route_metric_col, route_mask_col;
2006 static int route_num_cols;
2008 static int open_route_table (void);
2009 static void close_route_table (void);
2010 static int read_route_table (struct rtentry *rt);
2012 /********************************************************************
2014 * close_route_table - close the interface to the route table
2017 static void close_route_table (void)
2019 if (route_fd != (FILE *) 0) {
2021 route_fd = (FILE *) 0;
2025 /********************************************************************
2027 * open_route_table - open the interface to the route table
2029 static char route_delims[] = " \t\n";
2031 static int open_route_table (void)
2035 close_route_table();
2037 path = path_to_procfs("/net/route");
2038 route_fd = fopen (path, "r");
2039 if (route_fd == NULL) {
2040 error("can't open routing table %s: %m", path);
2044 route_dev_col = 0; /* default to usual columns */
2047 route_flags_col = 3;
2048 route_metric_col = 6;
2052 /* parse header line */
2053 if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
2054 char *p = route_buffer, *q;
2056 for (col = 0; col < ROUTE_MAX_COLS; ++col) {
2058 if ((q = strtok(p, route_delims)) == 0)
2060 if (strcasecmp(q, "iface") == 0)
2061 route_dev_col = col;
2062 else if (strcasecmp(q, "destination") == 0)
2063 route_dest_col = col;
2064 else if (strcasecmp(q, "gateway") == 0)
2066 else if (strcasecmp(q, "flags") == 0)
2067 route_flags_col = col;
2068 else if (strcasecmp(q, "mask") == 0)
2069 route_mask_col = col;
2072 if (used && col >= route_num_cols)
2073 route_num_cols = col + 1;
2081 /********************************************************************
2083 * read_route_table - read the next entry from the route table
2086 static int read_route_table(struct rtentry *rt)
2088 char *cols[ROUTE_MAX_COLS], *p;
2091 memset (rt, '\0', sizeof (struct rtentry));
2093 if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
2097 for (col = 0; col < route_num_cols; ++col) {
2098 cols[col] = strtok(p, route_delims);
2099 if (cols[col] == NULL)
2100 return 0; /* didn't get enough columns */
2104 SET_SA_FAMILY (rt->rt_dst, AF_INET);
2105 SET_SA_FAMILY (rt->rt_gateway, AF_INET);
2107 SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
2108 SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
2109 SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
2111 rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
2112 rt->rt_metric = (short) strtoul(cols[route_metric_col], NULL, 10);
2113 rt->rt_dev = cols[route_dev_col];
2118 /********************************************************************
2120 * defaultroute_exists - determine if there is a default route
2121 * with the given metric (or negative for any)
2124 static int defaultroute_exists (struct rtentry *rt, int metric)
2128 if (!open_route_table())
2131 while (read_route_table(rt) != 0) {
2132 if ((rt->rt_flags & RTF_UP) == 0)
2135 if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
2137 if (SIN_ADDR(rt->rt_dst) == 0L && (metric < 0
2138 || rt->rt_metric == metric)) {
2144 close_route_table();
2149 * have_route_to - determine if the system has any route to
2150 * a given IP address. `addr' is in network byte order.
2151 * Return value is 1 if yes, 0 if no, -1 if don't know.
2152 * For demand mode to work properly, we have to ignore routes
2153 * through our own interface.
2155 int have_route_to(u_int32_t addr)
2160 if (!open_route_table())
2161 return -1; /* don't know */
2163 while (read_route_table(&rt)) {
2164 if ((rt.rt_flags & RTF_UP) == 0 || strcmp(rt.rt_dev, ifname) == 0)
2166 if ((addr & SIN_ADDR(rt.rt_genmask)) == SIN_ADDR(rt.rt_dst)) {
2172 close_route_table();
2176 /********************************************************************
2178 * sifdefaultroute - assign a default route through the address given.
2180 * If the global default_rt_repl_rest flag is set, then this function
2181 * already replaced the original system defaultroute with some other
2182 * route and it should just replace the current defaultroute with
2183 * another one, without saving the current route. Use: demand mode,
2184 * when pppd sets first a defaultroute it it's temporary ppp0 addresses
2185 * and then changes the temporary addresses to the addresses for the real
2186 * ppp connection when it has come up.
2189 int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
2191 struct rtentry rt, tmp_rt;
2192 struct rtentry *del_rt = NULL;
2194 if (default_rt_repl_rest) {
2195 /* We have already replaced the original defaultroute, if we
2196 * are called again, we will delete the current default route
2197 * and set the new default route in this function.
2198 * - this is normally only the case the doing demand: */
2199 if (defaultroute_exists(&tmp_rt, -1))
2201 } else if (defaultroute_exists(&old_def_rt, -1 ) &&
2202 strcmp( old_def_rt.rt_dev, ifname) != 0) {
2204 * We did not yet replace an existing default route, let's
2205 * check if we should save and replace a default route:
2207 u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway);
2209 if (old_gateway != gateway) {
2211 error("not replacing default route to %s [%I]",
2212 old_def_rt.rt_dev, old_gateway);
2215 /* we need to copy rt_dev because we need it permanent too: */
2216 char * tmp_dev = malloc(strlen(old_def_rt.rt_dev)+1);
2217 strcpy(tmp_dev, old_def_rt.rt_dev);
2218 old_def_rt.rt_dev = tmp_dev;
2220 notice("replacing old default route to %s [%I]",
2221 old_def_rt.rt_dev, old_gateway);
2222 default_rt_repl_rest = 1;
2223 del_rt = &old_def_rt;
2228 memset (&rt, 0, sizeof (rt));
2229 SET_SA_FAMILY (rt.rt_dst, AF_INET);
2232 rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
2234 if (kernel_version > KVERSION(2,1,0)) {
2235 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2236 SIN_ADDR(rt.rt_genmask) = 0L;
2239 rt.rt_flags = RTF_UP;
2240 if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
2241 if ( ! ok_error ( errno ))
2242 error("default route ioctl(SIOCADDRT): %m");
2245 if (default_rt_repl_rest && del_rt)
2246 if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
2247 if ( ! ok_error ( errno ))
2248 error("del old default route ioctl(SIOCDELRT): %m(%d)", errno);
2252 have_default_route = 1;
2256 /********************************************************************
2258 * cifdefaultroute - delete a default route through the address given.
2261 int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
2265 have_default_route = 0;
2267 memset (&rt, '\0', sizeof (rt));
2268 SET_SA_FAMILY (rt.rt_dst, AF_INET);
2269 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2274 rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
2276 if (kernel_version > KVERSION(2,1,0)) {
2277 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
2278 SIN_ADDR(rt.rt_genmask) = 0L;
2281 rt.rt_flags = RTF_UP;
2282 if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
2284 if ( ! ok_error ( errno ))
2285 error("default route ioctl(SIOCDELRT): %m");
2289 if (default_rt_repl_rest) {
2290 notice("restoring old default route to %s [%I]",
2291 old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
2292 if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
2293 if ( ! ok_error ( errno ))
2294 error("restore default route ioctl(SIOCADDRT): %m(%d)", errno);
2297 default_rt_repl_rest = 0;
2303 #ifdef PPP_WITH_IPV6CP
2305 * /proc/net/ipv6_route parsing stuff.
2307 static int route_dest_plen_col;
2308 static int open_route6_table (void);
2309 static int read_route6_table (struct in6_rtmsg *rt);
2311 /********************************************************************
2313 * open_route6_table - open the interface to the route table
2315 static int open_route6_table (void)
2319 close_route_table();
2321 path = path_to_procfs("/net/ipv6_route");
2322 route_fd = fopen (path, "r");
2323 if (route_fd == NULL) {
2324 error("can't open routing table %s: %m", path);
2328 /* default to usual columns */
2330 route_dest_plen_col = 1;
2332 route_metric_col = 5;
2333 route_flags_col = 8;
2335 route_num_cols = 10;
2340 /********************************************************************
2342 * read_route6_table - read the next entry from the route table
2345 static void hex_to_in6_addr(struct in6_addr *addr, const char *s)
2352 for (i = 0; i < 4; i++) {
2353 memcpy(hex8, s + 8*i, 8);
2354 v = strtoul(hex8, NULL, 16);
2355 addr->s6_addr32[i] = v;
2359 static int read_route6_table(struct in6_rtmsg *rt)
2361 char *cols[ROUTE_MAX_COLS], *p;
2364 memset (rt, '\0', sizeof (struct in6_rtmsg));
2366 if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
2370 for (col = 0; col < route_num_cols; ++col) {
2371 cols[col] = strtok(p, route_delims);
2372 if (cols[col] == NULL)
2373 return 0; /* didn't get enough columns */
2377 hex_to_in6_addr(&rt->rtmsg_dst, cols[route_dest_col]);
2378 rt->rtmsg_dst_len = strtoul(cols[route_dest_plen_col], NULL, 16);
2379 hex_to_in6_addr(&rt->rtmsg_gateway, cols[route_gw_col]);
2381 rt->rtmsg_metric = strtoul(cols[route_metric_col], NULL, 16);
2382 rt->rtmsg_flags = strtoul(cols[route_flags_col], NULL, 16);
2383 rt->rtmsg_ifindex = if_nametoindex(cols[route_dev_col]);
2388 /********************************************************************
2390 * defaultroute6_exists - determine if there is a default route
2393 static int defaultroute6_exists (struct in6_rtmsg *rt, int metric)
2397 if (!open_route6_table())
2400 while (read_route6_table(rt) != 0) {
2401 if ((rt->rtmsg_flags & RTF_UP) == 0)
2404 if (rt->rtmsg_dst_len != 0)
2406 if (rt->rtmsg_dst.s6_addr32[0] == 0L
2407 && rt->rtmsg_dst.s6_addr32[1] == 0L
2408 && rt->rtmsg_dst.s6_addr32[2] == 0L
2409 && rt->rtmsg_dst.s6_addr32[3] == 0L
2410 && (metric < 0 || rt->rtmsg_metric == metric)) {
2416 close_route_table();
2420 /********************************************************************
2422 * sif6defaultroute - assign a default route through the address given.
2424 * If the global default_rt_repl_rest flag is set, then this function
2425 * already replaced the original system defaultroute with some other
2426 * route and it should just replace the current defaultroute with
2427 * another one, without saving the current route. Use: demand mode,
2428 * when pppd sets first a defaultroute it it's temporary ppp0 addresses
2429 * and then changes the temporary addresses to the addresses for the real
2430 * ppp connection when it has come up.
2433 int sif6defaultroute (int unit, eui64_t ouraddr, eui64_t gateway)
2435 struct in6_rtmsg rt;
2436 char buf[IF_NAMESIZE];
2438 if (defaultroute6_exists(&rt, dfl_route_metric) &&
2439 rt.rtmsg_ifindex != if_nametoindex(ifname)) {
2440 if (rt.rtmsg_flags & RTF_GATEWAY)
2441 error("not replacing existing default route via gateway");
2443 error("not replacing existing default route through %s",
2444 if_indextoname(rt.rtmsg_ifindex, buf));
2448 memset (&rt, 0, sizeof (rt));
2450 rt.rtmsg_ifindex = if_nametoindex(ifname);
2451 rt.rtmsg_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
2452 rt.rtmsg_dst_len = 0;
2454 rt.rtmsg_flags = RTF_UP;
2455 if (ioctl(sock6_fd, SIOCADDRT, &rt) < 0) {
2456 if ( ! ok_error ( errno ))
2457 error("default route ioctl(SIOCADDRT): %m");
2461 have_default_route6 = 1;
2465 /********************************************************************
2467 * cif6defaultroute - delete a default route through the address given.
2470 int cif6defaultroute (int unit, eui64_t ouraddr, eui64_t gateway)
2472 struct in6_rtmsg rt;
2474 have_default_route6 = 0;
2476 memset (&rt, '\0', sizeof (rt));
2478 rt.rtmsg_ifindex = if_nametoindex(ifname);
2479 rt.rtmsg_metric = dfl_route_metric + 1; /* +1 for binary compatibility */
2480 rt.rtmsg_dst_len = 0;
2482 rt.rtmsg_flags = RTF_UP;
2483 if (ioctl(sock6_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
2485 if ( ! ok_error ( errno ))
2486 error("default route ioctl(SIOCDELRT): %m");
2493 #endif /* PPP_WITH_IPV6CP */
2495 /********************************************************************
2497 * sifproxyarp - Make a proxy ARP entry for the peer.
2500 int sifproxyarp (int unit, u_int32_t his_adr)
2502 struct arpreq arpreq;
2505 if (has_proxy_arp == 0) {
2506 memset (&arpreq, '\0', sizeof(arpreq));
2508 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
2509 SIN_ADDR(arpreq.arp_pa) = his_adr;
2510 arpreq.arp_flags = ATF_PERM | ATF_PUBL;
2512 * Get the hardware address of an interface on the same subnet
2513 * as our local address.
2515 if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,
2516 sizeof(proxy_arp_dev))) {
2517 error("Cannot determine ethernet address for proxy ARP");
2520 strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
2522 if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
2523 if ( ! ok_error ( errno ))
2524 error("ioctl(SIOCSARP): %m");
2527 proxy_arp_addr = his_adr;
2531 forw_path = path_to_procfs("/sys/net/ipv4/ip_forward");
2532 if (forw_path != 0) {
2533 int fd = open(forw_path, O_WRONLY);
2535 if (write(fd, "1", 1) != 1)
2536 error("Couldn't enable IP forwarding: %m");
2546 /********************************************************************
2548 * cifproxyarp - Delete the proxy ARP entry for the peer.
2551 int cifproxyarp (int unit, u_int32_t his_adr)
2553 struct arpreq arpreq;
2555 if (has_proxy_arp) {
2557 memset (&arpreq, '\0', sizeof(arpreq));
2558 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
2559 SIN_ADDR(arpreq.arp_pa) = his_adr;
2560 arpreq.arp_flags = ATF_PERM | ATF_PUBL;
2561 strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
2563 if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
2564 if ( ! ok_error ( errno ))
2565 warn("ioctl(SIOCDARP): %m");
2572 /********************************************************************
2574 * get_ether_addr - get the hardware address of an interface on the
2575 * the same subnet as ipaddr.
2578 static int get_ether_addr (u_int32_t ipaddr,
2579 struct sockaddr *hwaddr,
2580 char *name, int namelen)
2582 struct ifreq *ifr, *ifend;
2583 u_int32_t ina, mask;
2585 struct ifreq ifreq, bestifreq;
2587 struct ifreq ifs[MAX_IFS];
2589 u_int32_t bestmask=0;
2590 int found_interface = 0;
2592 ifc.ifc_len = sizeof(ifs);
2594 if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
2595 if ( ! ok_error ( errno ))
2596 error("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
2601 * Scan through looking for an interface with an Internet
2602 * address on the same subnet as `ipaddr'.
2604 ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
2605 for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
2606 if (ifr->ifr_addr.sa_family == AF_INET) {
2607 ina = SIN_ADDR(ifr->ifr_addr);
2608 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
2610 * Check that the interface is up, and not point-to-point
2613 if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
2616 if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
2619 * Get its netmask and check that it's on the right subnet.
2621 if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
2624 mask = SIN_ADDR(ifreq.ifr_addr);
2626 if (((ipaddr ^ ina) & mask) != 0)
2627 continue; /* no match */
2629 if (mask >= bestmask) {
2630 /* Compare using >= instead of > -- it is possible for
2631 an interface to have a netmask of 0.0.0.0 */
2632 found_interface = 1;
2639 if (!found_interface) return 0;
2641 strlcpy(name, bestifreq.ifr_name, namelen);
2643 /* trim off the :1 in eth0:1 */
2644 aliasp = strchr(name, ':');
2648 info("found interface %s for proxy arp", name);
2650 * Now get the hardware address.
2652 memset (&bestifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
2653 if (ioctl (sock_fd, SIOCGIFHWADDR, &bestifreq) < 0) {
2654 error("SIOCGIFHWADDR(%s): %m", bestifreq.ifr_name);
2659 &bestifreq.ifr_hwaddr,
2660 sizeof (struct sockaddr));
2666 * get_if_hwaddr - get the hardware address for the specified
2667 * network interface device.
2670 get_if_hwaddr(u_char *addr, char *name)
2675 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
2678 memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
2679 strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
2680 ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
2683 memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6);
2688 * get_first_ether_hwaddr - get the hardware address for the first
2689 * ethernet-style interface on this system.
2692 get_first_ether_hwaddr(u_char *addr)
2694 struct if_nameindex *if_ni, *i;
2698 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
2702 if_ni = if_nameindex();
2710 for (i = if_ni; !(i->if_index == 0 && i->if_name == NULL); i++) {
2711 memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
2712 strlcpy(ifreq.ifr_name, i->if_name, sizeof(ifreq.ifr_name));
2713 ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
2714 if (ret >= 0 && ifreq.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
2715 memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6);
2721 if_freenameindex(if_ni);
2727 /********************************************************************
2729 * Return user specified netmask, modified by any mask we might determine
2730 * for address `addr' (in network byte order).
2731 * Here we scan through the system's list of interfaces, looking for
2732 * any non-point-to-point interfaces which might appear to be on the same
2733 * network as `addr'. If we find any, we OR in their netmask to the
2734 * user-specified netmask.
2737 u_int32_t GetMask (u_int32_t addr)
2739 u_int32_t mask, nmask, ina;
2740 struct ifreq *ifr, *ifend, ifreq;
2742 struct ifreq ifs[MAX_IFS];
2746 if (IN_CLASSA(addr)) /* determine network mask for address class */
2747 nmask = IN_CLASSA_NET;
2748 else if (IN_CLASSB(addr))
2749 nmask = IN_CLASSB_NET;
2751 nmask = IN_CLASSC_NET;
2753 /* class D nets are disallowed by bad_ip_adrs */
2754 mask = netmask | htonl(nmask);
2756 * Scan through the system's network interfaces.
2758 ifc.ifc_len = sizeof(ifs);
2760 if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
2761 if ( ! ok_error ( errno ))
2762 warn("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);
2766 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
2767 for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
2769 * Check the interface's internet address.
2771 if (ifr->ifr_addr.sa_family != AF_INET)
2773 ina = SIN_ADDR(ifr->ifr_addr);
2774 if (((ntohl(ina) ^ addr) & nmask) != 0)
2777 * Check that the interface is up, and not point-to-point nor loopback.
2779 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
2780 if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
2783 if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
2786 * Get its netmask and OR it into our mask.
2788 if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
2790 mask |= SIN_ADDR(ifreq.ifr_addr);
2796 /********************************************************************
2798 * Internal routine to decode the version.modification.patch level
2801 static void decode_version (char *buf, int *version,
2802 int *modification, int *patch)
2806 *version = (int) strtoul (buf, &endp, 10);
2810 if (endp != buf && *endp == '.') {
2812 *modification = (int) strtoul (buf, &endp, 10);
2813 if (endp != buf && *endp == '.') {
2815 *patch = (int) strtoul (buf, &buf, 10);
2820 /********************************************************************
2822 * Procedure to determine if the PPP line discipline is registered.
2826 ppp_registered(void)
2834 * We used to open the serial device and set it to the ppp line
2835 * discipline here, in order to create a ppp unit. But that is
2836 * not a good idea - the user might have specified a device that
2837 * they can't open (permission, or maybe it doesn't really exist).
2838 * So we grab a pty master/slave pair and use that.
2840 if (!get_pty(&mfd, &local_fd, slave, 0)) {
2841 no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";
2846 * Try to put the device into the PPP discipline.
2848 if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
2849 error("ioctl(TIOCSETD(PPP)): %m (line %d)", __LINE__);
2858 /********************************************************************
2860 * ppp_available - check whether the system has any ppp interfaces
2861 * (in fact we check whether we can do an ioctl on ppp0).
2864 int ppp_available(void)
2869 int my_version, my_modification, my_patch;
2870 int osmaj, osmin, ospatch;
2872 /* get the kernel version now, since we are called before sys_init */
2874 osmaj = osmin = ospatch = 0;
2875 sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
2876 kernel_version = KVERSION(osmaj, osmin, ospatch);
2878 fd = open("/dev/ppp", O_RDWR);
2880 new_style_driver = 1;
2882 /* XXX should get from driver */
2884 driver_modification = 4;
2890 if (kernel_version >= KVERSION(2,3,13)) {
2891 error("Couldn't open the /dev/ppp device: %m");
2892 if (errno == ENOENT)
2894 "You need to create the /dev/ppp device node by\n"
2895 "executing the following command as root:\n"
2896 " mknod /dev/ppp c 108 0\n";
2897 else if (errno == ENODEV || errno == ENXIO)
2899 "Please load the ppp_generic kernel module.\n";
2903 /* we are running on a really really old kernel */
2905 "This system lacks kernel support for PPP. This could be because\n"
2906 "the PPP kernel module could not be loaded, or because PPP was not\n"
2907 "included in the kernel configuration. If PPP was included as a\n"
2908 "module, try `/sbin/modprobe -v ppp'. If that fails, check that\n"
2909 "ppp.o exists in /lib/modules/`uname -r`/net.\n"
2910 "See README.linux file in the ppp distribution for more details.\n";
2913 * Open a socket for doing the ioctl operations.
2915 s = socket(AF_INET, SOCK_DGRAM, 0);
2919 strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2920 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2922 * If the device did not exist then attempt to create one by putting the
2923 * current tty into the PPP discipline. If this works then obtain the
2924 * flags for the device again.
2927 if (ppp_registered()) {
2928 strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
2929 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
2933 * Ensure that the hardware address is for PPP and not something else
2936 ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
2938 if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
2942 * This is the PPP device. Validate the version of the driver at this
2943 * point to ensure that this program will work with the driver.
2946 char abBuffer [1024];
2948 ifr.ifr_data = abBuffer;
2949 size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
2951 error("Couldn't read driver version: %m");
2953 no_ppp_msg = "Sorry, couldn't verify kernel driver version\n";
2956 decode_version(abBuffer,
2958 &driver_modification,
2961 * Validate the version of the driver against the version that we used.
2963 decode_version(VERSION,
2968 /* The version numbers must match */
2969 if (driver_version != my_version)
2972 /* The modification levels must be legal */
2973 if (driver_modification < 3) {
2974 if (driver_modification >= 2) {
2975 /* we can cope with 2.2.0 and above */
2983 slprintf(route_buffer, sizeof(route_buffer),
2984 "Sorry - PPP driver version %d.%d.%d is out of date\n",
2985 driver_version, driver_modification, driver_patch);
2987 no_ppp_msg = route_buffer;
2995 #ifndef HAVE_LOGWTMP
2996 /********************************************************************
2998 * Update the wtmp file with the appropriate user name and tty device.
3001 void logwtmp (const char *line, const char *name, const char *host)
3003 struct utmp ut, *utp;
3004 pid_t mypid = getpid();
3010 * Update the signon database for users.
3011 * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
3013 utmpname(_PATH_UTMP);
3015 while ((utp = getutent()) && (utp->ut_pid != mypid))
3019 memcpy(&ut, utp, sizeof(ut));
3021 /* some gettys/telnetds don't initialize utmp... */
3022 memset(&ut, 0, sizeof(ut));
3024 if (ut.ut_id[0] == 0)
3025 strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
3027 strncpy(ut.ut_user, name, sizeof(ut.ut_user));
3028 strncpy(ut.ut_line, line, sizeof(ut.ut_line));
3032 ut.ut_type = USER_PROCESS;
3035 /* Insert the host name if one is supplied */
3037 strncpy (ut.ut_host, host, sizeof(ut.ut_host));
3039 /* Insert the IP address of the remote system if IP is enabled */
3040 if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
3041 memcpy(&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
3042 sizeof(ut.ut_addr));
3044 /* CL: Makes sure that the logout works */
3045 if (*host == 0 && *name==0)
3051 * Update the wtmp file.
3054 updwtmp(_PATH_WTMP, &ut);
3056 wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
3058 flock(wtmp, LOCK_EX);
3060 if (write (wtmp, (char *)&ut, sizeof(ut)) != sizeof(ut))
3061 warn("error writing %s: %m", _PATH_WTMP);
3063 flock(wtmp, LOCK_UN);
3069 #endif /* HAVE_LOGWTMP */
3071 /********************************************************************
3073 * sifvjcomp - config tcp header compression
3076 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
3081 if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
3082 error("Couldn't set up TCP header compression: %m");
3087 x = (vjcomp? SC_COMP_TCP: 0) | (cidcomp? 0: SC_NO_TCP_CCID);
3088 modify_flags(ppp_dev_fd, SC_COMP_TCP|SC_NO_TCP_CCID, x);
3093 /********************************************************************
3095 * sifup - Config the interface up and enable IP packets to pass.
3102 if ((ret = setifstate(u, 1)))
3108 /********************************************************************
3110 * sifdown - Disable the indicated protocol and config the interface
3111 * down if there are no remaining protocols.
3116 if (if_is_up && --if_is_up > 0)
3119 #ifdef PPP_WITH_IPV6CP
3122 #endif /* PPP_WITH_IPV6CP */
3124 return setifstate(u, 0);
3127 #ifdef PPP_WITH_IPV6CP
3128 /********************************************************************
3130 * sif6up - Config the interface up for IPv6
3137 if ((ret = setifstate(u, 1)))
3143 /********************************************************************
3145 * sif6down - Disable the IPv6CP protocol and config the interface
3146 * down if there are no remaining protocols.
3149 int sif6down (int u)
3156 return setifstate(u, 0);
3158 #endif /* PPP_WITH_IPV6CP */
3160 /********************************************************************
3162 * setifstate - Config the interface up or down
3165 static int setifstate (int u, int state)
3169 memset (&ifr, '\0', sizeof (ifr));
3170 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
3171 if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
3172 if (! ok_error (errno))
3173 error("ioctl (SIOCGIFFLAGS): %m (line %d)", __LINE__);
3178 ifr.ifr_flags |= IFF_UP;
3180 ifr.ifr_flags &= ~IFF_UP;
3181 ifr.ifr_flags |= IFF_POINTOPOINT;
3182 if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
3183 if (! ok_error (errno))
3184 error("ioctl(SIOCSIFFLAGS): %m (line %d)", __LINE__);
3190 /********************************************************************
3192 * sifaddr - Config the interface IP addresses and netmask.
3195 int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
3201 memset (&ifr, '\0', sizeof (ifr));
3202 memset (&rt, '\0', sizeof (rt));
3204 SET_SA_FAMILY (ifr.ifr_addr, AF_INET);
3205 SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
3206 SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
3208 strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
3210 * Set our IP address
3212 SIN_ADDR(ifr.ifr_addr) = our_adr;
3213 if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
3214 if (errno != EEXIST) {
3215 if (! ok_error (errno))
3216 error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
3219 warn("ioctl(SIOCSIFADDR): Address already exists");
3224 * Set the gateway address
3227 SIN_ADDR(ifr.ifr_dstaddr) = his_adr;
3228 if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
3229 if (! ok_error (errno))
3230 error("ioctl(SIOCSIFDSTADDR): %m (line %d)", __LINE__);
3236 * For recent kernels, force the netmask to 255.255.255.255.
3238 if (kernel_version >= KVERSION(2,1,16))
3240 if (net_mask != 0) {
3241 SIN_ADDR(ifr.ifr_netmask) = net_mask;
3242 if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
3243 if (! ok_error (errno))
3244 error("ioctl(SIOCSIFNETMASK): %m (line %d)", __LINE__);
3249 * Add the device route
3251 if (kernel_version < KVERSION(2,1,16)) {
3252 SET_SA_FAMILY (rt.rt_dst, AF_INET);
3253 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
3256 SIN_ADDR(rt.rt_gateway) = 0L;
3257 SIN_ADDR(rt.rt_dst) = his_adr;
3258 rt.rt_flags = RTF_UP | RTF_HOST;
3260 if (kernel_version > KVERSION(2,1,0)) {
3261 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
3262 SIN_ADDR(rt.rt_genmask) = -1L;
3265 if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
3266 if (! ok_error (errno))
3267 error("ioctl(SIOCADDRT) device route: %m (line %d)", __LINE__);
3272 /* set ip_dynaddr in demand mode if address changes */
3273 if (demand && tune_kernel && !dynaddr_set
3274 && our_old_addr && our_old_addr != our_adr) {
3275 /* set ip_dynaddr if possible */
3279 path = path_to_procfs("/sys/net/ipv4/ip_dynaddr");
3280 if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
3281 if (write(fd, "1", 1) != 1)
3282 error("Couldn't enable dynamic IP addressing: %m");
3285 dynaddr_set = 1; /* only 1 attempt */
3292 /********************************************************************
3294 * cifaddr - Clear the interface IP addresses, and delete routes
3295 * through the interface if possible.
3298 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
3302 if (kernel_version < KVERSION(2,1,16)) {
3304 * Delete the route through the device
3307 memset (&rt, '\0', sizeof (rt));
3309 SET_SA_FAMILY (rt.rt_dst, AF_INET);
3310 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
3313 SIN_ADDR(rt.rt_gateway) = 0;
3314 SIN_ADDR(rt.rt_dst) = his_adr;
3315 rt.rt_flags = RTF_UP | RTF_HOST;
3317 if (kernel_version > KVERSION(2,1,0)) {
3318 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
3319 SIN_ADDR(rt.rt_genmask) = -1L;
3322 if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
3323 if (still_ppp() && ! ok_error (errno))
3324 error("ioctl(SIOCDELRT) device route: %m (line %d)", __LINE__);
3329 /* This way it is possible to have an IPv6-only interface */
3330 memset(&ifr, 0, sizeof(ifr));
3331 SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
3332 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3334 if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
3335 if (! ok_error (errno)) {
3336 error("ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
3341 our_old_addr = our_adr;
3346 #ifdef PPP_WITH_IPV6CP
3347 /********************************************************************
3349 * sif6addr_rtnetlink - Config the interface with both IPv6 link-local addresses via rtnetlink
3351 static int sif6addr_rtnetlink(unsigned int iface, eui64_t our_eui64, eui64_t his_eui64)
3354 struct nlmsghdr nlh;
3355 struct ifaddrmsg ifa;
3358 struct in6_addr addr;
3363 memset(&nlreq, 0, sizeof(nlreq));
3364 nlreq.nlh.nlmsg_len = sizeof(nlreq);
3365 nlreq.nlh.nlmsg_type = RTM_NEWADDR;
3366 nlreq.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
3367 nlreq.ifa.ifa_family = AF_INET6;
3368 nlreq.ifa.ifa_prefixlen = 128;
3369 nlreq.ifa.ifa_flags = IFA_F_NODAD | IFA_F_PERMANENT;
3370 nlreq.ifa.ifa_scope = RT_SCOPE_LINK;
3371 nlreq.ifa.ifa_index = iface;
3372 nlreq.addrs[0].rta.rta_len = sizeof(nlreq.addrs[0]);
3373 nlreq.addrs[0].rta.rta_type = IFA_LOCAL;
3374 IN6_LLADDR_FROM_EUI64(nlreq.addrs[0].addr, our_eui64);
3375 nlreq.addrs[1].rta.rta_len = sizeof(nlreq.addrs[1]);
3376 nlreq.addrs[1].rta.rta_type = IFA_ADDRESS;
3379 * To set only local address, older kernel expects that local address is
3380 * in IFA_ADDRESS field (not IFA_LOCAL). New kernels with support for peer
3381 * address, ignore IFA_ADDRESS if is same as IFA_LOCAL. So for backward
3382 * compatibility when setting only local address, set it via both IFA_LOCAL
3383 * and IFA_ADDRESS fields. Same logic is implemented in 'ip address' command
3384 * from iproute2 project.
3386 if (!eui64_iszero(his_eui64))
3387 IN6_LLADDR_FROM_EUI64(nlreq.addrs[1].addr, his_eui64);
3389 IN6_LLADDR_FROM_EUI64(nlreq.addrs[1].addr, our_eui64);
3391 resp = rtnetlink_msg("RTM_NEWADDR/NLM_F_CREATE", NULL, &nlreq, sizeof(nlreq), NULL, NULL, 0);
3394 * Linux kernel versions prior 3.11 do not support setting IPv6 peer
3395 * addresses and error response is expected. On older kernel versions
3396 * do not show this error message. On error pppd tries to fallback to
3397 * the old IOCTL method.
3399 errno = (resp < 0) ? -resp : EINVAL;
3400 if (kernel_version >= KVERSION(3,11,0))
3401 error("sif6addr_rtnetlink: %m (line %d)", __LINE__);
3408 /********************************************************************
3410 * sif6addr - Config the interface with an IPv6 link-local address
3412 int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
3414 struct in6_ifreq ifr6;
3416 struct in6_rtmsg rt6;
3421 error("IPv6 socket creation failed: %m");
3424 memset(&ifr, 0, sizeof (ifr));
3425 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3426 if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
3427 error("sif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
3431 if (kernel_version >= KVERSION(2,1,16)) {
3432 /* Set both local address and remote peer address (with route for it) via rtnetlink */
3433 ret = sif6addr_rtnetlink(ifr.ifr_ifindex, our_eui64, his_eui64);
3439 * Linux kernel versions prior 3.11 do not support setting IPv6 peer address
3440 * via rtnetlink. So if sif6addr_rtnetlink() fails then try old IOCTL method.
3443 /* Local interface */
3444 memset(&ifr6, 0, sizeof(ifr6));
3445 IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
3446 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
3447 ifr6.ifr6_prefixlen = 128;
3449 if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
3450 error("sif6addr: ioctl(SIOCSIFADDR): %m (line %d)", __LINE__);
3455 if (!ret && !eui64_iszero(his_eui64)) {
3457 * Linux kernel does not provide AF_INET6 ioctl SIOCSIFDSTADDR for
3458 * setting remote peer host address, so set only route to remote host.
3461 /* Route to remote host */
3462 memset(&rt6, 0, sizeof(rt6));
3463 IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
3464 rt6.rtmsg_flags = RTF_UP;
3465 rt6.rtmsg_dst_len = 128;
3466 rt6.rtmsg_ifindex = ifr.ifr_ifindex;
3467 rt6.rtmsg_metric = 1;
3469 if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
3470 error("sif6addr: ioctl(SIOCADDRT): %m (line %d)", __LINE__);
3479 /********************************************************************
3481 * cif6addr - Remove IPv6 address from interface
3483 int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
3486 struct in6_ifreq ifr6;
3490 error("IPv6 socket creation failed: %m");
3493 memset(&ifr, 0, sizeof(ifr));
3494 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
3495 if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
3496 error("cif6addr: ioctl(SIOCGIFINDEX): %m (line %d)", __LINE__);
3500 memset(&ifr6, 0, sizeof(ifr6));
3501 IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
3502 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
3503 ifr6.ifr6_prefixlen = 128;
3505 if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
3506 if (errno != EADDRNOTAVAIL) {
3507 if (! ok_error (errno))
3508 error("cif6addr: ioctl(SIOCDIFADDR): %m (line %d)", __LINE__);
3511 warn("cif6addr: ioctl(SIOCDIFADDR): No such address");
3517 #endif /* PPP_WITH_IPV6CP */
3520 * get_pty - get a pty master/slave pair and chown the slave side
3521 * to the uid given. Assumes slave_name points to >= 16 bytes of space.
3524 get_pty(int *master_fdp, int *slave_fdp, char *slave_name, int uid)
3526 int i, mfd, ret, sfd = -1;
3528 struct termios tios;
3532 * Try the unix98 way first.
3534 mfd = open("/dev/ptmx", O_RDWR);
3537 if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) {
3538 slprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn);
3539 chmod(pty_name, S_IRUSR | S_IWUSR);
3542 if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0)
3543 warn("Couldn't unlock pty slave %s: %m", pty_name);
3545 if ((sfd = open(pty_name, O_RDWR | O_NOCTTY)) < 0)
3547 warn("Couldn't open pty slave %s: %m", pty_name);
3552 #endif /* TIOCGPTN */
3555 /* the old way - scan through the pty name space */
3556 for (i = 0; i < 64; ++i) {
3557 slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
3558 'p' + i / 16, i % 16);
3559 mfd = open(pty_name, O_RDWR, 0);
3562 sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
3564 ret = fchown(sfd, uid, -1);
3566 warn("Couldn't change ownership of %s, %m", pty_name);
3568 ret = fchmod(sfd, S_IRUSR | S_IWUSR);
3570 warn("Couldn't change permissions of %s, %m", pty_name);
3582 strlcpy(slave_name, pty_name, 16);
3585 if (tcgetattr(sfd, &tios) == 0) {
3586 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
3587 tios.c_cflag |= CS8 | CREAD | CLOCAL;
3588 tios.c_iflag = IGNPAR;
3591 if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
3592 warn("couldn't set attributes on pty: %m");
3594 warn("couldn't get attributes on pty: %m");
3599 /********************************************************************
3601 * open_loopback - open the device we use for getting packets
3602 * in demand mode. Under Linux, we use a pty master/slave pair.
3605 open_ppp_loopback(void)
3610 if (new_style_driver) {
3611 /* allocate ourselves a ppp unit */
3612 if (make_ppp_unit() < 0)
3614 modify_flags(ppp_dev_fd, 0, SC_LOOP_TRAFFIC);
3615 set_kdebugflag(kdebugflag);
3620 if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
3621 fatal("No free pty for loopback");
3623 set_ppp_fd(slave_fd);
3625 flags = fcntl(master_fd, F_GETFL);
3627 fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
3628 warn("couldn't set master loopback to nonblock: %m");
3630 flags = fcntl(ppp_fd, F_GETFL);
3632 fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
3633 warn("couldn't set slave loopback to nonblock: %m");
3635 if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
3636 fatal("ioctl(TIOCSETD): %m (line %d)", __LINE__);
3638 * Find out which interface we were given.
3640 if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
3641 fatal("ioctl(PPPIOCGUNIT): %m (line %d)", __LINE__);
3643 * Enable debug in the driver if requested.
3645 set_kdebugflag (kdebugflag);
3650 /********************************************************************
3652 * sifnpmode - Set the mode for handling packets for a given NP.
3656 sifnpmode(int u, int proto, enum NPmode mode)
3660 npi.protocol = proto;
3662 if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
3663 if (! ok_error (errno))
3664 error("ioctl(PPPIOCSNPMODE, %d, %d): %m", proto, mode);
3671 * Use the hostname as part of the random number seed.
3680 for (p = hostname; *p != 0; ++p)
3685 /********************************************************************
3687 * sys_check_options - check the options that the user specified
3691 sys_check_options(void)
3693 if (demand && driver_is_old) {
3694 option_error("demand dialling is not supported by kernel driver "
3695 "version %d.%d.%d", driver_version, driver_modification,
3699 if (multilink && !new_style_driver) {
3700 warn("Warning: multilink is not supported by the kernel driver");
3706 /********************************************************************
3708 * get_time - Get current time, monotonic if possible.
3711 get_time(struct timeval *tv)
3713 /* Old glibc (< 2.3.4) does define CLOCK_MONOTONIC, but kernel may have it.
3714 * Runtime checking makes it safe. */
3715 #ifndef CLOCK_MONOTONIC
3716 #define CLOCK_MONOTONIC 1
3718 static int monotonic = -1;
3723 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
3727 tv->tv_sec = ts.tv_sec;
3728 tv->tv_usec = ts.tv_nsec / 1000;
3731 } else if (monotonic > 0)
3735 warn("Couldn't use monotonic clock source: %m");
3738 return gettimeofday(tv, NULL);