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>
25 Mono_Posix_SockaddrStorage_get_size (void)
27 return sizeof (struct sockaddr_storage
);
31 Mono_Posix_SockaddrUn_get_sizeof_sun_path (void)
33 struct sockaddr_un sun
;
34 return sizeof (sun
.sun_path
);
38 Mono_Posix_Cmsghdr_getsize (void)
40 return sizeof (struct cmsghdr
);
44 Mono_Posix_FromInAddr (struct Mono_Posix_InAddr
* source
, void* destination
)
46 memcpy (&((struct in_addr
*)destination
)->s_addr
, &source
->s_addr
, 4);
51 Mono_Posix_ToInAddr (void* source
, struct Mono_Posix_InAddr
* destination
)
53 memcpy (&destination
->s_addr
, &((struct in_addr
*)source
)->s_addr
, 4);
58 Mono_Posix_FromIn6Addr (struct Mono_Posix_In6Addr
* source
, void* destination
)
60 memcpy (&((struct in6_addr
*)destination
)->s6_addr
, &source
->addr0
, 16);
65 Mono_Posix_ToIn6Addr (void* source
, struct Mono_Posix_In6Addr
* destination
)
67 memcpy (&destination
->addr0
, &((struct in6_addr
*)source
)->s6_addr
, 16);
73 Mono_Posix_Syscall_socketpair (int domain
, int type
, int protocol
, int* socket1
, int* socket2
)
75 int filedes
[2] = {-1, -1};
78 r
= socketpair (domain
, type
, protocol
, filedes
);
80 *socket1
= filedes
[0];
81 *socket2
= filedes
[1];
86 Mono_Posix_Syscall_getsockopt (int socket
, int level
, int option_name
, void* option_value
, gint64
* option_len
)
91 mph_return_if_socklen_t_overflow (*option_len
);
95 r
= getsockopt (socket
, level
, option_name
, option_value
, &len
);
103 Mono_Posix_Syscall_getsockopt_timeval (int socket
, int level
, int option_name
, struct Mono_Posix_Timeval
* option_value
)
109 size
= sizeof (struct timeval
);
110 r
= getsockopt (socket
, level
, option_name
, &tv
, &size
);
112 if (r
!= -1 && size
== sizeof (struct timeval
)) {
113 if (Mono_Posix_ToTimeval (&tv
, option_value
) != 0)
116 memset (option_value
, 0, sizeof (struct Mono_Posix_Timeval
));
125 Mono_Posix_Syscall_getsockopt_linger (int socket
, int level
, int option_name
, struct Mono_Posix_Linger
* option_value
)
131 size
= sizeof (struct linger
);
132 r
= getsockopt (socket
, level
, option_name
, &ling
, &size
);
134 if (r
!= -1 && size
== sizeof (struct linger
)) {
135 if (Mono_Posix_ToLinger (&ling
, option_value
) != 0)
138 memset (option_value
, 0, sizeof (struct Mono_Posix_Linger
));
147 Mono_Posix_Syscall_setsockopt (int socket
, int level
, int option_name
, void* option_value
, gint64 option_len
)
149 mph_return_if_socklen_t_overflow (option_len
);
151 return setsockopt (socket
, level
, option_name
, option_value
, option_len
);
155 Mono_Posix_Syscall_setsockopt_timeval (int socket
, int level
, int option_name
, struct Mono_Posix_Timeval
* option_value
)
159 if (Mono_Posix_FromTimeval (option_value
, &tv
) != 0)
162 return setsockopt (socket
, level
, option_name
, &tv
, sizeof (struct timeval
));
166 Mono_Posix_Syscall_setsockopt_linger (int socket
, int level
, int option_name
, struct Mono_Posix_Linger
* option_value
)
170 if (Mono_Posix_FromLinger (option_value
, &ling
) != 0)
173 return setsockopt (socket
, level
, option_name
, &ling
, sizeof (struct linger
));
177 get_addrlen (struct Mono_Posix__SockaddrHeader
* address
, socklen_t
* addrlen
)
184 switch (address
->type
) {
185 case Mono_Posix_SockaddrType_SockaddrStorage
:
186 mph_return_if_socklen_t_overflow (((struct Mono_Posix__SockaddrDynamic
*) address
)->len
);
187 *addrlen
= ((struct Mono_Posix__SockaddrDynamic
*) address
)->len
;
189 case Mono_Posix_SockaddrType_SockaddrUn
:
190 mph_return_if_socklen_t_overflow (offsetof (struct sockaddr_un
, sun_path
) + ((struct Mono_Posix__SockaddrDynamic
*) address
)->len
);
191 *addrlen
= offsetof (struct sockaddr_un
, sun_path
) + ((struct Mono_Posix__SockaddrDynamic
*) address
)->len
;
193 case Mono_Posix_SockaddrType_Sockaddr
: *addrlen
= sizeof (struct sockaddr
); return 0;
194 case Mono_Posix_SockaddrType_SockaddrIn
: *addrlen
= sizeof (struct sockaddr_in
); return 0;
195 case Mono_Posix_SockaddrType_SockaddrIn6
: *addrlen
= sizeof (struct sockaddr_in6
); return 0;
204 Mono_Posix_Sockaddr_GetNativeSize (struct Mono_Posix__SockaddrHeader
* address
, gint64
* size
)
209 r
= get_addrlen (address
, &value
);
215 Mono_Posix_FromSockaddr (struct Mono_Posix__SockaddrHeader
* source
, void* destination
)
220 switch (source
->type
) {
221 case Mono_Posix_SockaddrType_SockaddrStorage
:
222 // Do nothing, don't copy source->sa_family into addr->sa_family
225 case Mono_Posix_SockaddrType_SockaddrUn
:
226 memcpy (((struct sockaddr_un
*) destination
)->sun_path
, ((struct Mono_Posix__SockaddrDynamic
*) source
)->data
, ((struct Mono_Posix__SockaddrDynamic
*) source
)->len
);
229 case Mono_Posix_SockaddrType_Sockaddr
:
232 case Mono_Posix_SockaddrType_SockaddrIn
:
233 if (Mono_Posix_FromSockaddrIn ((struct Mono_Posix_SockaddrIn
*) source
, (struct sockaddr_in
*) destination
) != 0)
237 case Mono_Posix_SockaddrType_SockaddrIn6
:
238 if (Mono_Posix_FromSockaddrIn6 ((struct Mono_Posix_SockaddrIn6
*) source
, (struct sockaddr_in6
*) destination
) != 0)
248 if (Mono_Posix_FromUnixAddressFamily (source
->sa_family
, &family
) != 0)
250 ((struct sockaddr
*) destination
)->sa_family
= family
;
256 Mono_Posix_ToSockaddr (void* source
, gint64 size
, struct Mono_Posix__SockaddrHeader
* destination
)
258 struct Mono_Posix__SockaddrDynamic
* destination_dyn
;
263 switch (destination
->type
) {
264 case Mono_Posix_SockaddrType_Sockaddr
:
265 if (size
< offsetof (struct sockaddr
, sa_family
) + sizeof (sa_family_t
)) {
271 case Mono_Posix_SockaddrType_SockaddrStorage
:
272 destination_dyn
= ((struct Mono_Posix__SockaddrDynamic
*) destination
);
273 if (size
> destination_dyn
->len
) {
277 destination_dyn
->len
= size
;
280 case Mono_Posix_SockaddrType_SockaddrUn
:
281 destination_dyn
= ((struct Mono_Posix__SockaddrDynamic
*) destination
);
282 if (size
- offsetof (struct sockaddr_un
, sun_path
) > destination_dyn
->len
) {
286 destination_dyn
->len
= size
- offsetof (struct sockaddr_un
, sun_path
);
287 memcpy (destination_dyn
->data
, ((struct sockaddr_un
*) source
)->sun_path
, size
);
290 case Mono_Posix_SockaddrType_SockaddrIn
:
291 if (size
!= sizeof (struct sockaddr_in
)) {
295 if (Mono_Posix_ToSockaddrIn ((struct sockaddr_in
*) source
, (struct Mono_Posix_SockaddrIn
*) destination
) != 0)
299 case Mono_Posix_SockaddrType_SockaddrIn6
:
300 if (size
!= sizeof (struct sockaddr_in6
)) {
304 if (Mono_Posix_ToSockaddrIn6 ((struct sockaddr_in6
*) source
, (struct Mono_Posix_SockaddrIn6
*) destination
) != 0)
313 if (Mono_Posix_ToUnixAddressFamily (((struct sockaddr
*) source
)->sa_family
, &destination
->sa_family
) != 0)
314 destination
->sa_family
= Mono_Posix_UnixAddressFamily_Unknown
;
319 // Macro for allocating space for the native sockaddr_* structure
320 // Must be a macro because it is using alloca()
322 #define ALLOC_SOCKADDR \
324 struct sockaddr* addr; \
325 gboolean need_free = 0; \
327 if (get_addrlen (address, &addrlen) != 0) \
329 if (address == NULL) { \
331 } else if (address->type == Mono_Posix_SockaddrType_SockaddrStorage) { \
332 addr = (struct sockaddr*) ((struct Mono_Posix__SockaddrDynamic*) address)->data; \
333 } else if (address->type == Mono_Posix_SockaddrType_SockaddrUn) { \
334 /* Use alloca() for up to 2048 bytes, use malloc() otherwise */ \
335 need_free = addrlen > 2048; \
336 addr = need_free ? malloc (addrlen) : alloca (addrlen); \
340 addr = alloca (addrlen); \
345 Mono_Posix_Syscall_bind (int socket
, struct Mono_Posix__SockaddrHeader
* address
)
350 if (Mono_Posix_FromSockaddr (address
, addr
) != 0) {
356 r
= bind (socket
, addr
, addrlen
);
365 Mono_Posix_Syscall_connect (int socket
, struct Mono_Posix__SockaddrHeader
* address
)
370 if (Mono_Posix_FromSockaddr (address
, addr
) != 0) {
376 r
= connect (socket
, addr
, addrlen
);
385 Mono_Posix_Syscall_accept (int socket
, struct Mono_Posix__SockaddrHeader
* address
)
391 r
= accept (socket
, addr
, &addrlen
);
393 if (r
!= -1 && Mono_Posix_ToSockaddr (addr
, addrlen
, address
) != 0) {
406 Mono_Posix_Syscall_accept4 (int socket
, struct Mono_Posix__SockaddrHeader
* address
, int flags
)
412 r
= accept4 (socket
, addr
, &addrlen
, flags
);
414 if (r
!= -1 && Mono_Posix_ToSockaddr (addr
, addrlen
, address
) != 0) {
427 Mono_Posix_Syscall_getpeername (int socket
, struct Mono_Posix__SockaddrHeader
* address
)
433 r
= getpeername (socket
, addr
, &addrlen
);
435 if (r
!= -1 && Mono_Posix_ToSockaddr (addr
, addrlen
, address
) != 0)
445 Mono_Posix_Syscall_getsockname (int socket
, struct Mono_Posix__SockaddrHeader
* address
)
451 r
= getsockname (socket
, addr
, &addrlen
);
453 if (r
!= -1 && Mono_Posix_ToSockaddr (addr
, addrlen
, address
) != 0)
463 Mono_Posix_Syscall_recv (int socket
, void* message
, guint64 length
, int flags
)
465 mph_return_if_size_t_overflow (length
);
467 return recv (socket
, message
, length
, flags
);
471 Mono_Posix_Syscall_send (int socket
, void* message
, guint64 length
, int flags
)
473 mph_return_if_size_t_overflow (length
);
475 return send (socket
, message
, length
, flags
);
479 Mono_Posix_Syscall_recvfrom (int socket
, void* buffer
, guint64 length
, int flags
, struct Mono_Posix__SockaddrHeader
* address
)
483 mph_return_if_size_t_overflow (length
);
487 r
= recvfrom (socket
, buffer
, length
, flags
, addr
, &addrlen
);
489 if (r
!= -1 && Mono_Posix_ToSockaddr (addr
, addrlen
, address
) != 0)
499 Mono_Posix_Syscall_sendto (int socket
, void* message
, guint64 length
, int flags
, struct Mono_Posix__SockaddrHeader
* address
)
503 mph_return_if_size_t_overflow (length
);
506 if (Mono_Posix_FromSockaddr (address
, addr
) != 0) {
512 r
= sendto (socket
, message
, length
, flags
, addr
, addrlen
);
521 Mono_Posix_Syscall_recvmsg (int socket
, struct Mono_Posix_Syscall__Msghdr
* message
, struct Mono_Posix__SockaddrHeader
* address
, int flags
)
528 memset (&hdr
, 0, sizeof (struct msghdr
));
531 hdr
.msg_namelen
= addrlen
;
532 hdr
.msg_iovlen
= message
->msg_iovlen
;
533 hdr
.msg_control
= message
->msg_control
;
534 hdr
.msg_controllen
= message
->msg_controllen
;
536 hdr
.msg_iov
= _mph_from_iovec_array (message
->msg_iov
, message
->msg_iovlen
);
538 r
= recvmsg (socket
, &hdr
, flags
);
540 if (r
!= -1 && Mono_Posix_ToSockaddr (addr
, hdr
.msg_namelen
, address
) != 0)
547 message
->msg_controllen
= hdr
.msg_controllen
;
548 message
->msg_flags
= hdr
.msg_flags
;
554 Mono_Posix_Syscall_sendmsg (int socket
, struct Mono_Posix_Syscall__Msghdr
* message
, struct Mono_Posix__SockaddrHeader
* address
, int flags
)
560 if (Mono_Posix_FromSockaddr (address
, addr
) != 0) {
566 memset (&hdr
, 0, sizeof (struct msghdr
));
569 hdr
.msg_namelen
= addrlen
;
570 hdr
.msg_iovlen
= message
->msg_iovlen
;
571 hdr
.msg_control
= message
->msg_control
;
572 hdr
.msg_controllen
= message
->msg_controllen
;
574 hdr
.msg_iov
= _mph_from_iovec_array (message
->msg_iov
, message
->msg_iovlen
);
576 r
= sendmsg (socket
, &hdr
, flags
);
585 static inline void make_msghdr (struct msghdr
* hdr
, unsigned char* msg_control
, gint64 msg_controllen
)
587 memset (hdr
, 0, sizeof (struct msghdr
));
588 hdr
->msg_control
= msg_control
;
589 hdr
->msg_controllen
= msg_controllen
;
591 static inline struct cmsghdr
* from_offset (unsigned char* msg_control
, gint64 offset
)
595 return (struct cmsghdr
*) (msg_control
+ offset
);
597 static inline gint64
to_offset (unsigned char* msg_control
, void* hdr
)
601 return ((unsigned char*) hdr
) - msg_control
;
606 Mono_Posix_Syscall_CMSG_FIRSTHDR (unsigned char* msg_control
, gint64 msg_controllen
)
610 make_msghdr (&hdr
, msg_control
, msg_controllen
);
611 return to_offset (msg_control
, CMSG_FIRSTHDR (&hdr
));
617 Mono_Posix_Syscall_CMSG_NXTHDR (unsigned char* msg_control
, gint64 msg_controllen
, gint64 cmsg
)
621 make_msghdr (&hdr
, msg_control
, msg_controllen
);
622 return to_offset (msg_control
, CMSG_NXTHDR (&hdr
, from_offset (msg_control
, cmsg
)));
628 Mono_Posix_Syscall_CMSG_DATA (unsigned char* msg_control
, gint64 msg_controllen
, gint64 cmsg
)
630 return to_offset (msg_control
, CMSG_DATA (from_offset (msg_control
, cmsg
)));
636 Mono_Posix_Syscall_CMSG_ALIGN (guint64 length
)
638 return CMSG_ALIGN (length
);
644 Mono_Posix_Syscall_CMSG_SPACE (guint64 length
)
646 return CMSG_SPACE (length
);
652 Mono_Posix_Syscall_CMSG_LEN (guint64 length
)
654 return CMSG_LEN (length
);
666 // indent-tabs-mode: t