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

📄 xfrm_state.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	 *     timeout of our timer function	 *  2. if x->replay_maxage has elapsed since last update,	 *     and there were changes	 *	 *  The state structure must be locked!	 */	switch (event) {	case XFRM_REPLAY_UPDATE:		if (x->replay_maxdiff &&		    (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&		    (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {			if (x->xflags & XFRM_TIME_DEFER)				event = XFRM_REPLAY_TIMEOUT;			else				return;		}		break;	case XFRM_REPLAY_TIMEOUT:		if ((x->replay.seq == x->preplay.seq) &&		    (x->replay.bitmap == x->preplay.bitmap) &&		    (x->replay.oseq == x->preplay.oseq)) {			x->xflags |= XFRM_TIME_DEFER;			return;		}		break;	}	memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));	c.event = XFRM_MSG_NEWAE;	c.data.aevent = event;	km_state_notify(x, &c);	if (x->replay_maxage &&	    !mod_timer(&x->rtimer, jiffies + x->replay_maxage))		x->xflags &= ~XFRM_TIME_DEFER;}static void xfrm_replay_timer_handler(unsigned long data){	struct xfrm_state *x = (struct xfrm_state*)data;	spin_lock(&x->lock);	if (x->km.state == XFRM_STATE_VALID) {		if (xfrm_aevent_is_on())			xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);		else			x->xflags |= XFRM_TIME_DEFER;	}	spin_unlock(&x->lock);}int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq){	u32 diff;	u32 seq = ntohl(net_seq);	if (unlikely(seq == 0))		return -EINVAL;	if (likely(seq > x->replay.seq))		return 0;	diff = x->replay.seq - seq;	if (diff >= min_t(unsigned int, x->props.replay_window,			  sizeof(x->replay.bitmap) * 8)) {		x->stats.replay_window++;		return -EINVAL;	}	if (x->replay.bitmap & (1U << diff)) {		x->stats.replay++;		return -EINVAL;	}	return 0;}EXPORT_SYMBOL(xfrm_replay_check);void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq){	u32 diff;	u32 seq = ntohl(net_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);	}	if (xfrm_aevent_is_on())		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);}EXPORT_SYMBOL(xfrm_replay_advance);static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);static DEFINE_RWLOCK(xfrm_km_lock);void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c){	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(xp, dir, c);	read_unlock(&xfrm_km_lock);}void km_state_notify(struct xfrm_state *x, struct km_event *c){	struct xfrm_mgr *km;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list)		if (km->notify)			km->notify(x, c);	read_unlock(&xfrm_km_lock);}EXPORT_SYMBOL(km_policy_notify);EXPORT_SYMBOL(km_state_notify);void km_state_expired(struct xfrm_state *x, int hard, u32 pid){	struct km_event c;	c.data.hard = hard;	c.pid = pid;	c.event = XFRM_MSG_EXPIRE;	km_state_notify(x, &c);	if (hard)		wake_up(&km_waitq);}EXPORT_SYMBOL(km_state_expired);/* * We send to all registered managers regardless of failure * We are happy with one success*/int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol){	int err = -EINVAL, acqret;	struct xfrm_mgr *km;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list) {		acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);		if (!acqret)			err = acqret;	}	read_unlock(&xfrm_km_lock);	return err;}EXPORT_SYMBOL(km_query);int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 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;}EXPORT_SYMBOL(km_new_mapping);void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid){	struct km_event c;	c.data.hard = hard;	c.pid = pid;	c.event = XFRM_MSG_POLEXPIRE;	km_policy_notify(pol, dir, &c);	if (hard)		wake_up(&km_waitq);}EXPORT_SYMBOL(km_policy_expired);#ifdef CONFIG_XFRM_MIGRATEint km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,	       struct xfrm_migrate *m, int num_migrate){	int err = -EINVAL;	int ret;	struct xfrm_mgr *km;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list) {		if (km->migrate) {			ret = km->migrate(sel, dir, type, m, num_migrate);			if (!ret)				err = ret;		}	}	read_unlock(&xfrm_km_lock);	return err;}EXPORT_SYMBOL(km_migrate);#endifint km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr){	int err = -EINVAL;	int ret;	struct xfrm_mgr *km;	read_lock(&xfrm_km_lock);	list_for_each_entry(km, &xfrm_km_list, list) {		if (km->report) {			ret = km->report(proto, sel, addr);			if (!ret)				err = ret;		}	}	read_unlock(&xfrm_km_lock);	return err;}EXPORT_SYMBOL(km_report);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, 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;}EXPORT_SYMBOL(xfrm_user_policy);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;}EXPORT_SYMBOL(xfrm_register_km);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;}EXPORT_SYMBOL(xfrm_unregister_km);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_bh(&xfrm_state_afinfo_lock);	if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))		err = -ENOBUFS;	else		xfrm_state_afinfo[afinfo->family] = afinfo;	write_unlock_bh(&xfrm_state_afinfo_lock);	return err;}EXPORT_SYMBOL(xfrm_state_register_afinfo);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_bh(&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;	}	write_unlock_bh(&xfrm_state_afinfo_lock);	return err;}EXPORT_SYMBOL(xfrm_state_unregister_afinfo);static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family){	struct xfrm_state_afinfo *afinfo;	if (unlikely(family >= NPROTO))		return NULL;	read_lock(&xfrm_state_afinfo_lock);	afinfo = xfrm_state_afinfo[family];	if (unlikely(!afinfo))		read_unlock(&xfrm_state_afinfo_lock);	return afinfo;}static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo){	read_unlock(&xfrm_state_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;	}}EXPORT_SYMBOL(xfrm_state_delete_tunnel);int xfrm_state_mtu(struct xfrm_state *x, int mtu){	int res;	spin_lock_bh(&x->lock);	if (x->km.state == XFRM_STATE_VALID &&	    x->type && x->type->get_mtu)		res = x->type->get_mtu(x, mtu);	else		res = mtu - x->props.header_len;	spin_unlock_bh(&x->lock);	return res;}int xfrm_init_state(struct xfrm_state *x){	struct xfrm_state_afinfo *afinfo;	int family = x->props.family;	int err;	err = -EAFNOSUPPORT;	afinfo = xfrm_state_get_afinfo(family);	if (!afinfo)		goto error;	err = 0;	if (afinfo->init_flags)		err = afinfo->init_flags(x);	xfrm_state_put_afinfo(afinfo);	if (err)		goto error;	err = -EPROTONOSUPPORT;	x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);	if (x->inner_mode == NULL)		goto error;	if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&	    family != x->sel.family)		goto error;	x->type = xfrm_get_type(x->id.proto, family);	if (x->type == NULL)		goto error;	err = x->type->init_state(x);	if (err)		goto error;	x->outer_mode = xfrm_get_mode(x->props.mode, family);	if (x->outer_mode == NULL)		goto error;	x->km.state = XFRM_STATE_VALID;error:	return err;}EXPORT_SYMBOL(xfrm_init_state);void __init xfrm_state_init(void){	unsigned int sz;	sz = sizeof(struct hlist_head) * 8;	xfrm_state_bydst = xfrm_hash_alloc(sz);	xfrm_state_bysrc = xfrm_hash_alloc(sz);	xfrm_state_byspi = xfrm_hash_alloc(sz);	if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi)		panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");	xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);	INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task);}#ifdef CONFIG_AUDITSYSCALLstatic inline void xfrm_audit_common_stateinfo(struct xfrm_state *x,					       struct audit_buffer *audit_buf){	if (x->security)		audit_log_format(audit_buf, " sec_alg=%u sec_doi=%u sec_obj=%s",				 x->security->ctx_alg, x->security->ctx_doi,				 x->security->ctx_str);	switch(x->props.family) {	case AF_INET:		audit_log_format(audit_buf, " src=%u.%u.%u.%u dst=%u.%u.%u.%u",				 NIPQUAD(x->props.saddr.a4),				 NIPQUAD(x->id.daddr.a4));		break;	case AF_INET6:		{			struct in6_addr saddr6, daddr6;			memcpy(&saddr6, x->props.saddr.a6,				sizeof(struct in6_addr));			memcpy(&daddr6, x->id.daddr.a6,				sizeof(struct in6_addr));			audit_log_format(audit_buf,					 " src=" NIP6_FMT " dst=" NIP6_FMT,					 NIP6(saddr6), NIP6(daddr6));		}		break;	}}voidxfrm_audit_state_add(struct xfrm_state *x, int result, u32 auid, u32 sid){	struct audit_buffer *audit_buf;	u32 spi;	extern int audit_enabled;	if (audit_enabled == 0)		return;	audit_buf = xfrm_audit_start(auid, sid);	if (audit_buf == NULL)		return;	audit_log_format(audit_buf, " op=SAD-add res=%u",result);	xfrm_audit_common_stateinfo(x, audit_buf);	spi = ntohl(x->id.spi);	audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);	audit_log_end(audit_buf);}EXPORT_SYMBOL_GPL(xfrm_audit_state_add);voidxfrm_audit_state_delete(struct xfrm_state *x, int result, u32 auid, u32 sid){	struct audit_buffer *audit_buf;	u32 spi;	extern int audit_enabled;	if (audit_enabled == 0)		return;	audit_buf = xfrm_audit_start(auid, sid);	if (audit_buf == NULL)		return;	audit_log_format(audit_buf, " op=SAD-delete res=%u",result);	xfrm_audit_common_stateinfo(x, audit_buf);	spi = ntohl(x->id.spi);	audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);	audit_log_end(audit_buf);}EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);#endif /* CONFIG_AUDITSYSCALL */

⌨️ 快捷键说明

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