Răsfoiți Sursa

Patch from Patrick
This patch restores the functionality in previous versions where the node
address could be specified as a network address in openais.conf



git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@925 fd59a12c-fef9-0310-b244-a6a79926bd2f

Steven Dake 20 ani în urmă
părinte
comite
5212bea264
1 a modificat fișierele cu 47 adăugiri și 10 ștergeri
  1. 47 10
      exec/totemip.c

+ 47 - 10
exec/totemip.c

@@ -258,6 +258,15 @@ int totemip_sockaddr_to_totemip_convert(struct sockaddr_storage *saddr, struct t
 	return ret;
 }
 
+static void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+        while (RTA_OK(rta, len)) {
+                if (rta->rta_type <= max)
+                        tb[rta->rta_type] = rta;
+                rta = RTA_NEXT(rta,len);
+        }
+}
+
 int totemip_iface_check(struct totem_ip_address *bindnet,
 			struct totem_ip_address *boundto,
 			int *interface_up,
@@ -269,10 +278,16 @@ int totemip_iface_check(struct totem_ip_address *bindnet,
                 struct rtgenmsg g;
         } req;
         struct sockaddr_nl nladdr;
+	struct totem_ip_address ipaddr;
 	static char rcvbuf[NETLINK_BUFSIZE];
 
 	*interface_up = 0;
 	*interface_num = 0;
+	memset(&ipaddr, 0, sizeof(ipaddr));
+
+	/* Make sure we preserve these */
+	ipaddr.family = bindnet->family;
+	ipaddr.nodeid = bindnet->nodeid;
 
 	/* Ask netlink for a list of interface addresses */
 	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@@ -327,14 +342,36 @@ int totemip_iface_check(struct totem_ip_address *bindnet,
 
 		while (NLMSG_OK(h, status)) {
 			if (h->nlmsg_type == RTM_NEWADDR) {
-				struct ifaddrmsg *msg = NLMSG_DATA(h);
-				struct rtattr *rta = (struct rtattr *)(msg+1);
-				struct totem_ip_address ipaddr;
-				unsigned char *data = (unsigned char *)(rta+1);
+				struct ifaddrmsg *ifa = NLMSG_DATA(h);
+				struct rtattr *tb[IFA_MAX+1];
+				int len = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
+				int found_if = 0;
+
+				memset(tb, 0, sizeof(tb));
+
+				parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
+
+				memcpy(ipaddr.addr, RTA_DATA(tb[IFA_ADDRESS]), TOTEMIP_ADDRLEN);
+				if (totemip_equal(&ipaddr, bindnet))
+					found_if = 1;
+
+				/* If the address we have is an IPv4 network address, then
+				   substitute the actual IP address of this interface */
+				if (!found_if && tb[IFA_BROADCAST] && ifa->ifa_family == AF_INET) {
+					uint32_t network;
+					uint32_t addr;
+					uint32_t netmask = htonl(~((1<<(32-ifa->ifa_prefixlen))-1));
+
+					memcpy(&network, RTA_DATA(tb[IFA_BROADCAST]), sizeof(uint32_t));
+					memcpy(&addr, bindnet->addr, sizeof(uint32_t));
+
+					if (addr == (network & netmask)) {
+						memcpy(ipaddr.addr, RTA_DATA(tb[IFA_ADDRESS]), TOTEMIP_ADDRLEN);
+						found_if = 1;
+					}
+				}
 
-				ipaddr.family = bindnet->family;
-				memcpy(ipaddr.addr, data, TOTEMIP_ADDRLEN);
-				if (totemip_equal(&ipaddr, bindnet)) {
+				if (found_if) {
 
 					/* Found it - check I/F is UP */
 					struct ifreq ifr;
@@ -346,7 +383,7 @@ int totemip_iface_check(struct totem_ip_address *bindnet,
 						return -1;
 					}
 					memset(&ifr, 0, sizeof(ifr));
-					ifr.ifr_ifindex = msg->ifa_index;
+					ifr.ifr_ifindex = ifa->ifa_index;
 
 					/* SIOCGIFFLAGS needs an interface name */
 					status = ioctl(ioctl_fd, SIOCGIFNAME, &ifr);
@@ -360,7 +397,7 @@ int totemip_iface_check(struct totem_ip_address *bindnet,
 					if (ifr.ifr_flags & IFF_UP)
 						*interface_up = 1;
 
-					*interface_num = msg->ifa_index;
+					*interface_num = ifa->ifa_index;
 					close(ioctl_fd);
 					goto finished;
 				}
@@ -370,7 +407,7 @@ int totemip_iface_check(struct totem_ip_address *bindnet,
 		}
 	}
 finished:
-	totemip_copy (boundto, bindnet);
+	totemip_copy (boundto, &ipaddr);
 	close(fd);
 	return 0;
 }