--- src/ftpd.h	2009-04-30 11:21:04.000000000 +0530
+++ src/ftpd.h	2009-07-17 15:08:23.000000000 +0530
@@ -150,6 +150,11 @@
 # define SENDFILE_NONE
 #endif
 
+# define SENDFILE_NONE 
+/*
+send file is not supported by NCP VOLUMES
+*/
+
 #ifdef HAVE_SYS_UIO_H
 # include <sys/uio.h>
 #endif
@@ -393,6 +398,16 @@ unsigned int zrand(void);
 void simplify(char *subdir);
 int checkprintable(register const char *s);
 void delete_atomic_file(void);
+int edir_login(const char* user,const char* passwd,int uid);
+int mount_remote_server(const char* where,char* nss_loc,char* remote_server);
+int umount_remote_server();
+int do_list_servers();
+int ldap_connect(const char* username,const char*passwd);
+int get_remote_server_path(char* path);
+int get_server_list_from_edir();
+int get_server_list_from_file();
+int get_ip(char* server,char* ip);
+int get_server(char*ip, char*server);
 #ifdef WITH_RFC2640
 char *charset_fs2client(const char * const string);
 #endif
--- src/ftpd_p.h	2009-04-30 11:21:04.000000000 +0530
+++ src/ftpd_p.h	2009-12-31 14:16:27.000000000 +0530
@@ -61,6 +61,10 @@ struct reply {
 
 static const char *GETOPT_OPTIONS =
     "0146"
+	"2:"
+	"3:"
+	"7"
+	"5"
 #ifdef WITH_RFC2640
     "8:9:"
 #endif
@@ -114,6 +118,10 @@ static struct option long_options[] = {
     { "logpid", 0, NULL, '1' },
     { "ipv4only", 0, NULL, '4' },
     { "ipv6only", 0, NULL, '6' },    
+    { "remoteserver", 0, NULL, '7' }, 
+    { "disallowlistoesserver", 0, NULL, '5' }, 
+    { "defaulthomedir", 1, NULL, '2' }, 
+    { "edirldapport", 1, NULL, '3' }, 
 #ifdef WITH_RFC2640
     { "fscharset", 1, NULL, '8' },
     { "clientcharset", 1, NULL, '9' },
--- src/globals.h	2009-04-30 11:21:04.000000000 +0530
+++ src/globals.h	2009-12-29 14:14:52.000000000 +0530
@@ -27,6 +27,10 @@ GLOBAL(int datafd, -1);                 
 GLOBAL0(struct sockaddr_storage ctrlconn);    /* stdin/stdout, for using the same ip number */
 GLOBAL0(signed char v6ready);                    /* IPv6 supported or not */
 GLOBAL0(signed char no_ipv4);                    /* IPv4 disabled or not */
+GLOBAL0(signed char remote_server);                    /* OES remote server supported or not*/
+GLOBAL0(signed char disallow_list_oes_server);         /* list remote OES server supported or not*/
+GLOBAL(unsigned int edir_ldap_port,389);                 /* edirectory ldap port*/
+GLOBAL0(char *default_home_dir);                /* default home dir */
 GLOBAL(const size_t cmdsize, MAXPATHLEN + 16U);
 GLOBAL0(char cmd[MAXPATHLEN + 32U]);        /* command line - about 30 chars for command */
 GLOBAL0(char wd[MAXPATHLEN + 1U]);            /* current working directory */
--- src/ftpd.c	2009-04-30 11:21:04.000000000 +0530
+++ src/ftpd.c	2010-01-13 18:22:05.000000000 +0530
@@ -37,6 +37,34 @@
 # include <dmalloc.h>
 #endif
 
+#include <strings.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <ldap.h>
+
+LDAP* ldapHandle;
+
+int no_of_server = 0 ;
+const char* SERV_LIST_FILE = "/var/opt/novell/pure-ftpd/server_list.txt";
+
+     
+
+// remote server navigation constants
+#define MAX_SERVER_SIZE 100
+#define MAX_SERVER_FDN_SIZE 300
+#define MAX_PATH_SIZE 1000
+#define MAX_IP_SIZE 20
+#define MAX_NO_OF_SERVERS 300
+
+
+char serverInfo[MAX_NO_OF_SERVERS][120]; 
+const char MOUNT_PATH[] = "/var/opt/novell/nclmnt";
+const int MOUNT_PATH_SIZE = 22;
+	
+char userFDN[512];
+static const char *getlocalhostname();
+	  
+
 #ifndef HAVE_SYS_FSUID_H
 void disablesignals(void)
 {
@@ -362,6 +390,9 @@ static RETSIGTYPE sigterm_client(int sig
 {
     (void) sig;
     
+    if(remote_server)
+	    umount_remote_server();
+    
 #ifndef HAVE_SYS_FSUID_H
     disablesignals();
 #endif
@@ -1637,7 +1668,16 @@ void dopass(char *password)
     {
         /* Clear password from memory, paranoia */        
         register volatile char *password_ = (volatile char *) password;
+		if(remote_server == 1 )
+			edir_login(account,password,authresult.uid);
+
+	if(default_home_dir != NULL)
+	{
+		if(authresult.dir != NULL)
+			free(authresult.dir);
         
+		authresult.dir = strdup(default_home_dir);
+	}	
         while (*password_ != 0) {
             *password_++ = 0;
         }
@@ -1994,6 +2034,34 @@ void docwd(const char *dir)
         addreply(550, MSG_SANITY_FILE_FAILURE, where);
         return;
     }
+
+	char server[MAX_SERVER_SIZE],nss_loc[MAX_PATH_SIZE];
+	if(remote_server ==1 )
+	{	
+		// Not allowed to move inside the folder NCPVolForFTP
+		if (strstr(where,"nclmnt") != NULL)
+			goto cd_success;
+
+		if(NULL == getcwd(wd, sizeof wd - (size_t) 1U))
+			logfile(LOG_ERR," Get current working directory failed");	
+
+		// cd .. is not allowed from base remote dir
+		if( (wd != NULL) && (strcmp(where,"..") == 0))
+		{	
+			if(strncasecmp(wd,MOUNT_PATH,MOUNT_PATH_SIZE) ==0)
+			{
+				if(strstr(wd+MOUNT_PATH_SIZE+1+strlen(account)+1,"/") == NULL )
+					goto cd_success;
+			}
+		}
+
+		get_remote_server_path(wd);
+
+		//mount remote server
+		if ( mount_remote_server(where,nss_loc,server) == 0 )	
+			where = nss_loc;	
+
+	} 	
     if (chdir(where) != 0) {
         
 #ifdef WITH_DIRALIASES
@@ -2037,6 +2105,9 @@ void docwd(const char *dir)
     failures = 0UL;
     dobanner(1);
 #endif
+
+cd_success:
+    
     if (getcwd(wd, sizeof wd - (size_t) 1U) == NULL) {
         if (*dir == '/') {
             if (SNCHECK(snprintf(wd, sizeof wd, "%s", dir), sizeof wd)) { /* already checked */
@@ -2050,6 +2121,10 @@ void docwd(const char *dir)
             }
         }
     }
+
+	if(remote_server ==1 )
+		get_remote_server_path(wd);
+
 #ifdef WITH_RFC2640
     nwd = charset_fs2client(wd);
     addreply(250, MSG_CURRENT_DIR_IS, nwd);
@@ -3529,6 +3604,7 @@ void domkd(char *name)
 #endif
         error(550, MSG_MKD_FAILURE);
     } else {
+	get_remote_server_path(name);
         addreply(257, "\"%s\" : " MSG_MKD_SUCCESS, name);
     }
 #ifdef QUOTAS
@@ -5268,6 +5344,30 @@ int main(int argc, char *argv[])
             no_ipv4 = 1;
             break;
         }
+		case '7': {
+			//Remove directory /var/opt/novell/pure-ftpd/		  
+			system("cnt=$(ps -eaf | grep pure-ftpd | wc -l);if [[ $cnt -lt 3 ]]; then rm -r /var/opt/novell/pure-ftpd/ &> /dev/null;fi");
+			mkdir("/var/opt/novell/pure-ftpd/",0777);
+			chmod("/var/opt/novell/pure-ftpd/",0777);
+			remote_server = 1;
+	   		break;
+		}			
+		case '5': {
+	   		disallow_list_oes_server = 1;
+	   		break;
+		}	
+				  
+		case '3': {
+	   		edir_ldap_port = atoi(optarg);
+			if(edir_ldap_port <= 0 )
+				edir_ldap_port = 389;
+	   		break;
+		}			
+		case '2': {
+	   		default_home_dir = strdup(optarg); 
+	   		break;
+		}
+			  
 #ifdef WITH_RFC2640
         case '8': {
             if ((charset_fs = strdup(optarg)) == NULL) {
@@ -5980,3 +6080,556 @@ int main(int argc, char *argv[])
 
     return 0;
 }
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+
+int (*namGetUserFDNfromUID)    (int uid, char * userFDN);
+
+static const char *getlocalhostname()
+{
+	static char buf[1025];
+
+	if (gethostname(buf, sizeof buf - 1U) != 0) {
+		snprintf(buf,sizeof(buf),"127.0.0.1");
+	}
+	return buf;
+}
+
+int edir_login(const char* user,const char* passwd,int uid)
+{
+	int srcIndex =0,destIndex=0,openCount = 0;
+	char tmp[MAX_PATH_SIZE+100];
+	FILE* fd = NULL;
+	char fdn[512];fdn[0] = '\0' ;	
+	struct stat buf;
+	int update = 1,pid = 0;
+	time_t curr_time;
+
+	
+	// get the FDN of user from pam_nam.so
+	void * lumHandle =  dlopen("/lib64/security/pam_nam.so", RTLD_LAZY);
+	if (lumHandle == NULL)
+		lumHandle =  dlopen("/lib/security/pam_nam.so", RTLD_LAZY);
+	if(lumHandle != NULL)
+	{
+		namGetUserFDNfromUID = (int (*)(int, char *))dlsym(lumHandle, "namGetUserFDNfromUID");
+		if(namGetUserFDNfromUID != NULL)
+		{	 
+			int error = namGetUserFDNfromUID(uid, fdn);
+			sprintf(tmp,"namGetUserFDNfromUID for uid %d return %d",uid,error);
+			logfile(LOG_DEBUG,tmp);
+		} else			
+			logfile(LOG_ERR,"Function namGetUserFDNfromUID not found");
+		dlclose(lumHandle);
+	} else
+		logfile(LOG_ERR,"PAM library not found");
+
+
+	//copy user name provided by the ftp client incase pam_nam.so does not provide FDN of user
+	if (fdn[0] == '\0')
+		strncpy(fdn,user,sizeof(fdn));
+
+
+	//Convert . separared user FDN to ldap formated(, separated) user FDN
+	while (fdn[srcIndex] != '\0')
+	{
+		if(strncasecmp(&fdn[srcIndex],",st=",4) == 0)
+		{
+			strncpy(&userFDN[destIndex],".s=",3);
+			srcIndex += 4;
+			destIndex += 3;
+		} else {
+			if(fdn[srcIndex] != ',')
+				userFDN[destIndex] = fdn[srcIndex];
+			else	
+				userFDN[destIndex] = '.';
+			++srcIndex;
+			++destIndex;
+		}
+	}
+	userFDN[destIndex] = '\0';
+		
+	/*
+	   do nwlogin the local server.Same nw connection is reused for connecting to different machine.
+	 */  
+ //   snprintf(tmp,sizeof(tmp),"su '%s'  /opt/novell/ncl/bin/nwlogin  -s '%s' -u '%s' -p '%s' -c x > /dev/null",user,hostname,userFDN,passwd );
+  //  system(tmp);
+   
+	if( (pid = fork()) == 0)
+	{	
+		// calling nwlogin from system command put password in /var/log/message 
+		
+		char* data[9];
+		char* context;
+		context = index(userFDN,'.');
+		if(context != NULL)
+			context++;
+
+		if(context == NULL)
+		{	
+			snprintf(tmp,sizeof(tmp),"no context for user %s",userFDN);
+			logfile(LOG_ERR,tmp);
+			exit(0);
+		}	
+		
+		data[0] ="-t 127.0.0.1";
+		data[1] ="-s 127.0.0.1";
+		data[2] ="-u" ; data[3] = (char*)user;
+		data[4] ="-c" ; data[5] = (char*)context;
+		data[6] ="-p" ; data[7] = (char*)passwd;
+		data[8] =NULL;
+		
+		snprintf(tmp,sizeof(tmp),"nwlogin -u %s uid %d context %s",userFDN,uid,context);
+		logfile(LOG_DEBUG,tmp);
+
+		setuid(uid);
+		seteuid(uid);
+		//redirect all nwlogin output to /dev/null to aviod sending wrong response to ftp client
+		stdout = freopen("/dev/null", "w", stdout);
+    		execv("/opt/novell/ncl/bin/nwlogin",data); 
+		exit(0);
+	} else
+		waitpid(pid,NULL,0);
+
+	//create directories to store no of simultaneous logins by same user
+	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s",account);
+	mkdir(tmp, 0777);
+	
+	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	fd = fopen(tmp,"r+");
+	
+	openCount = 1;
+	if(fd != NULL)
+	{
+		if(fread(&openCount,sizeof(int),1,fd) > 0)
+		{
+			if(openCount >= 0)
+				++openCount;
+			else
+				openCount = 1;
+		} else
+			 openCount = 1;
+		fclose(fd);	
+	} else
+		openCount = 1;
+
+	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	fd = fopen(tmp,"w+");
+	if(fd != NULL)
+	{
+		fwrite(&openCount,sizeof(int),1,fd);
+		fclose(fd);	
+	}
+
+	curr_time = time(NULL);
+	if(stat(SERV_LIST_FILE,&buf) ==0)
+	{
+        if ( curr_time  > 0) 
+		{
+			if(curr_time - buf.st_mtime < (60 * 30))
+				update = 0;
+		}	
+	}	
+			
+	if( (update != 0) || (get_server_list_from_file() < 0))
+	{
+		logfile(LOG_DEBUG,"refresh the server-ip cache");
+		if(fork() == 0)
+		{
+			ldap_connect(fdn,passwd);
+			get_server_list_from_edir();
+			if(ldapHandle != NULL)
+				ldap_unbind(ldapHandle);
+			exit(0);
+		}	
+	}
+
+	ldap_connect(fdn,passwd);
+	
+	return 0;
+}
+
+int mount_remote_server(const char* where,char* nss_loc,char* remote_server)
+{
+	char tmp[MAX_PATH_SIZE+1000],path[MAX_PATH_SIZE];
+	char* str1,*server;
+	int err,i;
+	struct hostent *he;
+	struct in_addr ipv4addr;
+	//mnt_loc         - mounted path name by novell client (server name)
+	//ncl_req_name    - Request used in novell client (IP - preferably) 
+	char mnt_loc[MAX_SERVER_SIZE],ncl_req_name[MAX_SERVER_SIZE],ip[MAX_IP_SIZE];
+	struct in_addr addr;	
+	char*  context = NULL;
+	
+	if((where != NULL ) &&(strncmp(where,"//",2 ) ==0))
+	{
+
+		if( no_of_server <= 0) 
+			get_server_list_from_file(); 
+
+		//Get the remote oes server path excluding server name
+		snprintf(path,sizeof(path),index(where+2, '/'));
+		
+		//Get the server name from remote oes path
+		str1 = (char*) where+2;
+		server = strtok(str1,"/");
+
+		/*
+		   Get the server name/ip address of remote server
+		   Remote server name in ftp request can be either server name / DNS name / IP
+		*/   
+		memset(mnt_loc,0,sizeof(mnt_loc));  
+		memset(ncl_req_name,0,sizeof(ncl_req_name)); 
+		if(inet_pton(AF_INET, server, &ipv4addr) > 0)
+		{	
+			// ftp request is with IP (server = ip )
+			snprintf(ncl_req_name,sizeof(ncl_req_name),"%s",server);
+			if(0 != get_server(server,mnt_loc))
+			{	
+				// IP is not available in server list. Use dns name as shared folder
+				he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
+				if(he != NULL)
+					server = strtok(he->h_name,".");
+				snprintf(mnt_loc,sizeof(mnt_loc),"%s",server);
+			}	
+			
+		} else 
+		{
+			// ftp request is with server name / dns name
+			snprintf(mnt_loc,sizeof(mnt_loc),"%s",server);
+
+			if(0 != get_ip(server,ncl_req_name))
+			{
+				// Server name is not available in cache. request name can be dns name
+				snprintf(ncl_req_name,sizeof(ncl_req_name),"%s",server);
+				he = gethostbyname(server);
+				if(he != NULL)
+				{
+					i = 0;
+					while (he->h_addr_list[i] != 0) 
+					{
+						
+						   addr.s_addr = *(u_long *) he->h_addr_list[i++];
+				           snprintf(ip,sizeof(ip),"%s", inet_ntoa(addr));
+						   if(get_server(ip,mnt_loc) == 0 )
+						   {
+							   
+								snprintf(ncl_req_name,sizeof(ncl_req_name),"%s",ip);
+								break;
+						   }	   
+					}
+				}
+			}	
+		}	
+		
+
+		if(remote_server != NULL )
+			strncpy(remote_server,mnt_loc, MAX_SERVER_SIZE);
+
+		context = index(userFDN,'.');
+		if(context != NULL)
+			context++;
+		if(context == NULL)
+			context = "x";
+			
+		/*
+		 * nwlogin as logged in ftp user. 
+		 * nwlogin does not require password here. novell client reuses exising connection
+		 */		
+		snprintf(tmp,sizeof(tmp),"sudo -u '%s' /opt/novell/ncl/bin/nwlogin -s '%s' -u '%s' -c '%s' -p x > /dev/null",account,ncl_req_name,account,context);
+		err= system(tmp);
+
+		if(err !=0 )
+		{
+			snprintf(tmp,sizeof(tmp),"Novell Client Login Failed with error %d ",err);
+			logfile(LOG_ERR,tmp);
+			return -1;
+		}
+
+		
+		if(nss_loc != NULL)
+			snprintf(nss_loc,MAX_PATH_SIZE,"%s/%s/%s/%s",MOUNT_PATH,account,mnt_loc,path);
+	
+		snprintf(tmp,sizeof(tmp),"ncl mount point:%s ftp request server name:%s ncl request server name:%s\n",nss_loc,remote_server,ncl_req_name);
+		logfile(LOG_DEBUG,tmp);
+
+		return 0;
+	}  else
+		return -1;	
+}
+
+
+int umount_remote_server()
+{
+	char tmp[MAX_PATH_SIZE+100];
+	int openCount = 0;
+	FILE* fd = NULL;
+	
+	snprintf(tmp,sizeof(tmp),"/var/opt/novell/pure-ftpd/%s/count.txt",account);
+	fd = fopen(tmp,"r+");
+	if(fd != NULL)
+	{
+		if(fread(&openCount,sizeof(int),1,fd) > 0)
+		{
+			if (openCount > 0  )
+				--openCount;
+			else
+				openCount = 0;
+		} else
+			openCount = 0;
+			
+		fclose(fd);	
+		
+		fd = fopen(tmp,"w+");
+		fwrite(&openCount,sizeof(int),1,fd);
+		fclose(fd);	
+	} else	
+		logfile(LOG_ERR,"File Open failed");
+	
+	//nwlogout is not called when same ftp user is logged in more than once
+	if(openCount <= 0)	
+	{	
+		snprintf(tmp,sizeof(tmp),"sudo -u '%s' /opt/novell/ncl/bin/nwlogout -f -a > /dev/null",account);
+		system(tmp); 
+	}	
+	return 0;
+}
+
+int get_remote_server_path(char* path)
+{	
+	char tmp[MAX_PATH_SIZE];
+	
+	if (path == NULL)
+		return -1;
+
+	// Send the remote dir location as reply	
+	if( strncasecmp(path,MOUNT_PATH,MOUNT_PATH_SIZE) == 0)
+	{
+		snprintf(tmp,sizeof(tmp),"//%s",path+MOUNT_PATH_SIZE+1+strlen(account)+1);
+		strncpy(path,tmp,MAX_PATH_SIZE);
+	}	
+	return 0;
+}	
+
+// response for site slist command
+int do_list_servers()
+{
+	FILE* file;
+	char buffer[2*MAX_SERVER_FDN_SIZE];
+	int serverLen;
+	char server[200],*ip;
+	
+	if( ( no_of_server <= 0) && (get_server_list_from_file() < 0))
+		 get_server_list_from_edir();
+	
+	file = fopen (SERV_LIST_FILE,"r"); 
+	
+    if(file != NULL)
+	{	
+		while (!feof (file))
+		{
+			if (!fgets (buffer, 2*MAX_SERVER_FDN_SIZE, file))
+				    continue;
+			
+			ip  = strrchr(buffer,'#');
+			if (ip == NULL)
+				continue;
+
+			serverLen = strlen(buffer) - strlen(ip) ;
+			if (serverLen > MAX_SERVER_FDN_SIZE)
+				serverLen = MAX_SERVER_FDN_SIZE;	
+			
+			snprintf(server,serverLen+1,"%s",buffer);
+			addreply_noformat(0, server);
+		}	
+		
+		fclose(file);
+	}  
+
+	return 0;
+	
+}
+
+				  
+int ldap_connect(const char* username,const char*passwd)
+{	
+    	ldapHandle = ldap_init("127.0.0.1",edir_ldap_port);
+    	if (ldapHandle == NULL)
+    	{
+			return -1;
+		}
+
+		ldap_simple_bind_s(ldapHandle,username,passwd);
+		return 0;
+}
+
+/*
+   get list of server from edir and store in the file
+   File format : server name#IP$
+*/   
+int get_server_list_from_edir()
+{	
+        //create server list
+        char* attrs[]={"networkAddress",NULL};
+        char* ldapDN,*attribute;
+        LDAPMessage* entry = NULL;
+        LDAPMessage* searchResult = NULL;
+	BerElement *ber;
+	char **vals;
+	int i = 0 ;
+	struct timeval timeval;
+	timeval.tv_sec = 1200; 
+	FILE* file = NULL;
+	char buffer[2*MAX_SERVER_FDN_SIZE],temp[2*MAX_SERVER_FDN_SIZE];
+	char tmp[MAX_PATH_SIZE+1000];
+		
+	get_server_list_from_file();
+			
+        if (ldapHandle == NULL)
+        {
+                 logfile(LOG_ERR,"LDAP connection is not available");
+                 return -1;
+        }
+        int rc = ldap_search_ext_s(ldapHandle,"",LDAP_SCOPE_SUBTREE,"(&(objectclass=NCP Server))",
+						attrs,  0,NULL, NULL, &timeval, 0, &searchResult);
+		
+	no_of_server = 0;
+	if(rc == LDAP_SUCCESS )
+	{
+		file = fopen (SERV_LIST_FILE,"w+"); 
+		for(entry = ldap_first_entry(ldapHandle,searchResult) ; entry != NULL ;
+				entry = ldap_next_entry(ldapHandle,entry))
+	    	    {
+	
+					if((ldapDN = ldap_get_dn(ldapHandle,entry)) != NULL )
+					{	
+						strncpy(temp,ldapDN,sizeof(temp));
+						memset(serverInfo[no_of_server],0,MAX_SERVER_SIZE);
+						snprintf(serverInfo[no_of_server],MAX_SERVER_SIZE,"%s",strtok_r(temp+3,"," , (char**)&buffer));
+					} else 	
+					    continue;
+					for (attribute = ldap_first_attribute (ldapHandle, entry, &ber); attribute != NULL;
+		                    		attribute = ldap_next_attribute (ldapHandle, entry, ber))
+					{
+						if ((vals = ldap_get_values (ldapHandle, entry, attribute)) != NULL)
+						{
+							for (i = 0; vals[i] != NULL; i++)
+							{
+								if(strncmp(vals[i],"8#",2) == 0)
+								{	
+									snprintf(&serverInfo[no_of_server][MAX_SERVER_SIZE],MAX_IP_SIZE,
+										"%d.%d.%d.%d",0xFF & vals[i][4],0xFF & vals[i][5], 0xFF & vals[i][6], 0xFF & vals[i][7]);
+									break;
+								}
+							}	
+							ldap_value_free(vals);
+						}	
+						ldap_memfree(attribute);
+					}
+					if ( ber != NULL ) 
+						 ber_free( ber, 0 );
+
+					if (file != NULL) 
+					{
+						snprintf(buffer,sizeof(buffer),"%s#%s$\n",ldapDN,&serverInfo[no_of_server][MAX_SERVER_SIZE]);	
+						fputs(buffer,file);
+					}
+					ldap_memfree( ldapDN );	
+					++no_of_server;
+				
+				}
+	} else
+	{	
+		snprintf(tmp,sizeof(tmp),"ldap search failed with error code %d",rc);		
+		logfile(LOG_ERR,tmp);
+
+	}	
+	if (file != NULL) 
+	{
+		fclose(file);
+	} 
+
+	if ( no_of_server > 0 )
+	{	
+		ldap_unbind(ldapHandle);
+		ldapHandle = NULL;
+	}	
+	return 0;
+}
+
+//create the server name / IP cache from file
+int get_server_list_from_file()
+{
+	FILE* file;
+	char buffer[2*MAX_SERVER_FDN_SIZE],saveptr[2*MAX_SERVER_FDN_SIZE];
+	char* server,*ip;
+	file = fopen (SERV_LIST_FILE,"r"); 
+	
+	no_of_server = 0;
+    if(file != NULL)
+	{	
+		while (!feof (file))
+		{
+			/*
+				data is stored in file in the format servername#IP$
+			*/   
+			if (!fgets (buffer, 2*MAX_SERVER_FDN_SIZE, file))
+				    continue;
+			ip = strrchr(buffer,'#');
+			if(ip != NULL)
+			{	
+				ip = strtok_r(ip+1,"$" , (char**)&saveptr);
+				if (ip!=NULL)
+					snprintf(&serverInfo[no_of_server][MAX_SERVER_SIZE],MAX_IP_SIZE,ip);
+			}	
+			server = strtok_r(buffer+3,"," , (char**)&saveptr);
+			if (server == NULL)
+				continue;
+			
+			snprintf(serverInfo[no_of_server],MAX_SERVER_SIZE,"%s",server);
+			++no_of_server;
+		}	
+		
+		fclose(file);
+	}
+
+	if(no_of_server <= 0)
+		return -1;
+	else
+		return 0;
+	
+}
+
+
+//get ip of server from cache
+int get_ip(char* server,char* ip)
+{
+	int index=0;
+	for(index = 0 ; index < no_of_server ; ++index )
+	{
+		if(strncasecmp(server,serverInfo[index], MAX_SERVER_SIZE) == 0)
+		{
+			strncpy(ip,&serverInfo[index][MAX_SERVER_SIZE],MAX_IP_SIZE);
+			return 0;
+		}
+	}	
+	return -1;
+}
+
+//get server name from cache
+int get_server(char*ip, char*server)
+{
+	int index=0;
+	for(index = 0 ; index < no_of_server ; ++index )
+	{
+		if(strncasecmp(ip,&serverInfo[index][MAX_SERVER_SIZE], MAX_IP_SIZE) == 0)
+		{
+			strncpy(server,serverInfo[index],MAX_SERVER_SIZE);
+			return 0;
+		}
+	}	
+	return -1;
+}
+	   
--- src/ftp_parser.c	2009-04-30 11:21:04.000000000 +0530
+++ src/ftp_parser.c	2009-06-29 19:30:55.000000000 +0530
@@ -16,6 +16,8 @@
 # include <dmalloc.h>
 #endif
 
+#define MAX_PATH_SIZE 1000
+
 static void antiidle(void)
 {
     if (noopidle == (time_t) -1) {
@@ -332,6 +334,8 @@ void parser(void)
             }
             dopass(arg);
         } else if (!strcmp(cmd, "quit")) {
+	    if(remote_server == 1)	
+	    	 umount_remote_server();	
             addreply(221, MSG_GOODBYE,
                      (unsigned long long) ((uploaded + 1023ULL) / 1024ULL),
                      (unsigned long long) ((downloaded + 1023ULL) / 1024ULL));
@@ -473,6 +477,10 @@ void parser(void)
             } else if (!strcmp(cmd, "cdup") || !strcmp(cmd, "xcup")) {
                 docwd("..");
             } else if (!strcmp(cmd, "retr")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 if (*arg != 0) {
 #ifdef WITH_TLS
                     if (enforce_tls_auth == 3 &&
@@ -497,12 +505,20 @@ void parser(void)
                 }
                 goto wayout;
             } else if (!strcmp(cmd, "dele")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 if (*arg != 0) {
                     dodele(arg);
                 } else {
                     addreply_noformat(501, MSG_NO_FILE_NAME);
                 }
             } else if (!strcmp(cmd, "stor")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 arg = revealextraspc(arg);
                 if (*arg != 0) {
 #ifdef WITH_TLS
@@ -518,6 +534,10 @@ void parser(void)
                     addreply_noformat(501, MSG_NO_FILE_NAME);
                 }
             } else if (!strcmp(cmd, "appe")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ((remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 arg = revealextraspc(arg);
                 if (*arg != 0) {
 #ifdef WITH_TLS
@@ -546,6 +566,10 @@ void parser(void)
 #endif
 #ifndef DISABLE_MKD_RMD
             } else if (!strcmp(cmd, "mkd") || !strcmp(cmd, "xmkd")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ((remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 arg = revealextraspc(arg);
                 if (*arg != 0) {
                     domkd(arg);
@@ -553,6 +577,10 @@ void parser(void)
                     addreply_noformat(501, MSG_NO_DIRECTORY_NAME);
                 }
             } else if (!strcmp(cmd, "rmd") || !strcmp(cmd, "xrmd")) {
+    		// support full remote server path
+    		char nss_loc[MAX_PATH_SIZE];
+    		if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+	    		arg = nss_loc;
                 if (*arg != 0) {
                     dormd(arg);
                 } else {
@@ -746,6 +774,8 @@ void parser(void)
                         }
                     }
 # endif
+		} else if ( (!strcasecmp(arg, "slist")) && (remote_server == 1) && (!disallow_list_oes_server) ) {
+		    		do_list_servers();
                 } else if (*arg != 0) {
                     addreply(500, "SITE %s " MSG_UNKNOWN_EXTENSION, arg);
                 } else {
--- src/ls.c	2009-04-30 11:21:04.000000000 +0530
+++ src/ls.c	2009-06-16 17:39:54.000000000 +0530
@@ -12,6 +12,8 @@
 # include <dmalloc.h>
 #endif
 
+#define MAX_PATH_SIZE 1000
+
 static void wrstr(const int f, const char *s)
 {
     static char outbuf[CONF_TCP_SO_SNDBUF];
@@ -374,6 +376,11 @@ static int listfile(const PureFileInfo *
             if ((alloca_nameline = ALLOCA(sizeof_nameline)) == NULL) {
                 return 0;
             }
+	    char remote_file_name[MAX_PATH_SIZE];
+	    strncpy(remote_file_name,name,MAX_PATH_SIZE);
+	    if(remote_server == 1) 
+	    	get_remote_server_path(remote_file_name);
+
             if (SNCHECK(snprintf(alloca_nameline, sizeof_nameline,
                                  "%s %4u %s %s %10llu %s %2d %s %s", 
                                  m, (unsigned int) st.st_nlink,
@@ -381,7 +388,7 @@ static int listfile(const PureFileInfo *
                                  getgroup(st.st_gid), 
                                  (unsigned long long) st.st_size,
                                  months[t->tm_mon],
-                                 t->tm_mday, timeline, name),
+                                 t->tm_mday, timeline, remote_file_name),
                         sizeof_nameline)) {
                 ALLOCA_FREE(alloca_nameline);
                 _EXIT(EXIT_FAILURE);
@@ -844,6 +851,11 @@ void donlist(char *arg, const int on_ctr
 
         justone = 1;            /* just one argument, so don't print dir name */
 
+	// support full remote server path
+ 	 char nss_loc[MAX_PATH_SIZE];
+ 	if ( (remote_server == 1) && (mount_remote_server(arg,nss_loc,NULL) ==0))
+		arg = nss_loc;
+
         do {
             glob_t g;
             int a;
--- configuration-file/pure-config.pl.in	2009-04-30 11:21:06.000000000 +0530
+++ configuration-file/pure-config.pl.in	2010-01-12 16:59:43.000000000 +0530
@@ -59,6 +59,7 @@ my %string_switch_for = (
 	TrustedIP		=> "-V",
 	AltLog			=> "-O",
 	PIDFile			=> "-g",
+	DefaultHomeDirectory    => "-2",
 );
 
 my %numeric_switch_for = (
@@ -70,6 +71,7 @@ my %numeric_switch_for = (
 	MaxLoad			=> "-m",
 	MinUID			=> "-u",
 	TLS			=> "-Y",
+	edir_ldap_port	=> "-3",
 );
 
 my %numpairb_switch_for = (
@@ -114,6 +116,8 @@ open CONF, "< $conffile" or die "Can't o
 	/$auth_method/i			? ("-l" . "$auth_method_for{$1}:$2") :
 	/UnixAuthentication\s+yes/i	? ("-l" . "unix") :
 	/PAMAuthentication\s+yes/i	? ("-l" . "pam") :
+	/remote_server\s+yes/i		? ("--remoteserver") :
+	/disallow_list_oes_server\s+yes/i		? ("--disallowlistoesserver") :
 	()
 ) while <CONF>;
 
--- configuration-file/pure-ftpd-stop.pl	1970-01-01 05:30:00.000000000 +0530
+++ configuration-file/pure-ftpd-stop.pl	2010-02-01 12:34:26.000000000 +0530
@@ -0,0 +1,43 @@
+#! /usr/bin/perl
+
+# Copyright (c) 2010 Novell Inc.
+# derived from code (C) 2001-2009 Aristotle Pagaltzis
+
+use strict;
+
+my ($conffile, @flg) = @ARGV;
+
+my $KILL_PROC="killproc"; 
+my $PUREFTPD;
+-x && ($PUREFTPD=$_, last) for qw(
+	${exec_prefix}/sbin/pure-ftpd
+	/usr/local/pure-ftpd/sbin/pure-ftpd
+	/usr/local/pureftpd/sbin/pure-ftpd
+	/usr/local/sbin/pure-ftpd
+	/usr/sbin/pure-ftpd
+);
+
+my %string_switch_for = (
+	PIDFile                 => "-p",
+	);				    
+
+my $string_switch = qr/(@{[join "|", keys %string_switch_for ]})\s+(\S+)/i;
+
+die "Usage: pure-ftpd-stop.pl <configuration file>\n"
+	unless defined $conffile;
+
+open CONF, "< $conffile" or die "Can't open $conffile: $!\n";
+
+!/^\s*(?:$|#)/ and (chomp, push @flg,
+	/$string_switch/i               ? ($string_switch_for{$1} . $2) :
+	()
+) while <CONF>;
+ 
+push @flg, (-G);
+push @flg, (-TERM);
+push @flg, ($PUREFTPD);
+
+close CONF;
+
+print "Running: $KILL_PROC ", join(" ", @flg), "\n";
+exec { $KILL_PROC } ($KILL_PROC, @flg) or die "cannot exec $KILL_PROC: $!";
