List of commits:
Subject Hash Author Date (UTC)
Added support for user hosts file c7d7cb830b04385097c85363c4b14e0ae04d76db Catalin(ux) M. BOIE 2021-11-30 09:02:33
Do not crash if no ipv4/v6 AF (from archlinux - Kevin MacMartin - thanks) e9e3a280247e14354ead0f9322c447da090c76e0 Catalin(ux) M. BOIE 2021-02-14 13:25:23
Seems that -dl is not taken in consideration if is added at the beginning 9ed2b864388da970f0a2a2cc7ebd65c7ebbaff04 Catalin(ux) M. BOIE 2021-01-05 18:57:18
Added support for FORCE_NET_V*_CONN_ERROR to return an error for connect syscall c221dc3ff63bcd28c2053694177a9a09ef9a6570 Catalin(ux) M. BOIE 2019-03-20 18:26:19
rpm changelog e7127f5191015b0b93c7108b6fa02fde7f0fe909 Catalin(ux) M. BOIE 2019-02-05 21:10:57
duilder update 71425ef75fbc076d6601ceadd52e81e678aabe57 Catalin(ux) M. BOIE 2019-02-05 21:09:29
Switch to v0.13 7a5ed99fa6629ff9dbe16f6b015712a78854b621 Catalin(ux) M. BOIE 2019-02-05 21:08:06
Lots of changes e11f13f4d11723f0c2c833ffbaca89e55d74e139 Catalin(ux) M. BOIE 2019-01-16 20:18:06
Restart accept interrupted by signal d84134f3193fd2d4c5298eaded8ffade5d74d220 Catalin(ux) M. BOIE 2014-11-11 06:57:12
Bump version to 0.12 ea1c70a262b706cd45f1eb98b6aa9805de300647 Catalin(ux) M. BOIE 2014-10-14 03:14:29
Added support to change poll timeout d0e5782e1fb0da5db1291b3c518486d3ac8dec97 Catalin(ux) M. BOIE 2014-10-14 03:13:58
Fixed strcmp on a NULL variable 59df6d596e3c842227f4f374b4b6635de3ce1c3e Catalin(ux) M. BOIE 2014-10-14 03:12:29
Added support for deny and fake for Kevin d9598fd2ca7886484b78512d71dbd29059720832 Catalin(ux) M. BOIE 2012-07-18 21:13:20
Log also the version in the log file. d5576baff697e87dfbbbcbfb77df4b364cee15a2 Catalin(ux) M. BOIE 2011-08-25 18:55:40
SOCK_DCCP is not defined on CentOS. :( 303830a06b80962e417c01d88cae6d50e9182662 Catalin(ux) M. BOIE 2011-08-25 09:46:09
More fixes for spec file 06d8c98718977c91419ffd6cabdd3e6bb57b8043 Catalin(ux) M. BOIE 2011-08-24 20:29:10
Added example for config file. 20becba1955981d5c3642e802031c08c25c701cf Catalin(ux) M. BOIE 2011-08-24 20:26:19
Bump version to 0.10. 9659780e6f025d10441c354eefe79e327a660c09 Catalin(ux) M. BOIE 2011-08-24 20:20:26
Ignore more files in repo. c1121dc5f6644043314880361c24fc2172326c02 Catalin(ux) M. BOIE 2011-08-24 20:20:00
Big fix for stuck programs. Stupid. f0ea19d9130bdc8851f08fb16a61a7be8da002cd Catalin(ux) M. BOIE 2011-08-24 20:19:56
Commit c7d7cb830b04385097c85363c4b14e0ae04d76db - Added support for user hosts file
Author: Catalin(ux) M. BOIE
Author date (UTC): 2021-11-30 09:02
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2021-11-30 09:02
Parent(s): e9e3a280247e14354ead0f9322c447da090c76e0
Signer:
Signing key:
Signing status: N
Tree: ac55f8b63421365600ff4d9449bc128c718e44f7
File Lines added Lines deleted
.gitignore 3 2
Makefile.in 7 8
README 6 0
TODO 9 2
dillo.sh 13 0
duilder 43 25
duilder.conf 0 13
firefox.sh 13 0
force_bind.c 422 4
force_bind.spec 4 4
force_bind_config.h 1 0
force_bind_config.h.in 0 1
test3.sh 11 0
test_getaddrinfo.c 63 0
test_getaddrinfo.hosts 4 0
test_getaddrinfo.sh 21 0
test_gethostbyname.c 38 0
test_gethostbyname.hosts 1 0
test_gethostbyname.sh 18 0
test_inet_pton.sh 5 2
File .gitignore changed (mode: 100644) (index 35830e1..f7c6f6e)
1 1 /Makefile /Makefile
2 2 Changelog* Changelog*
3 3 *.so* *.so*
4 *.spec
5 4 test_bind test_bind
6 5 test_bind6 test_bind6
7 6 *.strace *.strace
 
... ... test_client
10 9 test_client6 test_client6
11 10 *.out *.out
12 11 *.log *.log
13 force_bind_config.h
14 12 test_poll test_poll
13 vgcore.*
14 test_getaddrinfo
15 test_gethostbyname
File Makefile.in changed (mode: 100644) (index 649b1ec..21d7701)
1 1 export CC := gcc export CC := gcc
2 2 export INCS += export INCS +=
3 3 export LIBS += export LIBS +=
4 export CFLAGS += -O2 -ggdb -Wall -Wextra -pipe
5 export CFLAGS += -Wcast-align -Wformat=2 -Wformat-security -fno-common
6 export CFLAGS += -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes
7 export CFLAGS += -Wstrict-overflow -Wtrampolines -flto
8 export CFLAGS += -fstack-protector-all
4 export CFLAGS += @CC_SWITCHES@
5 export CFLAGS += -ggdb -Wall -Wextra -pipe
9 6 export CFLAGS += -D _FORTIFY_SOURCES=2 export CFLAGS += -D _FORTIFY_SOURCES=2
10 export CFLAGS += -fstack-reuse=all -fbounds-check
11 export CFLAGS += -Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro -Wl,-O1
12 7
13 export CFLAGSSO = $(CFLAGS) -ldl -lc -shared -rdynamic
8 export CFLAGSSO = $(CFLAGS) -ldl -lc -shared -rdynamic -fPIC
14 9
15 10
16 11 .PHONY: all .PHONY: all
 
... ... test_client6: test_client6.c
37 32 test_poll: test_poll.c test_poll: test_poll.c
38 33 $(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@
39 34
35 test_gethostbyname: test_gethostbyname.c
36 $(CC) $(CFLAGS) $< -o $@
37
40 38 .PHONY: clean .PHONY: clean
41 39 clean: clean:
42 40 @rm -f force_bind.so.* test_bind send_udp test_client test_client6 \ @rm -f force_bind.so.* test_bind send_udp test_client test_client6 \
41 test_gethostbyname \
43 42 *.a *.o *.so* $(PRJ)-*.rpm $(PRJ)-*-*-*.tgz $(PRJ)-*.tar.gz \ *.a *.o *.so* $(PRJ)-*.rpm $(PRJ)-*-*-*.tgz $(PRJ)-*.tar.gz \
44 43 *.strace *.log *.out \ *.strace *.log *.out \
45 44 test_poll test_poll
File README changed (mode: 100644) (index 1d1d3e8..fd5a739)
... ... Examples:
139 139 your_program_here your_program_here
140 140 # Supported errors: refused, unreach # Supported errors: refused, unreach
141 141
142 18. User /etc/hosts file
143 export FORCE_NET_HOSTS="/home/x/hosts"
144 export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so
145 your_program_here
146 # You may want to not specify a full path.
147
142 148 Installation: Installation:
143 149 - ./configure - ./configure
144 150 - make - make
File TODO changed (mode: 100644) (index c1e2ed8..b146d68)
1 [ ] Add io_uring support to replace (e)poll on-the-fly.
2 [ ] Add posibility to change on-the-fly the parameters by using a AF_UNIX socket
3 [ ] Add a control socket file to be able to control bandwidth and other stuff.
4 [ ] Allow the use of a local resolv.conf file (for a non root user).
5 Take in consideration the WiFi Ap in use, ip address on an interface,
6 time-of-the-day, application etc.
7 Partially done by specifying custom hosts file.
8 [ ] Add a default X (mark, tos etc.) for all new sockets.
1 9 [ ] accept/accept4 seems to not be intercepted! [ ] accept/accept4 seems to not be intercepted!
2 10 [ ] Clarify deny/fake for bind. It is only ipv4/ipv6? [ ] Clarify deny/fake for bind. It is only ipv4/ipv6?
3 11 [ ] Document force_poll_timeout [ ] Document force_poll_timeout
 
14 22 [ ] Corrupt data [ ] Corrupt data
15 23 [ ] Add possibility to change destination of packets. [ ] Add possibility to change destination of packets.
16 24 [ ] MTU [ ] MTU
17 [ ] Add posibility to change on-the-fly the parameters by using a AF_UNIX socket
18 25 [ ] bwtop: http://superuser.com/questions/32932/is-there-a-way-to-find-out-what-application-using-most-of-bandwidth-in-linux [ ] bwtop: http://superuser.com/questions/32932/is-there-a-way-to-find-out-what-application-using-most-of-bandwidth-in-linux
19 26 [ ] http://superuser.com/questions/106781/how-do-you-measure-the-bandwidth-used-by-a-given-process-after-it-has-completed [ ] http://superuser.com/questions/106781/how-do-you-measure-the-bandwidth-used-by-a-given-process-after-it-has-completed
20 27 [ ] Bandwidth limitting also for download [ ] Bandwidth limitting also for download
21 [ ] Dump statistics (bytes, syscalls etc.) in a file specified by a env var.
28 [ ] Dump statistics (bytes, syscalls etc.) in a file specified by an env var.
22 29 [ ] Need to study how to set only the class for IPv6. Also check Linux kernel [ ] Need to study how to set only the class for IPv6. Also check Linux kernel
23 30 to see how prio is set for IPv6 class. to see how prio is set for IPv6 class.
24 31 [ ] Nice: Force a protocol on a connection! So, user tries TCP but gets UDP! [ ] Nice: Force a protocol on a connection! So, user tries TCP but gets UDP!
File dillo.sh added (mode: 100755) (index 0000000..bde4784)
1 #!/bin/sh
2
3 export FORCE_NET_LOG="dillo.log"
4 export FORCE_NET_VERBOSE=999
5
6 export FORCE_BIND_ADDRESS_V4="192.168.79.33"
7 #export FORCE_BIND_PORT_V4=900
8
9 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
10
11 #strace -tt -f -o dillo-fb.strace -s200 dillo http://kernel.embedromix.ro
12 #strace -tt -f -o dillo-fb.strace -s200 dillo http://192.168.79.154
13 debug dillo http://kernel.embedromix.ro
File duilder changed (mode: 100755) (index e058c68..e243861)
... ... function duilder_docs()
34 34
35 35 echo "[*] Copying docs to [${EXPORT_PATH}]..." echo "[*] Copying docs to [${EXPORT_PATH}]..."
36 36 for f in README License LICENSE Changelog Changelog-last TODO FAQ INSTALL AUTHORS samples; do for f in README License LICENSE Changelog Changelog-last TODO FAQ INSTALL AUTHORS samples; do
37 if [ -r "${f}" ]; then
38 cp -avp "${f}" "${EXPORT_PATH}/"
39 if [ "${BUILD_SDEB}" = "1" ]; then
40 # No need to install the license file
41 if [ "${f}" = "LICENSE" ]; then
42 continue
43 fi
44 echo "${f}" >> debian/docs
37 [ ! -r "${f}" ] && continue
38
39 cp -avp "${f}" "${EXPORT_PATH}/"
40 if [ "${BUILD_SDEB}" = "1" ]; then
41 # No need to install the license file
42 if [ "${f}" = "LICENSE" ]; then
43 continue
45 44 fi fi
45 echo "${f}" >> debian/docs
46 46 fi fi
47 47 done done
48 48 echo echo
 
... ... function duilder_docs()
57 57
58 58 function duilder_git() function duilder_git()
59 59 { {
60 PRJ="${1}"
61 GIT_DEST="${2}"
62 EXPORT_GIT="${3}"
63 GIT_CHANGELOG="${4}"
64 GIT_PUSH="${5}"
60 PRJ="${1}"; shift
61 GIT_DEST="${1}"; shift
62 EXPORT_GIT="${1}"; shift
63 EXPORT_PATH="${1}"; shift
64 GIT_CHANGELOG="${1}"; shift
65 GIT_PUSH="${1}"; shift
65 66
66 67 if [ ! -x /usr/bin/git ]; then if [ ! -x /usr/bin/git ]; then
67 68 echo "[*] Warning: Git not found!" echo "[*] Warning: Git not found!"
 
... ... function duilder_srpm()
205 206 fi fi
206 207
207 208 if [ ! -z "${SRPM_DEST}" ]; then if [ ! -z "${SRPM_DEST}" ]; then
209 if [ -r "${SRPM_DEST}/${PKG}" ]; then
210 mv "${SRPM_DEST}/${PKG}" "${SRPM_DEST}/${PKG}.old"
211 fi
208 212 echo "[*] Copying [${PKG}] to [${SRPM_DEST}]..." echo "[*] Copying [${PKG}] to [${SRPM_DEST}]..."
209 213 cp -vp "${PKG}" "${SRPM_DEST}/" cp -vp "${PKG}" "${SRPM_DEST}/"
210 214 fi fi
 
... ... fi
307 311
308 312
309 313 if [ ! -r duilder.conf ]; then if [ ! -r duilder.conf ]; then
310 echo "[*] You must build a duilder.conf file!"
311 exit 1
314 echo "[*] You do not have a duilder.conf file. Trying to continue."
315 else
316 source ${PWD}/duilder.conf 2>/dev/null
312 317 fi fi
313 318
314 source ${PWD}/duilder.conf
315 319
316 320 # fixes # fixes
317 321 if [ -z "${GIT_DEST}" ]; then if [ -z "${GIT_DEST}" ]; then
 
... ... if [ -z "${GIT_DEST}" ]; then
319 323 fi fi
320 324
321 325 if [ -z "${PRJ}" ]; then if [ -z "${PRJ}" ]; then
322 echo "ERROR: PRJ= parameter is missing."
323 exit 1
326 echo "WARN: PRJ= parameter is missing."
324 327 fi fi
325 328
326 329 if [ -z "${VER}" ]; then if [ -z "${VER}" ]; then
327 echo "ERROR: VER= parameter is missing."
328 exit 1
330 echo "WARN: VER= parameter is missing."
329 331 fi fi
330 332
331 333 if [ -z "${REV}" ]; then if [ -z "${REV}" ]; then
332 echo "ERROR: REV= parameter is missing."
333 exit 1
334 echo "WARN: REV= parameter is missing."
334 335 fi fi
335 336
336 337 # export variables - just in case a script cares # export variables - just in case a script cares
 
... ... else
541 542 echo "s#@NCURSES_FOUND@#1#g" >> tmp.sed echo "s#@NCURSES_FOUND@#1#g" >> tmp.sed
542 543 fi fi
543 544
544 if [ -n "${CC_SWITCHES}" ]; then
545 if [ "${CC_SWITCHES}" = "" ]; then
546 CC_SWITCHES="-O3 -fstack-reuse=all -flto -Wtrampolines -Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro -Wl,-O1 -Wl,-z,noexecstack -fPIE -pie -fstack-protector-all -Wcast-align -Wformat=2 -Wformat-security -fno-common -Wmissing-prototypes -Wmissing-declarations -Wstrict-overflow -Wstrict-prototypes -fno-guess-branch-probability -fbounds-check -Wl,-O3 -Wpadded -ftree-loop-distribution -ftree-vectorize -ftree-loop-if-convert -ftree-loop-im -ftree-parallelize-loops=4 -fcf-protection -fstack-clash-protection -Wimplicit-fallthrough -fanalyzer"
547 fi
548
549 if [ "1" = "1" ]; then
545 550 _CC_SWITCHES="" _CC_SWITCHES=""
546 551 echo "[*] Search for valid compiler flags..." echo "[*] Search for valid compiler flags..."
547 552 add="" add=""
548 553 for s in ${CC_SWITCHES}; do for s in ${CC_SWITCHES}; do
549 554 echo -n " [*] Testing switch [${s}]..." echo -n " [*] Testing switch [${s}]..."
555 case ${s} in
556 -Wformat-security) extra=" -Wformat" ;;
557 *) extra="" ;;
558 esac
550 559 set +e set +e
551 echo "int main(void) { return 0; }" | gcc ${s} -x c -pipe - -o /dev/null 2>/dev/null
560 echo "int main(void) { return 0; }" \
561 | gcc ${extra} ${s} -x c -pipe - -o /dev/null 2>>duilder.log
552 562 E=${?} E=${?}
553 563 set -e set -e
554 564 if [ "${E}" != "0" ]; then if [ "${E}" != "0" ]; then
 
... ... if [ -r Makefile.in ]; then
642 652 echo >> Makefile echo >> Makefile
643 653 echo "# This is to allow exporting only the git tree" >> Makefile echo "# This is to allow exporting only the git tree" >> Makefile
644 654 echo "dist_git:" >> Makefile echo "dist_git:" >> Makefile
645 echo " @./duilder git \"\$(PRJ)\" \"${GIT_DEST}\" \"${EXPORT_GIT}\" \"${EXPORT_PATH}\" \"${GIT_CHANGELOG}\"" >> Makefile
655 echo " @./duilder git \"\$(PRJ)\" \"${GIT_DEST}\" \"${EXPORT_GIT}\" \"${EXPORT_PATH}\" \"${GIT_CHANGELOG}\" \"${GIT_PUSH}\"" >> Makefile
656 echo >> Makefile
657 echo "# This is to allow making the tar" >> Makefile
658 echo "dist_tar:" >> Makefile
659 echo " @./duilder tar \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\" \"${EXCLUDE}\"" >> Makefile
660 echo >> Makefile
661 echo "# This is to allow making rpm" >> Makefile
662 echo "dist_srpm: dist_tar" >> Makefile
663 echo " @./duilder srpm \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\" \"${BUILD_SRPM}\" \"${SRPM_DEST}\" \"${SRPM_POST_RUN}\"" >> Makefile
646 664 echo >> Makefile echo >> Makefile
647 665 echo ".PHONY: dist" >> Makefile echo ".PHONY: dist" >> Makefile
648 666 echo "dist: clean" >> Makefile echo "dist: clean" >> Makefile
File duilder.conf deleted (index c20881a..0000000)
1 PRJ="force_bind"
2 VER="0.13"
3 REV="1"
4 EXCLUDE=""
5 EXPORT_PATH="/data/www/umbrella/kernel/us/force_bind"
6 EXPORT_GIT="0"
7 GIT_CHANGELOG="1"
8 BUILD_SRPM="1"
9 SRPM_DEST="../dinorepo/fedora/SRPMS"
10 BUILD_TGZ="1"
11 BUILD_DEB="1"
12 RELEASE_SCRIPT="/usr/local/bin/duilder_release"
13 CONFIG_H="force_bind_config.h"
File firefox.sh added (mode: 100755) (index 0000000..e8f6406)
1 #!/bin/sh
2
3 export FORCE_NET_LOG="firefox.log"
4 export FORCE_NET_VERBOSE=999
5
6 export FORCE_BIND_ADDRESS_V4="192.168.79.33"
7 #export FORCE_BIND_PORT_V4=900
8
9 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
10
11 #strace -tt -f -o dillo-fb.strace -s200 dillo http://kernel.embedromix.ro
12 #strace -tt -f -o dillo-fb.strace -s200 dillo http://192.168.79.154
13 firefox http://kernel.embedromix.ro
File force_bind.c changed (mode: 100644) (index fd1b612..a6f8c06)
33 33 #include <netinet/in.h> #include <netinet/in.h>
34 34 #include <netinet/tcp.h> #include <netinet/tcp.h>
35 35 #include <poll.h> #include <poll.h>
36 #include <netdb.h>
37 #include <ctype.h>
36 38
37 39 #include "force_bind_config.h" #include "force_bind_config.h"
38 40
 
... ... struct private
79 81 int domain; int domain;
80 82 int type; int type;
81 83 unsigned int flags; unsigned int flags;
84 unsigned int pad1;
82 85 struct sockaddr_storage dest; struct sockaddr_storage dest;
83 86 socklen_t dest_len; socklen_t dest_len;
87 unsigned int pad2;
84 88
85 89 /* bandwidth */ /* bandwidth */
86 90 unsigned long long limit; unsigned long long limit;
 
... ... struct private
91 95 struct node struct node
92 96 { {
93 97 int fd; int fd;
98 int pad1;
94 99 struct private priv; struct private priv;
95 100 struct node *next; struct node *next;
96 101 }; };
 
... ... struct info
101 106 }; };
102 107
103 108
109 static unsigned int my_hosts_mtime;
110 static char *my_hosts_file = NULL;
111 struct my_hosts_node
112 {
113 struct hostent *h;
114 struct my_hosts_node *next;
115 };
116 static struct my_hosts_node *my_hosts_head, *my_hosts_tail;
117
104 118 static int (*old_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen) = NULL; static int (*old_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen) = NULL;
105 119 static int (*old_setsockopt)(int sockfd, int level, int optname, const void *optval, socklen_t optlen); static int (*old_setsockopt)(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
106 120 static int (*old_socket)(int domain, int type, int protocol); static int (*old_socket)(int domain, int type, int protocol);
 
... ... static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen
113 127 static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
114 128 static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
115 129 static int (*old_poll)(struct pollfd *fds, nfds_t nfds, int timeout); static int (*old_poll)(struct pollfd *fds, nfds_t nfds, int timeout);
130 static struct hostent *(*old_gethostbyname)(const char *name);
131 static int (*old_getaddrinfo)(const char *restrict node, const char *restrict service,
132 const struct addrinfo *restrict hints, struct addrinfo **restrict res);
116 133
117 134 static char *force_address_v4 = NULL; static char *force_address_v4 = NULL;
118 135 static char *force_address_v6 = NULL; static char *force_address_v6 = NULL;
 
... ... static void xlog(const unsigned int level, const char *format, ...)
236 253 va_end(ap); va_end(ap);
237 254 } }
238 255
256 __attribute__((unused))
239 257 static void dump(const unsigned int level, const char *title, const void *buf, static void dump(const unsigned int level, const char *title, const void *buf,
240 258 const unsigned int len) const unsigned int len)
241 259 { {
 
... ... static void init(void)
373 391 if (inited == 1) if (inited == 1)
374 392 return; return;
375 393
376 inited = 1;
394 xlog(1, "force_bind: init started...\n");
377 395
378 396 fdinfo.head = NULL; fdinfo.head = NULL;
379 397 fdinfo.tail = NULL; fdinfo.tail = NULL;
 
... ... static void init(void)
391 409 if (x != NULL) if (x != NULL)
392 410 verbose = (unsigned int) strtoul(x, NULL, 10); verbose = (unsigned int) strtoul(x, NULL, 10);
393 411
394 xlog(1, "force_bind: init started...\n");
395 xlog(1, "force_bind: version: %s\n", FORCE_BIND_VERSION);
412 xlog(1, "force_bind: version: %s, verbose %u\n",
413 FORCE_BIND_VERSION, verbose);
414
415 my_hosts_file = getenv("FORCE_NET_HOSTS");
416 if (my_hosts_file)
417 xlog(3, "hosts file: %s\n", my_hosts_file);
396 418
397 419 x = getenv("FORCE_BIND_ADDRESS_V4"); x = getenv("FORCE_BIND_ADDRESS_V4");
398 420 if (x != NULL) { if (x != NULL) {
 
... ... static void init(void)
644 666 exit(1); exit(1);
645 667 } }
646 668
669 old_gethostbyname = dlsym(RTLD_NEXT, "gethostbyname");
670 if (old_gethostbyname == NULL) {
671 xlog(0, "force_bind: cannot resolve 'gethostbyname'!\n");
672 exit(1);
673 }
674
675 old_getaddrinfo = dlsym(RTLD_NEXT, "getaddrinfo");
676 if (old_getaddrinfo == NULL) {
677 xlog(0, "force_bind: cannot resolve 'getaddrinfo'!\n");
678 exit(1);
679 }
680
647 681 xlog(1, "force_bind: init ended.\n"); xlog(1, "force_bind: init ended.\n");
682 inited = 1;
648 683 } }
649 684
650 685 static int set_ka(int sockfd) static int set_ka(int sockfd)
 
... ... static int alter_sa(const int sockfd, struct sockaddr *sa)
847 882 force_port = force_port_v6; force_port = force_port_v6;
848 883 break; break;
849 884
885 case AF_UNIX:
886 xlog(2, "force_bind: unsupported family AF_UNIX\n");
887 return 0;
888
850 889 default: default:
851 xlog(1, "force_bind: unsupported family=%u [%d]!\n",
890 xlog(1, "force_bind: unsupported family=%u [fd=%d]!\n",
852 891 sa->sa_family, sockfd); sa->sa_family, sockfd);
853 892 return 0; return 0;
854 893 } }
 
... ... int poll(struct pollfd *fds, nfds_t nfds, int timeout)
1370 1409 return old_poll(fds, nfds, timeout); return old_poll(fds, nfds, timeout);
1371 1410 } }
1372 1411
1412 static void my_hosts_clean(struct my_hosts_node *n)
1413 {
1414 struct my_hosts_node *next;
1415 unsigned int i;
1416
1417 while (n) {
1418 next = n->next;
1419
1420 if (n->h) {
1421 free(n->h->h_name);
1422
1423 i = 0;
1424 while (n->h->h_aliases[i])
1425 free(n->h->h_aliases[i++]);
1426 free(n->h->h_aliases);
1427
1428 i = 0;
1429 while (n->h->h_addr_list[i])
1430 free(n->h->h_addr_list[i++]);
1431 free(n->h->h_addr_list);
1432
1433 free(n->h);
1434 }
1435 free(n);
1436
1437 n = next;
1438 }
1439 }
1440
1441 // TODO: reload the file if mtime changed
1442 static unsigned int my_hosts_reload(void)
1443 {
1444 FILE *f;
1445 char line[4096], s[512], *q, *af = "v6", *n;
1446 unsigned int ret = 0, i, a;
1447 struct my_hosts_node *node;
1448 int r;
1449 struct stat st;
1450
1451 if (!my_hosts_file)
1452 return 1;
1453
1454 // If already loaded, return
1455 if (my_hosts_head) {
1456 r = stat(my_hosts_file, &st);
1457 if (r != 0) {
1458 xlog(1, "Cannot stat file [%s]: %m!\n", my_hosts_file);
1459 return 2;
1460 }
1461 if (my_hosts_mtime == st.st_mtime) {
1462 xlog(10, "File is up-to-date\n");
1463 return 0;
1464 }
1465
1466 // We need to reload
1467 my_hosts_clean(my_hosts_head);
1468 my_hosts_head = my_hosts_tail = NULL;
1469 }
1470
1471 f = fopen(my_hosts_file, "r");
1472 if (!f) {
1473 xlog(1, "Cannot open file [%s]: %m\n", my_hosts_file);
1474 return 2;
1475 }
1476
1477 while (1) {
1478 n = fgets(line, sizeof(line), f);
1479 if (!n)
1480 break;
1481
1482 //xlog(3, "Readed: %s\n", line);
1483
1484 node = calloc(1, sizeof(struct my_hosts_node));
1485 if (!node) {
1486 xlog(1, "Cannot alloc mem for node!\n");
1487 break;
1488 }
1489
1490 node->h = calloc(1, sizeof(struct hostent));
1491 if (!node->h) {
1492 xlog(1, "Cannot alloc mem for node!\n");
1493 my_hosts_clean(node);
1494 break;
1495 }
1496
1497 node->h->h_aliases = calloc(50, sizeof(char *));
1498 if (!node->h->h_aliases) {
1499 xlog(1, "Cannot alloc mem for node!\n");
1500 my_hosts_clean(node);
1501 break;
1502 }
1503
1504 node->h->h_addr_list = calloc(2, sizeof(char *));
1505 if (!node->h->h_addr_list) {
1506 xlog(1, "Cannot alloc mem for h_addr_list!\n");
1507 my_hosts_clean(node);
1508 break;
1509 }
1510
1511 node->h->h_addr_list[0] = malloc(16); // cover both ipv4 and ipv6
1512 if (!node->h->h_addr_list[0]) {
1513 xlog(1, "Cannot alloc mem for h_addr_list[0]!\n");
1514 my_hosts_clean(node);
1515 break;
1516 }
1517
1518 // ip
1519 q = line; i = 0;
1520 while (1) {
1521 if (!isxdigit(*q) && (*q != ':') && (*q != '.'))
1522 break;
1523 s[i++] = *q++;
1524 }
1525 s[i] = '\0';
1526 if (*s == '\0') {
1527 xlog(1, " ip is missing\n");
1528 my_hosts_clean(node);
1529 continue;
1530 }
1531 xlog(10, "ip=%s.\n", s);
1532 if (strchr(s, ':')) {
1533 node->h->h_addrtype = AF_INET6;
1534 node->h->h_length = 16;
1535 } else {
1536 node->h->h_addrtype = AF_INET;
1537 node->h->h_length = 4;
1538 af = "v4";
1539 }
1540 r = inet_pton(node->h->h_addrtype, s, node->h->h_addr_list[0]);
1541 if (r != 1) {
1542 xlog(1, "Invalid IP [%s] type %s!\n", s, af);
1543 my_hosts_clean(node);
1544 continue;
1545 }
1546
1547 while ((*q == '\t') || (*q == ' '))
1548 q++;
1549
1550 // h_name
1551 i = 0;
1552 while (1) {
1553 if (!isalnum(*q) && (*q != '.'))
1554 break;
1555 s[i++] = *q++;
1556 }
1557 s[i] = '\0';
1558 node->h->h_name = strdup(s);
1559
1560 // aliases
1561 a = 0;
1562 while (a < 48) {
1563 //xlog(10, "aliases: a=%u q=%s", a, q);
1564 if (*q == '\0')
1565 break;
1566 while ((*q == '\t') || (*q == ' '))
1567 q++;
1568
1569 i = 0;
1570 while (1) {
1571 if ((*q == '\n') || (*q == '\r'))
1572 break;
1573 if (!isalnum(*q) && (*q != '.'))
1574 break;
1575 s[i++] = *q++;
1576 }
1577 s[i] = '\0';
1578 if (*s == '\0')
1579 break;
1580 node->h->h_aliases[a++] = strdup(s);
1581 }
1582
1583 xlog(10, "AF=%s name=%s h_addrtype=%u h_length=%u\n",
1584 af, node->h->h_name, node->h->h_addrtype,
1585 node->h->h_length);
1586 i = 0;
1587 while (node->h->h_aliases[i]) {
1588 xlog(10, " alias: %s.\n", node->h->h_aliases[i]);
1589 i++;
1590 }
1591
1592 if (my_hosts_head == NULL)
1593 my_hosts_head = node;
1594 else
1595 my_hosts_tail->next = node;
1596 my_hosts_tail = node;
1597 }
1598 fclose(f);
1599
1600 if (ret == 0)
1601 my_hosts_mtime = st.st_mtime;
1602
1603 return ret;
1604 }
1605
1606 static struct my_hosts_node *my_hosts_find(const char *name)
1607 {
1608 struct my_hosts_node *p;
1609 unsigned int i;
1610
1611 i = my_hosts_reload();
1612 if (i != 0)
1613 return NULL;
1614
1615 xlog(10, " Searching for [%s]\n", name);
1616 p = my_hosts_head;
1617 while (p) {
1618 if (strcmp(p->h->h_name, name) == 0)
1619 return p;
1620
1621 i = 0;
1622 while (p->h->h_aliases[i]) {
1623 if (strcmp(p->h->h_aliases[i], name) == 0)
1624 return p;
1625 i++;
1626 }
1627
1628 p = p->next;
1629 }
1630
1631 xlog(3, "host [%s] not found in [%s] file\n", name, my_hosts_file);
1632 return NULL;
1633 }
1634
1635 struct hostent *gethostbyname(const char *name)
1636 {
1637 struct my_hosts_node *p;
1638
1639 init();
1640
1641 xlog(2, "force_bind: gethostbyname(%s)\n", name);
1642
1643 p = my_hosts_find(name);
1644 if (p)
1645 return p->h;
1646
1647 return old_gethostbyname(name);
1648 }
1649
1650 int getaddrinfo(const char *restrict node, const char *restrict service,
1651 const struct addrinfo *restrict hints, struct addrinfo **restrict res)
1652 {
1653 unsigned int i;
1654
1655 init();
1656
1657 xlog(2, "force_bind: getaddrinfo(node=%s, service=%s, hints=0x%x)\n",
1658 node, service, hints ? hints : 0);
1659
1660 i = my_hosts_reload();
1661 if (node && (i == 0)) {
1662 struct my_hosts_node *p;
1663 struct addrinfo *a, *head = NULL, *tail = NULL, *prev;
1664 struct addrinfo hints0;
1665 int port = 0, ret = 0;
1666
1667 if (hints) {
1668 memcpy(&hints0, hints, sizeof(struct addrinfo));
1669 } else {
1670 memset(&hints0, 0, sizeof(struct addrinfo));
1671 hints0.ai_family = AF_UNSPEC;
1672 hints0.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
1673 }
1674
1675 if (service) {
1676 if (hints0.ai_flags & AI_NUMERICSERV) {
1677 port = atoi(service);
1678 } else {
1679 struct servent *se;
1680 se = getservbyname(service, NULL);
1681 if (!se) {
1682 xlog(1, " Error looking up service [%s]: %m!\n", service);
1683 ret = EAI_NONAME;
1684 } else {
1685 port = se->s_port;
1686 }
1687 }
1688 }
1689
1690 xlog(10, " Searching for [%s]\n", node);
1691 p = my_hosts_head;
1692 prev = NULL;
1693 while ((ret == 0) && p) {
1694 int found;
1695 struct sockaddr_in *a4;
1696 struct sockaddr_in6 *a6;
1697
1698 if ((hints0.ai_family != AF_UNSPEC)
1699 && (hints0.ai_family != p->h->h_addrtype)) {
1700 p = p->next;
1701 continue;
1702 }
1703
1704 found = 0;
1705 if (strcmp(p->h->h_name, node) == 0) {
1706 found = 1;
1707 } else {
1708 i = 0;
1709 while (p->h->h_aliases[i]) {
1710 if (strcmp(p->h->h_aliases[i], node) != 0) {
1711 found = 1;
1712 break;
1713 }
1714 i++;
1715 }
1716 }
1717 if (!found) {
1718 p = p->next;
1719 continue;
1720 }
1721
1722 a = malloc(sizeof(struct addrinfo));
1723 if (!a) {
1724 xlog(1, "Canot alloc memory for addrinfo!\n");
1725 ret = EAI_MEMORY;
1726 break;
1727 }
1728 memcpy(a, &hints0, sizeof(struct addrinfo));
1729 a->ai_next = NULL;
1730
1731 if (head == NULL)
1732 head = a;
1733 else
1734 tail->ai_next = a;
1735 tail = a;
1736
1737 // TODO: AI_ADDRCONFIG
1738 a->ai_family = p->h->h_addrtype;
1739
1740 a->ai_addr = calloc(1, sizeof(struct sockaddr_storage));
1741 if (!a->ai_addr) {
1742 xlog(1, "Cannot alloc mem for ai_addr");
1743 ret = EAI_MEMORY;
1744 break;
1745 }
1746
1747 if (hints0.ai_socktype == AF_UNSPEC)
1748 a->ai_socktype = SOCK_STREAM;
1749
1750 if (a->ai_family == AF_INET) {
1751 a4 = (struct sockaddr_in *) a->ai_addr;
1752 a4->sin_port = port;
1753 a4->sin_family = a->ai_family;
1754 memcpy(&a4->sin_addr, p->h->h_addr_list[0], p->h->h_length);
1755 a->ai_addrlen = sizeof(struct sockaddr_in);
1756 } else if (a->ai_family == AF_INET6) {
1757 a6 = (struct sockaddr_in6 *) a->ai_addr;
1758 a6->sin6_port = port;
1759 a6->sin6_family = a->ai_family;
1760 memcpy(&a6->sin6_addr, p->h->h_addr_list[0], p->h->h_length);
1761 a->ai_addrlen = sizeof(struct sockaddr_in6);
1762 }
1763
1764 if (hints->ai_flags & AI_CANONNAME) {
1765 a->ai_canonname = strdup(p->h->h_name);
1766 if (!a->ai_canonname) {
1767 xlog(1, "Cannot alloca mem for canonname");
1768 ret = EAI_MEMORY;
1769 break;
1770 }
1771 }
1772
1773 if (prev)
1774 prev->ai_next = a;
1775
1776 prev = a;
1777 p = p->next;
1778 }
1779
1780 if (ret == 0) {
1781 *res = head;
1782 return 0;
1783 }
1784
1785 freeaddrinfo(head);
1786 }
1787
1788 return old_getaddrinfo(node, service, hints, res);
1789 }
1790
File force_bind.spec renamed from force_bind.spec.in (similarity 93%) (mode: 100644) (index 9ff243f..ff3754e)
1 1 Summary: Force binding to a specif address and/or port, changing TOS/TTL/MSS/etc Summary: Force binding to a specif address and/or port, changing TOS/TTL/MSS/etc
2 Name: @PRJ@
3 Version: @VER@
4 Release: @REV@
2 Name: force_bind
3 Version: 0.14
4 Release: 1
5 5 License: GPLv3+ License: GPLv3+
6 6 Group: Applications/Communications Group: Applications/Communications
7 7 Source: http://kernel.embedromix.ro/us/%{name}/%{name}-%{version}.tar.gz Source: http://kernel.embedromix.ro/us/%{name}/%{name}-%{version}.tar.gz
 
... ... rm -rf ${RPM_BUILD_ROOT}
35 35 %files %files
36 36 %attr (-,root,root) %attr (-,root,root)
37 37 %{_libdir}/*.so %{_libdir}/*.so
38 %doc README LICENSE Changelog TODO
38 %doc README LICENSE TODO
39 39
40 40 %changelog %changelog
41 41 * Tue Feb 5 2019 Catalin(ux) M. BOIE <catab at embedromix dot ro> 0.13-1 * Tue Feb 5 2019 Catalin(ux) M. BOIE <catab at embedromix dot ro> 0.13-1
File force_bind_config.h added (mode: 100644) (index 0000000..aa9baec)
1 #define FORCE_BIND_VERSION "0.14"
File force_bind_config.h.in deleted (index 6fa1dc0..0000000)
1 #define FORCE_BIND_VERSION "@VER@"
File test3.sh added (mode: 100755) (index 0000000..7baa42f)
1 #!/bin/sh
2
3 export FORCE_NET_VERBOSE=999
4
5 #export FORCE_BIND_ADDRESS_V4=127.0.0.2
6 #export FORCE_BIND_PORT_V4=900
7
8 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
9
10 strace -o ${0}.strace -s200 -f "$@"
11 #debug "$@"
File test_getaddrinfo.c added (mode: 100644) (index 0000000..6c38346)
1 /*
2 * Copyright: Catalin(ux) M. BOIE
3 * Part of force_bind package
4 */
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/un.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <arpa/inet.h>
13 #include <netdb.h>
14
15 int main(void)
16 {
17 struct addrinfo hints;
18 struct addrinfo *result, *rp;
19 int s;
20 unsigned int i, len;
21 unsigned char *a;
22 struct sockaddr_in *a4;
23 struct sockaddr_in6 *a6;
24
25 memset(&hints, 0, sizeof(hints));
26 hints.ai_family = AF_UNSPEC;
27 hints.ai_socktype = SOCK_DGRAM;
28 hints.ai_flags = 0;
29 hints.ai_protocol = 0;
30
31 s = getaddrinfo("kernel.embedromix.ro", "http", &hints, &result);
32 if (s != 0) {
33 fprintf(stderr, "Error lookup: %s!\n", gai_strerror(s));
34 return 1;
35 }
36 printf("Host found!\n");
37
38 for (rp = result; rp != NULL; rp = rp->ai_next) {
39 printf("ai_family=%s ai_canonname=%s ai_addrlen=%u addr:",
40 rp->ai_family == AF_INET ? "v4" :
41 rp->ai_family == AF_INET6 ? "v6" : "unk",
42 rp->ai_canonname, rp->ai_addrlen);
43
44 if (rp->ai_family == AF_INET) {
45 a4 = (struct sockaddr_in *) rp->ai_addr;
46 a = (unsigned char *) &a4->sin_addr;
47 len = 4;
48 } else if (rp->ai_family == AF_INET6) {
49 a6 = (struct sockaddr_in6 *) rp->ai_addr;
50 a = (unsigned char *) &a6->sin6_addr;
51 len = 16;
52 } else
53 continue;
54
55 for (i = 0; i < len; i++)
56 printf(" %02hhx", a[i]);
57
58 printf("\n");
59 }
60 freeaddrinfo(result);
61
62 return 0;
63 }
File test_getaddrinfo.hosts added (mode: 100644) (index 0000000..34f4bd0)
1 2.2.2.2 bla2
2 1.1.1.1 kernel.embedromix.ro kernel bla
3 3.3.3.3 bla3
4 fd::3 blaipv6
File test_getaddrinfo.sh added (mode: 100755) (index 0000000..72470b8)
1 #!/bin/sh
2
3 set -e
4
5 ulimit -c2000000
6
7 make test_getaddrinfo
8
9 export FORCE_NET_VERBOSE=99
10 export FORCE_NET_HOSTS="${PWD}/test_getaddrinfo.hosts"
11
12 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
13
14 #export LD_DEBUG=symbols
15 #export LD_DEBUG_OUTPUT=test_gethostbyname.ld
16 #strace -s2000 -q -f -o test_gethostbyname.strace \
17 #valgrind \
18 #gdb \
19 ./test_getaddrinfo
20
21 ping -c1 kernel.embedromix.ro
File test_gethostbyname.c added (mode: 100644) (index 0000000..43de7e9)
1 /*
2 * This program test IPv6 stuff: flowinfo.
3 * Copyright: Catalin(ux) M. BOIE
4 * Part of force_bind package
5 */
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <sys/un.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <arpa/inet.h>
14 #include <netdb.h>
15
16 int main(void)
17 {
18 struct hostent *a;
19
20 a = gethostbyname("kernel.embedromix.ro");
21 if (!a) {
22 fprintf(stderr, "Error lookup: %s!\n", hstrerror(h_errno));
23 return 1;
24 }
25 printf("Host found!\n");
26
27 if (a->h_aliases[0])
28 printf("a->h_alias[0]=%s\n", a->h_aliases[0]);
29
30 printf("a->h_length=%d\n", a->h_length);
31
32 if (a->h_addr_list[0])
33 printf("a->h_addr_list[0]=%hhu.%hhu.%hhu.%hhu\n",
34 a->h_addr_list[0][0], a->h_addr_list[0][1],
35 a->h_addr_list[0][2], a->h_addr_list[0][3]);
36
37 return 0;
38 }
File test_gethostbyname.hosts added (mode: 100644) (index 0000000..8a5ff7c)
1 1.1.1.1 kernel.embedromix.ro kernel bla
File test_gethostbyname.sh added (mode: 100755) (index 0000000..62cdd44)
1 #!/bin/sh
2
3 set -e
4
5 make test_gethostbyname
6
7 export FORCE_NET_VERBOSE=99
8 export FORCE_NET_HOSTS="${PWD}/test_gethostbyname.hosts"
9
10 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
11
12 #export LD_DEBUG=symbols
13 #export LD_DEBUG_OUTPUT=test_gethostbyname.ld
14 #strace -s2000 -q -f -o test_gethostbyname.strace \
15 #valgrind \
16 ./test_gethostbyname
17
18 ping -c3 kernel.embedromix.ro
File test_inet_pton.sh copied from file test_client3.sh (similarity 54%) (mode: 100755) (index 32459ed..0cf1f94)
1 1 #!/bin/sh #!/bin/sh
2 2
3 make test_inet_pton
4
3 5 export FORCE_NET_VERBOSE=1 export FORCE_NET_VERBOSE=1
4 export FORCE_NET_PRIO=2
5 6
6 7 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so" export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
7 8
8 strace -o ${0}.strace -f -s100 ./test_client "$@"
9 export LD_DEBUG=all
10
11 ./test_inet_pton
Date/time (UTC) Type Misc Labels
2021-11-30 11:36 build fedora-34-aarch64 worker/r1 builder/color=fff worker_elap/878s wait_time/2325s date/2021-11-30 time/10:37
2021-11-30 11:42 build fedora-34-x86_64 worker/r1 builder/color=fff worker_elap/341s wait_time/3356s date/2021-11-30 time/10:40
2021-11-30 12:01 build fedora-35-aarch64 worker/r1 builder/color=fff worker_elap/870s wait_time/1883s date/2021-11-30 time/11:10
2021-11-30 12:08 build fedora-35-x86_64 worker/r1 builder/color=fff worker_elap/391s wait_time/2865s date/2021-11-30 time/11:13
2021-11-30 12:13 build rocky-8-x86_64 worker/r1 builder/color=fff worker_elap/280s wait_time/3136s date/2021-11-30 time/11:16
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/force_bind

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/force_bind

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/force_bind

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main