From 883afba4fe080c84f0ee896c41a81df20683ea03 Mon Sep 17 00:00:00 2001 From: "7u83@mail.ru" <7u83@mail.ru@noemail.net> Date: Wed, 17 Feb 2016 19:26:59 +0000 Subject: [PATCH] sockilist_find_reply_socket works now for IPv6 For IPv6 and IPv4 a socket with a good port is chosen for reply. FossilOrigin-Name: 87778f4dd8978b40a3b818efcd610c845ee990337c74ce53b42f12cc2ed4dc2e --- src/ac/socklist.c | 329 ++++++++++++++++++++++++++-------------------- 1 file changed, 190 insertions(+), 139 deletions(-) diff --git a/src/ac/socklist.c b/src/ac/socklist.c index 5f7f9330..959e277a 100644 --- a/src/ac/socklist.c +++ b/src/ac/socklist.c @@ -32,23 +32,27 @@ #include "socklist.h" -struct socklistelem * socklist=0; +#include "stdio.h" + + +struct socklistelem *socklist = 0; int socklist_len; static pthread_mutex_t socklist_mutex; -static int socklist_wtpcount=0; +static int socklist_wtpcount = 0; int socklist_init() { - if (pthread_mutex_init(&socklist_mutex,NULL)) + if (pthread_mutex_init(&socklist_mutex, NULL)) return 0; socklist = malloc(sizeof(struct socklistelem) * SOCKLIST_SIZE); - memset(socklist,0,sizeof(struct socklistelem) * SOCKLIST_SIZE); - if (!socklist){ - cw_log(LOG_ERR,"Fatal error while initializing socklist: %s",strerror(errno)); + memset(socklist, 0, sizeof(struct socklistelem) * SOCKLIST_SIZE); + if (!socklist) { + cw_log(LOG_ERR, "Fatal error while initializing socklist: %s", + strerror(errno)); return 0; } @@ -70,11 +74,11 @@ void socklist_unlock() void socklist_destroy() { int i; - for(i=0; isa_family != socklist[i].addr.sa_family) + continue; + + + /* the first fd would be always the best, if we don't * find later a better one */ - if (bestsockfd == -1){ - bestsockfd = socklist[i].sockfd; + if (bestindex == -1) { + bestindex = i; continue; } + /* we want first the same port */ + if( sock_getport(&socklist[i].addr) != port){ + continue; + } + + /* if we havn't already found a socket with same port + * this is now our best socket*/ + if( sock_getport(&socklist[bestindex].addr) != port){ + bestindex=i; + } + + + + /* the next checks only aply to IPv4 */ + if (socklist[i].addr.sa_family != AF_INET) + continue; + /* get our source address and netmask */ - uint32_t addr = ((struct sockaddr_in*)&socklist[i].addr)->sin_addr.s_addr; - uint32_t mask = ((struct sockaddr_in*)&socklist[i].netmask)->sin_addr.s_addr; + uint32_t addr = + ((struct sockaddr_in *) &socklist[i].addr)->sin_addr.s_addr; + uint32_t mask = + ((struct sockaddr_in *) &socklist[i].netmask)->sin_addr.s_addr; /* get source of requested address */ - uint32_t saddr = ((struct sockaddr_in*)sa)->sin_addr.s_addr; + uint32_t saddr = ((struct sockaddr_in *) sa)->sin_addr.s_addr; - if ( (addr & mask)== (saddr & mask) ){ - bestsockfd = socklist[i].sockfd; + if ((addr & mask) == (saddr & mask)) { + bestindex = i; } - + } - return bestsockfd; + if (bestindex != -1) + return socklist[bestindex].sockfd; + return -1; } -static int find_reply_socket(struct sockaddr *sa,int bc) +static int find_reply_socket(struct sockaddr *sa, int bc) { //printf("Looking for best sock of: %s\n",sock_addr2str(sa)); int bestsockfd = -1; int i; - for (i=0; isa_family!=sn.ss_family) + if (sa->sa_family != sn.ss_family) continue; - if (sn.ss_family == AF_INET){ - int p1 = ntohs(((struct sockaddr_in *)sa)->sin_port); - int p2 = ntohs(((struct sockaddr_in *)&sn)->sin_port); + if (sn.ss_family == AF_INET) { + int p1 = ntohs(((struct sockaddr_in *) sa)->sin_port); + int p2 = ntohs(((struct sockaddr_in *) &sn)->sin_port); if (p1 != p2) continue; - + } @@ -161,16 +189,17 @@ static int find_reply_socket(struct sockaddr *sa,int bc) struct sockaddr_storage bcaddr; - if (!sock_getbroadcastaddr((struct sockaddr*)&sn,(struct sockaddr*)&bcaddr)) + if (!sock_getbroadcastaddr + ((struct sockaddr *) &sn, (struct sockaddr *) &bcaddr)) continue; - if (sock_cmpaddr((struct sockaddr*)&bcaddr,sa,0)) + if (sock_cmpaddr((struct sockaddr *) &bcaddr, sa, 0)) continue; bestsockfd = socklist[i].sockfd; - - } + + } return bestsockfd; } @@ -192,93 +221,102 @@ void socklist_del_connection(int index) -int socklist_add_multicast(const char * addr, const char * port,int ac_proto) +int socklist_add_multicast(const char *addr, const char *port, int ac_proto) { struct addrinfo hints; - struct addrinfo * res,*res0; - memset(&hints,0,sizeof(hints)); + struct addrinfo *res, *res0; + memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; - hints.ai_flags=AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; - int rc = getaddrinfo(addr,port,&hints,&res0); - if (rc!=0) { - cw_log(LOG_ERR,"Can't bind multicast address '%s': %s",addr,gai_strerror(rc)); + int rc = getaddrinfo(addr, port, &hints, &res0); + if (rc != 0) { + cw_log(LOG_ERR, "Can't bind multicast address '%s': %s", addr, + gai_strerror(rc)); return 0; } - for(res=res0; res; res=res->ai_next){ + for (res = res0; res; res = res->ai_next) { struct sockaddr *sa = res->ai_addr; int sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); /* create socket */ - if (sockfd==-1){ - cw_log(LOG_ERR,"Can't create multicast socket: %",strerror(errno)); + if (sockfd == -1) { + cw_log(LOG_ERR, "Can't create multicast socket: %", + strerror(errno)); continue; } /* bind address */ - if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) { + if (bind(sockfd, sa, sock_addrlen(sa)) < 0) { close(sockfd); - cw_log(LOG_ERR,"Can't bind multicast %s: %s",addr,strerror(errno)); + cw_log(LOG_ERR, "Can't bind multicast %s: %s", addr, + strerror(errno)); continue; } /* use setsockopt() to request that the kernel joins a multicast group */ void *opt; int optlen; - if (res->ai_addr->sa_family == AF_INET){ + if (res->ai_addr->sa_family == AF_INET) { struct ip_mreq mreq; - memset(&mreq,0,sizeof(mreq)); - struct sockaddr_in * sain = (struct sockaddr_in*)res->ai_addr; - mreq.imr_multiaddr.s_addr=sain->sin_addr.s_addr; - mreq.imr_interface.s_addr=htonl(INADDR_ANY); + memset(&mreq, 0, sizeof(mreq)); + struct sockaddr_in *sain = (struct sockaddr_in *) res->ai_addr; + mreq.imr_multiaddr.s_addr = sain->sin_addr.s_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); opt = &mreq; - optlen=sizeof(mreq); + optlen = sizeof(mreq); char sinin[100]; - sock_addrtostr((struct sockaddr*)sain,sinin,100); + sock_addrtostr((struct sockaddr *) sain, sinin, 100); - if (setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,opt,optlen) < 0) { + if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, opt, optlen) + < 0) { close(sockfd); - cw_log(LOG_ERR,"Can't add multicast membership %s: %s",addr,strerror(errno)); + cw_log(LOG_ERR, "Can't add multicast membership %s: %s", + addr, strerror(errno)); continue; } } - if (res->ai_addr->sa_family == AF_INET6){ + if (res->ai_addr->sa_family == AF_INET6) { struct ipv6_mreq mreq; - memset(&mreq,0,sizeof(mreq)); - struct sockaddr_in6 * sain6 = (struct sockaddr_in6*)res->ai_addr; -// mreq.ipv6mr_multiaddr.s_addr=sain->sin_addr.s_addr; - memcpy(&mreq.ipv6mr_multiaddr.s6_addr,&sain6->sin6_addr.s6_addr,sizeof(sain6->sin6_addr.s6_addr)); -// int si = sizeof(sain6->sin6_addr.s6_addr); + memset(&mreq, 0, sizeof(mreq)); + struct sockaddr_in6 *sain6 = (struct sockaddr_in6 *) res->ai_addr; +// mreq.ipv6mr_multiaddr.s_addr=sain->sin_addr.s_addr; + memcpy(&mreq.ipv6mr_multiaddr.s6_addr, &sain6->sin6_addr.s6_addr, + sizeof(sain6->sin6_addr.s6_addr)); +// int si = sizeof(sain6->sin6_addr.s6_addr); -// int i = sain6->sin6_addr.s6_addr; - mreq.ipv6mr_interface=0; //htonl(INADDR_ANY); +// int i = sain6->sin6_addr.s6_addr; + mreq.ipv6mr_interface = 0; //htonl(INADDR_ANY); opt = &mreq; - optlen=sizeof(mreq); - if (setsockopt(sockfd,IPPROTO_IPV6,IPV6_JOIN_GROUP,opt,optlen) < 0) { + optlen = sizeof(mreq); + if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, opt, optlen) + < 0) { close(sockfd); - cw_log(LOG_ERR,"Can't join multicast group %s: %s",addr,strerror(errno)); + cw_log(LOG_ERR, "Can't join multicast group %s: %s", addr, + strerror(errno)); continue; } } - int rfd = find_reply_socket(sa,0); + int rfd = find_reply_socket(sa, 0); - socklist[socklist_len].sockfd=sockfd; - socklist[socklist_len].reply_sockfd=rfd; - socklist[socklist_len].type=SOCKLIST_BCASTMCAST_SOCKET; - socklist[socklist_len].family=sa->sa_family; - socklist[socklist_len].ac_proto=ac_proto; + socklist[socklist_len].sockfd = sockfd; + socklist[socklist_len].reply_sockfd = rfd; + socklist[socklist_len].type = SOCKLIST_BCASTMCAST_SOCKET; + socklist[socklist_len].family = sa->sa_family; + socklist[socklist_len].ac_proto = ac_proto; socklist_len++; - cw_log(LOG_INFO,"Bound to multicast group: %s (fd=%i,r:%i)",addr,sockfd,rfd); + cw_log(LOG_INFO, "Bound to multicast group: %s (fd=%i,r:%i)", addr, + sockfd, rfd); } freeaddrinfo(res0); @@ -286,138 +324,151 @@ int socklist_add_multicast(const char * addr, const char * port,int ac_proto) } -int socklist_add_unicast(const char *addr, const char * port, int ac_proto) +int socklist_add_unicast(const char *addr, const char *port, int ac_proto) { struct addrinfo hints; - struct addrinfo * res,*res0; - memset(&hints,0,sizeof(hints)); + struct addrinfo *res, *res0; + memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; - hints.ai_flags=AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; - int rc = getaddrinfo(addr,port,&hints,&res0); - if (rc!=0) { - cw_log(LOG_ERR,"Can't bind unicast address '%s': %s",addr,gai_strerror(rc)); + int rc = getaddrinfo(addr, port, &hints, &res0); + if (rc != 0) { + cw_log(LOG_ERR, "Can't bind unicast address '%s': %s", addr, + gai_strerror(rc)); return 0; } - for(res=res0; res; res=res->ai_next){ + for (res = res0; res; res = res->ai_next) { char ifname[64]; struct sockaddr netmask; struct sockaddr broadcast; - ifname[0]=0; - rc = sock_getifinfo(res->ai_addr,ifname,&broadcast,&netmask); + ifname[0] = 0; + rc = sock_getifinfo(res->ai_addr, ifname, &broadcast, &netmask); if (!rc) { - cw_log(LOG_ERR,"No interface found for %s, can't bind.",addr); + cw_log(LOG_ERR, "No interface found for %s, can't bind.", addr); continue; } struct sockaddr *sa = res->ai_addr; int sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); /* create socket */ - if (sockfd==-1){ - cw_log(LOG_ERR,"Can't create unicast socket: %",strerror(errno)); + if (sockfd == -1) { + cw_log(LOG_ERR, "Can't create unicast socket: %s", + strerror(errno)); continue; } /* bind address */ - if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) { + if (bind(sockfd, sa, sock_addrlen(sa)) < 0) { close(sockfd); - cw_log(LOG_ERR,"Can't bind unicast socket %s: %s",addr,strerror(errno)); + cw_log(LOG_ERR, "Can't bind unicast socket %s: %s", addr, + strerror(errno)); continue; } - socklist[socklist_len].sockfd=sockfd; - socklist[socklist_len].reply_sockfd=sockfd; - socklist[socklist_len].family=sa->sa_family; - socklist[socklist_len].type=SOCKLIST_UNICAST_SOCKET; - socklist[socklist_len].ac_proto=ac_proto; - + socklist[socklist_len].sockfd = sockfd; + socklist[socklist_len].reply_sockfd = sockfd; + socklist[socklist_len].family = sa->sa_family; + socklist[socklist_len].type = SOCKLIST_UNICAST_SOCKET; + socklist[socklist_len].ac_proto = ac_proto; - if (res->ai_addr->sa_family == AF_INET ) { - memcpy(&socklist[socklist_len].netmask,&netmask,sock_addrlen(&netmask)); - memcpy(&socklist[socklist_len].addr,res->ai_addr,sock_addrlen(res->ai_addr)); - cw_log(LOG_INFO,"Bound to: %s (%i) on interface %s, netmask %s",addr,sockfd,ifname,sock_addr2str(&netmask)); - } - else{ - cw_log(LOG_INFO,"Bound to: %s (%i) on interface %s",addr,sockfd,ifname); + + if (res->ai_addr->sa_family == AF_INET) { + memcpy(&socklist[socklist_len].netmask, &netmask, + sock_addrlen(&netmask)); + memcpy(&socklist[socklist_len].addr, res->ai_addr, + sock_addrlen(res->ai_addr)); + cw_log(LOG_INFO, + "Bound to: %s:%s (%i) on interface %s, netmask %s", addr, + port, sockfd, ifname, sock_addr2str(&netmask)); + } else { + cw_log(LOG_INFO, "Bound to: %s:%s (%i) on interface %s", addr, + port, sockfd, ifname); } socklist_len++; } - freeaddrinfo(res0); + freeaddrinfo(res0); return 1; } -int socklist_add_broadcast(const char *addr, const char * port,int ac_proto) +int socklist_add_broadcast(const char *addr, const char *port, int ac_proto) { struct addrinfo hints; - struct addrinfo * res,*res0; - memset(&hints,0,sizeof(hints)); + struct addrinfo *res, *res0; + memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; - hints.ai_flags=AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; - int rc = getaddrinfo(addr,port,&hints,&res0); - if (rc!=0) { - cw_log(LOG_ERR,"Can't bind broadcast address '%s': %s",addr,gai_strerror(rc)); + int rc = getaddrinfo(addr, port, &hints, &res0); + if (rc != 0) { + cw_log(LOG_ERR, "Can't bind broadcast address '%s': %s", addr, + gai_strerror(rc)); return 0; } int sockfd; - for(res=res0; res; res=res->ai_next){ + for (res = res0; res; res = res->ai_next) { struct sockaddr *sa = res->ai_addr; sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); /* create socket */ - if (sockfd==-1){ - cw_log(LOG_ERR,"Can't create broadcast socket: %",strerror(errno)); + if (sockfd == -1) { + cw_log(LOG_ERR, "Can't create broadcast socket: %", + strerror(errno)); continue; } - #ifdef IP_BINDANY - struct sockaddr_in * sain = (struct sockaddr_in*)sa; - if (sain->sin_addr.s_addr==INADDR_BROADCAST ){ - int opt=1; - if (setsockopt(sockfd, IPPROTO_IP, IP_BINDANY, &opt, sizeof(opt))){ - cw_log(LOG_ERR,"Can't set sockopt IP_BIND_ANY: %s",strerror(errno)); + struct sockaddr_in *sain = (struct sockaddr_in *) sa; + if (sain->sin_addr.s_addr == INADDR_BROADCAST) { + int opt = 1; + if (setsockopt(sockfd, IPPROTO_IP, IP_BINDANY, &opt, sizeof(opt))) { + cw_log(LOG_ERR, "Can't set sockopt IP_BIND_ANY: %s", + strerror(errno)); continue; }; } -#endif +#endif /* bind address */ - if ( bind(sockfd,sa,sock_addrlen(sa)) < 0) { + if (bind(sockfd, sa, sock_addrlen(sa)) < 0) { close(sockfd); - sockfd=-1; - cw_log(LOG_ERR,"Can't bind broadcast %s: %s",addr,strerror(errno)); + sockfd = -1; + cw_log(LOG_ERR, "Can't bind broadcast %s: %s", addr, + strerror(errno)); continue; } - int rfd = find_reply_socket(sa,1); + int rfd = find_reply_socket(sa, 1); - socklist[socklist_len].sockfd=sockfd; - socklist[socklist_len].reply_sockfd=rfd; - socklist[socklist_len].type=SOCKLIST_BCASTMCAST_SOCKET; - socklist[socklist_len].family=sa->sa_family; - socklist[socklist_len].ac_proto=ac_proto; -// printf ("AC INIT PROTO : %d, i %i\n",ac_proto,socklist_len); -// printf ("sock proto %d\n",socklist[socklist_len].ac_proto); + socklist[socklist_len].sockfd = sockfd; + socklist[socklist_len].reply_sockfd = rfd; + socklist[socklist_len].type = SOCKLIST_BCASTMCAST_SOCKET; + socklist[socklist_len].family = sa->sa_family; + socklist[socklist_len].ac_proto = ac_proto; + + memcpy(&socklist[socklist_len].addr, res->ai_addr, + sock_addrlen(res->ai_addr)); + +// printf ("AC INIT PROTO : %d, i %i\n",ac_proto,socklist_len); +// printf ("sock proto %d\n",socklist[socklist_len].ac_proto); socklist_len++; - cw_log(LOG_INFO,"Bound to broadcast: %s:%s (%i,R:%i,I:%d)",addr,port,sockfd,rfd,socklist_len-1); + cw_log(LOG_INFO, "Bound to broadcast: %s:%s (%i,R:%i,I:%d)", addr, port, + sockfd, rfd, socklist_len - 1); } - freeaddrinfo(res0); - return 1; + freeaddrinfo(res0); + return 1; } - -