AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
socket.c
Go to the documentation of this file.
1
13
14#include <core/system.h>
15#include <dev/random.h>
16#include <core/string.h>
17#include <core/arch.h>
18#include <ds/queue.h>
19#include <fs/vfs.h>
20#include <net/byteorder.h>
21#include <net/inet.h>
22#include <net/socket.h>
23#include <sys/proc.h>
24#include <sys/sched.h>
25#include <sys/uaccess.h>
26
27#include <aquila/errno.h>
28#include <aquila/fcntl.h>
29#include <aquila/in.h>
30#include <aquila/ioctl.h>
31
32MALLOC_DECLARE(M_SOCKET);
33MALLOC_DEFINE(M_INET_SOCK, "inet socket", "AF_INET socket");
34
35/* What a socket's queue may hold, counted in buffers: each datagram costs
36 * its whole netbuf, whatever its size. If datagrams were counted by their
37 * bytes, empty ones would cost nothing, and a process could fill all of
38 * memory with them. */
39#define RECV_MAX (128 * NETBUF_SIZE)
40
41#define PORT_FIRST 49152 /* the ephemeral ports' range */
42#define PORT_LAST 65535
43
45struct inet_sock {
46 uint8_t proto; /* IP_PROTO_UDP or IP_PROTO_ICMP */
47
48 /* addresses and ports in network byte order; it isn't bound while
49 * lport is 0 */
55
57 size_t recv_bytes;
59
60 struct netif *netif; /* SO_BINDTODEVICE: only use this interface */
61
62 int error; /* an error to report (SO_ERROR, or the next call) */
63 uint64_t rcvtimeo; /* the receive timeout in ns, or 0 for none */
64 int broadcast; /* SO_BROADCAST */
66
67 struct inet_sock *next; /* the next bound socket */
68};
69
70static struct inet_sock *bound;
71
73
74/*
75 * The list of bound sockets
76 */
77
80static int port_used(uint8_t proto, uint32_t addr, uint16_t port)
81{
82 for (struct inet_sock *s = bound; s; s = s->next)
83 if (s->proto == proto && s->lport == port &&
84 (!s->laddr || !addr || s->laddr == addr))
85 return 1;
86
87 return 0;
88}
89
93static int sock_bind(struct inet_sock *sock, uint32_t addr, uint16_t port)
94{
95 if (!port) {
96 /* the first free port from a random one on (RFC 6056, algorithm
97 * 1), so that the next port isn't the last one plus one, for
98 * anyone to guess */
99 uint16_t next;
100 random_get(&next, sizeof(next));
101 next = PORT_FIRST + next % (PORT_LAST - PORT_FIRST + 1);
102
103 for (int i = 0; i <= PORT_LAST - PORT_FIRST; ++i) {
104 uint16_t p = htons(next);
105 next = next == PORT_LAST ? PORT_FIRST : next + 1;
106
107 if (!port_used(sock->proto, addr, p)) {
108 port = p;
109 break;
110 }
111 }
112
113 if (!port)
114 return -EADDRINUSE;
115 } else if (port_used(sock->proto, addr, port)) {
116 return -EADDRINUSE;
117 }
118
119 sock->laddr = addr;
120 sock->lport = port;
121 sock->next = bound;
122 bound = sock;
123
124 return 0;
125}
126
128static void sock_unbind(struct inet_sock *sock)
129{
130 for (struct inet_sock **p = &bound; *p; p = &(*p)->next) {
131 if (*p == sock) {
132 *p = sock->next;
133 break;
134 }
135 }
136
137 sock->lport = 0;
138}
139
155 uint16_t port, uint32_t remote, uint16_t remote_port)
156{
157 struct inet_sock *any = NULL;
158
159 for (struct inet_sock *s = bound; s; s = s->next) {
160 if (s->proto != proto || s->lport != port || (s->laddr && s->laddr != local) ||
161 (s->netif && s->netif != netif))
162 continue;
163
164 if (!s->connected) {
165 if (!any)
166 any = s;
167 continue;
168 }
169
170 if (s->raddr == remote && (proto == IP_PROTO_ICMP || s->rport == remote_port))
171 return s;
172 }
173
174 return any;
175}
176
185void inet_sock_deliver(struct inet_sock *sock, struct netbuf *nb)
186{
187 if (sock->shut_rd || sock->recv_bytes + NETBUF_SIZE > RECV_MAX) {
188 netbuf_free(nb);
189 return;
190 }
191
192 nb->next = NULL;
193
194 if (sock->recv_tail)
195 sock->recv_tail->next = nb;
196 else
197 sock->recv_head = nb;
198
199 sock->recv_tail = nb;
200 sock->recv_bytes += NETBUF_SIZE;
201
202 waitq_wakeup(&sock->recv_wait);
203}
204
211void inet_sock_error(struct inet_sock *sock, int err)
212{
213 sock->error = err;
214 waitq_wakeup(&sock->recv_wait);
215}
216
217/*
218 * Operations
219 */
220
230int socket_inet_create(struct file *file, int domain, int type, int protocol)
231{
233
234 if (type == SOCK_STREAM && (!protocol || protocol == IPPROTO_TCP))
235 return socket_tcp_create(file, domain, type, protocol);
236
237 if (type != SOCK_DGRAM)
238 return -EPROTONOSUPPORT;
239
240 switch (protocol) {
241 case 0:
242 case IPPROTO_UDP:
244 break;
245 case IPPROTO_ICMP:
247 break;
248 default:
249 return -EPROTONOSUPPORT;
250 }
251
252 struct socket *socket = kmalloc(sizeof(struct socket), &M_SOCKET, M_ZERO);
253 struct inet_sock *sock = kmalloc(sizeof(struct inet_sock), &M_INET_SOCK, M_ZERO);
254
255 if (!socket || !sock) {
256 kfree(socket);
257 kfree(sock);
258 return -ENOMEM;
259 }
260
261 sock->proto = proto;
262
263 socket->domain = domain;
264 socket->type = type;
265 socket->protocol = protocol;
267 socket->p = sock;
268
270 file->socket = socket;
271 return 0;
272}
273
283int inet_sockaddr_get(const struct sockaddr *addr, socklen_t len, uint32_t *ip, uint16_t *port)
284{
285 const struct sockaddr_in *sin = (const struct sockaddr_in *) addr;
286
287 if (len < sizeof(*sin))
288 return -EINVAL;
289
290 if (sin->sin_family != AF_INET)
291 return -EAFNOSUPPORT;
292
293 *ip = sin->sin_addr.s_addr;
294 *port = sin->sin_port;
295 return 0;
296}
297
306void inet_sockaddr_put(struct sockaddr *addr, socklen_t *len, uint32_t ip, uint16_t port)
307{
308 struct sockaddr_in sin = {
309 .sin_family = AF_INET,
310 .sin_port = port,
311 .sin_addr = {ip},
312 };
313
314 memcpy(addr, &sin, MIN(*len, sizeof(sin)));
315 *len = sizeof(sin);
316}
317
320static int socket_inet_bind(struct file *file, const struct sockaddr *addr, socklen_t len)
321{
322 struct inet_sock *sock = file->socket->p;
323 uint32_t ip;
324 uint16_t port;
325 int err;
326
327 if ((err = inet_sockaddr_get(addr, len, &ip, &port)))
328 return err;
329
330 if (sock->lport)
331 return -EINVAL;
332
333 /* any address, one of ours, or the broadcast address (to receive only
334 * what is sent to it, as a DHCP client does) */
335 if (ip && ip != 0xffffffff && !ipv4_is_local(ip))
336 return -EADDRNOTAVAIL;
337
338 /* only root may bind to the ports below 1024 */
339 if (sock->proto == IP_PROTO_UDP && ntohs(port) && ntohs(port) < 1024 && curproc->uid)
340 return -EACCES;
341
342 return sock_bind(sock, ip, port);
343}
344
347static int socket_inet_connect(struct file *file, const struct sockaddr *addr, socklen_t len)
348{
349 struct inet_sock *sock = file->socket->p;
350 uint32_t ip;
351 uint16_t port;
352 int err;
353
354 /* AF_UNSPEC: disconnect */
355 if (len >= sizeof(sa_family_t) && addr->sa_family == AF_UNSPEC) {
356 sock->connected = 0;
357 sock->raddr = 0;
358 sock->rport = 0;
359 return 0;
360 }
361
362 if ((err = inet_sockaddr_get(addr, len, &ip, &port)))
363 return err;
364
365 if (sock->proto == IP_PROTO_UDP && !port)
366 return -EINVAL;
367
368 if (!sock->lport && (err = sock_bind(sock, 0, 0)))
369 return err;
370
371 sock->raddr = ip;
372 sock->rport = port;
373 sock->connected = 1;
374 sock->error = 0;
375 return 0;
376}
377
381static ssize_t socket_inet_send(struct file *file, struct iobuf *io, int flags,
382 const struct sockaddr *to, socklen_t tolen)
383{
384 struct inet_sock *sock = file->socket->p;
385 size_t len = io->resid;
386 uint32_t ip;
387 uint16_t port;
388 int err;
389
390 if (to) {
391 if ((err = inet_sockaddr_get(to, tolen, &ip, &port)))
392 return err;
393 } else if (sock->connected) {
394 ip = sock->raddr;
395 port = sock->rport;
396 } else {
397 return -EDESTADDRREQ;
398 }
399
400 if (sock->error) {
401 err = -sock->error;
402 sock->error = 0;
403 return err;
404 }
405
406 /* a socket bound to an interface sends through it, whatever the routes
407 * say */
408 struct netif *netif = sock->netif ? sock->netif : ipv4_route(ip);
409
410 if (!netif)
411 return -ENETUNREACH;
412
413 if (!(netif->flags & NETIF_UP))
414 return -ENETDOWN;
415
416 if ((ip == 0xffffffff || ip == (netif->ip | ~netif->netmask)) && !sock->broadcast)
417 return -EACCES;
418
419 size_t header = sock->proto == IP_PROTO_UDP ? sizeof(struct udp_hdr) : 0;
420
421 if (len + header + sizeof(struct ipv4_hdr) > netif->mtu)
422 return -EMSGSIZE;
423
424 if (!sock->lport && (err = sock_bind(sock, 0, 0)))
425 return err;
426
427 struct netbuf *nb = netbuf_alloc();
428
429 if (!nb)
430 return -ENOBUFS;
431
432 /* send from the address it is bound to, if any (but not from the
433 * broadcast address: from the interface's then, or 0.0.0.0 if it has
434 * none) */
435 uint32_t src = sock->laddr && sock->laddr != 0xffffffff ? sock->laddr :
436 ipv4_source(netif, ip);
437
438 /* copy in the whole datagram, or nothing */
439 void *data = netbuf_put(nb, len);
440
441 if ((size_t) iobuf_in(io, data, len) != len) {
442 netbuf_free(nb);
443 return -EFAULT;
444 }
445
446 if (sock->proto == IP_PROTO_UDP) {
447 struct udp_hdr *uh = netbuf_push(nb, sizeof(*uh));
448 uh->src = sock->lport;
449 uh->dst = port;
450 uh->len = htons(nb->len);
451 uh->checksum = 0;
452 uh->checksum = inet_checksum_pseudo(src, ip, IP_PROTO_UDP, uh, nb->len);
453
454 /* 0 means no checksum, so a checksum of 0 is sent as all ones */
455 if (!uh->checksum)
456 uh->checksum = 0xffff;
457 } else {
458 /* ping: only echo requests, with the socket's identifier */
459 struct icmp_hdr *icmp = data;
460
461 if (len < sizeof(*icmp) || icmp->type != ICMP_ECHO_REQUEST || icmp->code) {
462 netbuf_free(nb);
463 return -EINVAL;
464 }
465
466 icmp->id = sock->lport;
467 icmp->checksum = 0;
468 icmp->checksum = inet_checksum(icmp, len);
469 }
470
471 if ((err = ipv4_output(netif, src, ip, sock->proto, nb)) && err != -ENOBUFS)
472 return err;
473
474 return len;
475}
476
481static ssize_t socket_inet_recv(struct file *file, struct iobuf *io, int flags,
482 struct sockaddr *from, socklen_t *fromlen)
483{
484 struct inet_sock *sock = file->socket->p;
485 uint64_t until = sock->rcvtimeo ? arch_rtime_ns() + sock->rcvtimeo : 0;
486
487 while (!sock->recv_head) {
488 if (sock->error) {
489 int err = sock->error;
490 sock->error = 0;
491 return -err;
492 }
493
494 if (sock->shut_rd)
495 return 0;
496
497 if ((file->flags & O_NONBLOCK) || (flags & MSG_DONTWAIT))
498 return -EAGAIN;
499
500 int r = sched_wait(&sock->recv_wait, until);
501
502 if (r)
503 return r < 0 ? r : -EAGAIN;
504 }
505
506 struct netbuf *nb = sock->recv_head;
507
508 /* if copying out faults, the datagram stays queued */
509 ssize_t n = iobuf_out(io, nb->data, nb->len);
510
511 if (n < 0)
512 return n;
513
514 if (from && fromlen)
515 inet_sockaddr_put(from, fromlen, nb->src_ip, nb->src_port);
516
517 /* the datagram is gone, even the part that didn't fit */
518 if (!(flags & MSG_PEEK)) {
519 sock->recv_head = nb->next;
520
521 if (!sock->recv_head)
522 sock->recv_tail = NULL;
523
524 sock->recv_bytes -= NETBUF_SIZE;
525 netbuf_free(nb);
526 }
527
528 return n;
529}
530
533static int socket_inet_can_read(struct file *file, size_t len)
534{
535 struct inet_sock *sock = file->socket->p;
536
537 return sock->recv_head ? (int) sock->recv_head->len + 1 : sock->error || sock->shut_rd;
538}
539
541static int socket_inet_can_write(struct file *file, size_t len)
542{
543 return 1;
544}
545
548static struct waitq *socket_inet_wait_queue(struct file *file, int write)
549{
550 struct inet_sock *sock = file->socket->p;
551 return write ? NULL : &sock->recv_wait;
552}
553
556static int socket_inet_getname(struct file *file, struct sockaddr *addr, socklen_t *len, int peer)
557{
558 struct inet_sock *sock = file->socket->p;
559
560 if (peer) {
561 if (!sock->connected)
562 return -ENOTCONN;
563
564 inet_sockaddr_put(addr, len, sock->raddr, sock->rport);
565 } else {
566 inet_sockaddr_put(addr, len, sock->laddr, sock->lport);
567 }
568
569 return 0;
570}
571
574static int socket_inet_getsockopt(struct file *file, int level, int name, void *val, socklen_t *len)
575{
576 struct inet_sock *sock = file->socket->p;
577
578 if (level != SOL_SOCKET)
579 return -ENOPROTOOPT;
580
581 switch (name) {
582 case SO_ERROR:
583 case SO_BROADCAST:
584 if (*len < sizeof(int))
585 return -EINVAL;
586
587 if (name == SO_ERROR) {
588 *(int *) val = sock->error;
589 sock->error = 0;
590 } else {
591 *(int *) val = sock->broadcast;
592 }
593
594 *len = sizeof(int);
595 return 0;
596
597 case SO_BINDTODEVICE: {
598 /* the interface's name, or "" if none */
599 const char *name = sock->netif ? sock->netif->name : "";
600 size_t n = strlen(name) + 1;
601
602 if (*len < n)
603 return -EINVAL;
604
605 memcpy(val, name, n);
606 *len = n;
607 return 0;
608 }
609
610 case SO_RCVTIMEO: {
611 if (*len < sizeof(struct timeval))
612 return -EINVAL;
613
614 struct timeval *tv = val;
615 tv->tv_sec = sock->rcvtimeo / 1000000000ULL;
616 tv->tv_usec = sock->rcvtimeo % 1000000000ULL / 1000;
617 *len = sizeof(struct timeval);
618 return 0;
619 }
620 }
621
622 return -ENOPROTOOPT;
623}
624
627static int socket_inet_setsockopt(struct file *file, int level, int name, const void *val, socklen_t len)
628{
629 struct inet_sock *sock = file->socket->p;
630
631 if (level != SOL_SOCKET)
632 return -ENOPROTOOPT;
633
634 switch (name) {
635 case SO_BROADCAST:
636 if (len < sizeof(int))
637 return -EINVAL;
638
639 sock->broadcast = !!*(const int *) val;
640 return 0;
641
642 case SO_BINDTODEVICE: {
643 /* an interface's name (in a buffer that may be longer, such as
644 * a struct ifreq), or none if empty; only root may set it, as
645 * on Linux */
646 char name[17] = {0};
647
648 if (curproc->uid)
649 return -EPERM;
650
651 memcpy(name, val, MIN(len, (socklen_t) 16));
652
653 if (!name[0]) {
654 sock->netif = NULL;
655 return 0;
656 }
657
658 struct netif *netif = netif_find(name);
659
660 if (!netif)
661 return -ENODEV;
662
663 sock->netif = netif;
664 return 0;
665 }
666
667 case SO_RCVTIMEO: {
668 if (len < sizeof(struct timeval))
669 return -EINVAL;
670
671 const struct timeval *tv = val;
672
673 if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
674 return -EDOM;
675
676 sock->rcvtimeo = (uint64_t) tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL;
677 return 0;
678 }
679 }
680
681 return -ENOPROTOOPT;
682}
683
686static int socket_inet_ioctl(struct file *file, int request, void *argp)
687{
688 struct inet_sock *sock = file->socket->p;
689
690 if (request == FIONREAD) {
691 int n = sock->recv_head ? (int) sock->recv_head->len : 0;
692 return copyout(argp, &n, sizeof(n));
693 }
694
695 return inet_ifioctl(request, argp);
696}
697
700static int socket_inet_shut(struct file *file, int how)
701{
702 struct inet_sock *sock = file->socket->p;
703
704 if (how & SHUT_RD) {
705 sock->shut_rd = 1;
706 waitq_wakeup(&sock->recv_wait);
707 }
708
709 return 0;
710}
711
714static int socket_inet_shutdown(struct file *file, int how)
715{
716 struct inet_sock *sock = file->socket->p;
717
718 if (sock->lport)
719 sock_unbind(sock);
720
721 while (sock->recv_head) {
722 struct netbuf *nb = sock->recv_head;
723 sock->recv_head = nb->next;
724 netbuf_free(nb);
725 }
726
727 kfree(sock);
728 kfree(file->socket);
729 file->socket = NULL;
730 return 0;
731}
732
733static struct sock_ops socket_inet_ops = {
734 .bind = socket_inet_bind,
735 .connect = socket_inet_connect,
736 .recv = socket_inet_recv,
737 .send = socket_inet_send,
738 .can_read = socket_inet_can_read,
739 .can_write = socket_inet_can_write,
740 .wait_queue = socket_inet_wait_queue,
741 .getname = socket_inet_getname,
742 .getsockopt = socket_inet_getsockopt,
743 .setsockopt = socket_inet_setsockopt,
744 .ioctl = socket_inet_ioctl,
745 .shut = socket_inet_shut,
746 .shutdown = socket_inet_shutdown,
747};
#define htons(x)
Definition byteorder.h:10
#define ntohs(x)
Definition byteorder.h:17
#define MIN(a, b)
Definition system.h:11
static int socket_inet_bind(struct file *file, const struct sockaddr *addr, socklen_t len)
Binds a socket to an address that is ours, any address, or the broadcast address.
Definition socket.c:320
static ssize_t socket_inet_send(struct file *file, struct iobuf *io, int flags, const struct sockaddr *to, socklen_t tolen)
Sends a datagram, whole: to to, or to the connected peer.
Definition socket.c:381
static int socket_inet_can_write(struct file *file, size_t len)
Says that a write never waits.
Definition socket.c:541
static int socket_inet_setsockopt(struct file *file, int level, int name, const void *val, socklen_t len)
Sets a socket option: SO_BROADCAST, SO_BINDTODEVICE or SO_RCVTIMEO.
Definition socket.c:627
#define RECV_MAX
Definition socket.c:39
static int socket_inet_ioctl(struct file *file, int request, void *argp)
Handles FIONREAD (the size of the next datagram) and the interface requests.
Definition socket.c:686
static int socket_inet_shut(struct file *file, int how)
Shuts down reading: the readers wake up and see the end.
Definition socket.c:700
static ssize_t socket_inet_recv(struct file *file, struct iobuf *io, int flags, struct sockaddr *from, socklen_t *fromlen)
Receives a datagram, waiting for one unless the socket doesn't block or the receive timeout passes.
Definition socket.c:481
static int socket_inet_connect(struct file *file, const struct sockaddr *addr, socklen_t len)
Connects a datagram socket: its default destination, and the only sender it receives from.
Definition socket.c:347
static void sock_unbind(struct inet_sock *sock)
Takes a socket off the list of bound sockets.
Definition socket.c:128
static int sock_bind(struct inet_sock *sock, uint32_t addr, uint16_t port)
Binds a socket to an address and port, and puts it on the list of bound sockets.
Definition socket.c:93
static int port_used(uint8_t proto, uint32_t addr, uint16_t port)
Returns whether a socket of proto is bound to port on addr (or on any address, or addr is any).
Definition socket.c:80
static struct sock_ops socket_inet_ops
Definition socket.c:72
static int socket_inet_getname(struct file *file, struct sockaddr *addr, socklen_t *len, int peer)
Gets the socket's local address, or its peer's (-ENOTCONN if it isn't connected).
Definition socket.c:556
#define PORT_FIRST
Definition socket.c:41
static int socket_inet_shutdown(struct file *file, int how)
Frees the socket when its last descriptor is closed: it is unbound, and its queued datagrams are free...
Definition socket.c:714
static struct inet_sock * bound
Definition socket.c:70
static int socket_inet_can_read(struct file *file, size_t len)
Says whether a read wouldn't wait: a datagram is queued, or there is an error to report,...
Definition socket.c:533
static int socket_inet_getsockopt(struct file *file, int level, int name, void *val, socklen_t *len)
Reads a socket option: SO_ERROR, SO_BROADCAST, SO_BINDTODEVICE or SO_RCVTIMEO.
Definition socket.c:574
static struct waitq * socket_inet_wait_queue(struct file *file, int write)
Returns the wait queue that the socket's readers sleep on; writers never wait.
Definition socket.c:548
#define PORT_LAST
Definition socket.c:42
uint16_t inet_checksum(const void *data, size_t len)
Computes the Internet checksum (RFC 1071): the ones' complement of the ones' complement sum of the da...
Definition ether.c:76
void inet_sockaddr_put(struct sockaddr *addr, socklen_t *len, uint32_t ip, uint16_t port)
Writes an AF_INET address, cut to *len bytes if it doesn't fit.
Definition socket.c:306
int inet_ifioctl(int request, void *argp)
Handles an interface ioctl() request on an AF_INET socket.
Definition ifioctl.c:153
struct inet_sock * inet_sock_find(struct netif *netif, uint8_t proto, uint32_t local, uint16_t port, uint32_t remote, uint16_t remote_port)
Finds the socket that a received datagram is for: a socket connected to its sender first,...
Definition socket.c:154
struct netif * ipv4_route(uint32_t dst)
Chooses the interface to send a packet to dst through: the one whose link it is on,...
Definition ipv4.c:142
#define ICMP_ECHO_REQUEST
Definition inet.h:62
#define IP_PROTO_UDP
Definition inet.h:43
int ipv4_is_local(uint32_t ip)
Says whether an address is one of ours: a loopback address, or an interface's.
Definition ipv4.c:48
void inet_sock_error(struct inet_sock *sock, int err)
Gives a socket an error (from ICMP), which its next call reports.
Definition socket.c:211
uint16_t inet_checksum_pseudo(uint32_t src, uint32_t dst, uint8_t proto, const void *data, size_t len)
Computes the Internet checksum of data with the IPv4 pseudo-header before it (the addresses,...
Definition ether.c:106
#define IP_PROTO_ICMP
Definition inet.h:41
uint32_t ipv4_source(struct netif *netif, uint32_t dst)
Chooses the source address of a packet to dst sent through netif.
Definition ipv4.c:69
int ipv4_output(struct netif *netif, uint32_t src, uint32_t dst, uint8_t proto, struct netbuf *nb)
Sends a packet through an interface: adds its IPv4 header and sends it to dst, or to the gateway if d...
Definition ipv4.c:190
void inet_sock_deliver(struct inet_sock *sock, struct netbuf *nb)
Queues a received datagram on its socket, and wakes up its readers.
Definition socket.c:185
int inet_sockaddr_get(const struct sockaddr *addr, socklen_t len, uint32_t *ip, uint16_t *port)
Reads an AF_INET address.
Definition socket.c:283
ssize_t iobuf_out(struct iobuf *io, const void *src, size_t n)
Copies bytes from the kernel into the iobuf's buffer, and moves past them.
Definition iobuf.c:115
#define MALLOC_DEFINE(type, _name, _desc)
Definition kvmem.h:30
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
#define MALLOC_DECLARE(type)
Definition kvmem.h:29
#define M_ZERO
Definition kvmem.h:26
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
Definition libc.c:11
static void * netbuf_push(struct netbuf *nb, size_t size)
Makes room for a header of size bytes before the data, and returns it.
Definition netbuf.h:52
#define NETBUF_SIZE
Definition netbuf.h:40
void netbuf_free(struct netbuf *nb)
Frees a netbuf.
Definition netbuf.c:99
struct netbuf * netbuf_alloc(void)
Allocates a netbuf, empty, with room for the headers that will be put in front of its data.
Definition netbuf.c:58
#define NETIF_UP
Definition netif.h:8
struct netif * netif_find(const char *name)
Finds an interface by its name.
Definition netif.c:186
void random_get(void *_buf, size_t len)
Fills a buffer with random bytes.
Definition random.c:93
#define curproc
Definition sched.h:13
int sched_wait(struct waitq *waitq, uint64_t until)
Puts the current thread to sleep on a wait queue until it is woken up, a signal ends the sleep,...
Definition sched.c:187
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
#define FILE_SOCKET
Definition socket.h:70
int socket_tcp_create(struct file *file, int domain, int type, int protocol)
Makes a TCP socket, with its connection, CLOSED.
Definition tcp_socket.c:490
#define NULL
Definition stddef.h:27
unsigned int uint32_t
Definition stddef.h:22
unsigned char uint8_t
Definition stddef.h:20
unsigned long long int uint64_t
Definition stddef.h:23
unsigned short int uint16_t
Definition stddef.h:21
An open file (POSIX's "open file description", fs/file.c).
Definition vfs.h:157
int flags
Definition vfs.h:164
An ICMP message's header.
Definition inet.h:68
uint8_t type
Definition inet.h:69
uint16_t id
Definition inet.h:72
uint8_t code
Definition inet.h:70
uint16_t checksum
Definition inet.h:71
A UDP or ping socket.
Definition socket.c:45
int connected
Definition socket.c:54
uint16_t rport
Definition socket.c:53
int broadcast
Definition socket.c:64
uint32_t raddr
Definition socket.c:52
size_t recv_bytes
Definition socket.c:57
uint16_t lport
Definition socket.c:51
struct waitq recv_wait
Definition socket.c:58
int shut_rd
Definition socket.c:65
struct netbuf * recv_tail
Definition socket.c:56
uint8_t proto
Definition socket.c:46
uint64_t rcvtimeo
Definition socket.c:63
uint32_t laddr
Definition socket.c:50
int error
Definition socket.c:62
struct netbuf * recv_head
Definition socket.c:56
struct inet_sock * next
Definition socket.c:67
struct netif * netif
Definition socket.c:60
An iobuf.
Definition iobuf.h:35
size_t resid
Definition iobuf.h:38
A packet (net/netbuf.c).
Definition netbuf.h:16
uint32_t src_ip
Definition netbuf.h:25
struct netbuf * next
Definition netbuf.h:17
uint8_t * data
Definition netbuf.h:19
uint16_t src_port
Definition netbuf.h:26
size_t len
Definition netbuf.h:20
A network interface (net/netif.c): a device that sends and receives Ethernet frames,...
Definition netif.h:16
int flags
Definition netif.h:20
uint32_t ip
Definition netif.h:24
uint32_t netmask
Definition netif.h:24
char name[8]
Definition netif.h:17
A domain's socket operations.
Definition socket.h:29
A socket.
Definition socket.h:16
int domain
Definition socket.h:17
void * p
Definition socket.h:25
int type
Definition socket.h:18
struct sock_ops * ops
Definition socket.h:22
int protocol
Definition socket.h:19
suseconds_t tv_usec
Definition types.h:37
time_t tv_sec
Definition types.h:36
A UDP datagram's header.
Definition inet.h:77
uint16_t checksum
Definition inet.h:81
uint16_t src
Definition inet.h:78
uint16_t len
Definition inet.h:80
uint16_t dst
Definition inet.h:79
Definition waitq.h:19
uint64_t arch_rtime_ns(void)
Reads the monotonic clock, which starts at boot.
Definition timer.c:56
long int ssize_t
Definition types.h:12
void waitq_wakeup(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, and every thread polling it.
Definition waitq.c:178