From 74d677ec591a715e28dba29a33ee40e1b1c2f830 Mon Sep 17 00:00:00 2001 From: Shirish Kalele Date: Thu, 18 May 2000 18:43:53 +0000 Subject: Added the NETDFS pipe to allow remote administration of the msdfs symlinks on the samba server. (This used to be commit 15e7d8f6c5cddf6ce409ee2505744250d181ec34) --- source3/rpc_server/srv_dfs.c | 456 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 456 insertions(+) create mode 100644 source3/rpc_server/srv_dfs.c (limited to 'source3/rpc_server/srv_dfs.c') diff --git a/source3/rpc_server/srv_dfs.c b/source3/rpc_server/srv_dfs.c new file mode 100644 index 0000000000..9f78b7db37 --- /dev/null +++ b/source3/rpc_server/srv_dfs.c @@ -0,0 +1,456 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines for Dfs + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Shirish Kalele 2000. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "nterr.h" + +#define MAX_MSDFS_JUNCTIONS 256 + +extern int DEBUGLEVEL; +extern pstring global_myname; + +#ifdef MS_DFS + +/********************************************************************** + api_dfs_exist + **********************************************************************/ +static BOOL api_dfs_exist( prs_struct *data, + prs_struct *rdata) +{ + DFS_R_DFS_EXIST r_d; + + if(lp_host_msdfs()) + r_d.dfs_exist_flag = 1; + else + r_d.dfs_exist_flag = 0; + + return dfs_io_r_dfs_exist("", &r_d, rdata, 0); +} + +static uint32 init_reply_dfs_add(DFS_Q_DFS_ADD* q_a) +{ + struct junction_map jn; + struct referral* old_referral_list = NULL; + BOOL exists = False; + + pstring dfspath, servername, sharename; + pstring altpath; + + unistr2_to_ascii(dfspath, &(q_a->DfsEntryPath), sizeof(dfspath)-1); + unistr2_to_ascii(servername, &(q_a->ServerName), sizeof(servername)-1); + unistr2_to_ascii(sharename, &(q_a->ShareName), sizeof(sharename)-1); + + DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n", + dfspath, servername, sharename)); + + pstrcpy(altpath, servername); + pstrcat(altpath, "\\"); + pstrcat(altpath, sharename); + + if(!create_junction(dfspath, &jn)) + return NERR_DfsNoSuchServer; + + if(get_referred_path(&jn)) + { + exists = True; + jn.referral_count += 1; + old_referral_list = jn.referral_list; + } + else + jn.referral_count = 1; + + jn.referral_list = (struct referral*) malloc(jn.referral_count + * sizeof(struct referral)); + + if(jn.referral_list == NULL) + { + DEBUG(0,("init_reply_dfs_add: malloc failed for referral list!\n")); + return NERR_DfsInternalError; + } + + if(old_referral_list) + { + memcpy(jn.referral_list, old_referral_list, + sizeof(struct referral)*jn.referral_count-1); + free(old_referral_list); + } + + jn.referral_list[jn.referral_count-1].proximity = 0; + jn.referral_list[jn.referral_count-1].ttl = REFERRAL_TTL; + + pstrcpy(jn.referral_list[jn.referral_count-1].alternate_path, altpath); + + if(!create_msdfs_link(&jn, exists)) + return NERR_DfsCantCreateJunctionPoint; + + return 0; +} +/***************************************************************** + api_dfs_add + *****************************************************************/ +static BOOL api_dfs_add(prs_struct* data, prs_struct* rdata) +{ + DFS_Q_DFS_ADD q_a; + DFS_R_DFS_ADD r_a; + + if(!dfs_io_q_dfs_add("", &q_a, data, 0)) + return False; + + r_a.status = init_reply_dfs_add(&q_a); + + dfs_io_r_dfs_add("", &r_a, rdata, 0); + + return True; +} + +static uint32 init_reply_dfs_remove(DFS_Q_DFS_REMOVE* q_r) +{ + struct junction_map jn; + BOOL found = False; + + pstring dfspath, servername, sharename; + pstring altpath; + + unistr2_to_ascii(dfspath, &(q_r->DfsEntryPath), sizeof(dfspath)-1); + if(q_r->ptr_ServerName) + unistr2_to_ascii(servername, &(q_r->ServerName), sizeof(servername)-1); + + if(q_r->ptr_ShareName) + unistr2_to_ascii(sharename, &(q_r->ShareName), sizeof(sharename)-1); + + if(q_r->ptr_ServerName && q_r->ptr_ShareName) + { + pstrcpy(altpath, servername); + pstrcat(altpath, "\\"); + pstrcat(altpath, sharename); + } + + DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n", + dfspath, servername, sharename)); + + if(!create_junction(dfspath, &jn)) + return NERR_DfsNoSuchServer; + + if(!get_referred_path(&jn)) + return NERR_DfsNoSuchVolume; + + /* if no server-share pair given, remove the msdfs link completely */ + if(!q_r->ptr_ServerName && !q_r->ptr_ShareName) + { + if(!remove_msdfs_link(&jn)) + return NERR_DfsNoSuchVolume; + } + else + { + int i=0; + /* compare each referral in the list with the one to remove */ + for(i=0;ialternate_path); + trim_string(path,"\\",""); + p = strrchr(path,'\\'); + if(p==NULL) + { + DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path)); + continue; + } + *p = '\0'; + DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1)); + stor->state = 2; /* set all storages as ONLINE */ + init_unistr2(&stor->servername, path, strlen(path)+1); + init_unistr2(&stor->sharename, p+1, strlen(p+1)+1); + stor->ptr_servername = stor->ptr_sharename = 1; + } + } + return True; +} + +static uint32 init_reply_dfs_ctr(uint32 level, DFS_INFO_CTR* ctr, + struct junction_map* jn, int num_jn) +{ + /* do the levels */ + switch(level) + { + case 1: + { + DFS_INFO_1* dfs1; + dfs1 = (DFS_INFO_1*) malloc(num_jn * sizeof(DFS_INFO_1)); + init_reply_dfs_info_1(jn, dfs1, num_jn); + ctr->dfs.info1 = dfs1; + break; + } + case 2: + { + DFS_INFO_2* dfs2; + dfs2 = (DFS_INFO_2*) malloc(num_jn * sizeof(DFS_INFO_2)); + init_reply_dfs_info_2(jn, dfs2, num_jn); + ctr->dfs.info2 = dfs2; + break; + } + case 3: + { + DFS_INFO_3* dfs3; + dfs3 = (DFS_INFO_3*) malloc(num_jn * sizeof(DFS_INFO_3)); + init_reply_dfs_info_3(jn, dfs3, num_jn); + ctr->dfs.info3 = dfs3; + } + } + return 0; +} + +static uint32 init_reply_dfs_enum(uint32 level, DFS_R_DFS_ENUM *q_r) +{ + struct junction_map jn[MAX_MSDFS_JUNCTIONS]; + int num_jn = 0; + int i=0; + + num_jn = enum_msdfs_junctions(jn); + + DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", + num_jn, level)); + + q_r->ptr_buffer = level; + q_r->level = q_r->level2 = level; + q_r->ptr_num_entries = q_r->ptr_num_entries2 = 1; + q_r->num_entries = q_r->num_entries2 = num_jn; + q_r->reshnd.ptr_hnd = 1; + q_r->reshnd.handle = num_jn; + + q_r->ctr = (DFS_INFO_CTR*) malloc(sizeof(DFS_INFO_CTR)); + q_r->ctr->switch_value = level; + q_r->ctr->num_entries = num_jn; + q_r->ctr->ptr_dfs_ctr = 1; + + init_reply_dfs_ctr(level, q_r->ctr, jn, num_jn); + + for(i=0;ilevel = level; + r_i->ptr_ctr = 1; + r_i->status = init_reply_dfs_ctr(level, &(r_i->ctr), &jn, 1); + + free(jn.referral_list); + return 0; +} +/******************************************************************* + api_dfs_get_info + *******************************************************************/ +static BOOL api_dfs_get_info(prs_struct* data, prs_struct* rdata) +{ + DFS_Q_DFS_GET_INFO q_i; + DFS_R_DFS_GET_INFO r_i; + + ZERO_STRUCT(r_i); + + if(!dfs_io_q_dfs_get_info("", &q_i, data, 0)) + return False; + + r_i.status = init_reply_dfs_get_info(&q_i.uni_path, q_i.level, &r_i); + + if(!dfs_io_r_dfs_get_info("", &r_i, rdata, 0)) + return False; + + switch(r_i.level) { + case 1: free(r_i.ctr.dfs.info1); break; + case 2: free(r_i.ctr.dfs.info2); break; + case 3: + { + free(r_i.ctr.dfs.info3->storages); + free(r_i.ctr.dfs.info3); + break; + } + } + return True; +} + +/******************************************************************* + api_dfs_enum + *******************************************************************/ +static BOOL api_dfs_enum(prs_struct* data, prs_struct* rdata) +{ + DFS_Q_DFS_ENUM q_e; + DFS_R_DFS_ENUM q_r; + + if(!dfs_io_q_dfs_enum("", &q_e, data, 0)) + return False; + + q_r.status = init_reply_dfs_enum(q_e.level, &q_r); + + if(!dfs_io_r_dfs_enum("", &q_r, rdata, 0)) + return False; + switch(q_e.level) { + case 1: + free(q_r.ctr->dfs.info1); break; + case 2: + free(q_r.ctr->dfs.info2); break; + case 3: + free(q_r.ctr->dfs.info3->storages); free(q_r.ctr->dfs.info3); break; + } + free(q_r.ctr); + return True; +} + +/******************************************************************* +\pipe\netdfs commands +********************************************************************/ +struct api_struct api_netdfs_cmds[] = +{ + {"DFS_EXIST", DFS_EXIST, api_dfs_exist }, + {"DFS_ADD", DFS_ADD, api_dfs_add }, + {"DFS_REMOVE", DFS_REMOVE, api_dfs_remove }, + {"DFS_GET_INFO", DFS_GET_INFO, api_dfs_get_info }, + {"DFS_ENUM", DFS_ENUM, api_dfs_enum }, + {NULL, 0, NULL } +}; + +/******************************************************************* +receives a netdfs pipe and responds. +********************************************************************/ +BOOL api_netdfs_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_netdfs_rpc", api_netdfs_cmds, data); +} + +#endif -- cgit