📄 arp.c
字号:
/* arp.c * linqianghe@163.com * 2006-09-26 */#include "neighbour.h"#include "dev.h"#include "dev_dummy.h"#include "af_inet.h"#include "arp.h"#include "log.h"#include "route.h"#include <linux/inetdevice.h>#include <linux/if_arp.h>#include <linux/rtnetlink.h>#include <linux/jhash.h>extern struct neigh_table myarp_tbl;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); PR_DEBUG( "%s, %u.%u.%u.%u %d, %p\n", dev->name, NIPQUAD(target), probes, in_dev); if (!in_dev) return; switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: if (skb && inet_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 (inet_addr_type(saddr) == RTN_LOCAL) { if (inet_addr_onlink(in_dev, target, saddr)) break; } saddr = 0; break; case 2: break; }*//* if (in_dev) in_dev_put(in_dev); if( !saddr ) saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);*/}static void myarp_error_report(struct neighbour *neigh, struct sk_buff *skb){ PR_DEBUG( "myarp_error_report!\n" ); dst_link_failure( skb ); kfree_skb(skb);}static struct neigh_ops myarp_dummy_ops = { .family = MY_AF_INET, .solicit = myarp_solicit, .error_report = myarp_error_report, .output = myneigh_resolve_output, .connected_output = myneigh_connected_output, .hh_output = dev_queue_xmit_dummy, .queue_xmit = dev_queue_xmit_dummy,};static struct neigh_ops myarp_generic_ops = { .family = MY_AF_INET, .solicit = myarp_solicit, .error_report = myarp_error_report, .output = myneigh_resolve_output, .connected_output = myneigh_connected_output, .hh_output = mydev_queue_xmit, .queue_xmit = mydev_queue_xmit,};static struct neigh_ops myarp_hh_ops = { .family = MY_AF_INET, .solicit = myarp_solicit, .error_report = myarp_error_report, .output = myneigh_resolve_output, .connected_output = myneigh_resolve_output, .hh_output = mydev_queue_xmit, .queue_xmit = mydev_queue_xmit,};static struct neigh_ops myarp_direct_ops = { .family = MY_AF_INET, .output = mydev_queue_xmit, .connected_output = mydev_queue_xmit, .hh_output = mydev_queue_xmit, .queue_xmit = mydev_queue_xmit,};struct neigh_ops myarp_broken_ops = { .family = MY_AF_INET, .solicit = myarp_solicit, .error_report = myarp_error_report, .output = myneigh_compat_output, .connected_output = myneigh_compat_output, .hh_output = mydev_queue_xmit, .queue_xmit = mydev_queue_xmit,};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 = inet_addr_type(addr); neigh->type = RTN_UNICAST; neigh->ops = &myarp_dummy_ops; neigh->output = neigh->ops->output; return 0; //temp code FIXME rcu_read_lock(); in_dev = __in_dev_get_rcu( dev ); if( in_dev == NULL ){ PR_ERR( "the in_dev is NULL\n" ); 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; //arp_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 ) neigh->ops = &myarp_hh_ops; else neigh->ops = &myarp_generic_ops; if( neigh->nud_state & NUD_VALID ) neigh->output = neigh->ops->connected_output; else neigh->output = neigh->ops->output; } return 0;}struct neigh_table tmp_tbl = { .family = MY_AF_INET, .entry_size = sizeof(struct neighbour) + 4, .key_len = 4, .hash = myarp_hash, .constructor = myarp_constructor, //.proxy_redo = parp_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; PR_DEBUG( "bind a neighbour to a dst on device: %s!\n", dev->name ); if( dev == NULL ) return -EINVAL; if( n == NULL ){ u32 nexthop = ((struct rtable*)dst)->rt_gateway; //if( dev->flags & ( IFF_LOOPBACK | IFF_POINTOPOINT ) ) // nexthop = 0; n = __myneigh_lookup_errno( &myarp_tbl, &nexthop, dev ); if( IS_ERR(n) ) return PTR_ERR(n); PR_DEEP_DEBUG( "bind a neighbour %p successed!\n", n ); dst->neighbour = n; } return 0;}static int myarp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr){ //struct net_device *dev = ptr; switch( event ){/* case NETDEV_CHANGEADDR: neigh_changeaddr(&arp_tbl, dev); rt_cache_flush(0); break;*/ default: break; } return NOTIFY_DONE;}static struct notifier_block myarp_netdev_notifier = { .notifier_call = myarp_netdev_event,};int myarp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev){ return 0;}static struct packet_type myarp_packet_type = { .type = __constant_htons(ETH_P_ARP), .func = myarp_rcv,};void __init myarp_init(void){ memcpy( &myarp_tbl, &tmp_tbl, sizeof(myarp_tbl) ); myneigh_table_init( &myarp_tbl ); mydev_add_pack( &myarp_packet_type ); //arp_proc_init();#ifdef CONFIG_SYSCTL //neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, // NET_IPV4_NEIGH, "ipv4", NULL, NULL);#endif register_netdevice_notifier( &myarp_netdev_notifier );}void __exit myarp_exit(void){ unregister_netdevice_notifier( &myarp_netdev_notifier ); mydev_remove_pack( &myarp_packet_type ); myneigh_table_destroy( &myarp_tbl );}EXPORT_SYMBOL_GPL( myarp_bind_neighbour );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -