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

📄 netpoll.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return;	skb_reset_network_header(send_skb);	arp = (struct arphdr *) skb_put(send_skb, size);	send_skb->dev = skb->dev;	send_skb->protocol = htons(ETH_P_ARP);	/* Fill the device header for the ARP frame */	if (dev_hard_header(send_skb, skb->dev, ptype,			    sha, np->local_mac,			    send_skb->len) < 0) {		kfree_skb(send_skb);		return;	}	/*	 * Fill out the arp protocol part.	 *	 * we only support ethernet device type,	 * which (according to RFC 1390) should always equal 1 (Ethernet).	 */	arp->ar_hrd = htons(np->dev->type);	arp->ar_pro = htons(ETH_P_IP);	arp->ar_hln = np->dev->addr_len;	arp->ar_pln = 4;	arp->ar_op = htons(type);	arp_ptr=(unsigned char *)(arp + 1);	memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);	arp_ptr += np->dev->addr_len;	memcpy(arp_ptr, &tip, 4);	arp_ptr += 4;	memcpy(arp_ptr, sha, np->dev->addr_len);	arp_ptr += np->dev->addr_len;	memcpy(arp_ptr, &sip, 4);	netpoll_send_skb(np, send_skb);}int __netpoll_rx(struct sk_buff *skb){	int proto, len, ulen;	struct iphdr *iph;	struct udphdr *uh;	struct netpoll_info *npi = skb->dev->npinfo;	struct netpoll *np = npi->rx_np;	if (!np)		goto out;	if (skb->dev->type != ARPHRD_ETHER)		goto out;	/* check if netpoll clients need ARP */	if (skb->protocol == htons(ETH_P_ARP) &&	    atomic_read(&trapped)) {		skb_queue_tail(&npi->arp_tx, skb);		return 1;	}	proto = ntohs(eth_hdr(skb)->h_proto);	if (proto != ETH_P_IP)		goto out;	if (skb->pkt_type == PACKET_OTHERHOST)		goto out;	if (skb_shared(skb))		goto out;	iph = (struct iphdr *)skb->data;	if (!pskb_may_pull(skb, sizeof(struct iphdr)))		goto out;	if (iph->ihl < 5 || iph->version != 4)		goto out;	if (!pskb_may_pull(skb, iph->ihl*4))		goto out;	if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)		goto out;	len = ntohs(iph->tot_len);	if (skb->len < len || len < iph->ihl*4)		goto out;	/*	 * Our transport medium may have padded the buffer out.	 * Now We trim to the true length of the frame.	 */	if (pskb_trim_rcsum(skb, len))		goto out;	if (iph->protocol != IPPROTO_UDP)		goto out;	len -= iph->ihl*4;	uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);	ulen = ntohs(uh->len);	if (ulen != len)		goto out;	if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr))		goto out;	if (np->local_ip && np->local_ip != ntohl(iph->daddr))		goto out;	if (np->remote_ip && np->remote_ip != ntohl(iph->saddr))		goto out;	if (np->local_port && np->local_port != ntohs(uh->dest))		goto out;	np->rx_hook(np, ntohs(uh->source),		    (char *)(uh+1),		    ulen - sizeof(struct udphdr));	kfree_skb(skb);	return 1;out:	if (atomic_read(&trapped)) {		kfree_skb(skb);		return 1;	}	return 0;}void netpoll_print_options(struct netpoll *np){	DECLARE_MAC_BUF(mac);	printk(KERN_INFO "%s: local port %d\n",			 np->name, np->local_port);	printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",			 np->name, HIPQUAD(np->local_ip));	printk(KERN_INFO "%s: interface %s\n",			 np->name, np->dev_name);	printk(KERN_INFO "%s: remote port %d\n",			 np->name, np->remote_port);	printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",			 np->name, HIPQUAD(np->remote_ip));	printk(KERN_INFO "%s: remote ethernet address %s\n",	                 np->name, print_mac(mac, np->remote_mac));}int netpoll_parse_options(struct netpoll *np, char *opt){	char *cur=opt, *delim;	if (*cur != '@') {		if ((delim = strchr(cur, '@')) == NULL)			goto parse_failed;		*delim = 0;		np->local_port = simple_strtol(cur, NULL, 10);		cur = delim;	}	cur++;	if (*cur != '/') {		if ((delim = strchr(cur, '/')) == NULL)			goto parse_failed;		*delim = 0;		np->local_ip = ntohl(in_aton(cur));		cur = delim;	}	cur++;	if (*cur != ',') {		/* parse out dev name */		if ((delim = strchr(cur, ',')) == NULL)			goto parse_failed;		*delim = 0;		strlcpy(np->dev_name, cur, sizeof(np->dev_name));		cur = delim;	}	cur++;	if (*cur != '@') {		/* dst port */		if ((delim = strchr(cur, '@')) == NULL)			goto parse_failed;		*delim = 0;		np->remote_port = simple_strtol(cur, NULL, 10);		cur = delim;	}	cur++;	/* dst ip */	if ((delim = strchr(cur, '/')) == NULL)		goto parse_failed;	*delim = 0;	np->remote_ip = ntohl(in_aton(cur));	cur = delim + 1;	if (*cur != 0) {		/* MAC address */		if ((delim = strchr(cur, ':')) == NULL)			goto parse_failed;		*delim = 0;		np->remote_mac[0] = simple_strtol(cur, NULL, 16);		cur = delim + 1;		if ((delim = strchr(cur, ':')) == NULL)			goto parse_failed;		*delim = 0;		np->remote_mac[1] = simple_strtol(cur, NULL, 16);		cur = delim + 1;		if ((delim = strchr(cur, ':')) == NULL)			goto parse_failed;		*delim = 0;		np->remote_mac[2] = simple_strtol(cur, NULL, 16);		cur = delim + 1;		if ((delim = strchr(cur, ':')) == NULL)			goto parse_failed;		*delim = 0;		np->remote_mac[3] = simple_strtol(cur, NULL, 16);		cur = delim + 1;		if ((delim = strchr(cur, ':')) == NULL)			goto parse_failed;		*delim = 0;		np->remote_mac[4] = simple_strtol(cur, NULL, 16);		cur = delim + 1;		np->remote_mac[5] = simple_strtol(cur, NULL, 16);	}	netpoll_print_options(np);	return 0; parse_failed:	printk(KERN_INFO "%s: couldn't parse config at %s!\n",	       np->name, cur);	return -1;}int netpoll_setup(struct netpoll *np){	struct net_device *ndev = NULL;	struct in_device *in_dev;	struct netpoll_info *npinfo;	unsigned long flags;	int err;	if (np->dev_name)		ndev = dev_get_by_name(&init_net, np->dev_name);	if (!ndev) {		printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",		       np->name, np->dev_name);		return -ENODEV;	}	np->dev = ndev;	if (!ndev->npinfo) {		npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);		if (!npinfo) {			err = -ENOMEM;			goto release;		}		npinfo->rx_flags = 0;		npinfo->rx_np = NULL;		spin_lock_init(&npinfo->rx_lock);		skb_queue_head_init(&npinfo->arp_tx);		skb_queue_head_init(&npinfo->txq);		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);		atomic_set(&npinfo->refcnt, 1);	} else {		npinfo = ndev->npinfo;		atomic_inc(&npinfo->refcnt);	}	if (!ndev->poll_controller) {		printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",		       np->name, np->dev_name);		err = -ENOTSUPP;		goto release;	}	if (!netif_running(ndev)) {		unsigned long atmost, atleast;		printk(KERN_INFO "%s: device %s not up yet, forcing it\n",		       np->name, np->dev_name);		rtnl_lock();		err = dev_open(ndev);		rtnl_unlock();		if (err) {			printk(KERN_ERR "%s: failed to open %s\n",			       np->name, ndev->name);			goto release;		}		atleast = jiffies + HZ/10;		atmost = jiffies + 4*HZ;		while (!netif_carrier_ok(ndev)) {			if (time_after(jiffies, atmost)) {				printk(KERN_NOTICE				       "%s: timeout waiting for carrier\n",				       np->name);				break;			}			cond_resched();		}		/* If carrier appears to come up instantly, we don't		 * trust it and pause so that we don't pump all our		 * queued console messages into the bitbucket.		 */		if (time_before(jiffies, atleast)) {			printk(KERN_NOTICE "%s: carrier detect appears"			       " untrustworthy, waiting 4 seconds\n",			       np->name);			msleep(4000);		}	}	if (is_zero_ether_addr(np->local_mac) && ndev->dev_addr)		memcpy(np->local_mac, ndev->dev_addr, 6);	if (!np->local_ip) {		rcu_read_lock();		in_dev = __in_dev_get_rcu(ndev);		if (!in_dev || !in_dev->ifa_list) {			rcu_read_unlock();			printk(KERN_ERR "%s: no IP address for %s, aborting\n",			       np->name, np->dev_name);			err = -EDESTADDRREQ;			goto release;		}		np->local_ip = ntohl(in_dev->ifa_list->ifa_local);		rcu_read_unlock();		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",		       np->name, HIPQUAD(np->local_ip));	}	if (np->rx_hook) {		spin_lock_irqsave(&npinfo->rx_lock, flags);		npinfo->rx_flags |= NETPOLL_RX_ENABLED;		npinfo->rx_np = np;		spin_unlock_irqrestore(&npinfo->rx_lock, flags);	}	/* fill up the skb queue */	refill_skbs();	/* last thing to do is link it to the net device structure */	ndev->npinfo = npinfo;	/* avoid racing with NAPI reading npinfo */	synchronize_rcu();	return 0; release:	if (!ndev->npinfo)		kfree(npinfo);	np->dev = NULL;	dev_put(ndev);	return err;}static int __init netpoll_init(void){	skb_queue_head_init(&skb_pool);	return 0;}core_initcall(netpoll_init);void netpoll_cleanup(struct netpoll *np){	struct netpoll_info *npinfo;	unsigned long flags;	if (np->dev) {		npinfo = np->dev->npinfo;		if (npinfo) {			if (npinfo->rx_np == np) {				spin_lock_irqsave(&npinfo->rx_lock, flags);				npinfo->rx_np = NULL;				npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;				spin_unlock_irqrestore(&npinfo->rx_lock, flags);			}			if (atomic_dec_and_test(&npinfo->refcnt)) {				skb_queue_purge(&npinfo->arp_tx);				skb_queue_purge(&npinfo->txq);				cancel_rearming_delayed_work(&npinfo->tx_work);				/* clean after last, unfinished work */				if (!skb_queue_empty(&npinfo->txq)) {					struct sk_buff *skb;					skb = __skb_dequeue(&npinfo->txq);					kfree_skb(skb);				}				kfree(npinfo);				np->dev->npinfo = NULL;			}		}		dev_put(np->dev);	}	np->dev = NULL;}int netpoll_trap(void){	return atomic_read(&trapped);}void netpoll_set_trap(int trap){	if (trap)		atomic_inc(&trapped);	else		atomic_dec(&trapped);}EXPORT_SYMBOL(netpoll_set_trap);EXPORT_SYMBOL(netpoll_trap);EXPORT_SYMBOL(netpoll_print_options);EXPORT_SYMBOL(netpoll_parse_options);EXPORT_SYMBOL(netpoll_setup);EXPORT_SYMBOL(netpoll_cleanup);EXPORT_SYMBOL(netpoll_send_udp);EXPORT_SYMBOL(netpoll_poll);

⌨️ 快捷键说明

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