f78e7b810b87e273f258de4bdf62cb1a0ea33bbc
[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 * implements host_t.get_address
74 */
75 static char *get_address(private_host_t *this)
76 {
77 switch (this->family)
78 {
79 case AF_INET:
80 {
81 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
82 return inet_ntoa(sin->sin_addr);
83 }
84 default:
85 {
86 return "(family not supported)";
87 }
88 }
89 }
90
91 /**
92 * Implementation of host_t.get_address_as_chunk.
93 */
94 static chunk_t get_address_as_chunk(private_host_t *this)
95 {
96 chunk_t address = CHUNK_INITIALIZER;
97
98 switch (this->family)
99 {
100 case AF_INET:
101 {
102 /* allocate 4 bytes for IPV4 address*/
103 address.ptr = allocator_alloc(4);
104 address.len = 4;
105 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
106 memcpy(address.ptr,&(sin->sin_addr.s_addr),4);
107 }
108 default:
109 {
110 /* empty chunk is returned */
111 return address;
112 }
113 }
114
115 }
116
117 /**
118 * implements host_t.get_port
119 */
120 static u_int16_t get_port(private_host_t *this)
121 {
122 switch (this->family)
123 {
124 case AF_INET:
125 {
126 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
127 return ntohs(sin->sin_port);
128 }
129 default:
130 {
131 return 0;
132 }
133 }
134 }
135
136 /**
137 * Implements host_t.destroy
138 */
139 static void destroy(private_host_t *this)
140 {
141 allocator_free(this);
142 }
143
144 /**
145 * Implements host_t.clone.
146 */
147 static private_host_t *clone(private_host_t *this)
148 {
149 private_host_t *new = allocator_alloc_thing(private_host_t);
150
151 memcpy(new, this, sizeof(private_host_t));
152 return new;
153 }
154
155
156 /**
157 * Impelements host_t.equals
158 */
159 static bool equals(private_host_t *this, private_host_t *other)
160 {
161 switch (this->family)
162 {
163 /* IPv4 */
164 case AF_INET:
165 {
166 struct sockaddr_in *sin1 = (struct sockaddr_in*)&(this->address);
167 struct sockaddr_in *sin2 = (struct sockaddr_in*)&(other->address);
168 if ((sin1->sin_family == sin2->sin_family) &&
169 (sin1->sin_port == sin2->sin_port) &&
170 (sin1->sin_addr.s_addr == sin2->sin_addr.s_addr))
171 {
172 return TRUE;
173 }
174 }
175 }
176 return FALSE;
177 }
178
179
180 /*
181 * Described in header.
182 */
183 host_t *host_create(int family, char *address, u_int16_t port)
184 {
185 private_host_t *this = allocator_alloc_thing(private_host_t);
186
187 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
188 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
189 this->public.clone = (host_t* (*) (host_t*))clone;
190 this->public.get_address = (char* (*) (host_t *))get_address;
191 this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
192 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
193 this->public.destroy = (void (*) (host_t*))destroy;
194
195 this->family = family;
196
197 switch (family)
198 {
199 /* IPv4 */
200 case AF_INET:
201 {
202 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
203 sin->sin_family = AF_INET;
204 sin->sin_addr.s_addr = inet_addr(address);
205 sin->sin_port = htons(port);
206 this->socklen = sizeof(struct sockaddr_in);
207 return (host_t*)this;
208 }
209 }
210 allocator_free(this);
211 return NULL;
212 }
213
214 /*
215 * Described in header.
216 */
217 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
218 {
219 private_host_t *this = allocator_alloc_thing(private_host_t);
220
221 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
222 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
223 this->public.clone = (host_t* (*) (host_t*))clone;
224 this->public.get_address = (char* (*) (host_t *))get_address;
225 this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
226 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
227 this->public.equals = (bool (*) (host_t *,host_t *))equals;
228 this->public.destroy = (void (*) (host_t*))destroy;
229
230 this->family = family;
231
232 if (address.len == 4)
233 {
234 switch (family)
235 {
236 /* IPv4 */
237 case AF_INET:
238 {
239 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
240 sin->sin_family = AF_INET;
241 memcpy(&(sin->sin_addr.s_addr),address.ptr,4);
242 sin->sin_port = htons(port);
243 this->socklen = sizeof(struct sockaddr_in);
244 return (host_t*)this;
245 }
246 }
247 }
248 allocator_free(this);
249 return NULL;
250 }