Esempio n. 1
0
void sync_browse_lists(struct work_record *work,
		       char *name, int nm_type, 
		       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_v4(ip)) {
done:
		END_PROFILE(sync_browse_lists);
		return;
	}

	s = SMB_MALLOC_P(struct sync_record);
	if (!s) goto done;

	ZERO_STRUCTP(s);

	unstrcpy(s->workgroup, work->work_group);
	unstrcpy(s->server, name);
	s->ip = ip;

	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 and call END_PROFILE*/
	CatchChild();
	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 = 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);

	x_fclose(fp);
	END_PROFILE(sync_browse_lists);
	_exit(0);
}
Esempio n. 2
0
static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
                                uint32 criterion, int timeup,const char *server_name)
{
	pstring outbuf;
	unstring srv_name;
	char *p;

	DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
		workgroup_name, subrec->subnet_name ));

	memset(outbuf,'\0',sizeof(outbuf));
	p = outbuf;
	SCVAL(p,0,ANN_Election); /* Election opcode. */
	p++;

	SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
	SIVAL(p,1,criterion);
	SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
	p += 13;
	unstrcpy(srv_name, server_name);
	strupper_m(srv_name);
	/* The following call does UNIX -> DOS charset conversion. */
	pstrcpy_base(p, srv_name, outbuf);
	p = skip_string(p,1);
  
	send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
		global_myname(), 0,
		workgroup_name, 0x1e,
		subrec->bcast_ip, subrec->myip, DGRAM_PORT);
}
Esempio n. 3
0
static void name_to_unstring(unstring unname, const char *name)
{
        nstring nname;

	errno = 0;
	push_ascii_nstring(nname, name);
	if (errno == E2BIG) {
		unstring tname;
		pull_ascii_nstring(tname, sizeof(tname), nname);
		unstrcpy(unname, tname);
		DEBUG(0,("name_to_nstring: workgroup name %s is too long. Truncating to %s\n",
			name, tname));
	} else {
		unstrcpy(unname, name);
	}
}
Esempio n. 4
0
static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
                                uint32_t criterion, int timeup,const char *server_name)
{
	char outbuf[1024];
	unstring srv_name;
	char *p;

	DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
		workgroup_name, subrec->subnet_name ));

	memset(outbuf,'\0',sizeof(outbuf));
	p = outbuf;
	SCVAL(p,0,ANN_Election); /* Election opcode. */
	p++;

	SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
	SIVAL(p,1,criterion);
	SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
	p += 13;
	unstrcpy(srv_name, server_name);
	if (!strupper_m(srv_name)) {
		DEBUG(2,("strupper_m failed for %s\n", srv_name));
		return;
	}
	/* The following call does UNIX -> DOS charset conversion. */
	push_ascii(p, srv_name, sizeof(outbuf)-PTR_DIFF(p,outbuf)-1, STR_TERMINATE);
	p = skip_string(outbuf,sizeof(outbuf),p);

	send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
		lp_netbios_name(), 0,
		workgroup_name, 0x1e,
		subrec->bcast_ip, subrec->myip, DGRAM_PORT);
}
Esempio n. 5
0
/* ************************************************************************** **
 * Create a browser entry and add it to the local master browser list.
 *
 *  Input:  work_name
 *          browser_name
 *          ip
 *
 *  Output: Pointer to the new entry, or NULL if malloc() failed.
 *
 * ************************************************************************** **
 */
struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name, 
                                                         const char *browser_name, 
                                                         struct in_addr ip )
{
	struct browse_cache_record *browc;
	time_t now = time( NULL );

	browc = SMB_MALLOC_P(struct browse_cache_record);

	if( NULL == browc ) {
		DEBUG( 0, ("create_browser_in_lmb_cache: malloc fail !\n") );
		return( NULL );
	}

	memset( (char *)browc, '\0', sizeof( *browc ) );
  
	/* For a new lmb entry we want to sync with it after one minute. This
	 will allow it time to send out a local announce and build its
	 browse list.
	*/

	browc->sync_time = now + 60;

	/* Allow the new lmb to miss an announce period before we remove it. */
	browc->death_time = now + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 );

	unstrcpy( browc->lmb_name, browser_name);
	unstrcpy( browc->work_group, work_name);
	strupper_m( browc->lmb_name );
	strupper_m( browc->work_group );
  
	browc->ip = ip;
 
	DLIST_ADD_END(lmb_browserlist, browc, struct browse_cache_record *);

	if( DEBUGLVL( 3 ) ) {
		Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" );
		Debug1( "  Added lmb cache entry for workgroup %s ", browc->work_group );
		Debug1( "name %s IP %s ", browc->lmb_name, inet_ntoa(ip) );
		Debug1( "ttl %d\n", (int)browc->death_time );
	}
  
	return( browc );
}
Esempio n. 6
0
static void complete_one(struct sync_record *s,
			 char *sname, uint32 stype, char *comment)
{
	struct work_record *work;
	struct server_record *servrec;

	stype &= ~SV_TYPE_LOCAL_LIST_ONLY;

	if (stype & SV_TYPE_DOMAIN_ENUM) {
		/* See if we can find the workgroup on this subnet. */
		if((work=find_workgroup_on_subnet(unicast_subnet, sname))) {
			/* We already know about this workgroup -
                           update the ttl. */
			update_workgroup_ttl(work,lp_max_ttl());
		} else {
			/* Create the workgroup on the subnet. */
			work = create_workgroup_on_subnet(unicast_subnet, 
							  sname, lp_max_ttl());
			if (work) {
				/* remember who the master is */
				unstrcpy(work->local_master_browser_name, comment);
			}
		}
		return;
	} 

	work = find_workgroup_on_subnet(unicast_subnet, s->workgroup);
	if (!work) {
		DEBUG(3,("workgroup %s doesn't exist on unicast subnet?\n",
			 s->workgroup));
		return;
	}

	if ((servrec = find_server_in_workgroup( work, sname))) {
		/* Check that this is not a locally known
		   server - if so ignore the entry. */
		if(!(servrec->serv.type & SV_TYPE_LOCAL_LIST_ONLY)) {
			/* We already know about this server - update
                           the ttl. */
			update_server_ttl(servrec, lp_max_ttl());
			/* Update the type. */
			servrec->serv.type = stype;
		}
		return;
	} 

	/* Create the server in the workgroup. */ 
	create_server_on_workgroup(work, sname,stype, lp_max_ttl(), comment);
}
Esempio n. 7
0
static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
{
	char outbuf[1024];
	unstring myname;
	unstring dmb_name;
	char *p;

	if(ismyip_v4(work->dmb_addr)) {
		if( DEBUGLVL( 2 ) ) {
			dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
			dbgtext( "We are both a domain and a local master browser for " );
			dbgtext( "workgroup %s.  ", work->work_group );
			dbgtext( "Do not announce to ourselves.\n" );
		}
		return;
	}

	memset(outbuf,'\0',sizeof(outbuf));
	p = outbuf;
	SCVAL(p,0,ANN_MasterAnnouncement);
	p++;

	unstrcpy(myname, lp_netbios_name());
	if (!strupper_m(myname)) {
		DEBUG(2,("strupper_m %s failed\n", myname));
		return;
	}
	myname[15]='\0';
	/* The call below does CH_UNIX -> CH_DOS conversion. JRA */
	push_ascii(p, myname, sizeof(outbuf)-PTR_DIFF(p,outbuf)-1, STR_TERMINATE);

	p = skip_string(outbuf,sizeof(outbuf),p);

	if( DEBUGLVL( 4 ) ) {
		dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
		dbgtext( "Sending local master announce to " );
		dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
					work->work_group );
	}

	/* Target name for send_mailslot must be in UNIX charset. */
	pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
	send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
		lp_netbios_name(), 0x0, dmb_name, 0x0,
		work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
}
void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
{
	struct dgram_packet *dgram = &p->packet.dgram;
	int ttl = IVAL(buf,1)/1000;
	unstring announce_name;
	uint32 servertype = IVAL(buf,23);
	fstring comment;
	struct work_record *work;
	struct server_record *servrec;
	unstring work_name;
	unstring source_name;

	START_PROFILE(host_announce);

	pull_ascii_fstring(comment, buf+31);
  
	pull_ascii_nstring(announce_name, sizeof(announce_name), buf+5);
	pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);

	DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
			nmb_namestr(&dgram->dest_name),announce_name));

	DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
		ttl, servertype,comment));

	/* Filter servertype to remove impossible bits. */
	servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);

	/* A host announcement must be sent to the name WORKGROUP<1d>. */
	if(dgram->dest_name.name_type != 0x1d) {
		DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
(was %02x) should be 0x1d. Allowing packet anyway.\n",
			inet_ntoa(p->ip), dgram->dest_name.name_type));
		/* Change it so it was. */
		dgram->dest_name.name_type = 0x1d;
	}

	/* For a host announce the workgroup name is the destination name. */
	pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);

	/*
	 * Syntax servers version 5.1 send HostAnnounce packets to
	 * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
	 * instead of WORKGROUP<1d> name. So to fix this we check if
	 * the workgroup name is our own name, and if so change it
	 * to be our primary workgroup name.
	 */

	if(strequal(work_name, global_myname()))
		unstrcpy(work_name,lp_workgroup());

	/*
	 * We are being very agressive here in adding a workgroup
	 * name on the basis of a host announcing itself as being
	 * in that workgroup. Maybe we should wait for the workgroup
	 * announce instead ? JRA.
	 */

	work = find_workgroup_on_subnet(subrec, work_name);

	if(servertype != 0) {
		if (work ==NULL ) {
			/* We have no record of this workgroup. Add it. */
			if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
				goto done;
		}
  
		if((servrec = find_server_in_workgroup( work, announce_name))==NULL) {
			/* If this server is not already in the workgroup, add it. */
			create_server_on_workgroup(work, announce_name, 
				servertype|SV_TYPE_LOCAL_LIST_ONLY, 
				ttl, comment);
		} else {
			/* Update the record. */
			servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
			update_server_ttl( servrec, ttl);
			fstrcpy(servrec->serv.comment,comment);
		}
	} else {
		/*
		 * This server is announcing it is going down. Remove it from the 
		 * workgroup.
		 */
		if(!is_myname(announce_name) && (work != NULL) &&
				((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) {
			remove_server_from_workgroup( work, servrec);
		}
	}

	subrec->work_changed = True;
done:

	END_PROFILE(host_announce);
}
Esempio n. 9
0
static void get_domain_master_name_node_status_success(struct subnet_record *subrec,
                                              struct userdata_struct *userdata,
                                              struct res_rec *answers,
                                              struct in_addr from_ip)
{
	struct work_record *work;
	unstring server_name;

	server_name[0] = 0;

	if( DEBUGLVL( 3 ) ) {
		dbgtext( "get_domain_master_name_node_status_success:\n" );
		dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
	}

	/* 
	 * Go through the list of names found at answers->rdata and look for
	 * the first WORKGROUP<0x1b> name.
	 */

	if(answers->rdata != NULL) {
		char *p = answers->rdata;
		int numnames = CVAL(p, 0);

		p += 1;

		while (numnames--) {
			unstring qname;
			uint16 nb_flags;
			int name_type;

			pull_ascii_nstring(qname, sizeof(qname), p);
			name_type = CVAL(p,15);
			nb_flags = get_nb_flags(&p[16]);
			trim_char(qname,'\0',' ');

			p += 18;

			if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
					server_name[0] == 0) {
				/* this is almost certainly the server netbios name */
				unstrcpy(server_name, qname);
				continue;
			}

			if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) {
				if( DEBUGLVL( 5 ) ) {
					dbgtext( "get_domain_master_name_node_status_success:\n" );
					dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
					dbgtext( "is a domain master browser for workgroup " );
					dbgtext( "%s. Adding this name.\n", qname );
				}

				/* 
				 * If we don't already know about this workgroup, add it
				 * to the workgroup list on the unicast_subnet.
				 */

				if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) {
					struct nmb_name nmbname;
					/* 
					 * Add it - with an hour in the cache.
					 */
					if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
						return;

					/* remember who the master is */
					unstrcpy(work->local_master_browser_name, server_name);
					make_nmb_name(&nmbname, server_name, 0x20);
					work->dmb_name = nmbname;
					work->dmb_addr = from_ip;
				}
				break;
			}
		}
	} else if( DEBUGLVL( 0 ) ) {
		dbgtext( "get_domain_master_name_node_status_success:\n" );
		dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
		dbgtext( "%s.\n", inet_ntoa(from_ip) );
	}
}