aboutsummaryrefslogtreecommitdiff
path: root/lib/mlibc/sysdeps/lemon/generic/sockets.cpp
blob: 7244218dfdd14cd087032dab7a6cfc39280b787f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <lemon/syscall.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#include <mlibc/all-sysdeps.hpp>

namespace {

int fcntl_helper(int fd, int request, int *result, ...) {
	va_list args;
	va_start(args, result);
	if(!mlibc::sys_fcntl) {
		return ENOSYS;
	}
	int ret = mlibc::sys_fcntl(fd, request, args, result);
	va_end(args);
	return ret;
}

}

namespace mlibc{

int sys_socket(int domain, int type, int protocol, int *fd){
    long ret = syscall(SYS_SOCKET, domain, type, protocol);

    if(ret < 0){
        return -ret;
    }

    *fd = ret;

    return 0;
}

int sys_bind(int sockfd, const struct sockaddr *addr_ptr, socklen_t addrlen){
    return syscall(SYS_BIND, sockfd, addr_ptr, addrlen);
}

int sys_connect(int sockfd, const struct sockaddr *addr_ptr, socklen_t addrlen){
    return syscall(SYS_CONNECT, sockfd, addr_ptr, addrlen);
}

int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags){
    long ret = syscall(SYS_ACCEPT, fd);

    if(ret < 0){
        return -ret;
    }

    *newfd = ret;

	if(flags & SOCK_NONBLOCK) {
		int fcntl_ret = 0;
		fcntl_helper(*newfd, F_GETFL, &fcntl_ret);
		fcntl_helper(*newfd, F_SETFL, &fcntl_ret, fcntl_ret | O_NONBLOCK);
	}

	if(flags & SOCK_CLOEXEC) {
		int fcntl_ret = 0;
		fcntl_helper(*newfd, F_GETFD, &fcntl_ret);
		fcntl_helper(*newfd, F_SETFD, &fcntl_ret, fcntl_ret | FD_CLOEXEC);
	}

    return 0;
}

int sys_listen(int fd, int backlog){
    return syscall(SYS_LISTEN, fd, backlog);
}

int sys_msg_recv(int sockfd, struct msghdr *hdr, int flags, ssize_t *length){
    long ret = syscall(SYS_RECVMSG, sockfd, hdr, flags);

    if(ret < 0){
        return -ret;
    }

    *length = ret;

    return 0;
}

int sys_msg_send(int sockfd, const struct msghdr *hdr, int flags, ssize_t *length){
    long ret = syscall(SYS_SENDMSG, sockfd, hdr, flags);

    if(ret < 0){
        return -ret;
    }

    *length = ret;

    return 0;
}

int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size){
    long ret = syscall(SYS_SET_SOCKET_OPTIONS, fd, layer, number, buffer, size);

    if(ret < 0){
        return -ret;
    }

    return 0;
}

int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, socklen_t *__restrict size){
    long ret = syscall(SYS_GET_SOCKET_OPTIONS, fd, layer, number, buffer, size);

    if(ret < 0){
        return -ret;
    }

    return 0;
}

int sys_socketpair(int domain, int type_and_flags, int proto, int *fds){
    return -syscall(SYS_SOCKETPAIR, domain, type_and_flags, proto, fds);
}

int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length,
    socklen_t *actual_length) {
    return -syscall(SYS_SOCKNAME, fd, addr_ptr, max_addr_length);
}

int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length,
    socklen_t *actual_length) {
    return -syscall(SYS_PEERNAME, fd, addr_ptr, max_addr_length);
}

}