Add counters for MPTP buffers and syscalls.
[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 <arpa/inet.h>
23 #include <unistd.h>
24 #include <errno.h>
25
26 #include "swift_types.h"
27 #include "swift_raw.h"
28 #include "socket_manager.h"
29 #include "debug.h"
30 #include "util.h"
31
32 /*
33  * Create a new socket of type TYPE in domain DOMAIN, using
34  * protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
35  * Returns a file descriptor for the new socket, or -1 for errors.
36  *
37  * swift: PROTOCOL is IPPROTO_SWIFT. Ignore TYPE.
38  */
39 int sw_socket(int __domain, int __type, int __protocol)
40 {
41         int s;
42         int rc;
43
44         if (__domain != PF_INET || __type != SOCK_DGRAM || __protocol != IPPROTO_SWIFT) {
45                 errno = EINVAL;
46                 goto sock_err;
47         }
48
49         s = socket(PF_INET, SOCK_RAW, IPPROTO_SWIFT);
50         if (s < 0) {
51                 goto sock_err;
52         }
53
54         rc = sm_add(s);
55         if (rc < 0) {
56                 errno = ENOMEM;
57                 goto list_add_err;
58         }
59
60         /* Socket is not bound. */
61         sm_mark_unbound(s);
62
63         return s;
64
65 list_add_err:
66         close(s);
67 sock_err:
68         return -1;
69 }
70
71 /*
72  * Give the socket FD the local address ADDR (which is LEN bytes long).
73  *
74  * swift: ADDR is of type struct sockaddr_sw.
75  */
76 int sw_bind(int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
77 {
78         int rc;
79
80         rc = sm_is_bound(__fd);
81         if (rc == 1) {
82                 errno = EINVAL;
83                 goto socket_bound_err;
84         }
85
86         /* Check whether address is already in use. */
87         rc = sm_address_exists(__addr);
88         if (rc == 1) {
89                 errno = EADDRINUSE;
90                 goto address_err;
91         }
92
93         /* Update __fd entry in socket management list. */
94         rc = sm_update_address(__fd, __addr);
95         if (rc < 0) {
96                 errno = EBADF;
97                 goto update_err;
98         }
99
100         sm_mark_bound(__fd);
101
102         return 0;
103
104 update_err:
105 address_err:
106 socket_bound_err:
107         return -1;
108 }
109
110 /* Put the local address of FD into *ADDR and its length in *LEN.  */
111 int sw_getsockname(int __fd, __SOCKADDR_ARG __addr,
112                         socklen_t *__restrict __len)
113 {
114         struct sockaddr *addr;
115
116         /* Find socket in management structure. */
117         addr = sm_get_address(__fd);
118         if (addr == NULL) {
119                 errno = EINVAL;
120                 goto address_err;
121         }
122
123         memcpy(__addr, &addr, sizeof(addr));
124         *__len = sizeof(addr);
125
126         return 0;
127
128 address_err:
129         return -1;
130 }
131
132 /*
133  * Send N bytes of BUF on socket FD to peer at address ADDR (which is
134  * ADDR_LEN bytes long).  Returns the number sent, or -1 for errors.
135  *
136  * This function is a cancellation point and therefore not marked with
137  * __THROW.
138  */
139 ssize_t sw_sendto(int __fd, __const void *__buf, size_t __n,
140                        int __flags, __CONST_SOCKADDR_ARG __addr,
141                        socklen_t __addr_len)
142 {
143         ssize_t bytes_sent;
144         struct iovec __iov[1];
145         struct msghdr __msgh;
146         struct sockaddr_sw *__sw_addr = (struct sockaddr_sw *) __addr;
147         int rc;
148
149         rc = sm_is_bound(__fd);
150         if (rc < 0) {
151                 errno = EAFNOSUPPORT;
152                 goto sock_err;
153         }
154
155         {
156                 char str[INET_ADDRSTRLEN];
157
158                 inet_ntop(AF_INET, &(__sw_addr->sin_addr), str, INET_ADDRSTRLEN);       
159                 printf("=== ADDR: %s ===\n", str);
160         }
161
162         /* Specify the components of the message in an "iovec".   */
163         __iov[0].iov_base = (void *) __buf;
164         __iov[0].iov_len = __n;
165         
166         /* The message header contains parameters for sendmsg.    */
167         __msgh.msg_name = (caddr_t) __addr;
168         __msgh.msg_namelen = sizeof(__addr);
169         __msgh.msg_iov = __iov;
170         __msgh.msg_iovlen = 1;
171         __msgh.msg_control = NULL;            /* irrelevant to AF_INET */
172         __msgh.msg_controllen = 0;            /* irrelevant to AF_INET */
173
174         return sendmsg(__fd, &__msgh, 0);
175
176 sock_err:
177         return -1;
178 }
179
180 /*
181  * Read N bytes into BUF through socket FD.
182  * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of
183  * the sender, and store the actual size of the address in *ADDR_LEN.
184  * Returns the number of bytes read or -1 for errors.
185  *
186  * This function is a cancellation point and therefore not marked with
187  * __THROW.
188  */
189 ssize_t sw_recvfrom(int __fd, void *__restrict __buf, size_t __n,
190                          int __flags, __SOCKADDR_ARG __addr,
191                          socklen_t *__restrict __addr_len)
192 {
193         ssize_t bytes_recv;
194         struct iovec __iov[1];
195         struct msghdr __msgh;
196         struct sockaddr_sw *__sw_addr = (struct sockaddr_sw *) __addr;
197         int rc;
198
199         rc = sm_is_bound(__fd);
200         if (rc < 0) {
201                 errno = EAFNOSUPPORT;
202                 goto sock_err;
203         }
204
205         /* TODO */
206
207         return recvmsg(__fd, &__msgh, 0);
208         
209 sock_err:
210         return -1;
211 }
212
213 /*
214  * Send a message described MESSAGE on socket FD.
215  * Returns the number of bytes sent, or -1 for errors.
216  *
217  * This function is a cancellation point and therefore not marked with
218  * __THROW.
219  */
220 ssize_t sw_sendmsg(int __fd, __const struct msghdr *__message,
221                         int __flags)
222 {
223         ssize_t bytes_sent;
224
225         /* TODO */
226         
227         return sendmsg(__fd, __message, __flags);
228 }
229
230 /*
231  * Receive a message as described by MESSAGE from socket FD.
232  * Returns the number of bytes read or -1 for errors.
233  *
234  * This function is a cancellation point and therefore not marked with
235  * __THROW.
236  */
237 ssize_t sw_recvmsg(int __fd, struct msghdr *__message, int __flags)
238 {
239         ssize_t bytes_recv;
240
241         /* TODO */
242
243         return recvmsg(__fd, __message, __flags);
244 }
245
246 /*
247  * Put the current value for socket FD's option OPTNAME at protocol level
248  * LEVEL into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the
249  * value's actual length.  Returns 0 on success, -1 for errors.
250  */
251 int sw_getsockopt(int __fd, int __level, int __optname,
252                        void *__restrict __optval,
253                        socklen_t *__restrict __optlen)
254 {
255         /* Call classical interface of getsockopt(2). */
256         return getsockopt(__fd, __level, __optname, __optval, __optlen);
257 }
258
259 /*
260  * Set socket FD's option OPTNAME at protocol level LEVEL
261  * to *OPTVAL (which is OPTLEN bytes long).
262  * Returns 0 on success, -1 for errors.
263  */
264 int sw_setsockopt(int __fd, int __level, int __optname,
265                        __const void *__optval, socklen_t __optlen)
266 {
267         /* Call classical interface of setsockopt(2). */
268         return setsockopt(__fd, __level, __optname, __optval, __optlen);
269 }
270
271 /*
272  * Close file descriptor for socket FD.
273  * Returns 0 on success, -1 for errors.
274  */
275 int sw_close(int __fd)
276 {
277         int rc;
278
279         /* Remove socket from socket management structure. */
280         rc = sm_del(__fd);
281         if (rc < 0) {
282                 errno = EBADF;
283                 goto del_err;
284         }
285
286         /* Call classical interface of close(2). */
287         return close(__fd);
288
289 del_err:
290         return -1;
291 }