Windows: Update fs newcell and add VIOCNEWCELL2
authorJeffrey Altman <jaltman@your-file-system.com>
Thu, 3 Jun 2010 16:04:15 +0000 (12:04 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Sat, 5 Jun 2010 18:33:21 +0000 (11:33 -0700)
The Windows version of "fs newcell" did not accept any parameters
and behaved quite differently from the Unix version.  Instead of
permitting new cell information to be added, the Windows version
simply forced the existing cell information to be reacquired.

This update adds a new pioctl, VIOCNEWCELL2, to support the
implementation of a Unix-style "fs newcell".  The functionality
added here differs from the Unix version in the following ways:

 1. "fs newcell" with no arguments is still accepted
    in order to maintain compatibility with prior Windows
    behavior.

 2. "fs newcell -cell <cell> -dns" instructs the cache manager
    to add the new cell but obtain the vldb server info from
    DNS.

 3. "fs newcell -cell <cell> ... -registry" instructs the cache
    manager to add the new cell and also save the cell configuration
    data in the registry for use the next time the service restarts.

 4. The -vlport and -fsport options are accepted although the
    -fsport value is currently unsupported by the cache manager.

LICENSE MIT

Change-Id: If62cc8e1c6cc8ba2defb4cd72dae8a87b4d915e0
Reviewed-on: http://gerrit.openafs.org/2080
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/afsd/NTMakefile
src/WINNT/afsd/cm_cell.c
src/WINNT/afsd/cm_cell.h
src/WINNT/afsd/cm_config.c
src/WINNT/afsd/cm_config.h
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb_iocons.h
src/WINNT/afsd/smb_ioctl.c
src/WINNT/afsd/smb_ioctl.h

index 8e92bb2..ba429a6 100644 (file)
@@ -204,6 +204,23 @@ MIDL_FLAGS=/app_config \
 .idl.h:
        midl $(MIDL_FLAGS) $(AFSDEV_AUXMIDLFLAGS) $<
 
+
+AFSD_SDKLIBS =\
+        netapi32.lib \
+        dnsapi.lib \
+        mpr.lib \
+        rpcrt4.lib \
+        user32.lib \
+        Dbghelp.lib \
+        strsafe.lib \
+        mpr.lib \
+        secur32.lib \
+        ole32.lib \
+        oleaut32.lib \
+        iphlpapi.lib \
+        shell32.lib \
+        shlwapi.lib
+
 ############################################################################
 # libafsconf.dll
 
@@ -214,7 +231,7 @@ CONF_DLLLIBS = \
     $(DESTDIR)\lib\afs\afsreg.lib
 
 $(CONF_DLLFILE): $(CONFOBJS) $(OUT)\libafsconf.res $(CONF_DLLLIBS)
-       $(DLLGUILINK) -def:libafsconf.def dnsapi.lib mpr.lib shell32.lib Rpcrt4.lib
+       $(DLLGUILINK) -def:libafsconf.def  $(AFSD_SDKLIBS)
         $(_VC_MANIFEST_EMBED_DLL)
        $(DLLPREP)
         $(CODESIGN_USERLAND)
@@ -400,20 +417,6 @@ $(EXEDIR)\afscpcc.exe: $(OUT)\afscpcc.obj $(OUT)\afscpcc.res $(LOGON_DLLLIBS)
 # afsd.exe
 AFSD_EXEFILE = $(EXEDIR)\afsd.exe
 
-AFSD_SDKLIBS =\
-       netapi32.lib \
-        dnsapi.lib \
-        mpr.lib \
-       rpcrt4.lib \
-       user32.lib \
-        Dbghelp.lib \
-        strsafe.lib \
-        mpr.lib \
-        secur32.lib \
-        ole32.lib \
-        oleaut32.lib \
-        iphlpapi.lib shell32.lib shlwapi.lib
-
 AFSD_EXELIBS =\
        $(DESTDIR)\lib\libosi.lib \
        $(DESTDIR)\lib\afs\mtafsvldb.lib \
index 317cd73..3e7e516 100644 (file)
@@ -701,3 +701,66 @@ void cm_RemoveCellFromIDHashTable(cm_cell_t *cellp)
     }
 }
 
+long
+cm_CreateCellWithInfo( char * cellname,
+                       char * linked_cellname,
+                       unsigned short vlport,
+                       afs_uint32 host_count,
+                       char *hostname[],
+                       afs_uint32 flags)
+{
+    afs_uint32 code = 0;
+    cm_cell_rock_t rock;
+    struct hostent *thp;
+    struct sockaddr_in vlSockAddr;
+    afs_uint32 i, j;
+
+    rock.cellp = cm_GetCell(cellname, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
+    rock.flags = 0;
+
+    cm_FreeServerList(&rock.cellp->vlServersp, CM_FREESERVERLIST_DELETE);
+
+    if (!(flags & CM_CELLFLAG_DNS)) {
+        for (i = 0; i < host_count; i++) {
+            thp = gethostbyname(hostname[i]);
+            if (thp) {
+                int foundAddr = 0;
+                for (j=0 ; thp->h_addr_list[j]; j++) {
+                    if (thp->h_addrtype != AF_INET)
+                        continue;
+                    memcpy(&vlSockAddr.sin_addr.s_addr,
+                           thp->h_addr_list[j],
+                           sizeof(long));
+                    vlSockAddr.sin_port = htons(vlport ? vlport : 7003);
+                    vlSockAddr.sin_family = AF_INET;
+                    cm_AddCellProc(&rock, &vlSockAddr, hostname[i], CM_FLAG_NOPROBE);
+                }
+            }
+        }
+        lock_ObtainMutex(&rock.cellp->mx);
+        rock.cellp->flags &= ~CM_CELLFLAG_DNS;
+    } else if (cm_dnsEnabled) {
+        int ttl;
+
+        code = cm_SearchCellByDNS(rock.cellp->name, NULL, &ttl, cm_AddCellProc, &rock);
+        lock_ObtainMutex(&rock.cellp->mx);
+        if (code == 0) {   /* got cell from DNS */
+            rock.cellp->flags |= CM_CELLFLAG_DNS;
+            rock.cellp->timeout = time(0) + ttl;
+#ifdef DEBUG
+            fprintf(stderr, "cell %s: ttl=%d\n", rock.cellp->name, ttl);
+#endif
+        }
+    } else {
+        lock_ObtainMutex(&rock.cellp->mx);
+        rock.cellp->flags &= ~CM_CELLFLAG_DNS;
+    }
+    rock.cellp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
+    StringCbCopy(rock.cellp->linkedName, CELL_MAXNAMELEN, linked_cellname);
+    lock_ReleaseMutex(&rock.cellp->mx);
+
+    if (rock.cellp->vlServersp)
+        cm_RandomizeServer(&rock.cellp->vlServersp);
+
+    return code;
+}
index 10eed9e..a3d8931 100644 (file)
@@ -81,4 +81,9 @@ extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep,
 
 extern cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags);
 
+extern long cm_CreateCellWithInfo( char * cellname,
+                                   char * linked_cellname,
+                                   unsigned short vlport, afs_uint32 host_count,
+                                   char *hostname[], afs_uint32 flags);
+
 #endif /* __CELL_H_ENV_ */
index de17596..e335182 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <windows.h>
 #include <winsock2.h>
+#include <shlwapi.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -722,7 +723,113 @@ long cm_SearchCellRegistry(afs_uint32 client,
     return ((dwForceDNS || dwServers == 0) ? CM_ERROR_FORCE_DNS_LOOKUP : 0);
 }
 
-long cm_EnumerateCellRegistry(afs_uint32 client, cm_enumCellRegistryProc_t *procp, void *rockp)
+/*
+ * Following the registry schema listed above, cm_AddCellToRegistry
+ * will either create or update the registry configuration data for
+ * the specified cellname.
+ */
+long cm_AddCellToRegistry( char * cellname,
+                           char * linked_cellname,
+                           unsigned short vlport,
+                           afs_uint32 host_count,
+                           char *hostname[],
+                           afs_uint32 flags)
+{
+    HKEY hkCellServDB = 0, hkCellName = 0, hkServerName = 0;
+    DWORD dwPort, dwDisposition;
+    long code;
+    unsigned int i;
+
+    if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+                        AFSREG_CLT_OPENAFS_SUBKEY "\\CellServDB",
+                        0,
+                        NULL,
+                        REG_OPTION_NON_VOLATILE,
+                        KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+                        NULL,
+                        &hkCellServDB,
+                        &dwDisposition) != ERROR_SUCCESS) {
+        code = CM_ERROR_NOACCESS;
+        goto done;
+    }
+
+    /* Perform a recursive deletion of the cellname key */
+    SHDeleteKey( hkCellServDB, cellname);
+
+    if (RegCreateKeyEx( hkCellServDB,
+                        cellname,
+                        0,
+                        NULL,
+                        REG_OPTION_NON_VOLATILE,
+                        KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+                        NULL,
+                        &hkCellName,
+                        &dwDisposition) != ERROR_SUCCESS ||
+        (dwDisposition == REG_OPENED_EXISTING_KEY) ) {
+        code = CM_ERROR_NOACCESS;
+        goto done;
+    }
+
+    /* If we get here, hkCellName is a handle to an empty key */
+
+    if (linked_cellname && linked_cellname[0]) {
+        code = RegSetValueEx( hkCellName, "LinkedCell",
+                              0, REG_SZ,
+                              (BYTE *) linked_cellname, CELL_MAXNAMELEN);
+    }
+
+    if (flags & CM_CELLFLAG_DNS) {
+        DWORD dwForceDNS = 1;
+        code = RegSetValueEx( hkCellName, "ForceDNS",
+                              0, REG_DWORD,
+                              (BYTE *) &dwForceDNS, sizeof(DWORD));
+    }
+
+    for ( i = 0; i < host_count; i++ ) {
+        if (RegCreateKeyEx( hkCellName,
+                            hostname[i],
+                            0,
+                            NULL,
+                            REG_OPTION_NON_VOLATILE,
+                            KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+                            NULL,
+                            &hkServerName,
+                            &dwDisposition) != ERROR_SUCCESS ||
+             (dwDisposition == REG_OPENED_EXISTING_KEY)) {
+            code = CM_ERROR_NOACCESS;
+            goto done;
+        }
+
+        /* We have a handle to a valid server key.  Now we need
+         * to add the server to the cell */
+
+        /* First, see if there is an alternate hostname specified */
+        code = RegSetValueEx( hkServerName, "HostName",
+                              0, REG_SZ,
+                              (BYTE *) hostname[i], (DWORD)strlen(hostname[i]) + 1);
+
+        if (vlport) {
+            dwPort = vlport;
+            code = RegSetValueEx( hkServerName, "vlserver",
+                                  0, REG_DWORD,
+                                  (BYTE *) &dwPort, (DWORD)sizeof(DWORD));
+        }
+        RegCloseKey( hkServerName);
+        hkServerName = 0;
+    }
+
+  done:
+    if (hkServerName)
+        RegCloseKey(hkServerName);
+    if (hkCellName)
+        RegCloseKey(hkCellName);
+    if (hkCellServDB)
+        RegCloseKey(hkCellServDB);
+
+    return code;
+}
+
+long cm_EnumerateCellRegistry(afs_uint32 client, cm_enumCellProc_t *procp, void *rockp)
 {
     HKEY hkCellServDB = 0;
     DWORD dwSize;
index 2882907..85b2a0b 100644 (file)
@@ -69,6 +69,13 @@ extern long cm_AppendNewCellLine(cm_configFile_t *filep, char *linep);
 
 extern long cm_CloseCellFile(cm_configFile_t *filep);
 
+extern long cm_AddCellToRegistry( char * cellname,
+                                  char * linked_cellname,
+                                  unsigned short vlport,
+                                  afs_uint32 host_count,
+                                  char *hostname[],
+                                  afs_uint32 flags);
+
 extern long cm_GetCellServDB(char *cellNamep, afs_uint32 len);
 
 extern void cm_GetConfigDir(char *dir, afs_uint32 len);
index f7ffda8..d321ea3 100644 (file)
@@ -10,6 +10,7 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 #include <afs/cellconfig.h>
+#include <afs/afs_consts.h>
 #include <afs/ptserver.h>
 #include <ubik.h>
 
@@ -1530,6 +1531,90 @@ cm_IoctlNewCell(struct cm_ioctl *ioctlp, struct cm_user *userp)
 }
 
 /* 
+ * VIOCNEWCELL2 internals.
+ *
+ * Assumes that pioctl path has been parsed or skipped.
+ *
+ * The pioctl data buffer consists of the following structure:
+ *
+ *  afs_uint32 flags
+ *  afs_uint32 alternative fs port
+ *  afs_uint32 alternative vl port
+ *  afs_uint32 count of vldb servers
+ *  char[]     cellname
+ *  char[]     linkedcell
+ *  n * char[] hostnames
+ */
+afs_int32
+cm_IoctlNewCell2(struct cm_ioctl *ioctlp, struct cm_user *userp)
+{
+    afs_uint32  code = 0;
+    afs_uint32  flags = 0;
+    afs_uint32  fsport = 0;
+    afs_uint32  vlport = 0;
+    afs_uint32  i, host_count = 0;
+    char *      cellname = NULL;
+    char *      linked_cellname = NULL;
+    char *tp;
+    size_t tplen;
+    afs_uint32 *lp;
+    char * hostname[AFS_MAXHOSTS];
+    size_t len;
+
+    memset(hostname, 0, sizeof(hostname));
+
+    tp = ioctlp->inDatap;
+    tplen = ioctlp->inCopied;
+    lp = (afs_uint32 *)tp;
+
+    if (tplen >= 4 * sizeof(afs_uint32)) {
+        flags = *lp++;
+        fsport = *lp++;
+        vlport = *lp++;
+        host_count = *lp++;
+        tp = (char *)lp;
+        tplen -= 4 * sizeof(afs_uint32);
+    }
+
+    if ( FAILED(StringCbLength(tp, tplen, &len)) ||
+         len + 1 > CELL_MAXNAMELEN)
+        return CM_ERROR_INVAL;
+    cellname = tp;
+    tp += len + 1;
+    tplen -= (len + 1);
+
+    if ( FAILED(StringCbLength(tp, tplen, &len)) ||
+         len + 1 > CELL_MAXNAMELEN)
+        return CM_ERROR_INVAL;
+    linked_cellname = tp;
+    tp += len + 1;
+    tplen -= (len + 1);
+
+    if (!(flags & VIOC_NEWCELL2_FLAG_USEDNS)) {
+        for ( i=0; i<host_count; i++) {
+            if ( FAILED(StringCbLength(tp, tplen, &len)) )
+                return CM_ERROR_INVAL;
+            hostname[i] = tp;
+            tp += len + 1;
+            tplen -= (len + 1);
+        }
+    }
+
+    code = cm_CreateCellWithInfo( cellname, linked_cellname,
+                                  vlport, host_count,
+                                  hostname,
+                                  (flags & VIOC_NEWCELL2_FLAG_USEDNS) ? CM_CELLFLAG_DNS : 0);
+
+    if (code == 0 && (flags & VIOC_NEWCELL2_FLAG_USEREG)) {
+        cm_AddCellToRegistry( cellname, linked_cellname,
+                              vlport, host_count,
+                              hostname,
+                              (flags & VIOC_NEWCELL2_FLAG_USEDNS) ? CM_CELLFLAG_DNS : 0);
+    }
+    return code;
+}
+
+/*
  * VIOC_GET_WS_CELL internals.
  * 
  * Assumes that pioctl path has been parsed or skipped.
index c62422f..33a71dc 100644 (file)
@@ -201,6 +201,8 @@ extern afs_int32 cm_IoctlGetCell(cm_ioctl_t *ioctlp, cm_user_t *userp);
 
 extern afs_int32 cm_IoctlNewCell(cm_ioctl_t *ioctlp, cm_user_t *userp);
 
+extern afs_int32 cm_IoctlNewCell2(cm_ioctl_t *ioctlp, cm_user_t *userp);
+
 extern afs_int32 cm_IoctlGetWsCell(cm_ioctl_t *ioctlp, cm_user_t *userp);
 
 extern afs_int32 cm_IoctlSysName(cm_ioctl_t *ioctlp, cm_user_t *userp);
index d56c363..c4a7eda 100644 (file)
@@ -2974,114 +2974,182 @@ CallBackRxConnCmd(struct cmd_syndesc *as, void *arock)
 static int
 NewCellCmd(struct cmd_syndesc *as, void *arock)
 {
-#ifndef WIN32
-    afs_int32 code, linkedstate=0, size=0, *lp;
+    afs_uint32 code, linkedstate=0, size=0, count=0, *lp;
+    afs_uint32 usedns=0, useregistry=0;
     struct ViceIoctl blob;
     struct cmd_item *ti;
-    char *destEnd, *tp, *cellname=0;
-    struct hostent *thp;
-    afs_int32 fsport = 0, vlport = 0;
-    errno_t err;
+    char *tp, *cellname=0, *linked_cellname=0;
+    afs_uint32 fsport = 0, vlport = 0;
     size_t destRemaining;
 
-    memset(space, 0, AFS_MAXHOSTS * sizeof(afs_int32));
-    tp = space;
-    lp = (afs_int32 *)tp;
-    *lp++ = 0x12345678;
-    tp += sizeof(afs_int32);
-    for(ti=as->parms[1].items; ti; ti=ti->next) {
-       thp = hostutil_GetHostByName(ti->data);
-       if (!thp) {
-           fprintf(stderr,"%s: Host %s not found in host table, skipping it.\n",
-                  pn, ti->data);
-       }
-       else {
-#if _MSC_VER < 1400
-            memcpy(tp, thp->h_addr, sizeof(afs_int32));
-#else
-            err = memcpy_s(tp, sizeof(space) - (tp - space) * sizeof(char), thp->h_addr, sizeof(afs_int32));
-           if ( err ) {
-                fprintf (stderr, "memcpy_s failure on tp");
-                exit(1);
-            }
-#endif
-           tp += sizeof(afs_int32);
-       }
+    if ( !IsAdmin() ) {
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
+        return EACCES;
     }
+
+    /* if there is no cell specified, use old Windows behavior */
+    if (as->parms[0].items == NULL) {
+        blob.in_size = 0;
+        blob.in = (char *) 0;
+        blob.out_size = AFS_PIOCTL_MAXSIZE;
+        blob.out = space;
+
+        code = pioctl_utf8((char *) 0, VIOCNEWCELL, &blob, 1);
+
+        if (code) {
+            Die(errno, (char *) 0);
+            return 1;
+        }
+
+        printf("Cell servers information refreshed\n");
+        return 0;
+    } else {
+        cellname = as->parms[0].items->data;
+    }
+
     if (as->parms[2].items) {
        /*
         * Link the cell, for the purposes of volume location, to the specified
         * cell.
         */
-       cellname = as->parms[2].items->data;
+       linked_cellname = as->parms[2].items->data;
        linkedstate = 1;
     }
-#ifdef FS_ENABLE_SERVER_DEBUG_PORTS
+
     if (as->parms[3].items) {
-       code = util_GetInt32(as->parms[3].items->data, &vlport);
+       code = util_GetInt32(as->parms[2].items->data, &vlport);
        if (code) {
            fprintf(stderr,"fs: bad integer specified for the fileserver port.\n");
            return code;
        }
     }
     if (as->parms[4].items) {
-       code = util_GetInt32(as->parms[4].items->data, &fsport);
+       code = util_GetInt32(as->parms[3].items->data, &fsport);
        if (code) {
            fprintf(stderr,"fs: bad integer specified for the vldb server port.\n");
            return code;
        }
     }
-#endif
-    tp = (char *)(space + (AFS_MAXHOSTS+1) *sizeof(afs_int32));
-    lp = (afs_int32 *)tp;    
+
+    if (as->parms[5].items) {
+        useregistry = 1;
+    }
+
+    if (as->parms[6].items) {
+        usedns = 1;
+    }
+
+    /* Count the number of hostnames */
+    for (ti=as->parms[1].items; ti && count < AFS_MAXHOSTS; ti=ti->next, count++);
+
+    if (!usedns && count == 0) {
+        fprintf( stderr, "fs: at least one vldb server must be specified.");
+        exit(1);
+    }
+
+    if (count > AFS_MAXHOSTS) {
+        fprintf( stderr, "fs: at most %u servers may be specified.", AFS_MAXHOSTS);
+        exit(1);
+    }
+
+    /*
+     * The pioctl data buffer consists of the following structure:
+     *
+     *  afs_uint32 flags
+     *  afs_uint32 alternative fs port
+     *  afs_uint32 alternative vl port
+     *  afs_uint32 count of vldb servers
+     *  char[]     cellname
+     *  char[]     linkedcell
+     *  n * char[] hostnames
+     */
+
+    memset(space, 0, sizeof(space));
+    tp = space;
+    lp = (afs_uint32 *)tp;
+
+    /* flags */
+    if (usedns)
+        *lp |= VIOC_NEWCELL2_FLAG_USEDNS;
+
+    if (useregistry)
+        *lp |= VIOC_NEWCELL2_FLAG_USEREG;
+
+    if (linkedstate)
+        *lp |= VIOC_NEWCELL2_FLAG_LINKED;
+    lp++;
+
+    /* alt fs port */
     *lp++ = fsport;
+
+    /* alt vl port */
     *lp++ = vlport;
-    *lp = linkedstate;
-    if( FAILED(StringCbCopyEx(space +  ((AFS_MAXHOSTS+4) * sizeof(afs_int32)), sizeof(space) - (AFS_MAXHOSTS+4) * sizeof(afs_int32)
-        , as->parms[0].items->data, &tp, &destRemaining, STRSAFE_FILL_ON_FAILURE))) {
-        fprintf (stderr, "var - not enough space");
+
+    /* count of server names */
+    *lp++ = count;
+
+    /* Switch back to char pointer */
+    tp = (char *)lp;
+
+    /* Add nul-terminated cellname */
+    destRemaining = sizeof(space) - (tp - space);
+    if( FAILED(StringCbCopyEx( tp,
+                               destRemaining,
+                               as->parms[0].items->data,
+                               &tp,
+                               &destRemaining,
+                               STRSAFE_FILL_ON_FAILURE))) {
+        fprintf (stderr, " not enough space for cellname");
+        exit(1);
+    }
+    /* Move beyond the terminating nul */
+    tp++;
+    destRemaining -= sizeof(char);
+
+    /* Add nul-terminated linkname */
+    if( FAILED(StringCbCopyEx( tp,
+                               destRemaining,
+                               linkedstate ? linked_cellname : "",
+                               &tp,
+                               &destRemaining,
+                               STRSAFE_FILL_ON_FAILURE))) {
+        fprintf (stderr, " not enough space for linked cellname");
         exit(1);
     }
-    tp++;   /* for null */
+    /* Move beyond the terminating nul */
+    tp++;
     destRemaining -= sizeof(char);
-    if (linkedstate) {
-        if( FAILED(StringCbCopyEx(tp, sizeof(space) - size, cellname, &destEnd, &destRemaining, STRSAFE_FILL_ON_FAILURE))) {
-            fprintf (tp, "space arr - not enough space");
+
+    /* Add the servers */
+    for (ti=as->parms[1].items; ti; ti=ti->next) {
+        if( FAILED(StringCbCopyEx( tp,
+                                   destRemaining,
+                                   ti->data,
+                                   &tp,
+                                   &destRemaining,
+                                   STRSAFE_FILL_ON_FAILURE))) {
+            fprintf (stderr, " not enough space for server %s", ti->data);
             exit(1);
-       }
-        size += destEnd - tp + 1;
+        }
+        /* Move beyond the terminating nul */
+        tp++;
+        destRemaining -= sizeof(char);
     }
-    blob.in_size = size;
+
+    blob.in_size = (tp - space);
     blob.in = space;
     blob.out_size = 0;
-    code = pioctl_utf8(0, VIOCNEWCELL, &blob, 1);
-    if (code < 0)
-       Die(errno, 0);
-    return 0;
-#else /* WIN32 */
-    afs_int32 code;
-    struct ViceIoctl blob;
-    
-    if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
-        return EACCES;
-    }
-
-    blob.in_size = 0;
-    blob.in = (char *) 0;
-    blob.out_size = AFS_PIOCTL_MAXSIZE;
     blob.out = space;
-
-    code = pioctl_utf8((char *) 0, VIOCNEWCELL, &blob, 1);
+    code = pioctl_utf8(NULL, VIOCNEWCELL2, &blob, 1);
 
     if (code) {
-        Die(errno, (char *) 0);
+        Die(errno, as->parms[0].items->data);
         return 1;
     }
     
-    printf("Cell servers information refreshed\n");
+    printf("Cell servers information for %s added or updated.\n",
+           as->parms[0].items->data);
     return 0;
-#endif /* WIN32 */
 }
 
 #ifndef WIN32
@@ -5694,12 +5762,10 @@ int wmain(int argc, wchar_t **wargv)
     cmd_CreateAlias(ts, "sq");
 
     ts = cmd_CreateSyntax("newcell", NewCellCmd, NULL, "configure new cell");
-#ifndef WIN32
-    cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "cell name");
-    cmd_AddParm(ts, "-servers", CMD_LIST, CMD_REQUIRED, "primary servers");
+    cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "cell name");
+    cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL, "primary servers");
     cmd_AddParm(ts, "-linkedcell", CMD_SINGLE, CMD_OPTIONAL, "linked cell name");
 
-#ifdef FS_ENABLE_SERVER_DEBUG_PORTS
     /*
      * Turn this on only if you wish to be able to talk to a server which is listening
      * on alternative ports. This is not intended for general use and may not be
@@ -5708,8 +5774,10 @@ int wmain(int argc, wchar_t **wargv)
      */
     cmd_AddParm(ts, "-fsport", CMD_SINGLE, CMD_OPTIONAL, "cell's fileserver port");
     cmd_AddParm(ts, "-vlport", CMD_SINGLE, CMD_OPTIONAL, "cell's vldb server port");
-#endif
+    cmd_AddParm(ts, "-registry", CMD_FLAG, CMD_OPTIONAL, "add cell info to registry cellservdb");
+    cmd_AddParm(ts, "-dns",    CMD_FLAG, CMD_OPTIONAL,   "force use of dns");
 
+#ifndef WIN32
     ts = cmd_CreateSyntax("newalias", NewAliasCmd, NULL,
                          "configure new cell alias");
     cmd_AddParm(ts, "-alias", CMD_SINGLE, 0, "alias name");
index 9ecb139..ada8834 100644 (file)
@@ -98,9 +98,14 @@ struct sbstruct {
 #define VIOC_SETOWNER                   0x34
 #define VIOC_SETGROUP                   0x35
 #define VIOC_FS_CMD                     0x36
+#define VIOCNEWCELL2                    0x37
 
 #define VIOC_VOLSTAT_TEST               0x3F
 
+#define VIOC_NEWCELL2_FLAG_LINKED       0x1
+#define VIOC_NEWCELL2_FLAG_USEDNS       0x2
+#define VIOC_NEWCELL2_FLAG_USEREG       0x4
+
 /* magic file name for ioctl opens */
 #define CM_IOCTL_FILENAME      "\\_._AFS_IOCTL_._"     /* double backslashes for C compiler */
 #define CM_IOCTL_FILENAME_NOSLASH "_._AFS_IOCTL_._"
index b11268a..55b6bf9 100644 (file)
@@ -89,6 +89,7 @@ smb_InitIoctl(void)
     smb_ioctlProcsp[VIOC_UNICODECTL] = smb_IoctlUnicodeControl;
     smb_ioctlProcsp[VIOC_SETOWNER] = smb_IoctlSetOwner;
     smb_ioctlProcsp[VIOC_SETGROUP] = smb_IoctlSetGroup;
+    smb_ioctlProcsp[VIOCNEWCELL2] = smb_IoctlNewCell2;
 }       
 
 /* called to make a fid structure into an IOCTL fid structure */
@@ -1554,6 +1555,14 @@ smb_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
 }
 
 afs_int32 
+smb_IoctlNewCell2(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    cm_SkipIoctlPath(&ioctlp->ioctl);
+
+    return cm_IoctlNewCell2(&ioctlp->ioctl, userp);
+}
+
+afs_int32
 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
 {
     cm_SkipIoctlPath(&ioctlp->ioctl);
index 033533f..ba136d3 100644 (file)
@@ -128,6 +128,8 @@ extern afs_int32 smb_IoctlGetCell(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
 extern afs_int32 smb_IoctlNewCell(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
+extern afs_int32 smb_IoctlNewCell2(smb_ioctl_t *ioctlp, cm_user_t *userp);
+
 extern afs_int32 smb_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
 extern afs_int32 smb_IoctlSysName(smb_ioctl_t *ioctlp, cm_user_t *userp);