move to codeberg (#11)

- switch to meson+ninja
- enhance documentaion
This commit is contained in:
T. von Dein
2025-12-01 17:09:54 +01:00
parent d5b6de3aa4
commit 5cf6e6b19d
14 changed files with 587 additions and 141 deletions

View File

@@ -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 &

32
.woodpecker/build.yaml Normal file
View File

@@ -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

54
.woodpecker/release.sh Executable file
View File

@@ -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

31
.woodpecker/release.yaml Normal file
View File

@@ -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-*

View File

@@ -18,6 +18,8 @@
#
# You can contact me by mail: <tom AT vondein DOT org>.
.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! +++"

226
README.md
View File

@@ -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 &gt; 213.133.98.98.53: 4552+ A? google.de. (27)
IP 213.133.98.98.53 &gt; 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 &gt; 172.16.0.3.53: 4552+ A? google.de. (27)
IP 172.16.0.3.53 &gt; 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 &gt; 172.17.0.1.123: NTPv4, Client, length 48
14:13:32.556627 IP 172.17.0.1.123 &gt; 10.10.10.1.123: NTPv4, Server, length 48
14:13:33.535081 IP 10.10.10.1.123 &gt; 172.17.0.2.123: NTPv4, Client, length 48
14:13:33.535530 IP 172.17.0.2.123 &gt; 10.10.10.1.123: NTPv4, Server, length 48
14:13:34.535166 IP 10.10.10.1.123 &gt; 172.17.0.1.123: NTPv4, Client, length 48
14:13:34.535278 IP 10.10.10.1.123 &gt; 172.17.0.3.123: NTPv4, Client, length 48
14:13:34.544585 IP 172.17.0.3.123 &gt; 10.10.10.1.123: NTPv4, Server, length 48
14:13:34.556956 IP 172.17.0.1.123 &gt; 10.10.10.1.123: NTPv4, Server, length 48
14:13:35.535308 IP 10.10.10.1.123 &gt; 172.17.0.2.123: NTPv4, Client, length 48
14:13:35.535742 IP 172.17.0.2.123 &gt; 10.10.10.1.123: NTPv4, Server, length 48
14:13:36.535363 IP 10.10.10.1.123 &gt; 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 &gt; 178.23.124.2.123: NTPv4, Client, length 48
14:13:32.556586 IP 178.23.124.2.123 &gt; 78.47.130.33.63956: NTPv4, Server, length 48
14:13:33.535188 IP 78.47.130.33.48131 &gt; 5.9.29.107.123: NTPv4, Client, length 48
14:13:33.535500 IP 5.9.29.107.123 &gt; 78.47.130.33.48131: NTPv4, Server, length 48
14:13:34.535255 IP 78.47.130.33.56807 &gt; 178.23.124.2.123: NTPv4, Client, length 48
14:13:34.535337 IP 78.47.130.33.56554 &gt; 217.79.179.106.123: NTPv4, Client, length 48
14:13:34.544543 IP 217.79.179.106.123 &gt; 78.47.130.33.56554: NTPv4, Server, length 48
14:13:34.556932 IP 178.23.124.2.123 &gt; 78.47.130.33.56807: NTPv4, Server, length 48
14:13:35.535379 IP 78.47.130.33.22968 &gt; 5.9.29.107.123: NTPv4, Client, length 48
14:13:35.535717 IP 5.9.29.107.123 &gt; 78.47.130.33.22968: NTPv4, Server, length 48
14:13:36.535442 IP 78.47.130.33.24583 &gt; 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 <tom AT vondein DOT org>
## Project homepage
https://github.com/TLINDEN/udpxd
https://codeberg.org/scip/udpxd

View File

@@ -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</dev/null; make"'
- cmd: '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; cygstart --hide ./udpxd -l 127.0.0.1:53 -t 8.8.8.8:53"'
- cmd: '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; cygstart --hide ./udpxd -l [::1]:53 -t 8.8.8.8:53"'
- cmd: '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; dig www.google.de soa @127.0.0.1"'
- cmd: '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; dig www.google.de soa @::1"'

89
meson.build Normal file
View File

@@ -0,0 +1,89 @@
# -*-python-*-
project(
'udpxd',
'c',
license: 'GPL',
version: '0.0.4',
meson_version: '>=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 <unistd.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n#include <sys/socket.h>\n#include <syslog.h>\n#include <stdarg.h>\n#include <arpa/inet.h>\n#include <sys/types.h>\n#include <ifaddrs.h>\n#include <netdb.h>\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

1
meson_options.txt Normal file
View File

@@ -0,0 +1 @@
# custom build options

48
net.h
View File

@@ -22,25 +22,24 @@
#ifndef _HAVE_NET_H
#define _HAVE_NET_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <setjmp.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pwd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#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

101
platform.h.in Normal file
View File

@@ -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

44
udpxd.1
View File

@@ -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 <ip:port> listen for incoming requests
\& \-\-bind \-b <ip> bind ip used for outgoing requests
\& \-\-bind \-b <ip[:port]> bind ip used for outgoing requests
\& specify port for promiscuous mode
\& \-\-to \-t <ip:port> destination to forward requests to
\& \-\-daemon \-d daemon mode, fork into background
\& \-\-pidfile \-p <file> 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:
<https://github.com/TLINDEN/udpxd/issues>.
<https://codeberg.org/scip/udpxd/issues>.
.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.

23
udpxd.h
View File

@@ -22,22 +22,21 @@
#ifndef _HAVE_UDPXD_H
#define _HAVE_UDPXD_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#define UDPXD_VERSION "0.0.4"
#include "platform.h"
void usage();
int parse_ip(char *src, char *ip, char *pt);

View File

@@ -135,7 +135,7 @@ B</var/run/udpxd.pid>: 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<https://github.com/TLINDEN/udpxd/issues>.
L<https://codeberg.org/scip/udpxd/issues>.
=head1 LICENSE