📄 netpoll.c
字号:
*/ 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, np->remote_mac, 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 *np; struct list_head *p; unsigned long flags; if (skb->dev->type != ARPHRD_ETHER) goto out; /* check if netpoll clients need ARP */ if (skb->protocol == __constant_htons(ETH_P_ARP) && atomic_read(&trapped)) { arp_reply(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; 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) < 0) goto out; spin_lock_irqsave(&rx_list_lock, flags); list_for_each(p, &rx_list) { np = list_entry(p, struct netpoll, rx_list); if (np->dev && np->dev != skb->dev) continue; if (np->local_ip && np->local_ip != ntohl(iph->daddr)) continue; if (np->remote_ip && np->remote_ip != ntohl(iph->saddr)) continue; if (np->local_port && np->local_port != ntohs(uh->dest)) continue; spin_unlock_irqrestore(&rx_list_lock, flags); if (np->rx_hook) np->rx_hook(np, ntohs(uh->source), (char *)(uh+1), ulen - sizeof(struct udphdr)); return 1; } spin_unlock_irqrestore(&rx_list_lock, flags);out: return atomic_read(&trapped);}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++; printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port); if(*cur != '/') { if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; *delim=0; np->local_ip=ntohl(in_aton(cur)); cur=delim; printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n", np->name, HIPQUAD(np->local_ip)); } 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++; printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name); 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++; printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port); /* dst ip */ if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; *delim=0; np->remote_ip=ntohl(in_aton(cur)); cur=delim+1; printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n", np->name, HIPQUAD(np->remote_ip)); 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); } printk(KERN_INFO "%s: remote ethernet address " "%02x:%02x:%02x:%02x:%02x:%02x\n", np->name, np->remote_mac[0], np->remote_mac[1], np->remote_mac[2], np->remote_mac[3], np->remote_mac[4], np->remote_mac[5]); 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; if (np->dev_name) ndev = dev_get_by_name(np->dev_name); if (!ndev) { printk(KERN_ERR "%s: %s doesn't exist, aborting.\n", np->name, np->dev_name); return -1; } if (!ndev->poll_controller) { printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", np->name, np->dev_name); goto release; } if (!(ndev->flags & IFF_UP)) { unsigned short oflags; unsigned long atmost, atleast; printk(KERN_INFO "%s: device %s not up yet, forcing it\n", np->name, np->dev_name); oflags = ndev->flags; rtnl_shlock(); if (dev_change_flags(ndev, oflags | IFF_UP) < 0) { printk(KERN_ERR "%s: failed to open %s\n", np->name, np->dev_name); rtnl_shunlock(); goto release; } rtnl_shunlock(); atleast = jiffies + HZ/10; atmost = jiffies + 10*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 (time_before(jiffies, atleast)) { printk(KERN_NOTICE "%s: carrier detect appears flaky," " waiting 10 seconds\n", np->name); while (time_before(jiffies, atmost)) cond_resched(); } } if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr) memcpy(np->local_mac, ndev->dev_addr, 6); if (!np->local_ip) { rcu_read_lock(); in_dev = __in_dev_get(ndev); if (!in_dev) { rcu_read_unlock(); printk(KERN_ERR "%s: no IP address for %s, aborting\n", np->name, np->dev_name); 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)); } np->dev = ndev; if(np->rx_hook) { unsigned long flags; np->dev->netpoll_rx = NETPOLL_RX_ENABLED; spin_lock_irqsave(&rx_list_lock, flags); list_add(&np->rx_list, &rx_list); spin_unlock_irqrestore(&rx_list_lock, flags); } return 0; release: dev_put(ndev); return -1;}void netpoll_cleanup(struct netpoll *np){ if (np->rx_hook) { unsigned long flags; spin_lock_irqsave(&rx_list_lock, flags); list_del(&np->rx_list); spin_unlock_irqrestore(&rx_list_lock, flags); } if (np->dev) np->dev->netpoll_rx = 0; 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_parse_options);EXPORT_SYMBOL(netpoll_setup);EXPORT_SYMBOL(netpoll_cleanup);EXPORT_SYMBOL(netpoll_send_skb);EXPORT_SYMBOL(netpoll_send_udp);EXPORT_SYMBOL(netpoll_poll);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -