From 5cf6e6b19d9aeaeaced5d1006d638418c729739b Mon Sep 17 00:00:00 2001 From: "T. von Dein" Date: Mon, 1 Dec 2025 17:09:54 +0100 Subject: [PATCH] move to codeberg (#11) - switch to meson+ninja - enhance documentaion --- .travis.yml | 24 ----- .woodpecker/build.yaml | 32 ++++++ .woodpecker/release.sh | 54 ++++++++++ .woodpecker/release.yaml | 31 ++++++ Makefile | 19 ++-- README.md | 226 ++++++++++++++++++++++++++++++++++----- appveyor.yml | 34 ------ meson.build | 89 +++++++++++++++ meson_options.txt | 1 + net.h | 48 +++++---- platform.h.in | 101 +++++++++++++++++ udpxd.1 | 44 +++++--- udpxd.h | 23 ++-- udpxd.pod | 2 +- 14 files changed, 587 insertions(+), 141 deletions(-) delete mode 100644 .travis.yml create mode 100644 .woodpecker/build.yaml create mode 100755 .woodpecker/release.sh create mode 100644 .woodpecker/release.yaml delete mode 100644 appveyor.yml create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100644 platform.h.in diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 52f79e2..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: c -os: - - linux -before_install: - - sudo apt-get update -qq - - sudo apt-get install dnsutils -compiler: - - clang - - gcc -script: - - make - - sudo make install - - sudo udpxd -l 127.0.0.1:53 -t 8.8.8.8:53 & - - dig +nocmd +noall +answer google.de a @127.0.0.1 - - sudo killall udpxd - -# -# ipv6 not supported anymore since Travis-ci moved to -# GCE: https://blog.travis-ci.com/2015-11-27-moving-to-a-more-elastic-future -# whatever this might have to do with "future".. However, Appveyor still -# supports it, so I suspect, disabling it here is probably ok. -# -# - dig +nocmd +noall +answer google.de a @::1 -# - sudo udpxd -l [::1]:53 -t [2001:4860:4860::8888]:53 & diff --git a/.woodpecker/build.yaml b/.woodpecker/build.yaml new file mode 100644 index 0000000..eb8a3e3 --- /dev/null +++ b/.woodpecker/build.yaml @@ -0,0 +1,32 @@ +matrix: + platform: + - linux/amd64 + +labels: + platform: ${platform} + +steps: + build: + when: + event: [push] + image: alpine:latest + commands: + - apk update + - apk add --no-cache bash build-base gdb pkgconfig meson ninja perl bind-tools + - meson setup --reconfigure build + - ninja -C build + + test: + when: + event: [push] + image: alpine:latest + commands: + - apk update + - apk add --no-cache bash bind-tools + - build/udpxd -l 127.0.0.1:53 -t 8.8.8.8:53 & + - dig +nocmd +noall +answer google.de a @127.0.0.1 + - killall udpxd + #- build/udpxd -l [::1]:53 -t [2001:4860:4860::8888]:53 & + #- dig +nocmd +noall +answer google.de a @::1 + #- killall udpxd + diff --git a/.woodpecker/release.sh b/.woodpecker/release.sh new file mode 100755 index 0000000..a44513a --- /dev/null +++ b/.woodpecker/release.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# This is my own simple codeberg generic releaser. It takes to +# binaries to be uploaded as arguments and takes every other args from +# env. Works on tags or normal commits (push), tags must start with v. + + +set -e + +die() { + echo $* + exit 1 +} + +if test -z "$DEPLOY_TOKEN"; then + die "token DEPLOY_TOKEN not set" +fi + +git fetch --all + +# determine current tag or commit hash +version="$CI_COMMIT_TAG" +previous="" +log="" +if test -z "$version"; then + version="${CI_COMMIT_SHA:0:6}" + log=$(git log -1 --oneline) +else + previous=$(git tag -l | grep -E "^v" | tac | grep -A1 "$version" | tail -1) + log=$(git log -1 --oneline "${previous}..${version}" | sed 's|^|- |g') +fi + +# release body +printf "# Changes\n\n %s\n" "$log" > body.txt + +# create the release +https --ignore-stdin --check-status -b -A bearer -a "$DEPLOY_TOKEN" POST \ + "https://codeberg.org/api/v1/repos/${CI_REPO_OWNER}/${CI_REPO_NAME}/releases" \ + tag_name="$version" name="Release $version" body=@body.txt > release.json + +# we need the id to upload files +ID=$(jq -r .id < release.json) + +if test -z "$ID"; then + cat release.json + die "failed to create release" +fi + +# actually upload +for file in "$@"; do + https --ignore-stdin --check-status -A bearer -a "$DEPLOY_TOKEN" -f POST \ + "https://codeberg.org/api/v1/repos/${CI_REPO_OWNER}/${CI_REPO_NAME}/releases/$ID/assets" \ + "name=${file}" "attachment@${file}" +done diff --git a/.woodpecker/release.yaml b/.woodpecker/release.yaml new file mode 100644 index 0000000..fca2a46 --- /dev/null +++ b/.woodpecker/release.yaml @@ -0,0 +1,31 @@ +# build release + +labels: + platform: linux/amd64 + +steps: + compile: + when: + event: [tag,manual] + image: alpine:latest + commands: + - apk update + - apk add --no-cache bash build-base gdb pkgconfig meson ninja perl git + - meson setup --reconfigure --prefer-static -Dc_link_args="-static -ldl" --buildtype=release build + - ninja -C build + - meson dist -C build --formats xztar,gztar,zip --allow-dirty + - file build/udpxd + - mv build/udpxd udpxd-linux-amd64-$CI_COMMIT_TAG + - mv build/meson-dist/* . + + release: + image: alpine:latest + when: + event: [tag,manual] + environment: + DEPLOY_TOKEN: + from_secret: DEPLOY_TOKEN + commands: + - apk update + - apk add --no-cache bash httpie jq git + - .woodpecker/release.sh udpxd-* diff --git a/Makefile b/Makefile index 9cd229f..dd45d7c 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,8 @@ # # You can contact me by mail: . +.PHONY: all clean man install deprecation + # warning: do not set -O to 2, see TODO CFLAGS = -Wall -Wextra -Werror -O1 -g LDFLAGS= @@ -28,22 +30,25 @@ UID = root GID = 0 MAN = udpxd.1 -all: $(DST) +all: deprecation $(DST) -$(DST): $(OBJS) +$(DST): deprecation $(OBJS) $(CC) $(OBJS) -o $(DST) -%.o: %.c +%.o: deprecation %.c $(CC) -c $(CFLAGS) $*.c -o $*.o -clean: - rm -f *.o $(DST) +clean: deprecation + rm -rf *.o $(DST) build .cache -man: +man: deprecation pod2man udpxd.pod > udpxd.1 -install: $(DST) +install: deprecation $(DST) install -d -o $(UID) -g $(GID) $(PREFIX)/sbin install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1 install -o $(UID) -g $(GID) -m 555 $(DST) $(PREFIX)/sbin/ install -o $(UID) -g $(GID) -m 444 $(MAN) $(PREFIX)/man/man1/ + +deprecation: + @echo "+++ DEPRECATION NOTE: Use meson & ninja to build please! +++" diff --git a/README.md b/README.md index 54483b0..6358e94 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,195 @@ -[![Build Status](https://travis-ci.org/TLINDEN/udpxd.svg?branch=master)](https://travis-ci.org/TLINDEN/udpxd) -[![Build status](https://ci.appveyor.com/api/projects/status/omvdru5ysa2swcd1?svg=true)](https://ci.appveyor.com/project/TLINDEN/udpxd) +[![status-badge](https://ci.codeberg.org/api/badges/15646/status.svg)](https://ci.codeberg.org/repos/15646) +[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://codeberg.org/scip/udpxd/raw/branch/main/LICENSE) + ## UDPXD - A general purpose UDP relay/port forwarder/proxy This is the README file for the network program udpxd. +## Introduction + +There are cases, when you need to change the source ip address of a +client, but can't do it in the kernel. Either because you don't have a +firewall running or because it doesn't work, or because there's no +firewall available. + +In such cases the usual aproach is to use a port forwarder. This is a +small piece of software, which opens a port on the inside, visible to +the client and establishes a new connection to the intended +destination, which is otherwise unreachable for the client. In fact, a +port forwarder implements hiding nat or masquerading in +userspace. Tools like this are also usefull for testing things, to +simulate requests when the tool you need to use for the test are +unable to set their source ip address (binding address). + +For TCP there are LOTs of solutions available, e.g. +[tcpxd](http://quozl.us.netrek.org/tcpxd/). Unfortunately there are +not so many solutions available if you want to do port forwarding with +UDP. One tool I found was +[udp-redirect](http://www.brokestream.com/udp_redirect.html). But it +is just a dirty hack and didn't work for me. Also it doesn't track +clients and is therefore not able to handle multiple clients +simultaneusly. + +So I decided to enhance it. The - current - result is `udpxd`, a +"general purpose UDP relay/port forwarder/proxy". It supports multiple +concurrent clients, it is able to bind to a specific source ip address +and it is small and simple. + udpxd can be used to forward or proxy UDP client traffic to another port on another system. It also supports binding to a specific ip address which will be used as the source for outgoing packets. It supports ip version 4 and 6. +## Quick Start + +How does it work: I'll explain it on a concrete example. On the server +where this website is running there are multiple ip addresses +configured on the outside interface, because I'm using jails to +separate services. One of those jail ip addresses is 78.47.130.33. Now +if I want to send a DNS query to the Hetzner nameserver 213.133.98.98 +from the root system (not inside the jail with the .33 ip address!), +then the packet will go out with the first interface address of the +system. Let's say I don't want that (either for testing or because the +remote end does only allow me to use the .33 address). In this +szenario I could use **udpxd** like this: + +```default +udpxd -l 172.16.0.3:53 -b 78.47.130.33 -t 213.133.98.98:53 +``` + +The ip address 172.16.0.3 is configured on the loopback interface +lo0. Now I can use dig to send a dns query to 172.16.0.3:53: + +```default +dig +nocmd +noall +answer google.de a @172.16.0.3 +google.de. 135 IN A 173.194.116.151 +google.de. 135 IN A 173.194.116.152 +google.de. 135 IN A 173.194.116.159 +google.de. 135 IN A 173.194.116.143 +``` + +When we look with tcpdump on our external interface, we see: + +```default +IP 78.47.130.33.24239 > 213.133.98.98.53: 4552+ A? google.de. (27) +IP 213.133.98.98.53 > 78.47.130.33.24239: 4552 4/0/0 A 173.194.116.152, + A 173.194.116.159, A 173.194.116.143, A 173.194.116.151 (91) +``` + +And this is how the same request looks on the loopback interface: + +```default +IP 172.16.0.3.24239 > 172.16.0.3.53: 4552+ A? google.de. (27) +IP 172.16.0.3.53 > 172.16.0.3.24239: 4552 4/0/0 A 173.194.116.152, + A 173.194.116.159, A 173.194.116.143, A 173.194.116.151 (91) +``` + +As you can see, dig sent the packet to 172.16.0.3:53, udpxd took it, +opened a new outgoing socket, bound to 78.47.130.33 and sent the +packet with that source ip address to the hetzner nameserver. It also +remembered which socket the particular client (source ip and source +port) has used. Then the response came back from hetzner, udpxd took +it, looked up its internal cache for the matching internal client and +sent it back to it with the source ip on the loopback interface. + +As I already said, udpxd is a general purpose udp port forwarder, so +you can use it with almost any udp protocol. Here's another example +using ntp: now I set up a tunnel between two systems, because udpxd +cannot bind to any interface with port 123 while ntpd is running (ntpd +binds to *.123). So on system A I have 3 udpxd's running: + +```default +udpxd -l 172.17.0.1:123 -b 78.47.130.33 -t 178.23.124.2:123 +udpxd -l 172.17.0.2:123 -b 78.47.130.33 -t 5.9.29.107:123 +udpxd -l 172.17.0.3:123 -b 78.47.130.33 -t 217.79.179.106:123 +``` + +Here I forward ntp queries on 172.16.0.1-3:123 to the real ntp pool +servers and I'm using the .33 source ip to bind for outgoing packets +again. On the other system B, which is able to reach 172.17.0.0/24 via +the tunnel, I reconfigured the ntpd like so: + +```default +server 172.17.0.1 iburst dynamic +server 172.17.0.2 iburst dynamic +server 172.17.0.3 iburst dynamic +``` + +After restarting, let's look how it works: + +```default +ntpq> peers + remote refid st t when poll reach delay offset jitter +============================================================================== +*172.17.0.1 131.188.3.221 2 u 12 64 1 18.999 2.296 1.395 + 172.17.0.2 192.53.103.104 2 u 11 64 1 0.710 1.979 0.136 + 172.17.0.3 130.149.17.8 2 u 10 64 1 12.073 5.836 0.089 +``` + +Seems to work :), here's what we see in the tunnel interface: + +```default +14:13:32.534832 IP 10.10.10.1.123 > 172.17.0.1.123: NTPv4, Client, length 48 +14:13:32.556627 IP 172.17.0.1.123 > 10.10.10.1.123: NTPv4, Server, length 48 +14:13:33.535081 IP 10.10.10.1.123 > 172.17.0.2.123: NTPv4, Client, length 48 +14:13:33.535530 IP 172.17.0.2.123 > 10.10.10.1.123: NTPv4, Server, length 48 +14:13:34.535166 IP 10.10.10.1.123 > 172.17.0.1.123: NTPv4, Client, length 48 +14:13:34.535278 IP 10.10.10.1.123 > 172.17.0.3.123: NTPv4, Client, length 48 +14:13:34.544585 IP 172.17.0.3.123 > 10.10.10.1.123: NTPv4, Server, length 48 +14:13:34.556956 IP 172.17.0.1.123 > 10.10.10.1.123: NTPv4, Server, length 48 +14:13:35.535308 IP 10.10.10.1.123 > 172.17.0.2.123: NTPv4, Client, length 48 +14:13:35.535742 IP 172.17.0.2.123 > 10.10.10.1.123: NTPv4, Server, length 48 +14:13:36.535363 IP 10.10.10.1.123 > 172.17.0.1.123: NTPv4, Client, length 48 +``` + +And the forwarded traffic on the public interface: + +```default +14:13:32.534944 IP 78.47.130.33.63956 > 178.23.124.2.123: NTPv4, Client, length 48 +14:13:32.556586 IP 178.23.124.2.123 > 78.47.130.33.63956: NTPv4, Server, length 48 +14:13:33.535188 IP 78.47.130.33.48131 > 5.9.29.107.123: NTPv4, Client, length 48 +14:13:33.535500 IP 5.9.29.107.123 > 78.47.130.33.48131: NTPv4, Server, length 48 +14:13:34.535255 IP 78.47.130.33.56807 > 178.23.124.2.123: NTPv4, Client, length 48 +14:13:34.535337 IP 78.47.130.33.56554 > 217.79.179.106.123: NTPv4, Client, length 48 +14:13:34.544543 IP 217.79.179.106.123 > 78.47.130.33.56554: NTPv4, Server, length 48 +14:13:34.556932 IP 178.23.124.2.123 > 78.47.130.33.56807: NTPv4, Server, length 48 +14:13:35.535379 IP 78.47.130.33.22968 > 5.9.29.107.123: NTPv4, Client, length 48 +14:13:35.535717 IP 5.9.29.107.123 > 78.47.130.33.22968: NTPv4, Server, length 48 +14:13:36.535442 IP 78.47.130.33.24583 > 178.23.124.2.123: NTPv4, Client, length 48 +``` + +You see, the ntp server gets the time via the tunnel via udpxd which +in turn forwards it to real ntp servers. + +Note, if you left the parameter -b out, then the first ip address of +the outgoing interface will be used. + +Udpxd can also proxy ipv6 udp traffic and forward between protocols +(v4 to v6 and vice versa). For instance listen on ipv6 loopback and +forward to ipv6 google: + +```default +udpxd -l [::1]:53 -t [2001:4860:4860::8888]:53 +``` + +Listen on ipv6 loopback and forward to ipv4 google: + +```default +udpxd -l [::1]:53 -t 8.8.8.8:53 +``` + +Or listen on ipv4 loopback and forward to ipv6 google: + +```default +udpxd -l 127.0.0.1:53 -t [2001:4860:4860::8888]:53 +``` + +Of course it is possble to set the bind ip address (-b) using ipv6 as +well. + + + ## Documentation You can read the documentation without installing the @@ -21,40 +201,38 @@ If it is already installed, you can read the manual page: man udpxd -## Installation +## Installation using pre-built binaries + +You can download a statically pre-compiled binary for linux from the [release page](releases). + +## Installation from source This software doesn't have any external dependencies, but -you need either BSD make or GNU make installed to build it. +you will need `meson` and `ninja`: https://mesonbuild.com/. -First you need to check out the source code. Skip this, if -you have already done so: +Check out the source and execute: - git clone git@github.com:TLINDEN/udpxd.git +```default +meson setup build +ninja -C build +``` -Next, change into the newly created directory 'udpxd' and -compile the source code: +You can supply some additional parameters to meson, +type `meson configuration` for details. - cd udpxd - make +To install, execute: -To install, type this command: +```default +sudo ninja -C install +``` - sudo make install - -This will install the binary to `$PREFIX/sbin/udpxd` and -the manual page to `$PREFIX/man/man1/udpxd.1`. You can -modify `$PREFIX` during installation time like this: - - make install PREFIX=/opt - -## Getting help + ## Getting help Although I'm happy to hear from udpxd users in private email, that's the best way for me to forget to do something. In order to report a bug, unexpected behavior, feature requests -or to submit a patch, please open an issue on github: -https://github.com/TLINDEN/udpxd/issues. +or to submit a patch, [please open an issue](https://codeberg.org/scip/udpxd/issues). ## Copyright and license @@ -66,4 +244,4 @@ T.v.Dein ## Project homepage -https://github.com/TLINDEN/udpxd +https://codeberg.org/scip/udpxd diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 1eb9cb0..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,34 +0,0 @@ -environment: - global: - CYG_ROOT: C:\cygwin - CYG_BASH: C:\cygwin\bin\bash - CYG_MIRROR: http://cygwin.mirror.constant.com - CYG_CACHE: C:\cygwin\var\cache\setup - -os: unstable - -cache: - - '%CYG_CACHE%' - -platform: - - Win32 - -test: off - -init: - - git config --global core.autocrlf input - -install: - - ps: 'Start-FileDownload "http://cygwin.com/setup-x86.exe" -FileName "setup-x86.exe"' - - cmd: 'setup-x86.exe --quiet-mode --no-shortcuts --only-site --root "%CYG_ROOT%" --site "%CYG_MIRROR%" --local-package-dir "%CYG_CACHE%" --packages bind,netcat > NUL 2>&1' - - cmd: '%CYG_BASH% -lc "cygcheck -dc cygwin"' - -build_script: - - cmd: '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0=1.3', + default_options: [ + 'warning_level=2', + 'werror=true', + ], +) + +add_project_arguments( + [ + '-Wno-unused-parameter', + '-Wno-unused-result', + '-Wno-missing-braces', + '-Wno-format-zero-length', + '-Wvla', + '-Wno-sign-compare', + '-Wno-narrowing', + '-Wno-stringop-truncation' + ], + language: 'c', +) + + +c = meson.get_compiler('c') +conf = configuration_data() + + +# check for funcs. +foreach func : ['getopt', 'malloc', 'fprintf', 'strncpy', 'strlen', 'strtok', 'strchr', 'signal', + 'select', 'free', 'perror', 'getsockname', 'setegid', 'seteuid', 'syslog', + 'va_start', 'va_end', 'inet_ntop', 'getifaddrs', 'getnameinfo', 'ntohs', 'memcpy', 'memset', 'sprintf' ] + conf.set('HAVE_'+func.to_upper(), c.has_function(func, prefix : '#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n')) +endforeach + + +# check commandline options +prefix = get_option('prefix') + +if get_option('buildtype') == 'debug' + conf.set('DEBUG', '1') +endif + + + +# setup conf map +version = '@0@'.format(meson.project_version()) +conf.set('prefix', prefix) +conf.set('VERSION', version) + + +# write out the config header +m = configure_file( + input : 'platform.h.in', + output : 'platform.h', + configuration : conf, +) + + +# code +udpxd_sources = files( + 'client.c', + 'host.c', + 'log.c', + 'net.c', + 'udpxd.c' +) + + + +executable( + 'udpxd', + [udpxd_sources], + install: true +) + +# build manual page +pod2man = find_program('pod2man', native: true) +if pod2man.found() + res = run_command(pod2man.full_path(), 'udpxd.pod', 'udpxd.1', check:true) + if res.returncode() == 0 + install_man('udpxd.1') + endif +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..e62869c --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +# custom build options diff --git a/net.h b/net.h index 6a7d615..978e4ad 100644 --- a/net.h +++ b/net.h @@ -22,25 +22,24 @@ #ifndef _HAVE_NET_H #define _HAVE_NET_H -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include +#include +#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include - +#include +#include +#include +#include #include "client.h" @@ -50,23 +49,26 @@ extern client_t *clients; extern int VERBOSE; extern int FORKED; - - void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h); void handle_outside(int inside, int outside, host_t *outside_h); -int main_loop(int listensocket, host_t *listen_h, host_t *bind_h, host_t *dst_h); -int start_listener (char *inip, char *inpt, char *srcip, char *srcpt, char *dstip, - char *dstpt, char *pidfile, char *chrootdir, char *user); +int main_loop(int listensocket, host_t *listen_h, host_t *bind_h, + host_t *dst_h); +int start_listener(char *inip, char *inpt, char *srcip, char *srcpt, + char *dstip, char *dstpt, char *pidfile, char *chrootdir, + char *user); int daemonize(char *pidfile); int drop_privileges(char *user, char *chrootdir); int fill_set(fd_set *fds); int get_sender(fd_set *fds); -int bindsocket( host_t *sock_h); -void int_handler(int sig); -void verb_prbind (host_t *bind_h); +int bindsocket(host_t *sock_h); +void int_handler(int sig); +void verb_prbind(host_t *bind_h); -#define _IS_LINK_LOCAL(a) do { IN6_IS_ADDR_LINKLOCAL(a); } while(0) +#define _IS_LINK_LOCAL(a) \ + do { \ + IN6_IS_ADDR_LINKLOCAL(a); \ + } while (0) #endif diff --git a/platform.h.in b/platform.h.in new file mode 100644 index 0000000..a2b742f --- /dev/null +++ b/platform.h.in @@ -0,0 +1,101 @@ +/* platform.h.in. Generated from configure.ac by autoheader. */ + +#define PACKAGE "udpxd" +#define UDPXD_VERSION "@VERSION@" + +#mesondefine HAVE_GETOPT +#ifndef HAVE_GETOPT +error "HAVE_GETOPT not defined" +#endif +#mesondefine HAVE_MALLOC +#ifndef HAVE_MALLOC + error "HAVE_MALLOC not defined" +#endif +#mesondefine HAVE_FPRINTF +#ifndef HAVE_FPRINTF + error "HAVE_FPRINTF not defined" +#endif +#mesondefine HAVE_STRNCPY +#ifndef HAVE_STRNCPY + error "HAVE_STRNCPY not defined" +#endif +#mesondefine HAVE_STRLEN +#ifndef HAVE_STRLEN + error "HAVE_STRLEN not defined" +#endif +#mesondefine HAVE_STRTOK +#ifndef HAVE_STRTOK + error "HAVE_STRTOK not defined" +#endif +#mesondefine HAVE_STRCHR +#ifndef HAVE_STRCHR + error "HAVE_STRCHR not defined" +#endif +#mesondefine HAVE_SIGNAL +#ifndef HAVE_SIGNAL + error "HAVE_SIGNAL not defined" +#endif +#mesondefine HAVE_SELECT +#ifndef HAVE_SELECT + error "HAVE_SELECT not defined" +#endif +#mesondefine HAVE_FREE +#ifndef HAVE_FREE + error "HAVE_FREE not defined" +#endif +#mesondefine HAVE_PERROR +#ifndef HAVE_PERROR + error "HAVE_PERROR not defined" +#endif +#mesondefine HAVE_GETSOCKNAME +#ifndef HAVE_GETSOCKNAME + error "HAVE_GETSOCKNAME not defined" +#endif +#mesondefine HAVE_SETEGID +#ifndef HAVE_SETEGID + error "HAVE_SETEGID not defined" +#endif +#mesondefine HAVE_SETEUID +#ifndef HAVE_SETEUID + error "HAVE_SETEUID not defined" +#endif +#mesondefine HAVE_SYSLOG +#ifndef HAVE_SYSLOG + error "HAVE_SYSLOG not defined" +#endif +#mesondefine HAVE_VA_START +#ifndef HAVE_VA_START + error "HAVE_VA_START not defined" +#endif +#mesondefine HAVE_VA_END +#ifndef HAVE_VA_END + error "HAVE_VA_END not defined" +#endif +#mesondefine HAVE_INET_NTOP +#ifndef HAVE_INET_NTOP + error "HAVE_INET_NTOP not defined" +#endif +#mesondefine HAVE_GETIFADDRS +#ifndef HAVE_GETIFADDRS + error "HAVE_GETIFADDRS not defined" +#endif +#mesondefine HAVE_GETNAMEINFO +#ifndef HAVE_GETNAMEINFO + error "HAVE_GETNAMEINFO not defined" +#endif +#mesondefine HAVE_NTOHS +#ifndef HAVE_NTOHS + error "HAVE_NTOHS not defined" +#endif +#mesondefine HAVE_MEMCPY +#ifndef HAVE_MEMCPY + error "HAVE_MEMCPY not defined" +#endif +#mesondefine HAVE_MEMSET +#ifndef HAVE_MEMSET + error "HAVE_MEMSET not defined" +#endif +#mesondefine HAVE_SPRINTF +#ifndef HAVE_SPRINTF + error "HAVE_SPRINTF not defined" +#endif diff --git a/udpxd.1 b/udpxd.1 index c3b5be4..563fad8 100644 --- a/udpxd.1 +++ b/udpxd.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== @@ -38,27 +38,36 @@ . ds PI \(*p . ds L" `` . ds R" '' +. ds C` +. ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX .. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} .\} +.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -124,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "UDPXD 1" -.TH UDPXD 1 "2015-2016-04-27" "perl v5.14.2" "User Contributed Perl Documentation" +.TH UDPXD 1 "2025-12-01" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -138,7 +147,8 @@ udpxd \- A general purpose UDP relay/port forwarder/proxy \& \& Options: \& \-\-listen \-l listen for incoming requests -\& \-\-bind \-b bind ip used for outgoing requests +\& \-\-bind \-b bind ip used for outgoing requests +\& specify port for promiscuous mode \& \-\-to \-t destination to forward requests to \& \-\-daemon \-d daemon mode, fork into background \& \-\-pidfile \-p pidfile, default: /var/run/udpxd.pid @@ -178,7 +188,9 @@ the background and becomes a daemon. It writes it pidfile to \&\f(CW\*(C`/var/run/udpxd.pid\*(C'\fR, which can be changed with the \fB\-p\fR option. If started as root, it also drops privileges to the user \f(CW\*(C`nobody\*(C'\fR or the user specified with \fB\-u\fR and chroots -to \f(CW\*(C`/var/empty\*(C'\fR or the directory specified with \fB\-c\fR. +to \f(CW\*(C`/var/empty\*(C'\fR or the directory specified with \fB\-c\fR. udpxd +will log to syslog facility user.info if \fB\-v\fR is specified and +if running in daemon mode. .PP \&\fBCaution: if not running in daemon mode, udpxd does not drop its privileges and will continue to run as root (if started as @@ -275,12 +287,12 @@ address: .IX Header "BUGS" In order to report a bug, unexpected behavior, feature requests or to submit a patch, please open an issue on github: -. +. .SH "LICENSE" .IX Header "LICENSE" -This software is licensed under the \s-1GNU\s0 \s-1GENERAL\s0 \s-1PUBLIC\s0 \s-1LICENSE\s0 version 3. +This software is licensed under the \s-1GNU GENERAL PUBLIC LICENSE\s0 version 3. .PP -Copyright (c) 2015-2016 by T. v. Dein. +Copyright (c) 2015\-2017 by T. v. Dein. .PP This software uses \fButhash\fR (bundled), which is Copyright (c) 2003\-2013 by Troy D. Hanson. diff --git a/udpxd.h b/udpxd.h index bac015d..6a14360 100644 --- a/udpxd.h +++ b/udpxd.h @@ -22,22 +22,21 @@ #ifndef _HAVE_UDPXD_H #define _HAVE_UDPXD_H -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include -#include -#include -#include -#include #include +#include +#include +#include +#include -#define UDPXD_VERSION "0.0.4" - +#include "platform.h" void usage(); int parse_ip(char *src, char *ip, char *pt); diff --git a/udpxd.pod b/udpxd.pod index 6e68c04..25c7f82 100644 --- a/udpxd.pod +++ b/udpxd.pod @@ -135,7 +135,7 @@ B: created if running in daemon mode (B<-d>). In order to report a bug, unexpected behavior, feature requests or to submit a patch, please open an issue on github: -L. +L. =head1 LICENSE