Ejemplo n.º 1
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);
}
Ejemplo n.º 2
0
void collect_all_workgroup_names_from_wins_server(time_t t)
{
	static time_t lastrun = 0;
	struct work_record *work;

	/* Only do this if we are using a WINS server. */
	if(we_are_a_wins_client() == False)
		return;

	/* Check to see if we are a domain master browser on the unicast subnet. */
	if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) {
		if( DEBUGLVL( 0 ) ) {
			dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
			dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
			dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
		}
		return;
	}

	if(!AM_DOMAIN_MASTER_BROWSER(work))
		return;

	if ((lastrun != 0) && (t < lastrun + (15 * 60)))
		return;
     
	lastrun = t;

	/* First, query for the *<1b> name from the WINS server. */
	query_name(unicast_subnet, "*", 0x1b,
		find_all_domain_master_names_query_success,
		find_all_domain_master_names_query_fail,
		NULL);
} 
Ejemplo n.º 3
0
void sync_all_dmbs(time_t t)
{
	static time_t lastrun = 0;
	struct work_record *work;
	int count=0;

	/* Only do this if we are using a WINS server. */
	if(we_are_a_wins_client() == False)
		return;

	/* Check to see if we are a domain master browser on the
           unicast subnet. */
	work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
	if (!work)
		return;

	if (!AM_DOMAIN_MASTER_BROWSER(work))
		return;

	if ((lastrun != 0) && (t < lastrun + (5 * 60)))
		return;
     
	/* count how many syncs we might need to do */
	for (work=unicast_subnet->workgrouplist; work; work = work->next) {
		if (strcmp(lp_workgroup(), work->work_group)) {
			count++;
		}
	}

	/* sync with a probability of 1/count */
	for (work=unicast_subnet->workgrouplist; work; work = work->next) {
		if (strcmp(lp_workgroup(), work->work_group)) {
			unstring dmb_name;

			if (((unsigned)sys_random()) % count != 0)
				continue;

			lastrun = t;

			if (!work->dmb_name.name[0]) {
				/* we don't know the DMB - assume it is
				   the same as the unicast local master */
				make_nmb_name(&work->dmb_name, 
					      work->local_master_browser_name,
					      0x20);
			}

			pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);

			DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
				 dmb_name, inet_ntoa(work->dmb_addr)));

			sync_browse_lists(work, 
					  dmb_name,
					  work->dmb_name.name_type, 
					  work->dmb_addr, False, False);
		}
	}
}
Ejemplo n.º 4
0
static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name,
                                   bool force_new_election )
{
	struct work_record *work;
	struct server_record *servrec;
	struct nmb_name nmbname;

	if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
		DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
subnet %s.\n", workgroup_name, subrec->subnet_name ));
		return;
	}
Ejemplo n.º 5
0
void process_workgroup_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 workgroup_announce_name;
	unstring master_name;
	uint32 servertype = IVAL(buf,23);
	struct work_record *work;
	unstring source_name;
	unstring dest_name;

	START_PROFILE(workgroup_announce);

	pull_ascii_nstring(workgroup_announce_name,sizeof(workgroup_announce_name),buf+5);
	pull_ascii_nstring(master_name,sizeof(master_name),buf+31);
	pull_ascii_nstring(source_name,sizeof(source_name),dgram->source_name.name);
	pull_ascii_nstring(dest_name,sizeof(dest_name),dgram->dest_name.name);

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

	DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",
		ttl, servertype, master_name));

	/* Workgroup announcements must only go to the MSBROWSE name. */
	if (!strequal(dest_name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) {
		DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",
			inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
		goto done;
	}

	if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) {
		/* We have no record of this workgroup. Add it. */
		if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)
			goto done;
	} else {
		/* Update the workgroup death_time. */
		update_workgroup_ttl(work, ttl);
	}

	if(*work->local_master_browser_name == '\0') {
		/* Set the master browser name. */
		set_workgroup_local_master_browser_name( work, master_name );
	}

	subrec->work_changed = True;

done:

	END_PROFILE(workgroup_announce);
}
Ejemplo n.º 6
0
static void become_domain_master_fail(struct subnet_record *subrec,
                                      struct response_record *rrec,
                                      struct nmb_name *fail_name)
{
  struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
  struct server_record *servrec;

  if(!work)
  {
    DEBUG(0,("become_domain_master_fail: Error - cannot find \
workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
    return;
  }
Ejemplo n.º 7
0
static void become_logon_server_fail(struct subnet_record *subrec,
                                      struct response_record *rrec,
                                      struct nmb_name *fail_name)
{
	unstring failname;
	struct work_record *work;
	struct server_record *servrec;

	pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
	work = find_workgroup_on_subnet(subrec, failname);
	if(!work) {
		DEBUG(0,("become_logon_server_fail: Error - cannot find \
workgroup %s on subnet %s\n", failname, subrec->subnet_name));
		return;
	}
Ejemplo n.º 8
0
void announce_my_lm_server_names(time_t t)
{
    struct subnet_record *subrec;
    static time_t last_lm_announce_time=0;
    int announce_interval = lp_lm_interval();
    int lm_announce = lp_lm_announce();

    if ((announce_interval <= 0) || (lm_announce <= 0))
    {
        /* user absolutely does not want LM announcements to be sent. */
        return;
    }

    if ((lm_announce >= 2) && (!found_lm_clients))
    {
        /* has been set to 2 (Auto) but no LM clients detected (yet). */
        return;
    }

    /* Otherwise: must have been set to 1 (Yes), or LM clients *have*
       been detected. */

    for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
    {
        struct work_record *work = find_workgroup_on_subnet(subrec, global_myworkgroup);

        if(work)
        {
            struct server_record *servrec;

            if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval ))
                continue;

            last_lm_announce_time = t;

            for (servrec = work->serverlist; servrec; servrec = servrec->next)
            {
                if (is_myname(servrec->serv.name))
                    /* skipping equivalent of announce_server() */
                    send_lm_host_announcement(subrec, work, servrec, announce_interval);
            }
        } /* if work */
    } /* for subrec */
}
Ejemplo n.º 9
0
/****************************************************************************
As a domain master browser, do a sync with a local master browser.
**************************************************************************/
static void sync_with_lmb(struct browse_cache_record *browc)
{                     
  struct work_record *work;

  if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) )
  {
    if( DEBUGLVL( 0 ) )
    {
      dbgtext( "sync_with_lmb:\n" );
      dbgtext( "Failed to get a workgroup for a local master browser " );
      dbgtext( "cache entry workgroup " );
      dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
    }
    return;
  }

  /* We should only be doing this if we are a domain master browser for
     the given workgroup. Ensure this is so. */

  if(!AM_DOMAIN_MASTER_BROWSER(work))
  {
    if( DEBUGLVL( 0 ) )
    {
      dbgtext( "sync_with_lmb:\n" );
      dbgtext( "We are trying to sync with a local master browser " );
      dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
      dbgtext( "and we are not a domain master browser on this workgroup.\n" );
      dbgtext( "Error!\n" );
    }
    return;
  }

  if( DEBUGLVL( 2 ) )
  {
    dbgtext( "sync_with_lmb:\n" );
    dbgtext( "Initiating sync with local master browser " );
    dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
    dbgtext( "for workgroup %s\n", browc->work_group );
  }

  sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);

  browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
}
Ejemplo n.º 10
0
static void check_for_master_browser_fail( struct subnet_record *subrec,
                                           struct response_record *rrec,
                                           struct nmb_name *question_name,
                                           int fail_code)
{
  char *workgroup_name = question_name->name;
  struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);

  if(work == NULL)
  {
    DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
          workgroup_name, subrec->subnet_name ));
    return;
  }

  if (strequal(work->work_group, global_myworkgroup))
  {

    if (lp_local_master())
    {
      /* We have discovered that there is no local master
         browser, and we are configured to initiate
         an election that we will participate in.
       */
      DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
               work->work_group, subrec->subnet_name ));

      /* Setting this means we will participate when the
         election is run in run_elections(). */
      work->needelection = True;
    }
    else
    {
      /* We need to force an election, because we are configured
         not to become the local master, but we still need one,
         having detected that one doesn't exist.
       */
      send_election_dgram(subrec, work->work_group, 0, 0, "");
    }
  }
}
Ejemplo n.º 11
0
void announce_my_server_names(time_t t)
{
    struct subnet_record *subrec;

    for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
    {
        struct work_record *work = find_workgroup_on_subnet(subrec, global_myworkgroup);

        if(work)
        {
            struct server_record *servrec;

            if (work->needannounce)
            {
                /* Drop back to a max 3 minute announce. This is to prevent a
                   single lost packet from breaking things for too long. */

                work->announce_interval = MIN(work->announce_interval,
                                              CHECK_TIME_MIN_HOST_ANNCE*60);
                work->lastannounce_time = t - (work->announce_interval+1);
                work->needannounce = False;
            }

            /* Announce every minute at first then progress to every 12 mins */
            if ((t - work->lastannounce_time) < work->announce_interval)
                continue;

            if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60))
                work->announce_interval += 60;

            work->lastannounce_time = t;

            for (servrec = work->serverlist; servrec; servrec = servrec->next)
            {
                if (is_myname(servrec->serv.name))
                    announce_server(subrec, work, servrec);
            }
        } /* if work */
    } /* for subrec */
}
Ejemplo n.º 12
0
void browse_sync_remote(time_t t)
{
	char *s;
	const char *ptr;
	static time_t last_time = 0;
	char *s2;
	struct in_addr addr;
	struct work_record *work;
	char outbuf[1024];
	char *p;
	unstring myname;
	TALLOC_CTX *frame = NULL;

	if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
		return;

	last_time = t;

	s = lp_remote_browse_sync(talloc_tos());
	if (!*s)
		return;

	/*
	 * We only do this if we are the local master browser
	 * for our workgroup on the firsst subnet.
	 */

	if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) {   
		DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n",
			lp_workgroup(), FIRST_SUBNET->subnet_name ));
		return;
	}

	if(!AM_LOCAL_MASTER_BROWSER(work)) {
		DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \
for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name ));
		return;
	}
Ejemplo n.º 13
0
static void find_domain_master_name_query_success(struct subnet_record *subrec,
                        struct userdata_struct *userdata_in,
                        struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
{
  /* 
   * Unfortunately, finding the IP address of the Domain Master Browser,
   * as we have here, is not enough. We need to now do a sync to the
   * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
   * respond to the SMBSERVER name. To get this name from IP
   * address we do a Node status request, and look for the first
   * NAME<0x20> in the response, and take that as the server name.
   * We also keep a cache of the Domain Master Browser name for this
   * workgroup in the Workgroup struct, so that if the same IP addess
   * is returned every time, we don't need to do the node status
   * request.
   */

  struct work_record *work;
  struct nmb_name nmbname;
  struct userdata_struct *userdata;
  int size = sizeof(struct userdata_struct) + sizeof(fstring)+1;

  if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) )
  {
    if( DEBUGLVL( 0 ) )
      {
      dbgtext( "find_domain_master_name_query_success:\n" );
      dbgtext( "Failed to find workgroup %s\n", q_name->name );
      }
    return;
  }

  /* First check if we already have a dmb for this workgroup. */

  if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip))
  {
    /* Do the local master browser announcement to the domain
       master browser name and IP. */
    announce_local_master_browser_to_domain_master_browser( work );

    /* Now synchronise lists with the domain master browser. */
    sync_with_dmb(work);
    return;
  }
  else
    zero_ip(&work->dmb_addr);

  /* Now initiate the node status request. */
  make_nmb_name(&nmbname,"*",0x0);

  /* Put the workgroup name into the userdata so we know
     what workgroup we're talking to when the reply comes
     back. */

  /* Setup the userdata_struct - this is copied so we can use
     a stack variable for this. */
  if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
  {
    DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
    return;
  }

  userdata->copy_fn = NULL;
  userdata->free_fn = NULL;
  userdata->userdata_len = strlen(work->work_group)+1;
  pstrcpy(userdata->data, work->work_group);

  node_status( subrec, &nmbname, answer_ip, 
               domain_master_node_status_success,
               domain_master_node_status_fail,
               userdata);

  zero_free(userdata, size);
}
Ejemplo n.º 14
0
static void domain_master_node_status_success(struct subnet_record *subrec,
                                              struct userdata_struct *userdata,
                                              struct res_rec *answers,
                                              struct in_addr from_ip)
{
  struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);

  if( work == NULL )
  {
    if( DEBUGLVL( 0 ) )
    {
      dbgtext( "domain_master_node_status_success:\n" );
      dbgtext( "Unable to find workgroup " );
      dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
    }
    return;
  }

  if( DEBUGLVL( 3 ) )
  {
    dbgtext( "domain_master_node_status_success:\n" );
    dbgtext( "Success in node status for workgroup " );
    dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
  }

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

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

    p += 1;

    while (numnames--)
    {
      char qname[17];
      uint16 nb_flags;
      int name_type;

      StrnCpy(qname,p,15);
      name_type = CVAL(p,15);
      nb_flags = get_nb_flags(&p[16]);
      trim_string(qname,NULL," ");

      p += 18;

      if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
      {
        struct nmb_name nmbname;

        make_nmb_name(&nmbname, qname, name_type);

        /* Copy the dmb name and IP address
           into the workgroup struct. */

        work->dmb_name = nmbname;
        putip((char *)&work->dmb_addr, &from_ip);

        /* Do the local master browser announcement to the domain
           master browser name and IP. */
        announce_local_master_browser_to_domain_master_browser( work );

        /* Now synchronise lists with the domain master browser. */
        sync_with_dmb(work);
        break;
      }
    }
  }
  else
    if( DEBUGLVL( 0 ) )
    {
      dbgtext( "domain_master_node_status_success:\n" );
      dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
      dbgtext( "%s.\n", inet_ntoa(from_ip) );
    }
}
Ejemplo n.º 15
0
void process_local_master_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 server_name;
	uint32 servertype = IVAL(buf,23);
	fstring comment;
	unstring work_name;
	struct work_record *work;
	struct server_record *servrec;
	unstring source_name;

	START_PROFILE(local_master_announce);

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

	DEBUG(3,("process_local_master_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),server_name));

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

	/* A local master announcement must be sent to the name WORKGROUP<1e>. */
	if(dgram->dest_name.name_type != 0x1e) {
		DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
(was %02x) should be 0x1e. Ignoring packet.\n",
			inet_ntoa(p->ip), dgram->dest_name.name_type));
		goto done;
	}

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

	/* For a local master announce the workgroup name is the destination name. */

	if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) {
		/* Don't bother adding if it's a local master release announce. */
		if(servertype == 0)
			goto done;

		/* We have no record of this workgroup. Add it. */
		if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
			goto done;
	}

	/* If we think we're the local master browser for this workgroup,
		we should never have got this packet. We don't see our own
		packets.
	*/
	if(AM_LOCAL_MASTER_BROWSER(work)) {
		DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
a local master browser for workgroup %s and we think we are master. Forcing election.\n",
			server_name, inet_ntoa(p->ip), work_name));

		/* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
		 they have become a local master browser once, they will never
		 stop sending local master announcements. To fix this we send
		 them a reset browser packet, with level 0x2 on the __SAMBA__
		 name that only they should be listening to. */
   
		send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);

		/* We should demote ourself and force an election. */

		unbecome_local_master_browser( subrec, work, True);

		/* The actual election requests are handled in nmbd_election.c */
		goto done;
	}  

	/* Find the server record on this workgroup. If it doesn't exist, add it. */

	if(servertype != 0) {
		if((servrec = find_server_in_workgroup( work, server_name))==NULL) {
			/* If this server is not already in the workgroup, add it. */
			create_server_on_workgroup(work, server_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);
		}
	
		set_workgroup_local_master_browser_name( work, server_name );
	} else {
		/*
		 * This server is announcing it is going down. Remove it from the
		 * workgroup.
		 */
		if(!is_myname(server_name) && (work != NULL) &&
				((servrec = find_server_in_workgroup( work, server_name))!=NULL)) {
			remove_server_from_workgroup( work, servrec);
		}
	}

	subrec->work_changed = True;
done:

	END_PROFILE(local_master_announce);
}
Ejemplo n.º 16
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;
  fstring 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--)
    {
      char qname[17];
      uint16 nb_flags;
      int name_type;

      StrnCpy(qname,p,15);
      name_type = CVAL(p,15);
      nb_flags = get_nb_flags(&p[16]);
      trim_string(qname,NULL," ");

      p += 18;

      if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
	 server_name[0] == 0) {
	      /* this is almost certainly the server netbios name */
	      fstrcpy(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 */
		fstrcpy(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) );
    }
}
Ejemplo n.º 17
0
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);
}