?? sys-linux.c
字號:
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(%d)", errno); 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; struct ifconf ifc; struct ifreq ifs[MAX_IFS]; ifc.ifc_len = sizeof(ifs); ifc.ifc_req = ifs; if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) { if ( ! ok_error ( errno )) error("ioctl(SIOCGIFCONF): %m(%d)", errno); return 0; } SYSDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s", ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));/* * 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)); SYSDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s", 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); SYSDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx", ip_ntoa(ina), ntohl(mask))); if (((ipaddr ^ ina) & mask) != 0) continue; break; } } if (ifr >= ifend) return 0; strlcpy(name, ifreq.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 (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr)); if (ioctl (sock_fd, SIOCGIFHWADDR, &ifreq) < 0) { error("SIOCGIFHWADDR(%s): %m(%d)", ifreq.ifr_name, errno); return 0; } memcpy (hwaddr, &ifreq.ifr_hwaddr, sizeof (struct sockaddr)); SYSDEBUG ((LOG_DEBUG, "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", (int) ((unsigned char *) &hwaddr->sa_data)[0], (int) ((unsigned char *) &hwaddr->sa_data)[1], (int) ((unsigned char *) &hwaddr->sa_data)[2], (int) ((unsigned char *) &hwaddr->sa_data)[3], (int) ((unsigned char *) &hwaddr->sa_data)[4], (int) ((unsigned char *) &hwaddr->sa_data)[5], (int) ((unsigned char *) &hwaddr->sa_data)[6], (int) ((unsigned char *) &hwaddr->sa_data)[7])); 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(%d)", errno); 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(%d)", errno); } 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) ok = 0; /* The modification levels must be legal */ if (driver_modification < 3) { if (driver_modification >= 2) { /* we can cope with 2.2.0 and above */ driver_is_old = 1; } else { ok = 0; } } close (s); if (!ok) { slprintf(route_buffer, sizeof(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;}/******************************************************************** * * Update the wtmp file with the appropriate user name and tty device. */void logwtmp (const char *line, const char *name, const char *host){ struct utmp ut, *utp; pid_t mypid = getpid();#if __GLIBC__ < 2 int wtmp;#endif/* * Update the signon database for users. * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996 */ utmpname(_PATH_UTMP); setutent(); while ((utp = getutent()) && (utp->ut_pid != mypid)) /* nothing */; /* Is this call really necessary? There is another one after the 'put' */ endutent(); if (utp) memcpy(&ut, utp, sizeof(ut)); else /* some gettys/telnetds don't initialize utmp... */ memset(&ut, 0, sizeof(ut)); if (ut.ut_id[0] == 0) strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id)); strncpy(ut.ut_user, name, sizeof(ut.ut_user)); strncpy(ut.ut_line, line, sizeof(ut.ut_line)); time(&ut.ut_time); ut.ut_type = USER_PROCESS; ut.ut_pid = mypid; /* Insert the host name if one is supplied */ if (*host) strncpy (ut.ut_host, host, sizeof(ut.ut_host)); /* Insert the IP address of the remote system if IP is enabled */ if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr) memcpy(&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr, sizeof(ut.ut_addr)); /* CL: Makes sure that the logout works */ if (*host == 0 && *name==0) ut.ut_host[0]=0; pututline(&ut); endutent();/* * Update the wtmp file. */#if __GLIBC__ >= 2 updwtmp(_PATH_WTMP, &ut);#else wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY); if (wtmp >= 0) { flock(wtmp, LOCK_EX); if (write (wtmp, (char *)&ut, sizeof(ut)) != sizeof(ut)) warn("error writing %s: %m", _PATH_WTMP); flock(wtmp, LOCK_UN); close (wtmp); }#endif}/******************************************************************** *
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -