From 64fa1f9491af93403c46121732928608deb0b8ba Mon Sep 17 00:00:00 2001 From: Calvin Owens Date: Mon, 3 Feb 2025 23:15:15 -0800 Subject: [PATCH] Portability fixes Seven fixes for minor issues which show up on BSD and linux+musl: 1) Add missing "#include " in a header file. 2) Add two missing casts for struct sockaddr. 3) Work around missing dlinfo() on OpenBSD by saving the module paths at open time instead of looking them up later with RTLD_DI_ORIGIN. This also fixes musl. The names are only cosmetic, so if they are subtly different it doesn't matter. 4) Omit the -lrt and -ldl flags on OpenBSD. 5) Use printf macros and portable udp field names in netconsblaster. 6) Unfortunately, (5) isn't enough: the runtime semantics of SOCK_RAW are completely different on *BSD, and nothing works. For now, just emit a compile error in netconsblaster for the !linux case. But keep (5) since it's a nice cleanup. 7) Drop -static-libgcc and -static-libstdc++ from the LDFLAGS in the modules, since they cause errors on musl and don't seem to be necessary on any platform. Also, don't pass LDFLAGS to the compile call, since it causes clang to emit warnings. --- Makefile | 7 ++++++- README.md | 6 +++--- include/listener.h | 1 + listener.c | 2 +- modules/Makefile | 6 +++--- output.c | 8 +++++--- util/netconsblaster.c | 26 +++++++++++++++++--------- 7 files changed, 36 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 6909321..50a45f3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC ?= gcc -LIBS = -lpthread -lrt -ldl +LIBS = -lpthread CFLAGS ?= -O2 -fPIC CFLAGS += -D_GNU_SOURCE -fno-strict-aliasing -Wall -Wextra \ -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \ @@ -9,6 +9,11 @@ CFLAGS += -D_GNU_SOURCE -fno-strict-aliasing -Wall -Wextra \ CPPFLAGS ?= INCLUDES = -Incrx +UNAME := $(shell uname) +ifneq ($(UNAME), OpenBSD) +LIBS += -lrt -ldl +endif + debug debug32: CFLAGS += -O0 -gdwarf-4 -fno-omit-frame-pointer \ -fstack-protector-all -fsanitize=address \ -fsanitize=undefined diff --git a/README.md b/README.md index a2ec1db..15d2808 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ own custom output module. ## Building netconsd The default Makefile target intended for production use has no external -dependencies besides glibc. To build it, just say `make`: you'll end up with a -single executable in this directory called `netconsd`, and a `*.so` file for every -module in the `modules/` directory. +dependencies besides glibc. To build it, just say `make` (or `gmake` on BSD): +you'll end up with a single executable in this directory called `netconsd`, and +a `*.so` file for every module in the `modules/` directory. The Makefile includes a few other handy targets: diff --git a/include/listener.h b/include/listener.h index 832f84b..1b7841b 100644 --- a/include/listener.h +++ b/include/listener.h @@ -9,6 +9,7 @@ #define __LISTENER_H__ #include "threads.h" +#include #define RCVBUF_SIZE 1024 diff --git a/listener.c b/listener.c index 4101b69..6c10aeb 100644 --- a/listener.c +++ b/listener.c @@ -124,7 +124,7 @@ static int get_listen_socket(struct sockaddr_in6 *bindaddr) if (ret == -1) fatal("Couldn't set SO_REUSEPORT on socket: %m\n"); - ret = bind(fd, bindaddr, sizeof(*bindaddr)); + ret = bind(fd, (const struct sockaddr *)bindaddr, sizeof(*bindaddr)); if (ret == -1) fatal("Couldn't bind: %m\n"); diff --git a/modules/Makefile b/modules/Makefile index f7c66f1..a981202 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -5,7 +5,7 @@ LDFLAGS ?= override CFLAGS += -fPIC override CXXFLAGS += -std=c++11 -fPIC -override LDFLAGS += -shared -static-libstdc++ -static-libgcc +override LDFLAGS += -shared INCLUDES = -I../ncrx -I../include mods = printer.so logger.so @@ -13,11 +13,11 @@ mods = printer.so logger.so all: $(mods) %.so: %.c - $(CC) $< $(CPPFLAGS) $(CFLAGS) $(INCLUDES) $(LDFLAGS) -c -o $(<:.c=.o) + $(CC) $< $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -c -o $(<:.c=.o) $(CC) $(<:.c=.o) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ %.so: %.cc - $(CXX) $< $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) $(LDFLAGS) -c -o $(<:.cc=.o) + $(CXX) $< $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c -o $(<:.cc=.o) $(CXX) $(<:.cc=.o) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ clean: diff --git a/output.c b/output.c index 64d67d9..05ead68 100644 --- a/output.c +++ b/output.c @@ -18,6 +18,7 @@ #include "include/output.h" static void *output_dlhandles[MAXOUTS]; +static const char *output_dlpaths[MAXOUTS]; static void (*outputs[MAXOUTS])(int, struct in6_addr *, struct msg_buf *, struct ncrx_msg *); static int nr_outputs; @@ -59,6 +60,7 @@ int register_output_module(char *path, int nr_workers) log("Module '%s' registered (#%d@%p)\n", path, nr_outputs, dlsym_addr); output_dlhandles[nr_outputs] = dl; + output_dlpaths[nr_outputs] = strdup(path); outputs[nr_outputs] = dlsym_addr; nr_outputs++; return 0; @@ -72,11 +74,9 @@ void destroy_output_modules(void) { int i, ret; void (*mod_exit)(void); - char path[PATH_MAX] = {0}; for (i = 0; i < nr_outputs; i++) { - if (dlinfo(output_dlhandles[i], RTLD_DI_ORIGIN, path)) - strncpy(path, dlerror(), PATH_MAX - 1); + const char *path = output_dlpaths[i]; mod_exit = dlsym(output_dlhandles[i], "netconsd_output_exit"); if (mod_exit) { @@ -88,6 +88,8 @@ void destroy_output_modules(void) ret = dlclose(output_dlhandles[i]); if (ret) warn("dlclose() failed: %s\n", dlerror()); + + free((void *)path); } } diff --git a/util/netconsblaster.c b/util/netconsblaster.c index faa2a33..89c7cdc 100644 --- a/util/netconsblaster.c +++ b/util/netconsblaster.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -21,6 +24,10 @@ #include #include +#ifndef __linux__ +#error Sorry, SOCK_RAW is not portable +#endif + #define fatal(...) \ do { \ printf(__VA_ARGS__); \ @@ -183,17 +190,17 @@ static void make_packet(struct netcons_packet *pkt, const struct in6_addr *src, pkt->l3.ip6_plen = htons(sizeof(pkt->l4) + len); pkt->l3.ip6_hlim = 64; - nr = snprintf(pkt->payload, len - 1, "%d,%lu,%lu,%s;", md->lvl, md->seq, - md->ts, contflag(md->cont)); + nr = snprintf(pkt->payload, len - 1, "%d,%" PRIu64 ",%" PRIu64 ",%s;", + md->lvl, md->seq, md->ts, contflag(md->cont)); if (nr < len) snprintf(pkt->payload + nr, len - nr, "%s", filler); pkt->payload[len - 1] = '\n'; - pkt->l4.source = htons(6666); - pkt->l4.dest = htons(*dst_port); - pkt->l4.len = htons(sizeof(pkt->l4) + len); - pkt->l4.check = htons(udp_csum(&pkt->l3.ip6_src, &pkt->l4, - sizeof(pkt->l4) + len)); + pkt->l4.uh_sport = htons(6666); + pkt->l4.uh_dport = htons(*dst_port); + pkt->l4.uh_ulen = htons(sizeof(pkt->l4) + len); + pkt->l4.uh_sum = htons(udp_csum(&pkt->l3.ip6_src, &pkt->l4, + sizeof(pkt->l4) + len)); } static int write_packet(int sockfd, struct netcons_packet *pkt) @@ -204,7 +211,8 @@ static int write_packet(int sockfd, struct netcons_packet *pkt) }; memcpy(&bogus.sin6_addr, &pkt->l3.ip6_dst, sizeof(pkt->l3.ip6_dst)); - return sendto(sockfd, pkt, len, 0, &bogus, sizeof(bogus)) != len; + return sendto(sockfd, pkt, len, 0, (const struct sockaddr *)&bogus, + sizeof(bogus)) != len; } static int get_raw_socket(void) @@ -457,7 +465,7 @@ int main(int argc, char **argv) } finish = now_epoch_ms(); - printf("Wrote %lu packets (%lu pkts/sec)\n", count, + printf("Wrote %" PRIu64 " packets (%" PRIu64 " pkts/sec)\n", count, count / (finish - start) * 1000UL); return 0; }