- started implementation of netlink kernel interface
[strongswan.git] / Source / charon / network / host.c
1 /**
2 * @file host.c
3 *
4 * @brief Implementation of host_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 "host.h"
24
25 #include <utils/allocator.h>
26
27
28 typedef struct private_host_t private_host_t;
29
30 /**
31 * @brief Private Data of a host object.
32 */
33 struct private_host_t {
34 /**
35 * Public data
36 */
37 host_t public;
38
39 /**
40 * Address family to use, such as AF_INET or AF_INET6
41 */
42 int family;
43
44 /**
45 * string representation of host
46 */
47 char *string;
48
49 /**
50 * low-lewel structure, wich stores the address
51 */
52 union {
53 struct sockaddr address;
54 struct sockaddr_in address4;
55 };
56 /**
57 * length of address structure
58 */
59 socklen_t socklen;
60 };
61
62
63 /**
64 * implements host_t.get_sockaddr
65 */
66 static sockaddr_t *get_sockaddr(private_host_t *this)
67 {
68 return &(this->address);
69 }
70
71 /**
72 * implements host_t.get_sockaddr_len
73 */
74 static socklen_t *get_sockaddr_len(private_host_t *this)
75 {
76 return &(this->socklen);
77 }
78
79 /**
80 * Implementation of host_t.is_default_route.
81 */
82 static bool is_default_route (private_host_t *this)
83 {
84 switch (this->family)
85 {
86 case AF_INET:
87 {
88 static u_int8_t default_route[4] = {0x00,0x00,0x00,0x00};
89
90 if (memcmp(default_route,&(this->address4.sin_addr.s_addr),4) == 0)
91 {
92 return TRUE;
93 }
94 return FALSE;
95 }
96 default:
97 {
98 /* empty chunk is returned */
99 return FALSE;
100 }
101 }
102 }
103
104 /**
105 * implements host_t.get_address
106 */
107 static char *get_address(private_host_t *this)
108 {
109 switch (this->family)
110 {
111 case AF_INET:
112 {
113 char *string;
114 /* we need to clone it, since inet_ntoa overwrites
115 * internal buffer on subsequent calls
116 */
117 allocator_free(this->string);
118 string = inet_ntoa(this->address4.sin_addr);
119 this->string = allocator_alloc(strlen(string)+1);
120 strcpy(this->string, string);
121 return this->string;
122 }
123 default:
124 {
125 return "(family not supported)";
126 }
127 }
128 }
129
130 /**
131 * Implementation of host_t.get_address_as_chunk.
132 */
133 static chunk_t get_address_as_chunk(private_host_t *this)
134 {
135 chunk_t address = CHUNK_INITIALIZER;
136
137 switch (this->family)
138 {
139 case AF_INET:
140 {
141 /* allocate 4 bytes for IPV4 address*/
142 address.ptr = allocator_alloc(4);
143 address.len = 4;
144 memcpy(address.ptr,&(this->address4.sin_addr.s_addr),4);
145 }
146 default:
147 {
148 /* empty chunk is returned */
149 return address;
150 }
151 }
152 }
153
154 static xfrm_address_t get_xfrm_addr(private_host_t *this)
155 {
156 switch (this->family)
157 {
158 case AF_INET:
159 {
160 return (xfrm_address_t)(this->address4.sin_addr.s_addr);
161 }
162 default:
163 {
164 /* todo */
165 return (xfrm_address_t)(this->address4.sin_addr.s_addr);
166 }
167 }
168 }
169
170 static int get_family(private_host_t *this)
171 {
172 return this->family;
173 }
174
175 /**
176 * implements host_t.get_port
177 */
178 static u_int16_t get_port(private_host_t *this)
179 {
180 switch (this->family)
181 {
182 case AF_INET:
183 {
184 return ntohs(this->address4.sin_port);
185 }
186 default:
187 {
188 return 0;
189 }
190 }
191 }
192
193
194 /**
195 * Implements host_t.clone.
196 */
197 static private_host_t *clone(private_host_t *this)
198 {
199 private_host_t *new = allocator_alloc_thing(private_host_t);
200
201
202 memcpy(new, this, sizeof(private_host_t));
203 if (this->string)
204 {
205 new->string = allocator_alloc(strlen(this->string)+1);
206 strcpy(new->string, this->string);
207 }
208 return new;
209 }
210
211
212 /**
213 * Impelements host_t.equals
214 */
215 static bool ip_is_equal(private_host_t *this, private_host_t *other)
216 {
217 switch (this->family)
218 {
219 /* IPv4 */
220 case AF_INET:
221 {
222 if ((this->address4.sin_family == other->address4.sin_family) &&
223 (this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr))
224 {
225 return TRUE;
226 }
227 }
228 }
229 return FALSE;
230 }
231
232 /**
233 * Implements host_t.destroy
234 */
235 static void destroy(private_host_t *this)
236 {
237 allocator_free(this->string);
238 allocator_free(this);
239 }
240
241 /**
242 * Creates an empty host_t object
243 */
244 static private_host_t *host_create_empty()
245 {
246 private_host_t *this = allocator_alloc_thing(private_host_t);
247
248 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
249 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
250 this->public.clone = (host_t* (*) (host_t*))clone;
251 this->public.get_family = (int (*) (host_t*))get_family;
252 this->public.get_xfrm_addr = (xfrm_address_t (*) (host_t *))get_xfrm_addr;
253 this->public.get_address = (char* (*) (host_t *))get_address;
254 this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
255 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
256 this->public.ip_is_equal = (bool (*) (host_t *,host_t *)) ip_is_equal;
257 this->public.is_default_route = (bool (*) (host_t *)) is_default_route;
258 this->public.destroy = (void (*) (host_t*))destroy;
259
260 this->string = NULL;
261
262 return this;
263 }
264
265 /*
266 * Described in header.
267 */
268 host_t *host_create(int family, char *address, u_int16_t port)
269 {
270 private_host_t *this = host_create_empty();
271
272 this->family = family;
273
274 switch (family)
275 {
276 /* IPv4 */
277 case AF_INET:
278 {
279 this->address4.sin_family = AF_INET;
280 this->address4.sin_addr.s_addr = inet_addr(address);
281 this->address4.sin_port = htons(port);
282 this->socklen = sizeof(struct sockaddr_in);
283 return &(this->public);
284 }
285 default:
286 {
287 allocator_free(this);
288 return NULL;
289
290 }
291 }
292
293 }
294
295 /*
296 * Described in header.
297 */
298 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
299 {
300 private_host_t *this = host_create_empty();
301
302 this->family = family;
303 switch (family)
304 {
305 /* IPv4 */
306 case AF_INET:
307 {
308 if (address.len != 4)
309 {
310 break;
311 }
312 this->address4.sin_family = AF_INET;
313 memcpy(&(this->address4.sin_addr.s_addr),address.ptr,4);
314 this->address4.sin_port = htons(port);
315 this->socklen = sizeof(struct sockaddr_in);
316 return &(this->public);
317 }
318 }
319 allocator_free(this);
320 return NULL;
321 }