#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include // For if_nametoindex // Build with: gcc -shared -fPIC bind.c -o libbind.so -ldl // Typedef for the original `bind()` function typedef int (*pfn_bind_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); // Hardcoded adapter name for the IPv6 link-local address #define HARDCODED_ADAPTER "enp5s0f3u1" // Our custom `bind()` function int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { // Get the original `bind()` function pfn_bind_t original_bind = (pfn_bind_t)dlsym(RTLD_NEXT, "bind"); // Get environment variables const char *bind_addr_env = getenv("BIND_ADDR"); const char *bind_addr6_env = getenv("BIND_ADDR6"); // Handle IPv4 binding if (addr->sa_family == AF_INET) { if (!bind_addr_env) { fprintf(stderr, "bind(): BIND_ADDR not set, skipping IPv4 bind\n"); return 0; // Simulate success } struct sockaddr_in new_addr; memcpy(&new_addr, addr, sizeof(new_addr)); // Copy the original address // Replace the IP address if (inet_pton(AF_INET, bind_addr_env, &new_addr.sin_addr) != 1) { fprintf(stderr, "Invalid BIND_ADDR: %s\n", bind_addr_env); return 0; // Simulate success even if the address is invalid } // Log the modification char original_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr, original_ip, INET_ADDRSTRLEN); fprintf(stderr, "bind(): Replacing IPv4 address %s with %s\n", original_ip, bind_addr_env); // Call the original `bind()` with the modified address return original_bind(sockfd, (struct sockaddr *)&new_addr, addrlen); } // Handle IPv6 binding if (addr->sa_family == AF_INET6) { if (!bind_addr6_env) { fprintf(stderr, "bind(): BIND_ADDR6 not set, skipping IPv6 bind\n"); return 0; // Simulate success } struct sockaddr_in6 new_addr6; memcpy(&new_addr6, addr, sizeof(new_addr6)); // Copy the original address // Replace the IP address if (inet_pton(AF_INET6, bind_addr6_env, &new_addr6.sin6_addr) != 1) { fprintf(stderr, "Invalid BIND_ADDR6: %s\n", bind_addr6_env); return 0; // Simulate success even if the address is invalid } // Set the scope ID using the hardcoded adapter name new_addr6.sin6_scope_id = if_nametoindex(HARDCODED_ADAPTER); if (new_addr6.sin6_scope_id == 0) { fprintf(stderr, "bind(): Failed to get scope ID for adapter %s\n", HARDCODED_ADAPTER); return 0; // Simulate success even if scope ID can't be set } // Log the modification char original_ip6[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr, original_ip6, INET6_ADDRSTRLEN); fprintf(stderr, "bind(): Replacing IPv6 address %s with %s and scope ID %d\n", original_ip6, bind_addr6_env, new_addr6.sin6_scope_id); // Call the original `bind()` with the modified address return original_bind(sockfd, (struct sockaddr *)&new_addr6, addrlen); } // If it's neither IPv4 nor IPv6, call the original `bind()` as-is return original_bind(sockfd, addr, addrlen); }