Annotation of embedaddon/strongswan/src/conftest/hooks/reset_seq.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2010 Martin Willi
! 3: * Copyright (C) 2010 revosec AG
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15: /*
! 16: * Copyright (C) 2012 achelos GmbH
! 17: *
! 18: * Permission is hereby granted, free of charge, to any person obtaining a copy
! 19: * of this software and associated documentation files (the "Software"), to deal
! 20: * in the Software without restriction, including without limitation the rights
! 21: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
! 22: * copies of the Software, and to permit persons to whom the Software is
! 23: * furnished to do so, subject to the following conditions:
! 24: *
! 25: * The above copyright notice and this permission notice shall be included in
! 26: * all copies or substantial portions of the Software.
! 27: *
! 28: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
! 29: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
! 30: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
! 31: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
! 32: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
! 33: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
! 34: * THE SOFTWARE.
! 35: */
! 36:
! 37: #include "hook.h"
! 38:
! 39: /* this hook is currently only supported on Linux (systems like FreeBSD don't
! 40: * actually provide an interface to change the sequence numbers of SAs) */
! 41: #ifdef __linux__
! 42:
! 43: #include <linux/xfrm.h>
! 44: #include <unistd.h>
! 45: #include <errno.h>
! 46:
! 47: #include <processing/jobs/callback_job.h>
! 48: #include <plugins/kernel_netlink/kernel_netlink_shared.h>
! 49:
! 50: #define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + NLMSG_ALIGN(sizeof(x))))
! 51:
! 52: typedef struct private_reset_seq_t private_reset_seq_t;
! 53:
! 54: /**
! 55: * Private data of an reset_seq_t object.
! 56: */
! 57: struct private_reset_seq_t {
! 58:
! 59: /**
! 60: * Implements the hook_t interface.
! 61: */
! 62: hook_t hook;
! 63:
! 64: /**
! 65: * Delay for reset
! 66: */
! 67: int delay;
! 68:
! 69: /**
! 70: * Sequence number to set for outgoing packages
! 71: */
! 72: int oseq;
! 73: };
! 74:
! 75: typedef struct reset_cb_data_t reset_cb_data_t;
! 76:
! 77: /**
! 78: * Data needed for the callback job
! 79: */
! 80: struct reset_cb_data_t {
! 81:
! 82: /**
! 83: * The SA to modify
! 84: */
! 85: struct xfrm_usersa_id usersa;
! 86:
! 87: /**
! 88: * Sequence number to set for outgoing packages
! 89: */
! 90: int oseq;
! 91: };
! 92:
! 93: /**
! 94: * Callback job
! 95: */
! 96: static job_requeue_t reset_cb(struct reset_cb_data_t *data)
! 97: {
! 98: netlink_buf_t request;
! 99: struct nlmsghdr *hdr;
! 100: struct xfrm_aevent_id *id;
! 101: struct rtattr *rthdr;
! 102: struct xfrm_replay_state *rpstate;
! 103: struct sockaddr_nl addr;
! 104: int s, len;
! 105:
! 106: DBG1(DBG_CFG, "setting sequence number of SPI 0x%x to %d",
! 107: htonl(data->usersa.spi), data->oseq);
! 108:
! 109: memset(&request, 0, sizeof(request));
! 110:
! 111: hdr = &request.hdr;
! 112: hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
! 113: hdr->nlmsg_seq = 201;
! 114: hdr->nlmsg_pid = getpid();
! 115: hdr->nlmsg_type = XFRM_MSG_NEWAE;
! 116: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
! 117:
! 118: id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr);
! 119: id->sa_id = data->usersa;
! 120:
! 121: rthdr = XFRM_RTA(hdr, struct xfrm_aevent_id);
! 122: rthdr->rta_type = XFRMA_REPLAY_VAL;
! 123: rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
! 124: hdr->nlmsg_len += rthdr->rta_len;
! 125:
! 126: /* xfrm_replay_state is the structure the kernel uses for
! 127: * replay detection, and the oseq element contains the
! 128: * sequence number for outgoing packets. Currently, this
! 129: * function sets the other elements seq (records the number of
! 130: * incoming packets) and bitmask to zero, but they could be
! 131: * adjusted in the same way as oseq if required. */
! 132: rpstate = (struct xfrm_replay_state*)RTA_DATA(rthdr);
! 133: rpstate->oseq = data->oseq;
! 134:
! 135: s = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
! 136: if (s == -1)
! 137: {
! 138: DBG1(DBG_CFG, "opening XFRM socket failed: %s", strerror(errno));
! 139: return JOB_REQUEUE_NONE;
! 140: }
! 141: memset(&addr, 0, sizeof(addr));
! 142: addr.nl_family = AF_NETLINK;
! 143: len = sendto(s, hdr, hdr->nlmsg_len, 0,
! 144: (struct sockaddr*)&addr, sizeof(addr));
! 145: if (len != hdr->nlmsg_len)
! 146: {
! 147: DBG1(DBG_CFG, "sending XFRM aevent failed: %s", strerror(errno));
! 148: }
! 149: close(s);
! 150: return JOB_REQUEUE_NONE;
! 151: }
! 152:
! 153: /**
! 154: * Schedule sequence number reset job
! 155: */
! 156: static void schedule_reset_job(private_reset_seq_t *this, host_t *dst,
! 157: uint32_t spi)
! 158: {
! 159: struct reset_cb_data_t *data;
! 160: chunk_t chunk;
! 161:
! 162: INIT(data,
! 163: .usersa = {
! 164: .spi = spi,
! 165: .family = dst->get_family(dst),
! 166: .proto = IPPROTO_ESP,
! 167: },
! 168: .oseq = this->oseq,
! 169: );
! 170:
! 171: chunk = dst->get_address(dst);
! 172: memcpy(&data->usersa.daddr, chunk.ptr,
! 173: min(chunk.len, sizeof(xfrm_address_t)));
! 174:
! 175: lib->scheduler->schedule_job(lib->scheduler,
! 176: (job_t*)callback_job_create(
! 177: (void*)reset_cb, data, (void*)free, NULL),
! 178: this->delay);
! 179: }
! 180:
! 181: METHOD(listener_t, child_updown, bool,
! 182: private_reset_seq_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
! 183: bool up)
! 184: {
! 185: if (up)
! 186: {
! 187: schedule_reset_job(this, ike_sa->get_other_host(ike_sa),
! 188: child_sa->get_spi(child_sa, FALSE));
! 189: }
! 190: return TRUE;
! 191: }
! 192:
! 193: METHOD(hook_t, destroy, void,
! 194: private_reset_seq_t *this)
! 195: {
! 196: free(this);
! 197: }
! 198:
! 199: /**
! 200: * Create the IKE_AUTH fill hook
! 201: */
! 202: hook_t *reset_seq_hook_create(char *name)
! 203: {
! 204: private_reset_seq_t *this;
! 205:
! 206: INIT(this,
! 207: .hook = {
! 208: .listener = {
! 209: .child_updown = _child_updown,
! 210: },
! 211: .destroy = _destroy,
! 212: },
! 213: .delay = conftest->test->get_int(conftest->test,
! 214: "hooks.%s.delay", 10, name),
! 215: .oseq = conftest->test->get_int(conftest->test,
! 216: "hooks.%s.oseq", 0, name),
! 217: );
! 218:
! 219: return &this->hook;
! 220: }
! 221:
! 222: #endif /* __linux__ */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>