// if the caller attempted to bind to 0.0.0.0 or ::, then change it to // this node's public IP address int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { errno = 0; // save the original bind() call void *handle = dlopen( LIBC_PATH, RTLD_LAZY ); if (!handle) { handle = dlopen( LIBC_PATH_DEBIAN, RTLD_LAZY ); if( !handle ) { fprintf( stderr, "Error loading libc.so.6\n" ); fflush( stderr ); return -1; } } bind_original = dlsym(handle, "bind"); if( bind_original == NULL ) { fprintf( stderr, "Error loading bind symbol\n" ); fflush( stderr ); return -1; } int tried_normal_bind = 0; int rc = is_addr_any( addr ); fprintf( stderr, "bind(%d, %p, %ld)\n", sockfd, addr, addrlen); if( rc > 0 ) { rc = 0; // rewrite this address struct sockaddr_storage new_addr; memset( &new_addr, 0, sizeof(struct sockaddr_storage)); memcpy( &new_addr, addr, addrlen ); rc = get_public_ip( (struct sockaddr*)&new_addr ); if( rc == -EINVAL ) { // this will happen for DHCP, so bind the normal way fprintf(stderr, "WARNING: could not get IP address; attempting normal bind."); rc = bind_original( sockfd, (struct sockaddr*)&new_addr, addrlen ); fprintf(stderr, "normal bind rc = %d, errno = %d\n", rc, errno ); tried_normal_bind = 1; } else if( rc != 0 ) { rc = -1; } if( rc == 0 && tried_normal_bind == 0 ) { debug( addr, (struct sockaddr*)&new_addr ); rc = bind_original( sockfd, (struct sockaddr*)&new_addr, addrlen ); fprintf( stderr, "re-addressed bind rc = %d, errno = %d\n", rc, errno); // save this result if( rc == 0 ) { cache_public_ip( (struct sockaddr*)&new_addr); } } } else { rc = bind_original( sockfd, (struct sockaddr*)addr, addrlen ); fprintf( stderr, "bind rc = %d, errno = %d\n", rc, errno); } return rc; }
int main() { char public_ip[16] = {0}; int ret = get_public_ip(16, public_ip); return 0; }