Ну если разделять по подсетям, то и другой прибор нужно в другую подсеть унести... Объяснять можно путём фиксации адреса в момент открытия сокета (bind(2) вызвать после socket(2)). Как-то так, как ниже показано. Компилировать через gcc file.c -shared -o libfakebind.so и через LD_PRELOAD подгружать перед использованием. В переменной окружения FAKEBIND=1.2.3.4 задаётся как бы адрес своего порта/интерфейса. Здесь предполагается, что bind(2) таки вызовется программой-клиентом (а если бы не вызывалось, а порт назначался автомагически -- то и проблемы бы не было).
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <assert.h>
#include <err.h>
#include <dlfcn.h>
static in_addr_t force_addr = 0;
void __attribute__ ((constructor)) fakebind_init(void)
{
const char *args = getenv("FAKEBIND");
if (args == NULL) return;
struct addrinfo hints, *result, *rp;
memset(&hints, 0, sizeof(hints));
hints.ai_family=AF_INET;
hints.ai_socktype=SOCK_DGRAM;
int e = getaddrinfo(args, NULL, &hints, &result);
if (e!=0)
errx(1, "fakebind: getaddrinfo %s: %s\n", args, gai_strerror(e));
for (rp=result; rp!=NULL; rp=rp->ai_next) {
if (rp->ai_family == AF_INET) {
force_addr = ((struct sockaddr_in*)rp->ai_addr)->sin_addr.s_addr;
#if 1
struct in_addr in; in.s_addr = force_addr;
fprintf(stderr, "bind 0.0.0.0 to %s\n", inet_ntoa(in));
#endif
break;
}
}
freeaddrinfo(result);
if (rp==NULL)
errx(1, "fakebind: %s: no INET address to bind\n", args);
}
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
struct sockaddr_in subst;
int val;
socklen_t len = sizeof(val);
if (getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, &val, &len) < 0)
warn("getsockopt");
else if (force_addr != 0) {
const struct sockaddr_in *in = (struct sockaddr_in*)addr;
if (in->sin_family==AF_INET) {
assert(addrlen >= sizeof(struct sockaddr_in));
if (in->sin_addr.s_addr == 0) {
subst = *in;
subst.sin_addr.s_addr = force_addr;
addr = (struct sockaddr*)&subst;
addrlen = sizeof(subst);
}
}
}
int (*real_bind)(int, const struct sockaddr *, socklen_t) = dlsym(RTLD_NEXT, "bind");
assert(real_bind!=NULL);
return real_bind(sockfd, addr, addrlen);
}
[ZX]