7313aedcec9036f3733eb8f3490788a80156255e
[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 sockaddr_t address;
53
54 /**
55 * length of address structure
56 */
57 socklen_t socklen;
58 };
59
60
61 /**
62 * implements host_t.get_sockaddr
63 */
64 static sockaddr_t *get_sockaddr(private_host_t *this)
65 {
66 return &(this->address);
67 }
68
69 /**
70 * implements host_t.get_sockaddr_len
71 */
72 static socklen_t *get_sockaddr_len(private_host_t *this)
73 {
74 return &(this->socklen);
75 }
76
77 /**
78 * Implementation of host_t.is_default_route.
79 */
80 static bool is_default_route (private_host_t *this)
81 {
82 switch (this->family)
83 {
84 case AF_INET:
85 {
86 static u_int8_t default_route[4] = {0x00,0x00,0x00,0x00};
87 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
88
89 if (memcmp(default_route,&(sin->sin_addr.s_addr),4) == 0)
90 {
91 return TRUE;
92 }
93 return FALSE;
94 }
95 default:
96 {
97 /* empty chunk is returned */
98 return FALSE;
99 }
100 }
101 }
102
103 /**
104 * implements host_t.get_address
105 */
106 static char *get_address(private_host_t *this)
107 {
108 switch (this->family)
109 {
110 case AF_INET:
111 {
112 char *string;
113 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
114 allocator_free(this->string);
115 string = inet_ntoa(sin->sin_addr);
116 this->string = allocator_alloc(strlen(string)+1);
117 strcpy(this->string, string);
118 return this->string;
119 }
120 default:
121 {
122 return "(family not supported)";
123 }
124 }
125 }
126
127 /**
128 * Implementation of host_t.get_address_as_chunk.
129 */
130 static chunk_t get_address_as_chunk(private_host_t *this)
131 {
132 chunk_t address = CHUNK_INITIALIZER;
133
134 switch (this->family)
135 {
136 case AF_INET:
137 {
138 /* allocate 4 bytes for IPV4 address*/
139 address.ptr = allocator_alloc(4);
140 address.len = 4;
141 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
142 memcpy(address.ptr,&(sin->sin_addr.s_addr),4);
143 }
144 default:
145 {
146 /* empty chunk is returned */
147 return address;
148 }
149 }
150
151 }
152
153 /**
154 * implements host_t.get_port
155 */
156 static u_int16_t get_port(private_host_t *this)
157 {
158 switch (this->family)
159 {
160 case AF_INET:
161 {
162 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
163 return ntohs(sin->sin_port);
164 }
165 default:
166 {
167 return 0;
168 }
169 }
170 }
171
172
173 /**
174 * Implements host_t.clone.
175 */
176 static private_host_t *clone(private_host_t *this)
177 {
178 private_host_t *new = allocator_alloc_thing(private_host_t);
179
180
181 memcpy(new, this, sizeof(private_host_t));
182 if (this->string)
183 {
184 new->string = allocator_alloc(strlen(this->string)+1);
185 strcpy(new->string, this->string);
186 }
187 return new;
188 }
189
190
191 /**
192 * Impelements host_t.equals
193 */
194 static bool ip_is_equal(private_host_t *this, private_host_t *other)
195 {
196 switch (this->family)
197 {
198 /* IPv4 */
199 case AF_INET:
200 {
201 struct sockaddr_in *sin1 = (struct sockaddr_in*)&(this->address);
202 struct sockaddr_in *sin2 = (struct sockaddr_in*)&(other->address);
203 if ((sin1->sin_family == sin2->sin_family) &&
204 (sin1->sin_addr.s_addr == sin2->sin_addr.s_addr))
205 {
206 return TRUE;
207 }
208 }
209 }
210 return FALSE;
211 }
212
213 /**
214 * Implements host_t.destroy
215 */
216 static void destroy(private_host_t *this)
217 {
218 allocator_free(this->string);
219 allocator_free(this);
220 }
221
222 /**
223 * Creates an empty host_t object
224 */
225 static private_host_t *host_create_empty()
226 {
227 private_host_t *this = allocator_alloc_thing(private_host_t);
228
229 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
230 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
231 this->public.clone = (host_t* (*) (host_t*))clone;
232 this->public.get_address = (char* (*) (host_t *))get_address;
233 this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
234 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
235 this->public.ip_is_equal = (bool (*) (host_t *,host_t *)) ip_is_equal;
236 this->public.is_default_route = (bool (*) (host_t *)) is_default_route;
237 this->public.destroy = (void (*) (host_t*))destroy;
238
239 this->string = NULL;
240
241 return this;
242 }
243
244 /*
245 * Described in header.
246 */
247 host_t *host_create(int family, char *address, u_int16_t port)
248 {
249 private_host_t *this = host_create_empty();
250
251 this->family = family;
252
253 switch (family)
254 {
255 /* IPv4 */
256 case AF_INET:
257 {
258 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
259 sin->sin_family = AF_INET;
260 sin->sin_addr.s_addr = inet_addr(address);
261 sin->sin_port = htons(port);
262 this->socklen = sizeof(struct sockaddr_in);
263 return &(this->public);
264 }
265 default:
266 {
267 allocator_free(this);
268 return NULL;
269
270 }
271 }
272
273 }
274
275 /*
276 * Described in header.
277 */
278 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
279 {
280 private_host_t *this = host_create_empty();
281
282 this->family = family;
283
284 if (address.len == 4)
285 {
286 switch (family)
287 {
288 /* IPv4 */
289 case AF_INET:
290 {
291 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
292 sin->sin_family = AF_INET;
293 memcpy(&(sin->sin_addr.s_addr),address.ptr,4);
294 sin->sin_port = htons(port);
295 this->socklen = sizeof(struct sockaddr_in);
296 return &(this->public);
297 }
298
299 }
300 }
301 allocator_free(this);
302 return NULL;
303 }