List of commits:
Subject Hash Author Date (UTC)
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
More duilder updates 83d91834796de59a679545c25d62a423d6f04f0e Catalin(ux) M. BOIE 2011-08-24 20:17:33
More stuff added to TODO aaf5da40115dc3ee2562f42522468f5bd9362012 Catalin(ux) M. BOIE 2011-08-24 20:17:11
Corrected a merge problem. bb0ce0b8b1c869572d15babb81543154f0c5db39 Catalin(ux) M. BOIE 2011-08-24 03:41:36
Bump version to 0.9. 97343f56db715658dc0fbf6179db0d300c5d8545 Catalin(ux) M. BOIE 2011-08-24 03:37:36
Remove the need for SO_DOMAIN because we can get domain from accepting socket. a027bcfd13a15a98dd2a5db924af77199e156c7f Catalin(ux) M. BOIE 2011-08-10 20:19:38
SO_MARK may not be defined by glibc. 2204bbcf4b4480008cabc0e330f64460a8995255 Catalin(ux) M. BOIE 2011-08-10 20:08:43
Removed some debugging leftovers. 3b71558fc26d7958f83362926555c1f4100a57ab Catalin(ux) M. BOIE 2011-08-23 22:18:02
Commit e11f13f4d11723f0c2c833ffbaca89e55d74e139 - Lots of changes
Author: Catalin(ux) M. BOIE
Author date (UTC): 2019-01-16 20:18
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2019-01-16 20:18
Parent(s): d84134f3193fd2d4c5298eaded8ffade5d74d220
Signing key:
Tree: 55ff6c77ff2c4c9d540dd53b01e95c33f2143730
File Lines added Lines deleted
.gitignore 1 0
Makefile.in 15 3
README 4 2
force_bind.c 152 106
force_bind.spec.in 1 1
test_bind.c 1 1
test_bind6.c 23 10
test_bind6.sh 3 4
File .gitignore changed (mode: 100644) (index 69a15ea..35830e1)
... ... Changelog*
3 3 *.so* *.so*
4 4 *.spec *.spec
5 5 test_bind test_bind
6 test_bind6
6 7 *.strace *.strace
7 8 send_udp send_udp
8 9 test_client test_client
File Makefile.in changed (mode: 100644) (index dbec961..142271e)
1 1 export CC := gcc export CC := gcc
2 2 export INCS += export INCS +=
3 3 export LIBS += export LIBS +=
4 export CFLAGS += -ggdb3 -Wall -Wextra -Wno-long-long -pipe
5 export CFLAGSSO = $(CFLAGS) -ldl -lc -shared -rdynamic -fpic
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
9 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
13 export CFLAGSSO = $(CFLAGS) -ldl -lc -shared -rdynamic
14
6 15
7 16 .PHONY: all .PHONY: all
8 17 all: force_bind.so all: force_bind.so
9 18
10 19 force_bind.so: force_bind.c force_bind_config.h force_bind.so: force_bind.c force_bind_config.h
11 $(CC) $(CFLAGSSO) -Wl,-soname,force_bind.so -o $@ force_bind.c
20 $(CC) $(CFLAGSSO) -fPIC -Wl,-soname,force_bind.so -o $@ force_bind.c
12 21
13 22 test_bind: test_bind.c test_bind: test_bind.c
14 23 $(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@
15 24
25 test_bind6: test_bind6.c
26 $(CC) $(CFLAGS) $< -o $@
27
16 28 send_udp: send_udp.c send_udp: send_udp.c
17 29 $(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@
18 30
File README changed (mode: 100644) (index a2eefad..68d1b9f)
1 1 Name: force_bind Name: force_bind
2 2
3 Author: Catali(ux) M. BOIE - catab at embedromix dot ro
3 Author: Catalin(ux) M. BOIE - catab at embedromix dot ro
4 4
5 5 Start date: 2010-10-26 Start date: 2010-10-26
6 6
7 7 Description: Force binding on a specific IP and/or port. Description: Force binding on a specific IP and/or port.
8 Plus forcing setsockopt calls on the socket.
8 9 Works with both IPv4 and IPv6. Works with both IPv4 and IPv6.
9 10 It is useful if you have a binary application without sources It is useful if you have a binary application without sources
10 11 and without the possibility to configure address or port to and without the possibility to configure address or port to
 
... ... Examples:
19 20 0. Output debug stuff in a log file (for debugging): 0. Output debug stuff in a log file (for debugging):
20 21 export FORCE_NET_VERBOSE=999 export FORCE_NET_VERBOSE=999
21 22 export FORCE_NET_LOG="xxx.log" export FORCE_NET_LOG="xxx.log"
23 export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so
22 24 your_program_here your_program_here
23 25
24 26 1. Force bind to 127.0.0.1, port 33, verbose operations: 1. Force bind to 127.0.0.1, port 33, verbose operations:
 
... ... Examples:
92 94 ::1.56981 > ::1.krb524: Flags [S], cksum 0x0030 (incorrect -> 0x91cf), ::1.56981 > ::1.krb524: Flags [S], cksum 0x0030 (incorrect -> 0x91cf),
93 95 seq 1154252590, win 32752, options [mss 16376,sackOK,TS val 28395104 ecr 0,nop,wscale 4], length 0 seq 1154252590, win 32752, options [mss 16376,sackOK,TS val 28395104 ecr 0,nop,wscale 4], length 0
94 96
95 13. Force FWMARK on a connection (only root is allowed):
97 13. Force FWMARK on a connection (only root can do it):
96 98 export FORCE_NET_VERBOSE=1 export FORCE_NET_VERBOSE=1
97 99 export FORCE_NET_FWMARK=0x1234 export FORCE_NET_FWMARK=0x1234
98 100 export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so
File force_bind.c changed (mode: 100644) (index d0c3e3b..08980e9)
... ... static ssize_t (*old_send)(int sockfd, const void *buf, size_t len, int flags)
110 110 static ssize_t (*old_sendto)(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); static ssize_t (*old_sendto)(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
111 111 static ssize_t (*old_sendmsg)(int sockfd, const struct msghdr *msg, int flags); static ssize_t (*old_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
112 112 static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen); static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
113 static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
113 114 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);
114 115 static int (*old_poll)(struct pollfd *fds, nfds_t nfds, int timeout); static int (*old_poll)(struct pollfd *fds, nfds_t nfds, int timeout);
115 116
 
... ... static char *sprotocol(const int protocol)
168 169
169 170 switch (protocol) { switch (protocol) {
170 171 case IPPROTO_TCP: return "tcp"; case IPPROTO_TCP: return "tcp";
172 case IPPROTO_UDP: return "udp";
171 173 default: snprintf(tmp, sizeof(tmp), "%d", protocol); return tmp; default: snprintf(tmp, sizeof(tmp), "%d", protocol); return tmp;
172 174 } }
173 175 } }
 
... ... static char *sprotocol(const int protocol)
175 177 /* /*
176 178 * Fills @out with domain/type/address/port string * Fills @out with domain/type/address/port string
177 179 */ */
178 static void saddr(char *out, const int out_len,
180 static void saddr(char *out, const size_t out_len,
179 181 const struct sockaddr_storage *ss) const struct sockaddr_storage *ss)
180 182 { {
181 183 struct sockaddr_in *s4; struct sockaddr_in *s4;
 
... ... static void xlog(const unsigned int level, const char *format, ...)
218 220 va_end(ap); va_end(ap);
219 221 } }
220 222
221 void dump(const int level, const char *title, const void *buf,
223 static void dump(const unsigned int level, const char *title, const void *buf,
222 224 const unsigned int len) const unsigned int len)
223 225 { {
224 226 unsigned int i; unsigned int i;
 
... ... void dump(const int level, const char *title, const void *buf,
228 230 for (i = 0; i < len; i++) for (i = 0; i < len; i++)
229 231 snprintf(out + i * 3, 4, " %02x", buf2[i]); snprintf(out + i * 3, 4, " %02x", buf2[i]);
230 232
231 xlog(level, "dump %s:%s\n", title, out);
233 xlog(level, "force_bind: dump %s:%s\n", title, out);
232 234 } }
233 235
234 236 static struct node *get(const int fd) static struct node *get(const int fd)
 
... ... static struct node *get(const int fd)
249 251 /* /*
250 252 * List all sockets * List all sockets
251 253 */ */
252 static void list(const int level)
254 static void list(const unsigned int level)
253 255 { {
254 256 struct node *q; struct node *q;
255 257 struct private *p; struct private *p;
256 258 char dest[128]; char dest[128];
257 259
258 xlog(level, "list...\n");
260 xlog(level, "force_bind: list...\n");
259 261
260 262 q = fdinfo.head; q = fdinfo.head;
261 263 while (q != NULL) { while (q != NULL) {
 
... ... static void add(const int fd, const struct private *p)
278 280 { {
279 281 struct node *q; struct node *q;
280 282
281 xlog(2, "add(fd=%d, ...)\n", fd);
283 xlog(2, "force_bind: add(fd=%d, ...)\n", fd);
282 284
283 285 /* do we have a copy? */ /* do we have a copy? */
284 286 q = get(fd); q = get(fd);
 
... ... static void add(const int fd, const struct private *p)
297 299 if (q == NULL) { if (q == NULL) {
298 300 q = (struct node *) malloc(sizeof(struct node)); q = (struct node *) malloc(sizeof(struct node));
299 301 if (q == NULL) { if (q == NULL) {
300 xlog(0, "Cannot alloc memory; ignore fd!\n");
302 xlog(0, "force_bind: cannot alloc memory"
303 "; ignore fd!\n");
301 304 return; return;
302 305 } }
303 306
 
... ... static void add(const int fd, const struct private *p)
321 324 gettimeofday(&q->priv.last, NULL); gettimeofday(&q->priv.last, NULL);
322 325 } }
323 326
324 list(2);
327 list(10);
325 328 } }
326 329
327 330 static void del(const int fd) static void del(const int fd)
328 331 { {
329 332 struct node *p; struct node *p;
330 333
331 xlog(2, "del(fd=%d)\n", fd);
334 xlog(2, "force_bind: del(fd=%d)\n", fd);
332 335
333 336 p = fdinfo.head; p = fdinfo.head;
334 337 while (p != NULL) { while (p != NULL) {
 
... ... static void init(void)
362 365 log_file = getenv("FORCE_NET_LOG"); log_file = getenv("FORCE_NET_LOG");
363 366 if (log_file != NULL) { if (log_file != NULL) {
364 367 Log = fopen(log_file, "w"); Log = fopen(log_file, "w");
365 setlinebuf(Log);
368 if (Log)
369 setlinebuf(Log);
370 } else {
371 Log = stderr;
366 372 } }
367 373
368 374 x = getenv("FORCE_NET_VERBOSE"); x = getenv("FORCE_NET_VERBOSE");
369 375 if (x != NULL) if (x != NULL)
370 verbose = strtol(x, NULL, 10);
376 verbose = (unsigned int) strtoul(x, NULL, 10);
371 377
372 xlog(1, "Init started...\n");
373 xlog(0, "Version: %s\n", FORCE_BIND_VERSION);
378 xlog(1, "force_bind: init started...\n");
379 xlog(1, "force_bind: version: %s\n", FORCE_BIND_VERSION);
374 380
375 381 x = getenv("FORCE_BIND_ADDRESS_V4"); x = getenv("FORCE_BIND_ADDRESS_V4");
376 382 if (x != NULL) { if (x != NULL) {
377 383 force_address_v4 = x; force_address_v4 = x;
378 xlog(1, "Force bind to IPv4 address \"%s\".\n",
384 xlog(1, "force_bind: conf: binding to IPv4 address \"%s\".\n",
379 385 force_address_v4); force_address_v4);
380 386 } }
381 387
382 388 x = getenv("FORCE_BIND_ADDRESS_V6"); x = getenv("FORCE_BIND_ADDRESS_V6");
383 389 if (x != NULL) { if (x != NULL) {
384 390 force_address_v6 = x; force_address_v6 = x;
385 xlog(1, "Force bind to IPv6 address \"%s\".\n",
391 xlog(1, "force_bind: conf: binding to IPv6 address \"%s\".\n",
386 392 force_address_v6); force_address_v6);
387 393 } }
388 394
 
... ... static void init(void)
391 397 if (x != NULL) { if (x != NULL) {
392 398 force_address_v4 = x; force_address_v4 = x;
393 399 force_address_v6 = x; force_address_v6 = x;
394 xlog(1, "Force bind to address \"%s\"."
400 xlog(1, "force_bind: conf: binding to address \"%s\"."
395 401 " Obsolete, use FORCE_BIND_ADDRESS_V4/6.\n", " Obsolete, use FORCE_BIND_ADDRESS_V4/6.\n",
396 402 force_address_v4); force_address_v4);
397 403 } }
398 404
399 405 x = getenv("FORCE_BIND_PORT_V4"); x = getenv("FORCE_BIND_PORT_V4");
400 406 if (x != NULL) { if (x != NULL) {
401 force_port_v4 = strtol(x, NULL, 10);
402 xlog(1, "Force bind to port %d.\n",
407 force_port_v4 = (int) strtol(x, NULL, 10);
408 xlog(1, "force_bind: conf: binding to port %d.\n",
403 409 force_port_v4); force_port_v4);
404 410 } }
405 411
406 412 x = getenv("FORCE_BIND_PORT_V6"); x = getenv("FORCE_BIND_PORT_V6");
407 413 if (x != NULL) { if (x != NULL) {
408 force_port_v6 = strtol(x, NULL, 10);
409 xlog(1, "Force bind to port %d.\n",
414 force_port_v6 = (int) strtol(x, NULL, 10);
415 xlog(1, "force_bind: conf: binding to port %d.\n",
410 416 force_port_v6); force_port_v6);
411 417 } }
412 418
413 419 /* obsolete mode */ /* obsolete mode */
414 420 x = getenv("FORCE_BIND_PORT"); x = getenv("FORCE_BIND_PORT");
415 421 if (x != NULL) { if (x != NULL) {
416 force_port_v4 = strtol(x, NULL, 10);
417 force_port_v6 = strtol(x, NULL, 10);
418 xlog(1, "Force bind to port %d."
422 force_port_v4 = (int) strtol(x, NULL, 10);
423 force_port_v6 = (int) strtol(x, NULL, 10);
424 xlog(1, "force_bind: conf: binding to port %d."
419 425 " Obsolete, use FORCE_BIND_PORT_V4/6.\n", " Obsolete, use FORCE_BIND_PORT_V4/6.\n",
420 426 force_port_v4); force_port_v4);
421 427 } }
 
... ... static void init(void)
424 430 x = getenv("FORCE_NET_TOS"); x = getenv("FORCE_NET_TOS");
425 431 if (x != NULL) { if (x != NULL) {
426 432 force_tos = 1; force_tos = 1;
427 tos = strtoul(x, NULL, 0);
428 xlog(1, "Force TOS to %hhu.\n",
433 tos = (unsigned int) strtoul(x, NULL, 0);
434 xlog(1, "force_bind: conf: forcing TOS to %hhu.\n",
429 435 tos); tos);
430 436 } }
431 437
 
... ... static void init(void)
433 439 x = getenv("FORCE_NET_TTL"); x = getenv("FORCE_NET_TTL");
434 440 if (x != NULL) { if (x != NULL) {
435 441 force_ttl = 1; force_ttl = 1;
436 ttl = strtoul(x, NULL, 0);
437 xlog(1, "Force TTL to %hhu.\n",
442 ttl = (unsigned int) strtoul(x, NULL, 0);
443 xlog(1, "force_bind: conf: forcing TTL to %hhu.\n",
438 444 ttl); ttl);
439 445 } }
440 446
 
... ... static void init(void)
442 448 x = getenv("FORCE_NET_KA"); x = getenv("FORCE_NET_KA");
443 449 if (x != NULL) { if (x != NULL) {
444 450 force_keepalive = 1; force_keepalive = 1;
445 keepalive = strtoul(x, NULL, 0);
446 xlog(1, "Force KA to %u.\n",
451 keepalive = (unsigned int) strtoul(x, NULL, 0);
452 xlog(1, "force_bind: conf: forcing KA to %u.\n",
447 453 keepalive); keepalive);
448 454 } }
449 455
 
... ... static void init(void)
451 457 x = getenv("FORCE_NET_MSS"); x = getenv("FORCE_NET_MSS");
452 458 if (x != NULL) { if (x != NULL) {
453 459 force_mss = 1; force_mss = 1;
454 mss = strtoul(x, NULL, 0);
455 xlog(1, "Force MSS to %u.\n",
460 mss = (unsigned int) strtoul(x, NULL, 0);
461 xlog(1, "force_bind: conf: forcing MSS to %u.\n",
456 462 mss); mss);
457 463 } }
458 464
 
... ... static void init(void)
460 466 x = getenv("FORCE_NET_REUSEADDR"); x = getenv("FORCE_NET_REUSEADDR");
461 467 if (x != NULL) { if (x != NULL) {
462 468 force_reuseaddr = 1; force_reuseaddr = 1;
463 reuseaddr = strtoul(x, NULL, 0);
464 xlog(1, "Force REUSEADDR to %u.\n",
469 reuseaddr = (unsigned int) strtoul(x, NULL, 0);
470 xlog(1, "force_bind: conf: forcing REUSEADDR to %u.\n",
465 471 reuseaddr); reuseaddr);
466 472 } }
467 473
 
... ... static void init(void)
469 475 x = getenv("FORCE_NET_NODELAY"); x = getenv("FORCE_NET_NODELAY");
470 476 if (x != NULL) { if (x != NULL) {
471 477 force_nodelay = 1; force_nodelay = 1;
472 nodelay = strtoul(x, NULL, 0);
473 xlog(1, "Force NODELAY to %u.\n",
478 nodelay = (unsigned int) strtoul(x, NULL, 0);
479 xlog(1, "force_bind: conf: forcing NODELAY to %u.\n",
474 480 nodelay); nodelay);
475 481 } }
476 482
477 483 /* bandwidth */ /* bandwidth */
478 484 x = getenv("FORCE_NET_BW"); x = getenv("FORCE_NET_BW");
479 485 if (x != NULL) { if (x != NULL) {
480 bw_global.limit = strtoul(x, NULL, 0);
486 bw_global.limit = (unsigned int) strtoul(x, NULL, 0);
481 487 gettimeofday(&bw_global.last, NULL); gettimeofday(&bw_global.last, NULL);
482 488 bw_global.rest = 0; bw_global.rest = 0;
483 xlog(1, "Force bandwidth to %llub/s.\n",
489 xlog(1, "force_bind: conf: forcing bandwidth to %llub/s.\n",
484 490 bw_global.limit); bw_global.limit);
485 491 } else { } else {
486 492 bw_global.limit = 0; bw_global.limit = 0;
 
... ... static void init(void)
490 496 x = getenv("FORCE_NET_BW_PER_SOCKET"); x = getenv("FORCE_NET_BW_PER_SOCKET");
491 497 if (x != NULL) { if (x != NULL) {
492 498 if (bw_global.limit > 0) { if (bw_global.limit > 0) {
493 xlog(1, "Cannot set limit per socket"
499 xlog(1, "force_bind: conf: cannot set limit per socket"
494 500 " when global one is set.\n"); " when global one is set.\n");
495 501 } else { } else {
496 bw_limit_per_socket = strtoul(x, NULL, 0);
497 xlog(1, "Force bandwidth per socket to %llub/s.\n",
502 bw_limit_per_socket = (unsigned int) strtoul(x, NULL, 0);
503 xlog(1, "force_bind: conf: forcing bandwidth per socket to %llub/s.\n",
498 504 bw_limit_per_socket); bw_limit_per_socket);
499 505 } }
500 506 } }
 
... ... static void init(void)
503 509 x = getenv("FORCE_NET_FLOWINFO"); x = getenv("FORCE_NET_FLOWINFO");
504 510 if (x != NULL) { if (x != NULL) {
505 511 force_flowinfo = 1; force_flowinfo = 1;
506 flowinfo = strtoul(x, NULL, 0) & IPV6_FLOWINFO_MASK;
507 xlog(1, "Force FLOWINFO to 0x%x.\n",
512 flowinfo = (unsigned int) strtoul(x, NULL, 0) & IPV6_FLOWINFO_MASK;
513 xlog(1, "force_bind: conf: forcing FLOWINFO to 0x%x.\n",
508 514 flowinfo); flowinfo);
509 515 } }
510 516
 
... ... static void init(void)
512 518 x = getenv("FORCE_NET_FWMARK"); x = getenv("FORCE_NET_FWMARK");
513 519 if (x != NULL) { if (x != NULL) {
514 520 force_fwmark = 1; force_fwmark = 1;
515 fwmark = strtoul(x, NULL, 0);
516 xlog(1, "Force fwmark to 0x%x.\n",
521 fwmark = (unsigned int) strtoul(x, NULL, 0);
522 xlog(1, "force_bind: conf: forcing fwmark to 0x%x.\n",
517 523 fwmark); fwmark);
518 524 } }
519 525
 
... ... static void init(void)
521 527 x = getenv("FORCE_NET_PRIO"); x = getenv("FORCE_NET_PRIO");
522 528 if (x != NULL) { if (x != NULL) {
523 529 force_prio = 1; force_prio = 1;
524 prio = strtoul(x, NULL, 0);
525 xlog(1, "Force prio to %u.\n",
530 prio = (unsigned int) strtoul(x, NULL, 0);
531 xlog(1, "force_bind: conf: forcing prio to %u.\n",
526 532 prio); prio);
527 533 } }
528 534
529 535 /* poll timeout */ /* poll timeout */
530 536 x = getenv("FORCE_NET_POLL_TIMEOUT"); x = getenv("FORCE_NET_POLL_TIMEOUT");
531 537 if (x != NULL) { if (x != NULL) {
532 force_poll_timeout = strtoul(x, NULL, 0);
533 xlog(1, "Force poll timeout to %d.\n",
538 force_poll_timeout = (int) strtoul(x, NULL, 0);
539 xlog(1, "force_bind: conf: forcing poll timeout to %d.\n",
534 540 force_poll_timeout); force_poll_timeout);
535 541 } }
536 542
 
... ... static void init(void)
538 544
539 545 old_bind = dlsym(RTLD_NEXT, "bind"); old_bind = dlsym(RTLD_NEXT, "bind");
540 546 if (old_bind == NULL) { if (old_bind == NULL) {
541 xlog(0, "Cannot resolve 'bind'!\n");
547 xlog(0, "force_bind: cannot resolve 'bind'!\n");
542 548 exit(1); exit(1);
543 549 } }
544 550
545 551 old_setsockopt = dlsym(RTLD_NEXT, "setsockopt"); old_setsockopt = dlsym(RTLD_NEXT, "setsockopt");
546 552 if (old_setsockopt == NULL) { if (old_setsockopt == NULL) {
547 xlog(0, "Cannot resolve 'setsockopt'!\n");
553 xlog(0, "force_bind: cannot resolve 'setsockopt'!\n");
548 554 exit(1); exit(1);
549 555 } }
550 556
551 557 old_socket = dlsym(RTLD_NEXT, "socket"); old_socket = dlsym(RTLD_NEXT, "socket");
552 558 if (old_socket == NULL) { if (old_socket == NULL) {
553 xlog(0, "Cannot resolve 'socket'!\n");
559 xlog(0, "force_bind: cannot resolve 'socket'!\n");
554 560 exit(1); exit(1);
555 561 } }
556 562
557 563 old_close = dlsym(RTLD_NEXT, "close"); old_close = dlsym(RTLD_NEXT, "close");
558 564 if (old_close == NULL) { if (old_close == NULL) {
559 xlog(0, "Cannot resolve 'close'!\n");
565 xlog(0, "force_bind: cannot resolve 'close'!\n");
560 566 exit(1); exit(1);
561 567 } }
562 568
563 569 old_write = dlsym(RTLD_NEXT, "write"); old_write = dlsym(RTLD_NEXT, "write");
564 570 if (old_write == NULL) { if (old_write == NULL) {
565 xlog(0, "Cannot resolve 'write'!\n");
571 xlog(0, "force_bind: cannot resolve 'write'!\n");
566 572 exit(1); exit(1);
567 573 } }
568 574
569 575 old_send = dlsym(RTLD_NEXT, "send"); old_send = dlsym(RTLD_NEXT, "send");
570 576 if (old_send == NULL) { if (old_send == NULL) {
571 xlog(0, "Cannot resolve 'send'!\n");
577 xlog(0, "force_bind: cannot resolve 'send'!\n");
572 578 exit(1); exit(1);
573 579 } }
574 580
575 581 old_sendto = dlsym(RTLD_NEXT, "sendto"); old_sendto = dlsym(RTLD_NEXT, "sendto");
576 582 if (old_sendto == NULL) { if (old_sendto == NULL) {
577 xlog(0, "Cannot resolve 'sendto'!\n");
583 xlog(0, "force_bind: cannot resolve 'sendto'!\n");
578 584 exit(1); exit(1);
579 585 } }
580 586
581 587 old_sendmsg = dlsym(RTLD_NEXT, "sendmsg"); old_sendmsg = dlsym(RTLD_NEXT, "sendmsg");
582 588 if (old_sendmsg == NULL) { if (old_sendmsg == NULL) {
583 xlog(0, "Cannot resolve 'sendmsg'!\n");
589 xlog(0, "force_bind: cannot resolve 'sendmsg'!\n");
584 590 exit(1); exit(1);
585 591 } }
586 592
587 593 old_accept = dlsym(RTLD_NEXT, "accept"); old_accept = dlsym(RTLD_NEXT, "accept");
588 594 if (old_accept == NULL) { if (old_accept == NULL) {
589 xlog(0, "Cannot resolve 'accept'!\n");
595 xlog(0, "force_bind: cannot resolve 'accept'!\n");
596 exit(1);
597 }
598
599 old_accept4 = dlsym(RTLD_NEXT, "accept4");
600 if (old_accept4 == NULL) {
601 xlog(0, "force_bind: cannot resolve 'accept4'!\n");
590 602 exit(1); exit(1);
591 603 } }
592 604
593 605 old_connect = dlsym(RTLD_NEXT, "connect"); old_connect = dlsym(RTLD_NEXT, "connect");
594 606 if (old_connect == NULL) { if (old_connect == NULL) {
595 xlog(0, "Cannot resolve 'connect'!\n");
607 xlog(0, "force_bind: cannot resolve 'connect'!\n");
596 608 exit(1); exit(1);
597 609 } }
598 610
599 611 old_poll = dlsym(RTLD_NEXT, "poll"); old_poll = dlsym(RTLD_NEXT, "poll");
600 612 if (old_poll == NULL) { if (old_poll == NULL) {
601 xlog(0, "Cannot resolve 'poll'!\n");
613 xlog(0, "force_bind: cannot resolve 'poll'!\n");
602 614 exit(1); exit(1);
603 615 } }
604 616
605 xlog(1, "Init ended.\n");
617 xlog(1, "force_bind: init ended.\n");
606 618 } }
607 619
608 620 static int set_ka(int sockfd) static int set_ka(int sockfd)
 
... ... static int set_ka(int sockfd)
614 626
615 627 flag = (keepalive > 0) ? 1 : 0; flag = (keepalive > 0) ? 1 : 0;
616 628 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag));
617 xlog(1, "changing SO_KEEPALIVE to %d (ret=%d(%s)) [%d].\n",
629 xlog(1, "force_bind: changing SO_KEEPALIVE to %d (ret=%d(%s)) [%d].\n",
618 630 flag, ret, strerror(errno), sockfd); flag, ret, strerror(errno), sockfd);
619 631
620 632 return ret; return ret;
 
... ... static int set_ka_idle(int sockfd)
628 640 return 0; return 0;
629 641
630 642 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, sizeof(keepalive)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, sizeof(keepalive));
631 xlog(1, "changing TCP_KEEPIDLE to %us (ret=%d(%s)) [%d].\n",
643 xlog(1, "force_bind: changing TCP_KEEPIDLE to %us (ret=%d(%s)) [%d].\n",
632 644 keepalive, ret, strerror(errno), sockfd); keepalive, ret, strerror(errno), sockfd);
633 645
634 646 return ret; return ret;
 
... ... static int set_mss(int sockfd)
642 654 return 0; return 0;
643 655
644 656 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss));
645 xlog(1, "changing MSS to %u (ret=%d(%s)) [%d].\n",
657 xlog(1, "force_bind: changing MSS to %u (ret=%d(%s)) [%d].\n",
646 658 mss, ret, strerror(errno), sockfd); mss, ret, strerror(errno), sockfd);
647 659
648 660 return ret; return ret;
 
... ... static int set_tos(int sockfd)
656 668 return 0; return 0;
657 669
658 670 ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
659 xlog(1, "changing TOS to %hhu (ret=%d(%s)) [%d].\n",
671 xlog(1, "force_bind: changing TOS to %hhu (ret=%d(%s)) [%d].\n",
660 672 tos, ret, strerror(errno), sockfd); tos, ret, strerror(errno), sockfd);
661 673
662 674 return ret; return ret;
 
... ... static int set_ttl(int sockfd)
670 682 return 0; return 0;
671 683
672 684 ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
673 xlog(1, "changing TTL to %hhu (ret=%d(%s)) [%d].\n",
685 xlog(1, "force_bind: changing TTL to %hhu (ret=%d(%s)) [%d].\n",
674 686 ttl, ret, strerror(errno), sockfd); ttl, ret, strerror(errno), sockfd);
675 687
676 688 return ret; return ret;
 
... ... static int set_reuseaddr(int sockfd)
684 696 return 0; return 0;
685 697
686 698 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
687 xlog(1, "changing reuseaddr to %u (ret=%d(%s)) [%d].\n",
699 xlog(1, "force_bind: changing reuseaddr to %u (ret=%d(%s)) [%d].\n",
688 700 reuseaddr, ret, strerror(errno), sockfd); reuseaddr, ret, strerror(errno), sockfd);
689 701
690 702 return ret; return ret;
 
... ... static int set_nodelay(int sockfd)
698 710 return 0; return 0;
699 711
700 712 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
701 xlog(1, "changing nodelay to %u (ret=%d(%s)) [%d].\n",
713 xlog(1, "force_bind: changing nodelay to %u (ret=%d(%s)) [%d].\n",
702 714 nodelay, ret, strerror(errno), sockfd); nodelay, ret, strerror(errno), sockfd);
703 715
704 716 return ret; return ret;
 
... ... static void set_flowinfo(int sockfd, struct private *p)
735 747 mgr.flr_share = IPV6_FL_S_ANY; mgr.flr_share = IPV6_FL_S_ANY;
736 748 mgr.flr_flags = IPV6_FL_F_CREATE; mgr.flr_flags = IPV6_FL_F_CREATE;
737 749 ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &mgr, sizeof(mgr)); ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &mgr, sizeof(mgr));
738 xlog(1, "flow mgr (ret=%d(%s)) [%d].\n",
750 xlog(1, "force_bind: flow mgr (ret=%d(%s)) [%d].\n",
739 751 ret, strerror(errno), sockfd); ret, strerror(errno), sockfd);
740 752
741 753 yes = 1; yes = 1;
742 754 ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &yes, sizeof(yes)); ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &yes, sizeof(yes));
743 xlog(1, "changing flowinfo to 'yes' (ret=%d(%s)) [%d].\n",
755 xlog(1, "force_bind: changing flowinfo to 'yes' (ret=%d(%s)) [%d].\n",
744 756 ret, strerror(errno), sockfd); ret, strerror(errno), sockfd);
745 757 } }
746 758
 
... ... static int set_fwmark(int sockfd)
752 764 return 0; return 0;
753 765
754 766 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark));
755 xlog(1, "changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
767 xlog(1, "force_bind: changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
756 768 fwmark, ret, strerror(errno), sockfd); fwmark, ret, strerror(errno), sockfd);
757 769
758 770 return ret; return ret;
 
... ... static int set_prio(int sockfd)
766 778 return 0; return 0;
767 779
768 780 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));
769 xlog(1, "changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
781 xlog(1, "force_bind: changing fwmark to 0x%x (ret=%d(%s)) [%d].\n",
770 782 prio, ret, strerror(errno), sockfd); prio, ret, strerror(errno), sockfd);
771 783
772 784 return ret; return ret;
 
... ... static int alter_sa(const int sockfd, struct sockaddr *sa)
786 798 int force_port; int force_port;
787 799 int err, ret = 0; int err, ret = 0;
788 800
789 xlog(2, "alter_sa(sockfd=%d, ...)\n", sockfd);
801 xlog(2, "force_bind: alter_sa(sockfd=%d, ...)\n", sockfd);
790 802
791 803 switch (sa->sa_family) { switch (sa->sa_family) {
792 804 case AF_INET: case AF_INET:
 
... ... static int alter_sa(const int sockfd, struct sockaddr *sa)
806 818 break; break;
807 819
808 820 default: default:
809 xlog(1, "unsupported family=%u [%d]!\n",
821 xlog(1, "force_bind: unsupported family=%u [%d]!\n",
810 822 sa->sa_family, sockfd); sa->sa_family, sockfd);
811 823 return 0; return 0;
812 824 } }
 
... ... static int alter_sa(const int sockfd, struct sockaddr *sa)
814 826 if (force_address != NULL) { if (force_address != NULL) {
815 827 err = inet_pton(sa->sa_family, force_address, p); err = inet_pton(sa->sa_family, force_address, p);
816 828 if (err != 1) { if (err != 1) {
817 xlog(1, "cannot convert [%s] (%d) (%s) [%d]!\n",
829 xlog(1, "force_bind: cannot convert [%s] (%d) (%s) [%d]!\n",
818 830 force_address, err, strerror(errno), sockfd); force_address, err, strerror(errno), sockfd);
819 831 return 0; return 0;
820 832 } }
 
... ... static void alter_dest_sa(int sockfd, struct sockaddr_storage *ss, socklen_t len
841 853 init(); init();
842 854
843 855 saddr(addr, sizeof(addr), ss); saddr(addr, sizeof(addr), ss);
844 xlog(2, "alter_dest_sa(sockfd=%d, addr=%s)\n",
856 xlog(2, "force_bind: alter_dest_sa(sockfd=%d, addr=%s)\n",
845 857 sockfd, addr); sockfd, addr);
846 858
847 859 /* We do not touch non network sockets */ /* We do not touch non network sockets */
 
... ... static void alter_dest_sa(int sockfd, struct sockaddr_storage *ss, socklen_t len
853 865 case AF_INET6: case AF_INET6:
854 866 sa6 = (struct sockaddr_in6 *) ss; sa6 = (struct sockaddr_in6 *) ss;
855 867 if (force_flowinfo == 1) { if (force_flowinfo == 1) {
856 xlog(1, "changing flowinfo from 0x%x to 0x%x [%d]!\n",
868 xlog(1, "force_bind: changing flowinfo from 0x%x to 0x%x [%d]!\n",
857 869 ntohl(sa6->sin6_flowinfo), flowinfo, sockfd); ntohl(sa6->sin6_flowinfo), flowinfo, sockfd);
858 870 sa6->sin6_flowinfo = htonl(flowinfo); sa6->sin6_flowinfo = htonl(flowinfo);
859 871 } }
 
... ... static void change_local_binding(int sockfd)
879 891
880 892 init(); init();
881 893
882 xlog(2, "change_local_binding(sockfd=%d)\n", sockfd);
894 xlog(2, "force_bind: change_local_binding(sockfd=%d)\n", sockfd);
883 895
884 896 /* We do not touch non network sockets */ /* We do not touch non network sockets */
885 897 q = get(sockfd); q = get(sockfd);
 
... ... static void change_local_binding(int sockfd)
893 905 tmp_len = sizeof(struct sockaddr_storage); tmp_len = sizeof(struct sockaddr_storage);
894 906 err = getsockname(sockfd, (struct sockaddr *) &tmp, &tmp_len); err = getsockname(sockfd, (struct sockaddr *) &tmp, &tmp_len);
895 907 if (err != 0) { if (err != 0) {
896 xlog(1, "Cannot get socket name err=%d (%s) [%d]!\n",
908 xlog(1, "force_bind: cannot get socket name err=%d (%s) [%d]!\n",
897 909 err, strerror(errno), sockfd); err, strerror(errno), sockfd);
898 910 return; return;
899 911 } }
 
... ... static void change_local_binding(int sockfd)
904 916 err = old_bind(sockfd, (struct sockaddr *) &tmp, tmp_len); err = old_bind(sockfd, (struct sockaddr *) &tmp, tmp_len);
905 917 q->priv.flags |= FB_FLAGS_BIND_CALLED; q->priv.flags |= FB_FLAGS_BIND_CALLED;
906 918 if (err != 0) if (err != 0)
907 xlog(1, "Cannot bind err=%d (%s) [%d]!\n",
919 xlog(1, "force_bind: cannot bind err=%d (%s) [%d]!\n",
908 920 err, strerror(errno), sockfd); err, strerror(errno), sockfd);
909 921 } }
910 922
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
918 930 init(); init();
919 931
920 932 saddr(tmp, sizeof(tmp), (struct sockaddr_storage *) addr); saddr(tmp, sizeof(tmp), (struct sockaddr_storage *) addr);
921 xlog(1, "bind(sockfd=%d, %s)\n", sockfd, tmp);
933 xlog(1, "force_bind: bind(sockfd=%d, %s)\n", sockfd, tmp);
922 934
923 935 memcpy(&new, addr, addrlen); memcpy(&new, addr, addrlen);
924 936
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
938 950
939 951 /* Test if we should deny the bind */ /* Test if we should deny the bind */
940 952 if (force_address && (strcmp(force_address, "deny") == 0)) { if (force_address && (strcmp(force_address, "deny") == 0)) {
941 xlog(1, "\tDeny binding to %s\n", tmp);
953 xlog(1, "force_bind: deny binding to %s\n", tmp);
942 954 errno = EACCES; errno = EACCES;
943 955 return -1; return -1;
944 956 } }
945 957
946 958 if (force_address && (strcmp(force_address, "fake") == 0)) { if (force_address && (strcmp(force_address, "fake") == 0)) {
947 xlog(1, "\tFake binding to %s\n", tmp);
959 xlog(1, "force_bind: fake binding to %s\n", tmp);
948 960 return 0; return 0;
949 961 } }
950 962
 
... ... int setsockopt(int sockfd, int level, int optname, const void *optval,
993 1005 /* /*
994 1006 * Helper called when a socket is created: socket, accept * Helper called when a socket is created: socket, accept
995 1007 */ */
996 void socket_create_callback(const int sockfd, int domain, int type)
1008 static void socket_create_callback(const int sockfd, int domain, int type)
997 1009 { {
998 1010 struct private p; struct private p;
999 1011
1000 1012 init(); init();
1001 1013
1002 xlog(2, "socket_create_callback(%d, %s, %s)\n",
1014 xlog(2, "force_bind: socket_create_callback(%d, %s, %s)\n",
1003 1015 sockfd, sdomain(domain), stype(type)); sockfd, sdomain(domain), stype(type));
1004 1016
1005 1017 set_tos(sockfd); set_tos(sockfd);
 
... ... int socket(int domain, int type, int protocol)
1033 1045
1034 1046 init(); init();
1035 1047
1036 xlog(1, "socket(domain=%s, type=%s, protocol=%s)\n",
1048 xlog(1, "force_bind: socket(domain=%s, type=%s, protocol=%s)\n",
1037 1049 sdomain(domain), stype(type), sprotocol(protocol)); sdomain(domain), stype(type), sprotocol(protocol));
1038 1050
1039 1051 sockfd = old_socket(domain, type, protocol); sockfd = old_socket(domain, type, protocol);
 
... ... static void bw(const int sockfd, const ssize_t bytes)
1052 1064 { {
1053 1065 struct timeval now; struct timeval now;
1054 1066 struct timespec ts, rest; struct timespec ts, rest;
1055 long long allowed;
1067 unsigned long long allowed;
1056 1068 long long diff_ms, sleep_ms; long long diff_ms, sleep_ms;
1057 1069 int err; int err;
1058 1070 struct node *q; struct node *q;
1059 1071 struct private *p; struct private *p;
1060 1072
1061 xlog(2, "bw(sockfd=%d, bytes=%zd)\n", sockfd, bytes);
1073 xlog(2, "force_bind: bw(sockfd=%d, bytes=%zd)\n", sockfd, bytes);
1062 1074
1063 1075 if (bytes <= 0) if (bytes <= 0)
1064 1076 return; return;
 
... ... static void bw(const int sockfd, const ssize_t bytes)
1093 1105 diff_ms, p->rest, bytes, allowed); diff_ms, p->rest, bytes, allowed);
1094 1106 */ */
1095 1107
1096 if (bytes <= allowed) {
1108 if (bytes <= (ssize_t) allowed) {
1097 1109 p->rest = allowed - bytes; p->rest = allowed - bytes;
1098 1110 /*printf("\tInside limit, rest=%llu.\n", p->rest);*/ /*printf("\tInside limit, rest=%llu.\n", p->rest);*/
1099 1111 return; return;
 
... ... static void bw(const int sockfd, const ssize_t bytes)
1119 1131 continue; continue;
1120 1132 } }
1121 1133
1122 xlog(1, "nanosleep returned error"
1134 xlog(1, "force_bind: nanosleep returned error"
1123 1135 " (%d) (%s).\n", " (%d) (%s).\n",
1124 1136 err, strerror(errno)); err, strerror(errno));
1125 1137 } }
 
... ... int close(int fd)
1132 1144 { {
1133 1145 init(); init();
1134 1146
1135 xlog(1, "close(fd=%d)\n", fd);
1147 xlog(1, "force_bind: close(fd=%d)\n", fd);
1136 1148
1137 1149 del(fd); del(fd);
1138 1150
 
... ... ssize_t write(int fd, const void *buf, size_t len)
1143 1155 { {
1144 1156 ssize_t n; ssize_t n;
1145 1157
1158 init();
1159
1160 xlog(1, "force_bind: write(fd=%d, ...)\n", fd);
1161
1146 1162 n = old_write(fd, buf, len); n = old_write(fd, buf, len);
1147 1163 bw(fd, n); bw(fd, n);
1148 1164
 
... ... ssize_t send(int sockfd, const void *buf, size_t len, int flags)
1153 1169 { {
1154 1170 ssize_t n; ssize_t n;
1155 1171
1156 xlog(1, "send(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
1172 init();
1173
1174 xlog(1, "force_bind: send(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
1157 1175 sockfd, len, flags); sockfd, len, flags);
1158 1176
1159 1177 n = old_send(sockfd, buf, len, flags); n = old_send(sockfd, buf, len, flags);
 
... ... ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
1168 1186 ssize_t n; ssize_t n;
1169 1187 struct sockaddr_storage new_dest; struct sockaddr_storage new_dest;
1170 1188
1171 xlog(1, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n",
1189 init();
1190
1191 xlog(1, "force_bind: sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n",
1172 1192 sockfd, len, flags); sockfd, len, flags);
1173 1193
1174 1194 change_local_binding(sockfd); change_local_binding(sockfd);
 
... ... ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
1192 1212 struct sockaddr_storage new_dest; struct sockaddr_storage new_dest;
1193 1213 */ */
1194 1214
1195 xlog(1, "sendmsg(sockfd=%d, ..., flags=0x%x)\n",
1215 init();
1216
1217 xlog(1, "force_bind: sendmsg(sockfd=%d, ..., flags=0x%x)\n",
1196 1218 sockfd, flags); sockfd, flags);
1197 1219
1198 1220 change_local_binding(sockfd); change_local_binding(sockfd);
 
... ... ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
1209 1231 } }
1210 1232
1211 1233 /* /*
1212 * We have to hijack accept because this program may be a daemon.
1213 * TODO: accept4 should also be hijacked.
1234 * We have to hijack accept because the program may be a daemon.
1214 1235 */ */
1215 1236 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
1216 1237 { {
 
... ... int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
1220 1241
1221 1242 init(); init();
1222 1243
1223 xlog(2, "accept(sockfd=%d, ...)\n", sockfd);
1244 xlog(2, "force_bind: accept(sockfd=%d, ...)\n", sockfd);
1224 1245
1225 while (1) {
1226 new_sock = old_accept(sockfd, addr, addrlen);
1227 if (new_sock == -1) {
1228 if (errno == EINTR)
1229 continue;
1230 return -1;
1231 }
1246 new_sock = old_accept(sockfd, addr, addrlen);
1247 if (new_sock == -1)
1248 return -1;
1232 1249
1233 break;
1250 /* We must find out domain and type for accepting socket */
1251 q = get(sockfd);
1252 if (q != NULL) {
1253 p = &q->priv;
1254
1255 socket_create_callback(new_sock, p->domain, p->type);
1234 1256 } }
1235 1257
1258 return new_sock;
1259 }
1260
1261 /*
1262 * We have to hijack accept4 because the program may be a daemon.
1263 */
1264 int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
1265 {
1266 int new_sock;
1267 struct node *q;
1268 struct private *p;
1269
1270 init();
1271
1272 xlog(2, "force_bind: accept4(sockfd=%d, ...)\n", sockfd);
1273
1274 new_sock = old_accept4(sockfd, addr, addrlen, flags);
1275 if (new_sock == -1)
1276 return -1;
1277
1236 1278 /* We must find out domain and type for accepting socket */ /* We must find out domain and type for accepting socket */
1237 1279 q = get(sockfd); q = get(sockfd);
1238 1280 if (q != NULL) { if (q != NULL) {
 
... ... int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1248 1290 { {
1249 1291 struct sockaddr_storage new_dest; struct sockaddr_storage new_dest;
1250 1292
1251 xlog(2, "connect(sockfd=%d, ...)\n", sockfd);
1293 init();
1294
1295 xlog(2, "force_bind: connect(sockfd=%d, ...)\n", sockfd);
1252 1296
1253 1297 change_local_binding(sockfd); change_local_binding(sockfd);
1254 1298
 
... ... int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1260 1304
1261 1305 int poll(struct pollfd *fds, nfds_t nfds, int timeout) int poll(struct pollfd *fds, nfds_t nfds, int timeout)
1262 1306 { {
1263 xlog(2, "poll(fds, %d, %d) old_poll=%p\n", nfds, timeout, old_poll);
1307 init();
1308
1309 xlog(2, "force_bind: poll(fds, %d, %d) old_poll=%p\n", nfds, timeout, old_poll);
1264 1310
1265 1311 if (force_poll_timeout != -1000) if (force_poll_timeout != -1000)
1266 1312 timeout = force_poll_timeout; timeout = force_poll_timeout;
File force_bind.spec.in changed (mode: 100644) (index d3e9125..69785b0)
... ... 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
8 8 URL: http://kernel.embedromix.ro/us/ URL: http://kernel.embedromix.ro/us/
9 9 BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
10
10 BuildRequires: gcc, make
11 11
12 12 %description %description
13 13 It uses LD_PRELOAD to manipulate socket calls. Environment variables It uses LD_PRELOAD to manipulate socket calls. Environment variables
File test_bind.c changed (mode: 100644) (index ef56403..504ddf6)
... ... int main(int argc, char *argv[])
25 25 if (argc >= 2) if (argc >= 2)
26 26 port = strtol(argv[1], NULL, 10); port = strtol(argv[1], NULL, 10);
27 27
28 memset(&sa, 0, sizeof(struct sockaddr));
28 memset(&sa, 0, sizeof(struct sockaddr_in));
29 29 sa.sin_family = AF_INET; sa.sin_family = AF_INET;
30 30 sa.sin_port = htons(port); sa.sin_port = htons(port);
31 31 sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_addr.s_addr = htonl(INADDR_ANY);
File test_bind6.c copied from file test_bind.c (similarity 57%) (mode: 100644) (index ef56403..f874e21)
1 #define _GNU_SOURCE
2
1 3 #include <sys/types.h> #include <sys/types.h>
2 4 #include <sys/socket.h> #include <sys/socket.h>
3 5 #include <sys/un.h> #include <sys/un.h>
 
9 11
10 12 int main(int argc, char *argv[]) int main(int argc, char *argv[])
11 13 { {
12 int sock, err;
13 struct sockaddr_in sa, sa2;
14 int sock, err, client_sock;
15 struct sockaddr_in6 sa, sa2, client;
14 16 socklen_t sa_len; socklen_t sa_len;
15 17 int port = 4444; int port = 4444;
16 18 char junk[128]; char junk[128];
17 19 unsigned char tos; unsigned char tos;
20 socklen_t sock_len;
18 21
19 sock = socket(AF_INET, SOCK_STREAM, 0);
22 sock = socket(AF_INET6, SOCK_STREAM, 0);
20 23 if (sock == -1) { if (sock == -1) {
21 24 perror("socket"); perror("socket");
22 25 return 1; return 1;
 
... ... int main(int argc, char *argv[])
25 28 if (argc >= 2) if (argc >= 2)
26 29 port = strtol(argv[1], NULL, 10); port = strtol(argv[1], NULL, 10);
27 30
28 memset(&sa, 0, sizeof(struct sockaddr));
29 sa.sin_family = AF_INET;
30 sa.sin_port = htons(port);
31 sa.sin_addr.s_addr = htonl(INADDR_ANY);
31 memset(&sa, 0, sizeof(struct sockaddr_in6));
32 sa.sin6_family = AF_INET6;
33 sa.sin6_port = htons(port);
32 34
33 sa_len = sizeof(struct sockaddr_in);
35 sa_len = sizeof(struct sockaddr_in6);
34 36 err = bind(sock, (struct sockaddr *) &sa, sa_len); err = bind(sock, (struct sockaddr *) &sa, sa_len);
35 37 if (err != 0) { if (err != 0) {
36 38 perror("bind"); perror("bind");
 
... ... int main(int argc, char *argv[])
44 46 } }
45 47
46 48 fprintf(stderr, "Socket bound to %s/%d.\n", fprintf(stderr, "Socket bound to %s/%d.\n",
47 inet_ntop(sa2.sin_family, &sa2.sin_addr, junk, sa_len),
48 ntohs(sa2.sin_port));
49 inet_ntop(sa2.sin6_family, &sa2.sin6_addr, junk, sa_len),
50 ntohs(sa2.sin6_port));
49 51
50 52 tos = 0x00; tos = 0x00;
51 53 err = setsockopt(sock, IPPROTO_IP, IP_TOS, &tos, 1); err = setsockopt(sock, IPPROTO_IP, IP_TOS, &tos, 1);
52 54 if (err != 0) if (err != 0)
53 55 perror("setsockopt"); perror("setsockopt");
54 56
57 err = listen(sock, 10);
58 if (err != 0) {
59 perror("listen");
60 return 1;
61 }
62
63 sock_len = sizeof(client);
64 client_sock = accept4(sock, (struct sockaddr *) &client, &sock_len, 0);
65 sleep(1);
66 close(client_sock);
67
55 68 close(sock); close(sock);
56 69
57 70 return 0; return 0;
File test_bind6.sh copied from file test_all.sh (similarity 63%) (mode: 100755) (index 711d784..7f1903c)
... ... export FORCE_NET_KA=60
6 6 export FORCE_NET_MSS=1400 export FORCE_NET_MSS=1400
7 7 export FORCE_NET_REUSEADDR=1 export FORCE_NET_REUSEADDR=1
8 8 export FORCE_NET_NODELAY=1 export FORCE_NET_NODELAY=1
9 export FORCE_BIND_ADDRESS_V6=::1
9 10
10 11 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so" export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
11 12
12 debug ./test_bind
13
14 strace -o test_all.strace -f -s100 ./test_bind
15 strace -o test_all2.strace -f -s100 telnet www.kernel.org 80
13 #debug ./test_bind6
14 strace -s200 -f ./test_bind6
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