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 <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Andrew Deason 2010-05-05 13:51:23 -05:00 committed by Derrick Brashear
parent f2ac483c2b
commit 134b599c3a

View File

@ -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;
}
} else if (HostAddress[i] == ipaddr1) {
exp = NULL;
if (ipaddr2 != 0 && HostAddress[i] == ipaddr2) {
ipaddr2_id = i;
}
}
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;