if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
goto error;
- err = -ENOENT;
- x->type = xfrm_get_type(x->id.proto, x->props.family);
- if (x->type == NULL)
- goto error;
-
- err = x->type->init_state(x, NULL);
+ err = xfrm_init_state(x);
if (err)
goto error;
- x->curlft.add_time = (unsigned long) xtime.tv_sec;
- x->km.state = XFRM_STATE_VALID;
x->km.seq = p->seq;
return x;
if (err < 0) {
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
- return err;
+ goto out;
}
c.seq = nlh->nlmsg_seq;
c.pid = nlh->nlmsg_pid;
- if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
- c.event = XFRM_SAP_ADDED;
- else
- c.event = XFRM_SAP_UPDATED;
+ c.event = nlh->nlmsg_type;
km_state_notify(x, &c);
+out:
xfrm_state_put(x);
-
return err;
}
c.seq = nlh->nlmsg_seq;
c.pid = nlh->nlmsg_pid;
- c.event = XFRM_SAP_DELETED;
+ c.event = nlh->nlmsg_type;
km_state_notify(x, &c);
xfrm_state_put(x);
return err;
}
- if (!excl)
- c.event = XFRM_SAP_UPDATED;
- else
- c.event = XFRM_SAP_ADDED;
-
+ c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq;
c.pid = nlh->nlmsg_pid;
km_policy_notify(xp, p->dir, &c);
MSG_DONTWAIT);
}
} else {
- c.event = XFRM_SAP_DELETED;
+ 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);
struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
xfrm_state_flush(p->proto);
- c.data = p->proto;
- c.event = XFRM_SAP_FLUSHED;
+ 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);
struct km_event c;
xfrm_policy_flush();
- c.event = XFRM_SAP_FLUSHED;
+ c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq;
c.pid = nlh->nlmsg_pid;
km_policy_notify(NULL, 0, &c);
static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
{
struct sk_buff *skb;
- int hard = c ->data;
+ int len = NLMSG_LENGTH(sizeof(struct xfrm_user_expire));
- /* fix to do alloc using NLM macros */
- skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC);
+ skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
- if (build_expire(skb, x, hard) < 0)
+ if (build_expire(skb, x, c->data.hard) < 0)
BUG();
- NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
-
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
}
static int xfrm_notify_sa_flush(struct km_event *c)
nlh->nlmsg_flags = 0;
p = NLMSG_DATA(nlh);
- p->proto = c->data;
+ p->proto = c->data.proto;
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_SA;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
nlmsg_failure:
kfree_skb(skb);
static int inline xfrm_sa_len(struct xfrm_state *x)
{
- int l = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+ int l = 0;
if (x->aalg)
l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
if (x->ealg)
static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
{
struct xfrm_usersa_info *p;
+ struct xfrm_usersa_id *id;
struct nlmsghdr *nlh;
struct sk_buff *skb;
- u32 nlt;
unsigned char *b;
int len = xfrm_sa_len(x);
+ int headlen;
+
+ headlen = sizeof(*p);
+ if (c->event == XFRM_MSG_DELSA) {
+ len += RTA_SPACE(headlen);
+ headlen = sizeof(*id);
+ }
+ len += NLMSG_SPACE(headlen);
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
b = skb->tail;
- if (c->event == XFRM_SAP_ADDED)
- nlt = XFRM_MSG_NEWSA;
- else if (c->event == XFRM_SAP_UPDATED)
- nlt = XFRM_MSG_UPDSA;
- else if (c->event == XFRM_SAP_DELETED)
- nlt = XFRM_MSG_DELSA;
- else
- goto nlmsg_failure;
-
- nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, sizeof(*p));
+ nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
nlh->nlmsg_flags = 0;
p = NLMSG_DATA(nlh);
+ if (c->event == XFRM_MSG_DELSA) {
+ id = NLMSG_DATA(nlh);
+ memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
+ id->spi = x->id.spi;
+ id->family = x->props.family;
+ id->proto = x->id.proto;
+
+ p = RTA_DATA(__RTA_PUT(skb, XFRMA_SA, sizeof(*p)));
+ }
+
copy_to_user_state(x, p);
if (x->aalg)
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_SA;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
nlmsg_failure:
rtattr_failure:
{
switch (c->event) {
- case XFRM_SAP_EXPIRED:
+ case XFRM_MSG_EXPIRE:
return xfrm_exp_state_notify(x, c);
- case XFRM_SAP_DELETED:
- case XFRM_SAP_UPDATED:
- case XFRM_SAP_ADDED:
+ case XFRM_MSG_DELSA:
+ case XFRM_MSG_UPDSA:
+ case XFRM_MSG_NEWSA:
return xfrm_notify_sa(x, c);
- case XFRM_SAP_FLUSHED:
+ case XFRM_MSG_FLUSHSA:
return xfrm_notify_sa_flush(c);
default:
printk("xfrm_user: Unknown SA event %d\n", c->event);
if (build_acquire(skb, x, xt, xp, dir) < 0)
BUG();
- NETLINK_CB(skb).dst_groups = XFRMGRP_ACQUIRE;
-
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_ACQUIRE, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_ACQUIRE;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
}
/* User gives us xfrm_user_policy_info followed by an array of 0
if (nr > XFRM_MAX_DEPTH)
return NULL;
+ if (p->dir > XFRM_POLICY_OUT)
+ return NULL;
+
xp = xfrm_policy_alloc(GFP_KERNEL);
if (xp == NULL) {
*dir = -ENOBUFS;
if (skb == NULL)
return -ENOMEM;
- if (build_polexpire(skb, xp, dir, c->data) < 0)
+ if (build_polexpire(skb, xp, dir, c->data.hard) < 0)
BUG();
- NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
-
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
}
static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
{
struct xfrm_userpolicy_info *p;
+ struct xfrm_userpolicy_id *id;
struct nlmsghdr *nlh;
struct sk_buff *skb;
- u32 nlt = 0 ;
unsigned char *b;
int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
- len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_info));
+ int headlen;
+
+ headlen = sizeof(*p);
+ if (c->event == XFRM_MSG_DELPOLICY) {
+ len += RTA_SPACE(headlen);
+ headlen = sizeof(*id);
+ }
+ len += NLMSG_SPACE(headlen);
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
b = skb->tail;
- if (c->event == XFRM_SAP_ADDED)
- nlt = XFRM_MSG_NEWPOLICY;
- else if (c->event == XFRM_SAP_UPDATED)
- nlt = XFRM_MSG_UPDPOLICY;
- else if (c->event == XFRM_SAP_DELETED)
- nlt = XFRM_MSG_DELPOLICY;
- else
- goto nlmsg_failure;
-
- nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, sizeof(*p));
+ nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
p = NLMSG_DATA(nlh);
+ if (c->event == XFRM_MSG_DELPOLICY) {
+ id = NLMSG_DATA(nlh);
+ memset(id, 0, sizeof(*id));
+ id->dir = dir;
+ if (c->data.byid)
+ id->index = xp->index;
+ else
+ memcpy(&id->sel, &xp->selector, sizeof(id->sel));
+
+ p = RTA_DATA(__RTA_PUT(skb, XFRMA_POLICY, sizeof(*p)));
+ }
nlh->nlmsg_flags = 0;
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_POLICY;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
nlmsg_failure:
+rtattr_failure:
kfree_skb(skb);
return -1;
}
nlh->nlmsg_len = skb->tail - b;
- return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+ NETLINK_CB(skb).dst_group = XFRMNLGRP_POLICY;
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
nlmsg_failure:
kfree_skb(skb);
{
switch (c->event) {
- case XFRM_SAP_ADDED:
- case XFRM_SAP_UPDATED:
- case XFRM_SAP_DELETED:
+ case XFRM_MSG_NEWPOLICY:
+ case XFRM_MSG_UPDPOLICY:
+ case XFRM_MSG_DELPOLICY:
return xfrm_notify_policy(xp, dir, c);
- case XFRM_SAP_FLUSHED:
+ case XFRM_MSG_FLUSHPOLICY:
return xfrm_notify_policy_flush(c);
- case XFRM_SAP_EXPIRED:
+ case XFRM_MSG_POLEXPIRE:
return xfrm_exp_policy_notify(xp, dir, c);
default:
printk("xfrm_user: Unknown Policy event %d\n", c->event);
{
printk(KERN_INFO "Initializing IPsec netlink socket\n");
- xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv);
+ xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
+ xfrm_netlink_rcv, THIS_MODULE);
if (xfrm_nl == NULL)
return -ENOMEM;
module_init(xfrm_user_init);
module_exit(xfrm_user_exit);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);