-
-static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
-{
- struct xfrm_aevent_id *id;
- struct nlmsghdr *nlh;
- struct xfrm_lifetime_cur ltime;
- unsigned char *b = skb->tail;
-
- nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id));
- id = NLMSG_DATA(nlh);
- nlh->nlmsg_flags = 0;
-
- id->sa_id.daddr = x->id.daddr;
- id->sa_id.spi = x->id.spi;
- id->sa_id.family = x->props.family;
- id->sa_id.proto = x->id.proto;
- id->flags = c->data.aevent;
-
- RTA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
-
- ltime.bytes = x->curlft.bytes;
- ltime.packets = x->curlft.packets;
- ltime.add_time = x->curlft.add_time;
- ltime.use_time = x->curlft.use_time;
-
- RTA_PUT(skb, XFRMA_LTIME_VAL, sizeof(struct xfrm_lifetime_cur), <ime);
-
- if (id->flags&XFRM_AE_RTHR) {
- RTA_PUT(skb,XFRMA_REPLAY_THRESH,sizeof(u32),&x->replay_maxdiff);
- }
-
- if (id->flags&XFRM_AE_ETHR) {
- u32 etimer = x->replay_maxage*10/HZ;
- RTA_PUT(skb,XFRMA_ETIMER_THRESH,sizeof(u32),&etimer);
- }
-
- nlh->nlmsg_len = skb->tail - b;
- return skb->len;
-
-rtattr_failure:
-nlmsg_failure:
- skb_trim(skb, b - skb->data);
- return -1;
-}
-
-static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
-{
- struct xfrm_state *x;
- struct sk_buff *r_skb;
- int err;
- struct km_event c;
- struct xfrm_aevent_id *p = NLMSG_DATA(nlh);
- int len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
- struct xfrm_usersa_id *id = &p->sa_id;
-
- len += RTA_SPACE(sizeof(struct xfrm_replay_state));
- len += RTA_SPACE(sizeof(struct xfrm_lifetime_cur));
-
- if (p->flags&XFRM_AE_RTHR)
- len+=RTA_SPACE(sizeof(u32));
-
- if (p->flags&XFRM_AE_ETHR)
- len+=RTA_SPACE(sizeof(u32));
-
- r_skb = alloc_skb(len, GFP_ATOMIC);
- if (r_skb == NULL)
- return -ENOMEM;
-
- x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family);
- if (x == NULL) {
- kfree(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 = netlink_unicast(xfrm_nl, r_skb,
- NETLINK_CB(skb).pid, MSG_DONTWAIT);
- spin_unlock_bh(&x->lock);
- xfrm_state_put(x);
- return err;
-}
-
-static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
-{
- struct xfrm_state *x;
- struct km_event c;
- int err = - EINVAL;
- struct xfrm_aevent_id *p = NLMSG_DATA(nlh);
- struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1];
- struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1];
-
- 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);
- err = xfrm_update_ae_params(x,(struct rtattr **)xfrma);
- spin_unlock_bh(&x->lock);
- if (err < 0)
- goto out;
-
- 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;
-}
-