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