List of commits:
Subject Hash Author Date (UTC)
Added support for IPv6 flowinfo (class + label). c23cc6042893fb98986b5aa38c146b7aec488079 Catalin(ux) M. BOIE 2011-08-06 21:11:46
Added support for connecting clients (socket -> connect or socket -> sendto). 8f94255890a99d4890206e53f031ffad79c55866 Catalin(ux) M. BOIE 2011-08-05 21:15:38
Bump version to 0.7. 1a51b690a50c482c9e727b3e8e129bbc2890f600 Catalin(ux) M. BOIE 2011-06-21 17:06:25
Corrected description and license. 708b98d98bb5704f3bd265928f07cc94c18bd212 Catalin(ux) M. BOIE 2011-06-21 17:06:04
Bump version to 0.6. cb4ef5c142753802f9dcd2410d094f9914e8273c Catalin(ux) M. BOIE 2011-06-21 16:56:15
Added support for separate FORCE_ADDR for IPv4 and IPv6, MSS, TTL etc. e32e97cafe360f192283168d76c327559282e24d Catalin(ux) M. BOIE 2011-06-21 16:55:12
Added TODO to %doc rpm section. 086dbb2e078955dddf83cbfd65998334d6db81e4 Catalin(ux) M. BOIE 2010-12-19 19:46:20
Added MSS. 9a5c3676567cb92e6c0b4106c2b97cd2da2273a5 Catalin(ux) M. BOIE 2010-12-14 17:00:37
Added TOS test script. a4b1b05b27b3eaa06a4a71f656e1b80731d1b8ff Catalin(ux) M. BOIE 2010-12-14 16:55:03
Ignore Changelog-last file. 1bfa5decd11f4fd95e4b002d88e2a2e04c747855 Catalin(ux) M. BOIE 2010-12-14 16:54:36
Added KA. ec9b4556e51ca9a807400910f8ca6d698f9ad670 Catalin(ux) M. BOIE 2010-12-14 16:53:58
Bump up the version to 0.5. f7ba7f0feb49ac4942d85903d31e085f1ffa6149 Catalin(ux) M. BOIE 2010-11-07 23:16:25
Duilder updates. 4d3691f340591f68f9b0ae704da24b4352957f05 Catalin(ux) M. BOIE 2010-11-07 23:15:29
Added support to force TOS by using env var FORCE_NET_TOS. 319cfbee315a0c6889791b122fdb8069aa2ffdf1 Catalin(ux) M. BOIE 2010-11-07 23:14:23
No need for duilder_release. I will use a global one. 15a59294aa3922e58bff8aaa9de7cc06dc44fe1e Catalin(ux) M. BOIE 2010-10-27 20:43:15
TODO in. 9ea8407b8a2767debcf7597bbfc1bddfe44c78eb Catalin(ux) M. BOIE 2010-10-27 20:21:13
Typo. 2282d895e91cf2b02a7b67d933af2c68db5798b6 Catalin(ux) M. BOIE 2010-10-27 19:54:40
Aded license information to README file. fe8071fd2d9f912136fb7fa22f289ddc63cf0f14 Catalin(ux) M. BOIE 2010-10-27 19:46:48
Improved description. 1f17958175bf3f2a656a365fdafca21118737cf1 Catalin(ux) M. BOIE 2010-10-27 19:43:33
Silence compiler useless warning. 117e169b70197ac7e62907f855eb475a0a43fe07 Catalin(ux) M. BOIE 2010-10-27 19:24:45
Commit c23cc6042893fb98986b5aa38c146b7aec488079 - Added support for IPv6 flowinfo (class + label).
Author: Catalin(ux) M. BOIE
Author date (UTC): 2011-08-06 21:11
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2011-08-06 21:13
Parent(s): 8f94255890a99d4890206e53f031ffad79c55866
Signing key:
Tree: ab7d603b813aae9c780e6cedd418681051ce9c71
File Lines added Lines deleted
.gitignore 2 0
Makefile.in 4 1
README 12 1
TODO 1 0
force_bind.c 190 42
test_client6-1.sh 10 0
test_client6.c 75 0
File .gitignore changed (mode: 100644) (index 0cd2559..9dbb318)
... ... Changelog*
5 5 test_bind test_bind
6 6 *.strace *.strace
7 7 send_udp send_udp
8 test_client
9 test_client6
File Makefile.in changed (mode: 100644) (index ab558a1..1191098)
... ... send_udp: send_udp.c
19 19 test_client: test_client.c test_client: test_client.c
20 20 $(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@
21 21
22 test_client6: test_client6.c
23 $(CC) $(CFLAGS) $< -o $@
24
22 25 .PHONY: clean .PHONY: clean
23 26 clean: clean:
24 @rm -f force_bind.so.* test_bind send_udp test_client *.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 *.a *.o *.so* $(PRJ)-*.rpm $(PRJ)-*-*-*.tgz $(PRJ)-*.tar.gz *.strace
25 28
26 29 install: all install: all
27 30 @mkdir -p $(I_USR_LIB) @mkdir -p $(I_USR_LIB)
File README changed (mode: 100644) (index f0a83e3..8cf66a6)
... ... Examples:
69 69 your_program_here your_program_here
70 70
71 71 11. Force client connections (for example 'telnet', 'ssh', 11. Force client connections (for example 'telnet', 'ssh',
72 'firefox' to connect from a specified address, not the auto
72 'firefox') to connect from a specified address, not the auto
73 73 selected one: selected one:
74 74 export FORCE_NET_VERBOSE=1 export FORCE_NET_VERBOSE=1
75 75 export FORCE_BIND_ADDRESS_V4=127.0.0.2 export FORCE_BIND_ADDRESS_V4=127.0.0.2
76 76 export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so
77 77 your_program_here your_program_here
78 78
79 12. Set a FLOWINFO (flow label + class) for a client connection:
80 export FORCE_NET_VERBOSE=1
81 export FORCE_NET_FLOWINFO=0x7812345 # class 0x78, label 0x12345
82 export LD_PRELOAD=${LD_PRELOAD}:/usr/lib/force_bind.so
83 your_program_here
84 A tcpdump of a connection will look like:
85 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv6 (0x86dd),
86 length 94: (class 0x78, flowlabel 0x12345, hlim 64, next-header TCP (6) payload length: 40)
87 ::1.56981 > ::1.krb524: Flags [S], cksum 0x0030 (incorrect -> 0x91cf),
88 seq 1154252590, win 32752, options [mss 16376,sackOK,TS val 28395104 ecr 0,nop,wscale 4], length 0
89
79 90 Installation: Installation:
80 91 - ./configure - ./configure
81 92 - make - make
File TODO changed (mode: 100644) (index 644a84a..c45ba11)
8 8 [ ] Bandwidth per total or per socket. Better, per ip/protocol [ ] Bandwidth per total or per socket. Better, per ip/protocol
9 9 [ ] IPv6 flowlabel. [ ] IPv6 flowlabel.
10 10 [ ] Corrupt data [ ] Corrupt data
11 [ ] Add possibility to change destination of packets.
11 12 [ ] [ ]
File force_bind.c changed (mode: 100644) (index f3118c8..06f6d46)
33 33 #include <netinet/in.h> #include <netinet/in.h>
34 34 #include <netinet/tcp.h> #include <netinet/tcp.h>
35 35
36 #ifndef IPV6_FLOWINFO_SEND
37 #define IPV6_FLOWLABEL_MGR 32
38 #define IPV6_FLOWINFO_SEND 33
39
40 #define IPV6_FL_F_CREATE 1
41 #define IPV6_FL_A_GET 0
42 #define IPV6_FL_S_ANY 255
43
44 #define IPV6_FLOWINFO_MASK 0x0FFFFFFFUL
45 #define IPV6_FLOWLABEL_MASK 0x000FFFFFUL
46
47 struct in6_flowlabel_req {
48 struct in6_addr flr_dst;
49 unsigned int flr_label;
50 unsigned char flr_action;
51 unsigned char flr_share;
52 unsigned short flr_flags;
53 unsigned short flr_expires;
54 unsigned short flr_linger;
55 unsigned int __flr_pad;
56 };
57 #endif
36 58
37 #define FB_FLAGS_NETSOCK (1 << 0)
38 #define FB_FLAGS_BIND_CALLED (1 << 1)
59 #define FB_FLAGS_NETSOCK (1 << 0)
60 #define FB_FLAGS_BIND_CALLED (1 << 1)
61 #define FB_FLAGS_FLOWINFO_CALLED (1 << 2)
39 62
40 63 struct private struct private
41 64 { {
42 65 int domain; int domain;
43 66 int type; int type;
44 67 unsigned int flags; unsigned int flags;
68 struct sockaddr_storage dest;
69 socklen_t dest_len;
45 70
46 71 /* bandwidth */ /* bandwidth */
47 72 unsigned long long limit; unsigned long long limit;
 
... ... static unsigned int force_mss = 0, mss;
84 109 static unsigned int force_reuseaddr = 0, reuseaddr; static unsigned int force_reuseaddr = 0, reuseaddr;
85 110 static unsigned int force_nodelay = 0, nodelay; static unsigned int force_nodelay = 0, nodelay;
86 111 static unsigned long long bw_limit_per_socket = 0; static unsigned long long bw_limit_per_socket = 0;
112 static unsigned int force_flowinfo = 0, flowinfo;
87 113 static struct private bw_global; static struct private bw_global;
88 114 static struct info fdinfo; static struct info fdinfo;
89 115 static unsigned int verbose = 0; static unsigned int verbose = 0;
 
... ... static int my_syslog(int priority, const char *format, ...)
104 130 return 0; return 0;
105 131 } }
106 132
133 static void dump(const char *title, const void *buf, const unsigned int len)
134 {
135 unsigned int i;
136 unsigned char *buf2 = (unsigned char *) buf;
137 char out[1024];
138
139 for (i = 0; i < len; i++)
140 snprintf(out + i * 3, 4, " %02x", buf2[i]);
141
142 my_syslog(LOG_INFO, "force_bind: %s:%s\n", title, out);
143 }
144
107 145 static struct node *get(const int fd) static struct node *get(const int fd)
108 146 { {
109 147 struct node *p; struct node *p;
 
... ... static void init(void)
329 367 } }
330 368 } }
331 369
370 /* IPv6 flowinfo */
371 x = getenv("FORCE_NET_FLOWINFO");
372 if (x != NULL) {
373 force_flowinfo = 1;
374 flowinfo = strtoul(x, NULL, 0) & IPV6_FLOWINFO_MASK;
375 my_syslog(LOG_INFO, "force_bind: Force FLOWINFO to 0x%x.\n",
376 flowinfo);
377 }
378
332 379
333 380 old_bind = dlsym(RTLD_NEXT, "bind"); old_bind = dlsym(RTLD_NEXT, "bind");
334 381 if (old_bind == NULL) { if (old_bind == NULL) {
 
... ... static int set_ka(int sockfd)
402 449
403 450 flag = (keepalive > 0) ? 1 : 0; flag = (keepalive > 0) ? 1 : 0;
404 451 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag));
405 my_syslog(LOG_INFO, "force_bind: changing SO_KEEPALIVE to %d (ret=%d) [%d].\n",
406 flag, ret, sockfd);
452 my_syslog(LOG_INFO, "force_bind: changing SO_KEEPALIVE to %d (ret=%d(%s)) [%d].\n",
453 flag, ret, strerror(errno), sockfd);
407 454
408 455 return 0; return 0;
409 456 } }
 
... ... static int set_ka_idle(int sockfd)
416 463 return 0; return 0;
417 464
418 465 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, sizeof(keepalive)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, sizeof(keepalive));
419 my_syslog(LOG_INFO, "force_bind: changing TCP_KEEPIDLE to %us (ret=%d) [%d].\n",
420 keepalive, ret, sockfd);
466 my_syslog(LOG_INFO, "force_bind: changing TCP_KEEPIDLE to %us (ret=%d(%s)) [%d].\n",
467 keepalive, ret, strerror(errno), sockfd);
421 468
422 469 return 0; return 0;
423 470 } }
 
... ... static int set_mss(int sockfd)
430 477 return 0; return 0;
431 478
432 479 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss));
433 my_syslog(LOG_INFO, "force_bind: changing MSS to %u (ret=%d) [%d].\n",
434 mss, ret, sockfd);
480 my_syslog(LOG_INFO, "force_bind: changing MSS to %u (ret=%d(%s)) [%d].\n",
481 mss, ret, strerror(errno), sockfd);
435 482
436 483 return 0; return 0;
437 484 } }
 
... ... static int set_tos(int sockfd)
444 491 return 0; return 0;
445 492
446 493 ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
447 my_syslog(LOG_INFO, "force_bind: changing TOS to %hhu (ret=%d) [%d].\n",
448 tos, ret, sockfd);
494 my_syslog(LOG_INFO, "force_bind: changing TOS to %hhu (ret=%d(%s)) [%d].\n",
495 tos, ret, strerror(errno), sockfd);
449 496
450 497 return 0; return 0;
451 498 } }
 
... ... static int set_ttl(int sockfd)
458 505 return 0; return 0;
459 506
460 507 ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); ret = old_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
461 my_syslog(LOG_INFO, "force_bind: changing TTL to %hhu (ret=%d) [%d].\n",
462 ttl, ret, sockfd);
508 my_syslog(LOG_INFO, "force_bind: changing TTL to %hhu (ret=%d(%s)) [%d].\n",
509 ttl, ret, strerror(errno), sockfd);
463 510
464 511 return 0; return 0;
465 512 } }
 
... ... static int set_reuseaddr(int sockfd)
472 519 return 0; return 0;
473 520
474 521 ret = old_setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); ret = old_setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
475 my_syslog(LOG_INFO, "force_bind: changing reuseaddr to %u (ret=%d) [%d].\n",
476 reuseaddr, ret, sockfd);
522 my_syslog(LOG_INFO, "force_bind: changing reuseaddr to %u (ret=%d(%s)) [%d].\n",
523 reuseaddr, ret, strerror(errno), sockfd);
477 524
478 525 return 0; return 0;
479 526 } }
 
... ... static int set_nodelay(int sockfd)
486 533 return 0; return 0;
487 534
488 535 ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); ret = old_setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
489 my_syslog(LOG_INFO, "force_bind: changing nodelay to %u (ret=%d) [%d].\n",
490 nodelay, ret, sockfd);
536 my_syslog(LOG_INFO, "force_bind: changing nodelay to %u (ret=%d(%s)) [%d].\n",
537 nodelay, ret, strerror(errno), sockfd);
491 538
492 539 return 0; return 0;
493 540 } }
494 541
542 /*
543 * Set IPv6 flowinfo
544 */
545 static void set_flowinfo(int sockfd, struct private *p)
546 {
547 int ret;
548 int yes;
549 struct in6_flowlabel_req mgr;
550 struct sockaddr_in6 *sa6;
551
552 if (force_flowinfo == 0)
553 return;
554
555 if (p->domain != AF_INET6)
556 return;
557
558 if ((p->flags & FB_FLAGS_FLOWINFO_CALLED) != 0)
559 return;
560
561 /* In case of error we cannot do anything, anyway */
562 p->flags |= FB_FLAGS_FLOWINFO_CALLED;
563
564 /* Prepare flow */
565 memset(&mgr, 0, sizeof(mgr));
566 sa6 = (struct sockaddr_in6 *) &p->dest;
567 memcpy(&mgr.flr_dst, &sa6->sin6_addr, sizeof(struct in6_addr));
568 mgr.flr_label = htonl(flowinfo & IPV6_FLOWLABEL_MASK);
569 mgr.flr_action = IPV6_FL_A_GET;
570 mgr.flr_share = IPV6_FL_S_ANY;
571 mgr.flr_flags = IPV6_FL_F_CREATE;
572 ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &mgr, sizeof(mgr));
573 my_syslog(LOG_INFO, "force_bind: flow mgr (ret=%d(%s)) [%d].\n",
574 ret, strerror(errno), sockfd);
575
576 yes = 1;
577 ret = old_setsockopt(sockfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &yes, sizeof(yes));
578 my_syslog(LOG_INFO, "force_bind: changing flowinfo to 'yes' (ret=%d(%s)) [%d].\n",
579 ret, strerror(errno), sockfd);
580 }
581
582
495 583 /* /*
496 584 * Alters a struct sockaddr, based on environment variables * Alters a struct sockaddr, based on environment variables
497 585 */ */
 
... ... static void alter_sa(const int sockfd, struct sockaddr *sa)
506 594 int err; int err;
507 595
508 596 switch (sa->sa_family) { switch (sa->sa_family) {
509 case AF_INET:
510 sa4 = (struct sockaddr_in *) sa;
511 p = &sa4->sin_addr;
512 pport = &sa4->sin_port;
513 force_address = force_address_v4;
514 force_port = force_port_v4;
515 break;
516
517 case AF_INET6:
518 sa6 = (struct sockaddr_in6 *) sa;
519 p = &sa6->sin6_addr.s6_addr;
520 pport = &sa6->sin6_port;
521 force_address = force_address_v6;
522 force_port = force_port_v6;
523 break;
524
525 default:
526 my_syslog(LOG_INFO, "force_bind: unsupported family=%u [%d]!\n",
527 sa->sa_family, sockfd);
528 return;
597 case AF_INET:
598 sa4 = (struct sockaddr_in *) sa;
599 p = &sa4->sin_addr;
600 pport = &sa4->sin_port;
601 force_address = force_address_v4;
602 force_port = force_port_v4;
603 break;
604
605 case AF_INET6:
606 sa6 = (struct sockaddr_in6 *) sa;
607 p = &sa6->sin6_addr.s6_addr;
608 pport = &sa6->sin6_port;
609 force_address = force_address_v6;
610 force_port = force_port_v6;
611 break;
612
613 default:
614 my_syslog(LOG_INFO, "force_bind: unsupported family=%u [%d]!\n",
615 sa->sa_family, sockfd);
616 return;
529 617 } }
530 618
531 619 if (force_address != NULL) { if (force_address != NULL) {
 
... ... static void alter_sa(const int sockfd, struct sockaddr *sa)
539 627
540 628 if (force_port != -1) if (force_port != -1)
541 629 *pport = htons(force_port); *pport = htons(force_port);
630 }
631
632 /*
633 * Alter destination sa
634 */
635 static void alter_dest_sa(int sockfd, struct sockaddr_storage *ss, socklen_t len)
636 {
637 struct node *q;
638 struct sockaddr *sa = (struct sockaddr *) ss;
639 struct sockaddr_in6 *sa6;
640
641 init();
642
643 /* We do not touch non network sockets */
644 q = get(sockfd);
645 if ((q == NULL) || ((q->priv.flags & FB_FLAGS_NETSOCK) == 0))
646 return;
647
648 switch (sa->sa_family) {
649 case AF_INET6:
650 sa6 = (struct sockaddr_in6 *) sa;
651 if (force_flowinfo == 1) {
652 my_syslog(LOG_INFO, "force_bind: changing flowinfo from 0x%x to 0x%x [%d]!\n",
653 ntohl(sa6->sin6_flowinfo), flowinfo, sockfd);
654 sa6->sin6_flowinfo = htonl(flowinfo);
655 }
656 break;
657 }
542 658
659 memcpy(&q->priv.dest, ss, len);
660 q->priv.dest_len = len;
661
662 set_flowinfo(sockfd, &q->priv);
543 663 } }
544 664
545 665 /* /*
 
... ... int setsockopt(int sockfd, int level, int optname, const void *optval,
635 755 void socket_create_callback(const int sockfd, int domain, int type) void socket_create_callback(const int sockfd, int domain, int type)
636 756 { {
637 757 struct private p; struct private p;
638 socklen_t type_len;
758 socklen_t len;
639 759 int err; int err;
640 760
641 761 init(); init();
642 762
643 if (type == -1) {
644 type_len = sizeof(type);
645 err = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &type, &type_len);
763 if (domain == -1) {
764 len = sizeof(domain);
765 err = getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, (void *) &domain, &len);
766 if (err != 0)
767 my_syslog(LOG_INFO, "force_bind: Cannot get socket domain err=%d (%s) [%d].\n",
768 err, strerror(errno), sockfd);
769
770 len = sizeof(type);
771 err = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &type, &len);
646 772 if (err != 0) if (err != 0)
647 773 my_syslog(LOG_INFO, "force_bind: Cannot get socket type err=%d (%s) [%d].\n", my_syslog(LOG_INFO, "force_bind: Cannot get socket type err=%d (%s) [%d].\n",
648 774 err, strerror(errno), sockfd); err, strerror(errno), sockfd);
 
... ... void socket_create_callback(const int sockfd, int domain, int type)
660 786 p.domain = domain; p.domain = domain;
661 787 p.type = type; p.type = type;
662 788 p.flags = FB_FLAGS_NETSOCK; p.flags = FB_FLAGS_NETSOCK;
789 memset(&p.dest, 0, sizeof(struct sockaddr_storage));
790 p.dest_len = 0;
663 791 add(sockfd, &p); add(sockfd, &p);
664 792 } }
665 793
 
... ... ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
789 917 const struct sockaddr *dest_addr, socklen_t addrlen) const struct sockaddr *dest_addr, socklen_t addrlen)
790 918 { {
791 919 ssize_t n; ssize_t n;
920 struct sockaddr_storage new_dest;
792 921
793 922 change_local_binding(sockfd); change_local_binding(sockfd);
794 n = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
923
924 memcpy(&new_dest, dest_addr, addrlen);
925 alter_dest_sa(sockfd, &new_dest, addrlen);
926
927 n = old_sendto(sockfd, buf, len, flags, (struct sockaddr *) &new_dest, addrlen);
795 928 bw(sockfd, n); bw(sockfd, n);
796 929
797 930 return n; return n;
 
... ... ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
803 936 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
804 937 { {
805 938 ssize_t n; ssize_t n;
939 /* see below
940 struct sockaddr_storage new_dest;
941 */
806 942
807 943 change_local_binding(sockfd); change_local_binding(sockfd);
944
945 /* TODO: how do we alter flowinfo in this case?!
946 memcpy(&new_dest, dest, addrlen);
947 alter_dest_sa(sockfd, &new_dest, addrlen);
948 */
949
808 950 n = old_sendmsg(sockfd, msg, flags); n = old_sendmsg(sockfd, msg, flags);
809 951 bw(sockfd, n); bw(sockfd, n);
810 952
 
... ... int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
832 974
833 975 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
834 976 { {
977 struct sockaddr_storage new_dest;
978
835 979 change_local_binding(sockfd); change_local_binding(sockfd);
836 return old_connect(sockfd, addr, addrlen);
980
981 memcpy(&new_dest, addr, addrlen);
982 alter_dest_sa(sockfd, &new_dest, addrlen);
983
984 return old_connect(sockfd, (struct sockaddr *) &new_dest, addrlen);
837 985 } }
838 986
File test_client6-1.sh added (mode: 100755) (index 0000000..eeea81b)
1 #!/bin/sh
2
3 export FORCE_NET_VERBOSE=1
4 export FORCE_NET_FLOWINFO=0x7812345
5
6 export LD_PRELOAD="${LD_PRELOAD}:./force_bind.so"
7
8 #gdb ./test_client6
9 #valgrind -v --db-attach=yes ./test_client6 "${@}"
10 strace -o ${0}.strace -x -f -s200 ./test_client6 "${@}"
File test_client6.c added (mode: 100644) (index 0000000..6b148a7)
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
15 int main(int argc, char *argv[])
16 {
17 int sock, err;
18 struct sockaddr_storage ss;
19 struct sockaddr_in6 sa, *sa2 = (struct sockaddr_in6 *) &ss;
20 socklen_t ss_len;
21 int port = 4444;
22 char junk[128];
23 char *dest = "::1";
24
25 ss_len = sizeof(struct sockaddr_storage);
26
27 sock = socket(AF_INET6, SOCK_STREAM, 0);
28 if (sock == -1) {
29 perror("socket");
30 return 1;
31 }
32
33 if (argc >= 2)
34 dest = argv[1];
35
36 if (argc >= 3)
37 port = strtol(argv[2], NULL, 10);
38
39 err = getsockname(sock, (struct sockaddr *) &ss, &ss_len);
40 if (err != 0) {
41 perror("getsockname");
42 return 1;
43 }
44 fprintf(stderr, "Socket bound to %s/%d, flowinfo 0x%x.\n",
45 inet_ntop(sa2->sin6_family, &sa2->sin6_addr, junk, ss_len),
46 ntohs(sa2->sin6_port), ntohl(sa2->sin6_flowinfo));
47
48 memset(&sa, 0, sizeof(struct sockaddr_in6));
49 sa.sin6_family = AF_INET6;
50 sa.sin6_port = htons(port);
51 err = inet_pton(AF_INET6, dest, &sa.sin6_addr);
52 if (err != 1) {
53 perror("inet_pton");
54 return 1;
55 }
56
57 err = connect(sock, (struct sockaddr *) &sa, sizeof(sa));
58 if (err == -1) {
59 perror("connect");
60 /* ignore error */
61 }
62
63 err = getsockname(sock, (struct sockaddr *) &ss, &ss_len);
64 if (err != 0) {
65 perror("getsockname");
66 return 1;
67 }
68 fprintf(stderr, "Socket bound to %s/%d, flowinfo 0x%x (after connect called).\n",
69 inet_ntop(sa2->sin6_family, &sa2->sin6_addr, junk, ss_len),
70 ntohs(sa2->sin6_port), ntohl(sa2->sin6_flowinfo));
71
72 close(sock);
73
74 return 0;
75 }
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