File force_bind.c changed (mode: 100644) (index 8967a67..f3118c8) |
34 |
34 |
#include <netinet/tcp.h> |
#include <netinet/tcp.h> |
35 |
35 |
|
|
36 |
36 |
|
|
37 |
|
#define FB_FLAGS_NETSOCK 1 |
|
|
37 |
|
#define FB_FLAGS_NETSOCK (1 << 0) |
|
38 |
|
#define FB_FLAGS_BIND_CALLED (1 << 1) |
38 |
39 |
|
|
39 |
40 |
struct private |
struct private |
40 |
41 |
{ |
{ |
|
... |
... |
static ssize_t (*old_send)(int sockfd, const void *buf, size_t len, int flags) |
70 |
71 |
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); |
71 |
72 |
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); |
72 |
73 |
static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen); |
static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen); |
|
74 |
|
static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); |
73 |
75 |
|
|
74 |
76 |
static char *force_address_v4 = NULL; |
static char *force_address_v4 = NULL; |
75 |
77 |
static char *force_address_v6 = NULL; |
static char *force_address_v6 = NULL; |
|
... |
... |
static void init(void) |
198 |
200 |
if (x != NULL) |
if (x != NULL) |
199 |
201 |
verbose = strtol(x, NULL, 10); |
verbose = strtol(x, NULL, 10); |
200 |
202 |
|
|
|
203 |
|
my_syslog(LOG_INFO, "force_bind: Init started...\n"); |
|
204 |
|
|
201 |
205 |
x = getenv("FORCE_BIND_ADDRESS_V4"); |
x = getenv("FORCE_BIND_ADDRESS_V4"); |
202 |
206 |
if (x != NULL) { |
if (x != NULL) { |
203 |
207 |
force_address_v4 = x; |
force_address_v4 = x; |
|
... |
... |
static void init(void) |
380 |
384 |
exit(1); |
exit(1); |
381 |
385 |
} |
} |
382 |
386 |
|
|
383 |
|
my_syslog(LOG_INFO, "force_bind: Inited.\n"); |
|
|
387 |
|
old_connect = dlsym(RTLD_NEXT, "connect"); |
|
388 |
|
if (old_connect == NULL) { |
|
389 |
|
my_syslog(LOG_ERR, "force_bind: Cannot resolve 'connect'!\n"); |
|
390 |
|
exit(1); |
|
391 |
|
} |
|
392 |
|
|
|
393 |
|
my_syslog(LOG_INFO, "force_bind: Init ended.\n"); |
384 |
394 |
} |
} |
385 |
395 |
|
|
386 |
396 |
static int set_ka(int sockfd) |
static int set_ka(int sockfd) |
|
... |
... |
static int set_nodelay(int sockfd) |
482 |
492 |
return 0; |
return 0; |
483 |
493 |
} |
} |
484 |
494 |
|
|
485 |
|
static void change_things(int sockfd, struct sockaddr *sa) |
|
|
495 |
|
/* |
|
496 |
|
* Alters a struct sockaddr, based on environment variables |
|
497 |
|
*/ |
|
498 |
|
static void alter_sa(const int sockfd, struct sockaddr *sa) |
486 |
499 |
{ |
{ |
487 |
|
int err; |
|
488 |
|
struct sockaddr_storage tmp; |
|
489 |
|
socklen_t tmp_len; |
|
490 |
500 |
struct sockaddr_in *sa4; |
struct sockaddr_in *sa4; |
491 |
501 |
struct sockaddr_in6 *sa6; |
struct sockaddr_in6 *sa6; |
492 |
502 |
unsigned short *pport = NULL; |
unsigned short *pport = NULL; |
493 |
503 |
void *p; |
void *p; |
494 |
|
struct node *q; |
|
495 |
504 |
char *force_address; |
char *force_address; |
496 |
505 |
int force_port; |
int force_port; |
497 |
|
|
|
498 |
|
init(); |
|
499 |
|
|
|
500 |
|
/* We do not touch non network sockets */ |
|
501 |
|
q = get(sockfd); |
|
502 |
|
if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)) |
|
503 |
|
return; |
|
504 |
|
|
|
505 |
|
if (sa == NULL) { |
|
506 |
|
tmp_len = sizeof(struct sockaddr_storage); |
|
507 |
|
err = getsockname(sockfd, (struct sockaddr *) &tmp, &tmp_len); |
|
508 |
|
if (err != 0) { |
|
509 |
|
my_syslog(LOG_INFO, "force_bind: Cannot get socket name err=%d (%s) [%d]!\n", |
|
510 |
|
err, strerror(errno), sockfd); |
|
511 |
|
return; |
|
512 |
|
} |
|
513 |
|
sa = (struct sockaddr *) &tmp; |
|
514 |
|
} |
|
|
506 |
|
int err; |
515 |
507 |
|
|
516 |
508 |
switch (sa->sa_family) { |
switch (sa->sa_family) { |
517 |
509 |
case AF_INET: |
case AF_INET: |
|
... |
... |
static void change_things(int sockfd, struct sockaddr *sa) |
547 |
539 |
|
|
548 |
540 |
if (force_port != -1) |
if (force_port != -1) |
549 |
541 |
*pport = htons(force_port); |
*pport = htons(force_port); |
|
542 |
|
|
|
543 |
|
} |
|
544 |
|
|
|
545 |
|
/* |
|
546 |
|
* Alter local binding by doing a forced 'bind' call. |
|
547 |
|
* This is called before calling connect and before using sendto/sendmsg. |
|
548 |
|
*/ |
|
549 |
|
static void change_local_binding(int sockfd) |
|
550 |
|
{ |
|
551 |
|
int err; |
|
552 |
|
struct node *q; |
|
553 |
|
struct sockaddr_storage tmp; |
|
554 |
|
socklen_t tmp_len; |
|
555 |
|
|
|
556 |
|
init(); |
|
557 |
|
|
|
558 |
|
/* We do not touch non network sockets */ |
|
559 |
|
q = get(sockfd); |
|
560 |
|
if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)) |
|
561 |
|
return; |
|
562 |
|
|
|
563 |
|
/* We do not touch already binded sockets */ |
|
564 |
|
if ((q->priv.flags & FB_FLAGS_BIND_CALLED) != 0) |
|
565 |
|
return; |
|
566 |
|
|
|
567 |
|
tmp_len = sizeof(struct sockaddr_storage); |
|
568 |
|
err = getsockname(sockfd, (struct sockaddr *) &tmp, &tmp_len); |
|
569 |
|
if (err != 0) { |
|
570 |
|
my_syslog(LOG_INFO, "force_bind: Cannot get socket name err=%d (%s) [%d]!\n", |
|
571 |
|
err, strerror(errno), sockfd); |
|
572 |
|
return; |
|
573 |
|
} |
|
574 |
|
alter_sa(sockfd, (struct sockaddr *) &tmp); |
|
575 |
|
err = old_bind(sockfd, (struct sockaddr *) &tmp, tmp_len); |
|
576 |
|
q->priv.flags |= FB_FLAGS_BIND_CALLED; |
|
577 |
|
if (err != 0) |
|
578 |
|
my_syslog(LOG_INFO, "force_bind: Cannot bind err=%d (%s) [%d]!\n", |
|
579 |
|
err, strerror(errno), sockfd); |
550 |
580 |
} |
} |
551 |
581 |
|
|
552 |
582 |
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) |
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) |
553 |
583 |
{ |
{ |
|
584 |
|
struct node *q; |
554 |
585 |
struct sockaddr_storage new; |
struct sockaddr_storage new; |
555 |
586 |
|
|
556 |
587 |
memcpy(&new, addr, addrlen); |
memcpy(&new, addr, addrlen); |
557 |
588 |
|
|
558 |
|
change_things(sockfd, (struct sockaddr *) &new); |
|
|
589 |
|
init(); |
|
590 |
|
|
|
591 |
|
/* We do not touch non network sockets */ |
|
592 |
|
q = get(sockfd); |
|
593 |
|
if ((q != NULL) && ((q->priv.flags & FB_FLAGS_NETSOCK) != 0)) { |
|
594 |
|
alter_sa(sockfd, (struct sockaddr *) &new); |
|
595 |
|
q->priv.flags |= FB_FLAGS_BIND_CALLED; |
|
596 |
|
} |
|
597 |
|
|
559 |
598 |
return old_bind(sockfd, (struct sockaddr *) &new, addrlen); |
return old_bind(sockfd, (struct sockaddr *) &new, addrlen); |
560 |
599 |
} |
} |
561 |
600 |
|
|
|
... |
... |
ssize_t write(int fd, const void *buf, size_t len) |
730 |
769 |
{ |
{ |
731 |
770 |
ssize_t n; |
ssize_t n; |
732 |
771 |
|
|
733 |
|
change_things(fd, NULL); |
|
734 |
772 |
n = old_write(fd, buf, len); |
n = old_write(fd, buf, len); |
735 |
773 |
bw(fd, n); |
bw(fd, n); |
736 |
774 |
|
|
|
... |
... |
ssize_t send(int sockfd, const void *buf, size_t len, int flags) |
741 |
779 |
{ |
{ |
742 |
780 |
ssize_t n; |
ssize_t n; |
743 |
781 |
|
|
744 |
|
change_things(sockfd, NULL); |
|
745 |
782 |
n = old_send(sockfd, buf, len, flags); |
n = old_send(sockfd, buf, len, flags); |
746 |
783 |
bw(sockfd, n); |
bw(sockfd, n); |
747 |
784 |
|
|
|
... |
... |
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, |
753 |
790 |
{ |
{ |
754 |
791 |
ssize_t n; |
ssize_t n; |
755 |
792 |
|
|
756 |
|
change_things(sockfd, NULL); |
|
|
793 |
|
change_local_binding(sockfd); |
757 |
794 |
n = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen); |
n = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen); |
758 |
795 |
bw(sockfd, n); |
bw(sockfd, n); |
759 |
796 |
|
|
|
... |
... |
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) |
767 |
804 |
{ |
{ |
768 |
805 |
ssize_t n; |
ssize_t n; |
769 |
806 |
|
|
770 |
|
change_things(sockfd, NULL); |
|
|
807 |
|
change_local_binding(sockfd); |
771 |
808 |
n = old_sendmsg(sockfd, msg, flags); |
n = old_sendmsg(sockfd, msg, flags); |
772 |
809 |
bw(sockfd, n); |
bw(sockfd, n); |
773 |
810 |
|
|
|
... |
... |
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) |
785 |
822 |
init(); |
init(); |
786 |
823 |
|
|
787 |
824 |
new_sock = old_accept(sockfd, addr, addrlen); |
new_sock = old_accept(sockfd, addr, addrlen); |
|
825 |
|
if (new_sock == -1) |
|
826 |
|
return -1; |
788 |
827 |
|
|
789 |
828 |
socket_create_callback(new_sock, -1, -1); |
socket_create_callback(new_sock, -1, -1); |
790 |
829 |
|
|
791 |
830 |
return new_sock; |
return new_sock; |
792 |
831 |
} |
} |
|
832 |
|
|
|
833 |
|
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) |
|
834 |
|
{ |
|
835 |
|
change_local_binding(sockfd); |
|
836 |
|
return old_connect(sockfd, addr, addrlen); |
|
837 |
|
} |
|
838 |
|
|
File test_client.c copied from file test_bind.c (similarity 55%) (mode: 100644) (index ef56403..13d4c8b) |
|
1 |
|
/* |
|
2 |
|
* This program test socket->connect binding |
|
3 |
|
* Copyright: Catalin(ux) M. BOIE |
|
4 |
|
* Part of force_bind package |
|
5 |
|
*/ |
1 |
6 |
#include <sys/types.h> |
#include <sys/types.h> |
2 |
7 |
#include <sys/socket.h> |
#include <sys/socket.h> |
3 |
8 |
#include <sys/un.h> |
#include <sys/un.h> |
|
... |
... |
int main(int argc, char *argv[]) |
14 |
19 |
socklen_t sa_len; |
socklen_t sa_len; |
15 |
20 |
int port = 4444; |
int port = 4444; |
16 |
21 |
char junk[128]; |
char junk[128]; |
17 |
|
unsigned char tos; |
|
|
22 |
|
char *dest = "127.0.0.1"; |
18 |
23 |
|
|
19 |
24 |
sock = socket(AF_INET, SOCK_STREAM, 0); |
sock = socket(AF_INET, SOCK_STREAM, 0); |
20 |
25 |
if (sock == -1) { |
if (sock == -1) { |
|
... |
... |
int main(int argc, char *argv[]) |
23 |
28 |
} |
} |
24 |
29 |
|
|
25 |
30 |
if (argc >= 2) |
if (argc >= 2) |
26 |
|
port = strtol(argv[1], NULL, 10); |
|
|
31 |
|
dest = argv[1]; |
|
32 |
|
|
|
33 |
|
if (argc >= 3) |
|
34 |
|
port = strtol(argv[2], NULL, 10); |
|
35 |
|
|
|
36 |
|
err = getsockname(sock, (struct sockaddr *) &sa2, &sa_len); |
|
37 |
|
if (err != 0) { |
|
38 |
|
perror("getsockname"); |
|
39 |
|
return 1; |
|
40 |
|
} |
|
41 |
|
fprintf(stderr, "Socket bound to %s/%d.\n", |
|
42 |
|
inet_ntop(sa2.sin_family, &sa2.sin_addr, junk, sa_len), |
|
43 |
|
ntohs(sa2.sin_port)); |
27 |
44 |
|
|
28 |
45 |
memset(&sa, 0, sizeof(struct sockaddr)); |
memset(&sa, 0, sizeof(struct sockaddr)); |
29 |
46 |
sa.sin_family = AF_INET; |
sa.sin_family = AF_INET; |
30 |
47 |
sa.sin_port = htons(port); |
sa.sin_port = htons(port); |
31 |
|
sa.sin_addr.s_addr = htonl(INADDR_ANY); |
|
32 |
|
|
|
33 |
|
sa_len = sizeof(struct sockaddr_in); |
|
34 |
|
err = bind(sock, (struct sockaddr *) &sa, sa_len); |
|
35 |
|
if (err != 0) { |
|
36 |
|
perror("bind"); |
|
|
48 |
|
err = inet_pton(AF_INET, dest, &sa.sin_addr); |
|
49 |
|
if (err != 1) { |
|
50 |
|
perror("inet_pton"); |
37 |
51 |
return 1; |
return 1; |
38 |
52 |
} |
} |
39 |
53 |
|
|
|
54 |
|
err = connect(sock, (struct sockaddr *) &sa, sizeof(sa)); |
|
55 |
|
if (err == -1) { |
|
56 |
|
perror("connect"); |
|
57 |
|
/* ignore error */ |
|
58 |
|
} |
|
59 |
|
|
40 |
60 |
err = getsockname(sock, (struct sockaddr *) &sa2, &sa_len); |
err = getsockname(sock, (struct sockaddr *) &sa2, &sa_len); |
41 |
61 |
if (err != 0) { |
if (err != 0) { |
42 |
62 |
perror("getsockname"); |
perror("getsockname"); |
43 |
63 |
return 1; |
return 1; |
44 |
64 |
} |
} |
45 |
|
|
|
46 |
|
fprintf(stderr, "Socket bound to %s/%d.\n", |
|
|
65 |
|
fprintf(stderr, "Socket bound to %s/%d (after connect called).\n", |
47 |
66 |
inet_ntop(sa2.sin_family, &sa2.sin_addr, junk, sa_len), |
inet_ntop(sa2.sin_family, &sa2.sin_addr, junk, sa_len), |
48 |
67 |
ntohs(sa2.sin_port)); |
ntohs(sa2.sin_port)); |
49 |
68 |
|
|
50 |
|
tos = 0x00; |
|
51 |
|
err = setsockopt(sock, IPPROTO_IP, IP_TOS, &tos, 1); |
|
52 |
|
if (err != 0) |
|
53 |
|
perror("setsockopt"); |
|
54 |
|
|
|
55 |
69 |
close(sock); |
close(sock); |
56 |
70 |
|
|
57 |
71 |
return 0; |
return 0; |