Skip to content

Instantly share code, notes, and snippets.

@pgassendi
Last active April 19, 2023 21:16
Show Gist options
  • Save pgassendi/d3e4fa66d513df3c88304316a788af27 to your computer and use it in GitHub Desktop.
Save pgassendi/d3e4fa66d513df3c88304316a788af27 to your computer and use it in GitHub Desktop.
get url info
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define case_return(ENUM_VALUE) case ENUM_VALUE: return #ENUM_VALUE;
const char* get_family(int f) {
switch(f) {
case_return(AF_INET);
case_return(AF_INET6);
case_return(AF_UNSPEC);
default: return "Neither ipv4 not ipv6 address family";
}
}
const char* get_socktype(int s) {
switch(s) {
case_return(SOCK_DGRAM);
case_return(SOCK_STREAM);
case_return(SOCK_RAW);
default: return "Neither raw nor dgram nor stream socket";
}
}
const char* get_proto(int p) {
switch(p) {
case_return(IPPROTO_IP);
case_return(IPPROTO_ICMP);
case_return(IPPROTO_TCP);
case_return(IPPROTO_UDP);
default: return "other proto";
}
}
static inline struct sockaddr_in* sa_ptr_to_in_ptr(struct sockaddr* sa) { return (struct sockaddr_in*)sa; }
static inline struct sockaddr_in6* sa_ptr_to_in6_ptr(struct sockaddr* sa) { return (struct sockaddr_in6*)sa; }
#define as_in4(SA) _Generic((SA), struct sockaddr*: sa_ptr_to_in_ptr)(SA)
#define as_in6(SA) _Generic((SA), struct sockaddr*: sa_ptr_to_in6_ptr)(SA)
#define sin_inet_ntop(SA, BUF, BUFSZ) inet_ntop(AF_INET, &(as_in4(SA)->sin_addr), BUF, BUFSZ)
#define sin6_inet_ntop(SA, BUF, BUFSZ) inet_ntop(AF_INET6, &(as_in6(SA)->sin6_addr), BUF, BUFSZ)
void print_sockaddr_row(struct sockaddr* sa, char* const sep) {
char buf[INET6_ADDRSTRLEN];
char const* addr = 0x0;
in_port_t port;
switch(sa->sa_family) {
case AF_INET: {
addr = sin_inet_ntop(sa, buf, sizeof(buf));
port = as_in4(sa)->sin_port;
break;
}
case AF_INET6: {
addr = sin6_inet_ntop(sa, buf, sizeof(buf));
port = as_in6(sa)->sin6_port;
break;
}
case AF_UNSPEC: { printf("AF_UNSPEC"); }
default: { fprintf(stderr, "unsupported sockaddr family"); return; }
}
if (addr) {
printf("%-40s%s%d", addr, sep, port);
} else {
fprintf(stderr, "inet_ntop error");
}
}
void print_addrinfo_row(const char* url, struct addrinfo* ai, char* const sep) {
printf("%s%s" "0x%x%s" "%-8s%s" "%s%s" "%s%s" "%d%s" "%s%s",
url, sep,
ai->ai_flags, sep,
get_family(ai->ai_family), sep,
get_socktype(ai->ai_socktype), sep,
get_proto(ai->ai_protocol), sep,
ai->ai_addrlen, sep,
ai->ai_canonname, sep
);
print_sockaddr_row(ai->ai_addr, sep);
puts("");
}
void print_addrinfo_header(char* const sep) {
printf("url\t%s" "flags%s" "familiy %s" "socktype%s" "protocol%s"
"addrlen%s" "cname%s" "address %s"
"port\n",
sep, sep, sep, sep ,sep ,sep ,sep, sep
);
}
int print_info(const char* url, char* const sep) {
struct addrinfo* result;
int error = getaddrinfo(url, NULL, NULL, &result);
if (error != 0) {
fprintf(stderr, "%s: error in getaddrinfo: %s\n", url, gai_strerror(error));
return EXIT_FAILURE;
}
for (struct addrinfo* res = result; res != NULL; res = res->ai_next) {
print_addrinfo_row(url, res, sep);
}
freeaddrinfo(result);
return EXIT_SUCCESS;
}
int main(int argc, char* argv[]) {
char* const sep = "\t";
print_addrinfo_header(sep);
for (int i = 1; i < argc; ++i) {
print_info(argv[i], sep);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment