Annotation of embedaddon/strongswan/src/conftest/hooks/reset_seq.c, revision 1.1.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>