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

📄 xfrm_user.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,					  struct xfrm_policy *xp,					  int dir, u32 seq){	struct xfrm_dump_info info;	struct sk_buff *skb;	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);	if (!skb)		return ERR_PTR(-ENOMEM);	info.in_skb = in_skb;	info.out_skb = skb;	info.nlmsg_seq = seq;	info.nlmsg_flags = 0;	info.this_idx = info.start_idx = 0;	if (dump_one_policy(xp, dir, 0, &info) < 0) {		kfree_skb(skb);		return NULL;	}	return skb;}static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct xfrm_policy *xp;	struct xfrm_userpolicy_id *p;	u8 type = XFRM_POLICY_TYPE_MAIN;	int err;	struct km_event c;	int delete;	p = nlmsg_data(nlh);	delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;	err = copy_from_user_policy_type(&type, attrs);	if (err)		return err;	err = verify_policy_dir(p->dir);	if (err)		return err;	if (p->index)		xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);	else {		struct nlattr *rt = attrs[XFRMA_SEC_CTX];		struct xfrm_policy tmp;		err = verify_sec_ctx_len(attrs);		if (err)			return err;		memset(&tmp, 0, sizeof(struct xfrm_policy));		if (rt) {			struct xfrm_user_sec_ctx *uctx = nla_data(rt);			if ((err = security_xfrm_policy_alloc(&tmp, uctx)))				return err;		}		xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,					   delete, &err);		security_xfrm_policy_free(&tmp);	}	if (xp == NULL)		return -ENOENT;	if (!delete) {		struct sk_buff *resp_skb;		resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq);		if (IS_ERR(resp_skb)) {			err = PTR_ERR(resp_skb);		} else {			err = nlmsg_unicast(xfrm_nl, resp_skb,					    NETLINK_CB(skb).pid);		}	} else {		xfrm_audit_policy_delete(xp, err ? 0 : 1,					 NETLINK_CB(skb).loginuid,					 NETLINK_CB(skb).sid);		if (err != 0)			goto out;		c.data.byid = p->index;		c.event = nlh->nlmsg_type;		c.seq = nlh->nlmsg_seq;		c.pid = nlh->nlmsg_pid;		km_policy_notify(xp, p->dir, &c);	}out:	xfrm_pol_put(xp);	return err;}static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct km_event c;	struct xfrm_usersa_flush *p = nlmsg_data(nlh);	struct xfrm_audit audit_info;	int err;	audit_info.loginuid = NETLINK_CB(skb).loginuid;	audit_info.secid = NETLINK_CB(skb).sid;	err = xfrm_state_flush(p->proto, &audit_info);	if (err)		return err;	c.data.proto = p->proto;	c.event = nlh->nlmsg_type;	c.seq = nlh->nlmsg_seq;	c.pid = nlh->nlmsg_pid;	km_state_notify(NULL, &c);	return 0;}static inline size_t xfrm_aevent_msgsize(void){	return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))	       + nla_total_size(sizeof(struct xfrm_replay_state))	       + nla_total_size(sizeof(struct xfrm_lifetime_cur))	       + nla_total_size(4) /* XFRM_AE_RTHR */	       + nla_total_size(4); /* XFRM_AE_ETHR */}static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c){	struct xfrm_aevent_id *id;	struct nlmsghdr *nlh;	nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id), 0);	if (nlh == NULL)		return -EMSGSIZE;	id = nlmsg_data(nlh);	memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr));	id->sa_id.spi = x->id.spi;	id->sa_id.family = x->props.family;	id->sa_id.proto = x->id.proto;	memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr));	id->reqid = x->props.reqid;	id->flags = c->data.aevent;	NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);	NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft);	if (id->flags & XFRM_AE_RTHR)		NLA_PUT_U32(skb, XFRMA_REPLAY_THRESH, x->replay_maxdiff);	if (id->flags & XFRM_AE_ETHR)		NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH,			    x->replay_maxage * 10 / HZ);	return nlmsg_end(skb, nlh);nla_put_failure:	nlmsg_cancel(skb, nlh);	return -EMSGSIZE;}static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct xfrm_state *x;	struct sk_buff *r_skb;	int err;	struct km_event c;	struct xfrm_aevent_id *p = nlmsg_data(nlh);	struct xfrm_usersa_id *id = &p->sa_id;	r_skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);	if (r_skb == NULL)		return -ENOMEM;	x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family);	if (x == NULL) {		kfree_skb(r_skb);		return -ESRCH;	}	/*	 * XXX: is this lock really needed - none of the other	 * gets lock (the concern is things getting updated	 * while we are still reading) - jhs	*/	spin_lock_bh(&x->lock);	c.data.aevent = p->flags;	c.seq = nlh->nlmsg_seq;	c.pid = nlh->nlmsg_pid;	if (build_aevent(r_skb, x, &c) < 0)		BUG();	err = nlmsg_unicast(xfrm_nl, r_skb, NETLINK_CB(skb).pid);	spin_unlock_bh(&x->lock);	xfrm_state_put(x);	return err;}static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct xfrm_state *x;	struct km_event c;	int err = - EINVAL;	struct xfrm_aevent_id *p = nlmsg_data(nlh);	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];	if (!lt && !rp)		return err;	/* pedantic mode - thou shalt sayeth replaceth */	if (!(nlh->nlmsg_flags&NLM_F_REPLACE))		return err;	x = xfrm_state_lookup(&p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);	if (x == NULL)		return -ESRCH;	if (x->km.state != XFRM_STATE_VALID)		goto out;	spin_lock_bh(&x->lock);	xfrm_update_ae_params(x, attrs);	spin_unlock_bh(&x->lock);	c.event = nlh->nlmsg_type;	c.seq = nlh->nlmsg_seq;	c.pid = nlh->nlmsg_pid;	c.data.aevent = XFRM_AE_CU;	km_state_notify(x, &c);	err = 0;out:	xfrm_state_put(x);	return err;}static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct km_event c;	u8 type = XFRM_POLICY_TYPE_MAIN;	int err;	struct xfrm_audit audit_info;	err = copy_from_user_policy_type(&type, attrs);	if (err)		return err;	audit_info.loginuid = NETLINK_CB(skb).loginuid;	audit_info.secid = NETLINK_CB(skb).sid;	err = xfrm_policy_flush(type, &audit_info);	if (err)		return err;	c.data.type = type;	c.event = nlh->nlmsg_type;	c.seq = nlh->nlmsg_seq;	c.pid = nlh->nlmsg_pid;	km_policy_notify(NULL, 0, &c);	return 0;}static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct xfrm_policy *xp;	struct xfrm_user_polexpire *up = nlmsg_data(nlh);	struct xfrm_userpolicy_info *p = &up->pol;	u8 type = XFRM_POLICY_TYPE_MAIN;	int err = -ENOENT;	err = copy_from_user_policy_type(&type, attrs);	if (err)		return err;	if (p->index)		xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);	else {		struct nlattr *rt = attrs[XFRMA_SEC_CTX];		struct xfrm_policy tmp;		err = verify_sec_ctx_len(attrs);		if (err)			return err;		memset(&tmp, 0, sizeof(struct xfrm_policy));		if (rt) {			struct xfrm_user_sec_ctx *uctx = nla_data(rt);			if ((err = security_xfrm_policy_alloc(&tmp, uctx)))				return err;		}		xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,					   0, &err);		security_xfrm_policy_free(&tmp);	}	if (xp == NULL)		return -ENOENT;	read_lock(&xp->lock);	if (xp->dead) {		read_unlock(&xp->lock);		goto out;	}	read_unlock(&xp->lock);	err = 0;	if (up->hard) {		xfrm_policy_delete(xp, p->dir);		xfrm_audit_policy_delete(xp, 1, NETLINK_CB(skb).loginuid,					 NETLINK_CB(skb).sid);	} else {		// reset the timers here?		printk("Dont know what to do with soft policy expire\n");	}	km_policy_expired(xp, p->dir, up->hard, current->pid);out:	xfrm_pol_put(xp);	return err;}static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct xfrm_state *x;	int err;	struct xfrm_user_expire *ue = nlmsg_data(nlh);	struct xfrm_usersa_info *p = &ue->state;	x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family);	err = -ENOENT;	if (x == NULL)		return err;	spin_lock_bh(&x->lock);	err = -EINVAL;	if (x->km.state != XFRM_STATE_VALID)		goto out;	km_state_expired(x, ue->hard, current->pid);	if (ue->hard) {		__xfrm_state_delete(x);		xfrm_audit_state_delete(x, 1, NETLINK_CB(skb).loginuid,					NETLINK_CB(skb).sid);	}	err = 0;out:	spin_unlock_bh(&x->lock);	xfrm_state_put(x);	return err;}static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,		struct nlattr **attrs){	struct xfrm_policy *xp;	struct xfrm_user_tmpl *ut;	int i;	struct nlattr *rt = attrs[XFRMA_TMPL];	struct xfrm_user_acquire *ua = nlmsg_data(nlh);	struct xfrm_state *x = xfrm_state_alloc();	int err = -ENOMEM;	if (!x)		return err;	err = verify_newpolicy_info(&ua->policy);	if (err) {		printk("BAD policy passed\n");		kfree(x);		return err;	}	/*   build an XP */	xp = xfrm_policy_construct(&ua->policy, attrs, &err);	if (!xp) {		kfree(x);		return err;	}	memcpy(&x->id, &ua->id, sizeof(ua->id));	memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr));	memcpy(&x->sel, &ua->sel, sizeof(ua->sel));	ut = nla_data(rt);	/* extract the templates and for each call km_key */	for (i = 0; i < xp->xfrm_nr; i++, ut++) {		struct xfrm_tmpl *t = &xp->xfrm_vec[i];		memcpy(&x->id, &t->id, sizeof(x->id));		x->props.mode = t->mode;		x->props.reqid = t->reqid;		x->props.family = ut->family;		t->aalgos = ua->aalgos;		t->ealgos = ua->ealgos;		t->calgos = ua->calgos;		err = km_query(x, t, xp);	}	kfree(x);	kfree(xp);	return 0;}#ifdef CONFIG_XFRM_MIGRATEstatic int copy_from_user_migrate(struct xfrm_migrate *ma,				  struct nlattr **attrs, int *num){	struct nlattr *rt = attrs[XFRMA_MIGRATE];	struct xfrm_user_migrate *um;	int i, num_migrate;	um = nla_data(rt);	num_migrate = nla_len(rt) / sizeof(*um);	if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH)		return -EINVAL;	for (i = 0; i < num_migrate; i++, um++, ma++) {		memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr));		memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr));		memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr));		memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr));		ma->proto = um->proto;		ma->mode = um->mode;		ma->reqid = um->reqid;		ma->old_family = um->old_family;		ma->new_family = um->new_family;	}	*num = i;	return 0;}static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,			   struct nlattr **attrs){	struct xfrm_userpolicy_id *pi = nlmsg_data(nlh);	struct xfrm_migrate m[XFRM_MAX_DEPTH];	u8 type;	int err;	int n = 0;	if (attrs[XFRMA_MIGRATE] == NULL)		return -EINVAL;	err = copy_from_user_policy_type(&type, attrs);	if (err)		return err;	err = copy_from_user_migrate((struct xfrm_migrate *)m,				     attrs, &n);	if (err)		return err;	if (!n)		return 0;	xfrm_migrate(&pi->sel, pi->dir, type, m, n);	return 0;}#elsestatic int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,			   struct nlattr **attrs){	return -ENOPROTOOPT;}#endif#ifdef CONFIG_XFRM_MIGRATEstatic int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb){	struct xfrm_user_migrate um;	memset(&um, 0, sizeof(um));	um.proto = m->proto;	um.mode = m->mode;	um.reqid = m->reqid;	um.old_family = m->old_family;	memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr));	memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr));	um.new_family = m->new_family;	memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr));	memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr));	return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um);}static inline size_t xfrm_migrate_msgsize(int num_migrate){	return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))	       + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)	       + userpolicy_type_attrsize();}static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m,			 int num_migrate, struct xfrm_selector *sel,			 u8 dir, u8 type){	struct xfrm_migrate *mp;	struct xfrm_userpolicy_id *pol_id;	struct nlmsghdr *nlh;	int i;	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id), 0);	if (nlh == NULL)		return -EMSGSIZE;	pol_id = nlmsg_data(nlh);	/* copy data from selector, dir, and type to the pol_id */	memset(pol_id, 0, sizeof(*pol_id));	memcpy(&pol_id->sel, sel, sizeof(pol_id->sel));	pol_id->dir = dir;	if (copy_to_user_policy_type(type, skb) < 0)		goto nlmsg_failure;	for (i = 0, mp = m ; i < num_migrate; i++, mp++) {		if (copy_to_user_migrate(mp, skb) < 0)			goto nlmsg_failure;	}	return nlmsg_end(skb, nlh);nlmsg_failure:	nlmsg_cancel(skb, nlh);	return -EMSGSIZE;}static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,			     struct xfrm_migrate *m, int num_migrate){	struct sk_buff *skb;	skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate), GFP_ATOMIC);	if (skb == NULL)		return -ENOMEM;	/* build migrate */	if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0)		BUG();	return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC);}#elsestatic int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,			     struct xfrm_migrate *m, int num_migrate){	return -ENOPROTOOPT;}#endif#define XMSGSIZE(type) sizeof(struct type)static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),	[XFRM_MSG_DELSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),	[XFRM_MSG_GETSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),	[XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),	[XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info),	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire),	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire),	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),	[XFRM_MSG_POLEXPIRE   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire),	[XFRM_MSG_FLUSHSA     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush),	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0,	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),	[XFRM_MSG_REPORT      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),	[XFRM_MSG_MIGRATE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),	[XFRM_MSG_GETSADINFO  - XFRM_MSG_BASE] = sizeof(u32),	[XFRM_MSG_GETSPDINFO  - XFRM_MSG_BASE] = sizeof(u32),};#undef XMSGSIZEstatic const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {	[XFRMA_ALG_AUTH]	= { .len = sizeof(struct xfrm_algo) },	[XFRMA_ALG_CRYPT]	= { .len = sizeof(struct xfrm_algo) },	[XFRMA_ALG_COMP]	= { .len = sizeof(struct xfrm_algo) },	[XFRMA_ENCAP]		= { .len = sizeof(struct xfrm_encap_tmpl) },	[XFRMA_TMPL]		= { .len = sizeof(struct xfrm_user_tmpl) },	[XFRMA_SEC_CTX]		= { .len = sizeof(struct xfrm_sec_ctx) },	[XFRMA_LTIME_VAL]	= { .len = sizeof(struct xfrm_lifetime_cur) },	[XFRMA_REPLAY_VAL]	= { .len = sizeof(struct xfrm_replay_state) },	[XFRMA_REPLAY_THRESH]	= { .type = NLA_U32 },	[XFRMA_ETIMER_THRESH]	= { .type = NLA_U32 },	[XFRMA_SRCADDR]		= { .len = sizeof(xfrm_address_t) },	[XFRMA_COADDR]		= { .len = sizeof(xfrm_address_t) },	[XFRMA_POLICY_TYPE]	= { .len = sizeof(struct xfrm_userpolicy_type)},	[XFRMA_MIGRATE]		= { .len = sizeof(struct xfrm_user_migrate) },

⌨️ 快捷键说明

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