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

📄 icmp.c

📁 ipv6地址转换器
💻 C
📖 第 1 页 / 共 2 页
字号:
	len = min((skb->tail - ((unsigned char *) hdr)) + sizeof(struct icmp6hdr), 		  IPV6_MIN_MTU - sizeof(struct ipv6hdr));	if (len < 0) {		printk(KERN_DEBUG "icmp: len problem\n");		return;	}	msg.len = len;	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,		       MSG_DONTWAIT);	if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)		(&icmpv6_statistics.Icmp6OutDestUnreachs)[type-1]++;	icmpv6_statistics.Icmp6OutMsgs++;}static void icmpv6_echo_reply(struct sk_buff *skb){	struct sock *sk = icmpv6_socket->sk;	struct ipv6hdr *hdr = skb->nh.ipv6h;	struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;	struct in6_addr *saddr;	struct icmpv6_msg msg;	struct flowi fl;	unsigned char *data;	int len;	data = (char *) (icmph + 1);	saddr = &hdr->daddr;	if (ipv6_addr_type(saddr) & IPV6_ADDR_MULTICAST)		saddr = NULL;	len = skb->tail - data;	len += sizeof(struct icmp6hdr);	msg.icmph.icmp6_type = ICMPV6_ECHO_REPLY;	msg.icmph.icmp6_code = 0;	msg.icmph.icmp6_cksum = 0;	msg.icmph.icmp6_identifier = icmph->icmp6_identifier;	msg.icmph.icmp6_sequence = icmph->icmp6_sequence;	msg.data = data;	msg.csum = 0;	msg.len = len;	msg.daddr = &hdr->saddr;	fl.proto = IPPROTO_ICMPV6;	fl.nl_u.ip6_u.daddr = &hdr->saddr;	fl.nl_u.ip6_u.saddr = saddr;	fl.oif = skb->dev->ifindex;	fl.fl6_flowlabel = 0;	fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;	fl.uli_u.icmpt.code = 0;	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,		       MSG_DONTWAIT);	icmpv6_statistics.Icmp6OutEchoReplies++;	icmpv6_statistics.Icmp6OutMsgs++;}static void icmpv6_notify(struct sk_buff *skb,			  int type, int code, u32 info, unsigned char *buff, int len){	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;	struct ipv6hdr *hdr = (struct ipv6hdr *) buff;	struct inet6_protocol *ipprot;	struct sock *sk;	u8 *pb;	int hash;	u8 nexthdr;	nexthdr = hdr->nexthdr;	len -= sizeof(struct ipv6hdr);	if (len < 0)		return;	/* now skip over extension headers */	pb = ipv6_skip_exthdr((struct ipv6_opt_hdr *) (hdr + 1), &nexthdr, len);	if (!pb)		return;	/* BUGGG_FUTURE: we should try to parse exthdrs in this packet.	   Without this we will not able f.e. to make source routed	   pmtu discovery.	   Corresponding argument (opt) to notifiers is already added.	   --ANK (980726)	 */	hash = nexthdr & (MAX_INET_PROTOS - 1);	for (ipprot = (struct inet6_protocol *) inet6_protos[hash]; 	     ipprot != NULL; 	     ipprot=(struct inet6_protocol *)ipprot->next) {		if (ipprot->protocol != nexthdr)			continue;		if (ipprot->err_handler)			ipprot->err_handler(skb, hdr, NULL, type, code, pb, info);	}	sk = raw_v6_htable[hash];	if (sk == NULL)		return;	while((sk = raw_v6_lookup(sk, nexthdr, daddr, saddr))) {		rawv6_err(sk, skb, hdr, NULL, type, code, pb, info);		sk = sk->next;	}}  /* *	Handle icmp messages */int icmpv6_rcv(struct sk_buff *skb, unsigned long len){	struct device *dev = skb->dev;	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;	struct ipv6hdr *orig_hdr;	struct icmp6hdr *hdr = (struct icmp6hdr *) skb->h.raw;	int ulen;	int type;	icmpv6_statistics.Icmp6InMsgs++;	if (len < sizeof(struct icmp6hdr))		goto discard_it;	/* Perform checksum. */	switch (skb->ip_summed) {		case CHECKSUM_NONE:		skb->csum = csum_partial((char *)hdr, len, 0);	case CHECKSUM_HW:		if (csum_ipv6_magic(saddr, daddr, len, IPPROTO_ICMPV6, 				    skb->csum)) {			printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",				ntohs(saddr->in6_u.u6_addr16[0]),				ntohs(saddr->in6_u.u6_addr16[1]),				ntohs(saddr->in6_u.u6_addr16[2]),				ntohs(saddr->in6_u.u6_addr16[3]),				ntohs(saddr->in6_u.u6_addr16[4]),				ntohs(saddr->in6_u.u6_addr16[5]),				ntohs(saddr->in6_u.u6_addr16[6]),				ntohs(saddr->in6_u.u6_addr16[7]),				ntohs(daddr->in6_u.u6_addr16[0]),				ntohs(daddr->in6_u.u6_addr16[1]),				ntohs(daddr->in6_u.u6_addr16[2]),				ntohs(daddr->in6_u.u6_addr16[3]),				ntohs(daddr->in6_u.u6_addr16[4]),				ntohs(daddr->in6_u.u6_addr16[5]),				ntohs(daddr->in6_u.u6_addr16[6]),				ntohs(daddr->in6_u.u6_addr16[7]));			goto discard_it;		}	default:		/* CHECKSUM_UNNECESSARY */	};	/*	 *	length of original packet carried in skb	 */	ulen = skb->tail - (unsigned char *) (hdr + 1);	type = hdr->icmp6_type;	if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)		(&icmpv6_statistics.Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;	else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)		(&icmpv6_statistics.Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;	switch (type) {	case ICMPV6_ECHO_REQUEST:		icmpv6_echo_reply(skb);		break;	case ICMPV6_ECHO_REPLY:		/* we coulnd't care less */		break;	case ICMPV6_PKT_TOOBIG:		/* BUGGG_FUTURE: if packet contains rthdr, we cannot update		   standard destination cache. Seems, only "advanced"		   destination cache will allow to solve this problem		   --ANK (980726)		 */		orig_hdr = (struct ipv6hdr *) (hdr + 1);		if (ulen >= sizeof(struct ipv6hdr))			rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,					   ntohl(hdr->icmp6_mtu));		/*		 *	Drop through to notify		 */	case ICMPV6_DEST_UNREACH:	case ICMPV6_TIME_EXCEED:	case ICMPV6_PARAMPROB:		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu,			      (char *) (hdr + 1), ulen);		break;	case NDISC_ROUTER_SOLICITATION:	case NDISC_ROUTER_ADVERTISEMENT:	case NDISC_NEIGHBOUR_SOLICITATION:	case NDISC_NEIGHBOUR_ADVERTISEMENT:	case NDISC_REDIRECT:		ndisc_rcv(skb, len);		break;	case ICMPV6_MGM_QUERY:		igmp6_event_query(skb, hdr, len);		break;	case ICMPV6_MGM_REPORT:		igmp6_event_report(skb, hdr, len);		break;	case ICMPV6_MGM_REDUCTION:		break;	default:		if (net_ratelimit())			printk(KERN_DEBUG "icmpv6: msg of unkown type\n");				/* informational */		if (type & 0x80)			break;		/* 		 * error of unkown type. 		 * must pass to upper level 		 */		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu,			      (char *) (hdr + 1), ulen);	};	kfree_skb(skb);	return 0;discard_it:	icmpv6_statistics.Icmp6InErrors++;	kfree_skb(skb);	return 0;}int __init icmpv6_init(struct net_proto_family *ops){	struct sock *sk;	int err;	icmpv6_socket = sock_alloc();	if (icmpv6_socket == NULL) {		printk(KERN_ERR		       "Failed to create the ICMP6 control socket.\n");		return -1;	}	icmpv6_socket->inode->i_uid = 0;	icmpv6_socket->inode->i_gid = 0;	icmpv6_socket->type = SOCK_RAW;	if ((err = ops->create(icmpv6_socket, IPPROTO_ICMPV6)) < 0) {		printk(KERN_ERR		       "Failed to initialize the ICMP6 control socket (err %d).\n",		       err);		sock_release(icmpv6_socket);		icmpv6_socket = NULL; /* for safety */		return err;	}	sk = icmpv6_socket->sk;	sk->allocation = GFP_ATOMIC;	sk->num = 256;			/* Don't receive any data */	inet6_add_protocol(&icmpv6_protocol);	return 0;}void icmpv6_cleanup(void){	sock_release(icmpv6_socket);	icmpv6_socket = NULL; /* For safety. */	inet6_del_protocol(&icmpv6_protocol);}static struct icmp6_err {	int err;	int fatal;} tab_unreach[] = {	{ ENETUNREACH,	0},	/* NOROUTE		*/	{ EACCES,	1},	/* ADM_PROHIBITED	*/	{ EHOSTUNREACH,	0},	/* Was NOT_NEIGHBOUR, now reserved */	{ EHOSTUNREACH,	0},	/* ADDR_UNREACH		*/	{ ECONNREFUSED,	1},	/* PORT_UNREACH		*/};int icmpv6_err_convert(int type, int code, int *err){	int fatal = 0;	*err = EPROTO;	switch (type) {	case ICMPV6_DEST_UNREACH:		fatal = 1;		if (code <= ICMPV6_PORT_UNREACH) {			*err  = tab_unreach[code].err;			fatal = tab_unreach[code].fatal;		}		break;	case ICMPV6_PKT_TOOBIG:		*err = EMSGSIZE;		break;			case ICMPV6_PARAMPROB:		*err = EPROTO;		fatal = 1;		break;	case ICMPV6_TIME_EXCEED:		*err = EHOSTUNREACH;		break;	};	return fatal;}

⌨️ 快捷键说明

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