diff --git a/src/modules/module-netjack2-driver.c b/src/modules/module-netjack2-driver.c index 4753cc091..da55f7c3d 100644 --- a/src/modules/module-netjack2-driver.c +++ b/src/modules/module-netjack2-driver.c @@ -34,6 +34,7 @@ #include "module-netjack2/packets.h" #include "module-netjack2/peer.c" +#include "network-utils.h" #ifndef IPTOS_DSCP #define IPTOS_DSCP_MASK 0xfc @@ -689,26 +690,6 @@ on_data_io(void *data, int fd, uint32_t mask) } } -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static bool is_multicast(struct sockaddr *sa, socklen_t salen) { if (sa->sa_family == AF_INET) { @@ -777,19 +758,6 @@ error: return res; } -static const char *get_ip(const struct sockaddr_storage *sa, char *ip, size_t len) -{ - if (sa->ss_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in*)sa; - inet_ntop(sa->ss_family, &in->sin_addr, ip, len); - } else if (sa->ss_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; - inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); - } else - snprintf(ip, len, "invalid ip"); - return ip; -} - static void update_timer(struct impl *impl, uint64_t timeout) { struct timespec value, interval; @@ -959,7 +927,7 @@ static int send_follower_available(struct impl *impl) pw_loop_update_io(impl->main_loop, impl->setup_socket, SPA_IO_IN); - pw_log_info("sending AVAILABLE to %s", get_ip(&impl->dst_addr, buffer, sizeof(buffer))); + pw_log_info("sending AVAILABLE to %s", get_ip_fmt(&impl->dst_addr, buffer, sizeof(buffer))); client_name = pw_properties_get(impl->props, "netjack2.client-name"); if (client_name == NULL) diff --git a/src/modules/module-netjack2-manager.c b/src/modules/module-netjack2-manager.c index ff2268ecc..f48cfb7c5 100644 --- a/src/modules/module-netjack2-manager.c +++ b/src/modules/module-netjack2-manager.c @@ -36,6 +36,7 @@ #include "module-netjack2/packets.h" #include "module-netjack2/peer.c" +#include "network-utils.h" #ifdef __FreeBSD__ #define ifr_ifindex ifr_index @@ -738,26 +739,6 @@ static int create_filters(struct follower *follower) return res; } -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static bool is_multicast(struct sockaddr *sa, socklen_t salen) { if (sa->sa_family == AF_INET) { @@ -882,20 +863,6 @@ error: return res; } -static const char *get_ip(const struct sockaddr_storage *sa, char *ip, size_t len) -{ - if (sa->ss_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in*)sa; - inet_ntop(sa->ss_family, &in->sin_addr, ip, len); - } else if (sa->ss_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; - inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); - } else { - snprintf(ip, len, "invalid address"); - } - return ip; -} - static int handle_follower_available(struct impl *impl, struct nj2_session_params *params, struct sockaddr_storage *addr, socklen_t addr_len) { @@ -1039,8 +1006,7 @@ static int handle_follower_available(struct impl *impl, struct nj2_session_param nj2_session_params_hton(params, &peer->params); params->packet_id = htonl(NJ2_ID_FOLLOWER_SETUP); - - pw_log_info("sending follower setup to %s", get_ip(addr, buffer, sizeof(buffer))); + pw_log_info("sending follower setup to %s", get_ip_fmt(addr, buffer, sizeof(buffer))); nj2_dump_session_params(params); send(follower->socket->fd, params, sizeof(*params), 0); @@ -1139,7 +1105,7 @@ static int create_netjack2_socket(struct impl *impl) goto out; } pw_log_info("listening for AVAILABLE on %s", - get_ip(&impl->src_addr, buffer, sizeof(buffer))); + get_ip_fmt(&impl->src_addr, buffer, sizeof(buffer))); return 0; out: return res; diff --git a/src/modules/module-rtp-sap.c b/src/modules/module-rtp-sap.c index 3dca46dcd..157a12f38 100644 --- a/src/modules/module-rtp-sap.c +++ b/src/modules/module-rtp-sap.c @@ -27,6 +27,7 @@ #include #include +#include "network-utils.h" #ifdef __FreeBSD__ #define ifr_ifindex ifr_index @@ -354,26 +355,6 @@ static void session_free(struct session *sess) free(sess); } -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static bool is_multicast(struct sockaddr *sa, socklen_t salen) { if (sa->sa_family == AF_INET) { @@ -414,21 +395,6 @@ static int make_unix_socket(const char *path) { return spa_steal_fd(fd); } -static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, bool *ip4) -{ - if (sa->ss_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in*)sa; - inet_ntop(sa->ss_family, &in->sin_addr, ip, len); - } else if (sa->ss_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; - inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); - } else - return -EIO; - if (ip4) - *ip4 = sa->ss_family == AF_INET; - return 0; -} - static int make_send_socket( struct sockaddr_storage *src, socklen_t src_len, struct sockaddr_storage *sa, socklen_t salen, @@ -510,7 +476,7 @@ static int make_recv_socket(struct sockaddr_storage *sa, socklen_t salen, memset(&mr4, 0, sizeof(mr4)); mr4.imr_multiaddr = sa4->sin_addr; mr4.imr_ifindex = req.ifr_ifindex; - get_ip(sa, addr, sizeof(addr), NULL); + get_ip(sa, addr, sizeof(addr), NULL, NULL); pw_log_info("join IPv4 group: %s iface:%d", addr, req.ifr_ifindex); res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4)); } else { @@ -523,7 +489,7 @@ static int make_recv_socket(struct sockaddr_storage *sa, socklen_t salen, memset(&mr6, 0, sizeof(mr6)); mr6.ipv6mr_multiaddr = sa6->sin6_addr; mr6.ipv6mr_interface = req.ifr_ifindex; - get_ip(sa, addr, sizeof(addr), NULL); + get_ip(sa, addr, sizeof(addr), NULL, NULL); pw_log_info("join IPv6 group: %s iface:%d", addr, req.ifr_ifindex); res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6)); } else { @@ -687,7 +653,7 @@ static int send_sap(struct impl *impl, struct session *sess, bool bye) iov[0].iov_base = &header; iov[0].iov_len = sizeof(header); - if ((res = get_ip(&impl->src_addr, src_addr, sizeof(src_addr), &src_ip4)) < 0) + if ((res = get_ip(&impl->src_addr, src_addr, sizeof(src_addr), &src_ip4, NULL)) < 0) return res; if (src_ip4) { @@ -701,7 +667,7 @@ static int send_sap(struct impl *impl, struct session *sess, bool bye) iov[2].iov_base = SAP_MIME_TYPE; iov[2].iov_len = sizeof(SAP_MIME_TYPE); - if ((res = get_ip(&sdp->dst_addr, dst_addr, sizeof(dst_addr), &dst_ip4)) < 0) + if ((res = get_ip(&sdp->dst_addr, dst_addr, sizeof(dst_addr), &dst_ip4, NULL)) < 0) return res; if ((user_name = pw_get_user_name()) == NULL) @@ -1141,7 +1107,7 @@ static struct session *session_new(struct impl *impl, struct sdp_info *info) pw_properties_set(props, PW_KEY_MEDIA_NAME, "RTP Stream"); } - get_ip(&info->dst_addr, dst_addr, sizeof(dst_addr), NULL); + get_ip(&info->dst_addr, dst_addr, sizeof(dst_addr), NULL, NULL); pw_properties_setf(props, "rtp.destination.ip", "%s", dst_addr); pw_properties_setf(props, "rtp.destination.port", "%u", info->dst_port); pw_properties_setf(props, "rtp.payload", "%u", info->payload); @@ -1511,7 +1477,7 @@ static int start_sap(struct impl *impl) if ((fd = make_recv_socket(&impl->sap_addr, impl->sap_len, impl->ifname)) < 0) return fd; - get_ip(&impl->sap_addr, addr, sizeof(addr), NULL); + get_ip(&impl->sap_addr, addr, sizeof(addr), NULL, NULL); pw_log_info("starting SAP listener on %s", addr); impl->sap_source = pw_loop_add_io(impl->loop, fd, SPA_IO_IN, true, on_sap_io, impl); diff --git a/src/modules/module-rtp-session.c b/src/modules/module-rtp-session.c index 36ccfe840..94dc7570e 100644 --- a/src/modules/module-rtp-session.c +++ b/src/modules/module-rtp-session.c @@ -37,6 +37,7 @@ #include #include #include +#include "network-utils.h" #ifdef __FreeBSD__ #define ifr_ifindex ifr_index @@ -603,26 +604,11 @@ static bool cmp_ip(const struct sockaddr_storage *sa, const struct sockaddr_stor } else if (sa->ss_family == AF_INET6 && sb->ss_family == AF_INET6) { struct sockaddr_in6 *ia = (struct sockaddr_in6*)sa; struct sockaddr_in6 *ib = (struct sockaddr_in6*)sb; - return ia->sin6_addr.s6_addr == ib->sin6_addr.s6_addr; + return ia->sin6_addr.s6_addr == ib->sin6_addr.s6_addr && ia->sin6_scope_id == ib->sin6_scope_id; } return false; } -static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, uint16_t *port) -{ - if (sa->ss_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in*)sa; - inet_ntop(sa->ss_family, &in->sin_addr, ip, len); - *port = ntohs(in->sin_port); - } else if (sa->ss_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; - inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); - *port = ntohs(in->sin6_port); - } else - return -EIO; - return 0; -} - static struct session *make_session(struct impl *impl, struct pw_properties *props) { struct session *sess; @@ -729,7 +715,7 @@ static void parse_apple_midi_cmd_in(struct impl *impl, bool ctrl, uint8_t *buffe initiator = ntohl(hdr->initiator); ssrc = ntohl(hdr->ssrc); - get_ip(sa, addr, sizeof(addr), &port); + get_ip(sa, addr, sizeof(addr), NULL, &port); pw_log_info("IN from %s:%d %s ssrc:%08x initiator:%08x", addr, port, hdr->name, ssrc, initiator); @@ -1269,26 +1255,6 @@ static const struct pw_core_events core_events = { .error = on_core_error, }; -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static void free_service(struct service *s) { spa_list_remove(&s->link); diff --git a/src/modules/module-rtp-sink.c b/src/modules/module-rtp-sink.c index 81a670542..0cedb4c58 100644 --- a/src/modules/module-rtp-sink.c +++ b/src/modules/module-rtp-sink.c @@ -26,6 +26,7 @@ #include #include +#include "network-utils.h" #ifndef IPTOS_DSCP #define IPTOS_DSCP_MASK 0xfc @@ -187,26 +188,6 @@ struct impl { int rtp_fd; }; -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static bool is_multicast(struct sockaddr *sa, socklen_t salen) { if (sa->sa_family == AF_INET) { @@ -404,19 +385,6 @@ static const struct rtp_stream_events stream_events = { .send_packet = stream_send_packet, }; -static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len) -{ - if (sa->ss_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in*)sa; - inet_ntop(sa->ss_family, &in->sin_addr, ip, len); - } else if (sa->ss_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; - inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); - } else - return -EIO; - return 0; -} - static void core_destroy(void *d) { struct impl *impl = d; @@ -589,9 +557,9 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) ts_offset = pw_rand32(); pw_properties_setf(stream_props, "rtp.sender-ts-offset", "%u", (uint32_t)ts_offset); - get_ip(&impl->src_addr, addr, sizeof(addr)); + get_ip(&impl->src_addr, addr, sizeof(addr), NULL, NULL); pw_properties_set(stream_props, "rtp.source.ip", addr); - get_ip(&impl->dst_addr, addr, sizeof(addr)); + get_ip(&impl->dst_addr, addr, sizeof(addr), NULL, NULL); pw_properties_set(stream_props, "rtp.destination.ip", addr); pw_properties_setf(stream_props, "rtp.destination.port", "%u", impl->dst_port); pw_properties_setf(stream_props, "rtp.ttl", "%u", impl->ttl); diff --git a/src/modules/module-rtp-source.c b/src/modules/module-rtp-source.c index f9703a9c7..41f2319d9 100644 --- a/src/modules/module-rtp-source.c +++ b/src/modules/module-rtp-source.c @@ -30,6 +30,7 @@ #include #include +#include "network-utils.h" #ifdef __FreeBSD__ #define ifr_ifindex ifr_index @@ -195,39 +196,6 @@ short_packet: return; } -static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len) -{ - if (sa->ss_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in*)sa; - inet_ntop(sa->ss_family, &in->sin_addr, ip, len); - } else if (sa->ss_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; - inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); - } else - return -EIO; - return 0; -} - -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname) { int af, fd, val, res; @@ -272,7 +240,7 @@ static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname) memset(&mr4, 0, sizeof(mr4)); mr4.imr_multiaddr = sa4->sin_addr; mr4.imr_ifindex = req.ifr_ifindex; - get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr)); + get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr), NULL, NULL); pw_log_info("join IPv4 group: %s", addr); res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4)); } else { @@ -289,7 +257,7 @@ static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname) memset(&mr6, 0, sizeof(mr6)); mr6.ipv6mr_multiaddr = sa6->sin6_addr; mr6.ipv6mr_interface = req.ifr_ifindex; - get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr)); + get_ip((struct sockaddr_storage*)sa, addr, sizeof(addr), NULL, NULL); pw_log_info("join IPv6 group: %s", addr); res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6)); } else { @@ -617,7 +585,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) pw_log_error("invalid source.ip %s: %s", str, spa_strerror(res)); goto out; } - get_ip(&impl->src_addr, addr, sizeof(addr)); + get_ip(&impl->src_addr, addr, sizeof(addr), NULL, NULL); pw_properties_set(stream_props, "rtp.source.ip", addr); pw_properties_setf(stream_props, "rtp.source.port", "%u", impl->src_port); diff --git a/src/modules/module-vban-recv.c b/src/modules/module-vban-recv.c index da8cfde9f..0cae43fb5 100644 --- a/src/modules/module-vban-recv.c +++ b/src/modules/module-vban-recv.c @@ -30,6 +30,7 @@ #include #include +#include "network-utils.h" #ifdef __FreeBSD__ #define ifr_ifindex ifr_index @@ -189,26 +190,6 @@ short_packet: return; } -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname) { int af, fd, val, res; diff --git a/src/modules/module-vban-send.c b/src/modules/module-vban-send.c index 896d82aaa..f004899e9 100644 --- a/src/modules/module-vban-send.c +++ b/src/modules/module-vban-send.c @@ -26,6 +26,7 @@ #include #include +#include "network-utils.h" #ifndef IPTOS_DSCP #define IPTOS_DSCP_MASK 0xfc @@ -218,26 +219,6 @@ static const struct vban_stream_events stream_events = { .send_packet = stream_send_packet, }; -static int parse_address(const char *address, uint16_t port, - struct sockaddr_storage *addr, socklen_t *len) -{ - struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; - - if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { - sa4->sin_family = AF_INET; - sa4->sin_port = htons(port); - *len = sizeof(*sa4); - } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(port); - *len = sizeof(*sa6); - } else - return -EINVAL; - - return 0; -} - static bool is_multicast(struct sockaddr *sa, socklen_t salen) { if (sa->sa_family == AF_INET) { @@ -299,19 +280,6 @@ error: return res; } -static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len) -{ - if (sa->ss_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in*)sa; - inet_ntop(sa->ss_family, &in->sin_addr, ip, len); - } else if (sa->ss_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; - inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); - } else - return -EIO; - return 0; -} - static void core_destroy(void *d) { struct impl *impl = d; @@ -477,9 +445,9 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) impl->mcast_loop = pw_properties_get_bool(props, "net.loop", DEFAULT_LOOP); impl->dscp = pw_properties_get_uint32(props, "net.dscp", DEFAULT_DSCP); - get_ip(&impl->src_addr, addr, sizeof(addr)); + get_ip(&impl->src_addr, addr, sizeof(addr), NULL, NULL); pw_properties_set(stream_props, "vban.source.ip", addr); - get_ip(&impl->dst_addr, addr, sizeof(addr)); + get_ip(&impl->dst_addr, addr, sizeof(addr), NULL, NULL); pw_properties_set(stream_props, "vban.destination.ip", addr); pw_properties_setf(stream_props, "vban.destination.port", "%u", impl->dst_port); pw_properties_setf(stream_props, "vban.ttl", "%u", impl->ttl); diff --git a/src/modules/network-utils.h b/src/modules/network-utils.h new file mode 100644 index 000000000..d16df3e34 --- /dev/null +++ b/src/modules/network-utils.h @@ -0,0 +1,81 @@ +#ifndef NETWORK_UTILS_H +#define NETWORK_UTILS_H + +#include +#include +#include +#include +#include +#include + +static int parse_address(const char *address, uint16_t port, + struct sockaddr_storage *addr, socklen_t *len) +{ + struct addrinfo hints; + struct addrinfo *result, *rp; + int res; + char port_str[6]; + + snprintf(port_str, sizeof(port_str), "%u", port); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + + res = getaddrinfo(address, port_str, &hints, &result); + + if (res != 0) { + return -EINVAL; + } + + for (rp = result; rp != NULL; rp = rp->ai_next) { + memcpy(addr, rp->ai_addr, rp->ai_addrlen); + *len = rp->ai_addrlen; + break; + } + freeaddrinfo(result); + + return 0; +} + +static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, bool *ip4, uint16_t *port) +{ + if (sa->ss_family == AF_INET) { + struct sockaddr_in *in = (struct sockaddr_in*)sa; + inet_ntop(sa->ss_family, &in->sin_addr, ip, len); + if (port) + *port = ntohs(in->sin_port); + } else if (sa->ss_family == AF_INET6) { + struct sockaddr_in6 *in = (struct sockaddr_in6*)sa; + inet_ntop(sa->ss_family, &in->sin6_addr, ip, len); + if (port) + *port = ntohs(in->sin6_port); + if (in->sin6_scope_id == 0 || len <= 1) { + goto finish; + } + size_t curlen = strlen(ip); + if (len-(curlen+1) >= IFNAMSIZ) { + ip += curlen+1; + ip[-1] = '%'; + if (if_indextoname(in->sin6_scope_id, ip) == NULL) { + ip[-1] = 0; + } + } + } else + return -EINVAL; +finish: + if (ip4) + *ip4 = sa->ss_family == AF_INET; + return 0; +} + +static inline char *get_ip_fmt(const struct sockaddr_storage *sa, char *ip, size_t len) +{ + if (get_ip(sa, ip, len, NULL, NULL) != 0) { + snprintf(ip, len, "invalid ip"); + } + return ip; +} + +#endif /* NETWORK_UTILS_H */