⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interface.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
字号:
/* interface.c * linqianghe@163.com * 2006-10-19 */#include "interface.h"#include "pathnames.h"#include "util.h"#include "sockets.h"#include "net-support.h"#include "af_inet.h"#include "log.h"#include <stdio.h>#include <string.h>#include <errno.h>#include <ctype.h>#include <linux/sockios.h>#include <sys/ioctl.h>#include <stdlib.h>int ife_short; int procnetdev_vsn = 1;static struct interface *int_list, *int_last;int for_all_interfaces( int (*doit) (struct interface *, void *), void *cookie ){	struct interface *ife;	if( !int_list && (if_readlist() < 0) )		return -1;	for( ife = int_list; ife; ife = ife->next ){		int err = doit( ife, cookie );		if( err )			return err;	}	return 0;}static int procnetdev_version(char *buf){	if( strstr(buf, "compressed") )		return 3;	if( strstr(buf, "bytes") )		return 2;	return 1;}static char *get_name(char *name, char *p){	while( isspace(*p) )		p++;	while( *p ){		if( isspace(*p) )			break;		if( *p == ':' ){			char *dot = p, *dotname = name;			*name++ = *p++;			while( isdigit(*p) )				*name++ = *p++;			if( *p != ':' ){				p = dot;				name = dotname;			}			if( *p == '\0' )				return NULL;			p++;			break;		}		*name++ = *p++;	}	*name++ = '\0';	return p;}static struct interface *add_interface(char *name){	struct interface *ife, **nextp, *new;	for( ife = int_last; ife; ife = ife->prev ){		int n = nstrcmp(ife->name, name);		if( n == 0 )			return ife;		if( n < 0 )			break;	}	new(new);	safe_strncpy(new->name, name, IFNAMSIZ);	nextp = ife ? &ife->next : &int_list;	new->prev = ife;	new->next = *nextp;	if (new->next)		new->next->prev = new;	else		int_last = new;	*nextp = new;	return new;}static int get_dev_fields(char *bp, struct interface *ife){	switch (procnetdev_vsn) {	case 3:		sscanf(bp, "%llu %llu %lu %lu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu %lu",						&ife->stats.rx_bytes,						&ife->stats.rx_packets,						&ife->stats.rx_errors,						&ife->stats.rx_dropped,						&ife->stats.rx_fifo_errors,						&ife->stats.rx_frame_errors,						&ife->stats.rx_compressed,						&ife->stats.rx_multicast,						&ife->stats.tx_bytes,						&ife->stats.tx_packets,						&ife->stats.tx_errors,						&ife->stats.tx_dropped,						&ife->stats.tx_fifo_errors,						&ife->stats.collisions,						&ife->stats.tx_carrier_errors,						&ife->stats.tx_compressed);		break;	case 2:		sscanf(bp, "%llu %llu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu",						&ife->stats.rx_bytes,						&ife->stats.rx_packets,						&ife->stats.rx_errors,						&ife->stats.rx_dropped,						&ife->stats.rx_fifo_errors,						&ife->stats.rx_frame_errors,						&ife->stats.tx_bytes,						&ife->stats.tx_packets,						&ife->stats.tx_errors,						&ife->stats.tx_dropped,						&ife->stats.tx_fifo_errors,						&ife->stats.collisions,						&ife->stats.tx_carrier_errors);		ife->stats.rx_multicast = 0;		break;	case 1:		sscanf(bp, "%llu %lu %lu %lu %lu %llu %lu %lu %lu %lu %lu",						&ife->stats.rx_packets,						&ife->stats.rx_errors,						&ife->stats.rx_dropped,						&ife->stats.rx_fifo_errors,						&ife->stats.rx_frame_errors,						&ife->stats.tx_packets,						&ife->stats.tx_errors,						&ife->stats.tx_dropped,						&ife->stats.tx_fifo_errors,						&ife->stats.collisions,						&ife->stats.tx_carrier_errors);		ife->stats.rx_bytes = 0;		ife->stats.tx_bytes = 0;		ife->stats.rx_multicast = 0;		break;	}	return 0;}static int if_readconf(void){	int numreqs = 30;	struct ifconf ifc;	struct ifreq *ifr;	int n, err = -1;	int skfd;	skfd = get_socket_for_af( MY_AF_INET );	if( skfd < 0 ){		PR_DEBUG( "warning: no inet socket available: %s\n", strerror(errno) );		skfd = sockets_open(0);		if( skfd < 0 )			return -1;	}	ifc.ifc_buf = NULL;	for( ;; ){		ifc.ifc_len = sizeof(struct ifreq) * numreqs;		ifc.ifc_buf = xrealloc( ifc.ifc_buf, ifc.ifc_len );		if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {			PR_ERR( "SIOCGIFCONF: %s", strerror(errno) );			goto out;		}		if( ifc.ifc_len == sizeof(struct ifreq) * numreqs ){			numreqs += 10;			continue;		}		break;	}	ifr = ifc.ifc_req;	for( n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq) ){		add_interface(ifr->ifr_name);		ifr++;	}	err = 0;out:	free(ifc.ifc_buf);	return err;}static int if_readlist_proc(char *target){	static int proc_read;	FILE *fh;	char buf[512];	struct interface *ife;	int err;	if( proc_read )		return 0;	if( !target )		proc_read = 1;	fh = fopen( _PATH_PROCNET_DEV, "r" );	if( !fh ){		PR_ERR( "Warning: cannot open %s (%s). Limited output.\n",						_PATH_PROCNET_DEV, strerror(errno) );		return if_readconf();	}	fgets(buf, sizeof buf, fh);	fgets(buf, sizeof buf, fh);	procnetdev_vsn = procnetdev_version(buf);	err = 0;	while( fgets(buf, sizeof buf, fh) ){		char *s, name[IFNAMSIZ];		s = get_name( name, buf );		ife = add_interface( name );		get_dev_fields(s, ife);		ife->statistics_valid = 1;		if( target && !strcmp(target,name) )			break;	}	if( ferror(fh) ){		PR_DEBUG( _PATH_PROCNET_DEV ": %s", strerror(errno) );		err = -1;		proc_read = 0;	}	fclose(fh);	return err;}int if_readlist(void){	int err = if_readlist_proc(NULL);	if( err < 0 )		err = if_readconf();	return err;}int if_fetch(struct interface *ife){	struct ifreq ifr;	int fd;	char *ifname = ife->name;	strcpy(ifr.ifr_name, ifname);	if( ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0 ){		PR_DEBUG("SIOCGIFFLAGS error!\n");		return (-1);	}	ife->flags = ifr.ifr_flags;	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0){		PR_DEBUG("SIOCGIFHWADDR error!\n");		memset(ife->hwaddr, 0, 32);	}else{		memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);	}	ife->type = ifr.ifr_hwaddr.sa_family;	strcpy( ifr.ifr_name, ifname );	if( ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0 ){		PR_DEBUG("SIOCGIFMETRIC error!\n");		ife->metric = 0;	}else{		ife->metric = ifr.ifr_metric;	}	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0){		PR_DEBUG("SIOCGIFMTU error!\n");		ife->mtu = 0;	}else		ife->mtu = ifr.ifr_mtu;	strcpy(ifr.ifr_name, ifname);	if( ioctl(skfd, SIOCGIFMAP, &ifr) < 0 ){		PR_DEBUG("SIOCGIFMAP error!\n");		memset( &ife->map, 0, sizeof(struct ifmap) );	}else{		memcpy( &ife->map, &ifr.ifr_map, sizeof(struct ifmap) );	}	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0){		PR_DEBUG("SIOCGIFMAP2 error!\n");		memset(&ife->map, 0, sizeof(struct ifmap));	}else{		ife->map = ifr.ifr_map;	}	strcpy(ifr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0){		PR_DEBUG("SIOCGIFTXQLEN error!\n");		ife->tx_queue_len = -1; /* unknown value */	}else		ife->tx_queue_len = ifr.ifr_qlen;	fd = get_socket_for_af(	MY_AF_INET );	if (fd >= 0) {		strcpy(ifr.ifr_name, ifname);		ifr.ifr_addr.sa_family = MY_AF_INET;		if( ioctl(fd, SIOCGIFADDR, &ifr) == 0 ){			ife->has_ip = 1;			ife->addr = ifr.ifr_addr;			strcpy(ifr.ifr_name, ifname);			if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0){				PR_DEBUG("SIOCGIFDSTADDR error!\n");				memset(&ife->dstaddr, 0, sizeof(struct sockaddr));			}else{				ife->dstaddr = ifr.ifr_dstaddr;			}			strcpy(ifr.ifr_name, ifname);			if( ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0 ){				PR_DEBUG("SIOCGIFBRDADDR error!\n");				memset(&ife->broadaddr, 0, sizeof(struct sockaddr));			}else				ife->broadaddr = ifr.ifr_broadaddr;			strcpy(ifr.ifr_name, ifname);			if( ioctl(fd, SIOCGIFNETMASK, &ifr) < 0 ){				PR_DEBUG("SIOCGIFNETMASK error!\n");				memset(&ife->netmask, 0, sizeof(struct sockaddr));			}else				ife->netmask = ifr.ifr_netmask;		}else{			PR_DEBUG("SIOCGIFADDR error!\n");			memset(&ife->addr, 0, sizeof(struct sockaddr));		}	}	return 0;}int do_if_fetch(struct interface *ife){	if( if_fetch(ife) < 0 ){		char *errmsg;		if( errno == ENODEV ){			errmsg = "Device not found";		}else{			errmsg = strerror(errno);		}		fprintf(stderr, "%s: error fetching interface information: %s\n",						ife->name, errmsg );		return -1;	}	return 0;}void ife_print_short(struct interface *ptr){	printf("%-5.5s ", ptr->name);	printf("%5d %3d", ptr->mtu, ptr->metric);	/* If needed, display the interface statistics. */	if (ptr->statistics_valid) {		printf("%8llu %6lu %6lu %6lu",						ptr->stats.rx_packets, ptr->stats.rx_errors,						ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors);		printf("%8llu %6lu %6lu %6lu ",						ptr->stats.tx_packets, ptr->stats.tx_errors,						ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors);	}else{		printf("%-56s", "- no statistics available -");	}	if (ptr->flags == 0)		printf("[NO FLAGS]");	if (ptr->flags & IFF_ALLMULTI)		printf("A");	if (ptr->flags & IFF_BROADCAST)		printf("B");	if (ptr->flags & IFF_DEBUG)		printf("D");	if (ptr->flags & IFF_LOOPBACK)		printf("L");	if (ptr->flags & IFF_MULTICAST)		printf("M");#ifdef HAVE_DYNAMIC	if (ptr->flags & IFF_DYNAMIC)		printf("d");#endif	if (ptr->flags & IFF_PROMISC)		printf("P");	if (ptr->flags & IFF_NOTRAILERS)		printf("N");	if (ptr->flags & IFF_NOARP)		printf("O");	if (ptr->flags & IFF_POINTOPOINT)		printf("P");	if (ptr->flags & IFF_SLAVE)		printf("s");	if (ptr->flags & IFF_MASTER)		printf("m");	if (ptr->flags & IFF_RUNNING)		printf("R");	if (ptr->flags & IFF_UP)		printf("U");	printf("\n");}void ife_print_long(struct interface *ptr){	struct aftype *ap;	struct hwtype *hw;	int hf;	int can_compress = 0;	unsigned long long rx, tx, short_rx, short_tx;	char Rext[5]="b";	char Text[5]="b";	ap = get_afntype(ptr->addr.sa_family);	if (ap == NULL)		ap = get_afntype(0);	hf = ptr->type;	if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)			can_compress = 1;	hw = get_hwntype(hf);	if( hw == NULL )		hw = get_hwntype(-1);	printf( "%-9.9s Link encap:%s  ", ptr->name, hw->title );    if( hw->print != NULL && ( !(hw_null_address(hw, ptr->hwaddr) &&									hw->suppress_null_addr)))		printf("HWaddr %s  ", hw->print((unsigned char *)ptr->hwaddr));	printf("\n");	if( ptr->has_ip ){		printf( "          %s addr:%s ", ap->name, ap->sprint(&ptr->addr, 1) );		if( ptr->flags & IFF_POINTOPOINT ){			printf(" P-t-P:%s ", ap->sprint(&ptr->dstaddr, 1));		}		if( ptr->flags & IFF_BROADCAST ){			printf(" Bcast:%s ", ap->sprint(&ptr->broadaddr, 1));		}		printf(" Mask:%s\n", ap->sprint(&ptr->netmask, 1));	}	printf("          ");	/* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */	if( ptr->flags == 0 )		printf("[NO FLAGS] ");	if( ptr->flags & IFF_UP )		printf("UP ");	if( ptr->flags & IFF_BROADCAST )		printf("BROADCAST ");	if( ptr->flags & IFF_DEBUG )		printf("DEBUG ");	if( ptr->flags & IFF_LOOPBACK )		printf("LOOPBACK ");	if( ptr->flags & IFF_POINTOPOINT )		printf("POINTOPOINT ");	if( ptr->flags & IFF_NOTRAILERS )		printf("NOTRAILERS ");	if( ptr->flags & IFF_RUNNING )		printf("RUNNING ");	if( ptr->flags & IFF_NOARP )		printf("NOARP ");	if( ptr->flags & IFF_PROMISC )		printf("PROMISC ");	if( ptr->flags & IFF_ALLMULTI )		printf("ALLMULTI ");	if( ptr->flags & IFF_SLAVE )		printf("SLAVE ");	if( ptr->flags & IFF_MASTER )		printf("MASTER ");	if( ptr->flags & IFF_MULTICAST )		printf("MULTICAST ");	printf(" MTU:%d  Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1);    printf("\n");	if( ptr->statistics_valid ){		printf("          ");		printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n",						ptr->stats.rx_packets, ptr->stats.rx_errors,						ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,						ptr->stats.rx_frame_errors);		if( can_compress )			printf("             compressed:%lu\n", ptr->stats.rx_compressed);		rx = ptr->stats.rx_bytes;		tx = ptr->stats.tx_bytes;		short_rx = rx * 10;		short_tx = tx * 10;		if( rx > 1048576 ) { short_rx /= 1048576;  strcpy(Rext, "Mb"); }		else if( rx > 1024 ) { short_rx /= 1024;  strcpy(Rext, "Kb"); }		if( tx > 1048576 ) { short_tx /= 1048576;  strcpy(Text, "Mb"); }		else if( tx > 1024 ) { short_tx /= 1024;  strcpy(Text, "Kb"); }		printf("          ");		printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n",						ptr->stats.tx_packets, ptr->stats.tx_errors,						ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,						ptr->stats.tx_carrier_errors);		printf("          collisions:%lu ", ptr->stats.collisions);		if( can_compress )			printf("compressed:%lu ", ptr->stats.tx_compressed);		if( ptr->tx_queue_len != -1 )			printf("txqueuelen:%d ", ptr->tx_queue_len);		printf("\n          ");		printf("RX bytes:%llu (%lu.%lu %s)  TX bytes:%llu (%lu.%lu %s)\n",						rx, (unsigned long)(short_rx / 10),						(unsigned long)(short_rx % 10), Rext,						tx, (unsigned long)(short_tx / 10),						(unsigned long)(short_tx % 10), Text);	}	if( (ptr->map.irq || ptr->map.mem_start || ptr->map.dma || ptr->map.base_addr) ){		printf("          ");		if( ptr->map.irq )			printf("Interrupt:%d ", ptr->map.irq);		if( ptr->map.base_addr >= 0x100 )				printf("Base address:0x%x ", ptr->map.base_addr);		if( ptr->map.mem_start ){			printf("Memory:%lx-%lx ", ptr->map.mem_start, ptr->map.mem_end);		}		if (ptr->map.dma)			printf("DMA chan:%x ", ptr->map.dma);		printf("\n");	}	printf("\n");}void ife_print(struct interface *i){	if( ife_short )		ife_print_short( i );	else		ife_print_long( i );}int do_if_print(struct interface *ife, void *cookie){	int *opt_a = (int *) cookie;	int res;	res = do_if_fetch( ife );	if( res >= 0 ){		if( (ife->flags & IFF_UP) || *opt_a )			ife_print(ife);	}	return res;}struct interface *lookup_interface(char *name){	struct interface *ife = NULL;	if( if_readlist_proc(name) < 0 ){		PR_DEBUG( "can't fine the dev: %s\n", name );		return NULL;	}	ife = add_interface(name);	return ife;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -