X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fsys-linux.c;h=29aa77fef300b9d3ef69334848723bb359825452;hp=c86d668d8ddda4a6e07e1909019b0cdd806771ca;hb=a25ab4af5d8ea4f1760b5db5f5ee5b65bbfcd53b;hpb=9164ea8da8dd803c9c8a34bb2bab7742669f65de diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index c86d668..29aa77f 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,8 @@ #include #include #include +#include +#include /* This is in netdevice.h. However, this compile will fail miserably if you attempt to include netdevice.h because it has so many references @@ -47,31 +50,48 @@ #define MAX_ADDR_LEN 7 #endif -#include +#if __GLIBC__ >= 2 +#include /* glibc 2 conflicts with linux/types.h */ #include -#include #include -#include #include +#include +#else +#include +#include +#include +#include #include +#endif #include +#include + +#include +#include #include "pppd.h" #include "fsm.h" #include "ipcp.h" - -#ifndef RTF_DEFAULT /* Normally in from */ -#define RTF_DEFAULT 0 -#endif +#include "patchlevel.h" #ifdef IPX_CHANGE #include "ipxcp.h" +#if __GLIBC__ >= 2 && \ + !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0) +#include +#else +#include #endif +#endif /* IPX_CHANGE */ #ifdef LOCKLIB #include #endif +#ifndef RTF_DEFAULT /* Normally in from */ +#define RTF_DEFAULT 0 +#endif + #define ok_error(num) ((num)==EIO) static int tty_disc = N_TTY; /* The TTY discipline */ @@ -86,6 +106,7 @@ static int has_proxy_arp = 0; static int driver_version = 0; static int driver_modification = 0; static int driver_patch = 0; +static int driver_is_old = 0; static int restore_term = 0; /* 1 => we've munged the terminal */ static struct termios inittermios; /* Initial TTY termios */ @@ -98,6 +119,10 @@ static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */ static char *lock_file; +static struct utsname utsname; /* for the kernel version */ +static int kernel_version; +#define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p)) + #define MAX_IFS 100 #define FLAGS_GOOD (IFF_UP | IFF_BROADCAST) @@ -134,22 +159,27 @@ extern u_char inpacket_buf[]; /* borrowed from main.c */ */ extern int hungup; -#define still_ppp() (hungup == 0) #ifndef LOCK_PREFIX #define LOCK_PREFIX "/var/lock/LCK.." #endif -/******************************************************************** - * - * Functions to read and set the flags value in the device driver - */ - static void set_ppp_fd (int new_fd) - { - SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", ppp_fd)); - ppp_fd = new_fd; - } +{ + SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", ppp_fd)); + ppp_fd = new_fd; +} + +static int still_ppp(void) +{ + if (!hungup || ppp_fd == slave_fd) + return 1; + if (slave_fd >= 0) { + set_ppp_fd(slave_fd); + return 1; + } + return 0; +} /******************************************************************** * @@ -200,6 +230,8 @@ static void set_flags (int flags) void sys_init(void) { + int osmaj, osmin, ospatch; + openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); setlogmask(LOG_UPTO(LOG_INFO)); if (debug) @@ -217,6 +249,11 @@ void sys_init(void) die(1); } } + + uname(&utsname); + osmaj = osmin = ospatch = 0; + sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch); + kernel_version = KVERSION(osmaj, osmin, ospatch); } /******************************************************************** @@ -228,7 +265,6 @@ void sys_init(void) void sys_cleanup(void) { - struct ifreq ifr; /* * Take down the device */ @@ -401,9 +437,6 @@ void establish_ppp (int tty_fd) void disestablish_ppp(int tty_fd) { - int x; - char *s; - /* * Attempt to restore the previous tty settings */ @@ -564,6 +597,12 @@ struct speed { #endif #ifdef EXTB { 38400, EXTB }, +#endif +#ifdef B230400 + { 230400, B230400 }, +#endif +#ifdef B460800 + { 460800, B460800 }, #endif { 0, 0 } }; @@ -622,7 +661,7 @@ static int baud_rate_of (int speed) void set_up_tty (int tty_fd, int local) { - int speed, x; + int speed; struct termios tios; if (tcgetattr(tty_fd, &tios) < 0) @@ -754,7 +793,7 @@ void output (int unit, unsigned char *p, int len) { if (debug) { - log_packet(p, len, "sent "); + log_packet(p, len, "sent ", LOG_DEBUG); } if (write(ppp_fd, p, len) < 0) @@ -1106,7 +1145,10 @@ static int path_to_procfs (void) } fclose (fp); } - return 0; + + /* Default the mount location of /proc */ + strncpy (route_buffer, "/proc", sizeof (route_buffer)-10); + return 1; } /******************************************************************** @@ -1173,7 +1215,7 @@ static int open_route_table (void) static int read_route_table (struct rtentry *rt) { static char delims[] = " \t\n"; - char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr; + char *dev_ptr, *dst_ptr, *gw_ptr, *flag_ptr; memset (rt, '\0', sizeof (struct rtentry)); @@ -1258,13 +1300,13 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) if (defaultroute_exists(&rt)) { - u_int32_t old_gateway = ((struct sockaddr_in *) (&rt.rt_gateway))-> - sin_addr.s_addr; + struct in_addr old_gateway = + ((struct sockaddr_in *) (&rt.rt_gateway))-> sin_addr; - if (old_gateway != gateway) + if (old_gateway.s_addr != gateway) { syslog (LOG_ERR, - "ppp not replacing existing default route to %s[%s]", + "not replacing existing default route to %s [%s]", rt.rt_dev, inet_ntoa (old_gateway)); } @@ -1275,10 +1317,10 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) SET_SA_FAMILY (rt.rt_dst, AF_INET); SET_SA_FAMILY (rt.rt_gateway, AF_INET); -#if LINUX_VERSION_CODE > 0x020100 - SET_SA_FAMILY (rt.rt_genmask, AF_INET); - ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L; -#endif + if (kernel_version > KVERSION(2,1,0)) { + SET_SA_FAMILY (rt.rt_genmask, AF_INET); + ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L; + } ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway; @@ -1311,10 +1353,10 @@ int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) SET_SA_FAMILY (rt.rt_dst, AF_INET); SET_SA_FAMILY (rt.rt_gateway, AF_INET); -#if LINUX_VERSION_CODE > 0x020100 - SET_SA_FAMILY (rt.rt_genmask, AF_INET); - ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L; -#endif + if (kernel_version > KVERSION(2,1,0)) { + SET_SA_FAMILY (rt.rt_genmask, AF_INET); + ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L; + } ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway; @@ -1415,8 +1457,7 @@ static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr, char *name) { - struct ifreq *ifr, *ifend, *ifp; - int i; + struct ifreq *ifr, *ifend; u_int32_t ina, mask; struct ifreq ifreq; struct ifconf ifc; @@ -1640,7 +1681,7 @@ static void decode_version (char *buf, int *version, /******************************************************************** * - * Procedure to determine if the PPP line dicipline is registered. + * Procedure to determine if the PPP line discipline is registered. */ int @@ -1703,7 +1744,7 @@ ppp_registered(void) */ int ppp_available(void) - { +{ int s, ok; struct ifreq ifr; int size; @@ -1714,9 +1755,9 @@ int ppp_available(void) */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) - { + { return 0; - } + } strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; @@ -1726,91 +1767,92 @@ int ppp_available(void) * flags for the device again. */ if (!ok) - { + { if (ppp_registered()) - { + { strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; - } - } + } + } /* * Ensure that the hardware address is for PPP and not something else */ if (ok) - { + { ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0; - } + } if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP)) - { + { ok = 0; - } + } if (!ok) - { + { no_ppp_msg = - "This system lacks kernel support for PPP. To include PPP support\n" - "in the kernel, please follow the steps detailed in the " - "README.linux\nfile in the ppp-2.3 distribution.\n"; - } + "This system lacks kernel support for PPP. This could be because\n" + "the PPP kernel module is not loaded, or because the kernel is\n" + "not configured for PPP. See the README.linux file in the\n" + "ppp-2.3.5 distribution.\n"; + } /* * This is the PPP device. Validate the version of the driver at this * point to ensure that this program will work with the driver. */ else - { + { char abBuffer [1024]; ifr.ifr_data = abBuffer; size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr); - ok = size >= 0; + if (size < 0) { + syslog(LOG_ERR, "Couldn't read driver version: %m"); + ok = 0; + no_ppp_msg = "Sorry, couldn't verify kernel driver version\n"; - if (ok) - { - decode_version (abBuffer, - &driver_version, - &driver_modification, - &driver_patch); - } - - if (!ok) - { - driver_version = - driver_modification = - driver_patch = 0; - } + } else { + decode_version(abBuffer, + &driver_version, + &driver_modification, + &driver_patch); /* * Validate the version of the driver against the version that we used. */ - decode_version (PPP_VERSION, - &my_version, - &my_modification, - &my_patch); + decode_version(VERSION, + &my_version, + &my_modification, + &my_patch); - /* The version numbers must match */ - if (driver_version != my_version) - { - ok = 0; - } + /* The version numbers must match */ + if (driver_version != my_version) + { + ok = 0; + } - /* The modification levels must be legal */ - if (driver_modification < my_modification) - { - ok = 0; - } - - close (s); - if (!ok) - { - sprintf (route_buffer, - "Sorry - PPP driver version %d.%d.%d is out of date\n", - driver_version, driver_modification, driver_patch); - - no_ppp_msg = route_buffer; - } - } + /* The modification levels must be legal */ + if (driver_modification < my_modification) + { + if (driver_modification >= 2) { + /* we can cope with 2.2.0 and above */ + driver_is_old = 1; + } else { + ok = 0; + } + } + + close (s); + if (!ok) + { + sprintf (route_buffer, + "Sorry - PPP driver version %d.%d.%d is out of date\n", + driver_version, driver_modification, driver_patch); + + no_ppp_msg = route_buffer; + } + } + } return ok; - } +} /******************************************************************** * @@ -2068,7 +2110,7 @@ int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid) { if (! ok_error (errno)) { - syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m(%d)", errno); + syslog (LOG_ERR, "ioctl(PPPIOCSMAXCID): %m(%d)", errno); } vjcomp = 0; } @@ -2200,8 +2242,11 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr, return (0); } /* - * Set the netmask + * Set the netmask. + * For recent kernels, force the netmask to 255.255.255.255. */ + if (kernel_version >= KVERSION(2,1,16)) + net_mask = ~0L; if (net_mask != 0) { ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask; @@ -2217,29 +2262,29 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr, /* * Add the device route */ -#if LINUX_VERSION_CODE < 0x020100+16 /* 2.1.16 */ - SET_SA_FAMILY (rt.rt_dst, AF_INET); - SET_SA_FAMILY (rt.rt_gateway, AF_INET); - rt.rt_dev = ifname; - - ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0L; - ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr; - rt.rt_flags = RTF_UP | RTF_HOST; + if (kernel_version < KVERSION(2,1,16)) { + SET_SA_FAMILY (rt.rt_dst, AF_INET); + SET_SA_FAMILY (rt.rt_gateway, AF_INET); + rt.rt_dev = ifname; -#if LINUX_VERSION_CODE > 0x020100 - SET_SA_FAMILY (rt.rt_genmask, AF_INET); - ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L; -#endif + ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0L; + ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr; + rt.rt_flags = RTF_UP | RTF_HOST; - if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) - { - if (! ok_error (errno)) - { - syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m(%d)", errno); - } - return (0); + if (kernel_version > KVERSION(2,1,0)) { + SET_SA_FAMILY (rt.rt_genmask, AF_INET); + ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L; } -#endif + + if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) + { + if (! ok_error (errno)) + { + syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m(%d)", errno); + } + return (0); + } + } return 1; } @@ -2251,35 +2296,36 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr, int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr) { -#if LINUX_VERSION_CODE < 0x020100+16 /* 2.1.16 */ struct rtentry rt; + + if (kernel_version < KVERSION(2,1,16)) { /* * Delete the route through the device */ - memset (&rt, '\0', sizeof (rt)); - - SET_SA_FAMILY (rt.rt_dst, AF_INET); - SET_SA_FAMILY (rt.rt_gateway, AF_INET); - rt.rt_dev = ifname; + memset (&rt, '\0', sizeof (rt)); - ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0; - ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr; - rt.rt_flags = RTF_UP | RTF_HOST; + SET_SA_FAMILY (rt.rt_dst, AF_INET); + SET_SA_FAMILY (rt.rt_gateway, AF_INET); + rt.rt_dev = ifname; -#if LINUX_VERSION_CODE > 0x020100 - SET_SA_FAMILY (rt.rt_genmask, AF_INET); - ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L; -#endif + ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0; + ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr; + rt.rt_flags = RTF_UP | RTF_HOST; - if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) - { - if (still_ppp() && ! ok_error (errno)) - { - syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m(%d)", errno); - } - return (0); + if (kernel_version > KVERSION(2,1,0)) { + SET_SA_FAMILY (rt.rt_genmask, AF_INET); + ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L; } -#endif + + if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) + { + if (still_ppp() && ! ok_error (errno)) + { + syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m(%d)", errno); + } + return (0); + } + } return 1; } @@ -2292,15 +2338,27 @@ int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr) void open_ppp_loopback(void) { - int flags; + int flags, i; struct termios tios; - if (openpty (&master_fd, &slave_fd, loop_name, NULL, NULL) < 0) - { - syslog(LOG_ERR, "No free pty for loopback"); - die(1); - } + master_fd = -1; + for (i = 0; i < 64; ++i) { + sprintf(loop_name, "/dev/pty%c%x", 'p' + i / 16, i % 16); + master_fd = open(loop_name, O_RDWR | O_NOCTTY, 0); + if (master_fd >= 0) + break; + } + if (master_fd < 0) { + syslog(LOG_ERR, "No free pty for loopback"); + die(1); + } SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name)); + loop_name[5] = 't'; + slave_fd = open(loop_name, O_RDWR | O_NOCTTY, 0); + if (slave_fd < 0) { + syslog(LOG_ERR, "Couldn't open %s for loopback: %m", loop_name); + die(1); + } set_ppp_fd(slave_fd); @@ -2402,8 +2460,6 @@ sifnpmode(u, proto, mode) } -#include - /******************************************************************** * * sipxfaddr - Config the interface IPX networknumber @@ -2415,7 +2471,6 @@ int sipxfaddr (int unit, unsigned long int network, unsigned char * node ) #ifdef IPX_CHANGE int skfd; - struct sockaddr_ipx ipx_addr; struct ifreq ifr; struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; @@ -2478,7 +2533,6 @@ int cipxfaddr (int unit) #ifdef IPX_CHANGE int skfd; - struct sockaddr_ipx ipx_addr; struct ifreq ifr; struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; @@ -2517,6 +2571,45 @@ int cipxfaddr (int unit) return result; } +/* + * daemon - Detach us from controlling terminal session. + */ +int +daemon(nochdir, noclose) + int nochdir, noclose; +{ + int pid; + + if ((pid = fork()) < 0) + return -1; + if (pid != 0) + exit(0); /* parent dies */ + setsid(); + if (!nochdir) + chdir("/"); + if (!noclose) { + fclose(stdin); /* don't need stdin, stdout, stderr */ + fclose(stdout); + fclose(stderr); + } + return 0; +} + +/* + * Use the hostname as part of the random number seed. + */ +int +get_host_seed() +{ + int h; + char *p = hostname; + + h = 407; + for (p = hostname; *p != 0; ++p) + h = h * 37 + *p; + return h; +} + /******************************************************************** * * sys_check_options - check the options that the user specified @@ -2547,4 +2640,10 @@ sys_check_options(void) break; } #endif + if (demand && driver_is_old) { + option_error("demand dialling is not supported by kernel driver version " + "%d.%d.%d", driver_version, driver_modification, + driver_patch); + demand = 0; + } }