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

📄 xfrm_state.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	err = -EINVAL;	spin_lock_bh(&x1->lock);	if (likely(x1->km.state == XFRM_STATE_VALID)) {		if (x->encap && x1->encap)			memcpy(x1->encap, x->encap, sizeof(*x1->encap));		memcpy(&x1->lft, &x->lft, sizeof(x1->lft));		x1->km.dying = 0;		if (!mod_timer(&x1->timer, jiffies + HZ))			xfrm_state_hold(x1);		if (x1->curlft.use_time)			xfrm_state_check_expire(x1);		err = 0;	}	spin_unlock_bh(&x1->lock);	xfrm_state_put(x1);	return err;}int xfrm_state_check_expire(struct xfrm_state *x){	if (!x->curlft.use_time)		x->curlft.use_time = (unsigned long)xtime.tv_sec;	if (x->km.state != XFRM_STATE_VALID)		return -EINVAL;	if (x->curlft.bytes >= x->lft.hard_byte_limit ||	    x->curlft.packets >= x->lft.hard_packet_limit) {		km_state_expired(x, 1);		if (!mod_timer(&x->timer, jiffies + XFRM_ACQ_EXPIRES*HZ))			xfrm_state_hold(x);		return -EINVAL;	}	if (!x->km.dying &&	    (x->curlft.bytes >= x->lft.soft_byte_limit ||	     x->curlft.packets >= x->lft.soft_packet_limit))		km_state_expired(x, 0);	return 0;}int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb){	int nhead = x->props.header_len + LL_RESERVED_SPACE(skb->dst->dev)		- skb_headroom(skb);	if (nhead > 0)		return pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);	/* Check tail too... */	return 0;}int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb){	int err = xfrm_state_check_expire(x);	if (err < 0)		goto err;	err = xfrm_state_check_space(x, skb);err:	return err;}struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,		  unsigned short family){	struct xfrm_state *x;	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);	if (!afinfo)		return NULL;	spin_lock_bh(&xfrm_state_lock);	x = afinfo->state_lookup(daddr, spi, proto);	spin_unlock_bh(&xfrm_state_lock);	xfrm_state_put_afinfo(afinfo);	return x;}struct xfrm_state *xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 	      xfrm_address_t *daddr, xfrm_address_t *saddr, 	      int create, unsigned short family){	struct xfrm_state *x;	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);	if (!afinfo)		return NULL;	spin_lock_bh(&xfrm_state_lock);	x = afinfo->find_acq(mode, reqid, proto, daddr, saddr, create);	spin_unlock_bh(&xfrm_state_lock);	xfrm_state_put_afinfo(afinfo);	return x;}/* Silly enough, but I'm lazy to build resolution list */static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq){	int i;	struct xfrm_state *x;	for (i = 0; i < XFRM_DST_HSIZE; i++) {		list_for_each_entry(x, xfrm_state_bydst+i, bydst) {			if (x->km.seq == seq) {				xfrm_state_hold(x);				return x;			}		}	}	return NULL;}struct xfrm_state *xfrm_find_acq_byseq(u32 seq){	struct xfrm_state *x;	spin_lock_bh(&xfrm_state_lock);	x = __xfrm_find_acq_byseq(seq);	spin_unlock_bh(&xfrm_state_lock);	return x;} u32 xfrm_get_acqseq(void){	u32 res;	static u32 acqseq;	static spinlock_t acqseq_lock = SPIN_LOCK_UNLOCKED;	spin_lock_bh(&acqseq_lock);	res = (++acqseq ? : ++acqseq);	spin_unlock_bh(&acqseq_lock);	return res;}voidxfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi){	u32 h;	struct xfrm_state *x0;	if (x->id.spi)		return;	if (minspi == maxspi) {		x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family);		if (x0) {			xfrm_state_put(x0);			return;		}		x->id.spi = minspi;	} else {		u32 spi = 0;		minspi = ntohl(minspi);		maxspi = ntohl(maxspi);		for (h=0; h<maxspi-minspi+1; h++) {			spi = minspi + net_random()%(maxspi-minspi+1);			x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);			if (x0 == NULL) {				x->id.spi = htonl(spi);				break;			}			xfrm_state_put(x0);		}	}	if (x->id.spi) {		spin_lock_bh(&xfrm_state_lock);		h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);		list_add(&x->byspi, xfrm_state_byspi+h);		xfrm_state_hold(x);		spin_unlock_bh(&xfrm_state_lock);		wake_up(&km_waitq);	}}int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),		    void *data){	int i;	struct xfrm_state *x;	int count = 0;	int err = 0;	spin_lock_bh(&xfrm_state_lock);	for (i = 0; i < XFRM_DST_HSIZE; i++) {		list_for_each_entry(x, xfrm_state_bydst+i, bydst) {			if (proto == IPSEC_PROTO_ANY || x->id.proto == proto)				count++;		}	}	if (count == 0) {		err = -ENOENT;		goto out;	}	for (i = 0; i < XFRM_DST_HSIZE; i++) {		list_for_each_entry(x, xfrm_state_bydst+i, bydst) {			if (proto != IPSEC_PROTO_ANY && x->id.proto != proto)				continue;			err = func(x, --count, data);			if (err)				goto out;		}	}out:	spin_unlock_bh(&xfrm_state_lock);	return err;}int xfrm_replay_check(struct xfrm_state *x, u32 seq){	u32 diff;	seq = ntohl(seq);	if (unlikely(seq == 0))		return -EINVAL;	if (likely(seq > x->replay.seq))		return 0;	diff = x->replay.seq - seq;	if (diff >= x->props.replay_window) {		x->stats.replay_window++;		return -EINVAL;	}	if (x->replay.bitmap & (1U << diff)) {		x->stats.replay++;		return -EINVAL;	}	return 0;}void xfrm_replay_advance(struct xfrm_state *x, u32 seq){	u32 diff;	seq = ntohl(seq);	if (seq > x->replay.seq) {		diff = seq - x->replay.seq;		if (diff < x->props.replay_window)			x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;		else			x->replay.bitmap = 1;		x->replay.seq = seq;	} else {		diff = x->replay.seq - seq;		x->replay.bitmap |= (1U << diff);	}}int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl){	int i;	for (i=0; i<n; i++) {		int match;		match = xfrm_selector_match(&x[i]->sel, fl, x[i]->props.family);		if (!match)			return -EINVAL;	}	return 0;}static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);static rwlock_t		xfrm_km_lock = RW_LOCK_UNLOCKED;void km_state_expired(struct xfrm_state *x, int hard){	struct xfrm_mgr *km;	if (hard)		x->km.state = XFRM_STATE_EXPIRED;	else		x->km.dying = 1;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list)		km->notify(x, hard);	read_unlock(&xfrm_km_lock);	if (hard)		wake_up(&km_waitq);}int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol){	int err = -EINVAL;	struct xfrm_mgr *km;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list) {		err = km->acquire(x, t, pol, XFRM_POLICY_OUT);		if (!err)			break;	}	read_unlock(&xfrm_km_lock);	return err;}int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport){	int err = -EINVAL;	struct xfrm_mgr *km;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list) {		if (km->new_mapping)			err = km->new_mapping(x, ipaddr, sport);		if (!err)			break;	}	read_unlock(&xfrm_km_lock);	return err;}void km_policy_expired(struct xfrm_policy *pol, int dir, int hard){	struct xfrm_mgr *km;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list)		if (km->notify_policy)			km->notify_policy(pol, dir, hard);	read_unlock(&xfrm_km_lock);	if (hard)		wake_up(&km_waitq);}int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen){	int err;	u8 *data;	struct xfrm_mgr *km;	struct xfrm_policy *pol = NULL;	if (optlen <= 0 || optlen > PAGE_SIZE)		return -EMSGSIZE;	data = kmalloc(optlen, GFP_KERNEL);	if (!data)		return -ENOMEM;	err = -EFAULT;	if (copy_from_user(data, optval, optlen))		goto out;	err = -EINVAL;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list) {		pol = km->compile_policy(sk->sk_family, optname, data,					 optlen, &err);		if (err >= 0)			break;	}	read_unlock(&xfrm_km_lock);	if (err >= 0) {		xfrm_sk_policy_insert(sk, err, pol);		xfrm_pol_put(pol);		err = 0;	}out:	kfree(data);	return err;}int xfrm_register_km(struct xfrm_mgr *km){	write_lock_bh(&xfrm_km_lock);	list_add_tail(&km->list, &xfrm_km_list);	write_unlock_bh(&xfrm_km_lock);	return 0;}int xfrm_unregister_km(struct xfrm_mgr *km){	write_lock_bh(&xfrm_km_lock);	list_del(&km->list);	write_unlock_bh(&xfrm_km_lock);	return 0;}int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo){	int err = 0;	if (unlikely(afinfo == NULL))		return -EINVAL;	if (unlikely(afinfo->family >= NPROTO))		return -EAFNOSUPPORT;	write_lock(&xfrm_state_afinfo_lock);	if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))		err = -ENOBUFS;	else {		afinfo->state_bydst = xfrm_state_bydst;		afinfo->state_byspi = xfrm_state_byspi;		xfrm_state_afinfo[afinfo->family] = afinfo;	}	write_unlock(&xfrm_state_afinfo_lock);	return err;}int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo){	int err = 0;	if (unlikely(afinfo == NULL))		return -EINVAL;	if (unlikely(afinfo->family >= NPROTO))		return -EAFNOSUPPORT;	write_lock(&xfrm_state_afinfo_lock);	if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {		if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))			err = -EINVAL;		else {			xfrm_state_afinfo[afinfo->family] = NULL;			afinfo->state_byspi = NULL;			afinfo->state_bydst = NULL;		}	}	write_unlock(&xfrm_state_afinfo_lock);	return err;}struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family){	struct xfrm_state_afinfo *afinfo;	if (unlikely(family >= NPROTO))		return NULL;	read_lock(&xfrm_state_afinfo_lock);	afinfo = xfrm_state_afinfo[family];	if (likely(afinfo != NULL))		read_lock(&afinfo->lock);	read_unlock(&xfrm_state_afinfo_lock);	return afinfo;}void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo){	if (unlikely(afinfo == NULL))		return;	read_unlock(&afinfo->lock);}/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */void xfrm_state_delete_tunnel(struct xfrm_state *x){	if (x->tunnel) {		struct xfrm_state *t = x->tunnel;		if (atomic_read(&t->tunnel_users) == 2)			xfrm_state_delete(t);		atomic_dec(&t->tunnel_users);		xfrm_state_put(t);		x->tunnel = NULL;	}}void __init xfrm_state_init(void){	int i;	for (i=0; i<XFRM_DST_HSIZE; i++) {		INIT_LIST_HEAD(&xfrm_state_bydst[i]);		INIT_LIST_HEAD(&xfrm_state_byspi[i]);	}	INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);}

⌨️ 快捷键说明

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