X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fsys-linux.c;h=676839bf359ad52d6b2d8715fa60cdfa0cb27dc8;hb=df7501b15fe4ed7f6674acde69dd8f51c5e16b82;hp=1e52e3bddf8ab4bd53fb26855c42c0f3c8d20c62;hpb=2c872bc67b83b91ba6390f6e5e72be08e09811a1;p=ppp.git diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index 1e52e3b..676839b 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -149,6 +149,7 @@ static char proxy_arp_dev[16]; /* Device for proxy arp entry */ static u_int32_t our_old_addr; /* for detecting address changes */ static int dynaddr_set; /* 1 if ip_dynaddr set */ static int looped; /* 1 if using loop */ +static int link_mtu; /* mtu for the link (not bundle) */ static struct utsname utsname; /* for the kernel version */ static int kernel_version; @@ -176,6 +177,7 @@ static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr, static void decode_version (char *buf, int *version, int *mod, int *patch); static int set_kdebugflag(int level); static int ppp_registered(void); +static int make_ppp_unit(void); extern u_char inpacket_buf[]; /* borrowed from main.c */ @@ -413,22 +415,14 @@ int establish_ppp (int tty_fd) warn("Couldn't set /dev/ppp (channel) to nonblock: %m"); set_ppp_fd(fd); - ifunit = -1; + if (!looped) + ifunit = -1; if (!looped && !multilink) { /* * Create a new PPP unit. */ - ifunit = req_unit; - x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); - if (x < 0 && req_unit >= 0 && errno == EEXIST) { - warn("Couldn't allocate PPP unit %d as it is already in use"); - ifunit = -1; - x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); - } - if (x < 0) { - error("Couldn't create new ppp unit: %m"); + if (make_ppp_unit() < 0) goto err_close; - } } if (looped) @@ -529,7 +523,7 @@ void disestablish_ppp(int tty_fd) if (new_style_driver) { close(ppp_fd); ppp_fd = -1; - if (!looped && ioctl(ppp_dev_fd, PPPIOCDETACH) < 0) + if (!looped && ifunit >= 0 && ioctl(ppp_dev_fd, PPPIOCDETACH) < 0) error("Couldn't release PPP unit: %m"); if (!multilink) remove_fd(ppp_dev_fd); @@ -537,30 +531,101 @@ void disestablish_ppp(int tty_fd) } /* - * bundle_attach - attach our link to a given PPP unit. + * make_ppp_unit - make a new ppp unit for ppp_dev_fd. + * Assumes new_style_driver. */ -int bundle_attach(int ifnum) +static int make_ppp_unit() { - int mrru = 1500; + int x; - if (!new_style_driver) - return -1; + ifunit = req_unit; + x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); + if (x < 0 && req_unit >= 0 && errno == EEXIST) { + warn("Couldn't allocate PPP unit %d as it is already in use"); + ifunit = -1; + x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); + } + if (x < 0) + error("Couldn't create new ppp unit: %m"); + return x; +} - if (ioctl(ppp_dev_fd, PPPIOCATTACH, &ifnum) < 0) { - error("Couldn't attach to interface unit %d: %m\n", ifnum); - return -1; - } - set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_MULTILINK); - if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0) - error("Couldn't set interface MRRU: %m"); +/* + * cfg_bundle - configure the existing bundle. + * Used in demand mode. + */ +void cfg_bundle(int mrru, int mtru, int rssn, int tssn) +{ + int flags; + struct ifreq ifr; - if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0) { - error("Couldn't connect to interface unit %d: %m", ifnum); - return -1; - } + if (!new_style_driver) + return; + + /* set the mrru, mtu and flags */ + if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0) + error("Couldn't set MRRU: %m"); + flags = get_flags(ppp_dev_fd); + flags &= ~(SC_MP_SHORTSEQ | SC_MP_XSHORTSEQ); + flags |= (rssn? SC_MP_SHORTSEQ: 0) | (tssn? SC_MP_XSHORTSEQ: 0); + + if (mtru > 0 && mtru != link_mtu) { + memset(&ifr, 0, sizeof(ifr)); + slprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "ppp%d", ifunit); + ifr.ifr_mtu = mtru; + if (ioctl(sock_fd, SIOCSIFMTU, &ifr) < 0) + error("Couldn't set interface MTU: %m"); + flags |= SC_MULTILINK; + } - dbglog("bundle_attach succeeded"); - return 0; + set_flags(ppp_dev_fd, flags); + + /* connect up the channel */ + if (ioctl(ppp_fd, PPPIOCCONNECT, &ifunit) < 0) + fatal("Couldn't attach to PPP unit %d: %m", ifunit); + add_fd(ppp_dev_fd); +} + +/* + * make_new_bundle - create a new PPP unit (i.e. a bundle) + * and connect our channel to it. This should only get called + * if `multilink' was set at the time establish_ppp was called. + * In demand mode this uses our existing bundle instead of making + * a new one. + */ +void make_new_bundle(int mrru, int mtru, int rssn, int tssn) +{ + if (!new_style_driver) + return; + + /* make us a ppp unit */ + if (make_ppp_unit() < 0) + die(1); + + /* set the mrru, mtu and flags */ + cfg_bundle(mrru, mtru, rssn, tssn); +} + +/* + * bundle_attach - attach our link to a given PPP unit. + * We assume the unit is controlled by another pppd. + */ +int bundle_attach(int ifnum) +{ + if (!new_style_driver) + return -1; + + if (ioctl(ppp_dev_fd, PPPIOCATTACH, &ifnum) < 0) { + if (errno == ENXIO) + return 0; /* doesn't still exist */ + fatal("Couldn't attach to interface unit %d: %m\n", ifnum); + } + if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0) + fatal("Couldn't connect to interface unit %d: %m", ifnum); + set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_MULTILINK); + + ifunit = ifnum; + return 1; } /******************************************************************** @@ -855,7 +920,7 @@ void output (int unit, unsigned char *p, int len) p += 2; len -= 2; proto = (p[0] << 8) + p[1]; - if (!multilink && proto != PPP_LCP) + if (ifunit >= 0 && !(proto >= 0xc000 || proto == PPP_CCPFRAG)) fd = ppp_dev_fd; } if (write(fd, p, len) < 0) { @@ -926,7 +991,7 @@ int read_packet (unsigned char *buf) if (nr < 0 && errno != EWOULDBLOCK && errno != EIO) error("read: %m"); } - if (nr < 0 && new_style_driver && !multilink) { + if (nr < 0 && new_style_driver && ifunit >= 0) { /* N.B. we read ppp_fd first since LCP packets come in there. */ nr = read(ppp_dev_fd, buf, len); if (nr < 0 && errno != EWOULDBLOCK && errno != EIO) @@ -988,7 +1053,8 @@ void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp) if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0) fatal("ioctl(SIOCSIFMTU): %m(%d)", errno); - + link_mtu = mtu; + if (!still_ppp()) return; SYSDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap)); @@ -1600,6 +1666,38 @@ static int get_ether_addr (u_int32_t ipaddr, return 1; } +/* + * get_if_hwaddr - get the hardware address for the specified + * network interface device. + */ +int +get_if_hwaddr(u_char *addr, char *name) +{ + struct ifreq ifreq; + int ret, sock_fd; + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) + return 0; + memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr)); + strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); + ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq); + close(sock_fd); + if (ret >= 0) + memcpy(addr, ifreq.ifr_hwaddr.sa_data, 6); + return ret; +} + +/* + * get_first_ethernet - return the name of the first ethernet-style + * interface on this system. + */ +char * +get_first_ethernet() +{ + return "eth0"; +} + /******************************************************************** * * Return user specified netmask, modified by any mask we might determine @@ -1763,35 +1861,34 @@ int ppp_available(void) sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch); kernel_version = KVERSION(osmaj, osmin, ospatch); - if (kernel_version >= KVERSION(2,3,13)) { - fd = open("/dev/ppp", O_RDWR); + fd = open("/dev/ppp", O_RDWR); #if 0 - if (fd < 0 && errno == ENOENT) { - /* try making it and see if that helps. */ - if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR, - makedev(108, 0)) >= 0) { - fd = open("/dev/ppp", O_RDWR); - if (fd >= 0) - info("Created /dev/ppp device node"); - else - unlink("/dev/ppp"); /* didn't work, undo the mknod */ - } else if (errno == EEXIST) { - fd = open("/dev/ppp", O_RDWR); - } + if (fd < 0 && errno == ENOENT) { + /* try making it and see if that helps. */ + if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR, + makedev(108, 0)) >= 0) { + fd = open("/dev/ppp", O_RDWR); + if (fd >= 0) + info("Created /dev/ppp device node"); + else + unlink("/dev/ppp"); /* didn't work, undo the mknod */ + } else if (errno == EEXIST) { + fd = open("/dev/ppp", O_RDWR); } + } #endif /* 0 */ - if (fd >= 0) { - new_style_driver = 1; - - /* XXX should get from driver */ - driver_version = 2; - driver_modification = 4; - driver_patch = 0; - close(fd); - return 1; - } - return 0; + if (fd >= 0) { + new_style_driver = 1; + + /* XXX should get from driver */ + driver_version = 2; + driver_modification = 4; + driver_patch = 0; + close(fd); + return 1; } + if (kernel_version >= KVERSION(2,3,13)) + return 0; /* * Open a socket for doing the ioctl operations. @@ -2355,20 +2452,13 @@ get_pty(master_fdp, slave_fdp, slave_name, uid) int open_ppp_loopback(void) { - int flags, x; + int flags; looped = 1; if (new_style_driver) { /* allocate ourselves a ppp unit */ - ifunit = req_unit; - x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); - if (x < 0 && req_unit >= 0 && errno == EEXIST) { - warn("Couldn't allocate PPP unit %d as it is already in use"); - ifunit = -1; - x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit); - } - if (x < 0) - fatal("Couldn't create PPP unit: %m"); + if (make_ppp_unit() < 0) + die(1); set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC); set_kdebugflag(kdebugflag); ppp_fd = -1; @@ -2595,8 +2685,8 @@ sys_check_options(void) return 0; } if (multilink && !new_style_driver) { - option_error("multilink is not supported by the kernel driver"); - return 0; + warn("Warning: multilink is not supported by the kernel driver"); + multilink = 0; } return 1; }