ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 марта
874658 Топик полностью
fk0, легенда (02.10.2018 00:43, просмотров: 94) ответил Nikolay_Po на Если не разделять IP по подсетям, то как тогда "объяснять" хост-процессу, через какой из IP нужно выходить на конкретное устройство?
Ну если разделять по подсетям, то и другой прибор нужно в другую подсеть унести... Объяснять можно путём фиксации адреса в момент открытия сокета (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]