📄 myarp.c
字号:
#define MYIN_DEV_ARP_IGNORE(in_dev) \ (max(myipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))#define MYIN_DEV_ARPFILTER(in_dev) \ (myipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)#define MYIN_DEV_ARP_ANNOUNCE(in_dev) \ (max(myipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))static int myarp_ignore(struct in_device *in_dev, struct net_device *dev, u32 sip, u32 tip){ int scope; switch( MYIN_DEV_ARP_IGNORE(in_dev) ){ case 0: return 0; case 1: sip = 0; scope = RT_SCOPE_HOST; break; case 2: scope = RT_SCOPE_HOST; break; case 3: sip = 0; scope = RT_SCOPE_LINK; dev = NULL; break; case 4: case 5: case 6: case 7: return 0; case 8: return 1; default: return 0; } return !myinet_confirm_addr( dev, sip, tip, scope );}static void myarp_solicit(struct neighbour *neigh, struct sk_buff *skb){ u32 saddr = 0; u8 *dst_ha = NULL; struct net_device *dev = neigh->dev; u32 target = *(u32*)neigh->primary_key; int probes = atomic_read(&neigh->probes); struct in_device *in_dev = in_dev_get(dev); if (!in_dev) return; switch (MYIN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: if( skb && myinet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL ) saddr = skb->nh.iph->saddr; break; case 1: if (!skb) break; saddr = skb->nh.iph->saddr; if( myinet_addr_type(saddr) == RTN_LOCAL ){ if( myinet_addr_onlink(in_dev, target, saddr) ) break; } saddr = 0; break; case 2: break; } if (in_dev) in_dev_put(in_dev); if (!saddr) saddr = myinet_select_addr(dev, target, RT_SCOPE_LINK); if ((probes -= neigh->parms->ucast_probes) < 0) { if (!(neigh->nud_state&NUD_VALID)) printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); dst_ha = neigh->ha; read_lock_bh(&neigh->lock); } else if ((probes -= neigh->parms->app_probes) < 0) {#ifdef CONFIG_ARPD neigh_app_ns(neigh);#endif return; } myarp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, dst_ha, dev->dev_addr, NULL); if (dst_ha) read_unlock_bh(&neigh->lock);}static void myarp_error_report(struct neighbour *neigh, struct sk_buff *skb){}static struct neigh_ops myarp_generic_ops = { .family = MY_AF_INET, .solicit = myarp_solicit, .error_report = myarp_error_report, .output = neigh_resolve_output, .connected_output = neigh_connected_output, .hh_output = dev_queue_xmit, .queue_xmit = dev_queue_xmit,};static struct neigh_ops myarp_hh_ops = { .family = MY_AF_INET, .solicit = myarp_solicit, .error_report = myarp_error_report, .output = neigh_resolve_output, .connected_output = neigh_resolve_output, .hh_output = dev_queue_xmit, .queue_xmit = dev_queue_xmit,};struct neigh_ops myarp_broken_ops = { .family = MY_AF_INET, .solicit = myarp_solicit, .error_report = myarp_error_report, .output = neigh_compat_output, .connected_output = neigh_compat_output, .hh_output = dev_queue_xmit, .queue_xmit = dev_queue_xmit,};static struct neigh_ops myarp_direct_ops = { .family = MY_AF_INET, .output = dev_queue_xmit, .connected_output = dev_queue_xmit, .hh_output = dev_queue_xmit, .queue_xmit = dev_queue_xmit,};int myarp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir){ switch (dev->type) { case ARPHRD_ETHER: case ARPHRD_FDDI: case ARPHRD_IEEE802: ip_eth_mc_map(addr, haddr); return 0; case ARPHRD_IEEE802_TR: ip_tr_mc_map(addr, haddr); return 0; case ARPHRD_INFINIBAND: ip_ib_mc_map(addr, haddr); return 0; default: if (dir) { memcpy(haddr, dev->broadcast, dev->addr_len); return 0; } } return -EINVAL;}static u32 myarp_hash(const void *pkey, const struct net_device *dev){ return jhash_2words(*(u32 *)pkey, dev->ifindex, myarp_tbl.hash_rnd);}static int myarp_constructor(struct neighbour *neigh){ u32 addr = *(u32*)neigh->primary_key; struct net_device *dev = neigh->dev; struct in_device *in_dev; struct neigh_parms *parms; neigh->type = myinet_addr_type(addr); rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (in_dev == NULL) { rcu_read_unlock(); return -EINVAL; } parms = in_dev->arp_parms; __neigh_parms_put(neigh->parms); neigh->parms = neigh_parms_clone(parms); rcu_read_unlock(); if (dev->hard_header == NULL) { neigh->nud_state = NUD_NOARP; neigh->ops = &myarp_direct_ops; neigh->output = neigh->ops->queue_xmit; }else{ switch (dev->type) { default: break; case ARPHRD_ROSE: #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) case ARPHRD_AX25:#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) case ARPHRD_NETROM:#endif neigh->ops = &myarp_broken_ops; neigh->output = neigh->ops->output; return 0;#endif ;} if( neigh->type == RTN_MULTICAST ){ neigh->nud_state = NUD_NOARP; myarp_mc_map(addr, neigh->ha, dev, 1); }else if( dev->flags & (IFF_NOARP|IFF_LOOPBACK) ){ neigh->nud_state = NUD_NOARP; memcpy(neigh->ha, dev->dev_addr, dev->addr_len); }else if( neigh->type == RTN_BROADCAST || dev->flags&IFF_POINTOPOINT ){ neigh->nud_state = NUD_NOARP; memcpy(neigh->ha, dev->broadcast, dev->addr_len); } if (dev->hard_header_cache){ printk(KERN_INFO "arp hh ops!\n"); neigh->ops = &myarp_hh_ops; }else{ printk(KERN_INFO "arp generic ops!\n"); neigh->ops = &myarp_generic_ops; } if( neigh->nud_state & NUD_VALID ){ printk(KERN_INFO "connected output!\n"); neigh->output = neigh->ops->connected_output; }else neigh->output = neigh->ops->output; printk(KERN_INFO "output: %p\n", neigh->output); } return 0;}static void myparp_redo(struct sk_buff *skb){}struct neigh_table myarp_tbl = { .family = MY_AF_INET, .entry_size = sizeof(struct neighbour) + 4, .key_len = 4, .hash = myarp_hash, .constructor = myarp_constructor, .proxy_redo = myparp_redo, .id = "myarp_cache", .parms = { .tbl = &myarp_tbl, .base_reachable_time = 30 * HZ, .retrans_time = 1 * HZ, .gc_staletime = 60 * HZ, .reachable_time = 30 * HZ, .delay_probe_time = 5 * HZ, .queue_len = 3, .ucast_probes = 3, .mcast_probes = 3, .anycast_delay = 1 * HZ, .proxy_delay = (8 * HZ) / 10, .proxy_qlen = 64, .locktime = 1 * HZ, }, .gc_interval = 30 * HZ, .gc_thresh1 = 128, .gc_thresh2 = 512, .gc_thresh3 = 1024,};int myarp_bind_neighbour(struct dst_entry *dst){ struct net_device *dev = dst->dev; struct neighbour *n = dst->neighbour; if (dev == NULL) return -EINVAL; if (n == NULL) { u32 nexthop = ((struct rtable*)dst)->rt_gateway; printk(KERN_INFO "nexthop: %u.%u.%u.%u\n", NIPQUAD(nexthop) ); if( dev->flags & (IFF_LOOPBACK|IFF_POINTOPOINT) ) nexthop = 0; n = __neigh_lookup_errno( &myarp_tbl, &nexthop, dev); if( IS_ERR(n) ) return PTR_ERR(n); printk(KERN_INFO "neighbour.parms: %p\n", n->parms ); printk(KERN_INFO "neighbour.used: %lu\n", n->used ); printk(KERN_INFO "neighbour.confirmed: %lu\n", n->confirmed ); printk(KERN_INFO "neighbour.updated: %lu\n", n->updated ); printk(KERN_INFO "neighbour.flags: %x\n", n->flags ); printk(KERN_INFO "neighbour.nud_state: %x\n", n->nud_state ); printk(KERN_INFO "neighbour.type: %d\n", n->type ); printk(KERN_INFO "neighbour.dead: %d\n", n->dead ); printk(KERN_INFO "neighbour.probes: %d\n", atomic_read( &(n->probes) ) ); printk(KERN_INFO "neighbour.ha: %x.%x.%x.%x.%x.%x\n", n->ha[0], n->ha[1], n->ha[2], n->ha[3], n->ha[4], n->ha[5] ); printk(KERN_INFO "neighbour.hh: %p\n", n->hh); printk(KERN_INFO "neighbour.refcnt: %d\n", atomic_read( &(n->refcnt) ) ); printk(KERN_INFO "neighbour.primary key: %u.%u.%u.%u\n", NIPQUAD(n->primary_key) ); dst->neighbour = n; } return 0;}struct sk_buff *myarp_create(int type, int ptype, u32 dest_ip, struct net_device *dev, u32 src_ip, unsigned char *dest_hw, unsigned char *src_hw, unsigned char *target_hw){ struct sk_buff *skb; struct arphdr *arp; unsigned char *arp_ptr; skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4) + LL_RESERVED_SPACE(dev), GFP_ATOMIC); if (skb == NULL) return NULL; skb_reserve(skb, LL_RESERVED_SPACE(dev)); skb->nh.raw = skb->data; arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4)); skb->dev = dev; skb->protocol = htons(ETH_P_ARP); if (src_hw == NULL) src_hw = dev->dev_addr; if (dest_hw == NULL) dest_hw = dev->broadcast; if (dev->hard_header && dev->hard_header(skb,dev,ptype,dest_hw,src_hw,skb->len) < 0) goto out; switch (dev->type) { default: arp->ar_hrd = htons(dev->type); arp->ar_pro = htons(ETH_P_IP); break;#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) case ARPHRD_AX25:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -