AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
tcp_socket.c
Go to the documentation of this file.
1
17
18#include <core/system.h>
19#include <core/arch.h>
20#include <core/string.h>
21#include <dev/random.h>
22#include <ds/hashmap.h>
23#include <fs/vfs.h>
24#include <net/byteorder.h>
25#include <net/inet.h>
26#include <net/netif.h>
27#include <net/socket.h>
28#include <net/tcp.h>
29#include <sys/proc.h>
30#include <sys/sched.h>
31#include <sys/uaccess.h>
32
33#include <aquila/errno.h>
34#include <aquila/fcntl.h>
35#include <aquila/in.h>
36#include <aquila/ioctl.h>
37#include <aquila/tcp.h>
38
39MALLOC_DECLARE(M_SOCKET);
40MALLOC_DEFINE(M_TCP_PCB, "tcp pcb", "TCP connection");
41
42#define PORT_FIRST 49152 /* the ephemeral ports' range */
43#define PORT_LAST 65535
44
45#define MSL 30000000000ULL /* 30 s: TIME_WAIT lasts 2 MSL */
46#define FIN_WAIT_2_TIME 60000000000ULL /* how long a closed socket waits for the peer's FIN */
47#define RTO_INITIAL 1000000000ULL
48
49#define KEEP_IDLE 7200000000000ULL /* keepalive: after 2 h of silence, */
50#define KEEP_INTERVAL 75000000000ULL /* a probe every 75 s, */
51#define KEEP_PROBES 9 /* and ETIMEDOUT after 9 unanswered */
52
53#define COPY_CHUNK 512
54
56static struct hashmap *conns;
58
60
61/*
62 * The connections
63 */
64
70
72static hash_t key_hash(const struct tcp_key *key)
73{
74 return hashmap_digest(key, sizeof(*key));
75}
76
78static int key_eq(void *entry, void *k)
79{
80 struct tcp_pcb *pcb = entry;
81 struct tcp_key *key = k;
82
83 return pcb->laddr == key->laddr && pcb->raddr == key->raddr &&
84 pcb->lport == key->lport && pcb->rport == key->rport;
85}
86
97{
98 struct tcp_key key = {laddr, raddr, lport, rport};
99 struct hashmap_node *node = conns ? hashmap_lookup(conns, key_hash(&key), &key) : NULL;
100
101 return node ? node->entry : NULL;
102}
103
112int tcp_insert(struct tcp_pcb *pcb)
113{
114 struct tcp_key key = {pcb->laddr, pcb->raddr, pcb->lport, pcb->rport};
115 hash_t hash = key_hash(&key);
116
117 if (!conns && !(conns = hashmap_new(0, key_eq)))
118 return -ENOMEM;
119
120 if (hashmap_lookup(conns, hash, &key))
121 return -EADDRINUSE;
122
123 if (hashmap_insert(conns, hash, pcb))
124 return -ENOMEM;
125
126 pcb->hnode = hashmap_lookup(conns, hash, &key);
127 return 0;
128}
129
139{
140 struct tcp_pcb *any = NULL;
141
142 for (struct tcp_pcb *pcb = tcp_pcbs; pcb; pcb = pcb->next) {
143 if (pcb->state != TCP_LISTEN || pcb->lport != lport)
144 continue;
145
146 if (pcb->laddr == laddr)
147 return pcb;
148
149 if (!pcb->laddr)
150 any = pcb;
151 }
152
153 return any;
154}
155
162struct tcp_pcb *tcp_pcb_new(void)
163{
164 struct tcp_pcb *pcb = kmalloc(sizeof(struct tcp_pcb), &M_TCP_PCB, M_ZERO);
165
166 if (!pcb)
167 return NULL;
168
169 pcb->sndbuf = ringbuf_new(TCP_BUFSIZE);
170 pcb->rcvbuf = ringbuf_new(TCP_BUFSIZE);
171
172 if (!pcb->sndbuf || !pcb->rcvbuf) {
173 ringbuf_free(pcb->sndbuf);
174 ringbuf_free(pcb->rcvbuf);
175 kfree(pcb);
176 return NULL;
177 }
178
179 pcb->state = TCP_CLOSED;
180 pcb->mss = TCP_MSS_DEFAULT;
181 pcb->rto = RTO_INITIAL;
182 pcb->ssthresh = 0xffffffff;
183
184 pcb->next = tcp_pcbs;
185 tcp_pcbs = pcb;
186
187 return pcb;
188}
189
196void tcp_pcb_free(struct tcp_pcb *pcb)
197{
198 callout_stop(&pcb->rexmt);
199 callout_stop(&pcb->dack);
200 callout_stop(&pcb->timer2);
201
202 if (pcb->hnode)
203 hashmap_node_remove(conns, pcb->hnode);
204
205 for (struct tcp_pcb **p = &tcp_pcbs; *p; p = &(*p)->next) {
206 if (*p == pcb) {
207 *p = pcb->next;
208 break;
209 }
210 }
211
212 while (pcb->ooo) {
213 struct netbuf *nb = pcb->ooo;
214 pcb->ooo = nb->next;
215 netbuf_free(nb);
216 }
217
218 ringbuf_free(pcb->sndbuf);
219 ringbuf_free(pcb->rcvbuf);
220 kfree(pcb);
221}
222
232{
233 static int keyed;
234
235 if (!keyed) {
237 keyed = 1;
238 }
239
240 struct {
241 struct tcp_key key;
242 uint8_t secret[16];
243 } in;
244
245 in.key = (struct tcp_key) {pcb->laddr, pcb->raddr, pcb->lport, pcb->rport};
246 memcpy(in.secret, iss_secret, sizeof(in.secret));
247
248 return (uint32_t) (arch_rtime_ns() / 4000) + (uint32_t) hashmap_digest(&in, sizeof(in));
249}
250
257void tcp_wakeup(struct tcp_pcb *pcb)
258{
259 waitq_wakeup(&pcb->wait);
260}
261
264static void unlink_parent(struct tcp_pcb *pcb)
265{
266 struct tcp_pcb *l = pcb->parent;
267
268 if (!l)
269 return;
270
271 for (struct tcp_pcb **p = &l->accept_head; *p; p = &(*p)->accept_next) {
272 if (*p == pcb) {
273 *p = pcb->accept_next;
274 if (l->accept_tail == pcb) {
275 l->accept_tail = NULL;
276 for (struct tcp_pcb *q = l->accept_head; q; q = q->accept_next)
277 l->accept_tail = q;
278 }
279 break;
280 }
281 }
282
283 pcb->accept_next = NULL;
284 pcb->parent = NULL;
285 l->qlen--;
286}
287
295void tcp_closed(struct tcp_pcb *pcb)
296{
297 pcb->state = TCP_CLOSED;
298
299 if (pcb->hnode) {
300 hashmap_node_remove(conns, pcb->hnode);
301 pcb->hnode = NULL;
302 }
303
304 callout_stop(&pcb->rexmt);
305 callout_stop(&pcb->dack);
306 callout_stop(&pcb->timer2);
307 tcp_wakeup(pcb);
308
309 if (pcb->parent) {
310 unlink_parent(pcb);
311 tcp_pcb_free(pcb);
312 } else if (pcb->detached) {
313 tcp_pcb_free(pcb);
314 }
315}
316
323void tcp_drop(struct tcp_pcb *pcb, int err)
324{
325 pcb->error = err;
326 tcp_closed(pcb);
327}
328
335void tcp_established(struct tcp_pcb *pcb)
336{
337 pcb->state = TCP_ESTABLISHED;
338 pcb->connected = 1;
339
340 /* the initial congestion window (RFC 5681) */
341 pcb->cwnd = MIN(4U * pcb->mss, MAX(2U * pcb->mss, 4380U));
342 pcb->snd_nxt = pcb->snd_max = pcb->snd_una;
343
345
346 /* a listener's connection waits for accept() */
347 struct tcp_pcb *l = pcb->parent;
348
349 if (l) {
350 if (l->accept_tail)
351 l->accept_tail->accept_next = pcb;
352 else
353 l->accept_head = pcb;
354
355 l->accept_tail = pcb;
356 tcp_wakeup(l);
357 }
358
359 tcp_wakeup(pcb);
360}
361
363static void timer2_closed(void *arg)
364{
365 tcp_closed(arg);
366}
367
373void tcp_time_wait(struct tcp_pcb *pcb)
374{
375 pcb->state = TCP_TIME_WAIT;
376 callout_stop(&pcb->rexmt);
377 net_callout_set(&pcb->timer2, 2 * MSL, timer2_closed, pcb);
378 tcp_wakeup(pcb);
379}
380
387void tcp_fin_wait_2(struct tcp_pcb *pcb)
388{
389 if (pcb->detached)
391}
392
395static void keepalive_timeout(void *arg)
396{
397 struct tcp_pcb *pcb = arg;
398
399 if (pcb->state != TCP_ESTABLISHED || !pcb->keepalive)
400 return;
401
402 if (pcb->keep_probes++ >= KEEP_PROBES) {
403 tcp_send_rst(pcb);
404 tcp_drop(pcb, ETIMEDOUT);
405 return;
406 }
407
410}
411
418{
419 pcb->keep_probes = 0;
420
421 if (pcb->keepalive && pcb->state == TCP_ESTABLISHED)
423}
424
425/*
426 * Ports
427 */
428
431static int port_used(uint32_t addr, uint16_t port, int reuseaddr)
432{
433 for (struct tcp_pcb *pcb = tcp_pcbs; pcb; pcb = pcb->next) {
434 if (pcb->lport != port || (pcb->laddr && addr && pcb->laddr != addr))
435 continue;
436
437 if (pcb->state == TCP_LISTEN || !reuseaddr)
438 return 1;
439 }
440
441 return 0;
442}
443
446static int bind_port(struct tcp_pcb *pcb, uint32_t addr, uint16_t port)
447{
448 if (!port) {
449 /* the first free port from a random one on (RFC 6056, algorithm
450 * 1), so that the next port isn't the last one plus one, for
451 * anyone to guess */
453 random_get(&next, sizeof(next));
455
456 for (int i = 0; i <= PORT_LAST - PORT_FIRST; ++i) {
457 uint16_t p = htons(next);
458 next = next == PORT_LAST ? PORT_FIRST : next + 1;
459
460 if (!port_used(0, p, 0)) {
461 port = p;
462 break;
463 }
464 }
465
466 if (!port)
467 return -EADDRINUSE;
468 } else if (port_used(addr, port, pcb->reuseaddr)) {
469 return -EADDRINUSE;
470 }
471
472 pcb->laddr = addr;
473 pcb->lport = port;
474 return 0;
475}
476
477/*
478 * The socket
479 */
480
490int socket_tcp_create(struct file *file, int domain, int type, int protocol)
491{
492 struct socket *socket = kmalloc(sizeof(struct socket), &M_SOCKET, M_ZERO);
493 struct tcp_pcb *pcb = tcp_pcb_new();
494
495 if (!socket || !pcb) {
496 kfree(socket);
497 if (pcb)
498 tcp_pcb_free(pcb);
499 return -ENOMEM;
500 }
501
502 socket->domain = domain;
503 socket->type = type;
504 socket->protocol = protocol;
506 socket->p = pcb;
507
509 file->socket = socket;
510 return 0;
511}
512
515static int nonblock(struct file *file, int flags)
516{
517 return (file->flags & O_NONBLOCK) || (flags & MSG_DONTWAIT);
518}
519
523{
524 return timeo ? arch_rtime_ns() + timeo : 0;
525}
526
529static int socket_tcp_bind(struct file *file, const struct sockaddr *addr, socklen_t len)
530{
531 struct tcp_pcb *pcb = file->socket->p;
532 uint32_t ip;
533 uint16_t port;
534 int err;
535
536 if ((err = inet_sockaddr_get(addr, len, &ip, &port)))
537 return err;
538
539 if (pcb->state != TCP_CLOSED || pcb->lport)
540 return -EINVAL;
541
542 if (ip && !ipv4_is_local(ip))
543 return -EADDRNOTAVAIL;
544
545 /* only root may bind to the ports below 1024 */
546 if (ntohs(port) && ntohs(port) < 1024 && curproc->uid)
547 return -EACCES;
548
549 return bind_port(pcb, ip, port);
550}
551
554static int socket_tcp_listen(struct file *file, int backlog)
555{
556 struct tcp_pcb *pcb = file->socket->p;
557 int err;
558
559 if (pcb->state != TCP_CLOSED && pcb->state != TCP_LISTEN)
560 return -EINVAL;
561
562 if (!pcb->lport && (err = bind_port(pcb, 0, 0)))
563 return err;
564
565 pcb->state = TCP_LISTEN;
566 pcb->backlog = MIN(MAX(backlog, 1), SOMAXCONN);
567 return 0;
568}
569
572static int socket_tcp_accept(struct file *file, struct file *conn, const struct sockaddr *addr, socklen_t *len)
573{
574 struct tcp_pcb *pcb = file->socket->p;
575 int err;
576
577 if (pcb->state != TCP_LISTEN)
578 return -EINVAL;
579
580 uint64_t until = deadline(pcb->rcvtimeo);
581
582 while (!pcb->accept_head) {
583 if (nonblock(file, 0))
584 return -EAGAIN;
585
586 if ((err = sched_wait(&pcb->wait, until)))
587 return err < 0 ? err : -EAGAIN;
588
589 if (pcb->state != TCP_LISTEN)
590 return -EINVAL;
591 }
592
593 struct socket *socket = kmalloc(sizeof(struct socket), &M_SOCKET, M_ZERO);
594
595 if (!socket)
596 return -ENOMEM;
597
598 struct tcp_pcb *child = pcb->accept_head;
599 unlink_parent(child);
600
601 memcpy(socket, file->socket, sizeof(struct socket));
602 socket->p = child;
603
604 conn->socket = socket;
605 conn->flags = FILE_SOCKET;
606 conn->offset = 0;
607
608 if (addr)
609 inet_sockaddr_put((struct sockaddr *) addr, len, child->raddr, child->rport);
610
611 return 0;
612}
613
616static int socket_tcp_connect(struct file *file, const struct sockaddr *addr, socklen_t len)
617{
618 struct tcp_pcb *pcb = file->socket->p;
619 uint32_t ip;
620 uint16_t port;
621 int err;
622
623 switch (pcb->state) {
624 case TCP_CLOSED:
625 if (pcb->connected)
626 return -EISCONN;
627 break;
628 case TCP_SYN_SENT:
629 case TCP_SYN_RECEIVED:
630 /* a blocking connect() that a signal interrupted and that was
631 * restarted waits for the same connection, as on Linux */
632 if (nonblock(file, 0))
633 return -EALREADY;
634 goto wait;
635 case TCP_LISTEN:
636 return -EINVAL;
637 default:
638 return -EISCONN;
639 }
640
641 if ((err = inet_sockaddr_get(addr, len, &ip, &port)))
642 return err;
643
644 if (!ip || !port || ip == 0xffffffff)
645 return -EADDRNOTAVAIL;
646
647 struct netif *netif = ipv4_route(ip);
648
649 if (!netif)
650 return -ENETUNREACH;
651
652 if (!pcb->lport && (err = bind_port(pcb, 0, 0)))
653 return err;
654
655 if (!pcb->laddr)
656 pcb->laddr = ipv4_source(netif, ip);
657
658 pcb->raddr = ip;
659 pcb->rport = port;
660 pcb->error = 0;
661
662 if ((err = tcp_insert(pcb))) {
663 pcb->raddr = pcb->rport = 0;
664 return err;
665 }
666
667 pcb->iss = tcp_iss(pcb);
668 pcb->snd_una = pcb->iss;
669 pcb->state = TCP_SYN_SENT;
670 pcb->retries = 0;
671 tcp_send_syn(pcb);
672
673 if (nonblock(file, 0))
674 return -EINPROGRESS;
675
676wait:
677 /* if a signal ends the wait, the connection goes on being made
678 * without us */
679 while (pcb->state == TCP_SYN_SENT || pcb->state == TCP_SYN_RECEIVED)
680 if ((err = sched_wait(&pcb->wait, 0)) < 0)
681 return err;
682
683 if (pcb->connected && pcb->state != TCP_CLOSED)
684 return 0;
685
686 err = pcb->error ? pcb->error : ECONNREFUSED;
687 pcb->error = 0;
688 return -err;
689}
690
692static int can_send(struct tcp_pcb *pcb)
693{
694 return (pcb->state == TCP_ESTABLISHED || pcb->state == TCP_CLOSE_WAIT) && !pcb->fin_queued;
695}
696
700static ssize_t socket_tcp_send(struct file *file, struct iobuf *io, int flags,
701 const struct sockaddr *to, socklen_t tolen)
702{
703 struct tcp_pcb *pcb = file->socket->p;
704 int r;
705 uint64_t until = deadline(pcb->sndtimeo);
706 size_t sent = 0, len = io->resid;
707
708 if (flags & MSG_OOB)
709 return -EOPNOTSUPP;
710
711 while (sent < len) {
712 if (pcb->error) {
713 int err = pcb->error;
714 pcb->error = 0;
715 return sent ? (ssize_t) sent : -err;
716 }
717
718 /* still connecting: wait until it is connected */
719 if (pcb->state == TCP_SYN_SENT || pcb->state == TCP_SYN_RECEIVED) {
720 if (nonblock(file, flags))
721 return sent ? (ssize_t) sent : -EAGAIN;
722
723 if ((r = sched_wait(&pcb->wait, until)))
724 return sent ? (ssize_t) sent : r < 0 ? r : -EAGAIN;
725
726 continue;
727 }
728
729 if (!can_send(pcb))
730 return sent ? (ssize_t) sent : pcb->connected ? -EPIPE : -ENOTCONN;
731
732 size_t room = TCP_BUFSIZE - 1 - ringbuf_available(pcb->sndbuf);
733
734 if (!room) {
735 tcp_output(pcb);
736
737 if (nonblock(file, flags))
738 return sent ? (ssize_t) sent : -EAGAIN;
739
740 if ((r = sched_wait(&pcb->wait, until)))
741 return sent ? (ssize_t) sent : r < 0 ? r : -EAGAIN;
742
743 continue;
744 }
745
746 /* copy straight into the ring: the network's thread doesn't look
747 * past its tail */
748 ssize_t n = ringbuf_write_iobuf(pcb->sndbuf, MIN(room, len - sent), io);
749
750 if (n < 0) {
751 if (!sent)
752 return n;
753 break;
754 }
755
756 sent += n;
757
758 if (io->fault)
759 break;
760 }
761
762 tcp_output(pcb);
763 return sent;
764}
765
768static void window_update(struct tcp_pcb *pcb)
769{
770 if (pcb->state != TCP_ESTABLISHED && pcb->state != TCP_FIN_WAIT_1 &&
771 pcb->state != TCP_FIN_WAIT_2)
772 return;
773
774 uint32_t cur = SEQ_GT(pcb->rcv_adv, pcb->rcv_nxt) ? pcb->rcv_adv - pcb->rcv_nxt : 0;
775
776 if (tcp_rcv_window(pcb) > cur)
777 tcp_send_ack(pcb);
778}
779
783static ssize_t socket_tcp_recv(struct file *file, struct iobuf *io, int flags,
784 struct sockaddr *from, socklen_t *fromlen)
785{
786 struct tcp_pcb *pcb = file->socket->p;
787 int r;
788 uint64_t until = deadline(pcb->rcvtimeo);
789 size_t got = 0, len = io->resid;
790 char chunk[COPY_CHUNK];
791
792 if (flags & MSG_OOB)
793 return -EOPNOTSUPP;
794
795 if (pcb->state == TCP_LISTEN)
796 return -ENOTCONN;
797
798 while (got < len) {
799 size_t avail = ringbuf_available(pcb->rcvbuf);
800
801 /* a peek reads further into the ring each time, through a chunk
802 * on the stack */
803 if ((flags & MSG_PEEK) && avail > got) {
804 size_t n = ringbuf_read_noconsume(pcb->rcvbuf, got, MIN(len - got, sizeof(chunk)), chunk);
805 ssize_t c = iobuf_out(io, chunk, n);
806
807 if (c < 0)
808 return got ? (ssize_t) got : c;
809
810 got += c;
811
812 if (io->fault)
813 break;
814
815 continue;
816 }
817
818 /* copy straight from the ring: the network's thread doesn't look
819 * before its head */
820 if (avail && !(flags & MSG_PEEK)) {
821 ssize_t n = ringbuf_read_iobuf(pcb->rcvbuf, len - got, io);
822
823 if (n < 0)
824 return got ? (ssize_t) got : n;
825
826 got += n;
827 window_update(pcb);
828
829 if (io->fault)
830 break;
831
832 continue;
833 }
834
835 /* some data was read, and we don't wait for all of it */
836 if (got && (!(flags & MSG_WAITALL) || (flags & MSG_PEEK)))
837 break;
838
839 if (pcb->error) {
840 int err = pcb->error;
841 pcb->error = 0;
842 return got ? (ssize_t) got : -err;
843 }
844
845 /* the end of the data */
846 if (pcb->fin_received || pcb->shut_rd || (pcb->state == TCP_CLOSED && pcb->connected))
847 break;
848
849 if (pcb->state == TCP_CLOSED)
850 return -ENOTCONN;
851
852 if (nonblock(file, flags))
853 return got ? (ssize_t) got : -EAGAIN;
854
855 if ((r = sched_wait(&pcb->wait, until)))
856 return got ? (ssize_t) got : r < 0 ? r : -EAGAIN;
857 }
858
859 if (from && fromlen)
860 inet_sockaddr_put(from, fromlen, pcb->raddr, pcb->rport);
861
862 return got;
863}
864
867static int socket_tcp_can_read(struct file *file, size_t len)
868{
869 struct tcp_pcb *pcb = file->socket->p;
870
871 if (pcb->state == TCP_LISTEN)
872 return pcb->accept_head != NULL;
873
874 return ringbuf_available(pcb->rcvbuf) || pcb->fin_received || pcb->error || pcb->shut_rd ||
875 (pcb->state == TCP_CLOSED && pcb->connected);
876}
877
880static struct waitq *socket_tcp_wait_queue(struct file *file, int write)
881{
882 struct tcp_pcb *pcb = file->socket->p;
883 return &pcb->wait;
884}
885
888static int socket_tcp_can_write(struct file *file, size_t len)
889{
890 struct tcp_pcb *pcb = file->socket->p;
891
892 if (pcb->error || (pcb->connected && !can_send(pcb)))
893 return 1;
894
895 return can_send(pcb) && ringbuf_available(pcb->sndbuf) < TCP_BUFSIZE - 1;
896}
897
900static int socket_tcp_getname(struct file *file, struct sockaddr *addr, socklen_t *len, int peer)
901{
902 struct tcp_pcb *pcb = file->socket->p;
903
904 if (peer) {
905 if (pcb->state <= TCP_SYN_SENT)
906 return -ENOTCONN;
907
908 inet_sockaddr_put(addr, len, pcb->raddr, pcb->rport);
909 } else {
910 inet_sockaddr_put(addr, len, pcb->laddr, pcb->lport);
911 }
912
913 return 0;
914}
915
917static int int_get(void *val, socklen_t *len, int v)
918{
919 if (*len < sizeof(int))
920 return -EINVAL;
921
922 *(int *) val = v;
923 *len = sizeof(int);
924 return 0;
925}
926
928static int timeo_get(void *val, socklen_t *len, uint64_t ns)
929{
930 if (*len < sizeof(struct timeval))
931 return -EINVAL;
932
933 struct timeval *tv = val;
934 tv->tv_sec = ns / 1000000000ULL;
935 tv->tv_usec = ns % 1000000000ULL / 1000;
936 *len = sizeof(struct timeval);
937 return 0;
938}
939
942static int timeo_set(const void *val, socklen_t len, uint64_t *ns)
943{
944 if (len < sizeof(struct timeval))
945 return -EINVAL;
946
947 const struct timeval *tv = val;
948
949 if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
950 return -EDOM;
951
952 *ns = (uint64_t) tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL;
953 return 0;
954}
955
957static int socket_tcp_getsockopt(struct file *file, int level, int name, void *val, socklen_t *len)
958{
959 struct tcp_pcb *pcb = file->socket->p;
960
961 if (level == IPPROTO_TCP) {
962 switch (name) {
963 case TCP_NODELAY: return int_get(val, len, pcb->nodelay);
964 case TCP_MAXSEG: return int_get(val, len, pcb->mss);
965 }
966
967 return -ENOPROTOOPT;
968 }
969
970 if (level != SOL_SOCKET)
971 return -ENOPROTOOPT;
972
973 switch (name) {
974 case SO_ERROR: {
975 int err = pcb->error;
976 pcb->error = 0;
977 return int_get(val, len, err);
978 }
979 case SO_KEEPALIVE: return int_get(val, len, pcb->keepalive);
980 case SO_REUSEADDR: return int_get(val, len, pcb->reuseaddr);
981 case SO_ACCEPTCONN: return int_get(val, len, pcb->state == TCP_LISTEN);
982 case SO_SNDBUF:
983 case SO_RCVBUF: return int_get(val, len, TCP_BUFSIZE - 1);
984 case SO_RCVTIMEO: return timeo_get(val, len, pcb->rcvtimeo);
985 case SO_SNDTIMEO: return timeo_get(val, len, pcb->sndtimeo);
986 }
987
988 return -ENOPROTOOPT;
989}
990
992static int socket_tcp_setsockopt(struct file *file, int level, int name, const void *val, socklen_t len)
993{
994 struct tcp_pcb *pcb = file->socket->p;
995
996 if (level == IPPROTO_TCP) {
997 if (len < sizeof(int))
998 return -EINVAL;
999
1000 switch (name) {
1001 case TCP_NODELAY:
1002 pcb->nodelay = !!*(const int *) val;
1003 tcp_output(pcb);
1004 return 0;
1005 case TCP_MAXSEG:
1006 /* accepted, without effect: the peer's MSS and the
1007 * interface's MTU decide */
1008 return 0;
1009 }
1010
1011 return -ENOPROTOOPT;
1012 }
1013
1014 if (level != SOL_SOCKET)
1015 return -ENOPROTOOPT;
1016
1017 switch (name) {
1018 case SO_KEEPALIVE:
1019 if (len < sizeof(int))
1020 return -EINVAL;
1021
1022 pcb->keepalive = !!*(const int *) val;
1024 return 0;
1025
1026 case SO_REUSEADDR:
1027 if (len < sizeof(int))
1028 return -EINVAL;
1029
1030 pcb->reuseaddr = !!*(const int *) val;
1031 return 0;
1032
1033 case SO_RCVTIMEO: return timeo_set(val, len, &pcb->rcvtimeo);
1034 case SO_SNDTIMEO: return timeo_set(val, len, &pcb->sndtimeo);
1035 }
1036
1037 /* the socket layer accepts SO_SNDBUF, SO_RCVBUF and SO_LINGER */
1038 return -ENOPROTOOPT;
1039}
1040
1043static int socket_tcp_ioctl(struct file *file, int request, void *argp)
1044{
1045 struct tcp_pcb *pcb = file->socket->p;
1046
1047 if (request == FIONREAD) {
1048 int n = ringbuf_available(pcb->rcvbuf);
1049 return copyout(argp, &n, sizeof(n));
1050 }
1051
1052 return inet_ifioctl(request, argp);
1053}
1054
1056static void send_fin(struct tcp_pcb *pcb)
1057{
1058 if (pcb->fin_queued)
1059 return;
1060
1061 pcb->fin_queued = 1;
1062
1063 if (pcb->state == TCP_CLOSE_WAIT)
1064 pcb->state = TCP_LAST_ACK;
1065 else
1066 pcb->state = TCP_FIN_WAIT_1;
1067
1068 tcp_output(pcb);
1069}
1070
1073static int socket_tcp_shut(struct file *file, int how)
1074{
1075 struct tcp_pcb *pcb = file->socket->p;
1076
1077 if (pcb->state == TCP_CLOSED || pcb->state == TCP_LISTEN || pcb->state == TCP_SYN_SENT)
1078 return -ENOTCONN;
1079
1080 if (how & SHUT_RD) {
1081 pcb->shut_rd = 1;
1082 tcp_wakeup(pcb);
1083 }
1084
1085 if ((how & SHUT_WR) && (pcb->state == TCP_ESTABLISHED || pcb->state == TCP_CLOSE_WAIT ||
1086 pcb->state == TCP_SYN_RECEIVED))
1087 send_fin(pcb);
1088
1089 return 0;
1090}
1091
1095static int socket_tcp_shutdown(struct file *file, int how)
1096{
1097 struct tcp_pcb *pcb = file->socket->p;
1098
1099 pcb->detached = 1;
1100
1101 switch (pcb->state) {
1102 case TCP_LISTEN:
1103 /* reset the connections not accepted yet, and drop the ones
1104 * still being made */
1105 while (pcb->accept_head) {
1106 struct tcp_pcb *child = pcb->accept_head;
1107 tcp_send_rst(child);
1108 tcp_drop(child, 0);
1109 }
1110
1111 for (struct tcp_pcb *p = tcp_pcbs, *next; p; p = next) {
1112 next = p->next;
1113 if (p->parent == pcb)
1114 tcp_drop(p, 0);
1115 }
1116
1117 tcp_pcb_free(pcb);
1118 break;
1119
1120 case TCP_CLOSED:
1121 case TCP_SYN_SENT:
1122 tcp_pcb_free(pcb);
1123 break;
1124
1125 case TCP_SYN_RECEIVED:
1126 case TCP_ESTABLISHED:
1127 case TCP_CLOSE_WAIT:
1128 /* there is data no one will read: reset (RFC 2525) */
1129 if (ringbuf_available(pcb->rcvbuf) || pcb->ooo) {
1130 tcp_send_rst(pcb);
1131 tcp_drop(pcb, 0);
1132 break;
1133 }
1134
1135 send_fin(pcb);
1136 break;
1137
1138 case TCP_FIN_WAIT_2:
1139 tcp_fin_wait_2(pcb);
1140 break;
1141 }
1142
1143 kfree(file->socket);
1144 file->socket = NULL;
1145 return 0;
1146}
1147
1148static struct sock_ops socket_tcp_ops = {
1149 .accept = socket_tcp_accept,
1150 .bind = socket_tcp_bind,
1151 .connect = socket_tcp_connect,
1152 .listen = socket_tcp_listen,
1153 .recv = socket_tcp_recv,
1154 .send = socket_tcp_send,
1155 .can_read = socket_tcp_can_read,
1156 .can_write = socket_tcp_can_write,
1157 .wait_queue = socket_tcp_wait_queue,
1158 .getname = socket_tcp_getname,
1159 .getsockopt = socket_tcp_getsockopt,
1160 .setsockopt = socket_tcp_setsockopt,
1161 .ioctl = socket_tcp_ioctl,
1162 .shut = socket_tcp_shut,
1163 .shutdown = socket_tcp_shutdown,
1164};
#define htons(x)
Definition byteorder.h:10
#define ntohs(x)
Definition byteorder.h:17
void callout_stop(struct callout *c)
Cancels a callout, if it is pending.
Definition callout.c:23
uintptr_t hash_t
Definition hashmap.h:22
#define MIN(a, b)
Definition system.h:11
#define MAX(a, b)
Definition system.h:10
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
#define PORT_FIRST
Definition socket.c:41
#define PORT_LAST
Definition socket.c:42
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 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
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
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 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
void netbuf_free(struct netbuf *nb)
Frees a netbuf.
Definition netbuf.c:99
void net_callout_set(struct callout *c, uint64_t ns, void(*fn)(void *), void *arg)
Sets a callout that the network's thread runs: fn(arg) is called once ns ns have passed.
Definition netif.c:137
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
#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
off_t offset
Definition vfs.h:163
int flags
Definition vfs.h:164
A hash table's node: an entry, with its key's hash.
Definition hashmap.h:43
void * entry
Definition hashmap.h:45
A hash table.
Definition hashmap.h:32
An iobuf.
Definition iobuf.h:35
int fault
Definition iobuf.h:40
size_t resid
Definition iobuf.h:38
A packet (net/netbuf.c).
Definition netbuf.h:16
struct netbuf * next
Definition netbuf.h:17
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
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
What identifies a connection: both ends' addresses and ports.
Definition tcp_socket.c:66
uint32_t raddr
Definition tcp_socket.c:67
uint16_t lport
Definition tcp_socket.c:68
uint16_t rport
Definition tcp_socket.c:68
uint32_t laddr
Definition tcp_socket.c:67
A connection (its control block, or PCB).
Definition tcp.h:66
int nodelay
Definition tcp.h:106
uint32_t laddr
Definition tcp.h:70
uint16_t mss
Definition tcp.h:80
struct callout rexmt
Definition tcp.h:111
uint32_t cwnd
Definition tcp.h:100
int detached
Definition tcp.h:122
uint64_t rto
Definition tcp.h:92
int backlog
Definition tcp.h:120
struct tcp_pcb * next
Definition tcp.h:73
struct tcp_pcb * parent
Definition tcp.h:118
int error
Definition tcp.h:124
uint32_t snd_una
Definition tcp.h:78
uint32_t iss
Definition tcp.h:78
struct callout timer2
Definition tcp.h:113
int retries
Definition tcp.h:96
int shut_rd
Definition tcp.h:125
uint32_t snd_nxt
Definition tcp.h:78
int fin_received
Definition tcp.h:89
struct tcp_pcb * accept_next
Definition tcp.h:119
uint32_t rcv_adv
Definition tcp.h:86
int reuseaddr
Definition tcp.h:109
uint16_t rport
Definition tcp.h:71
uint16_t lport
Definition tcp.h:71
int qlen
Definition tcp.h:120
struct netbuf * ooo
Definition tcp.h:88
struct waitq wait
Definition tcp.h:127
uint32_t ssthresh
Definition tcp.h:100
uint64_t sndtimeo
Definition tcp.h:126
struct ringbuf * rcvbuf
Definition tcp.h:87
int state
Definition tcp.h:67
uint64_t rcvtimeo
Definition tcp.h:126
int fin_queued
Definition tcp.h:82
struct tcp_pcb * accept_head
Definition tcp.h:119
struct tcp_pcb * accept_tail
Definition tcp.h:119
struct hashmap_node * hnode
Definition tcp.h:74
int keep_probes
Definition tcp.h:108
uint32_t rcv_nxt
Definition tcp.h:86
int keepalive
Definition tcp.h:107
struct ringbuf * sndbuf
Definition tcp.h:81
uint32_t raddr
Definition tcp.h:70
struct callout dack
Definition tcp.h:112
int connected
Definition tcp.h:123
uint32_t snd_max
Definition tcp.h:78
suseconds_t tv_usec
Definition types.h:37
time_t tv_sec
Definition types.h:36
Definition waitq.h:19
void tcp_established(struct tcp_pcb *pcb)
Moves a connection to ESTABLISHED: its congestion window starts, and a listener's connection is queue...
Definition tcp_socket.c:335
struct tcp_pcb * tcp_lookup(uint32_t laddr, uint16_t lport, uint32_t raddr, uint16_t rport)
Finds a connection by both ends' addresses and ports.
Definition tcp_socket.c:96
void tcp_send_syn(struct tcp_pcb *pcb)
Sends the SYN (or, in SYN_RECEIVED, the SYN and ACK), the first time or again, and starts the retrans...
Definition tcp_output.c:135
#define SEQ_GT(a, b)
Definition tcp.h:52
#define TCP_BUFSIZE
Definition tcp.h:56
struct tcp_pcb * tcp_pcb_new(void)
Makes a connection, CLOSED, with its send and receive buffers, on the list of connections.
Definition tcp_socket.c:162
void tcp_closed(struct tcp_pcb *pcb)
Moves a connection to CLOSED: it leaves the hashmap, its timers stop, and its waiters wake up.
Definition tcp_socket.c:295
struct tcp_pcb * tcp_listener(uint32_t laddr, uint16_t lport)
Finds the listener for a local address and port: one bound to that address, or else one bound to any ...
Definition tcp_socket.c:138
void tcp_output(struct tcp_pcb *pcb)
Sends as much of the send buffer as the windows allow, in segments of at most mss bytes.
Definition tcp_output.c:249
#define TCP_MSS_DEFAULT
Definition tcp.h:59
void tcp_wakeup(struct tcp_pcb *pcb)
Wakes up the threads waiting on a connection (in accept(), connect(), recv() or send()).
Definition tcp_socket.c:257
void tcp_fin_wait_2(struct tcp_pcb *pcb)
Handles our FIN being acknowledged (FIN_WAIT_2): if the socket is closed, the connection waits for th...
Definition tcp_socket.c:387
void tcp_send_rst(struct tcp_pcb *pcb)
Sends a reset on a connection.
Definition tcp_output.c:178
void tcp_send_ack(struct tcp_pcb *pcb)
Sends an ACK, now.
Definition tcp_output.c:157
void tcp_time_wait(struct tcp_pcb *pcb)
Moves a connection to TIME_WAIT, which it leaves after 2 MSL.
Definition tcp_socket.c:373
int tcp_insert(struct tcp_pcb *pcb)
Adds a connection to the hashmap of connections, by its addresses and ports, which it must have now.
Definition tcp_socket.c:112
struct tcp_pcb * tcp_pcbs
Definition tcp_socket.c:55
@ TCP_ESTABLISHED
Definition tcp.h:40
@ TCP_LISTEN
Definition tcp.h:37
@ TCP_LAST_ACK
Definition tcp.h:45
@ TCP_FIN_WAIT_1
Definition tcp.h:41
@ TCP_CLOSE_WAIT
Definition tcp.h:43
@ TCP_CLOSED
Definition tcp.h:36
@ TCP_FIN_WAIT_2
Definition tcp.h:42
@ TCP_TIME_WAIT
Definition tcp.h:46
@ TCP_SYN_SENT
Definition tcp.h:38
@ TCP_SYN_RECEIVED
Definition tcp.h:39
uint16_t tcp_rcv_window(struct tcp_pcb *pcb)
Computes the window to advertise: the room in the receive buffer.
Definition tcp_output.c:49
uint32_t tcp_iss(struct tcp_pcb *pcb)
Chooses a connection's initial sequence number (RFC 6528): a clock that ticks every 4 us,...
Definition tcp_socket.c:231
void tcp_drop(struct tcp_pcb *pcb, int err)
Drops a connection that is lost, giving its socket an error.
Definition tcp_socket.c:323
void tcp_send_keepalive(struct tcp_pcb *pcb)
Sends a keepalive probe: a segment one byte before what the peer has acknowledged (with no data),...
Definition tcp_output.c:168
void tcp_keepalive_reset(struct tcp_pcb *pcb)
Restarts the keepalive timer, when the peer was heard from.
Definition tcp_socket.c:417
void tcp_pcb_free(struct tcp_pcb *pcb)
Frees a connection: its timers stop, it leaves the lists, and its buffers and waiting segments are fr...
Definition tcp_socket.c:196
#define KEEP_IDLE
Definition tcp_socket.c:49
static ssize_t socket_tcp_recv(struct file *file, struct iobuf *io, int flags, struct sockaddr *from, socklen_t *fromlen)
Receives data, waiting for some unless the socket doesn't block or the receive timeout passes (with M...
Definition tcp_socket.c:783
static int socket_tcp_shutdown(struct file *file, int how)
Detaches the connection when the socket's last descriptor is closed: the connection is closed,...
static struct hashmap * conns
Definition tcp_socket.c:56
static int can_send(struct tcp_pcb *pcb)
Returns whether data may be sent in the connection's state.
Definition tcp_socket.c:692
#define MSL
Definition tcp_socket.c:45
#define RTO_INITIAL
Definition tcp_socket.c:47
#define KEEP_PROBES
Definition tcp_socket.c:51
static int socket_tcp_can_read(struct file *file, size_t len)
Says whether a read (or an accept) wouldn't wait: there is data, a connection to accept,...
Definition tcp_socket.c:867
static int timeo_get(void *val, socklen_t *len, uint64_t ns)
Sets an option's value to a timeout, as a struct timeval.
Definition tcp_socket.c:928
static int key_eq(void *entry, void *k)
Returns whether a connection has the key k.
Definition tcp_socket.c:78
static int nonblock(struct file *file, int flags)
Returns whether a call shouldn't wait: the socket doesn't block, or the call has MSG_DONTWAIT.
Definition tcp_socket.c:515
static int socket_tcp_setsockopt(struct file *file, int level, int name, const void *val, socklen_t len)
Sets a TCP or socket option.
Definition tcp_socket.c:992
static int socket_tcp_connect(struct file *file, const struct sockaddr *addr, socklen_t len)
Connects to a peer: sends the SYN, and waits for the connection to be established,...
Definition tcp_socket.c:616
static uint64_t deadline(uint64_t timeo)
Returns the deadline for a timeout of timeo ns from now, or 0 for none.
Definition tcp_socket.c:522
static void keepalive_timeout(void *arg)
Sends a keepalive probe after a silence, or drops the connection (ETIMEDOUT) once too many probes wen...
Definition tcp_socket.c:395
#define COPY_CHUNK
Definition tcp_socket.c:53
static int socket_tcp_getsockopt(struct file *file, int level, int name, void *val, socklen_t *len)
Reads a TCP or socket option.
Definition tcp_socket.c:957
static void window_update(struct tcp_pcb *pcb)
Tells the peer that reading made room in the receive window, if it opened enough (tcp_rcv_window()).
Definition tcp_socket.c:768
static int socket_tcp_can_write(struct file *file, size_t len)
Says whether a write wouldn't wait: there is room in the send buffer, or an error or the end of sendi...
Definition tcp_socket.c:888
static uint8_t iss_secret[16]
Definition tcp_socket.c:57
static ssize_t socket_tcp_send(struct file *file, struct iobuf *io, int flags, const struct sockaddr *to, socklen_t tolen)
Sends data: it goes into the send buffer, waiting for room unless the socket doesn't block,...
Definition tcp_socket.c:700
static void timer2_closed(void *arg)
Closes a connection when its TIME_WAIT or FIN_WAIT_2 time is over.
Definition tcp_socket.c:363
#define FIN_WAIT_2_TIME
Definition tcp_socket.c:46
static struct waitq * socket_tcp_wait_queue(struct file *file, int write)
Returns the connection's wait queue, which accept(), connect(), recv() and send() all wait on.
Definition tcp_socket.c:880
static int socket_tcp_ioctl(struct file *file, int request, void *argp)
Handles FIONREAD (how much data can be read) and the interface requests.
static struct sock_ops socket_tcp_ops
Definition tcp_socket.c:59
static int int_get(void *val, socklen_t *len, int v)
Sets an option's value to the int v.
Definition tcp_socket.c:917
static void send_fin(struct tcp_pcb *pcb)
Queues our FIN, to go after what is in the send buffer.
static void unlink_parent(struct tcp_pcb *pcb)
Takes a connection off its listener's queue, when it is done or accept() took it.
Definition tcp_socket.c:264
static hash_t key_hash(const struct tcp_key *key)
Returns a connection key's hash.
Definition tcp_socket.c:72
static int socket_tcp_accept(struct file *file, struct file *conn, const struct sockaddr *addr, socklen_t *len)
Accepts an established connection, waiting for one unless the socket doesn't block or the receive tim...
Definition tcp_socket.c:572
#define KEEP_INTERVAL
Definition tcp_socket.c:50
static int socket_tcp_shut(struct file *file, int how)
Shuts down reading (readers see the end), writing (the FIN is sent), or both, for shutdown().
static int socket_tcp_bind(struct file *file, const struct sockaddr *addr, socklen_t len)
Binds the socket to a local address (ours, or any) and port; ports below 1024 are root's.
Definition tcp_socket.c:529
static int socket_tcp_listen(struct file *file, int backlog)
Makes the socket listen, binding it to an ephemeral port if it isn't bound.
Definition tcp_socket.c:554
static int socket_tcp_getname(struct file *file, struct sockaddr *addr, socklen_t *len, int peer)
Gets the socket's local address, or its peer's (-ENOTCONN before the peer is known).
Definition tcp_socket.c:900
static int timeo_set(const void *val, socklen_t len, uint64_t *ns)
Reads a timeout from an option's value, a struct timeval, into *ns.
Definition tcp_socket.c:942
static int bind_port(struct tcp_pcb *pcb, uint32_t addr, uint16_t port)
Binds a connection to a local address and port; port 0 picks a free ephemeral port.
Definition tcp_socket.c:446
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