preparing for release of alpha.1.7
[samba.git] / source / msdfs / parse_dfs_map.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    MSDfs services for Samba
5    Copyright (C) Shirish Kalele 2000
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /*********************************************************************** 
23  * Parses the per-service Dfs map file which is of the form:
24  * junction_point1
25  *     alternate_path1:proximity:ttl
26  *     alternate_path2:proximity:ttl
27  * junction_point2
28  * ...
29  *
30  * Junction points are directories in the service (upon encountering which
31  * Samba redirects the client to the servers hosting the underlying share)
32  *
33  * Alternate paths are of the form: \\smbserver\share
34  * Currently, the parser detects alternate paths by the leading \'s
35  *
36  ***********************************************************************/
37
38 #include "includes.h"
39
40 #ifdef MS_DFS
41
42 #define MAX_ALTERNATE_PATHS 256
43
44 extern int DEBUGLEVEL;
45
46 static char* Dfs_Crop_Whitespace(char* line)
47 {
48   int i=0;
49   int len = strlen(line);
50
51   if(line[0]=='#' || line[0]==';') return NULL;
52   
53   for(i=0;i<len && line[i]==' ';i++);
54
55   if(i>=len) return NULL;
56   
57   line = &line[i];
58
59   /* crop off the newline at the end, if present */
60   /* if(line[len-1]=='\n') line[len-1]='\0'; */
61
62   /* remove white sace from the end */
63   for(i=strlen(line)-1;i>=0 && isspace(line[i]);i--);
64   
65   if(i<0) return NULL;
66
67   line[i]='\0';
68
69   if(line[0] == '\0') return NULL;
70
71   return line;
72 }
73
74 static BOOL parse_referral(char* s, struct referral* ref)
75 {
76 #define MAXTOK_IN_REFERRAL 3
77   char *tok[MAXTOK_IN_REFERRAL+1];
78   int count=0;
79   int i=0;
80
81   if(s[1]=='\\') s = &s[1]; /* skip one backslash
82                                if there are two */
83
84   tok[count++] = strtok(s,":");
85   
86   while( ((tok[count]=strtok(NULL,":")) != NULL) && count<MAXTOK_IN_REFERRAL)
87     count++;
88
89   DEBUG(10,("parse_referral: Tokens"));
90   for(i=0;i<count;i++)
91     DEBUG(10,(" %s",tok[i]));
92   DEBUG(10,(".\n"));
93   if(count > 0)
94     pstrcpy(ref->alternate_path,tok[0]);
95   else
96     {
97       DEBUG(6,("Invalid referral line: %s\n",s));
98       return False;
99     }
100
101   if(count > 1)
102     ref->proximity = atoi(tok[1]);
103   else
104     ref->proximity = 0;
105
106   if(count > 2)
107     ref->ttl = atoi(tok[2]);
108   else
109     ref->ttl = REFERRAL_TTL; 
110
111   return True;
112 }
113
114 static BOOL load_dfsmap(char* fname, int snum)
115 {
116   struct junction_map* junction = NULL;
117   struct referral tmp_ref_array[MAX_ALTERNATE_PATHS];
118   int ref_count = 0;
119   FILE* fp;
120
121   if(lp_dfsmap_loaded(snum))
122     return True;
123   
124   if((fp = sys_fopen(fname,"r")) == NULL)
125     {
126       DEBUG(1,("can't open dfs map file %s for service [%s]\nError was %s",fname,
127                lp_servicename(snum), strerror(errno)));
128       return False;
129     }
130
131   if(!msdfs_open(True))
132     return False;
133
134   while(!feof(fp))
135     {
136       pstring rawline;
137       char* line;
138
139       if(!fgets(rawline,PSTRING_LEN,fp))
140         continue;
141
142       if((line = Dfs_Crop_Whitespace(rawline)) == NULL)
143         continue;
144
145       DEBUG(6,("load_dfsmap: Cropped line: %s\n",line));
146
147       /* the line contains a new junction or 
148          an alternate path to current junction */
149
150       if(line[0]!='\\')
151         {
152           /* a junction encountered. add the current junction first */
153           if(junction)
154             {
155               junction->referral_count = ref_count;
156               junction->referral_list = tmp_ref_array;
157               DEBUG(4,("Adding Dfs junction: %s\\%s  Referrals: %u First referral path: %s\n",
158                        junction->service_name,junction->volume_name,
159                        junction->referral_count, junction->referral_list[0].alternate_path));
160
161               if(!add_junction_entry(junction))
162                 {
163                   DEBUG(6,("Unable to add junction entry %s:%s after parsing\n",
164                            junction->service_name,junction->volume_name));
165                 }
166               free(junction);
167             }
168           
169           /* then, create a new junction_map node */
170           if((junction = (struct junction_map*) malloc(sizeof(struct junction_map))) == NULL)
171             {
172               DEBUG(0,("Couldn't malloc for Dfs junction_map node\n"));
173               return False;
174             }
175           pstrcpy(junction->service_name,lp_servicename(snum));
176           pstrcpy(junction->volume_name,line);
177           ref_count = 0;
178         }
179       else
180         {
181           /* referral encountered. add to current junction */
182           if(!junction)
183             {
184               DEBUG(4,("Invalid entry in Dfs map file.\nAlternate path defined outside of a junction in line:\n%s\n",line));
185               return False;
186             }
187
188           /* parse the referral */
189           if(!parse_referral(line,&tmp_ref_array[ref_count]))
190             continue;
191           ref_count++;
192
193         }
194     }
195   
196   /* End of file. Add the current junction and return */
197   if(junction)
198     {
199       junction->referral_count = ref_count;
200       junction->referral_list = tmp_ref_array;
201       DEBUG(4,("Adding Dfs junction: %s\%s  Referrals: %u First referral path: %s\n",
202                        junction->service_name,junction->volume_name,
203                        junction->referral_count, junction->referral_list[0].alternate_path));
204       if(!add_junction_entry(junction))
205         {
206           DEBUG(6,("Unable to add junction entry %s:%s after parsing\n",
207                    junction->service_name,junction->volume_name));
208         }
209       free(junction);
210     }
211   
212   fclose(fp);
213   msdfs_close();
214   return True;
215 }
216
217 void load_dfsmaps(void)
218 {
219   int i=0;
220   if(!lp_host_msdfs()) 
221     return;
222   
223   for(i=0;*lp_servicename(i) && *lp_dfsmap(i) 
224         && !lp_dfsmap_loaded(i);i++)
225     {
226       char* dfsmapfile = lp_dfsmap(i);
227       DEBUG(4,("loading dfsmap for servicename: %s\n",lp_servicename(i)));
228       if(load_dfsmap(dfsmapfile,i))
229         {
230           set_dfsmap_loaded(i,True);
231         }
232       else
233         {
234           DEBUG(0,("handle_dfsmap: Unable to load Dfs map file %s.\nService %s not using MS Dfs",dfsmapfile,lp_servicename(i)));
235           set_dfsmap_loaded(i,False);
236         }
237       
238     }
239 }
240           
241 #else 
242 /* Stub function if MS_DFS is not defined */      
243
244 void load_dfsmaps(void)
245 {}        
246           
247 #endif          
248           
249           
250           
251              
252         
253         
254           
255