7c23c64a96ad478afe54551d76b03f117dd1a4ab
[kai/samba.git] / source3 / nmbsync.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines to synchronise browse lists
5    Copyright (C) Andrew Tridgell 1994-1997
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 #include "includes.h"
24
25 extern int ClientNMB;
26 extern int ClientDGRAM;
27
28 extern int DEBUGLEVEL;
29
30 extern pstring myname;
31
32 extern int name_type;
33 extern int max_protocol;
34 extern struct in_addr dest_ip;
35 extern int pid;
36 extern int gid;
37 extern int uid;
38 extern int mid;
39 extern BOOL got_pass;
40 extern BOOL have_ip;
41 extern pstring workgroup;
42 extern pstring service;
43 extern pstring desthost;
44 extern BOOL connect_as_ipc;
45
46 /****************************************************************************
47 fudge for getpass function
48 ****************************************************************************/
49 char *getsmbpass(char *pass)
50 {
51         return "dummy"; /* return anything: it should be ignored anyway */
52 }
53
54 /****************************************************************************
55 adds information retrieved from a NetServerEnum call
56 ****************************************************************************/
57 static BOOL add_info(struct subnet_record *d, struct work_record *work, int servertype)
58 {
59   char *rparam = NULL;
60   char *rdata = NULL;
61   int rdrcnt,rprcnt;
62   char *p;
63   pstring param;
64   int uLevel = 1;
65   int count = -1;
66   
67   /* now send a SMBtrans command with api ServerEnum? */
68   p = param;
69   SSVAL(p,0,0x68); /* api number */
70   p += 2;
71   strcpy(p,"WrLehDz");
72   p = skip_string(p,1);
73   
74   strcpy(p,"B16BBDz");
75   
76   p = skip_string(p,1);
77   SSVAL(p,0,uLevel);
78   SSVAL(p,2,0x2000); /* buf length */
79   p += 4;
80   SIVAL(p,0,servertype);
81   p += 4;
82   
83   strcpy(p, work->work_group);
84   p = skip_string(p,1);
85   
86   if (cli_call_api(PTR_DIFF(p,param),0, 8,10000,
87                    &rprcnt,&rdrcnt, param,NULL,
88                    &rparam,&rdata))
89     {
90       int res = SVAL(rparam,0);
91       int converter=SVAL(rparam,2);
92       int i;
93       
94       if (res == 0)
95         {
96           count=SVAL(rparam,4);
97           p = rdata;
98           
99           for (i = 0;i < count;i++, p += 26)
100             {
101               char *sname = p;
102               uint32 stype = IVAL(p,18);
103               int comment_offset = IVAL(p,22) & 0xFFFF;
104               char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
105               
106               struct work_record *w = work;
107               
108               DEBUG(4, ("\t%-16.16s     %08x    %s\n", sname, stype, cmnt));
109               
110               if (stype & SV_TYPE_DOMAIN_ENUM)
111                 {
112                   /* creates workgroup on remote subnet */
113                   if ((w = find_workgroupstruct(d,sname,True)))
114                     {
115                       announce_request(w, d->bcast_ip);
116                     }
117                 }
118               
119           if (w)
120                 add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False);
121             }
122         }
123     }
124   
125   if (rparam) free(rparam);
126   if (rdata) free(rdata);
127   
128   return(True);
129 }
130
131
132 /*******************************************************************
133   synchronise browse lists with another browse server.
134
135   log in on the remote server's SMB port to their IPC$ service,
136   do a NetServerEnum and update our server and workgroup databases.
137   ******************************************************************/
138 void sync_browse_lists(struct subnet_record *d, struct work_record *work,
139                 char *name, int nm_type, struct in_addr ip, BOOL local)
140 {
141   uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
142
143   if (!d || !work ) return;
144
145   if(d != wins_subnet) {
146       DEBUG(0,
147         ("sync_browse_lists: ERROR sync requested on non-WINS subnet.\n"));
148       return;
149   }
150
151   pid = getpid();
152   uid = getuid();
153   gid = getgid();
154   mid = pid + 100;
155   name_type = nm_type;
156   
157   got_pass = True;
158   
159   DEBUG(4,("sync browse lists with %s for %s %s\n",
160             work->work_group, name, inet_ntoa(ip)));
161   
162   strcpy(workgroup,work->work_group);
163   strcpy(desthost,name);
164   dest_ip = ip;
165   
166   if (zero_ip(dest_ip)) return;
167   have_ip = True;
168   
169   connect_as_ipc = True;
170   
171   /* connect as server and get domains, then servers */
172   
173   sprintf(service,"\\\\%s\\IPC$", name);
174   strupper(service);
175   
176   if (cli_open_sockets(SMB_PORT))
177     {
178       if (cli_send_login(NULL,NULL,True,True))
179         {
180           add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM);
181           add_info(d, work, local_type|(SV_TYPE_ALL&
182                       ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY)));
183         }
184       
185       close_sockets();
186     }
187 }