libosmocore/include/osmocom/core/socket.h

144 lines
5.4 KiB
C
Raw Normal View History

/*! \file socket.h
* Osmocom socket convenience functions. */
#pragma once
#if (!EMBEDDED)
/*! \defgroup socket Socket convenience functions
* @{
* \file socket.h */
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <arpa/inet.h>
/*! maximum length of a socket name ("r=1.2.3.4:123<->l=5.6.7.8:987") */
#define OSMO_SOCK_NAME_MAXLEN (2 + INET6_ADDRSTRLEN + 1 + 5 + 3 + 2 + INET6_ADDRSTRLEN + 1 + 5 + 1)
struct sockaddr_in;
struct sockaddr;
struct osmo_fd;
struct osmo_sockaddr {
union {
struct sockaddr sa;
struct sockaddr_storage sas;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} u;
};
/* flags for osmo_sock_init. */
/*! connect the socket to a remote peer */
#define OSMO_SOCK_F_CONNECT (1 << 0)
/*! bind the socket to a local address/port */
#define OSMO_SOCK_F_BIND (1 << 1)
/*! switch socket to non-blocking mode */
#define OSMO_SOCK_F_NONBLOCK (1 << 2)
/*! disable multiast loop (IP_MULTICAST_LOOP) */
#define OSMO_SOCK_F_NO_MCAST_LOOP (1 << 3)
/*! disable receiving all multiast even for non-subscribed groups */
#define OSMO_SOCK_F_NO_MCAST_ALL (1 << 4)
/*! use SO_REUSEADDR on UDP ports (required for multicast) */
#define OSMO_SOCK_F_UDP_REUSEADDR (1 << 5)
/*! use OSMO_SOCK_F_DSCP(x) to set IP DSCP 'x' for packets transmitted on the socket */
#define OSMO_SOCK_F_DSCP(x) (((x)&0x3f) << 24)
#define GET_OSMO_SOCK_F_DSCP(f) (((f) >> 24) & 0x3f)
/*! use OSMO_SOCK_F_PRIO(x) to set priority 'x' for packets transmitted on the socket */
#define OSMO_SOCK_F_PRIO(x) (((x)&0xff) << 16)
#define GET_OSMO_SOCK_F_PRIO(f) (((f) >> 16) & 0xff)
/*! maximum number of local or remote addresses supported by an osmo_sock instance */
#define OSMO_SOCK_MAX_ADDRS 32
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
const char *host, uint16_t port, unsigned int flags);
int osmo_sock_init2(uint16_t family, uint16_t type, uint8_t proto,
const char *local_host, uint16_t local_port,
const char *remote_host, uint16_t remote_port, unsigned int flags);
int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
const char **local_hosts, size_t local_hosts_cnt, uint16_t local_port,
const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port, unsigned int flags);
int osmo_sock_init_osa(uint16_t type, uint8_t proto,
const struct osmo_sockaddr *local,
const struct osmo_sockaddr *remote,
unsigned int flags);
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
const char *host, uint16_t port, unsigned int flags);
int osmo_sock_init2_ofd(struct osmo_fd *ofd, int family, int type, int proto,
const char *local_host, uint16_t local_port,
const char *remote_host, uint16_t remote_port, unsigned int flags);
int osmo_sock_init_osa_ofd(struct osmo_fd *ofd, int type, int proto,
const struct osmo_sockaddr *local,
const struct osmo_sockaddr *remote,
unsigned int flags);
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
uint8_t proto, unsigned int flags);
int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen);
unsigned int osmo_sockaddr_to_str_and_uint(char *addr, unsigned int addr_len, uint16_t *port,
const struct sockaddr *sa);
size_t osmo_sockaddr_in_to_str_and_uint(char *addr, unsigned int addr_len, uint16_t *port,
const struct sockaddr_in *sin);
const char *osmo_sockaddr_ntop(const struct sockaddr *sa, char *dst);
uint16_t osmo_sockaddr_port(const struct sockaddr *sa);
int osmo_sock_unix_init(uint16_t type, uint8_t proto,
const char *socket_path, unsigned int flags);
int osmo_sock_unix_init_ofd(struct osmo_fd *ofd, uint16_t type, uint8_t proto,
const char *socket_path, unsigned int flags);
char *osmo_sock_get_name(const void *ctx, int fd);
add to osmo_sock_get_name*() API Basically, I am applying code review that I would have given had I not been on vacation when the last osmo_sock_get_name* stuff was merged. osmo_sock_get_name2() is so far a static internal function. However, it is nothing like osmo_sock_get_name(), so instead rename it to osmo_sock_get_ip_and_port(). Also make it public API, no need to hide it. I'm adding an "and" in the name to hopefully clarify: "ip_port" vs. "ip_and_port" -- there already are _get_X_ip_port() functions that only return the port string, despite "ip" in the name. Add new public osmo_sock_get_name2(), which is like osmo_sock_get_name(), except it uses a static string instead of talloc, and omits the braces. This is most convenient for log statement formats, avoiding dyn allocations. Add new osmo_sock_get_name_buf(), which is like osmo_sock_get_name2() but writes to a caller provided char buffer. Use osmo_sock_get_name_buf() in the implementation of osmo_sock_get_name(), but use another (non-static) local string buffer, because adding braces is too complex without talloc_snprintf(). Rationale: I want to improve the logging of socket errors, e.g. change DLMGCP ERROR Failed to read: 111/Connection refused (mgcp_client.c:720) to DLMGCP ERROR Failed to read: r=10.0.99.2:2427<->l=10.0.99.2:2728: 111='Connection refused' (mgcp_client.c:721) but it is just not handy to compose logging with the current API: - osmo_sock_get_name() requires a talloc_free(). - all the others require output buffers. - the only way to conveniently compose a logging string and, - notably, the only trivial way to skip the string composition if the logging level is currently muted, is to have a function that returns a static string: the new osmo_sock_get_name2(). - (I think the osmo_sock_get_{local,remote}_* convenience wrappers should never have been added, because they encourage the caller to invoke the same code twice, for IP addr and port, and throw away one half each time.) Related: Iae728192f499330d16836d9435648f6b8ed213b6 (osmo-mgw) Change-Id: I8ad89ac447c9c582742e70d082072bdd40a5a398
2018-12-12 00:48:54 +00:00
const char *osmo_sock_get_name2(int fd);
char *osmo_sock_get_name2_c(const void *ctx, int fd);
add to osmo_sock_get_name*() API Basically, I am applying code review that I would have given had I not been on vacation when the last osmo_sock_get_name* stuff was merged. osmo_sock_get_name2() is so far a static internal function. However, it is nothing like osmo_sock_get_name(), so instead rename it to osmo_sock_get_ip_and_port(). Also make it public API, no need to hide it. I'm adding an "and" in the name to hopefully clarify: "ip_port" vs. "ip_and_port" -- there already are _get_X_ip_port() functions that only return the port string, despite "ip" in the name. Add new public osmo_sock_get_name2(), which is like osmo_sock_get_name(), except it uses a static string instead of talloc, and omits the braces. This is most convenient for log statement formats, avoiding dyn allocations. Add new osmo_sock_get_name_buf(), which is like osmo_sock_get_name2() but writes to a caller provided char buffer. Use osmo_sock_get_name_buf() in the implementation of osmo_sock_get_name(), but use another (non-static) local string buffer, because adding braces is too complex without talloc_snprintf(). Rationale: I want to improve the logging of socket errors, e.g. change DLMGCP ERROR Failed to read: 111/Connection refused (mgcp_client.c:720) to DLMGCP ERROR Failed to read: r=10.0.99.2:2427<->l=10.0.99.2:2728: 111='Connection refused' (mgcp_client.c:721) but it is just not handy to compose logging with the current API: - osmo_sock_get_name() requires a talloc_free(). - all the others require output buffers. - the only way to conveniently compose a logging string and, - notably, the only trivial way to skip the string composition if the logging level is currently muted, is to have a function that returns a static string: the new osmo_sock_get_name2(). - (I think the osmo_sock_get_{local,remote}_* convenience wrappers should never have been added, because they encourage the caller to invoke the same code twice, for IP addr and port, and throw away one half each time.) Related: Iae728192f499330d16836d9435648f6b8ed213b6 (osmo-mgw) Change-Id: I8ad89ac447c9c582742e70d082072bdd40a5a398
2018-12-12 00:48:54 +00:00
int osmo_sock_get_name_buf(char *str, size_t str_len, int fd);
int osmo_sock_get_ip_and_port(int fd, char *ip, size_t ip_len, char *port, size_t port_len, bool local);
int osmo_sock_get_local_ip(int fd, char *host, size_t len);
int osmo_sock_get_local_ip_port(int fd, char *port, size_t len);
int osmo_sock_get_remote_ip(int fd, char *host, size_t len);
int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len);
int osmo_sock_mcast_loop_set(int fd, bool enable);
int osmo_sock_mcast_ttl_set(int fd, uint8_t ttl);
int osmo_sock_mcast_all_set(int fd, bool enable);
int osmo_sock_mcast_iface_set(int fd, const char *ifname);
int osmo_sock_mcast_subscribe(int fd, const char *grp_addr);
int osmo_sock_local_ip(char *local_ip, const char *remote_ip);
int osmo_sockaddr_local_ip(struct osmo_sockaddr *local_ip,
const struct osmo_sockaddr *remote_ip);
int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
const struct osmo_sockaddr *b);
int osmo_sockaddr_to_octets(uint8_t *dst, size_t dst_maxlen, const struct osmo_sockaddr *os);
int osmo_sockaddr_from_octets(struct osmo_sockaddr *os, const void *src, size_t src_len);
const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *sockaddr);
char *osmo_sockaddr_to_str_buf(char *buf, size_t buf_len,
const struct osmo_sockaddr *sockaddr);
int osmo_sockaddr_to_str_buf2(char *buf, size_t buf_len, const struct osmo_sockaddr *sockaddr);
char *osmo_sockaddr_to_str_c(void *ctx, const struct osmo_sockaddr *sockaddr);
int osmo_sock_set_dscp(int fd, uint8_t dscp);
int osmo_sock_set_priority(int fd, int prio);
#endif /* (!EMBEDDED) */
/*! @} */