43861238f124a2f76db5129db2b78ccc59c62085
[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 * Described in header.
158 */
159 host_t *host_create(int family, char *address, u_int16_t port)
160 {
161 private_host_t *this = allocator_alloc_thing(private_host_t);
162
163 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
164 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
165 this->public.clone = (host_t* (*) (host_t*))clone;
166 this->public.get_address = (char* (*) (host_t *))get_address;
167 this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
168 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
169 this->public.destroy = (void (*) (host_t*))destroy;
170
171 this->family = family;
172
173 switch (family)
174 {
175 /* IPv4 */
176 case AF_INET:
177 {
178 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
179 sin->sin_family = AF_INET;
180 sin->sin_addr.s_addr = inet_addr(address);
181 sin->sin_port = htons(port);
182 this->socklen = sizeof(struct sockaddr_in);
183 return (host_t*)this;
184 }
185 }
186 allocator_free(this);
187 return NULL;
188 }
189
190 /*
191 * Described in header.
192 */
193 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
194 {
195 private_host_t *this = allocator_alloc_thing(private_host_t);
196
197 this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
198 this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
199 this->public.clone = (host_t* (*) (host_t*))clone;
200 this->public.get_address = (char* (*) (host_t *))get_address;
201 this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
202 this->public.get_port = (u_int16_t (*) (host_t *))get_port;
203 this->public.destroy = (void (*) (host_t*))destroy;
204
205 this->family = family;
206
207 if (address.len == 4)
208 {
209 switch (family)
210 {
211 /* IPv4 */
212 case AF_INET:
213 {
214 struct sockaddr_in *sin = (struct sockaddr_in*)&(this->address);
215 sin->sin_family = AF_INET;
216 memcpy(&(sin->sin_addr.s_addr),address.ptr,4);
217 sin->sin_port = htons(port);
218 this->socklen = sizeof(struct sockaddr_in);
219 return (host_t*)this;
220 }
221 }
222 }
223 allocator_free(this);
224 return NULL;
225 }