AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
socket.c
Go to the documentation of this file.
1
9
10#include <core/system.h>
11#include <core/string.h>
12#include <ds/queue.h>
13#include <aquila/errno.h>
14#include <net/socket.h>
15
16#include <aquila/fcntl.h>
17
27int socket_create(struct file *file, int domain, int type, int protocol)
28{
29 int err;
30
31 switch (domain) {
32 case AF_UNIX:
33 err = socket_unix_create(file, domain, type, protocol);
34 break;
35 case AF_INET:
36 err = socket_inet_create(file, domain, type, protocol);
37 break;
38 default:
39 return -EAFNOSUPPORT;
40 }
41
42 /* a socket is open for reading and writing (F_GETFL says so, and
43 * fdopen() checks it) */
44 if (!err)
45 file->flags |= O_RDWR;
46
47 return err;
48}
49
59int socket_accept(struct file *file, struct file *conn, const struct sockaddr *addr, socklen_t *len)
60{
61 if (!(file->flags & FILE_SOCKET))
62 return -ENOTSOCK;
63
64 if (!file->socket->ops || !file->socket->ops->accept)
65 return -EOPNOTSUPP;
66
67 int err = file->socket->ops->accept(file, conn, addr, len);
68
69 if (!err)
70 conn->flags |= O_RDWR;
71
72 return err;
73}
74
83int socket_bind(struct file *file, const struct sockaddr *addr, socklen_t len)
84{
85 if (!(file->flags & FILE_SOCKET))
86 return -ENOTSOCK;
87
88 if (!file->socket->ops || !file->socket->ops->bind)
89 return -EOPNOTSUPP;
90
91 return file->socket->ops->bind(file, addr, len);
92}
93
102int socket_connect(struct file *file, const struct sockaddr *addr, socklen_t len)
103{
104 if (!(file->flags & FILE_SOCKET))
105 return -ENOTSOCK;
106
107 if (!file->socket->ops || !file->socket->ops->connect)
108 return -EOPNOTSUPP;
109
110 return file->socket->ops->connect(file, addr, len);
111}
112
120int socket_listen(struct file *file, int backlog)
121{
122 if (!(file->flags & FILE_SOCKET))
123 return -ENOTSOCK;
124
125 if (!file->socket->ops || !file->socket->ops->listen)
126 return -EOPNOTSUPP;
127
128 return file->socket->ops->listen(file, backlog);
129}
130
141ssize_t socket_send(struct file *file, struct iobuf *io, int flags, const struct sockaddr *to, socklen_t tolen)
142{
143 if (!file)
144 return -EINVAL;
145
146 if (!(file->flags & FILE_SOCKET))
147 return -ENOTSOCK;
148
149 if (!(file->socket))
150 return -EINVAL;
151
152 if (!file->socket->ops || !file->socket->ops->send)
153 return -EOPNOTSUPP;
154
155 return file->socket->ops->send(file, io, flags, to, tolen);
156}
157
169ssize_t socket_recv(struct file *file, struct iobuf *io, int flags, struct sockaddr *from, socklen_t *fromlen)
170{
171 if (!(file->flags & FILE_SOCKET))
172 return -ENOTSOCK;
173
174 if (!file->socket->ops || !file->socket->ops->recv)
175 return -EOPNOTSUPP;
176
177 return file->socket->ops->recv(file, io, flags, from, fromlen);
178}
179
189int socket_can_read(struct file *file, size_t len)
190{
191 if (!(file->flags & FILE_SOCKET))
192 return -ENOTSOCK;
193
194 if (!file->socket->ops || !file->socket->ops->can_read)
195 return -EOPNOTSUPP;
196
197 return file->socket->ops->can_read(file, len);
198}
199
209struct waitq *socket_wait_queue(struct file *file, int write)
210{
211 if (!file->socket->ops || !file->socket->ops->wait_queue)
212 return NULL;
213
214 return file->socket->ops->wait_queue(file, write);
215}
216
225int socket_can_write(struct file *file, size_t len)
226{
227 if (!(file->flags & FILE_SOCKET))
228 return -ENOTSOCK;
229
230 if (!file->socket->ops || !file->socket->ops->can_write)
231 return -EOPNOTSUPP;
232
233 return file->socket->ops->can_write(file, len);
234}
235
245int socket_shutdown_dir(struct file *file, int how)
246{
247 if (!(file->flags & FILE_SOCKET))
248 return -ENOTSOCK;
249
250 if (how & ~SHUT_RDWR || !how)
251 return -EINVAL;
252
253 if (!file->socket->ops || !file->socket->ops->shut)
254 return -EOPNOTSUPP;
255
256 return file->socket->ops->shut(file, how);
257}
258
267int socket_shutdown(struct file *file, int how)
268{
269 if (!(file->flags & FILE_SOCKET))
270 return -ENOTSOCK;
271
272 if (!file->socket->ops || !file->socket->ops->shutdown)
273 return -EOPNOTSUPP;
274
275 /* the open file is closed (its last descriptor went) */
276 return file->socket->ops->shutdown(file, how);
277}
278
289int socket_getname(struct file *file, struct sockaddr *addr, socklen_t *len, int peer)
290{
291 if (!(file->flags & FILE_SOCKET))
292 return -ENOTSOCK;
293
294 if (!file->socket->ops || !file->socket->ops->getname)
295 return -EOPNOTSUPP;
296
297 return file->socket->ops->getname(file, addr, len, peer);
298}
299
302static int sockopt_int(void *val, socklen_t *len, int v)
303{
304 if (*len < sizeof(int))
305 return -EINVAL;
306
307 *(int *) val = v;
308 *len = sizeof(int);
309 return 0;
310}
311
325int socket_getsockopt(struct file *file, int level, int name, void *val, socklen_t *len)
326{
327 if (!(file->flags & FILE_SOCKET))
328 return -ENOTSOCK;
329
330 struct sock_ops *ops = file->socket->ops;
331
332 if (level == SOL_SOCKET && name == SO_TYPE)
333 return sockopt_int(val, len, file->socket->type);
334
335 if (ops && ops->getsockopt) {
336 int err = ops->getsockopt(file, level, name, val, len);
337
338 if (err != -ENOPROTOOPT)
339 return err;
340 }
341
342 /* if the protocol doesn't keep errors, there is no pending one */
343 if (level == SOL_SOCKET && name == SO_ERROR)
344 return sockopt_int(val, len, 0);
345
346 return -ENOPROTOOPT;
347}
348
361int socket_setsockopt(struct file *file, int level, int name, const void *val, socklen_t len)
362{
363 if (!(file->flags & FILE_SOCKET))
364 return -ENOTSOCK;
365
366 struct sock_ops *ops = file->socket->ops;
367
368 if (ops && ops->setsockopt) {
369 int err = ops->setsockopt(file, level, name, val, len);
370
371 if (err != -ENOPROTOOPT)
372 return err;
373 }
374
375 /* these are accepted, without effect */
376 if (level == SOL_SOCKET) {
377 switch (name) {
378 case SO_REUSEADDR:
379 case SO_KEEPALIVE:
380 case SO_SNDBUF:
381 case SO_RCVBUF:
382 case SO_LINGER:
383 case SO_SNDTIMEO:
384 return 0;
385 }
386 }
387
388 return -ENOPROTOOPT;
389}
390
399int socket_ioctl(struct file *file, int request, void *argp)
400{
401 if (!(file->flags & FILE_SOCKET))
402 return -ENOTSOCK;
403
404 if (!file->socket->ops || !file->socket->ops->ioctl)
405 return -ENOTTY;
406
407 return file->socket->ops->ioctl(file, request, argp);
408}
static int sockopt_int(void *val, socklen_t *len, int v)
Sets an option's value to the int v.
Definition socket.c:302
int socket_listen(struct file *file, int backlog)
Makes a socket listen for connections, for listen().
Definition socket.c:120
int socket_inet_create(struct file *file, int domain, int type, int protocol)
Makes an AF_INET socket: a TCP, UDP or ping socket.
Definition socket.c:230
int socket_shutdown_dir(struct file *file, int how)
Shuts down reading, writing or both on a socket, for shutdown().
Definition socket.c:245
int socket_can_write(struct file *file, size_t len)
Says whether a socket has room to write, for select() and poll().
Definition socket.c:225
#define FILE_SOCKET
Definition socket.h:70
int socket_getsockopt(struct file *file, int level, int name, void *val, socklen_t *len)
Reads a socket option, for getsockopt().
Definition socket.c:325
int socket_connect(struct file *file, const struct sockaddr *addr, socklen_t len)
Connects a socket to a peer, for connect().
Definition socket.c:102
int socket_setsockopt(struct file *file, int level, int name, const void *val, socklen_t len)
Sets a socket option, for setsockopt().
Definition socket.c:361
int socket_can_read(struct file *file, size_t len)
Says whether a socket has something to read, for select() and poll().
Definition socket.c:189
struct waitq * socket_wait_queue(struct file *file, int write)
Finds the wait queue that a socket's readers (or writers) sleep on, for select() and poll() to regist...
Definition socket.c:209
int socket_create(struct file *file, int domain, int type, int protocol)
Makes a socket of a domain in an open file, for socket().
Definition socket.c:27
int socket_unix_create(struct file *file, int domain, int type, int protocol)
Makes an AF_UNIX socket, for socket().
Definition unix.c:68
int socket_accept(struct file *file, struct file *conn, const struct sockaddr *addr, socklen_t *len)
Accepts a connection on a listening socket, for accept().
Definition socket.c:59
int socket_ioctl(struct file *file, int request, void *argp)
Handles an ioctl() on a socket, by passing it to the protocol.
Definition socket.c:399
int socket_shutdown(struct file *file, int how)
Releases a socket when its open file is closed (its last descriptor went).
Definition socket.c:267
ssize_t socket_recv(struct file *file, struct iobuf *io, int flags, struct sockaddr *from, socklen_t *fromlen)
Receives data from a socket, for recv(), recvfrom() and read().
Definition socket.c:169
int socket_getname(struct file *file, struct sockaddr *addr, socklen_t *len, int peer)
Gets a socket's local address, or its peer's, for getsockname() and getpeername().
Definition socket.c:289
ssize_t socket_send(struct file *file, struct iobuf *io, int flags, const struct sockaddr *to, socklen_t tolen)
Sends data on a socket, for send(), sendto() and write().
Definition socket.c:141
int socket_bind(struct file *file, const struct sockaddr *addr, socklen_t len)
Gives a socket its local address, for bind().
Definition socket.c:83
#define NULL
Definition stddef.h:27
An open file (POSIX's "open file description", fs/file.c).
Definition vfs.h:157
int flags
Definition vfs.h:164
An iobuf.
Definition iobuf.h:35
A domain's socket operations.
Definition socket.h:29
int(*) setsockopt(struct file *socket, int level, int name, const void *val, socklen_t len)
Definition socket.h:49
int(*) getsockopt(struct file *socket, int level, int name, void *val, socklen_t *len)
Definition socket.h:48
Definition waitq.h:19
long int ssize_t
Definition types.h:12