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 + -
显示快捷键?