⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys-linux.c

📁 自己精简过的PPPD代码。在嵌入中应用可以更好的发挥。比原先的小了很多
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************** * * sifdefaultroute - assign a default route through the address given. */int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway){    struct rtentry rt;    if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {	if (rt.rt_flags & RTF_GATEWAY)	    error("not replacing existing default route via %I",		  SIN_ADDR(rt.rt_gateway));	else	    error("not replacing existing default route through %s",		  rt.rt_dev);	return 0;    }    memset (&rt, 0, sizeof (rt));    SET_SA_FAMILY (rt.rt_dst, AF_INET);    rt.rt_dev = ifname;    if (kernel_version > KVERSION(2,1,0)) {	SET_SA_FAMILY (rt.rt_genmask, AF_INET);	SIN_ADDR(rt.rt_genmask) = 0L;    }    rt.rt_flags = RTF_UP;    if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {	if ( ! ok_error ( errno ))	    error("default route ioctl(SIOCADDRT): %m");	return 0;    }    have_default_route = 1;    return 1;}/******************************************************************** * * cifdefaultroute - delete a default route through the address given. */int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway){    struct rtentry rt;    have_default_route = 0;    memset (&rt, '\0', sizeof (rt));    SET_SA_FAMILY (rt.rt_dst,     AF_INET);    SET_SA_FAMILY (rt.rt_gateway, AF_INET);    if (kernel_version > KVERSION(2,1,0)) {	SET_SA_FAMILY (rt.rt_genmask, AF_INET);	SIN_ADDR(rt.rt_genmask) = 0L;    }    rt.rt_flags = RTF_UP;    if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {	if (still_ppp()) {	    if ( ! ok_error ( errno ))		error("default route ioctl(SIOCDELRT): %m");	    return 0;	}    }    return 1;}/******************************************************************** * * sifproxyarp - Make a proxy ARP entry for the peer. */int sifproxyarp (int unit, u_int32_t his_adr){    struct arpreq arpreq;    char *forw_path;    if (has_proxy_arp == 0) {	memset (&arpreq, '\0', sizeof(arpreq));	SET_SA_FAMILY(arpreq.arp_pa, AF_INET);	SIN_ADDR(arpreq.arp_pa) = his_adr;	arpreq.arp_flags = ATF_PERM | ATF_PUBL;/* * Get the hardware address of an interface on the same subnet * as our local address. */	if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,			    sizeof(proxy_arp_dev))) {	    error("Cannot determine ethernet address for proxy ARP");	    return 0;	}	strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));	if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {	    if ( ! ok_error ( errno ))		error("ioctl(SIOCSARP): %m");	    return 0;	}	proxy_arp_addr = his_adr;	has_proxy_arp = 1;	if (tune_kernel) {	    forw_path = path_to_procfs("/sys/net/ipv4/ip_forward");	    if (forw_path != 0) {		int fd = open(forw_path, O_WRONLY);		if (fd >= 0) {		    if (write(fd, "1", 1) != 1)			error("Couldn't enable IP forwarding: %m");		    close(fd);		}	    }	}    }    return 1;}/******************************************************************** * * cifproxyarp - Delete the proxy ARP entry for the peer. */int cifproxyarp (int unit, u_int32_t his_adr){    struct arpreq arpreq;    if (has_proxy_arp) {	has_proxy_arp = 0;	memset (&arpreq, '\0', sizeof(arpreq));	SET_SA_FAMILY(arpreq.arp_pa, AF_INET);	SIN_ADDR(arpreq.arp_pa) = his_adr;	arpreq.arp_flags = ATF_PERM | ATF_PUBL;	strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));	if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {	    if ( ! ok_error ( errno ))		warn("ioctl(SIOCDARP): %m");	    return 0;	}    }    return 1;}/******************************************************************** * * get_ether_addr - get the hardware address of an interface on the * the same subnet as ipaddr. */static int get_ether_addr (u_int32_t ipaddr,			   struct sockaddr *hwaddr,			   char *name, int namelen){    struct ifreq *ifr, *ifend;    u_int32_t ina, mask;    char *aliasp;    struct ifreq ifreq, bestifreq;    struct ifconf ifc;    struct ifreq ifs[MAX_IFS];    u_int32_t bestmask=0;    int found_interface = 0;    ifc.ifc_len = sizeof(ifs);    ifc.ifc_req = ifs;    if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {	if ( ! ok_error ( errno ))	    error("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);	return 0;    }/* * Scan through looking for an interface with an Internet * address on the same subnet as `ipaddr'. */    ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {	if (ifr->ifr_addr.sa_family == AF_INET) {	    ina = SIN_ADDR(ifr->ifr_addr);	    strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));/* * Check that the interface is up, and not point-to-point * nor loopback. */	    if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)		continue;	    if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)		continue;/* * Get its netmask and check that it's on the right subnet. */	    if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)		continue;	    mask = SIN_ADDR(ifreq.ifr_addr);	    if (((ipaddr ^ ina) & mask) != 0)		continue; /* no match */	    /* matched */	    if (mask >= bestmask) {		/* Compare using >= instead of > -- it is possible for		   an interface to have a netmask of 0.0.0.0 */		found_interface = 1;		bestifreq = ifreq;		bestmask = mask;	    }	}    }    if (!found_interface) return 0;    strlcpy(name, bestifreq.ifr_name, namelen);    /* trim off the :1 in eth0:1 */    aliasp = strchr(name, ':');    if (aliasp != 0)	*aliasp = 0;    info("found interface %s for proxy arp", name);/* * Now get the hardware address. */    memset (&bestifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));    if (ioctl (sock_fd, SIOCGIFHWADDR, &bestifreq) < 0) {	error("SIOCGIFHWADDR(%s): %m", bestifreq.ifr_name);	return 0;    }    memcpy (hwaddr,	    &bestifreq.ifr_hwaddr,	    sizeof (struct sockaddr));    return 1;}/* * get_if_hwaddr - get the hardware address for the specified * network interface device. */intget_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 * for address `addr' (in network byte order). * Here we scan through the system's list of interfaces, looking for * any non-point-to-point interfaces which might appear to be on the same * network as `addr'.  If we find any, we OR in their netmask to the * user-specified netmask. */u_int32_t GetMask (u_int32_t addr){    u_int32_t mask, nmask, ina;    struct ifreq *ifr, *ifend, ifreq;    struct ifconf ifc;    struct ifreq ifs[MAX_IFS];    addr = ntohl(addr);    if (IN_CLASSA(addr))	/* determine network mask for address class */	nmask = IN_CLASSA_NET;    else if (IN_CLASSB(addr))	    nmask = IN_CLASSB_NET;    else	    nmask = IN_CLASSC_NET;    /* class D nets are disallowed by bad_ip_adrs */    mask = netmask | htonl(nmask);/* * Scan through the system's network interfaces. */    ifc.ifc_len = sizeof(ifs);    ifc.ifc_req = ifs;    if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {	if ( ! ok_error ( errno ))	    warn("ioctl(SIOCGIFCONF): %m (line %d)", __LINE__);	return mask;    }    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {/* * Check the interface's internet address. */	if (ifr->ifr_addr.sa_family != AF_INET)	    continue;	ina = SIN_ADDR(ifr->ifr_addr);	if (((ntohl(ina) ^ addr) & nmask) != 0)	    continue;/* * Check that the interface is up, and not point-to-point nor loopback. */	strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)	    continue;	if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)	    continue;/* * Get its netmask and OR it into our mask. */	if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)	    continue;	mask |= SIN_ADDR(ifreq.ifr_addr);	break;    }    return mask;}/******************************************************************** * * Internal routine to decode the version.modification.patch level */static void decode_version (char *buf, int *version,			    int *modification, int *patch){    char *endp;    *version      = (int) strtoul (buf, &endp, 10);    *modification = 0;    *patch        = 0;    if (endp != buf && *endp == '.') {	buf = endp + 1;	*modification = (int) strtoul (buf, &endp, 10);	if (endp != buf && *endp == '.') {	    buf = endp + 1;	    *patch = (int) strtoul (buf, &buf, 10);	}    }}/******************************************************************** * * Procedure to determine if the PPP line discipline is registered. */static intppp_registered(void){    int local_fd;    int mfd = -1;    int ret = 0;    char slave[16];    /*     * We used to open the serial device and set it to the ppp line     * discipline here, in order to create a ppp unit.  But that is     * not a good idea - the user might have specified a device that     * they can't open (permission, or maybe it doesn't really exist).     * So we grab a pty master/slave pair and use that.     */    if (!get_pty(&mfd, &local_fd, slave, 0)) {	no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";	return 0;    }    /*     * Try to put the device into the PPP discipline.     */    if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {	error("ioctl(TIOCSETD(PPP)): %m (line %d)", __LINE__);    } else	ret = 1;    close(local_fd);    close(mfd);    return ret;}/******************************************************************** * * ppp_available - check whether the system has any ppp interfaces * (in fact we check whether we can do an ioctl on ppp0). */int ppp_available(void){    int s, ok, fd;    struct ifreq ifr;    int    size;    int    my_version, my_modification, my_patch;    int osmaj, osmin, ospatch;    no_ppp_msg =	"This system lacks kernel support for PPP.  This could be because\n"	"the PPP kernel module could not be loaded, or because PPP was not\n"	"included in the kernel configuration.  If PPP was included as a\n"	"module, try `/sbin/modprobe -v ppp'.  If that fails, check that\n"	"ppp.o exists in /lib/modules/`uname -r`/net.\n"	"See README.linux file in the ppp distribution for more details.\n";    /* get the kernel version now, since we are called before sys_init */    uname(&utsname);    osmaj = osmin = ospatch = 0;    sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);    kernel_version = KVERSION(osmaj, osmin, ospatch);    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);	}    }#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;    }    if (kernel_version >= KVERSION(2,3,13)) {	if (errno == ENOENT)	    no_ppp_msg =		"pppd is unable to open the /dev/ppp device.\n"		"You need to create the /dev/ppp device node by\n"		"executing the following command as root:\n"		"	mknod /dev/ppp c 108 0\n";	return 0;    }/* * Open a socket for doing the ioctl operations. */    s = socket(AF_INET, SOCK_DGRAM, 0);    if (s < 0)	return 0;    strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;/* * If the device did not exist then attempt to create one by putting the * current tty into the PPP discipline. If this works then obtain the * flags for the device again. */    if (!ok) {	if (ppp_registered()) {	    strlcpy (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;/* *  This is the PPP device. Validate the version of the driver at this *  point to ensure that this program will work with the driver. */    if (ok) {	char   abBuffer [1024];	ifr.ifr_data = abBuffer;	size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);	if (size < 0) {	    error("Couldn't read driver version: %m");	    ok = 0;	    no_ppp_msg = "Sorry, couldn't verify kernel driver version\n";	} else {	    decode_version(abBuffer,			   &driver_version,			   &driver_modification,			   &driver_patch);/* * Validate the version of the driver against the version that we used. */	    decode_version(VERSION,			   &my_version,			   &my_modification,			   &my_patch);	    /* The version numbers must match */	    if (driver_version != my_version)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -