add multicast interface support

This commit is contained in:
Martin/Geno 2018-08-05 19:53:04 +02:00
parent 9285147699
commit 69ff5a62ca
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
3 changed files with 55 additions and 26 deletions

View File

@ -32,10 +32,11 @@ struct option longopts[] = {
{"addr", required_argument, 0, 6}, {"addr", required_argument, 0, 6},
{"maddr", required_argument, 0, 7}, {"maddr", required_argument, 0, 7},
{"port", required_argument, 0, 8}, {"port", required_argument, 0, 8},
{"ifname", required_argument, 0, 9}, {"if", required_argument, 0, 9},
{"mif", required_argument, 0, 10},
// other extended option // other extended option
{"socket-learning", optional_argument, 0, 10}, {"socket-learning", optional_argument, 0, 11},
{"socket-always-answer", optional_argument, 0, 11}, {"socket-always-answer", optional_argument, 0, 12},
#endif #endif
}; };
@ -64,7 +65,8 @@ void usage(int c) {
printf(" --addr listen on ip address (current: %s)\n", addr); printf(" --addr listen on ip address (current: %s)\n", addr);
printf(" --maddr listen and request on multcast address (current: %s)\n", maddr); printf(" --maddr listen and request on multcast address (current: %s)\n", maddr);
printf(" --port listen on port (current: %s)\n", port); printf(" --port listen on port (current: %s)\n", port);
printf(" --ifname listen on interface for multicast (current: %s)\n", ifname); printf(" --if listen on interface (current: %s)\n", ifname);
printf(" --mif listen on interface for multicast (current: %s)\n", ifname);
printf("\nother extended options:\n"); printf("\nother extended options:\n");
printf(" --socket-learning learn clients during listen on socket (current: %s)\n", BOOL2STR(config_client_socket_learning)); printf(" --socket-learning learn clients during listen on socket (current: %s)\n", BOOL2STR(config_client_socket_learning));
printf(" --socket-always-answer answer on socket only with useful information (current: %s)\n", BOOL2STR(config_socket_always_answer)); printf(" --socket-always-answer answer on socket only with useful information (current: %s)\n", BOOL2STR(config_socket_always_answer));
@ -167,14 +169,17 @@ int main(int argc, char *argv[])
case 9: case 9:
ifname = optarg; ifname = optarg;
break; break;
// other extended option
case 10: case 10:
// skip - check later after init socket
break;
// other extended option
case 11:
if(optarg) if(optarg)
config_client_socket_learning = atoi(optarg); config_client_socket_learning = atoi(optarg);
else else
config_client_socket_learning = !config_client_socket_learning; config_client_socket_learning = !config_client_socket_learning;
break; break;
case 11: case 12:
if(optarg) if(optarg)
config_socket_always_answer = atoi(optarg); config_socket_always_answer = atoi(optarg);
else else
@ -215,6 +220,15 @@ int main(int argc, char *argv[])
log_error("exit with error on socket init\n"); log_error("exit with error on socket init\n");
return ret; return ret;
} }
c = 0;
indexptr = 0;
while ((c = getopt_long(argc, argv, "vht:s:fp",longopts, &indexptr)) != -1) {
switch (c) {
case 10:
socket_join_mcast(optarg);
break;
}
}
#endif #endif
uloop_run(); uloop_run();
uloop_done(); uloop_done();

View File

@ -6,8 +6,9 @@
#include "socket_handler.h" #include "socket_handler.h"
static struct uloop_fd server; static struct uloop_fd server;
struct sockaddr_in6 ownaddr; int info_sock = 0;
struct sockaddr_in6 client_addr; struct sockaddr_in6 own_addr;
struct sockaddr_in6 multicast_addr;
int socket_info(struct socket_msg *info) { int socket_info(struct socket_msg *info) {
int ret = 0; int ret = 0;
@ -19,7 +20,7 @@ int socket_info(struct socket_msg *info) {
return ret; return ret;
} }
ret = sendto(server.fd, msg, REQUEST_MAXLEN, 0, (struct sockaddr *)&client_addr, sizeof(client_addr)); ret = sendto(info_sock, msg, REQUEST_MAXLEN, 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr));
if (ret < 0) { if (ret < 0) {
log_error("socket_info: could not send message: %d\n", ret); log_error("socket_info: could not send message: %d\n", ret);
} }
@ -46,7 +47,7 @@ int socket_request_timeout(struct socket_msg *request, struct socket_msg *answer
return -1; return -1;
} }
if(bind(sock, (struct sockaddr*)&ownaddr, sizeof(ownaddr))) { if(bind(sock, (struct sockaddr*)&own_addr, sizeof(own_addr))) {
log_error("socket_request: could not bind to addr\n"); log_error("socket_request: could not bind to addr\n");
return -1; return -1;
} }
@ -58,7 +59,7 @@ int socket_request_timeout(struct socket_msg *request, struct socket_msg *answer
return -1; return -1;
} }
ret = sendto(sock, msg, REQUEST_MAXLEN, 0, (struct sockaddr *)&client_addr, sizeof(client_addr)); ret = sendto(sock, msg, REQUEST_MAXLEN, 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr));
if (ret < 0) { if (ret < 0) {
close(sock); close(sock);
log_error("socket_request: could not send message: %d\n", ret); log_error("socket_request: could not send message: %d\n", ret);
@ -168,40 +169,45 @@ static void server_cb(struct uloop_fd *fd, unsigned int events) {
int socket_init(char *ifname, char *socket_bind, char *socket_maddr, char *socket_port) { int socket_init(char *ifname, char *socket_bind, char *socket_maddr, char *socket_port) {
server.cb = server_cb; server.cb = server_cb;
server.fd = usock(USOCK_UDP | USOCK_SERVER | USOCK_IPV6ONLY | USOCK_NUMERIC, socket_bind, socket_port); server.fd = usock(USOCK_UDP | USOCK_SERVER | USOCK_IPV6ONLY | USOCK_NUMERIC, "::", socket_port);
if (server.fd < 0) { if (server.fd < 0) {
log_error("socket: error create socket to recv\n");
return 1;
}
info_sock = usock(USOCK_UDP | USOCK_IPV6ONLY | USOCK_NUMERIC, socket_bind, socket_port);
if (info_sock < 0) {
log_error("socket: error create socket to send\n");
return 1; return 1;
} }
client_addr.sin6_family = AF_INET6; multicast_addr.sin6_family = AF_INET6;
client_addr.sin6_port = htons(atoi(socket_port)); multicast_addr.sin6_port = htons(atoi(socket_port));
client_addr.sin6_scope_id = if_nametoindex(ifname); multicast_addr.sin6_scope_id = if_nametoindex(ifname);
ownaddr.sin6_family = AF_INET6; own_addr.sin6_family = AF_INET6;
ownaddr.sin6_scope_id = client_addr.sin6_scope_id; own_addr.sin6_scope_id = multicast_addr.sin6_scope_id;
if(!inet_pton(AF_INET6, socket_bind, &ownaddr.sin6_addr)) { if(!inet_pton(AF_INET6, socket_bind, &own_addr.sin6_addr)) {
log_error("socket: could not parse address for socket_request\n"); log_error("socket: could not parse address for socket_request\n");
return -1; return -1;
} }
// listen multicast // listen multicast
if (!inet_pton(AF_INET6, socket_maddr, &client_addr.sin6_addr)) { if (!inet_pton(AF_INET6, socket_maddr, &multicast_addr.sin6_addr)) {
log_error("socket: invalid multicast group\n"); log_error("socket: invalid multicast group\n");
return -1; return -1;
} }
struct ipv6_mreq mreq = { if (socket_join_mcast(ifname) < 0) {
.ipv6mr_multiaddr = client_addr.sin6_addr,
.ipv6mr_interface = client_addr.sin6_scope_id,
};
if (setsockopt(server.fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) {
log_error("socket: unable to join multicast group: %d\n", errno); log_error("socket: unable to join multicast group: %d\n", errno);
return -1; return -1;
} }
int loop = 0; int loop = 0;
if(setsockopt(info_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
log_error("socket_request: unable to disable listen/loop own multicast package: %d\n", errno);
return -1;
}
if(setsockopt(server.fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { if(setsockopt(server.fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
log_error("socket_request: unable to disable listen/loop own multicast package: %d\n", errno); log_error("socket_request: unable to disable listen/loop own multicast package: %d\n", errno);
return -1; return -1;
@ -212,6 +218,14 @@ int socket_init(char *ifname, char *socket_bind, char *socket_maddr, char *socke
return 0; return 0;
} }
int socket_join_mcast(char *ifname) {
struct ipv6_mreq mreq = {
.ipv6mr_multiaddr = multicast_addr.sin6_addr,
.ipv6mr_interface = if_nametoindex(ifname),
};
return setsockopt(server.fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq));
}
void socket_close() { void socket_close() {
uloop_fd_delete(&server); uloop_fd_delete(&server);
//ustream_free(&(server.fd)); //ustream_free(&(server.fd));

View File

@ -4,7 +4,8 @@
#include "include.h" #include "include.h"
#include "socket_msg.h" #include "socket_msg.h"
int socket_init(); int socket_init(char *ifname, char *socket_bind, char *socket_maddr, char *socket_port);
int socket_join_mcast(char *ifname);
void socket_close(); void socket_close();
int socket_info(struct socket_msg *info); int socket_info(struct socket_msg *info);