- started implementation of netlink kernel interface
[strongswan.git] / Source / charon / threads / kernel_interface.c
1 /**
2 * @file kernel_interface.c
3 *
4 * @brief Implementation of kernel_interface_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <linux/netlink.h>
26 #include <linux/xfrm.h>
27 #include <pthread.h>
28
29 #include "kernel_interface.h"
30
31 #include <utils/allocator.h>
32 #include <utils/linked_list.h>
33 #include <network/host.h>
34 #include <encoding/payloads/proposal_substructure.h>
35
36
37 typedef struct netlink_message_t netlink_message_t;
38
39 struct netlink_message_t {
40
41 /**
42 * header of the netlink message
43 */
44 struct nlmsghdr hdr;
45
46 union {
47 struct nlmsgerr e;
48 struct xfrm_userspi_info spi;
49 struct xfrm_usersa_info sa;
50 };
51
52 u_int8_t data[];
53 };
54
55
56 typedef struct private_kernel_interface_t private_kernel_interface_t;
57
58 /**
59 * @brief Private Variables and Functions of kernel_interface class
60 *
61 */
62 struct private_kernel_interface_t {
63 /**
64 * Public part of the kernel_interface_t object
65 */
66 kernel_interface_t public;
67
68 /**
69 * netlink communication socket
70 */
71 int socket;
72
73 /**
74 * since we use multiple threads, we can't call
75 * getpid multiple times. The pid is set once.
76 */
77 pid_t pid;
78
79 /**
80 * sequence number for messages
81 */
82 u_int32_t seq;
83
84 /**
85 * list of replies messages
86 */
87 linked_list_t *replies;
88
89 /**
90 * Function for the thread, receives messages
91 */
92 void (*receive_messages) (private_kernel_interface_t *this);
93
94 /**
95 * Sends a netlink_message_t down to the kernel
96 */
97 void (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t *response);
98 };
99
100
101 //static u_int32_t get_spi(private_kernel_interface_t *this, host_t *src, host_t *dest, protocol_id_t protocol, bool tunnel_mode)
102 //{
103 // netlink_message_t request, response;
104 //
105 // memset(&request, 0, sizeof(request));
106 // request.hdr.nlmsg_flags = NLM_F_REQUEST;
107 // request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
108 // request.spi.info.saddr = src->get_xfrm_addr(src);
109 // request.spi.info.id.daddr = dest->get_xfrm_addr(dest);
110 // request.spi.info.mode = tunnel_mode;
111 // request.spi.info.id.proto = protocol;
112 // request.spi.info.family = src->get_family(src);
113 // request.spi.min = 0;
114 // request.spi.max = 50000;
115 // request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi)));
116 //
117 // this->send_message(this, &request, &response);
118 //
119 // if (response.hdr.nlmsg_type == NLMSG_ERROR)
120 // {
121 // /* error handling */
122 // }
123 // else if (response.hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response.sa)))
124 // {
125 // /* error handling */
126 // }
127 //
128 // return response.sa.id.spi;
129 //}
130 //
131 //
132 //
133 //static status_t send_message(private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t *response)
134 //{
135 // size_t length;
136 // ssize_t r;
137 //
138 // length = request->hdr.nlmsg_len;
139 //
140 //
141 //
142 //
143 //
144 // size_t len;
145 // ssize_t r;
146 //
147 //
148 //
149 // request->hdr.nlmsg_seq = ++this->seq;
150 // length = request->hdr.nlmsg_len;
151 //
152 // do {
153 // r = write(netlinkfd, hdr, len);
154 // } while (r < 0 && errno == EINTR);
155 //
156 // if (r < 0)
157 // {
158 // return FAILED;
159 // }
160 // else if ((size_t)r != len)
161 // {
162 // return FAILED;
163 // }
164 //
165 //
166 // /* wait for receiver thread */
167 //
168 // return TRUE;
169 //}
170 //
171 //
172 //static void receive_messages(private_kernel_interface_t *this)
173 //{
174 // while(TRUE)
175 // {
176 // netlink_message_t *response;
177 //
178 //
179 // socklen_t addr_length;
180 // struct sockaddr_nl addr;
181 // size_t length;
182 //
183 // addr_length = sizeof(addr);
184 // length = recvfrom(netlinkfd, &rsp, sizeof(rsp), 0, (struct sockaddr*)&addr, &addr_length);
185 // if (r < 0)
186 // {
187 // if (errno == EINTR)
188 // {
189 // continue;
190 // }
191 // return FAILED;
192 // }
193 // else if ((size_t) r < sizeof(rsp.n))
194 // {
195 // /* not enought bytes for header */
196 // continue;
197 // }
198 // else if (addr.nl_pid != 0)
199 // {
200 // /* not interested */
201 // continue;
202 // }
203 // else if (rsp.n.nlmsg_seq != seq)
204 // {
205 // DBG(DBG_KLIPS,
206 // DBG_log("netlink: ignoring out of sequence (%u/%u) message %s"
207 // , rsp.n.nlmsg_seq, seq
208 // , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)));
209 // continue;
210 // }
211 // break;
212 // }
213 //
214 // if (rsp.n.nlmsg_len > (size_t) r)
215 // {
216 // return FALSE;
217 // }
218 // else if (rsp.n.nlmsg_type != NLMSG_ERROR
219 // && (rbuf && rsp.n.nlmsg_type != rbuf->nlmsg_type))
220 // {
221 // loglog(RC_LOG_SERIOUS
222 // , "netlink recvfrom() of response to our %s message"
223 // " for %s %s was of wrong type (%s)"
224 // , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
225 // , description, text_said
226 // , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type));
227 // return FALSE;
228 // }
229 // else if (rbuf)
230 // {
231 // if ((size_t) r > rbuf_len)
232 // {
233 // loglog(RC_LOG_SERIOUS
234 // , "netlink recvfrom() of response to our %s message"
235 // " for %s %s was too long: %ld > %lu"
236 // , sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
237 // , description, text_said
238 // , (long)r, (unsigned long)rbuf_len);
239 // return FALSE;
240 // }
241 // memcpy(rbuf, &rsp, r);
242 // return TRUE;
243 // }
244 // else if (rsp.n.nlmsg_type == NLMSG_ERROR && rsp.e.error)
245 // {
246 // loglog(RC_LOG_SERIOUS
247 // , "ERROR: netlink response for %s %s included errno %d: %s"
248 // , description, text_said
249 // , -rsp.e.error
250 // , strerror(-rsp.e.error));
251 // return FALSE;
252 // }
253 //}
254
255
256
257 /**
258 * implements kernel_interface_t.destroy
259 */
260 static void destroy (private_kernel_interface_t *this)
261 {
262 allocator_free(this);
263 }
264
265 /*
266 * Documented in header
267 */
268 kernel_interface_t *kernel_interface_create()
269 {
270 private_kernel_interface_t *this = allocator_alloc_thing(private_kernel_interface_t);
271
272 /* public functions */
273 this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
274
275 /* private members */
276 this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM);
277
278 return (&this->public);
279 }