2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines for Dfs
5 * Copyright (C) Andrew Tridgell 1992-1997,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
7 * Copyright (C) Shirish Kalele 2000.
8 * Copyright (C) Jeremy Allison 2001.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* This is the implementation of the dfs pipe. */
30 extern int DEBUGLEVEL
;
31 extern pstring global_myname
;
35 #define MAX_MSDFS_JUNCTIONS 256
37 uint32
_dfs_exist(pipes_struct
*p
, DFS_Q_DFS_EXIST
*q_u
, DFS_R_DFS_EXIST
*r_u
)
45 uint32
_dfs_add(pipes_struct
*p
, DFS_Q_DFS_ADD
* q_u
, DFS_R_DFS_ADD
*r_u
)
47 struct junction_map jn
;
48 struct referral
* old_referral_list
= NULL
;
51 pstring dfspath
, servername
, sharename
;
54 unistr2_to_ascii(dfspath
, &q_u
->DfsEntryPath
, sizeof(dfspath
)-1);
55 unistr2_to_ascii(servername
, &q_u
->ServerName
, sizeof(servername
)-1);
56 unistr2_to_ascii(sharename
, &q_u
->ShareName
, sizeof(sharename
)-1);
58 DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n",
59 dfspath
, servername
, sharename
));
61 pstrcpy(altpath
, servername
);
62 pstrcat(altpath
, "\\");
63 pstrcat(altpath
, sharename
);
65 if(!create_junction(dfspath
, &jn
))
66 return NERR_DfsNoSuchServer
;
68 if(get_referred_path(&jn
))
71 jn
.referral_count
+= 1;
72 old_referral_list
= jn
.referral_list
;
75 jn
.referral_count
= 1;
77 jn
.referral_list
= (struct referral
*) talloc(p
->mem_ctx
, jn
.referral_count
78 * sizeof(struct referral
));
80 if(jn
.referral_list
== NULL
)
82 DEBUG(0,("init_reply_dfs_add: talloc failed for referral list!\n"));
83 return NERR_DfsInternalError
;
88 memcpy(jn
.referral_list
, old_referral_list
,
89 sizeof(struct referral
)*jn
.referral_count
-1);
90 free(old_referral_list
);
93 jn
.referral_list
[jn
.referral_count
-1].proximity
= 0;
94 jn
.referral_list
[jn
.referral_count
-1].ttl
= REFERRAL_TTL
;
96 pstrcpy(jn
.referral_list
[jn
.referral_count
-1].alternate_path
, altpath
);
98 if(!create_msdfs_link(&jn
, exists
))
99 return NERR_DfsCantCreateJunctionPoint
;
101 return NT_STATUS_NOPROBLEMO
;
104 uint32
_dfs_remove(pipes_struct
*p
, DFS_Q_DFS_REMOVE
*q_u
, DFS_R_DFS_REMOVE
*r_u
)
106 struct junction_map jn
;
109 pstring dfspath
, servername
, sharename
;
112 unistr2_to_ascii(dfspath
, &q_u
->DfsEntryPath
, sizeof(dfspath
)-1);
113 if(q_u
->ptr_ServerName
)
114 unistr2_to_ascii(servername
, &q_u
->ServerName
, sizeof(servername
)-1);
116 if(q_u
->ptr_ShareName
)
117 unistr2_to_ascii(sharename
, &q_u
->ShareName
, sizeof(sharename
)-1);
119 if(q_u
->ptr_ServerName
&& q_u
->ptr_ShareName
)
121 pstrcpy(altpath
, servername
);
122 pstrcat(altpath
, "\\");
123 pstrcat(altpath
, sharename
);
126 DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n",
127 dfspath
, servername
, sharename
));
129 if(!create_junction(dfspath
, &jn
))
130 return NERR_DfsNoSuchServer
;
132 if(!get_referred_path(&jn
))
133 return NERR_DfsNoSuchVolume
;
135 /* if no server-share pair given, remove the msdfs link completely */
136 if(!q_u
->ptr_ServerName
&& !q_u
->ptr_ShareName
)
138 if(!remove_msdfs_link(&jn
))
139 return NERR_DfsNoSuchVolume
;
144 /* compare each referral in the list with the one to remove */
145 for(i
=0;i
<jn
.referral_count
;i
++)
148 pstrcpy(refpath
,jn
.referral_list
[i
].alternate_path
);
149 trim_string(refpath
, "\\", "\\");
150 if(strequal(refpath
, altpath
))
152 *(jn
.referral_list
[i
].alternate_path
)='\0';
157 return NERR_DfsNoSuchShare
;
159 /* Only one referral, remove it */
160 if(jn
.referral_count
== 1)
162 if(!remove_msdfs_link(&jn
))
163 return NERR_DfsNoSuchVolume
;
167 if(!create_msdfs_link(&jn
, True
))
168 return NERR_DfsCantCreateJunctionPoint
;
172 return NT_STATUS_NOPROBLEMO
;
175 static BOOL
init_reply_dfs_info_1(struct junction_map
* j
, DFS_INFO_1
* dfs1
, int num_j
)
181 dfs1
[i
].ptr_entrypath
= 1;
182 slprintf(str
, sizeof(pstring
)-1, "\\\\%s\\%s\\%s", global_myname
,
183 j
[i
].service_name
, j
[i
].volume_name
);
184 DEBUG(5,("init_reply_dfs_info_1: %d) initing entrypath: %s\n",i
,str
));
185 init_unistr2(&dfs1
[i
].entrypath
,str
,strlen(str
)+1);
190 static BOOL
init_reply_dfs_info_2(struct junction_map
* j
, DFS_INFO_2
* dfs2
, int num_j
)
196 dfs2
[i
].ptr_entrypath
= 1;
197 slprintf(str
, sizeof(pstring
)-1, "\\\\%s\\%s\\%s", global_myname
,
198 j
[i
].service_name
, j
[i
].volume_name
);
199 init_unistr2(&dfs2
[i
].entrypath
, str
, strlen(str
)+1);
200 dfs2
[i
].ptr_comment
= 0;
201 dfs2
[i
].state
= 1; /* set up state of dfs junction as OK */
202 dfs2
[i
].num_storages
= j
[i
].referral_count
;
207 static BOOL
init_reply_dfs_info_3(TALLOC_CTX
*ctx
, struct junction_map
* j
, DFS_INFO_3
* dfs3
, int num_j
)
213 dfs3
[i
].ptr_entrypath
= 1;
214 slprintf(str
, sizeof(pstring
)-1, "\\\\%s\\%s\\%s", global_myname
,
215 j
[i
].service_name
, j
[i
].volume_name
);
216 init_unistr2(&dfs3
[i
].entrypath
, str
, strlen(str
)+1);
217 dfs3
[i
].ptr_comment
= 1;
218 init_unistr2(&dfs3
[i
].comment
, "", 1);
220 dfs3
[i
].num_storages
= dfs3
[i
].num_storage_infos
= j
[i
].referral_count
;
221 dfs3
[i
].ptr_storages
= 1;
223 /* also enumerate the storages */
224 dfs3
[i
].storages
= (DFS_STORAGE_INFO
*) talloc(ctx
, j
[i
].referral_count
*
225 sizeof(DFS_STORAGE_INFO
));
226 if (!dfs3
[i
].storages
)
229 memset(dfs3
[i
].storages
, '\0', j
[i
].referral_count
* sizeof(DFS_STORAGE_INFO
));
231 for(ii
=0;ii
<j
[i
].referral_count
;ii
++)
235 DFS_STORAGE_INFO
* stor
= &(dfs3
[i
].storages
[ii
]);
236 struct referral
* ref
= &(j
[i
].referral_list
[ii
]);
238 pstrcpy(path
, ref
->alternate_path
);
239 trim_string(path
,"\\","");
240 p
= strrchr(path
,'\\');
243 DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path
));
247 DEBUG(5,("storage %d: %s.%s\n",ii
,path
,p
+1));
248 stor
->state
= 2; /* set all storages as ONLINE */
249 init_unistr2(&stor
->servername
, path
, strlen(path
)+1);
250 init_unistr2(&stor
->sharename
, p
+1, strlen(p
+1)+1);
251 stor
->ptr_servername
= stor
->ptr_sharename
= 1;
257 static uint32
init_reply_dfs_ctr(TALLOC_CTX
*ctx
, uint32 level
, DFS_INFO_CTR
* ctr
,
258 struct junction_map
* jn
, int num_jn
)
266 dfs1
= (DFS_INFO_1
*) talloc(ctx
, num_jn
* sizeof(DFS_INFO_1
));
268 return NT_STATUS_NO_MEMORY
;
269 init_reply_dfs_info_1(jn
, dfs1
, num_jn
);
270 ctr
->dfs
.info1
= dfs1
;
276 dfs2
= (DFS_INFO_2
*) talloc(ctx
, num_jn
* sizeof(DFS_INFO_2
));
278 return NT_STATUS_NO_MEMORY
;
279 init_reply_dfs_info_2(jn
, dfs2
, num_jn
);
280 ctr
->dfs
.info2
= dfs2
;
286 dfs3
= (DFS_INFO_3
*) talloc(ctx
, num_jn
* sizeof(DFS_INFO_3
));
288 return NT_STATUS_NO_MEMORY
;
289 init_reply_dfs_info_3(ctx
, jn
, dfs3
, num_jn
);
290 ctr
->dfs
.info3
= dfs3
;
293 return NT_STATUS_INVALID_LEVEL
;
295 return NT_STATUS_NOPROBLEMO
;
298 uint32
_dfs_enum(pipes_struct
*p
, DFS_Q_DFS_ENUM
*q_u
, DFS_R_DFS_ENUM
*r_u
)
300 uint32 level
= q_u
->level
;
301 struct junction_map jn
[MAX_MSDFS_JUNCTIONS
];
304 num_jn
= enum_msdfs_links(jn
);
306 DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", num_jn
, level
));
308 r_u
->ptr_buffer
= level
;
309 r_u
->level
= r_u
->level2
= level
;
310 r_u
->ptr_num_entries
= r_u
->ptr_num_entries2
= 1;
311 r_u
->num_entries
= r_u
->num_entries2
= num_jn
;
312 r_u
->reshnd
.ptr_hnd
= 1;
313 r_u
->reshnd
.handle
= num_jn
;
315 r_u
->ctr
= (DFS_INFO_CTR
*)talloc(p
->mem_ctx
, sizeof(DFS_INFO_CTR
));
317 return NT_STATUS_NO_MEMORY
;
318 ZERO_STRUCTP(r_u
->ctr
);
319 r_u
->ctr
->switch_value
= level
;
320 r_u
->ctr
->num_entries
= num_jn
;
321 r_u
->ctr
->ptr_dfs_ctr
= 1;
323 r_u
->status
= init_reply_dfs_ctr(p
->mem_ctx
, level
, r_u
->ctr
, jn
, num_jn
);
328 uint32
_dfs_get_info(pipes_struct
*p
, DFS_Q_DFS_GET_INFO
*q_u
, DFS_R_DFS_GET_INFO
*r_u
)
330 UNISTR2
* uni_path
= &q_u
->uni_path
;
331 uint32 level
= q_u
->level
;
333 struct junction_map jn
;
335 unistr2_to_ascii(path
, uni_path
, sizeof(path
)-1);
336 if(!create_junction(path
, &jn
))
337 return NERR_DfsNoSuchServer
;
339 if(!get_referred_path(&jn
))
340 return NERR_DfsNoSuchVolume
;
344 r_u
->status
= init_reply_dfs_ctr(p
->mem_ctx
, level
, &r_u
->ctr
, &jn
, 1);
349 void dfs_dummy1(void) {;} /* So some compilers don't complain. */