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

📄 snap_kern_iface.c

📁 一个学习SNMP项目:tmoerlan.
💻 C
字号:
/* * snap_kern_iface.c : interface between snap interpreter and the rest * of the kernel networking code */#include <asm/types.h>#include <sys/types.h>#include <assert.h>#include <errno.h>#include <features.h>#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1#include <netpacket/packet.h>#include <net/ethernet.h>     /* the L2 protocols */#else#include <asm/types.h>#include <linux/if_packet.h>#include <linux/if_ether.h>   /* The L2 protocols */#endif#include <sys/socket.h>#include <net/if.h>#include <net/if_arp.h>#include <netdb.h>#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>#include <stdlib.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/un.h>#include <unistd.h>#include "d_printf.h"#include "packet.h"#include "memalloc.h"#include "interface.h"#include "sockets.h"#include "pathnames.h"#include "intl.h"#include "net-support.h"#include "router.h"#include "io.h"#include "warn.h"struct iphdr  {#if __BYTE_ORDER == __LITTLE_ENDIAN    unsigned int ihl:4;    unsigned int version:4;#elif __BYTE_ORDER == __BIG_ENDIAN    unsigned int version:4;    unsigned int ihl:4;#else# error	"Please fix <bits/endian.h>"#endif    u_int8_t tos;    u_int16_t tot_len;    u_int16_t id;    u_int16_t frag_off;    u_int8_t ttl;    u_int8_t protocol;    u_int16_t check;    u_int32_t saddr;    u_int32_t daddr;    /*The options start here. */  };#define NIPQUAD(addr) \        ((unsigned char *)&(addr))[0], \        ((unsigned char *)&(addr))[1], \        ((unsigned char *)&(addr))[2], \        ((unsigned char *)&(addr))[3]#ifdef CONFIG_IP_SNAPstatic inline unsigned short ip_fast_csum(unsigned char * iph,					  unsigned int ihl);#ifdef CONFIG_IP_SNAP_DEBUGint sysctl_snap_debug_level = 0;#endif /* CONFIG_IP_SNAP_DEBUG *//* hardware interface definitions */struct if_info {  struct if_nameindex ifni;  __u32 addr;  char hwaddr[32];};/* hardware interface variables */struct sockaddr_in *thishosthint = NULL;struct hostent *thishe = NULL;unsigned int numifs = 0;struct if_info *ifs = NULL;unsigned int maxifnum = 0;unsigned int ifs_size = 0;/* the send sockets */static int rawip_send_ra_socket;void init_kern_iface(struct sockaddr_in *hint) {  char hostname[128];  struct if_nameindex *allifs;  struct if_nameindex *currif;  struct interface ife;  unsigned char ra_space[4];  /* get the primary hostname */  if ((hint != NULL) && (hint->sin_addr.s_addr != 0)) {    thishosthint = hint;  }  if (gethostname(hostname,sizeof(hostname)) < 0) {    perror("gethostname");    exit(EXIT_FAILURE);  }  if ((thishe = gethostbyname(hostname)) == NULL) {    herror("gethostbyname");	fprintf(stderr,"debug >> error while trying to resolve %s\n",hostname);    exit(EXIT_FAILURE);  }  if ((rawip_send_ra_socket = socket(AF_INET, SOCK_RAW, IPPROTO_SNAP)) < 0) {    perror("snap_kern_iface: rawip_send_ra_socket: socket()");    exit(EXIT_FAILURE);  }  ra_space[IPOPT_OPTVAL] = IPOPT_RA;  ra_space[IPOPT_OLEN] = 4;  ra_space[2] = ra_space[3] = 0;  if (setsockopt(rawip_send_ra_socket, IPPROTO_IP, IP_OPTIONS, ra_space,		 sizeof(ra_space)) < 0) {    perror("rawip_send_ra_socket: router alert setsockopt()");    exit(EXIT_FAILURE);  }  /* retrieve the active interfaces from the kernel */  if ((skfd = sockets_open()) < 0) {    perror("skfd: sockets_open()");    exit(EXIT_FAILURE);  }  /* collect IFACE info from glibc functions */  if ((allifs = if_nameindex()) == NULL) {    perror("if_nameindex");    exit(EXIT_FAILURE);  }  for (currif = allifs;       (currif->if_index != 0) && (currif->if_name != NULL);       currif++) {    if (currif->if_index > maxifnum) {      maxifnum = currif->if_index;    }    numifs++;  }  d_printf(40,"found %d interfaces\n",numifs);    assert(maxifnum > 0);    /* get additional IFACE info from local functions */  memalloc(ifs,struct if_info *,sizeof(struct if_info) * (maxifnum + 1));  ifs_size = maxifnum + 1;  for (currif = allifs;(currif->if_index != 0) && (currif->if_name != NULL); currif++) {		(void)if_fetch(currif->if_name, &ife);		ifs[currif->if_index].ifni.if_index = currif->if_index;		ifs[currif->if_index].ifni.if_name = currif->if_name;		ifs[currif->if_index].addr =		(*(struct sockaddr_in *)(&ife.addr)).sin_addr.s_addr;		memcpy(ifs[currif->if_index].hwaddr, ife.hwaddr, 32);		d_printf(45,"if_index %d = %s inaddr = %d.%d.%d.%d\n",	currif->if_index,currif->if_name, NIPQUAD((*(struct sockaddr_in *)(&ife.addr)).sin_addr.s_addr));		fflush(stderr);  }  /*   	read additional IFACE and ROUTE info from /proc 	NB: IFACE info from /proc/net/dev is used for ifacename<->ifaceindex translation	I don't know why Jon implemented this.  */  read_ifaces(PROC_NET_DEV_PATH);  read_routes(PROC_NET_ROUTE_PATH);}/* returns one of the current host's IP addresses, preferably not   127.0.0.1 */#ifdef __KERNEL__int snap_here(u32 *addr, struct sk_buff *skb) {#elseint snap_here(__u32 *addr, packet_t *p) {#endif  int i;  __u32 tmpaddr;  if (thishosthint != NULL) {    d_printf(50,"%s:%d: HERE: found non-loopback addr\n",	     __FILE__,__LINE__);    *addr = thishosthint->sin_addr.s_addr;    return 0;  }  assert(thishe != NULL);  for(i=0; thishe->h_addr_list[i] != NULL; i++) {    tmpaddr = *(__u32 *)thishe->h_addr_list[i];    if (tmpaddr != htonl(INADDR_LOOPBACK)) {      d_printf(50,"%s:%d: HERE: found non-loopback addr\n",	       __FILE__,__LINE__);      *addr = tmpaddr;      return 0;    }  }  if (i > 0) {    d_printf(50,"%s:%d: HERE: ran through %d ifs, all loopback!\n",	     __FILE__,__LINE__,i);    *addr = *(__u32 *)thishe->h_addr_list[0];    return 0;  }  return -1;}#ifdef __KERNEL__int getdevindex(struct device *dev_in) {  return -1;			/* not found */}#endifint next_hop(__u32 *hop,	     __u32 daddr,		  /* where we are headed */	     int tos ) {	  /* type of service */  struct rt_lookup rt;  if (nexthop(daddr,&rt) < 0) {    *hop = 0;    return -1;  }  *hop = rt.hopaddr;  return 0;}#ifdef __KERNEL__int ishere(__u32 addr, struct sk_buff *skb) {#elseint ishere(__u32 addr, packet_t *p) {#endif  int i;  struct if_info *curr;  for(i=0; i<=maxifnum; i++) {    curr = &ifs[i];      d_printf(100,"%s:%d: curr=%d, here=(%d.%d.%d.%d)\n",	       __FILE__,__LINE__,i,NIPQUAD(curr->addr));    if ((curr->ifni.if_index != 0) && (curr->ifni.if_name != NULL) &&	(curr->addr == addr)) {      d_printf(100,"%s:%d: ishere(%d.%d.%d.%d) -> YES\n",	       __FILE__,__LINE__,NIPQUAD(addr));      return 1;    }  }  d_printf(100,"%s:%d: ishere(%d.%d.%d.%d) -> NO\n", __FILE__,__LINE__,NIPQUAD(addr));  return 0;}/*	protocol specific demux send handlers*/#include "../src/snap_demux_handler.h"#ifdef __KERNEL__int snap_demux_send_unix(__u16 destport, struct sk_buff *skb,	       void *s, unsigned int slen) {#elseint snap_demux_send_unix(__u16 destport, packet_t *p,	       void *s, unsigned int slen) {#endif  int usock;  struct sockaddr_un laddr;  d_printf_timed(7,"snap_demux_send_unix : creating socket\n");  if ((usock = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {    perror("snap_demux_send_unix: socket()");    return -1;  }  d_printf_timed(7,"snap_demux_send_unix : creating sockaddr_un struct\n");  laddr.sun_family = AF_UNIX;  sprintf(laddr.sun_path, "/tmp/snap%d",destport);  d_printf_timed(7,"snap_demux_send_unix : sending \n");  if (sendto(usock, s, slen, 0, (struct sockaddr *)&laddr,	     sizeof(laddr)) < slen) {    perror("snap_demux_send_unix: sendto()");    return -1;  }  d_printf_timed(7,"snap_demux_send_unix : finished \n");  close(usock);  return 0;}#ifdef __KERNEL__int snap_demux_send_rawip(__u16 destport, struct sk_buff *skb,	       void *s, unsigned int slen) {#elseint snap_demux_send_rawip(__u16 destport, packet_t *p,	       void *s, unsigned int slen) {#endif	struct sockaddr_in bindaddr;	int socket_rawip;	if ((socket_rawip = socket(AF_INET, SOCK_RAW, IPPROTO_SNAP)) < 0) {    	perror("snap_demux_send_rawip: socket()");  		return 1;	}	memset(&bindaddr, 0, sizeof(bindaddr));	bindaddr.sin_family = AF_INET;	bindaddr.sin_addr.s_addr = htonl( (127 << 24) + 1 ); /* == 127.0.0.1 */	if (sendto(socket_rawip, s, slen, 0, (struct sockaddr *)&bindaddr,			sizeof(bindaddr)) < slen) {		perror("snap_demux_send_udp: sendto()");		close (socket_rawip);		return -1;	}	close (socket_rawip);	return 0;}#ifdef __KERNEL__int snap_demux_send_udp(__u16 destport, struct sk_buff *skb,	       void *s, unsigned int slen) {#elseint snap_demux_send_udp(__u16 destport, packet_t *p,	       void *s, unsigned int slen) {#endif	struct sockaddr_in bindaddr;	int socket_udp;	d_printf_timed(7,"snap_demux_send_udp : creating socket\n");	if ((socket_udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {    	perror("snap_demux_send_udp: socket()");  		return 1;	}	d_printf_timed(7,"snap_demux_send_udp : creating sockaddr_in struct\n");	memset(&bindaddr, 0, sizeof(bindaddr));	bindaddr.sin_family = AF_INET;	bindaddr.sin_addr.s_addr = htonl( (127 << 24) + 1 ); /* == 127.0.0.1 */	bindaddr.sin_port = htons(destport);	d_printf_timed(7,"snap_demux_send_udp : sending \n");	if (sendto(socket_udp, s, slen, 0, (struct sockaddr *)&bindaddr,			sizeof(bindaddr)) < slen) {		perror("snap_demux_send_udp: sendto()");		close(socket_udp);		return -1;	}	close(socket_udp);	d_printf_timed(7,"snap_demux_send_udp : finished \n");  return 0;}/*	handle demux instruction. Outgoing interfaces can be selected	by setting an environment variable. For backward compatibility	purposes handling defaults to a unix pipe*/#ifdef __KERNEL__int snap_demux_send(__u16 destport, struct sk_buff *skb,	       void *s, unsigned int slen) {#elseint snap_demux_send(__u16 destport, packet_t *p,	       void *s, unsigned int slen) {#endif	int protocols;	int returnvals = 0;	char* env_val;	d_printf_timed(7,"snap_demux_send : preparing for send ..\n");	/* retrieve the protocols */	env_val = getenv("SNAP_DEMUX_HANDLER");	if (env_val != NULL)		protocols = atoi(env_val);	else		protocols = SNAP_UDP;	if (protocols & SNAP_UNIX)		returnvals += snap_demux_send_unix(destport, p, s, slen);	if (protocols & SNAP_RAWIP)		returnvals += snap_demux_send_rawip(destport, p, s, slen);	if (protocols & SNAP_UDP)		returnvals += snap_demux_send_udp(destport, p, s, slen);	d_printf_timed(7,"snap_demux_send : .. sent message\n");	return returnvals;}int snap_send_packet(packet_t *p, int stack_amt, __u32 dest, unsigned char rb, int ep, short direct) {	struct snaphdr *sh;	buffer_t newbuf;	__u32 hopaddr;	struct rt_lookup rt;	struct iphdr *newiph;	struct sockaddr_in hopipaddr;	d_printf(60,"snap_send_packet : marshalling packet and initializing structure\n");	if (marshal_packet(p, stack_amt, &newbuf)) {		warn("%s:%d: marshal_packet failed\n",__FILE__,__LINE__);		return -1;	}	/* modify the snapheader */	newiph = (struct iphdr *)newbuf.s;	sh = (struct snaphdr *)(newbuf.s + newiph->ihl * 4);	sh->entry_point = htons(ep);	sh->daddr = dest;	/* create the ip header */	newiph->daddr = dest;	newiph->ttl = rb;	newiph->check = 0;	newiph->check =	ip_fast_csum((unsigned char *)newiph,		 newiph->ihl);	/* initialize the sockaddr structure */	memset(&hopipaddr, 0, sizeof(hopipaddr));	hopipaddr.sin_family = AF_INET;	/* calculate the next hop only if we do not want a direct connection */	if (!direct){		if (nexthop(dest,&rt) < 0) /* find next IP hop */			return -1;		hopaddr = rt.hopaddr;		d_printf(100,"%s:%d: indirect send to next hop: %d.%d.%d.%d, ifindex %d\n",__FILE__,__LINE__,NIPQUAD(hopaddr),rt.ifidx);		hopipaddr.sin_addr.s_addr = hopaddr;	}	else	{		d_printf(100,"%s:%d: direct send to next host: %d.%d.%d.%d, ifindex unknown\n",__FILE__,__LINE__,NIPQUAD(dest));		hopipaddr.sin_addr.s_addr = dest;	}#ifdef LINUX	if (setsockopt(rawip_send_ra_socket, IPPROTO_IP, IP_TTL, (char *)&rb,			sizeof(rb)) < 0) {		perror("rawip_send_ra_socket: ttl setsockopt()");		return -1;	}#else//freeBSD	int ttl_int = (int) rb;	if (setsockopt(rawip_send_ra_socket, IPPROTO_IP, IP_TTL, (void *)&ttl_int,                        sizeof(int)) < 0) {                perror("rawip_send_ra_socket: ttl setsockopt()");                return -1;        }#endif	d_printf(60,"snap_send_packet : sending packet\n");	if (sendto(rawip_send_ra_socket, sh, newbuf.lenb - (newiph->ihl * 4), 0,			(struct sockaddr *)&hopipaddr, sizeof(hopipaddr)) !=		newbuf.lenb - (newiph->ihl * 4)) {		perror("rawip_send_ra_socket: sendto()");		return -1;	}	d_printf(60,"snap_send_packet : finished\n");	return 0;}packet_t *pkt_dup(packet_t *p) {  return NULL;}int next_hop_and_dev(__u32 *hop, int *dev, __u32 daddr) {  struct rt_lookup rt;  if (nexthop(daddr, &rt) < 0) {    *hop = 0;    *dev = 0;    return -1;  }  *hop = rt.hopaddr;  *dev = rt.ifidx;  return 0;}static inline unsigned short ip_fast_csum(unsigned char * iph,					  unsigned int ihl) {	unsigned int sum;	__asm__ __volatile__("\n\	    movl (%1), %0 	\n\	    subl $4, %2 	\n\	    jbe 2f			\n\	    addl 4(%1), %0	\n\	    adcl 8(%1), %0	\n\	    adcl 12(%1), %0	\n\1:	    adcl 16(%1), %0	\n\	    lea 4(%1), %1	\n\	    decl %2			\n\	    jne	1b			\n\	    adcl $0, %0		\n\	    movl %0, %2		\n\	    shrl $16, %0	\n\	    addw %w2, %w0	\n\	    adcl $0, %0		\n\	    notl %0			\n\2:						\n\	    "	/* Since the input registers which are loaded with iph and ipl	   are modified, we must also specify them as outputs, or gcc	   will assume they contain their original values. */	: "=r" (sum), "=r" (iph), "=r" (ihl)	: "1" (iph), "2" (ihl));	return(sum);}#endif /* CONFIG_IP_SNAP */

⌨️ 快捷键说明

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