27#include <aquila/errno.h>
28#include <aquila/fcntl.h>
30#include <aquila/ioctl.h>
39#define RECV_MAX (128 * NETBUF_SIZE)
41#define PORT_FIRST 49152
42#define PORT_LAST 65535
83 if (s->proto == proto && s->lport == port &&
84 (!s->laddr || !addr || s->laddr == addr))
160 if (s->proto !=
proto || s->lport != port || (s->laddr && s->laddr != local) ||
161 (s->netif && s->netif !=
netif))
234 if (type == SOCK_STREAM && (!protocol || protocol == IPPROTO_TCP))
237 if (type != SOCK_DGRAM)
238 return -EPROTONOSUPPORT;
249 return -EPROTONOSUPPORT;
285 const struct sockaddr_in *sin = (
const struct sockaddr_in *) addr;
287 if (len <
sizeof(*sin))
290 if (sin->sin_family != AF_INET)
291 return -EAFNOSUPPORT;
293 *ip = sin->sin_addr.s_addr;
294 *port = sin->sin_port;
308 struct sockaddr_in sin = {
309 .sin_family = AF_INET,
314 memcpy(addr, &sin,
MIN(*len,
sizeof(sin)));
336 return -EADDRNOTAVAIL;
355 if (len >=
sizeof(sa_family_t) && addr->sa_family == AF_UNSPEC) {
382 const struct sockaddr *to, socklen_t tolen)
385 size_t len = io->
resid;
397 return -EDESTADDRREQ;
421 if (len + header + sizeof(struct ipv4_hdr) >
netif->mtu)
424 if (!sock->lport && (err = sock_bind(sock, 0, 0)))
435 uint32_t src = sock->laddr && sock->laddr != 0xffffffff ? sock->laddr :
439 void *data = netbuf_put(nb, len);
441 if ((size_t) iobuf_in(io, data, len) != len) {
482 struct sockaddr *from, socklen_t *fromlen)
489 int err = sock->
error;
497 if ((
file->
flags & O_NONBLOCK) || (flags & MSG_DONTWAIT))
503 return r < 0 ? r : -EAGAIN;
518 if (!(flags & MSG_PEEK)) {
578 if (level != SOL_SOCKET)
584 if (*len <
sizeof(
int))
587 if (name == SO_ERROR) {
588 *(
int *) val = sock->
error;
597 case SO_BINDTODEVICE: {
600 size_t n = strlen(name) + 1;
611 if (*len <
sizeof(
struct timeval))
631 if (level != SOL_SOCKET)
636 if (len <
sizeof(
int))
642 case SO_BINDTODEVICE: {
651 memcpy(name, val,
MIN(len, (socklen_t) 16));
668 if (len <
sizeof(
struct timeval))
671 const struct timeval *tv = val;
690 if (request == FIONREAD) {
692 return copyout(argp, &n,
sizeof(n));
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.
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.
static int socket_inet_can_write(struct file *file, size_t len)
Says that a write never waits.
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.
static int socket_inet_ioctl(struct file *file, int request, void *argp)
Handles FIONREAD (the size of the next datagram) and the interface requests.
static int socket_inet_shut(struct file *file, int how)
Shuts down reading: the readers wake up and see the end.
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.
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.
static void sock_unbind(struct inet_sock *sock)
Takes a socket off the list of bound sockets.
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.
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).
static struct sock_ops socket_inet_ops
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).
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...
static struct inet_sock * bound
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,...
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.
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.
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...
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.
int inet_ifioctl(int request, void *argp)
Handles an interface ioctl() request on an AF_INET socket.
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,...
struct netif * ipv4_route(uint32_t dst)
Chooses the interface to send a packet to dst through: the one whose link it is on,...
#define ICMP_ECHO_REQUEST
int ipv4_is_local(uint32_t ip)
Says whether an address is one of ours: a loopback address, or an interface's.
void inet_sock_error(struct inet_sock *sock, int err)
Gives a socket an error (from ICMP), which its next call reports.
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,...
uint32_t ipv4_source(struct netif *netif, uint32_t dst)
Chooses the source address of a packet to dst sent through netif.
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...
void inet_sock_deliver(struct inet_sock *sock, struct netbuf *nb)
Queues a received datagram on its socket, and wakes up its readers.
int inet_sockaddr_get(const struct sockaddr *addr, socklen_t len, uint32_t *ip, uint16_t *port)
Reads an AF_INET address.
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.
#define MALLOC_DEFINE(type, _name, _desc)
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
#define MALLOC_DECLARE(type)
void kfree(void *)
Frees an object that kmalloc() gave.
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
static void * netbuf_push(struct netbuf *nb, size_t size)
Makes room for a header of size bytes before the data, and returns it.
void netbuf_free(struct netbuf *nb)
Frees a netbuf.
struct netbuf * netbuf_alloc(void)
Allocates a netbuf, empty, with room for the headers that will be put in front of its data.
struct netif * netif_find(const char *name)
Finds an interface by its name.
void random_get(void *_buf, size_t len)
Fills a buffer with random bytes.
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,...
int socket_inet_create(struct file *file, int domain, int type, int protocol)
Makes an AF_INET socket: a TCP, UDP or ping socket.
int socket_tcp_create(struct file *file, int domain, int type, int protocol)
Makes a TCP socket, with its connection, CLOSED.
unsigned long long int uint64_t
unsigned short int uint16_t
An open file (POSIX's "open file description", fs/file.c).
An ICMP message's header.
struct netbuf * recv_tail
struct netbuf * recv_head
A network interface (net/netif.c): a device that sends and receives Ethernet frames,...
A domain's socket operations.
uint64_t arch_rtime_ns(void)
Reads the monotonic clock, which starts at boot.
void waitq_wakeup(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, and every thread polling it.