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
This commit is contained in:
		@ -32,6 +32,9 @@
 | 
			
		||||
#include "socklist.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "stdio.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct socklistelem *socklist = 0;
 | 
			
		||||
int socklist_len;
 | 
			
		||||
static pthread_mutex_t socklist_mutex;
 | 
			
		||||
@ -48,7 +51,8 @@ int socklist_init()
 | 
			
		||||
	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));
 | 
			
		||||
		cw_log(LOG_ERR, "Fatal error while initializing socklist: %s",
 | 
			
		||||
		       strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -84,44 +88,68 @@ void socklist_destroy()
 | 
			
		||||
 * @param sa source address
 | 
			
		||||
 * @return socket or -1 if no socket was found
 | 
			
		||||
 */
 | 
			
		||||
int socklist_find_reply_socket(struct sockaddr *sa)
 | 
			
		||||
int socklist_find_reply_socket(struct sockaddr *sa,int port)
 | 
			
		||||
{
 | 
			
		||||
	int bestsockfd=-1;
 | 
			
		||||
	int bestindex = -1;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < socklist_len; i++) {
 | 
			
		||||
		/* we can only determine a reply socket for IPv4 */
 | 
			
		||||
		if (socklist[i].addr.sa_family != AF_INET)
 | 
			
		||||
			continue;
 | 
			
		||||
		/* and we want only a unicast socket for reply */
 | 
			
		||||
		/* we want only an unicast socket for reply */
 | 
			
		||||
		if (socklist[i].type != SOCKLIST_UNICAST_SOCKET)
 | 
			
		||||
			continue;
 | 
			
		||||
		/* the first fd would be always the best if don't
 | 
			
		||||
 | 
			
		||||
		/* and we want only sockets with same sa_family */
 | 
			
		||||
		if (sa->sa_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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		if ((addr & mask) == (saddr & mask)) {
 | 
			
		||||
			bestsockfd = socklist[i].sockfd;
 | 
			
		||||
			bestindex = i;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bestsockfd;
 | 
			
		||||
	if (bestindex != -1)
 | 
			
		||||
		return socklist[bestindex].sockfd;
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int find_reply_socket(struct sockaddr *sa, int bc)
 | 
			
		||||
@ -161,7 +189,8 @@ 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))
 | 
			
		||||
@ -205,7 +234,8 @@ int socklist_add_multicast(const char * addr, const char * port,int ac_proto)
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
		cw_log(LOG_ERR, "Can't bind multicast address '%s': %s", addr,
 | 
			
		||||
		       gai_strerror(rc));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -214,7 +244,8 @@ int socklist_add_multicast(const char * addr, const char * port,int ac_proto)
 | 
			
		||||
		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));
 | 
			
		||||
			cw_log(LOG_ERR, "Can't create multicast socket: %",
 | 
			
		||||
			       strerror(errno));
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -222,7 +253,8 @@ int socklist_add_multicast(const char * addr, const char * port,int ac_proto)
 | 
			
		||||
		/* bind address */
 | 
			
		||||
		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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -242,9 +274,11 @@ int socklist_add_multicast(const char * addr, const char * port,int ac_proto)
 | 
			
		||||
			char 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;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -254,16 +288,19 @@ int socklist_add_multicast(const char * addr, const char * port,int ac_proto)
 | 
			
		||||
			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));
 | 
			
		||||
			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);
 | 
			
		||||
			opt = &mreq;
 | 
			
		||||
			optlen = sizeof(mreq);
 | 
			
		||||
			if (setsockopt(sockfd,IPPROTO_IPV6,IPV6_JOIN_GROUP,opt,optlen) < 0) {
 | 
			
		||||
			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;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@ -278,7 +315,8 @@ int socklist_add_multicast(const char * addr, const char * port,int 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);
 | 
			
		||||
@ -298,7 +336,8 @@ int socklist_add_unicast(const char *addr, const char * port, int ac_proto)
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
		cw_log(LOG_ERR, "Can't bind unicast address '%s': %s", addr,
 | 
			
		||||
		       gai_strerror(rc));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -318,14 +357,16 @@ int socklist_add_unicast(const char *addr, const char * port, int ac_proto)
 | 
			
		||||
		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));
 | 
			
		||||
			cw_log(LOG_ERR, "Can't create unicast socket: %s",
 | 
			
		||||
			       strerror(errno));
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* bind address */
 | 
			
		||||
		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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -338,12 +379,16 @@ int socklist_add_unicast(const char *addr, const char * port, int 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);
 | 
			
		||||
			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++;
 | 
			
		||||
 | 
			
		||||
@ -366,7 +411,8 @@ int socklist_add_broadcast(const char *addr, const char * port,int ac_proto)
 | 
			
		||||
 | 
			
		||||
	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));
 | 
			
		||||
		cw_log(LOG_ERR, "Can't bind broadcast address '%s': %s", addr,
 | 
			
		||||
		       gai_strerror(rc));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -378,16 +424,17 @@ int socklist_add_broadcast(const char *addr, const char * port,int ac_proto)
 | 
			
		||||
 | 
			
		||||
		/* create socket */
 | 
			
		||||
		if (sockfd == -1) {
 | 
			
		||||
			cw_log(LOG_ERR,"Can't create broadcast socket: %",strerror(errno));
 | 
			
		||||
			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));
 | 
			
		||||
				cw_log(LOG_ERR, "Can't set sockopt IP_BIND_ANY: %s",
 | 
			
		||||
				       strerror(errno));
 | 
			
		||||
				continue;
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
@ -397,7 +444,8 @@ int socklist_add_broadcast(const char *addr, const char * port,int ac_proto)
 | 
			
		||||
		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));
 | 
			
		||||
			cw_log(LOG_ERR, "Can't bind  broadcast %s: %s", addr,
 | 
			
		||||
			       strerror(errno));
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -409,15 +457,18 @@ int socklist_add_broadcast(const char *addr, const char * port,int ac_proto)
 | 
			
		||||
		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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user