vfs: check userland buffers before reading them.
[haiku.git] / src / kits / network / libnetapi / NetAddress.cpp
blob734363cbee31eb63225a91d3d9e8e0d05cd70674
1 /*
2 * Copyright 2002-2006,2008, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Scott T. Mansfield, thephantom@mac.com
7 * Oliver Tappe, zooey@hirschkaefer.de
8 */
10 /*!
11 NetAddress.cpp -- Implementation of the BNetAddress class.
12 Remarks:
13 * In all accessors, non-struct output values are converted from network to
14 host byte order.
15 * In all mutators, non-struct input values are converted from host to
16 network byte order.
17 * No trouts were harmed during the development of this class.
20 #include <r5_compatibility.h>
22 #include <ByteOrder.h>
23 #include <NetAddress.h>
24 #include <Message.h>
26 #include <arpa/inet.h>
27 #include <netdb.h>
28 #include <netinet/in.h>
29 #include <new>
30 #include <string.h>
33 BNetAddress::BNetAddress(const char* hostname, unsigned short port)
35 fInit(B_NO_INIT)
37 SetTo(hostname, port);
41 BNetAddress::BNetAddress(const struct sockaddr_in& addr)
43 fInit(B_NO_INIT)
45 SetTo(addr);
49 BNetAddress::BNetAddress(in_addr addr, int port)
51 fInit(B_NO_INIT)
53 SetTo(addr, port);
57 BNetAddress::BNetAddress(uint32 addr, int port)
59 fInit(B_NO_INIT)
61 SetTo(addr, port);
65 BNetAddress::BNetAddress(const char* hostname, const char* protocol,
66 const char* service)
68 fInit(B_NO_INIT)
70 SetTo(hostname, protocol, service);
74 BNetAddress::BNetAddress(const BNetAddress& other)
76 *this = other;
80 BNetAddress::BNetAddress(BMessage* archive)
82 int16 int16value;
83 if (archive->FindInt16("bnaddr_family", &int16value) != B_OK)
84 return;
86 fFamily = int16value;
88 if (archive->FindInt16("bnaddr_port", &int16value) != B_OK)
89 return;
91 fPort = int16value;
93 if (archive->FindInt32("bnaddr_addr", &fAddress) != B_OK)
94 return;
96 fInit = B_OK;
100 BNetAddress::~BNetAddress()
105 BNetAddress&
106 BNetAddress::operator=(const BNetAddress& other)
108 fInit = other.fInit;
109 fFamily = other.fFamily;
110 fPort = other.fPort;
111 fAddress = other.fAddress;
113 return *this;
117 /* GetAddr
118 *=--------------------------------------------------------------------------=*
119 * Purpose:
120 * Class accessor.
122 * Output parameters:
123 * hostname: Host name associated with this instance (default: NULL).
124 * In this particular implementation, hostname will be an
125 * ASCII-fied representation of an IP address.
127 * port: Port number associated with this instance
128 * (default: NULL). Will be converted to host byte order
129 * here, so it is not necessary to call ntohs() after
130 * calling this method.
132 * Returns:
133 * B_OK for success, B_NO_INIT if instance was not properly constructed.
135 * Remarks:
136 * Hostname and/or port can be NULL; although having them both NULL would
137 * be a pointless waste of CPU cycles. ;-)
139 * The hostname output parameter can be a variety of things, but in this
140 * method we convert the IP address to a string. See the relevant
141 * documentation about inet_ntoa() for details.
143 * Make sure hostname is large enough or you will step on someone
144 * else's toes. (Can you say "buffer overflow exploit" boys and girls?)
145 * You can generally be safe using the MAXHOSTNAMELEN define, which
146 * defaults to 64 bytes--don't forget to leave room for the NULL!
148 status_t
149 BNetAddress::GetAddr(char* hostname, unsigned short* port) const
151 if (fInit != B_OK)
152 return B_NO_INIT;
154 if (port != NULL)
155 *port = ntohs(fPort);
157 if (hostname != NULL) {
158 struct in_addr addr;
159 addr.s_addr = fAddress;
161 char* text = inet_ntoa(addr);
162 if (text != NULL)
163 strcpy(hostname, text);
166 return B_OK;
170 /* GetAddr
171 *=--------------------------------------------------------------------------=*
172 * Purpose:
173 * Class accessor.
175 * Output parameter:
176 * sa: sockaddr_in struct to be filled.
178 * Returns:
179 * B_OK for success, B_NO_INIT if instance was not properly constructed.
181 * Remarks:
182 * This method fills in the sin_addr, sin_family, and sin_port fields of
183 * the output parameter, all other fields are untouched so we can work
184 * with both POSIX and non-POSIX versions of said struct. The port and
185 * address values added to the output parameter are in network byte order.
187 status_t BNetAddress::GetAddr(struct sockaddr_in& sa) const
189 if (fInit != B_OK)
190 return B_NO_INIT;
192 sa.sin_port = fPort;
193 sa.sin_addr.s_addr = fAddress;
194 if (check_r5_compatibility()) {
195 r5_sockaddr_in* r5Addr = (r5_sockaddr_in*)&sa;
196 if (fFamily == AF_INET)
197 r5Addr->sin_family = R5_AF_INET;
198 else
199 r5Addr->sin_family = fFamily;
200 } else
201 sa.sin_family = fFamily;
203 return B_OK;
207 /* GetAddr
208 *=--------------------------------------------------------------------------=*
209 * Purpose:
210 * Class accessor.
212 * Output parameters:
213 * addr: in_addr struct to fill.
214 * port: optional port number to fill.
216 * Returns:
217 * B_OK for success, B_NO_INIT if instance was not properly constructed.
219 * Remarks:
220 * Output port will be in host byte order, but addr will be in the usual
221 * network byte order (ready to be used by other network functions).
223 status_t BNetAddress::GetAddr(in_addr& addr, unsigned short* port) const
225 if (fInit != B_OK)
226 return B_NO_INIT;
228 addr.s_addr = fAddress;
230 if (port != NULL)
231 *port = ntohs(fPort);
233 return B_OK;
237 /* InitCheck
238 *=--------------------------------------------------------------------------=*
239 * Purpose:
240 * Determine whether or not this instance is properly initialized.
242 * Returns:
243 * B_OK if this instance is initialized, B_ERROR if not.
245 status_t BNetAddress::InitCheck() const
247 return fInit == B_OK ? B_OK : B_ERROR;
251 status_t BNetAddress::InitCheck()
253 return const_cast<const BNetAddress*>(this)->InitCheck();
257 /* Archive
258 *=--------------------------------------------------------------------------=*
259 * Purpose:
260 * Serialize this instance into the passed BMessage parameter.
262 * Input parameter:
263 * deep: [ignored] default==true.
265 * Output parameter:
266 * into: BMessage object to serialize into.
268 * Returns:
269 * B_OK/BERROR on success/failure. Returns B_NO_INIT if instance not
270 * properly initialized.
272 status_t BNetAddress::Archive(BMessage* into, bool deep) const
274 if (fInit != B_OK)
275 return B_NO_INIT;
277 if (into->AddInt16("bnaddr_family", fFamily) != B_OK)
278 return B_ERROR;
280 if (into->AddInt16("bnaddr_port", fPort) != B_OK)
281 return B_ERROR;
283 if (into->AddInt32("bnaddr_addr", fAddress) != B_OK)
284 return B_ERROR;
286 return B_OK;
290 /* Instantiate
291 *=--------------------------------------------------------------------------=*
292 * Purpose:
293 * Un-serialize and instantiate from the passed BMessage parameter.
295 * Input parameter:
296 * archive: Archived BMessage object for (de)serialization.
298 * Returns:
299 * NULL if a BNetAddress instance can not be initialized, otherwise
300 * a new BNetAddress object instantiated from the BMessage parameter.
302 BArchivable*
303 BNetAddress::Instantiate(BMessage* archive)
305 if (!validate_instantiation(archive, "BNetAddress"))
306 return NULL;
308 BNetAddress* address = new (std::nothrow) BNetAddress(archive);
309 if (address == NULL)
310 return NULL;
312 if (address->InitCheck() != B_OK) {
313 delete address;
314 return NULL;
317 return address;
321 /* SetTo
322 *=--------------------------------------------------------------------------=*
323 * Purpose:
324 * Set hostname and port network address data.
326 * Input parameters:
327 * hostname: Can be one of three things:
328 * 1. An ASCII-string representation of an IP address.
329 * 2. A canonical hostname.
330 * 3. NULL. If NULL, then by default the address will be
331 * set to INADDR_ANY (0.0.0.0).
332 * port: Duh.
334 * Returns:
335 * B_OK/B_ERROR for success/failure.
337 status_t
338 BNetAddress::SetTo(const char* hostname, unsigned short port)
340 if (hostname == NULL)
341 return B_ERROR;
343 in_addr_t addr = INADDR_ANY;
345 // Try like all git-out to set the address from the given hostname.
347 // See if the string is an ASCII-fied IP address.
348 addr = inet_addr(hostname);
349 if (addr == INADDR_ANY || addr == (in_addr_t)-1) {
350 // See if we can resolve the hostname to an IP address.
351 struct hostent* host = gethostbyname(hostname);
352 if (host != NULL)
353 addr = *(int*)host->h_addr_list[0];
354 else
355 return B_ERROR;
358 fFamily = AF_INET;
359 fPort = htons(port);
360 fAddress = addr;
362 return fInit = B_OK;
367 Set from passed in sockaddr_in address.
369 \param addr address
370 \return B_OK.
372 status_t
373 BNetAddress::SetTo(const struct sockaddr_in& addr)
375 fPort = addr.sin_port;
376 fAddress = addr.sin_addr.s_addr;
378 if (check_r5_compatibility()) {
379 const r5_sockaddr_in* r5Addr = (const r5_sockaddr_in*)&addr;
380 if (r5Addr->sin_family == R5_AF_INET)
381 fFamily = AF_INET;
382 else
383 fFamily = r5Addr->sin_family;
384 } else
385 fFamily = addr.sin_family;
387 return fInit = B_OK;
392 Set from passed in address and port.
394 \param addr IP address in network form.
395 \param port Optional port number.
397 \return B_OK.
399 status_t
400 BNetAddress::SetTo(in_addr addr, int port)
402 fFamily = AF_INET;
403 fPort = htons((short)port);
404 fAddress = addr.s_addr;
406 return fInit = B_OK;
411 Set from passed in address and port.
413 \param addr IP address in network form.
414 \param port Optional port number.
416 \return B_OK.
418 status_t
419 BNetAddress::SetTo(uint32 addr, int port)
421 fFamily = AF_INET;
422 fPort = htons((short)port);
423 fAddress = addr;
425 return fInit = B_OK;
429 /* SetTo
430 *=--------------------------------------------------------------------------=*
431 * Purpose:
432 * Set from passed in hostname and protocol/service information.
434 * Input parameters:
435 * hostname: Can be one of three things:
436 * 1. An ASCII-string representation of an IP address.
437 * 2. A canonical hostname.
438 * 3. NULL. If NULL, then by default the address will be
439 * set to INADDR_ANY (0.0.0.0).
440 * protocol: Datagram type, typically "TCP" or "UDP"
441 * service: The name of the service, such as http, ftp, et al. This
442 * must be one of the official service names listed in
443 * /etc/services -- but you already knew that because
444 * you're doing network/sockets programming, RIIIGHT???.
446 * Returns:
447 * B_OK/B_ERROR on success/failure.
449 * Remarks:
450 * The protocol and service input parameters must be one of the official
451 * types listed in /etc/services. We use these two parameters to
452 * determine the port number (see getservbyname(3)). This method will
453 * fail if the aforementioned precondition is not met.
455 status_t
456 BNetAddress::SetTo(const char* hostname, const char* protocol,
457 const char* service)
459 struct servent* serviceEntry = getservbyname(service, protocol);
460 if (serviceEntry == NULL)
461 return B_ERROR;
463 return SetTo(hostname, serviceEntry->s_port);
467 // #pragma mark - FBC
470 void BNetAddress::_ReservedBNetAddressFBCCruft1() {}
471 void BNetAddress::_ReservedBNetAddressFBCCruft2() {}
472 void BNetAddress::_ReservedBNetAddressFBCCruft3() {}
473 void BNetAddress::_ReservedBNetAddressFBCCruft4() {}
474 void BNetAddress::_ReservedBNetAddressFBCCruft5() {}
475 void BNetAddress::_ReservedBNetAddressFBCCruft6() {}