raw: Add library macro for struct sockaddr in function arguments.
[swifty.git] / src / raw / swift_raw.c
1 /*
2  * swift implementation of syscall API>
3  *
4  * Simulates the classic socket syscalls (socket, bind, send, recv).
5  * Implementation uses raw sockets (AF_INET, SOCK_RAW).
6  *
7  * Subsequently, implementation is to be ported into kernel space and
8  * the interface is going to be offered by the Linux syscall API.
9  *
10  * Heavily inspired by GLIBC's <sys/socket.h>
11  * (/usr/include/sys/socket.h).
12  *
13  * 2011, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
14  */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <unistd.h>
23 #include <errno.h>
24
25 #include "swift_types.h"
26 #include "swift_raw.h"
27
28 /* socket management structure */
29 struct sock_list {
30         int s;
31         struct sockaddr_sw addr;
32         struct sock_list *next;
33         struct sock_list *prev;
34 };
35
36 static struct sock_list sock_list_head = {
37         .next = &sock_list_head,
38         .prev = &sock_list_head
39 };
40
41 /*
42  * Add new socket to list. Called by sw_socket "syscall".
43  */
44
45 static struct sock_list *list_add_socket(int s)
46 {
47         struct sock_list *ptr = malloc(sizeof(*ptr));
48         if (ptr == NULL)
49                 return NULL;
50
51         ptr->next = &sock_list_head;
52         ptr->prev = sock_list_head.prev;
53         sock_list_head.prev->next = ptr;
54         sock_list_head.prev = ptr;
55
56         return ptr;
57 }
58
59 /*
60  * Bind socket to given address. Called by sw_bind "syscall".
61  */
62
63 static struct sock_list *list_update_socket_address(int s, __CONST_SOCKADDR_ARG addr)
64 {
65         struct sock_list *ptr;
66
67         for (ptr = sock_list_head.next; ptr != &sock_list_head; ptr = ptr->next)
68                 if (ptr->s == s) {
69                         memcpy(&ptr->addr, addr, sizeof(ptr->addr));
70                         return ptr;
71                 }
72
73         return NULL;
74 }
75
76 /*
77  * Get list element containing socket s. Called by sw_send* "syscalls".
78  */
79
80 static struct sock_list *list_elem_from_socket(int s)
81 {
82         struct sock_list *ptr;
83
84         for (ptr = sock_list_head.next; ptr != &sock_list_head; ptr = ptr->next)
85                 if (ptr->s == s) {
86                         return ptr;
87                 }
88
89         return NULL;
90 }
91
92 /*
93  * Get list element containing address addr. Called by sw_bind "syscall".
94  */
95
96 static struct sock_list *list_elem_from_address(__CONST_SOCKADDR_ARG addr)
97 {
98         struct sock_list *ptr;
99
100         for (ptr = sock_list_head.next; ptr != &sock_list_head; ptr = ptr->next)
101                 if (memcmp(&ptr->addr, addr, sizeof(addr)) == 0)
102                         return ptr;
103
104         return NULL;
105 }
106
107 /*
108  * Remove socket from list. Called by sw_close "syscall".
109  */
110
111 static struct sock_list *list_unlink_socket(int s)
112 {
113         struct sock_list *ptr;
114
115         for (ptr = sock_list_head.next; ptr != &sock_list_head; ptr = ptr->next)
116                 if (ptr->s == s) {
117                         ptr->next->prev = ptr->prev;
118                         ptr->prev->next = ptr->next;
119                         ptr->next = ptr;
120                         ptr->prev = ptr;
121                         return ptr;
122                 }
123
124         return NULL;
125 }
126
127 /*
128  * Create a new socket of type TYPE in domain DOMAIN, using
129  * protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
130  * Returns a file descriptor for the new socket, or -1 for errors.
131  *
132  * swift: PROTOCOL is IPPROTO_SWIFT. Ignore TYPE.
133  */
134 int sw_socket (int __domain, int __type, int __protocol)
135 {
136         int s;
137         struct sock_list *list;
138
139         s = socket(__domain, SOCK_RAW, IPPROTO_SWIFT);
140         if (s < 0)
141                 goto sock_err;
142
143         list = list_add_socket(s);
144         if (list == NULL)
145                 goto list_add_err;
146
147         return s;
148
149 list_add_err:
150         close(s);
151 sock_err:
152         return -1;
153 }
154
155 /*
156  * Give the socket FD the local address ADDR (which is LEN bytes long).
157  *
158  * swift: ADDR is of type struct sockaddr_sw.
159  */
160 int sw_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
161 {
162         struct sock_list *list;
163
164         /* Check whether address is already in use. */
165         list = list_elem_from_address(__addr);
166         if (list != NULL) {
167                 errno = EADDRINUSE;
168                 goto list_elem_err;
169         }
170         /* Update __fd entry in socket management list. */
171         list = list_update_socket_address(__fd, __addr);
172         if (list == NULL) {
173                 errno = EBADF;
174                 goto list_update_err;
175         }
176
177         return 0;
178
179 list_update_err:
180 list_elem_err:
181         return -1;
182 }
183
184 /* Put the local address of FD into *ADDR and its length in *LEN.  */
185 int sw_getsockname (int __fd, __SOCKADDR_ARG __addr,
186                         socklen_t *__restrict __len)
187 {
188         /* TODO */
189
190         return 0;
191 }
192
193 /*
194  * Send N bytes of BUF on socket FD to peer at address ADDR (which is
195  * ADDR_LEN bytes long).  Returns the number sent, or -1 for errors.
196  *
197  * This function is a cancellation point and therefore not marked with
198  * __THROW.
199  */
200 ssize_t sw_sendto (int __fd, __const void *__buf, size_t __n,
201                        int __flags, __CONST_SOCKADDR_ARG __addr,
202                        socklen_t __addr_len)
203 {
204         ssize_t bytes_sent;
205
206         /* TODO */
207
208         return bytes_sent;
209 }
210
211 /*
212  * Read N bytes into BUF through socket FD.
213  * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of
214  * the sender, and store the actual size of the address in *ADDR_LEN.
215  * Returns the number of bytes read or -1 for errors.
216  *
217  * This function is a cancellation point and therefore not marked with
218  * __THROW.
219  */
220 ssize_t sw_recvfrom (int __fd, void *__restrict __buf, size_t __n,
221                          int __flags, __SOCKADDR_ARG __addr,
222                          socklen_t *__restrict __addr_len)
223 {
224         ssize_t bytes_recv;
225
226         /* TODO */
227
228         return bytes_recv;
229 }
230
231 /*
232  * Send a message described MESSAGE on socket FD.
233  * Returns the number of bytes sent, or -1 for errors.
234  *
235  * This function is a cancellation point and therefore not marked with
236  * __THROW.
237  */
238 ssize_t sw_sendmsg (int __fd, __const struct msghdr *__message,
239                         int __flags)
240 {
241         ssize_t bytes_sent;
242
243         /* TODO */
244
245         return bytes_sent;
246 }
247
248 /*
249  * Receive a message as described by MESSAGE from socket FD.
250  * Returns the number of bytes read or -1 for errors.
251  *
252  * This function is a cancellation point and therefore not marked with
253  * __THROW.
254  */
255 ssize_t sw_recvmsg (int __fd, struct msghdr *__message, int __flags)
256 {
257         ssize_t bytes_recv;
258
259         /* TODO */
260
261         return bytes_recv;
262 }
263
264 /*
265  * Put the current value for socket FD's option OPTNAME at protocol level
266  * LEVEL into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the
267  * value's actual length.  Returns 0 on success, -1 for errors.
268  */
269 int sw_getsockopt (int __fd, int __level, int __optname,
270                        void *__restrict __optval,
271                        socklen_t *__restrict __optlen)
272 {
273         /* Call classical interface of getsockopt(2). */
274         return getsockopt(__fd, __level, __optname, __optval, __optlen);
275 }
276
277 /*
278  * Set socket FD's option OPTNAME at protocol level LEVEL
279  * to *OPTVAL (which is OPTLEN bytes long).
280  * Returns 0 on success, -1 for errors.
281  */
282
283 int sw_setsockopt (int __fd, int __level, int __optname,
284                        __const void *__optval, socklen_t __optlen)
285 {
286         /* Call classical interface of setsockopt(2). */
287         return setsockopt(__fd, __level, __optname, __optval, __optlen);
288 }
289
290 /*
291  * Shut down all or part of the connection open on socket FD.
292  * HOW determines what to shut down:
293  *   SHUT_RD   = No more receptions;
294  *   SHUT_WR   = No more transmissions;
295  *   SHUT_RDWR = No more receptions or transmissions.
296  * Returns 0 on success, -1 for errors.
297  */
298 int sw_shutdown (int __fd, int __how)
299 {
300         /* Call classical interface of shutdown(2). */
301         return shutdown(__fd, __how);
302 }