📄 sys-linux.c
字号:
/* * add_fd - add an fd to the set that wait_input waits for. */void add_fd(int fd){ if (fd >= FD_SETSIZE) fatal("internal error: file descriptor too large (%d)", fd); FD_SET(fd, &in_fds); if (fd > max_in_fd) max_in_fd = fd;}/* * remove_fd - remove an fd from the set that wait_input waits for. */void remove_fd(int fd){ FD_CLR(fd, &in_fds);}/******************************************************************** * * read_packet - get a PPP packet from the serial device. */int read_packet (unsigned char *buf){ int len, nr; len = PPP_MRU + PPP_HDRLEN; if (new_style_driver) { *buf++ = PPP_ALLSTATIONS; *buf++ = PPP_UI; len -= 2; } nr = -1; if (ppp_fd >= 0) { nr = read(ppp_fd, buf, len); if (nr < 0 && errno != EWOULDBLOCK && errno != EAGAIN && errno != EIO && errno != EINTR) error("read: %m"); if (nr < 0 && errno == ENXIO) return 0; } if (nr < 0 && new_style_driver && ppp_dev_fd >= 0 && !bundle_eof) { /* 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 != EAGAIN && errno != EIO && errno != EINTR) error("read /dev/ppp: %m"); if (nr < 0 && errno == ENXIO) nr = 0; if (nr == 0 && doing_multilink) { remove_fd(ppp_dev_fd); bundle_eof = 1; } } if (new_style_driver && ppp_fd < 0 && ppp_dev_fd < 0) nr = 0; return (new_style_driver && nr > 0)? nr+2: nr;}/******************************************************************** * * get_loop_output - get outgoing packets from the ppp device, * and detect when we want to bring the real link up. * Return value is 1 if we need to bring up the link, 0 otherwise. */intget_loop_output(void){ int rv = 0; int n; if (new_style_driver) { while ((n = read_packet(inpacket_buf)) > 0) if (loop_frame(inpacket_buf, n)) rv = 1; return rv; } while ((n = read(master_fd, inbuf, sizeof(inbuf))) > 0) if (loop_chars(inbuf, n)) rv = 1; if (n == 0) fatal("eof on loopback"); if (errno != EWOULDBLOCK && errno != EAGAIN) fatal("read from loopback: %m(%d)", errno); return rv;}/* * netif_set_mtu - set the MTU on the PPP network interface. */voidnetif_set_mtu(int unit, int mtu){ struct ifreq ifr; 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) error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);}/* * netif_get_mtu - get the MTU on the PPP network interface. */intnetif_get_mtu(int unit){ struct ifreq ifr; memset (&ifr, '\0', sizeof (ifr)); strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) { error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__); return 0; } return ifr.ifr_mtu;}/******************************************************************** * * 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){ int x; if (!still_ppp()) return; link_mtu = mtu; if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) { if (errno != EIO && errno != ENOTTY) error("Couldn't set transmit async character map: %m"); ++error_count; return; } x = (pcomp? SC_COMP_PROT: 0) | (accomp? SC_COMP_AC: 0) | (sync_serial? SC_SYNC: 0); modify_flags(ppp_fd, SC_COMP_PROT|SC_COMP_AC|SC_SYNC, x);}/******************************************************************** * * tty_set_xaccm - set the extended transmit ACCM for the interface. */void tty_set_xaccm (ext_accm accm){ if (!still_ppp()) return; if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) { if ( ! ok_error (errno)) warn("ioctl(set extended ACCM): %m (line %d)", __LINE__); }}/******************************************************************** * * 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){/* * 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 (errno != EIO && errno != ENOTTY) error("Couldn't set channel receive MRU: %m"); } if (new_style_driver && ppp_dev_fd >= 0 && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) error("Couldn't set MRU in generic PPP layer: %m"); if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { if (errno != EIO && errno != ENOTTY) error("Couldn't set channel receive asyncmap: %m"); }}/******************************************************************** * * ccp_test - ask kernel whether a given compression method * is acceptable for use. */intccp_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){ int x; x = (isopen? SC_CCP_OPEN: 0) | (isup? SC_CCP_UP: 0); if (still_ppp() && ppp_dev_fd >= 0) modify_flags(ppp_dev_fd, SC_CCP_OPEN|SC_CCP_UP, 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; stats->pkts_in = req.stats.p.ppp_ipackets; stats->pkts_out = req.stats.p.ppp_opackets; 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 flags; if (ioctl(ppp_dev_fd, PPPIOCGFLAGS, &flags) < 0) { error("Couldn't read compression error flags: %m"); flags = 0; } return flags & 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -