diff --git a/doc/man-pages/pod1/vos_changeaddr.pod b/doc/man-pages/pod1/vos_changeaddr.pod
index 432705ab16..ffe28bf935 100644
--- a/doc/man-pages/pod1/vos_changeaddr.pod
+++ b/doc/man-pages/pod1/vos_changeaddr.pod
@@ -8,12 +8,12 @@ vos_changeaddr - Changes or removes a file server machine's entry in the VLDB
B S<<< B<-oldaddr> > >>>
- S<<< [B<-newaddr> >] >>> [B<-remove>]
+ S<<< [B<-newaddr> >] >>> [B<-remove>] [B<-force>]
S<<< [B<-cell> >] >>> [B<-noauth>] [B<-localauth>]
[B<-verbose>] [B<-encrypt>] [B<-noresolve>] [B<-help>]
B S<<< B<-o> > >>>
- S<<< [B<-ne> >] >>> [B<-r>]
+ S<<< [B<-ne> >] >>> [B<-r>] [B<-f>]
S<<< [B<-c> >] >>>
[B<-noa>] [B<-l>] [B<-v>] [B<-e>] [B<-nor>] [B<-h>]
@@ -74,11 +74,21 @@ multihomed machine, use any of them to identify the server entry.
Specifies the new IP address that replaces all currently registered
addresses.
+Unless the B<-force> option is given, B will refuse to change
+addresses when the address given in B<-oldaddr> is registered with a multihomed
+server entry in the VLDB. See L.
+
=item B<-remove>
Removes from the VLDB the server entry that includes the address specified
by the B<-oldaddr> argument.
+=item B<-force>
+
+Overrides the multihomed server entry check when the B<-oldaddr> and
+B<-newaddr> options are combined. The B<-force> flag is provided for historical
+compatibility and is not recommended.
+
=item B<-cell> >
Names the cell in which to run the command. Do not combine this argument
diff --git a/src/volser/vos.c b/src/volser/vos.c
index bb9d1eace8..47a94f4920 100644
--- a/src/volser/vos.c
+++ b/src/volser/vos.c
@@ -5208,6 +5208,7 @@ ChangeAddr(struct cmd_syndesc *as, void *arock)
{
afs_int32 ip1, ip2, vcode;
int remove = 0;
+ int force = 0;
if (noresolve)
ip1 = GetServerNoresolve(as->parms[0].items->data);
@@ -5225,6 +5226,10 @@ ChangeAddr(struct cmd_syndesc *as, void *arock)
return (EINVAL);
}
+ if (as->parms[3].items) {
+ force = 1;
+ }
+
if (as->parms[1].items) {
if (noresolve)
ip2 = GetServerNoresolve(as->parms[1].items->data);
@@ -5244,6 +5249,42 @@ ChangeAddr(struct cmd_syndesc *as, void *arock)
ip1 = 0xffffffff;
}
+ if (!remove && !force) {
+ afs_int32 m_nentries;
+ bulkaddrs m_addrs;
+ afs_int32 m_uniq = 0;
+ afsUUID m_uuid;
+ ListAddrByAttributes m_attrs;
+ char buffer[128];
+
+ memset(&m_attrs, 0, sizeof(m_attrs));
+ memset(&m_uuid, 0, sizeof(m_uuid));
+ memset(&m_addrs, 0, sizeof(m_addrs));
+ memset(buffer, 0, sizeof(buffer));
+
+ m_attrs.Mask = VLADDR_IPADDR;
+ m_attrs.ipaddr = ntohl(ip1); /* -oldaddr */
+
+ vcode =
+ ubik_VL_GetAddrsU(cstruct, UBIK_CALL_NEW, &m_attrs, &m_uuid,
+ &m_uniq, &m_nentries, &m_addrs);
+ xdr_free((xdrproc_t) xdr_bulkaddrs, &m_addrs);
+ switch (vcode) {
+ case 0: /* mh entry detected */
+ afsUUID_to_string(&m_uuid, buffer, sizeof(buffer) - 1);
+ fprintf(STDERR, "vos: Refusing to change address in multi-homed server entry.\n");
+ fprintf(STDERR, " -oldaddr address is registered to file server UUID %s\n", buffer);
+ fprintf(STDERR, " Please restart the file server or use vos setaddrs.\n");
+ return EINVAL;
+ case VL_NOENT:
+ break;
+ default:
+ fprintf(STDERR, "vos: could not list the server addresses\n");
+ PrintError("", vcode);
+ return vcode;
+ }
+ }
+
vcode = ubik_VL_ChangeAddr(cstruct, UBIK_CALL_NEW, ntohl(ip1), ntohl(ip2));
if (vcode) {
char hoststr1[16], hoststr2[16];
@@ -6288,6 +6329,8 @@ main(int argc, char **argv)
cmd_AddParm(ts, "-newaddr", CMD_SINGLE, CMD_OPTIONAL, "new IP address");
cmd_AddParm(ts, "-remove", CMD_FLAG, CMD_OPTIONAL,
"remove the IP address from the VLDB");
+ cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
+ "allow multi-homed server entry change (not recommended)");
COMMONPARMS;
ts = cmd_CreateSyntax("listaddrs", ListAddrs, NULL,