2 * <sys/socket.h> wrapper functions.
5 * Steffen Kiess (s-kiess@web.de)
7 * Copyright (C) 2015 Steffen Kiess
10 #include <sys/socket.h>
12 #include <netinet/in.h>
24 Mono_Posix_SockaddrStorage_get_size (void)
26 return sizeof (struct sockaddr_storage);
30 Mono_Posix_SockaddrUn_get_sizeof_sun_path (void)
32 struct sockaddr_un sun;
33 return sizeof (sun.sun_path);
37 Mono_Posix_FromInAddr (struct Mono_Posix_InAddr* source, void* destination)
39 memcpy (&((struct in_addr*)destination)->s_addr, &source->s_addr, 4);
44 Mono_Posix_ToInAddr (void* source, struct Mono_Posix_InAddr* destination)
46 memcpy (&destination->s_addr, &((struct in_addr*)source)->s_addr, 4);
51 Mono_Posix_FromIn6Addr (struct Mono_Posix_In6Addr* source, void* destination)
53 memcpy (&((struct in6_addr*)destination)->s6_addr, &source->addr0, 16);
58 Mono_Posix_ToIn6Addr (void* source, struct Mono_Posix_In6Addr* destination)
60 memcpy (&destination->addr0, &((struct in6_addr*)source)->s6_addr, 16);
66 Mono_Posix_Syscall_socketpair (int domain, int type, int protocol, int* socket1, int* socket2)
68 int filedes[2] = {-1, -1};
71 r = socketpair (domain, type, protocol, filedes);
73 *socket1 = filedes[0];
74 *socket2 = filedes[1];
79 Mono_Posix_Syscall_getsockopt (int socket, int level, int option_name, void* option_value, gint64* option_len)
84 mph_return_if_socklen_t_overflow (*option_len);
88 r = getsockopt (socket, level, option_name, option_value, &len);
96 Mono_Posix_Syscall_getsockopt_timeval (int socket, int level, int option_name, struct Mono_Posix_Timeval* option_value)
102 size = sizeof (struct timeval);
103 r = getsockopt (socket, level, option_name, &tv, &size);
105 if (r != -1 && size == sizeof (struct timeval)) {
106 if (Mono_Posix_ToTimeval (&tv, option_value) != 0)
109 memset (option_value, 0, sizeof (struct Mono_Posix_Timeval));
118 Mono_Posix_Syscall_getsockopt_linger (int socket, int level, int option_name, struct Mono_Posix_Linger* option_value)
124 size = sizeof (struct linger);
125 r = getsockopt (socket, level, option_name, &ling, &size);
127 if (r != -1 && size == sizeof (struct linger)) {
128 if (Mono_Posix_ToLinger (&ling, option_value) != 0)
131 memset (option_value, 0, sizeof (struct Mono_Posix_Linger));
140 Mono_Posix_Syscall_setsockopt (int socket, int level, int option_name, void* option_value, gint64 option_len)
142 mph_return_if_socklen_t_overflow (option_len);
144 return setsockopt (socket, level, option_name, option_value, option_len);
148 Mono_Posix_Syscall_setsockopt_timeval (int socket, int level, int option_name, struct Mono_Posix_Timeval* option_value)
152 if (Mono_Posix_FromTimeval (option_value, &tv) != 0)
155 return setsockopt (socket, level, option_name, &tv, sizeof (struct timeval));
159 Mono_Posix_Syscall_setsockopt_linger (int socket, int level, int option_name, struct Mono_Posix_Linger* option_value)
163 if (Mono_Posix_FromLinger (option_value, &ling) != 0)
166 return setsockopt (socket, level, option_name, &ling, sizeof (struct linger));
170 get_addrlen (struct Mono_Posix__SockaddrHeader* address, socklen_t* addrlen)
177 switch (address->type) {
178 case Mono_Posix_SockaddrType_SockaddrStorage:
179 mph_return_if_socklen_t_overflow (((struct Mono_Posix__SockaddrDynamic*) address)->len);
180 *addrlen = ((struct Mono_Posix__SockaddrDynamic*) address)->len;
182 case Mono_Posix_SockaddrType_SockaddrUn:
183 mph_return_if_socklen_t_overflow (offsetof (struct sockaddr_un, sun_path) + ((struct Mono_Posix__SockaddrDynamic*) address)->len);
184 *addrlen = offsetof (struct sockaddr_un, sun_path) + ((struct Mono_Posix__SockaddrDynamic*) address)->len;
186 case Mono_Posix_SockaddrType_Sockaddr: *addrlen = sizeof (struct sockaddr); return 0;
187 case Mono_Posix_SockaddrType_SockaddrIn: *addrlen = sizeof (struct sockaddr_in); return 0;
188 case Mono_Posix_SockaddrType_SockaddrIn6: *addrlen = sizeof (struct sockaddr_in6); return 0;
197 Mono_Posix_Sockaddr_GetNativeSize (struct Mono_Posix__SockaddrHeader* address, gint64* size)
202 r = get_addrlen (address, &value);
208 Mono_Posix_FromSockaddr (struct Mono_Posix__SockaddrHeader* source, void* destination)
213 switch (source->type) {
214 case Mono_Posix_SockaddrType_SockaddrStorage:
215 // Do nothing, don't copy source->sa_family into addr->sa_family
218 case Mono_Posix_SockaddrType_SockaddrUn:
219 memcpy (((struct sockaddr_un*) destination)->sun_path, ((struct Mono_Posix__SockaddrDynamic*) source)->data, ((struct Mono_Posix__SockaddrDynamic*) source)->len);
222 case Mono_Posix_SockaddrType_Sockaddr:
225 case Mono_Posix_SockaddrType_SockaddrIn:
226 if (Mono_Posix_FromSockaddrIn ((struct Mono_Posix_SockaddrIn*) source, (struct sockaddr_in*) destination) != 0)
230 case Mono_Posix_SockaddrType_SockaddrIn6:
231 if (Mono_Posix_FromSockaddrIn6 ((struct Mono_Posix_SockaddrIn6*) source, (struct sockaddr_in6*) destination) != 0)
241 if (Mono_Posix_FromUnixAddressFamily (source->sa_family, &family) != 0)
243 ((struct sockaddr*) destination)->sa_family = family;
249 Mono_Posix_ToSockaddr (void* source, gint64 size, struct Mono_Posix__SockaddrHeader* destination)
251 struct Mono_Posix__SockaddrDynamic* destination_dyn;
256 switch (destination->type) {
257 case Mono_Posix_SockaddrType_Sockaddr:
258 if (size < offsetof (struct sockaddr, sa_family) + sizeof (sa_family_t)) {
264 case Mono_Posix_SockaddrType_SockaddrStorage:
265 destination_dyn = ((struct Mono_Posix__SockaddrDynamic*) destination);
266 if (size > destination_dyn->len) {
270 destination_dyn->len = size;
273 case Mono_Posix_SockaddrType_SockaddrUn:
274 destination_dyn = ((struct Mono_Posix__SockaddrDynamic*) destination);
275 if (size - offsetof (struct sockaddr_un, sun_path) > destination_dyn->len) {
279 destination_dyn->len = size - offsetof (struct sockaddr_un, sun_path);
280 memcpy (destination_dyn->data, ((struct sockaddr_un*) source)->sun_path, size);
283 case Mono_Posix_SockaddrType_SockaddrIn:
284 if (size != sizeof (struct sockaddr_in)) {
288 if (Mono_Posix_ToSockaddrIn ((struct sockaddr_in*) source, (struct Mono_Posix_SockaddrIn*) destination) != 0)
292 case Mono_Posix_SockaddrType_SockaddrIn6:
293 if (size != sizeof (struct sockaddr_in6)) {
297 if (Mono_Posix_ToSockaddrIn6 ((struct sockaddr_in6*) source, (struct Mono_Posix_SockaddrIn6*) destination) != 0)
306 if (Mono_Posix_ToUnixAddressFamily (((struct sockaddr*) source)->sa_family, &destination->sa_family) != 0)
307 destination->sa_family = Mono_Posix_UnixAddressFamily_Unknown;
312 // Macro for allocating space for the native sockaddr_* structure
313 // Must be a macro because it is using alloca()
315 #define ALLOC_SOCKADDR \
317 struct sockaddr* addr; \
318 gboolean need_free = 0; \
320 if (get_addrlen (address, &addrlen) != 0) \
322 if (address == NULL) { \
324 } else if (address->type == Mono_Posix_SockaddrType_SockaddrStorage) { \
325 addr = (struct sockaddr*) ((struct Mono_Posix__SockaddrDynamic*) address)->data; \
326 } else if (address->type == Mono_Posix_SockaddrType_SockaddrUn) { \
327 /* Use alloca() for up to 2048 bytes, use malloc() otherwise */ \
328 need_free = addrlen > 2048; \
329 addr = need_free ? malloc (addrlen) : alloca (addrlen); \
333 addr = alloca (addrlen); \
338 Mono_Posix_Syscall_bind (int socket, struct Mono_Posix__SockaddrHeader* address)
343 if (Mono_Posix_FromSockaddr (address, addr) != 0) {
349 r = bind (socket, addr, addrlen);
358 Mono_Posix_Syscall_connect (int socket, struct Mono_Posix__SockaddrHeader* address)
363 if (Mono_Posix_FromSockaddr (address, addr) != 0) {
369 r = connect (socket, addr, addrlen);
378 Mono_Posix_Syscall_accept (int socket, struct Mono_Posix__SockaddrHeader* address)
384 r = accept (socket, addr, &addrlen);
386 if (r != -1 && Mono_Posix_ToSockaddr (addr, addrlen, address) != 0) {
398 Mono_Posix_Syscall_accept4 (int socket, struct Mono_Posix__SockaddrHeader* address, int flags)
405 r = accept4 (socket, addr, &addrlen, flags);
407 if (r != -1 && Mono_Posix_ToSockaddr (addr, addrlen, address) != 0) {
423 Mono_Posix_Syscall_getpeername (int socket, struct Mono_Posix__SockaddrHeader* address)
429 r = getpeername (socket, addr, &addrlen);
431 if (r != -1 && Mono_Posix_ToSockaddr (addr, addrlen, address) != 0)
441 Mono_Posix_Syscall_getsockname (int socket, struct Mono_Posix__SockaddrHeader* address)
447 r = getsockname (socket, addr, &addrlen);
449 if (r != -1 && Mono_Posix_ToSockaddr (addr, addrlen, address) != 0)
459 Mono_Posix_Syscall_recv (int socket, void* message, guint64 length, int flags)
461 mph_return_if_size_t_overflow (length);
463 return recv (socket, message, length, flags);
467 Mono_Posix_Syscall_send (int socket, void* message, guint64 length, int flags)
469 mph_return_if_size_t_overflow (length);
471 return send (socket, message, length, flags);
475 Mono_Posix_Syscall_recvfrom (int socket, void* buffer, guint64 length, int flags, struct Mono_Posix__SockaddrHeader* address)
479 mph_return_if_size_t_overflow (length);
483 r = recvfrom (socket, buffer, length, flags, addr, &addrlen);
485 if (r != -1 && Mono_Posix_ToSockaddr (addr, addrlen, address) != 0)
495 Mono_Posix_Syscall_sendto (int socket, void* message, guint64 length, int flags, struct Mono_Posix__SockaddrHeader* address)
499 mph_return_if_size_t_overflow (length);
502 if (Mono_Posix_FromSockaddr (address, addr) != 0) {
508 r = sendto (socket, message, length, flags, addr, addrlen);
520 // indent-tabs-mode: t