У меня есть следующий код C для UDP-сервера, который будет привязываться к адресу ipv6 вторичного интерфейса tap0.Не удается получить пакеты UDP/IPv6 на вторичном интерфейсе
context_t *
new_context(const struct sockaddr *listen_addr, size_t addr_size) {
context_t *c = malloc(sizeof(context_t));
time_t now;
int reuse = 1;
if (!listen_addr) {
fprintf(stderr, "no listen address specified\n");
return NULL;
}
srand(getpid()^time(&now));
if (!c) {
perror("init: malloc:");
return NULL;
}
memset(c, 0, sizeof(context_t));
c->sockfd = socket(listen_addr->sa_family, SOCK_DGRAM, 0);
if (c->sockfd < 0) {
perror("new_context: socket");
goto onerror;
}
if (setsockopt(c->sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
perror("setsockopt SO_REUSEADDR");
if (bind (c->sockfd, listen_addr, addr_size) < 0) {
perror("new_context: bind");
goto onerror;
}
return c;
onerror:
if (c->sockfd >= 0)
close (c->sockfd);
free(c);
return NULL;
}
context_t *
get_context(const char *ipaddress, const char *port, unsigned int scopeId) {
int s;
context_t* ctx;
struct addrinfo hints;
struct addrinfo *result, *rp;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL;
s = getaddrinfo(ipaddress, port, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
return NULL;
}
/* iterate through results until success */
for (rp = result; rp != NULL; rp = rp->ai_next) {
ctx = new_context(rp->ai_addr, rp->ai_addrlen);
if (ctx) {
if (rp->ai_family == PF_INET6) {
struct sockaddr_in6* pSadrIn6 = (struct sockaddr_in6*) rp->ai_addr;
if (pSadrIn6->sin6_scope_id == 0) {
pSadrIn6->sin6_scope_id = scopeId;
} /* End IF the scope ID wasn't set. */
}
goto finish;
}
}
fprintf(stderr, "no context available for interface '%s'\n", node);
finish:
freeaddrinfo(result);
return ctx;
}
Устройство tap0 имеет следующие данные:
tap0 Link encap:Ethernet HWaddr ce:23:fc:81:7f:65
inet6 addr: fe80::cc23:fcff:fe81:7f65/64 Scope:Link
inet6 addr: aaaa::1/64 Scope:Global
Я бегу приведенный выше код с помощью следующей команды:
./server -A aaaa::1
Но это не в состоянии слушать сообщения, приходящие на адрес aaaa :: 1 на tap0. Я вижу пакеты на дампе проводов на интерфейсе tap0. Интересно, что сервер, запущенный из указанной выше команды (и кода), может получать сообщения через localhost. Таким образом, если я выполняю следующую команду, сервер получает сообщения:
nc -6 -vvv -u aaaa::1 61616 < /tmp/send_to_node_raw
Вышеуказанная команда отправки и приема выполняется через localhost. Можно ли каким-либо образом программно получать сообщения UDP/IPv6 на вторичных интерфейсах?
Что такое 'scopeId', который вы устанавливаете? Действительно ли это «1»? –
Это просто один интерфейс. И помните, что bind (2) «связывается» с адресами, а не с интерфейсами, то есть пакеты с dst addr aaaa :: 1 будут получены максимум. –
@Nikolai: Я устанавливаю scopeInd как tap0. –