From: Andrew Deason Date: Wed, 5 May 2010 18:51:23 +0000 (-0500) Subject: vlserver: prevent duplicate IPs via ChangeAddr X-Git-Tag: openafs-devel-1_5_75~300 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=134b599c3ad475685dd0a7251d192e38966fef4c vlserver: prevent duplicate IPs via ChangeAddr Add a safety check in VL_ChangeAddr/ChangeIPAddr to check if we are adding a duplicate server IP in the database. Return VL_MULTIPADDR when we try to do that. Change-Id: Iaff2792b90f4152dac5a1ab4c1072ef56fef518b Reviewed-on: http://gerrit.openafs.org/1927 Tested-by: Andrew Deason Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- diff --git a/src/vlserver/vlprocs.c b/src/vlserver/vlprocs.c index 6c8acc9..0bd0c01 100644 --- a/src/vlserver/vlprocs.c +++ b/src/vlserver/vlprocs.c @@ -3206,6 +3206,7 @@ ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2, struct ubik_trans *atrans) afs_int32 blockindex, count; int pollcount = 0; struct nvlentry tentry; + int ipaddr1_id = -1, ipaddr2_id = -1; if (!atrans) return VL_CREATEFAIL; @@ -3240,22 +3241,44 @@ ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2, struct ubik_trans *atrans) for (mhidx = 0; mhidx < VL_MAXIPADDRS_PERMH; mhidx++) { if (!exp->ex_addrs[mhidx]) continue; - if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) - break; + if (ntohl(exp->ex_addrs[mhidx]) == ipaddr1) { + ipaddr1_id = i; + } + if (ipaddr2 != 0 && ntohl(exp->ex_addrs[mhidx]) == ipaddr2) { + ipaddr2_id = i; + } } - if (mhidx < VL_MAXIPADDRS_PERMH) { - break; + } else { + if (HostAddress[i] == ipaddr1) { + exp = NULL; + ipaddr1_id = i; + } + if (ipaddr2 != 0 && HostAddress[i] == ipaddr2) { + ipaddr2_id = i; } - } else if (HostAddress[i] == ipaddr1) { - exp = NULL; + } + + if (ipaddr1_id >= 0 && (ipaddr2 == 0 || ipaddr2_id >= 0)) { + /* we've either found both IPs already in the VLDB, or we found + * ipaddr1, and we're not going to find ipaddr2 because it's 0 */ break; } } - if (i >= MAXSERVERID) { + if (ipaddr1_id < 0) { return VL_NOENT; /* not found */ } + if (ipaddr2_id >= 0 && ipaddr2_id != ipaddr1_id) { + char buf1[16], buf2[16]; + VLog(0, ("Cannot change IP address from %s to %s because the latter " + "is in use by server id %d\n", + afs_inet_ntoa_r(htonl(ipaddr1), buf1), + afs_inet_ntoa_r(htonl(ipaddr2), buf2), + ipaddr2_id)); + return VL_MULTIPADDR; + } + /* If we are removing a server entry, a volume cannot * exist on the server. If one does, don't remove the * server entry: return error "volume entry exists". @@ -3272,7 +3295,7 @@ ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2, struct ubik_trans *atrans) for (j = 0; j < NMAXNSERVERS; j++) { if (tentry.serverNumber[j] == BADSERVERID) break; - if (tentry.serverNumber[j] == i) { + if (tentry.serverNumber[j] == ipaddr1_id) { return VL_IDEXIST; } } @@ -3318,12 +3341,12 @@ ChangeIPAddr(afs_uint32 ipaddr1, afs_uint32 ipaddr2, struct ubik_trans *atrans) } /* Now change the host address entry */ - cheader.IpMappedAddr[i] = htonl(ipaddr2); + cheader.IpMappedAddr[ipaddr1_id] = htonl(ipaddr2); code = - vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[i]), + vlwrite(atrans, DOFFSET(0, &cheader, &cheader.IpMappedAddr[ipaddr1_id]), (char *) - &cheader.IpMappedAddr[i], sizeof(afs_int32)); - HostAddress[i] = ipaddr2; + &cheader.IpMappedAddr[ipaddr1_id], sizeof(afs_int32)); + HostAddress[ipaddr1_id] = ipaddr2; if (code) return VL_IO;