Mercurial > libjeffpc
changeset 871:de55ae9a8839
sock: add sockaddr_{ntop,cmp,copy} helpers and a sockaddr_union
For now, it only supports AF_INET and AF_INET6. That should be enough for
most things, but it is likely only a matter of time before AF_UNIX crops up.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Wed, 14 Feb 2024 09:54:10 -0500 |
parents | 7ecf3aed80fc |
children | a3965185623f |
files | include/jeffpc/sock.h mapfile-vers sock.c |
diffstat | 3 files changed, 92 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/include/jeffpc/sock.h Wed Jan 31 23:41:07 2024 -0500 +++ b/include/jeffpc/sock.h Wed Feb 14 09:54:10 2024 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2016-2019,2024 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,13 +25,33 @@ #include <stdbool.h> #include <stdint.h> +#include <sys/socket.h> +#include <netinet/in.h> #include <jeffpc/error.h> +/* a union of all the different socket address structs */ +union xsockaddr { + struct sockaddr sa; + struct sockaddr_in inet; + struct sockaddr_in6 inet6; +}; + +/* max length (with trailing nul) generated by xsockaddr_ntop */ +#define XSOCKADDR_STRLEN (MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1) + enum ip_type { IP_TCP, }; +/* + * socket address helpers + */ +extern const char *xsockaddr_ntop(const struct sockaddr *sa, char *str, + size_t strlen); +extern bool xsockaddr_cmp(struct sockaddr *sa1, struct sockaddr *sa2); +extern void xsockaddr_copy(union xsockaddr *u, struct sockaddr *sa); + extern int connect_ip(const char *host, uint16_t port, bool v4, bool v6, enum ip_type type);
--- a/mapfile-vers Wed Jan 31 23:41:07 2024 -0500 +++ b/mapfile-vers Wed Feb 14 09:54:10 2024 -0500 @@ -255,6 +255,9 @@ # sock connect_ip; xgethostname; + xsockaddr_cmp; + xsockaddr_copy; + xsockaddr_ntop; # socksvc socksvc;
--- a/sock.c Wed Jan 31 23:41:07 2024 -0500 +++ b/sock.c Wed Feb 14 09:54:10 2024 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2016-2020,2024 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,7 @@ #include <sys/socket.h> #include <netdb.h> #include <unistd.h> +#include <arpa/inet.h> #include <jeffpc/sock.h> #include <jeffpc/atomic.h> @@ -152,3 +153,69 @@ return sock; } + +const char *xsockaddr_ntop(const struct sockaddr *sa, char *str, size_t strlen) +{ + const union xsockaddr *u = (const union xsockaddr *) sa; + + switch (u->sa.sa_family) { + case AF_INET: + return inet_ntop(AF_INET, &u->inet.sin_addr, str, + strlen); + case AF_INET6: + return inet_ntop(AF_INET6, &u->inet6.sin6_addr, str, + strlen); + } + + panic("Unknown address family %d", u->sa.sa_family); +} + +bool xsockaddr_cmp(struct sockaddr *sa1, struct sockaddr *sa2) +{ + if (sa1->sa_family != sa2->sa_family) + return false; + + /* + * NOTE: Some systems (e.g., FreeBSD) have sa_len which we could + * sanity check, but other systems (e.g., Linux) do not have it. We + * could work around this with conditional compilation, but that's + * too much effort with no obvious benefit. So, just imagine that + * we assert here that sa1->sa_len == sa2->sa_len. + */ + + switch (sa1->sa_family) { + case AF_INET: { + struct sockaddr_in *in1 = (struct sockaddr_in *) sa1; + struct sockaddr_in *in2 = (struct sockaddr_in *) sa2; + + return in1->sin_addr.s_addr == in2->sin_addr.s_addr; + } + case AF_INET6: { + struct sockaddr_in6 *in1 = (struct sockaddr_in6 *) sa1; + struct sockaddr_in6 *in2 = (struct sockaddr_in6 *) sa2; + + return IN6_ARE_ADDR_EQUAL(&in1->sin6_addr, + &in2->sin6_addr); + } + } + + panic("Unknown address family %d", sa1->sa_family); +} + +void xsockaddr_copy(union xsockaddr *u, struct sockaddr *sa) +{ + size_t len; + + switch (sa->sa_family) { + case AF_INET: + len = sizeof(u->inet); + break; + case AF_INET6: + len = sizeof(u->inet6); + break; + default: + panic("Unknown address family %d", sa->sa_family); + } + + memcpy(u, sa, len); +}