Cast first argument for %.*s to int
[strongswan.git] / src / conftest / hooks / reset_seq.c
index 6fb7a2e..1009773 100644 (file)
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  */
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  */
+/*
+ * Copyright (C) 2012 achelos GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
 
 #include "hook.h"
 
 
 #include "hook.h"
 
@@ -40,21 +61,46 @@ struct private_reset_seq_t {
         * Delay for reset
         */
        int delay;
         * Delay for reset
         */
        int delay;
+
+       /**
+        * Sequence number to set for outgoing packages
+        */
+       int oseq;
+};
+
+typedef struct reset_cb_data_t reset_cb_data_t;
+
+/**
+ * Data needed for the callback job
+ */
+struct reset_cb_data_t {
+
+       /**
+        * The SA to modify
+        */
+       struct xfrm_usersa_id usersa;
+
+       /**
+        * Sequence number to set for outgoing packages
+        */
+       int oseq;
 };
 
 /**
  * Callback job
  */
 };
 
 /**
  * Callback job
  */
-static job_requeue_t reset_cb(struct xfrm_usersa_id *data)
+static job_requeue_t reset_cb(struct reset_cb_data_t *data)
 {
        netlink_buf_t request;
        struct nlmsghdr *hdr;
        struct xfrm_aevent_id *id;
        struct rtattr *rthdr;
 {
        netlink_buf_t request;
        struct nlmsghdr *hdr;
        struct xfrm_aevent_id *id;
        struct rtattr *rthdr;
+       struct xfrm_replay_state *rpstate;
        struct sockaddr_nl addr;
        int s, len;
 
        struct sockaddr_nl addr;
        int s, len;
 
-       DBG1(DBG_CFG, "resetting sequence number of SPI 0x%x", htonl(data->spi));
+       DBG1(DBG_CFG, "setting sequence number of SPI 0x%x to %d",
+                htonl(data->usersa.spi), data->oseq);
 
        memset(&request, 0, sizeof(request));
 
 
        memset(&request, 0, sizeof(request));
 
@@ -66,13 +112,22 @@ static job_requeue_t reset_cb(struct xfrm_usersa_id *data)
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
 
        id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr);
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
 
        id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr);
-       id->sa_id = *data;
+       id->sa_id = data->usersa;
 
        rthdr = XFRM_RTA(hdr, struct xfrm_aevent_id);
        rthdr->rta_type = XFRMA_REPLAY_VAL;
        rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
        hdr->nlmsg_len += rthdr->rta_len;
 
 
        rthdr = XFRM_RTA(hdr, struct xfrm_aevent_id);
        rthdr->rta_type = XFRMA_REPLAY_VAL;
        rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
        hdr->nlmsg_len += rthdr->rta_len;
 
+       /* xfrm_replay_state is the structure the kernel uses for
+        * replay detection, and the oseq element contains the
+        * sequence number for outgoing packets. Currently, this
+        * function sets the other elements seq (records the number of
+        * incoming packets) and bitmask to zero, but they could be
+        * adjusted in the same way as oseq if required. */
+       rpstate = (struct xfrm_replay_state*)RTA_DATA(rthdr);
+       rpstate->oseq = data->oseq;
+
        s = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
        if (s == -1)
        {
        s = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
        if (s == -1)
        {
@@ -97,17 +152,21 @@ static job_requeue_t reset_cb(struct xfrm_usersa_id *data)
 static void schedule_reset_job(private_reset_seq_t *this, host_t *dst,
                                                           u_int32_t spi)
 {
 static void schedule_reset_job(private_reset_seq_t *this, host_t *dst,
                                                           u_int32_t spi)
 {
-       struct xfrm_usersa_id *data;
+       struct reset_cb_data_t *data;
        chunk_t chunk;
 
        INIT(data,
        chunk_t chunk;
 
        INIT(data,
-               .spi = spi,
-               .family = dst->get_family(dst),
-               .proto = IPPROTO_ESP,
+               .usersa = {
+                       .spi = spi,
+                       .family = dst->get_family(dst),
+                       .proto = IPPROTO_ESP,
+               },
+               .oseq = this->oseq,
        );
 
        chunk = dst->get_address(dst);
        );
 
        chunk = dst->get_address(dst);
-       memcpy(&data->daddr, chunk.ptr, min(chunk.len, sizeof(xfrm_address_t)));
+       memcpy(&data->usersa.daddr, chunk.ptr,
+                  min(chunk.len, sizeof(xfrm_address_t)));
 
        lib->scheduler->schedule_job(lib->scheduler,
                                                                 (job_t*)callback_job_create(
 
        lib->scheduler->schedule_job(lib->scheduler,
                                                                 (job_t*)callback_job_create(
@@ -149,6 +208,8 @@ hook_t *reset_seq_hook_create(char *name)
                },
                .delay = conftest->test->get_int(conftest->test,
                                                                                "hooks.%s.delay", 10, name),
                },
                .delay = conftest->test->get_int(conftest->test,
                                                                                "hooks.%s.delay", 10, name),
+               .oseq = conftest->test->get_int(conftest->test,
+                                                                               "hooks.%s.oseq", 0, name),
        );
 
        return &this->hook;
        );
 
        return &this->hook;