sys-linux.c
来自「经典的ppp程序」· C语言 代码 · 共 2,629 行 · 第 1/5 页
C
2,629 行
SYSDEBUG ((LOG_DEBUG, "netif_set_mtu: mtu = %d\n", mtu)); memset (&ifr, '\0', sizeof (ifr)); strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); ifr.ifr_mtu = mtu; if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0) fatal("ioctl(SIOCSIFMTU): %m");}/******************************************************************** * * tty_send_config - configure the transmit characteristics of * the ppp interface. */void tty_send_config (int mtu,u_int32_t asyncmap,int pcomp,int accomp){ u_int x;/* * Set the asyncmap and other parameters for the ppp device */ if (!still_ppp()) return; link_mtu = mtu; SYSDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap)); if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) { if (!ok_error(errno)) fatal("ioctl(PPPIOCSASYNCMAP): %m(%d)", errno); return; } x = get_flags(ppp_fd); x = pcomp ? x | SC_COMP_PROT : x & ~SC_COMP_PROT; x = accomp ? x | SC_COMP_AC : x & ~SC_COMP_AC; x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC; set_flags(ppp_fd, x);}/******************************************************************** * * tty_set_xaccm - set the extended transmit ACCM for the interface. */void tty_set_xaccm (ext_accm accm){ SYSDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n", accm[0], accm[1], accm[2], accm[3])); if (!still_ppp()) return; if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) { if ( ! ok_error (errno)) warn("ioctl(set extended ACCM): %m(%d)", errno); }}/******************************************************************** * * tty_recv_config - configure the receive-side characteristics of * the ppp interface. */void tty_recv_config (int mru,u_int32_t asyncmap,int pcomp,int accomp){ SYSDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));/* * If we were called because the link has gone down then there is nothing * which may be done. Just return without incident. */ if (!still_ppp()) return;/* * Set the receiver parameters */ if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { if ( ! ok_error (errno)) error("ioctl(PPPIOCSMRU): %m(%d)", errno); } if (new_style_driver && ifunit >= 0 && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) error("Couldn't set MRU in generic PPP layer: %m"); SYSDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap)); if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { if (!ok_error(errno)) error("ioctl(PPPIOCSRASYNCMAP): %m(%d)", errno); }}/******************************************************************** * * ccp_test - ask kernel whether a given compression method * is acceptable for use. */int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit){ struct ppp_option_data data; memset (&data, '\0', sizeof (data)); data.ptr = opt_ptr; data.length = opt_len; data.transmit = for_transmit; if (ioctl(ppp_dev_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0) return 1; return (errno == ENOBUFS)? 0: -1;}/******************************************************************** * * ccp_flags_set - inform kernel about the current state of CCP. */void ccp_flags_set (int unit, int isopen, int isup){ if (still_ppp()) { int x = get_flags(ppp_dev_fd); x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN; x = isup? x | SC_CCP_UP : x &~ SC_CCP_UP; set_flags (ppp_dev_fd, x); }}#ifdef PPP_FILTER/* * set_filters - set the active and pass filters in the kernel driver. */int set_filters(struct bpf_program *pass, struct bpf_program *active){ struct sock_fprog fp; fp.len = pass->bf_len; fp.filter = (struct sock_filter *) pass->bf_insns; if (ioctl(ppp_dev_fd, PPPIOCSPASS, &fp) < 0) { if (errno == ENOTTY) warn("kernel does not support PPP filtering"); else error("Couldn't set pass-filter in kernel: %m"); return 0; } fp.len = active->bf_len; fp.filter = (struct sock_filter *) active->bf_insns; if (ioctl(ppp_dev_fd, PPPIOCSACTIVE, &fp) < 0) { error("Couldn't set active-filter in kernel: %m"); return 0; } return 1;}#endif /* PPP_FILTER *//******************************************************************** * * get_idle_time - return how long the link has been idle. */intget_idle_time(u, ip) int u; struct ppp_idle *ip;{ return ioctl(ppp_dev_fd, PPPIOCGIDLE, ip) >= 0;} /******************************************************************** * * get_ppp_stats - return statistics for the link. */intget_ppp_stats(u, stats) int u; struct pppd_stats *stats;{ struct ifpppstatsreq req; memset (&req, 0, sizeof (req)); req.stats_ptr = (caddr_t) &req.stats; strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name)); if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) { error("Couldn't get PPP statistics: %m"); return 0; } stats->bytes_in = req.stats.p.ppp_ibytes; stats->bytes_out = req.stats.p.ppp_obytes; return 1;}/******************************************************************** * * ccp_fatal_error - returns 1 if decompression was disabled as a * result of an error detected after decompression of a packet, * 0 otherwise. This is necessary because of patent nonsense. */int ccp_fatal_error (int unit){ int x = get_flags(ppp_dev_fd); return x & SC_DC_FERROR;}/******************************************************************** * * path_to_procfs - find the path to the proc file system mount point */static char proc_path[MAXPATHLEN];static int proc_path_len;static char *path_to_procfs(const char *tail){ struct mntent *mntent; FILE *fp; if (proc_path_len == 0) { /* Default the mount location of /proc */ strlcpy (proc_path, "/proc", sizeof(proc_path)); proc_path_len = 5; fp = fopen(MOUNTED, "r"); if (fp != NULL) { while ((mntent = getmntent(fp)) != NULL) { if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0) continue; if (strcmp(mntent->mnt_type, "proc") == 0) { strlcpy(proc_path, mntent->mnt_dir, sizeof(proc_path)); proc_path_len = strlen(proc_path); break; } } fclose (fp); } } strlcpy(proc_path + proc_path_len, tail, sizeof(proc_path) - proc_path_len); return proc_path;}/* * /proc/net/route parsing stuff. */#define ROUTE_MAX_COLS 12FILE *route_fd = (FILE *) 0;static char route_buffer[512];static int route_dev_col, route_dest_col, route_gw_col;static int route_flags_col, route_mask_col;static int route_num_cols;static int open_route_table (void);static void close_route_table (void);static int read_route_table (struct rtentry *rt);/******************************************************************** * * close_route_table - close the interface to the route table */static void close_route_table (void){ if (route_fd != (FILE *) 0) { fclose (route_fd); route_fd = (FILE *) 0; }}/******************************************************************** * * open_route_table - open the interface to the route table */static char route_delims[] = " \t\n";static int open_route_table (void){ char *path; close_route_table(); path = path_to_procfs("/net/route"); route_fd = fopen (path, "r"); if (route_fd == NULL) { error("can't open routing table %s: %m", path); return 0; } route_dev_col = 0; /* default to usual columns */ route_dest_col = 1; route_gw_col = 2; route_flags_col = 3; route_mask_col = 7; route_num_cols = 8; /* parse header line */ if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) { char *p = route_buffer, *q; int col; for (col = 0; col < ROUTE_MAX_COLS; ++col) { int used = 1; if ((q = strtok(p, route_delims)) == 0) break; if (strcasecmp(q, "iface") == 0) route_dev_col = col; else if (strcasecmp(q, "destination") == 0) route_dest_col = col; else if (strcasecmp(q, "gateway") == 0) route_gw_col = col; else if (strcasecmp(q, "flags") == 0) route_flags_col = col; else if (strcasecmp(q, "mask") == 0) route_mask_col = col; else used = 0; if (used && col >= route_num_cols) route_num_cols = col + 1; p = NULL; } } return 1;}/******************************************************************** * * read_route_table - read the next entry from the route table */static int read_route_table(struct rtentry *rt){ char *cols[ROUTE_MAX_COLS], *p; int col; memset (rt, '\0', sizeof (struct rtentry)); if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0) return 0; p = route_buffer; for (col = 0; col < route_num_cols; ++col) { cols[col] = strtok(p, route_delims); if (cols[col] == NULL) return 0; /* didn't get enough columns */ p = NULL; } SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16); SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16); SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16); rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16); rt->rt_dev = cols[route_dev_col]; return 1;}/******************************************************************** * * defaultroute_exists - determine if there is a default route */static int defaultroute_exists (struct rtentry *rt){ int result = 0; if (!open_route_table()) return 0; while (read_route_table(rt) != 0) { if ((rt->rt_flags & RTF_UP) == 0) continue; if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0) continue; if (SIN_ADDR(rt->rt_dst) == 0L) { result = 1; break; } } close_route_table(); return result;}/* * have_route_to - determine if the system has any route to * a given IP address. `addr' is in network byte order. * Return value is 1 if yes, 0 if no, -1 if don't know. * For demand mode to work properly, we have to ignore routes * through our own interface. */int have_route_to(u_int32_t addr){ struct rtentry rt; int result = 0; if (!open_route_table()) return -1; /* don't know */ while (read_route_table(&rt)) { if ((rt.rt_flags & RTF_UP) == 0 || strcmp(rt.rt_dev, ifname) == 0) continue; if ((addr & SIN_ADDR(rt.rt_genmask)) == SIN_ADDR(rt.rt_dst)) { result = 1; break; } } close_route_table(); return result;}/******************************************************************** * * 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) { u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway); if (old_gateway != gateway) error("not replacing existing default route to %s [%I]", rt.rt_dev, old_gateway); return 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; } SIN_ADDR(rt.rt_gateway) = gateway; rt.rt_flags = RTF_UP | RTF_GATEWAY; if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) { if ( ! ok_error ( errno )) error("default route ioctl(SIOCADDRT): %m(%d)", errno); return 0; } default_route_gateway = gateway; 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; default_route_gateway = 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; } SIN_ADDR(rt.rt_gateway) = gateway; rt.rt_flags = RTF_UP | RTF_GATEWAY; if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) { if (still_ppp()) { if ( ! ok_error ( errno )) error("default route ioctl(SIOCDELRT): %m (%d)", errno); 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(%d)", errno); 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)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?