Subject SHA-1 Author Date
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
Commit d9598fd2ca7886484b78512d71dbd29059720832 - Added support for deny and fake for Kevin
Author: Catalin(ux) M. BOIE
Author date (UTC): 2012-07-18 21:13
Committer: Catalin(ux) M. BOIE
Commit date (UTC): 2012-07-18 21:13
Tree: 744c8ad44a67ae52c7716679d961880367561a66
Parents: d5576baff697e87dfbbbcbfb77df4b364cee15a2
File Lines added Lines deleted
Makefile.in 3 1
README 13 0
TODO 9 0
duilder.conf 1 1
force_bind.c 56 25
force_bind.spec.in 5 3
test_deny.sh 14 0
test_fake.sh 14 0

File Makefile.in changed (mode: 100644) (index ee74c03..e87d60c)
... ... test_client6: test_client6.c
24 24
25 25 .PHONY: clean .PHONY: clean
26 26 clean: clean:
27 @rm -f force_bind.so.* test_bind send_udp test_client test_client6 *.a *.o *.so* $(PRJ)-*.rpm $(PRJ)-*-*-*.tgz $(PRJ)-*.tar.gz *.strace
27 @rm -f force_bind.so.* test_bind send_udp test_client test_client6 \
28 *.a *.o *.so* $(PRJ)-*.rpm $(PRJ)-*-*-*.tgz $(PRJ)-*.tar.gz \
29 *.strace *.log *.out
28 30
29 31 install: all install: all
30 32 @mkdir -p $(I_USR_LIB) @mkdir -p $(I_USR_LIB)

File README changed (mode: 100644) (index 9b49b87..95feff7)
... ... Examples:
116 116 # 3. Run tc statistics so you can see the classification: # 3. Run tc statistics so you can see the classification:
117 117 tc -s class show dev eth0 tc -s class show dev eth0
118 118
119 15: Deny binding to any IPv4 sockets. The bind syscall
120 will return -1 and errno will be set to EACCES.
121 export FORCE_NET_VERBOSE=1
122 export FORCE_BIND_ADDRESS_V4=deny
123 export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so
124 your_program_here
125
126 16: Silent fake binding to any IPv6 sockets. The bind will
127 return success, but will never accept any connection.
128 export FORCE_NET_VERBOSE=1
129 export FORCE_BIND_ADDRESS_V6=fake
130 export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so
131 your_program_here
119 132
120 133 Installation: Installation:
121 134 - ./configure - ./configure

File TODO changed (mode: 100644) (index a565f71..5c2fda3)
13 13 [ ] 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
14 14 [ ] Bandwidth limitting also for download [ ] Bandwidth limitting also for download
15 15 [ ] Dump statistics (bytes, syscalls etc.) in a file specified by a env var. [ ] Dump statistics (bytes, syscalls etc.) in a file specified by a env var.
16 [ ] Need to study how to set only the class for IPv6. Also check Linux kernel
17 to see how prio is set for IPv6 class.
18 [ ] Nice: Force a protocol on a connection! So, uer tries TCP but get UDP!
19 [ ] Controlling timeout (SO_RCVTIMEO, SO_SNDTIMEO)
20 [ ] Enforce connect timeout
21 [ ] Change data on the fly...
22 [ ] Allow saving stream data in a file.
23 [ ] sendmmsg/recvmmsg support
24 [ ] There are stupid applications (skype) that run poll with timeout 0! Fix it!
16 25 [ ] [ ]

File duilder.conf changed (mode: 100644) (index 3b9eb25..d622c2e)
1 1 PRJ="force_bind" PRJ="force_bind"
2 VER="0.10"
2 VER="0.11"
3 3 REV="1" REV="1"
4 4 EXCLUDE="" EXCLUDE=""
5 5 EXPORT_PATH="/data/www/umbrella/kernel/us/force_bind" EXPORT_PATH="/data/www/umbrella/kernel/us/force_bind"

File force_bind.c changed (mode: 100644) (index 27e1eb1..644e3a7)
... ... static char *sprotocol(const int protocol)
170 170 } }
171 171
172 172 /* /*
173 * Set @out to a string with the address
173 * Fills @out with domain/type/address/port string
174 174 */ */
175 static void saddr(char *out, const struct sockaddr_storage *ss)
175 static void saddr(char *out, const int out_len,
176 const struct sockaddr_storage *ss)
176 177 { {
177 178 struct sockaddr_in *s4; struct sockaddr_in *s4;
178 179 struct sockaddr_in6 *s6; struct sockaddr_in6 *s6;
180 char addr[40], port[8];
179 181
180 182 switch (ss->ss_family) { switch (ss->ss_family) {
181 183 case AF_INET: case AF_INET:
182 184 s4 = (struct sockaddr_in *) ss; s4 = (struct sockaddr_in *) ss;
183 inet_ntop(AF_INET, (void *) &s4->sin_addr.s_addr, out, sizeof(struct sockaddr_in));
185 inet_ntop(AF_INET, (void *) &s4->sin_addr.s_addr, addr, sizeof(struct sockaddr_in));
186 snprintf(port, sizeof(port), "%d", s4->sin_port);
184 187 break; break;
185 188 case AF_INET6: case AF_INET6:
186 189 s6 = (struct sockaddr_in6 *) ss; s6 = (struct sockaddr_in6 *) ss;
187 inet_ntop(AF_INET6, (void *) &s6->sin6_addr.s6_addr, out, sizeof(struct sockaddr_in6));
190 inet_ntop(AF_INET6, (void *) &s6->sin6_addr.s6_addr, addr, sizeof(struct sockaddr_in6));
191 snprintf(port, sizeof(port), "%d", s6->sin6_port);
188 192 break; break;
189 193 default: default:
190 sprintf(out, "Unknown address type (%d)", ss->ss_family);
194 strcpy(addr, "?");
195 strcpy(port, "?");
191 196 break; break;
192 197 } }
198
199 snprintf(out, out_len, "%s/%s/%s",
200 sdomain(ss->ss_family), addr, port);
193 201 } }
194 202
195 203 static void xlog(const unsigned int level, const char *format, ...) static void xlog(const unsigned int level, const char *format, ...)
 
... ... static void list(const int level)
242 250 { {
243 251 struct node *q; struct node *q;
244 252 struct private *p; struct private *p;
245 char dest[64];
253 char dest[128];
246 254
247 255 xlog(level, "list...\n"); xlog(level, "list...\n");
248 256
 
... ... static void list(const int level)
254 262 } }
255 263
256 264 p = &q->priv; p = &q->priv;
257 saddr(dest, &p->dest);
258 xlog(level, "\tfd=%4d domain=%s type=%s"
259 " flags=%04x limit=%llu"
265 saddr(dest, sizeof(dest), &p->dest);
266 xlog(level, "\tfd=%4d type=%s flags=%04x limit=%llu"
260 267 " rest=%llu last=%u.%06u dest=%s\n", " rest=%llu last=%u.%06u dest=%s\n",
261 q->fd, sdomain(p->domain), stype(p->type),
262 p->flags, p->limit,
268 q->fd, stype(p->type), p->flags, p->limit,
263 269 p->rest, p->last.tv_sec, p->last.tv_usec, dest); p->rest, p->last.tv_sec, p->last.tv_usec, dest);
264 270 q = q->next; q = q->next;
265 271 } }
 
... ... static void init(void)
364 370 x = getenv("FORCE_BIND_ADDRESS_V4"); x = getenv("FORCE_BIND_ADDRESS_V4");
365 371 if (x != NULL) { if (x != NULL) {
366 372 force_address_v4 = x; force_address_v4 = x;
367 xlog(1, "Force bind to address %s.\n",
373 xlog(1, "Force bind to IPv4 address \"%s\".\n",
368 374 force_address_v4); force_address_v4);
369 375 } }
370 376
371 377 x = getenv("FORCE_BIND_ADDRESS_V6"); x = getenv("FORCE_BIND_ADDRESS_V6");
372 378 if (x != NULL) { if (x != NULL) {
373 379 force_address_v6 = x; force_address_v6 = x;
374 xlog(1, "Force bind to address %s.\n",
380 xlog(1, "Force bind to IPv6 address \"%s\".\n",
375 381 force_address_v6); force_address_v6);
376 382 } }
377 383
 
... ... static void init(void)
380 386 if (x != NULL) { if (x != NULL) {
381 387 force_address_v4 = x; force_address_v4 = x;
382 388 force_address_v6 = x; force_address_v6 = x;
383 xlog(1, "Force bind to address %s."
389 xlog(1, "Force bind to address \"%s\"."
384 390 " Obsolete, use FORCE_BIND_ADDRESS_V4/6.\n", " Obsolete, use FORCE_BIND_ADDRESS_V4/6.\n",
385 391 force_address_v4); force_address_v4);
386 392 } }
 
... ... static int alter_sa(const int sockfd, struct sockaddr *sa)
809 815 static void alter_dest_sa(int sockfd, struct sockaddr_storage *ss, socklen_t len) static void alter_dest_sa(int sockfd, struct sockaddr_storage *ss, socklen_t len)
810 816 { {
811 817 struct node *q; struct node *q;
812 struct sockaddr *sa = (struct sockaddr *) ss;
813 818 struct sockaddr_in6 *sa6; struct sockaddr_in6 *sa6;
814 char addr[64];
819 char addr[128];
815 820
816 821 init(); init();
817 822
818 saddr(addr, ss);
819 xlog(2, "alter_dest_sa(sockfd=%d, [domain=%s, addr=%s])\n",
820 sockfd, sdomain(ss->ss_family), addr);
823 saddr(addr, sizeof(addr), ss);
824 xlog(2, "alter_dest_sa(sockfd=%d, addr=%s)\n",
825 sockfd, addr);
821 826
822 827 /* We do not touch non network sockets */ /* We do not touch non network sockets */
823 828 q = get(sockfd); q = get(sockfd);
824 829 if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)) if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0))
825 830 return; return;
826 831
827 switch (sa->sa_family) {
832 switch (ss->ss_family) {
828 833 case AF_INET6: case AF_INET6:
829 sa6 = (struct sockaddr_in6 *) sa;
834 sa6 = (struct sockaddr_in6 *) ss;
830 835 if (force_flowinfo == 1) { if (force_flowinfo == 1) {
831 836 xlog(1, "changing flowinfo from 0x%x to 0x%x [%d]!\n", xlog(1, "changing flowinfo from 0x%x to 0x%x [%d]!\n",
832 837 ntohl(sa6->sin6_flowinfo), flowinfo, sockfd); ntohl(sa6->sin6_flowinfo), flowinfo, sockfd);
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
887 892 { {
888 893 struct node *q; struct node *q;
889 894 struct sockaddr_storage new; struct sockaddr_storage new;
895 char *force_address = "";
896 char tmp[128];
890 897
891 898 init(); init();
892 899
893 xlog(1, "bind(sockfd=%d, ...)!\n", sockfd);
900 saddr(tmp, sizeof(tmp), (struct sockaddr_storage *) addr);
901 xlog(1, "bind(sockfd=%d, %s)\n", sockfd, tmp);
894 902
895 903 memcpy(&new, addr, addrlen); memcpy(&new, addr, addrlen);
896 904
897 905 /* We do not touch non network sockets */ /* We do not touch non network sockets */
898 906 q = get(sockfd); q = get(sockfd);
899 if ((q != NULL) && ((q->priv.flags & FB_FLAGS_NETSOCK) != 0)) {
907 do {
908 if (q == NULL)
909 break;
910
911 if ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)
912 break;
913
914 switch (q->priv.domain) {
915 case AF_INET: force_address = force_address_v4; break;
916 case AF_INET6: force_address = force_address_v6; break;
917 }
918
919 /* Test if we should deny the bind */
920 if (strcmp(force_address, "deny") == 0) {
921 xlog(1, "\tDeny binding to %s\n", tmp);
922 errno = EACCES;
923 return -1;
924 }
925
926 if (strcmp(force_address, "fake") == 0) {
927 xlog(1, "\tFake binding to %s\n", tmp);
928 return 0;
929 }
930
900 931 alter_sa(sockfd, (struct sockaddr *) &new); alter_sa(sockfd, (struct sockaddr *) &new);
901 932 q->priv.flags |= FB_FLAGS_BIND_CALLED; q->priv.flags |= FB_FLAGS_BIND_CALLED;
902 }
933 } while (0);
903 934
904 935 return old_bind(sockfd, (struct sockaddr *) &new, addrlen); return old_bind(sockfd, (struct sockaddr *) &new, addrlen);
905 936 } }
 
... ... int socket(int domain, int type, int protocol)
982 1013
983 1014 init(); init();
984 1015
985 xlog(1, "socket(domain=%s, type=%s, protocol=%d)\n",
1016 xlog(1, "socket(domain=%s, type=%s, protocol=%s)\n",
986 1017 sdomain(domain), stype(type), sprotocol(protocol)); sdomain(domain), stype(type), sprotocol(protocol));
987 1018
988 1019 sockfd = old_socket(domain, type, protocol); sockfd = old_socket(domain, type, protocol);

File force_bind.spec.in changed (mode: 100644) (index bc901b2..b7b631f)
... ... Summary: Force binding to a specif address and/or port, changing TOS/TTL/MSS/etc
2 2 Name: @PRJ@ Name: @PRJ@
3 3 Version: @VER@ Version: @VER@
4 4 Release: @REV@ Release: @REV@
5 License: GPLv3
5 License: GPLv3+
6 6 Group: Applications/Communications Group: Applications/Communications
7 7 Source: http://kernel.embedromix.ro/us/Conn/%{name}-%{version}.tar.gz Source: http://kernel.embedromix.ro/us/Conn/%{name}-%{version}.tar.gz
8 8 URL: http://kernel.embedromix.ro/us/ URL: http://kernel.embedromix.ro/us/
 
... ... rm -rf ${RPM_BUILD_ROOT}
34 34
35 35 %files %files
36 36 %attr (-,root,root) %attr (-,root,root)
37 %{_libdir}/*
37 %{_libdir}/*.so
38 38 %doc README LICENSE Changelog TODO %doc README LICENSE Changelog TODO
39 39
40 40 %changelog %changelog
41 * Mon Aug 22 2011 Catalin(ux) M. BOIE <catab at embedromix dot ro> 0.8
41 * Wed Jul 18 2012 Catalin(ux) M. BOIE <catab at embedromix dot ro> - 0.11-1
42 Added support for deny and fake.
43 * Mon Aug 22 2011 Catalin(ux) M. BOIE <catab at embedromix dot ro> - 0.8-1
42 44 Added support for SO_PRIORITY, FWMARK and IPv6 flowinfo and other fixes. Added support for SO_PRIORITY, FWMARK and IPv6 flowinfo and other fixes.

File test_deny.sh added (mode: 100755) (index 0000000..a225478)
1 #!/bin/sh
2
3 # Test if we can deny the bind to a protocol
4
5 ulimit -c2000000
6
7 export FORCE_BIND_ADDRESS_V4=deny
8 export FORCE_NET_LOG="test_deny.sh.log"
9 export FORCE_NET_VERBOSE=1
10
11 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
12
13 make test_bind
14 strace -f -s200 -o ${0}.strace ./test_bind 10000

File test_fake.sh added (mode: 100755) (index 0000000..acf74df)
1 #!/bin/sh
2
3 # Test if we can fake bind a protocol
4
5 ulimit -c2000000
6
7 export FORCE_BIND_ADDRESS_V4=fake
8 export FORCE_NET_LOG="test_fake.sh.log"
9 export FORCE_NET_VERBOSE=1
10
11 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
12
13 make test_bind
14 strace -f -s200 -o ${0}.strace ./test_bind 10000
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 pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master