mirror of
https://codeberg.org/scip/udpxd.git
synced 2025-12-16 19:40:58 +01:00
24
.travis.yml
24
.travis.yml
@@ -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
32
.woodpecker/build.yaml
Normal 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
54
.woodpecker/release.sh
Executable 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
31
.woodpecker/release.yaml
Normal 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-*
|
||||||
19
Makefile
19
Makefile
@@ -18,6 +18,8 @@
|
|||||||
#
|
#
|
||||||
# You can contact me by mail: <tom AT vondein DOT org>.
|
# 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
|
# warning: do not set -O to 2, see TODO
|
||||||
CFLAGS = -Wall -Wextra -Werror -O1 -g
|
CFLAGS = -Wall -Wextra -Werror -O1 -g
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
@@ -28,22 +30,25 @@ UID = root
|
|||||||
GID = 0
|
GID = 0
|
||||||
MAN = udpxd.1
|
MAN = udpxd.1
|
||||||
|
|
||||||
all: $(DST)
|
all: deprecation $(DST)
|
||||||
|
|
||||||
$(DST): $(OBJS)
|
$(DST): deprecation $(OBJS)
|
||||||
$(CC) $(OBJS) -o $(DST)
|
$(CC) $(OBJS) -o $(DST)
|
||||||
|
|
||||||
%.o: %.c
|
%.o: deprecation %.c
|
||||||
$(CC) -c $(CFLAGS) $*.c -o $*.o
|
$(CC) -c $(CFLAGS) $*.c -o $*.o
|
||||||
|
|
||||||
clean:
|
clean: deprecation
|
||||||
rm -f *.o $(DST)
|
rm -rf *.o $(DST) build .cache
|
||||||
|
|
||||||
man:
|
man: deprecation
|
||||||
pod2man udpxd.pod > udpxd.1
|
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)/sbin
|
||||||
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
|
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 555 $(DST) $(PREFIX)/sbin/
|
||||||
install -o $(UID) -g $(GID) -m 444 $(MAN) $(PREFIX)/man/man1/
|
install -o $(UID) -g $(GID) -m 444 $(MAN) $(PREFIX)/man/man1/
|
||||||
|
|
||||||
|
deprecation:
|
||||||
|
@echo "+++ DEPRECATION NOTE: Use meson & ninja to build please! +++"
|
||||||
|
|||||||
224
README.md
224
README.md
@@ -1,15 +1,195 @@
|
|||||||
[](https://travis-ci.org/TLINDEN/udpxd)
|
[](https://ci.codeberg.org/repos/15646)
|
||||||
[](https://ci.appveyor.com/project/TLINDEN/udpxd)
|
[](https://codeberg.org/scip/udpxd/raw/branch/main/LICENSE)
|
||||||
|
|
||||||
|
|
||||||
## UDPXD - A general purpose UDP relay/port forwarder/proxy
|
## UDPXD - A general purpose UDP relay/port forwarder/proxy
|
||||||
|
|
||||||
This is the README file for the network program udpxd.
|
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
|
udpxd can be used to forward or proxy UDP client traffic
|
||||||
to another port on another system. It also supports binding
|
to another port on another system. It also supports binding
|
||||||
to a specific ip address which will be used as the source
|
to a specific ip address which will be used as the source
|
||||||
for outgoing packets. It supports ip version 4 and 6.
|
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
|
## Documentation
|
||||||
|
|
||||||
You can read the documentation without installing the
|
You can read the documentation without installing the
|
||||||
@@ -21,31 +201,30 @@ If it is already installed, you can read the manual page:
|
|||||||
|
|
||||||
man udpxd
|
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
|
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
|
Check out the source and execute:
|
||||||
you have already done so:
|
|
||||||
|
|
||||||
git clone git@github.com:TLINDEN/udpxd.git
|
```default
|
||||||
|
meson setup build
|
||||||
|
ninja -C build
|
||||||
|
```
|
||||||
|
|
||||||
Next, change into the newly created directory 'udpxd' and
|
You can supply some additional parameters to meson,
|
||||||
compile the source code:
|
type `meson configuration` for details.
|
||||||
|
|
||||||
cd udpxd
|
To install, execute:
|
||||||
make
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -53,8 +232,7 @@ Although I'm happy to hear from udpxd users in private email,
|
|||||||
that's the best way for me to forget to do something.
|
that's the best way for me to forget to do something.
|
||||||
|
|
||||||
In order to report a bug, unexpected behavior, feature requests
|
In order to report a bug, unexpected behavior, feature requests
|
||||||
or to submit a patch, please open an issue on github:
|
or to submit a patch, [please open an issue](https://codeberg.org/scip/udpxd/issues).
|
||||||
https://github.com/TLINDEN/udpxd/issues.
|
|
||||||
|
|
||||||
## Copyright and license
|
## Copyright and license
|
||||||
|
|
||||||
@@ -66,4 +244,4 @@ T.v.Dein <tom AT vondein DOT org>
|
|||||||
|
|
||||||
## Project homepage
|
## Project homepage
|
||||||
|
|
||||||
https://github.com/TLINDEN/udpxd
|
https://codeberg.org/scip/udpxd
|
||||||
|
|||||||
34
appveyor.yml
34
appveyor.yml
@@ -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
89
meson.build
Normal 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
1
meson_options.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# custom build options
|
||||||
42
net.h
42
net.h
@@ -22,25 +22,24 @@
|
|||||||
#ifndef _HAVE_NET_H
|
#ifndef _HAVE_NET_H
|
||||||
#define _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 <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <syslog.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 <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
@@ -50,14 +49,14 @@ extern client_t *clients;
|
|||||||
extern int VERBOSE;
|
extern int VERBOSE;
|
||||||
extern int FORKED;
|
extern int FORKED;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void handle_inside(int inside, host_t *listen_h, host_t *bind_h, host_t *dst_h);
|
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);
|
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 main_loop(int listensocket, host_t *listen_h, host_t *bind_h,
|
||||||
int start_listener (char *inip, char *inpt, char *srcip, char *srcpt, char *dstip,
|
host_t *dst_h);
|
||||||
char *dstpt, char *pidfile, char *chrootdir, char *user);
|
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 daemonize(char *pidfile);
|
||||||
int drop_privileges(char *user, char *chrootdir);
|
int drop_privileges(char *user, char *chrootdir);
|
||||||
|
|
||||||
@@ -67,6 +66,9 @@ int bindsocket( host_t *sock_h);
|
|||||||
void int_handler(int sig);
|
void int_handler(int sig);
|
||||||
void verb_prbind(host_t *bind_h);
|
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
|
#endif
|
||||||
|
|||||||
101
platform.h.in
Normal file
101
platform.h.in
Normal 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
|
||||||
38
udpxd.1
38
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:
|
.\" Standard preamble:
|
||||||
.\" ========================================================================
|
.\" ========================================================================
|
||||||
@@ -38,27 +38,36 @@
|
|||||||
. ds PI \(*p
|
. ds PI \(*p
|
||||||
. ds L" ``
|
. ds L" ``
|
||||||
. ds R" ''
|
. ds R" ''
|
||||||
|
. ds C`
|
||||||
|
. ds C'
|
||||||
'br\}
|
'br\}
|
||||||
.\"
|
.\"
|
||||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
||||||
.ie \n(.g .ds Aq \(aq
|
.ie \n(.g .ds Aq \(aq
|
||||||
.el .ds 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
|
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
||||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||||
.\" output yourself in some meaningful fashion.
|
.\" output yourself in some meaningful fashion.
|
||||||
.ie \nF \{\
|
.\"
|
||||||
|
.\" Avoid warning from groff about undefined register 'F'.
|
||||||
|
.de IX
|
||||||
|
..
|
||||||
|
.nr rF 0
|
||||||
|
.if \n(.g .if rF .nr rF 1
|
||||||
|
.if (\n(rF:(\n(.g==0)) \{\
|
||||||
|
. if \nF \{\
|
||||||
. de IX
|
. de IX
|
||||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||||
..
|
..
|
||||||
|
. if !\nF==2 \{\
|
||||||
. nr % 0
|
. nr % 0
|
||||||
. rr F
|
. nr F 2
|
||||||
. \}
|
. \}
|
||||||
.el \{\
|
|
||||||
. de IX
|
|
||||||
..
|
|
||||||
. \}
|
. \}
|
||||||
|
.\}
|
||||||
|
.rr rF
|
||||||
.\"
|
.\"
|
||||||
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
||||||
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
||||||
@@ -124,7 +133,7 @@
|
|||||||
.\" ========================================================================
|
.\" ========================================================================
|
||||||
.\"
|
.\"
|
||||||
.IX Title "UDPXD 1"
|
.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
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||||
.\" way too many mistakes in technical documents.
|
.\" way too many mistakes in technical documents.
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
@@ -138,7 +147,8 @@ udpxd \- A general purpose UDP relay/port forwarder/proxy
|
|||||||
\&
|
\&
|
||||||
\& Options:
|
\& Options:
|
||||||
\& \-\-listen \-l <ip:port> listen for incoming requests
|
\& \-\-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
|
\& \-\-to \-t <ip:port> destination to forward requests to
|
||||||
\& \-\-daemon \-d daemon mode, fork into background
|
\& \-\-daemon \-d daemon mode, fork into background
|
||||||
\& \-\-pidfile \-p <file> pidfile, default: /var/run/udpxd.pid
|
\& \-\-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
|
\&\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
|
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
|
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
|
.PP
|
||||||
\&\fBCaution: if not running in daemon mode, udpxd does not drop
|
\&\fBCaution: if not running in daemon mode, udpxd does not drop
|
||||||
its privileges and will continue to run as root (if started as
|
its privileges and will continue to run as root (if started as
|
||||||
@@ -275,12 +287,12 @@ address:
|
|||||||
.IX Header "BUGS"
|
.IX Header "BUGS"
|
||||||
In order to report a bug, unexpected behavior, feature requests
|
In order to report a bug, unexpected behavior, feature requests
|
||||||
or to submit a patch, please open an issue on github:
|
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"
|
.SH "LICENSE"
|
||||||
.IX Header "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
|
.PP
|
||||||
Copyright (c) 2015-2016 by T. v. Dein.
|
Copyright (c) 2015\-2017 by T. v. Dein.
|
||||||
.PP
|
.PP
|
||||||
This software uses \fButhash\fR (bundled), which is
|
This software uses \fButhash\fR (bundled), which is
|
||||||
Copyright (c) 2003\-2013 by Troy D. Hanson.
|
Copyright (c) 2003\-2013 by Troy D. Hanson.
|
||||||
|
|||||||
23
udpxd.h
23
udpxd.h
@@ -22,22 +22,21 @@
|
|||||||
#ifndef _HAVE_UDPXD_H
|
#ifndef _HAVE_UDPXD_H
|
||||||
#define _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 <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 <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();
|
void usage();
|
||||||
int parse_ip(char *src, char *ip, char *pt);
|
int parse_ip(char *src, char *ip, char *pt);
|
||||||
|
|||||||
@@ -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
|
In order to report a bug, unexpected behavior, feature requests
|
||||||
or to submit a patch, please open an issue on github:
|
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
|
=head1 LICENSE
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user