Subject | Hash | Author | Date (UTC) |
---|---|---|---|
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 |
Spec files updates. | 7a09b21c11b8d3c562544826c1fddb6009b16263 | Catalin(ux) M. BOIE | 2011-08-22 21:30:13 |
Duilder updates. | f2b462384459025a3ffdcb8ebffcb070d8289ca7 | Catalin(ux) M. BOIE | 2011-08-22 21:29:51 |
Bump version to 0.8. | e330ad91c75eeb6e627c6725b17fcc69d01eac50 | Catalin(ux) M. BOIE | 2011-08-22 15:17:00 |
Added a good example for tc prio classification. | 32b9078e47fccc09527ca2c11904f82879934da3 | Catalin(ux) M. BOIE | 2011-08-22 15:16:21 |
Added support for multiple connections and chunk size for send_udp example. | eff367aa527ed763fe525832891e0fc0df9badbb | Catalin(ux) M. BOIE | 2011-08-22 14:58:13 |
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 |