/* vim: set expandtab ts=4 sw=4: */
/*
* You may redistribute this program and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef Sockaddr_H
#define Sockaddr_H
#include "memory/Allocator.h"
#include "util/Endian.h"
#include "util/Linker.h"
Linker_require("util/platform/Sockaddr.c")
#include
typedef struct Sockaddr
{
/** the length of this sockaddr, this field is included in the length. */
uint16_t addrLen;
#define Sockaddr_flags_BCAST 1
#define Sockaddr_flags_PREFIX (1<<1)
uint8_t flags;
#define Sockaddr_PLATFORM 0
#define Sockaddr_HANDLE 1
uint8_t type;
/** Only applies if flags & Sockaddr_flags_PREFIX is true. */
uint8_t prefix;
uint8_t pad1;
uint16_t pad2;
} Sockaddr_t;
/** The number of bytes of space taken for representing the addrLen at the beginning. */
#define Sockaddr_OVERHEAD 8
/** The maximum possible size for the native sockaddr (not including Sockaddr_OVERHEAD) */
#define Sockaddr_MAXSIZE 128
struct Sockaddr_storage
{
Sockaddr_t addr;
uint64_t nativeAddr[Sockaddr_MAXSIZE / 8];
};
/** 127.0.0.1 and ::1 addresses for building from. */
extern const Sockaddr_t* const Sockaddr_LOOPBACK_be;
extern const Sockaddr_t* const Sockaddr_LOOPBACK_le;
#define Sockaddr_LOOPBACK (Endian_isBigEndian() ? Sockaddr_LOOPBACK_be : Sockaddr_LOOPBACK_le)
extern const Sockaddr_t* const Sockaddr_LOOPBACK6;
/**
* Parse an internal form of Sockaddr which is used to represent a uint32_t handle.
* If the length of the address is not equal to sizeof(Sockaddr_t) or the type is not
* Sockaddr_HANDLE then this returns Sockaddr_addrHandle_INVALID.
*/
#define Sockaddr_addrHandle_INVALID 0xffffffffu
uint32_t Sockaddr_addrHandle(const Sockaddr_t* addr);
/**
* Create a handle sockaddr from a numeric handle, if handle is equal to
* Sockaddr_addrHandle_INVALID then this will trigger an assertion.
*/
void Sockaddr_addrFromHandle(Sockaddr_t* addr, uint32_t handle);
int Sockaddr_getPrefix(Sockaddr_t* addr);
/**
* Parse a sockaddr from a string, may be IP4 or IP6.
*
* @param str a string representation of the sockaddr.
* @param output a sockaddr_storage to populate, if null then the validity of the string will be
* checked only.
* @return 0 if all goes well, -1 if there is an error.
*/
int Sockaddr_parse(const char* str, struct Sockaddr_storage* out);
/**
* Convert a sockaddr to a printable string.
*/
char* Sockaddr_print(Sockaddr_t* addr, struct Allocator* alloc);
/**
* Get the port from a sockaddr if applicable.
*
* @param a sockaddr.
* @return the port number or -1 if not applicable to this sockaddr.
*/
int Sockaddr_getPort(const Sockaddr_t* sa);
/**
* Set the port for a sockaddr if applicable.
*
* @param sa a sockaddr.
* @param port the port number to set.
* @return 0 if all goes well, -1 if not applicable to this sockaddr.
*/
int Sockaddr_setPort(Sockaddr_t* sa, uint16_t port);
/**
* Get the address family for the address.
*
* @param a sockaddr.
* @return the AF number for this sockaddr.
*/
extern const int Sockaddr_AF_INET;
extern const int Sockaddr_AF_INET6;
int Sockaddr_getFamily(const Sockaddr_t* sa);
/**
* Get the address stored in a sockaddr.
*
* @param sa a sockaddr.
* @param addrPtr a pointer which will be set to the actual address component of the sockaddr.
* If NULL, the length will be returned only.
* @return the length of the address component in bytes, -1 if failed to parse.
*/
int Sockaddr_getAddress(Sockaddr_t* sa, void* addrPtr);
/**
* Whatever the address is, attempt to represent it as an IPv6 address.
* IPv6 addresses are easy.
* IPv4 are represented as ::ffff::aabb::ccdd
* Other addresses smaller or equal than 14 bytes are represented as fffe::
* Other addresses larger than 14 bytes are represented as ffff::<14 bytes of sha256 hash of address>
*/
void Sockaddr_asIp6(uint8_t addrOut[static 16], const Sockaddr_t* sockaddr);
/**
* Output the native form of a sockaddr.
*/
static inline void* Sockaddr_asNative(Sockaddr_t* sa)
{
return (void*)(&sa[1]);
}
/**
* @brief Initialize a Sockaddr in place from bytes.
*
* @param out The location in memory to place the sockaddr data
* @param bytes The bytes of the address, e.g. {127,0,0,1} (port not included)
* @param addrFamily The address family (Sockaddr_AF_INET / Sockaddr_AF_INET6)
* @return Sockaddr_t* which points to the memory of `out`
*/
Sockaddr_t* Sockaddr_initFromBytes(struct Sockaddr_storage* out, const uint8_t* bytes, int addrFamily);
/**
* Sockaddr_fromBytes() takes
* input as the bytes of the address eg: Sockaddr_fromBytes({127,0,0,1}, Sockaddr_AF_INET, alloc)
*/
Sockaddr_t* Sockaddr_fromBytes(const uint8_t* bytes, int addrFamily, struct Allocator* alloc);
/**
* Clone the sockaddr, the clone will use only as much memory as the type of sockaddr requires.
*/
Sockaddr_t* Sockaddr_clone(const Sockaddr_t* addr, struct Allocator* alloc);
/**
* Normalize inconsistent native sockaddr implementations
*/
void Sockaddr_normalizeNative(void* nativeSockaddr);
/**
* Get a hash for hashtable lookup.
*/
uint32_t Sockaddr_hash(const Sockaddr_t* addr);
/**
* Compare two sockaddrs for sorting, comparison does not put them in any specific order.
*/
int Sockaddr_compare(const Sockaddr_t* a, const Sockaddr_t* b);
#endif