/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
also allows us to have more than 1 sync going at once (tridge) */
#include "includes.h"
-#include "smb.h"
-
-extern int DEBUGLEVEL;
-extern pstring scope;
struct sync_record {
struct sync_record *next, *prev;
- fstring workgroup;
- fstring server;
- pstring fname;
+ unstring workgroup;
+ unstring server;
+ char *fname;
struct in_addr ip;
- int pid;
+ pid_t pid;
};
/* a linked list of current sync connections */
static struct sync_record *syncs;
-static FILE *fp;
+static XFILE *fp;
/*******************************************************************
This is the NetServerEnum callback.
+ Note sname and comment are in UNIX codepage format.
******************************************************************/
-static void callback(const char *sname, uint32 stype, const char *comment)
+
+static void callback(const char *sname, uint32 stype,
+ const char *comment, void *state)
{
- fprintf(fp,"\"%s\" %08X \"%s\"\n", sname, stype, comment);
+ x_fprintf(fp,"\"%s\" %08X \"%s\"\n", sname, stype, comment);
}
-
/*******************************************************************
Synchronise browse lists with another browse server.
Log in on the remote server's SMB port to their IPC$ service,
do a NetServerEnum and record the results in fname
******************************************************************/
+
static void sync_child(char *name, int nm_type,
char *workgroup,
- struct in_addr ip, BOOL local, BOOL servers,
+ struct in_addr ip, bool local, bool servers,
char *fname)
{
- extern fstring local_machine;
- static struct cli_state cli;
+ fstring unix_workgroup;
+ struct cli_state *cli;
uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
struct nmb_name called, calling;
+ struct sockaddr_storage ss;
+ NTSTATUS status;
+
+ /* W2K DMB's return empty browse lists on port 445. Use 139.
+ * Patch from Andy Levine andyl@epicrealm.com.
+ */
+
+ cli = cli_initialise();
+ if (!cli) {
+ return;
+ }
- if (!cli_initialise(&cli) || !cli_connect(&cli, name, &ip)) {
- fclose(fp);
+ if (!cli_set_port(cli, 139)) {
return;
}
- make_nmb_name(&calling, local_machine, 0x0 , scope);
- make_nmb_name(&called , name , nm_type, scope);
+ in_addr_to_sockaddr_storage(&ss, ip);
+ status = cli_connect(cli, name, &ss);
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
- if (!cli_session_request(&cli, &calling, &called))
- {
- cli_shutdown(&cli);
- fclose(fp);
+ make_nmb_name(&calling, get_local_machine_name(), 0x0);
+ make_nmb_name(&called , name, nm_type);
+
+ if (!cli_session_request(cli, &calling, &called)) {
+ cli_shutdown(cli);
return;
}
- if (!cli_negprot(&cli)) {
- cli_shutdown(&cli);
+ if (!cli_negprot(cli)) {
+ cli_shutdown(cli);
return;
}
- if (!cli_session_setup(&cli, local_machine, "", "", 1, "", 0, workgroup)) {
- cli_shutdown(&cli);
+ if (!NT_STATUS_IS_OK(cli_session_setup(cli, "", "", 1, "", 0,
+ workgroup))) {
+ cli_shutdown(cli);
return;
}
- if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
- cli_shutdown(&cli);
+ if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
+ cli_shutdown(cli);
return;
}
+ /* All the cli_XX functions take UNIX character set. */
+ fstrcpy(unix_workgroup, cli->server_domain ? cli->server_domain : workgroup);
+
/* Fetch a workgroup list. */
- cli_NetServerEnum(&cli, workgroup,
- local_type|SV_TYPE_DOMAIN_ENUM,
- callback);
+ cli_NetServerEnum(cli, unix_workgroup,
+ local_type|SV_TYPE_DOMAIN_ENUM,
+ callback, NULL);
/* Now fetch a server list. */
if (servers) {
- cli_NetServerEnum(&cli, workgroup,
+ fstrcpy(unix_workgroup, workgroup);
+ cli_NetServerEnum(cli, unix_workgroup,
local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL,
- callback);
+ callback, NULL);
}
- cli_shutdown(&cli);
+ cli_shutdown(cli);
}
-
/*******************************************************************
initialise a browse sync with another browse server. Log in on the
remote server's SMB port to their IPC$ service, do a NetServerEnum
and record the results
******************************************************************/
+
void sync_browse_lists(struct work_record *work,
char *name, int nm_type,
- struct in_addr ip, BOOL local, BOOL servers)
+ struct in_addr ip, bool local, bool servers)
{
struct sync_record *s;
static int counter;
+ START_PROFILE(sync_browse_lists);
/* Check we're not trying to sync with ourselves. This can
happen if we are a domain *and* a local master browser. */
- if (ismyip(ip)) {
+ if (ismyip_v4(ip)) {
+done:
+ END_PROFILE(sync_browse_lists);
return;
}
- s = (struct sync_record *)malloc(sizeof(*s));
- if (!s) return;
+ s = SMB_MALLOC_P(struct sync_record);
+ if (!s) goto done;
ZERO_STRUCTP(s);
-
- fstrcpy(s->workgroup, work->work_group);
- fstrcpy(s->server, name);
+
+ unstrcpy(s->workgroup, work->work_group);
+ unstrcpy(s->server, name);
s->ip = ip;
- slprintf(s->fname, sizeof(pstring)-1,
- "%s/sync.%d", lp_lockdir(), counter++);
- string_sub(s->fname,"//", "/");
-
+ if (asprintf(&s->fname, "%s/sync.%d", lp_lockdir(), counter++) < 0) {
+ SAFE_FREE(s);
+ goto done;
+ }
+ /* Safe to use as 0 means no size change. */
+ all_string_sub(s->fname,"//", "/", 0);
+
DLIST_ADD(syncs, s);
/* the parent forks and returns, leaving the child to do the
- actual sync */
+ actual sync and call END_PROFILE*/
CatchChild();
- if ((s->pid = fork())) return;
+ if ((s->pid = sys_fork())) return;
BlockSignals( False, SIGTERM );
DEBUG(2,("Initiating browse sync for %s to %s(%s)\n",
work->work_group, name, inet_ntoa(ip)));
- fp = sys_fopen(s->fname,"w");
- if (!fp) _exit(1);
+ fp = x_fopen(s->fname,O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (!fp) {
+ END_PROFILE(sync_browse_lists);
+ _exit(1);
+ }
sync_child(name, nm_type, work->work_group, ip, local, servers,
s->fname);
- fclose(fp);
+ x_fclose(fp);
+ END_PROFILE(sync_browse_lists);
_exit(0);
}
/**********************************************************************
-handle one line from a completed sync file
+ Handle one line from a completed sync file.
**********************************************************************/
-static void complete_one(struct sync_record *s,
+
+static void complete_one(struct sync_record *s,
char *sname, uint32 stype, char *comment)
{
struct work_record *work;
sname, lp_max_ttl());
if (work) {
/* remember who the master is */
- fstrcpy(work->local_master_browser_name,
- comment);
+ unstrcpy(work->local_master_browser_name, comment);
}
}
return;
/* Create the server in the workgroup. */
create_server_on_workgroup(work, sname,stype, lp_max_ttl(), comment);
}
-
/**********************************************************************
-read the completed sync info
- **********************************************************************/
+ Read the completed sync info.
+**********************************************************************/
+
static void complete_sync(struct sync_record *s)
{
- FILE *f;
- fstring server, type_str;
+ XFILE *f;
+ char *server;
+ char *type_str;
unsigned type;
- pstring comment;
- pstring line;
- char *ptr;
+ char *comment;
+ char line[1024];
+ const char *ptr;
int count=0;
- f = sys_fopen(s->fname,"r");
+ f = x_fopen(s->fname,O_RDONLY, 0);
+
+ if (!f)
+ return;
+
+ while (!x_feof(f)) {
+ TALLOC_CTX *frame = NULL;
+
+ if (!fgets_slash(line,sizeof(line),f))
+ continue;
- if (!f) return;
-
- while (!feof(f)) {
-
- if (!fgets_slash(line,sizeof(pstring),f)) continue;
-
ptr = line;
- if (!next_token(&ptr,server,NULL,sizeof(server)) ||
- !next_token(&ptr,type_str,NULL, sizeof(type_str)) ||
- !next_token(&ptr,comment,NULL, sizeof(comment))) {
+ frame = talloc_stackframe();
+ if (!next_token_talloc(frame,&ptr,&server,NULL) ||
+ !next_token_talloc(frame,&ptr,&type_str,NULL) ||
+ !next_token_talloc(frame,&ptr,&comment,NULL)) {
+ TALLOC_FREE(frame);
continue;
}
complete_one(s, server, type, comment);
count++;
+ TALLOC_FREE(frame);
}
-
- fclose(f);
+ x_fclose(f);
unlink(s->fname);
}
/**********************************************************************
-check for completion of any of the child processes
- **********************************************************************/
+ Check for completion of any of the child processes.
+**********************************************************************/
+
void sync_check_completion(void)
{
struct sync_record *s, *next;
for (s=syncs;s;s=next) {
next = s->next;
- if (!process_exists(s->pid)) {
+ if (!process_exists_by_pid(s->pid)) {
/* it has completed - grab the info */
complete_sync(s);
DLIST_REMOVE(syncs, s);
- ZERO_STRUCTP(s);
- free(s);
+ SAFE_FREE(s->fname);
+ SAFE_FREE(s);
}
}
}