CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / pppoecd / sys-linux.c
blob847323b695d07fd0a5f55ea98854ca160dacefa8
1 /*
2 * sys-linux.c - System-dependent procedures for setting up
3 * PPP interfaces on Linux systems
5 * Copyright (c) 1989 Carnegie Mellon University.
6 * All rights reserved.
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by Carnegie Mellon University. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/time.h>
25 #include <sys/errno.h>
26 #include <sys/file.h>
27 #include <sys/stat.h>
28 #include <sys/utsname.h>
29 #include <sys/sysmacros.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <syslog.h>
34 #include <string.h>
35 #include <time.h>
36 #include <memory.h>
37 #include <utmp.h>
38 #include <mntent.h>
39 #include <signal.h>
40 #include <fcntl.h>
41 #include <ctype.h>
42 #include <termios.h>
43 #include <unistd.h>
45 /* This is in netdevice.h. However, this compile will fail miserably if
46 you attempt to include netdevice.h because it has so many references
47 to __memcpy functions which it should not attempt to do. So, since I
48 really don't use it, but it must be defined, define it now. */
50 #ifndef MAX_ADDR_LEN
51 #define MAX_ADDR_LEN 7
52 #endif
54 #if __GLIBC__ >= 2
55 #include <asm/types.h> /* glibc 2 conflicts with linux/types.h */
56 #include <net/if.h>
57 #include <net/if_arp.h>
58 #include <net/route.h>
59 #include <netinet/if_ether.h>
60 #else
61 #include <linux/types.h>
62 #include <linux/if.h>
63 #include <linux/if_arp.h>
64 #include <linux/route.h>
65 #include <linux/if_ether.h>
66 #endif
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
70 #include <linux/ppp_defs.h>
71 #include <linux/if_ppp.h>
73 #include "pppd.h"
74 #include "fsm.h"
75 #include "ipcp.h"
77 #ifdef INET6
78 #ifndef _LINUX_IN6_H
80 * This is in linux/include/net/ipv6.h.
83 struct in6_ifreq {
84 struct in6_addr ifr6_addr;
85 __u32 ifr6_prefixlen;
86 unsigned int ifr6_ifindex;
88 #endif
90 #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do { \
91 memset(&sin6.s6_addr, 0, sizeof(struct in6_addr)); \
92 sin6.s6_addr16[0] = htons(0xfe80); \
93 eui64_copy(eui64, sin6.s6_addr32[2]); \
94 } while (0)
95 #endif /* INET6 */
97 /* We can get an EIO error on an ioctl if the modem has hung up */
98 #define ok_error(num) ((num)==EIO)
100 static int tty_disc = N_TTY; /* The TTY discipline */
101 static int ppp_disc = N_PPP; /* The PPP discpline */
102 static int initfdflags = -1; /* Initial file descriptor flags for fd */
103 static int ppp_fd = -1; /* fd which is set to PPP discipline */
104 static int sock_fd = -1; /* socket for doing interface ioctls */
105 static int slave_fd = -1;
106 static int master_fd = -1;
107 #ifdef INET6
108 static int sock6_fd = -1;
109 #endif /* INET6 */
110 static int ppp_dev_fd = -1; /* fd for /dev/ppp (new style driver) */
111 static int chindex; /* channel index (new style driver) */
113 static fd_set in_fds; /* set of fds that wait_input waits for */
114 static int max_in_fd; /* highest fd set in in_fds */
116 static int driver_version = 0;
117 static int driver_modification = 0;
118 static int driver_patch = 0;
120 // static char loop_name[20];
121 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
123 static int if_is_up; /* Interface has been marked up */
124 static u_int32_t our_old_addr; /* for detecting address changes */
125 static int dynaddr_set; /* 1 if ip_dynaddr set */
126 static int looped; /* 1 if using loop */
128 static int kernel_version;
129 #define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p))
131 #define MAX_IFS 100
133 #define FLAGS_GOOD (IFF_UP | IFF_BROADCAST)
134 #define FLAGS_MASK (IFF_UP | IFF_BROADCAST | \
135 IFF_POINTOPOINT | IFF_LOOPBACK | IFF_NOARP)
137 #define SIN_ADDR(x) (((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
139 /* Prototypes for procedures local to this file. */
140 static int get_flags (int fd);
141 static void set_flags (int fd, int flags);
142 static int make_ppp_unit(void);
143 static void restore_loop(void); /* Transfer ppp unit back to loopback */
145 extern u_char inpacket_buf[]; /* borrowed from main.c */
148 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
149 * if it exists.
152 #define SET_SA_FAMILY(addr, family) \
153 memset ((char *) &(addr), '\0', sizeof(addr)); \
154 addr.sa_family = (family);
157 * Determine if the PPP connection should still be present.
160 extern int hungup;
162 /* new_fd is the fd of a tty */
163 static void set_ppp_fd (int new_fd)
165 SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", new_fd));
166 ppp_fd = new_fd;
167 if (!new_style_driver)
168 ppp_dev_fd = new_fd;
171 static int still_ppp(void)
173 if (new_style_driver)
174 return !hungup && ppp_fd >= 0;
175 if (!hungup || ppp_fd == slave_fd)
176 return 1;
177 if (slave_fd >= 0) {
178 set_ppp_fd(slave_fd);
179 return 1;
181 return 0;
184 /********************************************************************
186 * Functions to read and set the flags value in the device driver
189 static int get_flags (int fd)
191 int flags;
193 if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
194 if ( ok_error (errno) )
195 flags = 0;
196 else
197 fatal("ioctl(PPPIOCGFLAGS): %m");
200 SYSDEBUG ((LOG_DEBUG, "get flags = %x\n", flags));
201 return flags;
204 /********************************************************************/
206 static void set_flags (int fd, int flags)
208 SYSDEBUG ((LOG_DEBUG, "set flags = %x\n", flags));
210 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0) {
211 if (! ok_error (errno) )
212 fatal("ioctl(PPPIOCSFLAGS, %x): %m", flags, errno);
216 /********************************************************************
218 * sys_init - System-dependent initialization.
221 void sys_init(void)
223 int flags;
225 if (new_style_driver) {
226 ppp_dev_fd = open("/dev/ppp", O_RDWR);
227 if (ppp_dev_fd < 0)
228 fatal("Couldn't open /dev/ppp: %m");
229 flags = fcntl(ppp_dev_fd, F_GETFL);
230 if (flags == -1
231 || fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
232 warn("Couldn't set /dev/ppp to nonblock: %m");
235 /* Get an internet socket for doing socket ioctls. */
236 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
237 if (sock_fd < 0)
238 fatal("Couldn't create IP socket: %m(%d)", errno);
240 #ifdef INET6
241 sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0);
242 if (sock6_fd < 0)
243 sock6_fd = -errno; /* save errno for later */
244 #endif
246 FD_ZERO(&in_fds);
247 max_in_fd = 0;
250 /********************************************************************
252 * sys_cleanup - restore any system state we modified before exiting:
253 * mark the interface down, delete default route and/or proxy arp entry.
254 * This shouldn't call die() because it's called from die().
257 void sys_cleanup(void)
260 * Take down the device
262 if (if_is_up) {
263 if_is_up = 0;
264 sifdown(0);
268 /********************************************************************
270 * sys_close - Clean up in a child process before execing.
272 void
273 sys_close(void)
275 close(ppp_dev_fd);
276 if (sock_fd >= 0)
277 close(sock_fd);
278 if (slave_fd >= 0)
279 close(slave_fd);
280 if (master_fd >= 0)
281 close(master_fd);
282 closelog();
285 /********************************************************************
287 * set_kdebugflag - Define the debugging level for the kernel
290 static int set_kdebugflag (int requested_level)
292 if (new_style_driver && ifunit < 0)
293 return 1;
294 if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
295 if ( ! ok_error (errno) )
296 error("ioctl(PPPIOCSDEBUG): %m");
297 return (0);
299 SYSDEBUG ((LOG_INFO, "set kernel debugging level to %d",
300 requested_level));
301 return (1);
305 /********************************************************************
307 * generic_establish_ppp - Turn the fd into a ppp interface.
309 int generic_establish_ppp (int fd)
311 int x;
313 * Demand mode - prime the old ppp device to relinquish the unit.
315 if (!new_style_driver && looped
316 && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
317 error("ioctl(transfer ppp unit): %m");
318 return -1;
322 if (new_style_driver) {
323 /* Open another instance of /dev/ppp and connect the channel to it */
324 int flags;
326 if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
327 error("Couldn't get channel number: %m");
328 goto err;
330 dbglog("using channel %d", chindex);
331 fd = open("/dev/ppp", O_RDWR);
332 if (fd < 0) {
333 error("Couldn't reopen /dev/ppp: %m");
334 goto err;
336 if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
337 error("Couldn't attach to channel %d: %m", chindex);
338 goto err_close;
340 flags = fcntl(fd, F_GETFL);
341 if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
342 warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
343 set_ppp_fd(fd);
345 if (!looped)
346 ifunit = -1;
347 if (!looped && !multilink) {
349 * Create a new PPP unit.
351 if (make_ppp_unit() < 0)
352 goto err_close;
355 if (looped)
356 set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & ~SC_LOOP_TRAFFIC);
358 if (!multilink) {
359 add_fd(ppp_dev_fd);
360 if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
361 error("Couldn't attach to PPP unit %d: %m", ifunit);
362 goto err_close;
366 } else {
369 * Old-style driver: find out which interface we were given.
371 set_ppp_fd (fd);
372 if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
373 if (ok_error (errno))
374 goto err;
375 fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
377 /* Check that we got the same unit again. */
378 if (looped && x != ifunit)
379 fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
380 ifunit = x;
383 * Fetch the initial file flags and reset blocking mode on the file.
385 initfdflags = fcntl(fd, F_GETFL);
386 if (initfdflags == -1 ||
387 fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
388 if ( ! ok_error (errno))
389 warn("Couldn't set device to non-blocking mode: %m");
395 * Enable debug in the driver if requested.
397 if (!looped)
398 set_kdebugflag (kdebugflag);
400 SYSDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
401 driver_version, driver_modification, driver_patch));
403 return ppp_fd;
405 err_close:
406 close(fd);
407 err:
408 if (ioctl(fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
409 warn("Couldn't reset tty to normal line discipline: %m");
410 return -1;
413 /********************************************************************
415 * generic_disestablish_ppp - Restore device components to normal
416 * operation, and reconnect the ppp unit to the loopback if in demand
417 * mode. This shouldn't call die() because it's called from die().
419 void generic_disestablish_ppp(int dev_fd){
420 /* Restore loop if needed */
421 if(demand)
422 restore_loop();
424 /* Finally detach the device */
425 initfdflags = -1;
427 if (new_style_driver) {
428 close(ppp_fd);
429 ppp_fd = -1;
430 if (!looped && ifunit >= 0 && ioctl(ppp_dev_fd, PPPIOCDETACH) < 0)
431 error("Couldn't release PPP unit: %m");
432 if (!multilink)
433 remove_fd(ppp_dev_fd);
438 * make_ppp_unit - make a new ppp unit for ppp_dev_fd.
439 * Assumes new_style_driver.
441 static int make_ppp_unit()
443 int x;
445 ifunit = req_unit;
446 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
447 if (x < 0 && req_unit >= 0 && errno == EEXIST) {
448 warn("Couldn't allocate PPP unit %d as it is already in use");
449 ifunit = -1;
450 x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
452 if (x < 0)
453 error("Couldn't create new ppp unit: %m");
454 return x;
457 /********************************************************************
459 * clean_check - Fetch the flags for the device and generate
460 * appropriate error messages.
462 void clean_check(void)
464 int x;
465 char *s;
467 if (still_ppp()) {
468 if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
469 s = NULL;
470 switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
471 case SC_RCV_B7_0:
472 s = "all had bit 7 set to 1";
473 break;
475 case SC_RCV_B7_1:
476 s = "all had bit 7 set to 0";
477 break;
479 case SC_RCV_EVNP:
480 s = "all had odd parity";
481 break;
483 case SC_RCV_ODDP:
484 s = "all had even parity";
485 break;
488 if (s != NULL) {
489 warn("Receive serial link is not 8-bit clean:");
490 warn("Problem: %s", s);
496 /********************************************************************
498 * output - Output PPP packet.
501 void output (int unit, unsigned char *p, int len)
503 int fd = ppp_fd;
504 int proto;
506 if (debug)
507 dbglog("sent %P", p, len);
509 if (len < PPP_HDRLEN)
510 return;
511 if (new_style_driver) {
512 p += 2;
513 len -= 2;
514 proto = (p[0] << 8) + p[1];
515 if (ifunit >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG))
516 fd = ppp_dev_fd;
518 if (write(fd, p, len) < 0) {
519 if (errno == EWOULDBLOCK || errno == ENOBUFS
520 || errno == ENXIO || errno == EIO || errno == EINTR)
521 warn("write: warning: %m (%d)", errno);
522 else
523 error("write: %m (%d)", errno);
527 /********************************************************************
529 * wait_input - wait until there is data available,
530 * for the length of time specified by *timo (indefinite
531 * if timo is NULL).
534 void wait_input(struct timeval *timo)
536 fd_set ready, exc;
537 int n;
539 ready = in_fds;
540 exc = in_fds;
541 n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
542 if (n < 0 && errno != EINTR)
543 fatal("select: %m(%d)", errno);
547 * add_fd - add an fd to the set that wait_input waits for.
549 void add_fd(int fd)
551 FD_SET(fd, &in_fds);
552 if (fd > max_in_fd)
553 max_in_fd = fd;
557 * remove_fd - remove an fd from the set that wait_input waits for.
559 void remove_fd(int fd)
561 FD_CLR(fd, &in_fds);
565 /********************************************************************
567 * read_packet - get a PPP packet from the serial device.
570 int read_packet (unsigned char *buf)
572 int len, nr;
574 len = PPP_MRU + PPP_HDRLEN;
575 if (new_style_driver) {
576 *buf++ = PPP_ALLSTATIONS;
577 *buf++ = PPP_UI;
578 len -= 2;
580 nr = -1;
581 if (ppp_fd >= 0) {
582 nr = read(ppp_fd, buf, len);
583 if (nr < 0 && errno != EWOULDBLOCK && errno != EIO && errno != EINTR)
584 error("read: %m");
585 if (nr < 0 && errno == ENXIO)
586 return 0;
588 if (nr < 0 && new_style_driver && ifunit >= 0) {
589 /* N.B. we read ppp_fd first since LCP packets come in there. */
590 nr = read(ppp_dev_fd, buf, len);
591 if (nr < 0 && errno != EWOULDBLOCK && errno != EIO && errno != EINTR)
592 error("read /dev/ppp: %m");
593 if (nr < 0 && errno == ENXIO)
594 return 0;
596 return (new_style_driver && nr > 0)? nr+2: nr;
599 /********************************************************************
601 * get_loop_output - get outgoing packets from the ppp device,
602 * and detect when we want to bring the real link up.
603 * Return value is 1 if we need to bring up the link, 0 otherwise.
606 get_loop_output(void)
608 int rv = 0;
609 int n;
611 if (new_style_driver) {
612 while ((n = read_packet(inpacket_buf)) > 0)
613 if (loop_frame(inpacket_buf, n))
614 rv = 1;
615 return rv;
618 while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0)
619 if (loop_chars(inbuf, n))
620 rv = 1;
622 if (n == 0)
623 fatal("eof on loopback");
625 if (errno != EWOULDBLOCK)
626 fatal("read from loopback: %m(%d)", errno);
628 return rv;
632 * netif_set_mtu - set the MTU on the PPP network interface.
634 void
635 netif_set_mtu(int unit, int mtu)
637 struct ifreq ifr;
639 SYSDEBUG ((LOG_DEBUG, "netif_set_mtu: mtu = %d\n", mtu));
641 memset (&ifr, '\0', sizeof (ifr));
642 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
643 ifr.ifr_mtu = mtu;
645 if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
646 fatal("ioctl(SIOCSIFMTU): %m");
649 /********************************************************************
651 * ccp_test - ask kernel whether a given compression method
652 * is acceptable for use.
655 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
657 struct ppp_option_data data;
659 memset (&data, '\0', sizeof (data));
660 data.ptr = opt_ptr;
661 data.length = opt_len;
662 data.transmit = for_transmit;
664 if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
665 return 1;
667 return (errno == ENOBUFS)? 0: -1;
670 /********************************************************************
672 * ccp_flags_set - inform kernel about the current state of CCP.
675 void ccp_flags_set (int unit, int isopen, int isup)
677 if (still_ppp()) {
678 int x = get_flags(ppp_dev_fd);
679 x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
680 x = isup? x | SC_CCP_UP : x &~ SC_CCP_UP;
681 set_flags (ppp_dev_fd, x);
685 /********************************************************************
687 * get_idle_time - return how long the link has been idle.
690 get_idle_time(u, ip)
691 int u;
692 struct ppp_idle *ip;
694 return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;
697 /********************************************************************
699 * get_ppp_stats - return statistics for the link.
702 get_ppp_stats(u, stats)
703 int u;
704 struct pppd_stats *stats;
706 struct ifpppstatsreq req;
708 memset (&req, 0, sizeof (req));
710 req.stats_ptr = (caddr_t) &req.stats;
711 strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
712 if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
713 error("Couldn't get PPP statistics: %m");
714 return 0;
716 stats->bytes_in = req.stats.p.ppp_ibytes;
717 stats->bytes_out = req.stats.p.ppp_obytes;
718 return 1;
721 /********************************************************************
723 * ccp_fatal_error - returns 1 if decompression was disabled as a
724 * result of an error detected after decompression of a packet,
725 * 0 otherwise. This is necessary because of patent nonsense.
728 int ccp_fatal_error (int unit)
730 int x = get_flags(ppp_dev_fd);
732 return x & SC_DC_FERROR;
735 /********************************************************************
737 * Return user specified netmask, modified by any mask we might determine
738 * for address `addr' (in network byte order).
739 * Here we scan through the system's list of interfaces, looking for
740 * any non-point-to-point interfaces which might appear to be on the same
741 * network as `addr'. If we find any, we OR in their netmask to the
742 * user-specified netmask.
745 u_int32_t GetMask (u_int32_t addr)
747 u_int32_t mask, nmask, ina;
748 struct ifreq *ifr, *ifend, ifreq;
749 struct ifconf ifc;
750 struct ifreq ifs[MAX_IFS];
752 addr = ntohl(addr);
754 if (IN_CLASSA(addr)) /* determine network mask for address class */
755 nmask = IN_CLASSA_NET;
756 else if (IN_CLASSB(addr))
757 nmask = IN_CLASSB_NET;
758 else
759 nmask = IN_CLASSC_NET;
761 /* class D nets are disallowed by bad_ip_adrs */
762 mask = netmask | htonl(nmask);
764 * Scan through the system's network interfaces.
766 ifc.ifc_len = sizeof(ifs);
767 ifc.ifc_req = ifs;
768 if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
769 if ( ! ok_error ( errno ))
770 warn("ioctl(SIOCGIFCONF): %m(%d)", errno);
771 return mask;
774 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
775 for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
777 * Check the interface's internet address.
779 if (ifr->ifr_addr.sa_family != AF_INET)
780 continue;
781 ina = SIN_ADDR(ifr->ifr_addr);
782 if (((ntohl(ina) ^ addr) & nmask) != 0)
783 continue;
785 * Check that the interface is up, and not point-to-point nor loopback.
787 strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
788 if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
789 continue;
791 if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
792 continue;
794 * Get its netmask and OR it into our mask.
796 if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
797 continue;
798 mask |= SIN_ADDR(ifreq.ifr_addr);
799 break;
801 return mask;
804 /********************************************************************
806 * ppp_available - check whether the system has any ppp interfaces
807 * (in fact we check whether we can do an ioctl on ppp0).
810 int ppp_available(void)
812 struct utsname utsname; /* for the kernel version */
813 int osmaj, osmin, ospatch;
815 /* get the kernel version now, since we are called before sys_init */
816 uname(&utsname);
817 osmaj = osmin = ospatch = 0;
818 sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
819 kernel_version = KVERSION(osmaj, osmin, ospatch);
821 driver_version = 2;
822 driver_modification = 4;
823 driver_patch = 0;
825 return 1;
828 /********************************************************************
830 * sifvjcomp - config tcp header compression
833 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
835 u_int x = get_flags(ppp_dev_fd);
837 if (vjcomp) {
838 if (ioctl (ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
839 if (! ok_error (errno))
840 error("ioctl(PPPIOCSMAXCID): %m(%d)", errno);
841 vjcomp = 0;
845 x = vjcomp ? x | SC_COMP_TCP : x &~ SC_COMP_TCP;
846 x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
847 set_flags (ppp_dev_fd, x);
849 return 1;
852 /********************************************************************
854 * sifup - Config the interface up and enable IP packets to pass.
857 int sifup(int u)
859 struct ifreq ifr;
861 memset (&ifr, '\0', sizeof (ifr));
862 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
863 if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
864 if (! ok_error (errno))
865 error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
866 return 0;
869 ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
870 if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
871 if (! ok_error (errno))
872 error("ioctl(SIOCSIFFLAGS): %m(%d)", errno);
873 return 0;
875 if_is_up++;
877 return 1;
880 /********************************************************************
882 * sifdown - Disable the indicated protocol and config the interface
883 * down if there are no remaining protocols.
886 int sifdown (int u)
888 struct ifreq ifr;
890 if (if_is_up && --if_is_up > 0)
891 return 1;
893 memset (&ifr, '\0', sizeof (ifr));
894 strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
895 if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
896 if (! ok_error (errno))
897 error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
898 return 0;
901 ifr.ifr_flags &= ~IFF_UP;
902 ifr.ifr_flags |= IFF_POINTOPOINT;
903 if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
904 if (! ok_error (errno))
905 error("ioctl(SIOCSIFFLAGS): %m(%d)", errno);
906 return 0;
908 return 1;
911 /********************************************************************
913 * sifaddr - Config the interface IP addresses and netmask.
916 int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
917 u_int32_t net_mask)
919 struct ifreq ifr;
920 struct rtentry rt;
922 memset (&ifr, '\0', sizeof (ifr));
923 memset (&rt, '\0', sizeof (rt));
925 SET_SA_FAMILY (ifr.ifr_addr, AF_INET);
926 SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
927 SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
929 strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
931 * Set our IP address
933 SIN_ADDR(ifr.ifr_addr) = our_adr;
934 if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
935 if (errno != EEXIST) {
936 if (! ok_error (errno))
937 error("ioctl(SIOCSIFADDR): %m(%d)", errno);
939 else {
940 warn("ioctl(SIOCSIFADDR): Address already exists");
942 return (0);
945 * Set the gateway address
947 SIN_ADDR(ifr.ifr_dstaddr) = his_adr;
948 if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
949 if (! ok_error (errno))
950 error("ioctl(SIOCSIFDSTADDR): %m(%d)", errno);
951 return (0);
954 * Set the netmask.
955 * For recent kernels, force the netmask to 255.255.255.255.
957 if (kernel_version >= KVERSION(2,1,16))
958 net_mask = ~0L;
959 if (net_mask != 0) {
960 SIN_ADDR(ifr.ifr_netmask) = net_mask;
961 if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
962 if (! ok_error (errno))
963 error("ioctl(SIOCSIFNETMASK): %m(%d)", errno);
964 return (0);
968 * Add the device route
970 if (kernel_version < KVERSION(2,1,16)) {
971 SET_SA_FAMILY (rt.rt_dst, AF_INET);
972 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
973 rt.rt_dev = ifname;
975 SIN_ADDR(rt.rt_gateway) = 0L;
976 SIN_ADDR(rt.rt_dst) = his_adr;
977 rt.rt_flags = RTF_UP | RTF_HOST;
979 if (kernel_version > KVERSION(2,1,0)) {
980 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
981 SIN_ADDR(rt.rt_genmask) = -1L;
984 if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
985 if (! ok_error (errno))
986 error("ioctl(SIOCADDRT) device route: %m(%d)", errno);
987 return (0);
991 /* set ip_dynaddr in demand mode if address changes */
992 if (demand && tune_kernel && !dynaddr_set
993 && our_old_addr && our_old_addr != our_adr) {
994 /* set ip_dynaddr if possible */
995 char *path;
996 int fd;
998 path = "/proc/sys/net/ipv4/ip_dynaddr";
999 if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) {
1000 if (write(fd, "1", 1) != 1)
1001 error("Couldn't enable dynamic IP addressing: %m");
1002 close(fd);
1004 dynaddr_set = 1; /* only 1 attempt */
1006 our_old_addr = 0;
1008 return 1;
1011 /********************************************************************
1013 * cifaddr - Clear the interface IP addresses, and delete routes
1014 * through the interface if possible.
1017 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
1019 struct ifreq ifr;
1021 if (kernel_version < KVERSION(2,1,16)) {
1023 * Delete the route through the device
1025 struct rtentry rt;
1026 memset (&rt, '\0', sizeof (rt));
1028 SET_SA_FAMILY (rt.rt_dst, AF_INET);
1029 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1030 rt.rt_dev = ifname;
1032 SIN_ADDR(rt.rt_gateway) = 0;
1033 SIN_ADDR(rt.rt_dst) = his_adr;
1034 rt.rt_flags = RTF_UP | RTF_HOST;
1036 if (kernel_version > KVERSION(2,1,0)) {
1037 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1038 SIN_ADDR(rt.rt_genmask) = -1L;
1041 if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
1042 if (still_ppp() && ! ok_error (errno))
1043 error("ioctl(SIOCDELRT) device route: %m(%d)", errno);
1044 return (0);
1048 /* This way it is possible to have an IPX-only or IPv6-only interface */
1049 memset(&ifr, 0, sizeof(ifr));
1050 SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1051 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1053 if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
1054 if (! ok_error (errno)) {
1055 error("ioctl(SIOCSIFADDR): %m(%d)", errno);
1056 return 0;
1060 our_old_addr = our_adr;
1062 return 1;
1065 #ifdef INET6
1066 /********************************************************************
1068 * sif6addr - Config the interface with an IPv6 link-local address
1070 int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
1072 struct in6_ifreq ifr6;
1073 struct ifreq ifr;
1074 struct in6_rtmsg rt6;
1076 if (sock6_fd < 0) {
1077 errno = -sock6_fd;
1078 error("IPv6 socket creation failed: %m");
1079 return 0;
1081 memset(&ifr, 0, sizeof (ifr));
1082 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1083 if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
1084 error("sif6addr: ioctl(SIOCGIFINDEX): %m (%d)", errno);
1085 return 0;
1088 /* Local interface */
1089 memset(&ifr6, 0, sizeof(ifr6));
1090 IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
1091 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
1092 ifr6.ifr6_prefixlen = 10;
1094 if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) {
1095 error("sif6addr: ioctl(SIOCSIFADDR): %m (%d)", errno);
1096 return 0;
1099 /* Route to remote host */
1100 memset(&rt6, 0, sizeof(rt6));
1101 IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64);
1102 rt6.rtmsg_flags = RTF_UP;
1103 rt6.rtmsg_dst_len = 10;
1104 rt6.rtmsg_ifindex = ifr.ifr_ifindex;
1105 rt6.rtmsg_metric = 1;
1107 if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) {
1108 error("sif6addr: ioctl(SIOCADDRT): %m (%d)", errno);
1109 return 0;
1112 return 1;
1115 /********************************************************************
1117 * cif6addr - Remove IPv6 address from interface
1119 int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64)
1121 struct ifreq ifr;
1122 struct in6_ifreq ifr6;
1124 if (sock6_fd < 0) {
1125 errno = -sock6_fd;
1126 error("IPv6 socket creation failed: %m");
1127 return 0;
1129 memset(&ifr, 0, sizeof(ifr));
1130 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1131 if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) {
1132 error("cif6addr: ioctl(SIOCGIFINDEX): %m (%d)", errno);
1133 return 0;
1136 memset(&ifr6, 0, sizeof(ifr6));
1137 IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);
1138 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
1139 ifr6.ifr6_prefixlen = 10;
1141 if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) {
1142 if (errno != EADDRNOTAVAIL) {
1143 if (! ok_error (errno))
1144 error("cif6addr: ioctl(SIOCDIFADDR): %m (%d)", errno);
1146 else {
1147 warn("cif6addr: ioctl(SIOCDIFADDR): No such address");
1149 return (0);
1151 return 1;
1153 #endif /* INET6 */
1155 //===================================================================
1157 #if 1
1159 * /proc/net/route parsing stuff.
1162 #define ROUTE_MAX_COLS 12
1163 FILE *route_fd = (FILE *) 0;
1164 static char route_buffer[512];
1165 static int route_dev_col, route_dest_col, route_gw_col;
1166 static int route_flags_col, route_mask_col;
1167 static int route_num_cols;
1169 static int open_route_table (void);
1170 static void close_route_table (void);
1171 static int read_route_table (struct rtentry *rt);
1172 static char route_delims[] = " \t\n";
1174 /********************************************************************
1176 * close_route_table - close the interface to the route table
1178 // copy from pppd/sys-linux.c by tallest
1179 static void close_route_table (void)
1181 if (route_fd != (FILE *) 0) {
1182 fclose (route_fd);
1183 route_fd = (FILE *) 0;
1187 /********************************************************************
1189 * read_route_table - read the next entry from the route table
1191 // copy from pppd/sys-linux.c by tallest
1192 static int read_route_table(struct rtentry *rt)
1194 char *cols[ROUTE_MAX_COLS], *p;
1195 int col;
1197 memset (rt, '\0', sizeof (struct rtentry));
1199 if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
1200 return 0;
1202 p = route_buffer;
1203 for (col = 0; col < route_num_cols; ++col) {
1204 cols[col] = strtok(p, route_delims);
1205 if (cols[col] == NULL)
1206 return 0; /* didn't get enough columns */
1207 p = NULL;
1210 SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
1211 SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
1212 SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
1214 rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
1215 rt->rt_dev = cols[route_dev_col];
1217 return 1;
1220 /********************************************************************
1222 * open_route_table - open the interface to the route table
1224 // copy from pppd/sys-linux.c by tallest
1226 static int open_route_table (void)
1228 close_route_table();
1230 route_fd = fopen ("proc/net/route", "r");
1231 if (route_fd == NULL) {
1232 error("can't open routing table");
1233 return 0;
1236 route_dev_col = 0; /* default to usual columns */
1237 route_dest_col = 1;
1238 route_gw_col = 2;
1239 route_flags_col = 3;
1240 route_mask_col = 7;
1241 route_num_cols = 8;
1243 /* parse header line */
1244 if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
1245 char *p = route_buffer, *q;
1246 int col;
1247 for (col = 0; col < ROUTE_MAX_COLS; ++col) {
1248 int used = 1;
1249 if ((q = strtok(p, route_delims)) == 0)
1250 break;
1251 if (strcasecmp(q, "iface") == 0)
1252 route_dev_col = col;
1253 else if (strcasecmp(q, "destination") == 0)
1254 route_dest_col = col;
1255 else if (strcasecmp(q, "gateway") == 0)
1256 route_gw_col = col;
1257 else if (strcasecmp(q, "flags") == 0)
1258 route_mask_col = col;
1259 else
1260 used = 0;
1261 if (used && col >= route_num_cols)
1262 route_num_cols = col + 1;
1263 p = NULL;
1267 return 1;
1270 /********************************************************************
1272 * defaultroute_exists - determine if there is a default route
1274 // copy from pppd/sys-linux.c by tallest
1275 static int defaultroute_exists (struct rtentry *rt)
1277 int result = 0;
1279 if (!open_route_table())
1280 return 0;
1282 while (read_route_table(rt) != 0) {
1283 if ((rt->rt_flags & RTF_UP) == 0)
1284 continue;
1286 if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
1287 continue;
1288 if (SIN_ADDR(rt->rt_dst) == 0L) {
1289 result = 1;
1290 break;
1294 close_route_table();
1295 return result;
1298 /********************************************************************
1300 * sifdefaultroute - assign a default route through the address given.
1302 // copy from pppd/sys_linux.c by tallest
1303 int
1304 sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
1306 struct rtentry rt;
1308 if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
1309 u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway);
1311 if (old_gateway != gateway)
1312 error("not replacing existing default route to %s [%I]",
1313 rt.rt_dev, old_gateway);
1314 return 0;
1317 memset (&rt, '\0', sizeof (rt));
1318 SET_SA_FAMILY (rt.rt_dst, AF_INET);
1319 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1321 if (kernel_version > KVERSION(2,1,0)) {
1322 SET_SA_FAMILY (rt.rt_genmask, AF_INET);
1323 SIN_ADDR(rt.rt_genmask) = 0L;
1326 SIN_ADDR(rt.rt_gateway) = gateway;
1328 rt.rt_flags = RTF_UP | RTF_GATEWAY;
1329 if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
1330 if ( ! ok_error ( errno ))
1331 error("default route ioctl(SIOCADDRT): %m(%d)", errno);
1332 return 0;
1335 //default_route_gateway = gateway;
1336 return 1;
1338 #endif
1339 //===================================================================
1342 /********************************************************************
1344 * open_loopback - open the device we use for getting packets
1345 * in demand mode. Under Linux, we use a pty master/slave pair.
1348 open_ppp_loopback(void)
1350 int flags;
1352 looped = 1;
1353 if (new_style_driver) {
1354 /* allocate ourselves a ppp unit */
1355 if (make_ppp_unit() < 0)
1356 die(1);
1357 set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC);
1358 set_kdebugflag(kdebugflag);
1359 ppp_fd = -1;
1360 return ppp_dev_fd;
1363 if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
1364 fatal("No free pty for loopback");
1365 SYSDEBUG(("using %s for loopback", loop_name));
1367 set_ppp_fd(slave_fd);
1369 flags = fcntl(master_fd, F_GETFL);
1370 if (flags == -1 ||
1371 fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
1372 warn("couldn't set master loopback to nonblock: %m(%d)", errno);
1374 flags = fcntl(ppp_fd, F_GETFL);
1375 if (flags == -1 ||
1376 fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
1377 warn("couldn't set slave loopback to nonblock: %m(%d)", errno);
1379 if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
1380 fatal("ioctl(TIOCSETD): %m(%d)", errno);
1382 * Find out which interface we were given.
1384 if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
1385 fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
1387 * Enable debug in the driver if requested.
1389 set_kdebugflag (kdebugflag);
1391 return master_fd;
1394 /********************************************************************
1396 * restore_loop - reattach the ppp unit to the loopback.
1398 * The kernel ppp driver automatically reattaches the ppp unit to
1399 * the loopback if the serial port is set to a line discipline other
1400 * than ppp, or if it detects a modem hangup. The former will happen
1401 * in disestablish_ppp if the latter hasn't already happened, so we
1402 * shouldn't need to do anything.
1404 * Just to be sure, set the real serial port to the normal discipline.
1407 void
1408 restore_loop(void)
1410 looped = 1;
1411 if (new_style_driver) {
1412 set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_LOOP_TRAFFIC);
1413 return;
1415 if (ppp_fd != slave_fd) {
1416 (void) ioctl(ppp_fd, TIOCSETD, &tty_disc);
1417 set_ppp_fd(slave_fd);
1421 /********************************************************************
1423 * sifnpmode - Set the mode for handling packets for a given NP.
1427 sifnpmode(u, proto, mode)
1428 int u;
1429 int proto;
1430 enum NPmode mode;
1432 struct npioctl npi;
1434 npi.protocol = proto;
1435 npi.mode = mode;
1436 if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
1437 if (! ok_error (errno))
1438 error("ioctl(PPPIOCSNPMODE, %d, %d): %m (%d)",
1439 proto, mode, errno);
1440 return 0;
1442 return 1;
1446 * Use the hostname as part of the random number seed.
1449 get_host_seed()
1451 int h;
1452 char *p = hostname;
1454 h = 407;
1455 for (p = hostname; *p != 0; ++p)
1456 h = h * 37 + *p;
1457 return h;