summaryrefslogtreecommitdiffstats
path: root/src/contrib/net.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/net.h')
-rw-r--r--src/contrib/net.h264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/contrib/net.h b/src/contrib/net.h
new file mode 100644
index 0000000..698c66b
--- /dev/null
+++ b/src/contrib/net.h
@@ -0,0 +1,264 @@
+/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+// 1280 (IPv6 minimum link MTU) - 40 (IPv6 fixed header) - 20 (TCP fixed header)
+#define KNOT_TCP_MSS 1220
+
+/*!
+ * \brief Network interface flags.
+ */
+typedef enum {
+ NET_BIND_NONLOCAL = (1 << 0), //!< Allow to bind unavailable address.
+ NET_BIND_MULTIPLE = (1 << 1), //!< Allow to bind address multiple times.
+} net_bind_flag_t;
+
+/*!
+ * \brief Create unbound socket of given family and type.
+ *
+ * \note The socket is set to non-blocking mode.
+ *
+ * \param type Socket transport type (SOCK_STREAM, SOCK_DGRAM).
+ * \param addr Socket address.
+ *
+ * \return socket or error code
+ */
+int net_unbound_socket(int type, const struct sockaddr_storage *addr);
+
+/*!
+ * \brief Create socket bound to given address.
+ *
+ * The socket is set to non-blocking mode.
+ *
+ * \param type Socket transport type (SOCK_STREAM, SOCK_DGRAM).
+ * \param addr Socket address.
+ * \param flags Socket binding options.
+ * \param unix_mode Socket file mode (UNIX socket only). 0 means don't set mode.
+ *
+ * \return socket or error code
+ */
+int net_bound_socket(int type, const struct sockaddr_storage *addr,
+ net_bind_flag_t flags, mode_t unix_mode);
+
+/*!
+ * \brief Create socket connected (asynchronously) to destination address.
+ *
+ * \note The socket is set to non-blocking mode.
+ *
+ * \param type Socket transport type (SOCK_STREAM, SOCK_DGRAM).
+ * \param dst_addr Destination address.
+ * \param src_addr Source address (can be NULL).
+ * \param tfo Enable TCP Fast Open.
+ *
+ * \return socket or error code
+ */
+int net_connected_socket(int type, const struct sockaddr_storage *dst_addr,
+ const struct sockaddr_storage *src_addr, bool tfo);
+
+/*!
+ * \brief Enables TCP Fast Open on a bound socket.
+ *
+ * \param sock Socket.
+ *
+ * \return KNOT_EOK or error code
+ */
+int net_bound_tfo(int sock, int backlog);
+
+/*!
+ * \brief Tell kernel to send ECN bits thru CMSG on packet receival.
+ *
+ * \param sock Socket to enable receiving ECN bits.
+ * \param family Address family on that socket.
+ *
+ * \return KNOT_E*
+ */
+int net_cmsg_ecn_enable(int sock, int family);
+
+/*!
+ * \brief Return pointer to possible ECN value in cmsg.
+ *
+ * \note The function also updates cmsg_type for outgoing use.
+ *
+ * \param cmsg Received control message.
+ *
+ * \return Pointer to ECN value or NULL.
+ */
+int *net_cmsg_ecn_ptr(struct cmsghdr *cmsg);
+
+/*!
+ * \brief Get ECN bits of packets received by recv(m)msg.
+ *
+ * \param msg Received message header.
+ *
+ * \return 0..3
+ */
+uint8_t net_cmsg_ecn(struct msghdr *msg);
+
+/*!
+ * \brief Set ECN for outgoing packets on this socket.
+ *
+ * \param sock Socket file descriptor.
+ * \param family Address family for outgoing packets.
+ * \param ecn ECN bits to be set.
+ *
+ * \return KNOT_E*
+ */
+int net_ecn_set(int sock, int family, uint8_t ecn);
+
+/*!
+ * \brief Return true if the socket is fully connected.
+ *
+ * \param sock Socket.
+ *
+ * \return true if connected
+ */
+bool net_is_connected(int sock);
+
+/*!
+ * \brief Get socket type (e.g. \a SOCK_STREAM).
+ *
+ * \param sock Socket.
+ */
+int net_socktype(int sock);
+
+/*!
+ * \brief Check if socket is a SOCK_STREAM socket.
+ */
+bool net_is_stream(int sock);
+
+/*!
+ * \brief Accept a connection on a listening socket.
+ *
+ * \brief The socket is set to non-blocking mode.
+ *
+ * \param sock Socket
+ * \param addr Remote address (can be NULL).
+ *
+ * \return socket or error code
+ */
+int net_accept(int sock, struct sockaddr_storage *addr);
+
+/*!
+ * \brief Reset a TCP connection (with a RST packet).
+ */
+void net_reset(int sock);
+
+/*!
+ * \brief Send a message on a socket.
+ *
+ * The socket can be SOCK_STREAM or SOCK_DGRAM.
+ *
+ * The implementation handles partial-writes automatically.
+ *
+ * \param[in] sock Socket.
+ * \param[in] buffer Message buffer.
+ * \param[in] size Size of the message.
+ * \param[in] addr Remote address (ignored for SOCK_STREAM).
+ * \param[in] timeout_ms Write timeout in milliseconds (-1 for infinity,
+ * not valid for SOCK_DGRAM).
+ *
+ * \return Number of bytes sent or negative error code.
+ */
+ssize_t net_base_send(int sock, const uint8_t *buffer, size_t size,
+ const struct sockaddr_storage *addr, int timeout_ms);
+
+/*!
+ * \brief Receive a message from a socket.
+ *
+ * \param[in] sock Socket.
+ * \param[out] buffer Receiving buffer.
+ * \param[in] size Capacity of the receiving buffer.
+ * \param[out] addr Remote address (can be NULL).
+ * \param[in] timeout_ms Read timeout in milliseconds (-1 for infinity).
+ *
+ * \return Number of bytes read or negative error code.
+ */
+ssize_t net_base_recv(int sock, uint8_t *buffer, size_t size,
+ struct sockaddr_storage *addr, int timeout_ms);
+
+/*!
+ * \brief Send a message with prepared msghdr structure.
+ *
+ * \see net_base_send
+ */
+ssize_t net_msg_send(int sock, struct msghdr *msg, int timeout_ms);
+
+/*!
+ * \brief Receive a message into msghdr structure.
+ *
+ * \see net_base_send
+ */
+ssize_t net_msg_recv(int sock, struct msghdr *msg, int timeout_ms);
+
+/*!
+ * \brief Send a message on a SOCK_DGRAM socket.
+ *
+ * \see net_base_send
+ */
+ssize_t net_dgram_send(int sock, const uint8_t *buffer, size_t size,
+ const struct sockaddr_storage *addr);
+
+/*!
+ * \brief Receive a message from a SOCK_DGRAM socket.
+ *
+ * \see net_base_recv
+ */
+ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
+
+/*!
+ * \brief Send a message on a SOCK_STREAM socket.
+ *
+ * \see net_base_send
+ */
+ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms);
+
+/*!
+ * \brief Receive a message from a SOCK_STREAM socket.
+ *
+ * \see net_base_recv
+ */
+ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
+
+/*!
+ * \brief Send a DNS message on a TCP socket.
+ *
+ * The outgoing message is prefixed with a two-byte value carrying the DNS
+ * message size according to the specification. These two bytes are not
+ * reflected in the return value.
+ *
+ * \param[in] tfo_addr If not NULL, send using TCP Fast Open to this address.
+ *
+ * \see net_base_send
+ */
+ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms,
+ struct sockaddr_storage *tfo_addr);
+
+/*!
+ * \brief Receive a DNS message from a TCP socket.
+ *
+ * The first two bytes of the incoming message are interpreted as a DNS message
+ * size according to the specification. These two bytes are not included in
+ * the returned size. Only a complete DNS message is retrieved.
+ *
+ * \see net_base_recv
+ */
+ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);