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

📄 neighbour.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	__skb_queue_tail(&tbl->proxy_queue, skb);	add_timer(&tbl->proxy_timer);}struct neigh_parms *neigh_parms_alloc(struct device *dev, struct neigh_table *tbl){	struct neigh_parms *p;	p = kmalloc(sizeof(*p), GFP_KERNEL);	if (p) {		memcpy(p, &tbl->parms, sizeof(*p));		p->tbl = tbl;		p->reachable_time = neigh_rand_reach_time(p->base_reachable_time);		if (dev && dev->neigh_setup) {			if (dev->neigh_setup(dev, p)) {				kfree(p);				return NULL;			}		}		p->next = tbl->parms.next;		tbl->parms.next = p;	}	return p;}void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms){	struct neigh_parms **p;		if (parms == NULL || parms == &tbl->parms)		return;	for (p = &tbl->parms.next; *p; p = &(*p)->next) {		if (*p == parms) {			*p = parms->next;			synchronize_bh();#ifdef CONFIG_SYSCTL			neigh_sysctl_unregister(parms);#endif			kfree(parms);			return;		}	}	NEIGH_PRINTK1("neigh_release_parms: not found\n");}void neigh_table_init(struct neigh_table *tbl){	unsigned long now = jiffies;	tbl->parms.reachable_time = neigh_rand_reach_time(tbl->parms.base_reachable_time);	init_timer(&tbl->gc_timer);	tbl->gc_timer.data = (unsigned long)tbl;	tbl->gc_timer.function = neigh_periodic_timer;	tbl->gc_timer.expires = now + tbl->gc_interval + tbl->parms.reachable_time;	add_timer(&tbl->gc_timer);	init_timer(&tbl->proxy_timer);	tbl->proxy_timer.data = (unsigned long)tbl;	tbl->proxy_timer.function = neigh_proxy_process;	skb_queue_head_init(&tbl->proxy_queue);	tbl->last_flush = now;	tbl->last_rand = now + tbl->parms.reachable_time*20;	tbl->next = neigh_tables;	neigh_tables = tbl;}int neigh_table_clear(struct neigh_table *tbl){	struct neigh_table **tp;	start_bh_atomic();	del_timer(&tbl->gc_timer);	del_timer(&tbl->proxy_timer);	skb_queue_purge(&tbl->proxy_queue);	neigh_ifdown(tbl, NULL);	end_bh_atomic();	if (tbl->entries)		printk(KERN_CRIT "neighbour leakage\n");	for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {		if (*tp == tbl) {			*tp = tbl->next;			synchronize_bh();			break;		}	}#ifdef CONFIG_SYSCTL	neigh_sysctl_unregister(&tbl->parms);#endif	return 0;}#ifdef CONFIG_RTNETLINKint neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){	struct ndmsg *ndm = NLMSG_DATA(nlh);	struct rtattr **nda = arg;	struct neigh_table *tbl;	struct device *dev = NULL;	if (ndm->ndm_ifindex) {		if ((dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)			return -ENODEV;	}	for (tbl=neigh_tables; tbl; tbl = tbl->next) {		int err = 0;		struct neighbour *n;		if (tbl->family != ndm->ndm_family)			continue;		if (nda[NDA_DST-1] == NULL ||		    nda[NDA_DST-1]->rta_len != RTA_LENGTH(tbl->key_len))			return -EINVAL;		if (ndm->ndm_flags&NTF_PROXY)			return pneigh_delete(tbl, RTA_DATA(nda[NDA_DST-1]), dev);		if (dev == NULL)			return -EINVAL;		start_bh_atomic();		n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 0);		if (n) {			err = neigh_update(n, NULL, NUD_FAILED, 1, 0);			neigh_release(n);		}		end_bh_atomic();		return err;	}	return -EADDRNOTAVAIL;}int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){	struct ndmsg *ndm = NLMSG_DATA(nlh);	struct rtattr **nda = arg;	struct neigh_table *tbl;	struct device *dev = NULL;	if (ndm->ndm_ifindex) {		if ((dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)			return -ENODEV;	}	for (tbl=neigh_tables; tbl; tbl = tbl->next) {		int err = 0;		struct neighbour *n;		if (tbl->family != ndm->ndm_family)			continue;		if (nda[NDA_DST-1] == NULL ||		    nda[NDA_DST-1]->rta_len != RTA_LENGTH(tbl->key_len))			return -EINVAL;		if (ndm->ndm_flags&NTF_PROXY) {			if (pneigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 1))				return 0;			return -ENOBUFS;		}		if (dev == NULL)			return -EINVAL;		if (nda[NDA_LLADDR-1] != NULL &&		    nda[NDA_LLADDR-1]->rta_len != RTA_LENGTH(dev->addr_len))			return -EINVAL;		start_bh_atomic();		n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 0);		if (n) {			if (nlh->nlmsg_flags&NLM_F_EXCL)				err = -EEXIST;		} else if (!(nlh->nlmsg_flags&NLM_F_CREATE))			err = -ENOENT;		else {			n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 1);			if (n == NULL)				err = -ENOBUFS;		}		if (err == 0) {			err = neigh_update(n, nda[NDA_LLADDR-1] ? RTA_DATA(nda[NDA_LLADDR-1]) : NULL,					   ndm->ndm_state,					   nlh->nlmsg_flags&NLM_F_REPLACE, 0);		}		if (n)			neigh_release(n);		end_bh_atomic();		return err;	}	return -EADDRNOTAVAIL;}static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,			   u32 pid, u32 seq, int event){	unsigned long now = jiffies;	struct ndmsg *ndm;	struct nlmsghdr  *nlh;	unsigned char	 *b = skb->tail;	struct nda_cacheinfo ci;	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ndm));	ndm = NLMSG_DATA(nlh);	ndm->ndm_family = n->ops->family;	ndm->ndm_flags = n->flags;	ndm->ndm_type = n->type;	ndm->ndm_state = n->nud_state;	ndm->ndm_ifindex = n->dev->ifindex;	RTA_PUT(skb, NDA_DST, n->tbl->key_len, n->primary_key);	if (n->nud_state&NUD_VALID)		RTA_PUT(skb, NDA_LLADDR, n->dev->addr_len, n->ha);	ci.ndm_used = now - n->used;	ci.ndm_confirmed = now - n->confirmed;	ci.ndm_updated = now - n->updated;	ci.ndm_refcnt = atomic_read(&n->refcnt);	RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);	nlh->nlmsg_len = skb->tail - b;	return skb->len;nlmsg_failure:rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, struct netlink_callback *cb){	struct neighbour *n;	int h, s_h;	int idx, s_idx;	s_h = cb->args[1];	s_idx = idx = cb->args[2];	for (h=0; h <= NEIGH_HASHMASK; h++) {		if (h < s_h) continue;		if (h > s_h)			s_idx = 0;		start_bh_atomic();		for (n = tbl->hash_buckets[h], idx = 0; n;		     n = n->next, idx++) {			if (idx < s_idx)				continue;			if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,					    cb->nlh->nlmsg_seq, RTM_NEWNEIGH) <= 0) {				end_bh_atomic();				cb->args[1] = h;				cb->args[2] = idx;				return -1;			}		}		end_bh_atomic();	}	cb->args[1] = h;	cb->args[2] = idx;	return skb->len;}int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb){	int t;	int s_t;	struct neigh_table *tbl;	int family = ((struct rtgenmsg*)NLMSG_DATA(cb->nlh))->rtgen_family;	s_t = cb->args[0];	for (tbl=neigh_tables, t=0; tbl; tbl = tbl->next, t++) {		if (t < s_t) continue;		if (family && tbl->family != family)			continue;		if (t > s_t)			memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));		if (neigh_dump_table(tbl, skb, cb) < 0) 			break;	}	cb->args[0] = t;	return skb->len;}#ifdef CONFIG_ARPDvoid neigh_app_ns(struct neighbour *n){	struct sk_buff *skb;	struct nlmsghdr  *nlh;	int size = NLMSG_SPACE(sizeof(struct ndmsg)+256);	skb = alloc_skb(size, GFP_ATOMIC);	if (!skb)		return;	if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH) < 0) {		kfree_skb(skb);		return;	}	nlh = (struct nlmsghdr*)skb->data;	nlh->nlmsg_flags = NLM_F_REQUEST;	NETLINK_CB(skb).dst_groups = RTMGRP_NEIGH;	netlink_broadcast(rtnl, skb, 0, RTMGRP_NEIGH, GFP_ATOMIC);}static void neigh_app_notify(struct neighbour *n){	struct sk_buff *skb;	struct nlmsghdr  *nlh;	int size = NLMSG_SPACE(sizeof(struct ndmsg)+256);	skb = alloc_skb(size, GFP_ATOMIC);	if (!skb)		return;	if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH) < 0) {		kfree_skb(skb);		return;	}	nlh = (struct nlmsghdr*)skb->data;	NETLINK_CB(skb).dst_groups = RTMGRP_NEIGH;	netlink_broadcast(rtnl, skb, 0, RTMGRP_NEIGH, GFP_ATOMIC);}#endif#endif#ifdef CONFIG_SYSCTLstruct neigh_sysctl_table{	struct ctl_table_header *sysctl_header;	ctl_table neigh_vars[17];	ctl_table neigh_dev[2];	ctl_table neigh_neigh_dir[2];	ctl_table neigh_proto_dir[2];	ctl_table neigh_root_dir[2];} neigh_sysctl_template = {	NULL,        {{NET_NEIGH_MCAST_SOLICIT, "mcast_solicit",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_UCAST_SOLICIT, "ucast_solicit",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_APP_SOLICIT, "app_solicit",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_RETRANS_TIME, "retrans_time",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_REACHABLE_TIME, "base_reachable_time",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies},	{NET_NEIGH_DELAY_PROBE_TIME, "delay_first_probe_time",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies},	{NET_NEIGH_GC_STALE_TIME, "gc_stale_time",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies},	{NET_NEIGH_UNRES_QLEN, "unres_qlen",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_PROXY_QLEN, "proxy_qlen",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_ANYCAST_DELAY, "anycast_delay",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_PROXY_DELAY, "proxy_delay",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_LOCKTIME, "locktime",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_GC_INTERVAL, "gc_interval",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies},	{NET_NEIGH_GC_THRESH1, "gc_thresh1",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_GC_THRESH2, "gc_thresh2",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_NEIGH_GC_THRESH3, "gc_thresh3",         NULL, sizeof(int), 0644, NULL,         &proc_dointvec},	 {0}},	{{NET_PROTO_CONF_DEFAULT, "default", NULL, 0, 0555, NULL},{0}},	{{0, "neigh", NULL, 0, 0555, NULL},{0}},	{{0, NULL, NULL, 0, 0555, NULL},{0}},	{{CTL_NET, "net", NULL, 0, 0555, NULL},{0}}};int neigh_sysctl_register(struct device *dev, struct neigh_parms *p,			  int p_id, int pdev_id, char *p_name){	struct neigh_sysctl_table *t;	t = kmalloc(sizeof(*t), GFP_KERNEL);	if (t == NULL)		return -ENOBUFS;	memcpy(t, &neigh_sysctl_template, sizeof(*t));	t->neigh_vars[0].data = &p->mcast_probes;	t->neigh_vars[1].data = &p->ucast_probes;	t->neigh_vars[2].data = &p->app_probes;	t->neigh_vars[3].data = &p->retrans_time;	t->neigh_vars[4].data = &p->base_reachable_time;	t->neigh_vars[5].data = &p->delay_probe_time;	t->neigh_vars[6].data = &p->gc_staletime;	t->neigh_vars[7].data = &p->queue_len;	t->neigh_vars[8].data = &p->proxy_qlen;	t->neigh_vars[9].data = &p->anycast_delay;	t->neigh_vars[10].data = &p->proxy_delay;	t->neigh_vars[11].data = &p->locktime;	if (dev) {		t->neigh_dev[0].procname = dev->name;		t->neigh_dev[0].ctl_name = dev->ifindex;		memset(&t->neigh_vars[12], 0, sizeof(ctl_table));	} else {		t->neigh_vars[12].data = (int*)(p+1);		t->neigh_vars[13].data = (int*)(p+1) + 1;		t->neigh_vars[14].data = (int*)(p+1) + 2;		t->neigh_vars[15].data = (int*)(p+1) + 3;	}	t->neigh_neigh_dir[0].ctl_name = pdev_id;	t->neigh_proto_dir[0].procname = p_name;	t->neigh_proto_dir[0].ctl_name = p_id;	t->neigh_dev[0].child = t->neigh_vars;	t->neigh_neigh_dir[0].child = t->neigh_dev;	t->neigh_proto_dir[0].child = t->neigh_neigh_dir;	t->neigh_root_dir[0].child = t->neigh_proto_dir;	t->sysctl_header = register_sysctl_table(t->neigh_root_dir, 0);	if (t->sysctl_header == NULL) {		kfree(t);		return -ENOBUFS;	}	p->sysctl_table = t;	return 0;}void neigh_sysctl_unregister(struct neigh_parms *p){	if (p->sysctl_table) {		struct neigh_sysctl_table *t = p->sysctl_table;		p->sysctl_table = NULL;		unregister_sysctl_table(t->sysctl_header);		kfree(t);	}}#endif	/* CONFIG_SYSCTL */

⌨️ 快捷键说明

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