📄 sys-linux.c
字号:
} }/* * Add the device route */ 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; SIN_ADDR(rt.rt_gateway) = 0L; SIN_ADDR(rt.rt_dst) = his_adr; rt.rt_flags = RTF_UP | RTF_HOST; if (kernel_version > KVERSION(2,1,0)) { SET_SA_FAMILY (rt.rt_genmask, AF_INET); SIN_ADDR(rt.rt_genmask) = -1L; } if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) { if (! ok_error (errno)) error("ioctl(SIOCADDRT) device route: %m(%d)", errno); return (0); } } /* set ip_dynaddr in demand mode if address changes */ if (demand && tune_kernel && !dynaddr_set && our_old_addr && our_old_addr != our_adr) { /* set ip_dynaddr if possible */ char *path; int fd; path = path_to_procfs("/sys/net/ipv4/ip_dynaddr"); if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) { if (write(fd, "1", 1) != 1) error("Couldn't enable dynamic IP addressing: %m"); close(fd); } dynaddr_set = 1; /* only 1 attempt */ } our_old_addr = 0; return 1;}/******************************************************************** * * cifaddr - Clear the interface IP addresses, and delete routes * through the interface if possible. */int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr){ struct ifreq ifr; if (kernel_version < KVERSION(2,1,16)) {/* * Delete the route through the device */ struct rtentry rt; 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; SIN_ADDR(rt.rt_gateway) = 0; SIN_ADDR(rt.rt_dst) = his_adr; rt.rt_flags = RTF_UP | RTF_HOST; if (kernel_version > KVERSION(2,1,0)) { SET_SA_FAMILY (rt.rt_genmask, AF_INET); SIN_ADDR(rt.rt_genmask) = -1L; } if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) { if (still_ppp() && ! ok_error (errno)) error("ioctl(SIOCDELRT) device route: %m(%d)", errno); return (0); } } /* This way it is possible to have an IPX-only or IPv6-only interface */ memset(&ifr, 0, sizeof(ifr)); SET_SA_FAMILY(ifr.ifr_addr, AF_INET); strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) { if (! ok_error (errno)) { error("ioctl(SIOCSIFADDR): %m(%d)", errno); return 0; } } our_old_addr = our_adr; return 1;}#ifdef INET6/******************************************************************** * * sif6addr - Config the interface with an IPv6 link-local address */int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64){ struct in6_ifreq ifr6; struct ifreq ifr; struct in6_rtmsg rt6; memset(&ifr, 0, sizeof (ifr)); strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) { error("sif6addr: ioctl(SIOCGIFINDEX): %m (%d)", errno); return 0; } /* Local interface */ memset(&ifr6, 0, sizeof(ifr6)); IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64); ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = 10; if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) { error("sif6addr: ioctl(SIOCSIFADDR): %m (%d)", errno); return 0; } /* Route to remote host */ memset(&rt6, 0, sizeof(rt6)); IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64); rt6.rtmsg_flags = RTF_UP; rt6.rtmsg_dst_len = 10; rt6.rtmsg_ifindex = ifr.ifr_ifindex; rt6.rtmsg_metric = 1; if (ioctl(sock6_fd, SIOCADDRT, &rt6) < 0) { error("sif6addr: ioctl(SIOCADDRT): %m (%d)", errno); return 0; } return 1;}/******************************************************************** * * cif6addr - Remove IPv6 address from interface */int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64){ struct ifreq ifr; struct in6_ifreq ifr6; memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(sock6_fd, SIOCGIFINDEX, (caddr_t) &ifr) < 0) { error("cif6addr: ioctl(SIOCGIFINDEX): %m (%d)", errno); return 0; } memset(&ifr6, 0, sizeof(ifr6)); IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64); ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = 10; if (ioctl(sock6_fd, SIOCDIFADDR, &ifr6) < 0) { if (errno != EADDRNOTAVAIL) { if (! ok_error (errno)) error("cif6addr: ioctl(SIOCDIFADDR): %m (%d)", errno); } else { warn("cif6addr: ioctl(SIOCDIFADDR): No such address"); } return (0); } return 1;}#endif /* INET6 *//* * get_pty - get a pty master/slave pair and chown the slave side * to the uid given. Assumes slave_name points to >= 16 bytes of space. */intget_pty(master_fdp, slave_fdp, slave_name, uid) int *master_fdp; int *slave_fdp; char *slave_name; int uid;{ int i, mfd, sfd = -1; char pty_name[16]; struct termios tios;#ifdef TIOCGPTN /* * Try the unix98 way first. */ mfd = open("/dev/ptmx", O_RDWR); if (mfd >= 0) { int ptn; if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) { slprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn); chmod(pty_name, S_IRUSR | S_IWUSR);#ifdef TIOCSPTLCK ptn = 0; if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0) warn("Couldn't unlock pty slave %s: %m", pty_name);#endif if ((sfd = open(pty_name, O_RDWR | O_NOCTTY)) < 0) warn("Couldn't open pty slave %s: %m", pty_name); } }#endif /* TIOCGPTN */ if (sfd < 0) { /* the old way - scan through the pty name space */ for (i = 0; i < 64; ++i) { slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x", 'p' + i / 16, i % 16); mfd = open(pty_name, O_RDWR, 0); if (mfd >= 0) { pty_name[5] = 't'; sfd = open(pty_name, O_RDWR | O_NOCTTY, 0); if (sfd >= 0) { fchown(sfd, uid, -1); fchmod(sfd, S_IRUSR | S_IWUSR); break; } close(mfd); } } } if (sfd < 0) return 0; strlcpy(slave_name, pty_name, 16); *master_fdp = mfd; *slave_fdp = sfd; if (tcgetattr(sfd, &tios) == 0) { tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB); tios.c_cflag |= CS8 | CREAD; tios.c_iflag = IGNPAR | CLOCAL; tios.c_oflag = 0; tios.c_lflag = 0; if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0) warn("couldn't set attributes on pty: %m"); } else warn("couldn't get attributes on pty: %m"); return 1;}/******************************************************************** * * open_loopback - open the device we use for getting packets * in demand mode. Under Linux, we use a pty master/slave pair. */intopen_ppp_loopback(void){ int flags; looped = 1; if (new_style_driver) { /* allocate ourselves a ppp unit */ ifunit = -1; if (ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit) < 0) fatal("Couldn't create PPP unit: %m"); set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC); set_kdebugflag(kdebugflag); ppp_fd = -1; return ppp_dev_fd; } if (!get_pty(&master_fd, &slave_fd, loop_name, 0)) fatal("No free pty for loopback"); SYSDEBUG(("using %s for loopback", loop_name)); set_ppp_fd(slave_fd); flags = fcntl(master_fd, F_GETFL); if (flags == -1 || fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1) warn("couldn't set master loopback to nonblock: %m(%d)", errno); flags = fcntl(ppp_fd, F_GETFL); if (flags == -1 || fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1) warn("couldn't set slave loopback to nonblock: %m(%d)", errno); if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0) fatal("ioctl(TIOCSETD): %m(%d)", errno);/* * Find out which interface we were given. */ if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);/* * Enable debug in the driver if requested. */ set_kdebugflag (kdebugflag); return master_fd;}/******************************************************************** * * restore_loop - reattach the ppp unit to the loopback. * * The kernel ppp driver automatically reattaches the ppp unit to * the loopback if the serial port is set to a line discipline other * than ppp, or if it detects a modem hangup. The former will happen * in disestablish_ppp if the latter hasn't already happened, so we * shouldn't need to do anything. * * Just to be sure, set the real serial port to the normal discipline. */voidrestore_loop(void){ looped = 1; if (new_style_driver) { set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_LOOP_TRAFFIC); return; } if (ppp_fd != slave_fd) { (void) ioctl(ppp_fd, TIOCSETD, &tty_disc); set_ppp_fd(slave_fd); }}/******************************************************************** * * sifnpmode - Set the mode for handling packets for a given NP. */intsifnpmode(u, proto, mode) int u; int proto; enum NPmode mode;{ struct npioctl npi; npi.protocol = proto; npi.mode = mode; if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) { if (! ok_error (errno)) error("ioctl(PPPIOCSNPMODE, %d, %d): %m (%d)", proto, mode, errno); return 0; } return 1;}/******************************************************************** * * sipxfaddr - Config the interface IPX networknumber */int sipxfaddr (int unit, unsigned long int network, unsigned char * node ){ int result = 1;#ifdef IPX_CHANGE int skfd; struct ifreq ifr; struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; skfd = socket (AF_IPX, SOCK_DGRAM, 0); if (skfd < 0) { if (! ok_error (errno)) dbglog("socket(AF_IPX): %m (%d)", errno); result = 0; } else { memset (&ifr, '\0', sizeof (ifr)); strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); memcpy (sipx->sipx_node, node, IPX_NODE_LEN); sipx->sipx_family = AF_IPX; sipx->sipx_port = 0; sipx->sipx_network = htonl (network); sipx->sipx_type = IPX_FRAME_ETHERII; sipx->sipx_action = IPX_CRTITF;/* * Set the IPX device */ if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) { result = 0; if (errno != EEXIST) { if (! ok_error (errno)) dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (%d)", errno); } else { warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists"); } } close (skfd); }#endif return result;}/******************************************************************** * * cipxfaddr - Clear the information for the IPX network. The IPX routes * are removed and the device is no longer able to pass IPX * frames. */int cipxfaddr (int unit){ int result = 1;#ifdef IPX_CHANGE int skfd; struct ifreq ifr; struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; skfd = socket (AF_IPX, SOCK_DGRAM, 0); if (skfd < 0) { if (! ok_error (errno)) dbglog("socket(AF_IPX): %m (%d)", errno); result = 0; } else { memset (&ifr, '\0', sizeof (ifr)); strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); sipx->sipx_type = IPX_FRAME_ETHERII; sipx->sipx_action = IPX_DLTITF; sipx->sipx_family = AF_IPX;/* * Set the IPX device */ if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) { if (! ok_error (errno)) info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (%d)", errno); result = 0; } close (skfd); }#endif return result;}/* * Use the hostname as part of the random number seed. */intget_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 */intsys_check_options(void){#ifdef IPX_CHANGE/* * Disable the IPX protocol if the support is not present in the kernel. */ char *path; if (ipxcp_protent.enabled_flag) { struct stat stat_buf; if ((path = path_to_procfs("/net/ipx_interface")) == 0 || lstat(path, &stat_buf) < 0) { error("IPX support is not present in the kernel\n"); ipxcp_protent.enabled_flag = 0; } }#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); return 0; } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -