Example #1
0
static void msg_nmbd_send_packet(struct messaging_context *msg,
				 void *private_data,
				 uint32_t msg_type,
				 struct server_id src,
				 DATA_BLOB *data)
{
	struct packet_struct *p = (struct packet_struct *)data->data;
	struct subnet_record *subrec;
	struct sockaddr_storage ss;
	const struct sockaddr_storage *pss;
	const struct in_addr *local_ip;

	DEBUG(10, ("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src)));

	if (data->length != sizeof(struct packet_struct)) {
		DEBUG(2, ("Discarding invalid packet length from %u\n",
			  (unsigned int)procid_to_pid(&src)));
		return;
	}

	if ((p->packet_type != NMB_PACKET) &&
	    (p->packet_type != DGRAM_PACKET)) {
		DEBUG(2, ("Discarding invalid packet type from %u: %d\n",
			  (unsigned int)procid_to_pid(&src), p->packet_type));
		return;
	}

	in_addr_to_sockaddr_storage(&ss, p->ip);
	pss = iface_ip((struct sockaddr *)(void *)&ss);

	if (pss == NULL) {
		DEBUG(2, ("Could not find ip for packet from %u\n",
			  (unsigned int)procid_to_pid(&src)));
		return;
	}

	local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
	subrec = FIRST_SUBNET;

	p->recv_fd = -1;
	p->send_fd = (p->packet_type == NMB_PACKET) ?
		subrec->nmb_sock : subrec->dgram_sock;

	for (subrec = FIRST_SUBNET; subrec != NULL;
	     subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
		if (ip_equal_v4(*local_ip, subrec->myip)) {
			p->send_fd = (p->packet_type == NMB_PACKET) ?
				subrec->nmb_sock : subrec->dgram_sock;
			break;
		}
	}

	if (p->packet_type == DGRAM_PACKET) {
		p->port = 138;
		p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
		p->packet.dgram.header.source_port = 138;
	}

	send_packet(p);
}
void check_master_browser_exists(time_t t)
{
	static time_t lastrun=0;
	struct subnet_record *subrec;
	const char *workgroup_name = lp_workgroup();

	if (!lastrun)
		lastrun = t;

	if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
		return;

	lastrun = t;

	dump_workgroups(False);

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

		for (work = subrec->workgrouplist; work; work = work->next) {
			if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) {
				/* Do a name query for the local master browser on this net. */
				query_name( subrec, work->work_group, 0x1d,
					check_for_master_browser_success,
					check_for_master_browser_fail,
					NULL);
			}
		}
	}
}
static void wins_next_registration(struct response_record *rrec)
{
	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
	struct nmb_name *nmbname = &sent_nmb->question.question_name;
	uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
	struct userdata_struct *userdata = rrec->userdata;
	const char *tag;
	struct in_addr last_ip;
	struct subnet_record *subrec;

	putip(&last_ip,&sent_nmb->additional->rdata[2]);

	if (!userdata) {
		/* it wasn't multi-homed */
		return;
	}

	tag = (const char *)userdata->data;

	for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
		if (ip_equal(last_ip, subrec->myip)) {
			subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
			break;
		}
	}

	if (!subrec) {
		/* no more to do! */
		return;
	}

	switch (sent_nmb->header.opcode) {
	case NMB_NAME_MULTIHOMED_REG_OPCODE:
		multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
		break;
	case NMB_NAME_REFRESH_OPCODE_8:
		queue_wins_refresh(nmbname, 
				   register_name_response,
				   register_name_timeout_response,
				   nb_flags, subrec->myip, tag);
		break;
	}
}
Example #4
0
static void msg_nmbd_send_packet(int msg_type, struct process_id src,
				 void *buf, size_t len, void *private_data)
{
	struct packet_struct *p = (struct packet_struct *)buf;
	struct subnet_record *subrec;
	struct in_addr *local_ip;

	DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));

	if (len != sizeof(struct packet_struct)) {
		DEBUG(2, ("Discarding invalid packet length from %d\n",
			  procid_to_pid(&src)));
		return;
	}

	if ((p->packet_type != NMB_PACKET) &&
	    (p->packet_type != DGRAM_PACKET)) {
		DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
			  procid_to_pid(&src), p->packet_type));
		return;
	}

	local_ip = iface_ip(p->ip);

	if (local_ip == NULL) {
		DEBUG(2, ("Could not find ip for packet from %d\n",
			  procid_to_pid(&src)));
		return;
	}

	subrec = FIRST_SUBNET;

	p->fd = (p->packet_type == NMB_PACKET) ?
		subrec->nmb_sock : subrec->dgram_sock;

	for (subrec = FIRST_SUBNET; subrec != NULL;
	     subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
		if (ip_equal(*local_ip, subrec->myip)) {
			p->fd = (p->packet_type == NMB_PACKET) ?
				subrec->nmb_sock : subrec->dgram_sock;
			break;
		}
	}

	if (p->packet_type == DGRAM_PACKET) {
		p->port = 138;
		p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
		p->packet.dgram.header.source_port = 138;
	}

	send_packet(p);
}
Example #5
0
void run_elections(time_t t)
{
  static time_t lastime = 0;
  
  struct subnet_record *subrec;
  
  /* Send election packets once every 2 seconds - note */
  if (lastime && (t - lastime < 2))
    return;
  
  lastime = t;
  
  START_PROFILE(run_elections);
  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
  {
    struct work_record *work;

    for (work = subrec->workgrouplist; work; work = work->next)
    {
      if (work->RunningElection)
      {
        /*
         * We can only run an election for a workgroup if we have
         * registered the WORKGROUP<1e> name, as that's the name
         * we must listen to.
         */
        struct nmb_name nmbname;

        make_nmb_name(&nmbname, work->work_group, 0x1e);
        if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
          DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
          continue;
        }

        send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
                      t - StartupTime, global_myname);
	      
        if (work->ElectionCount++ >= 4)
        {
          /* Won election (4 packets were sent out uncontested. */
          DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
                    work->work_group, subrec->subnet_name ));

          work->RunningElection = False;

          become_local_master_browser(subrec, work);
        }
      }
    }
  }
Example #6
0
void load_lmhosts_file(const char *fname)
{
	char *name = NULL;
	int name_type;
	struct sockaddr_storage ss;
	TALLOC_CTX *ctx = talloc_init("load_lmhosts_file");
	FILE *fp = startlmhosts( fname );

	if (!fp) {
		DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n",
			fname, strerror(errno)));
		TALLOC_FREE(ctx);
		return;
	}

	while (getlmhostsent(ctx, fp, &name, &name_type, &ss) ) {
		struct in_addr ipaddr;
		struct subnet_record *subrec = NULL;
		enum name_source source = LMHOSTS_NAME;

		if (ss.ss_family != AF_INET) {
			TALLOC_FREE(name);
			continue;
		}

		ipaddr = ((struct sockaddr_in *)&ss)->sin_addr;

		/* We find a relevent subnet to put this entry on, then add it. */
		/* Go through all the broadcast subnets and see if the mask matches. */
		for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
			if(same_net_v4(ipaddr, subrec->bcast_ip, subrec->mask_ip))
				break;
		}

		/* If none match add the name to the remote_broadcast_subnet. */
		if(subrec == NULL)
			subrec = remote_broadcast_subnet;

		if(name_type == -1) {
			/* Add the (0) and (0x20) names directly into the namelist for this subnet. */
			(void)add_name_to_subnet(subrec,name,0x00,(uint16_t)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
			(void)add_name_to_subnet(subrec,name,0x20,(uint16_t)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
		} else {
			/* Add the given name type to the subnet namelist. */
			(void)add_name_to_subnet(subrec,name,name_type,(uint16_t)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
		}
	}

	TALLOC_FREE(ctx);
	endlmhosts(fp);
}
void tell_become_backup(void)
{
  struct subnet_record *subrec;
  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
  {
    struct work_record *work;
    for (work = subrec->workgrouplist; work; work = work->next)
    {
      struct server_record *servrec;
      int num_servers = 0;
      int num_backups = 0;
	  
      for (servrec = work->serverlist; servrec; servrec = servrec->next)
      {
        num_servers++;
	      
        if (is_myname(servrec->serv.name))
          continue;
	      
        if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER) 
        {
          num_backups++;
          continue;
        }
	      
        if (servrec->serv.type & SV_TYPE_MASTER_BROWSER)
          continue;
	      
        if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER))
          continue;
	      
        DEBUG(3,("num servers: %d num backups: %d\n", 
              num_servers, num_backups));
	      
        /* make first server a backup server. thereafter make every
           tenth server a backup server */
        if (num_backups != 0 && (num_servers+9) / num_backups > 10)
          continue;
	      
        DEBUG(2,("sending become backup to %s %s for %s\n",
             servrec->serv.name, inet_ntoa(subrec->bcast_ip),
             work->work_group));
	      
        /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
        do_announce_request(servrec->serv.name, work->work_group,
              ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip);
      }
    }
  }
}
Example #8
0
void announce_my_servers_removed(void)
{
    int announce_interval = lp_lm_interval();
    int lm_announce = lp_lm_announce();
    struct subnet_record *subrec;

    for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
    {
        struct work_record *work;
        for (work = subrec->workgrouplist; work; work = work->next)
        {
            struct server_record *servrec;

            work->announce_interval = 0;
            for (servrec = work->serverlist; servrec; servrec = servrec->next)
            {
                if (!is_myname(servrec->serv.name))
                    continue;
                servrec->serv.type = 0;
                if(AM_LOCAL_MASTER_BROWSER(work))
                    send_local_master_announcement(subrec, work, servrec);
                send_host_announcement(subrec, work, servrec);


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

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

                /*
                 * lm announce was set or we have seen lm announcements, so do
                 * a lm announcement of host removed.
                 */

                send_lm_host_announcement(subrec, work, servrec, 0);
            }
        }
    }
}
Example #9
0
/****************************************************************************
Load a lmhosts file.
****************************************************************************/
void load_lmhosts_file(char *fname)
{  
  pstring name;
  int name_type;
  struct in_addr ipaddr;
  FILE *fp = startlmhosts( fname );

  if (!fp) {
    DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n",
             fname, strerror(errno)));
    return;
  }
   
  while (getlmhostsent(fp, name, &name_type, &ipaddr) )
  {
    struct subnet_record *subrec = NULL;
    enum name_source source = LMHOSTS_NAME;

    /* We find a relevent subnet to put this entry on, then add it. */
    /* Go through all the broadcast subnets and see if the mask matches. */
    for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
    {
      if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip))
        break;
    }
  
    /* If none match add the name to the remote_broadcast_subnet. */
    if(subrec == NULL)
      subrec = remote_broadcast_subnet;

    if(name_type == -1)
    {
      /* Add the (0) and (0x20) names directly into the namelist for this subnet. */
      (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
      (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
    }
    else
    {
      /* Add the given name type to the subnet namelist. */
      (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
    }
  }
   
  endlmhosts(fp);
}
Example #10
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 */
}
Example #11
0
void announce_myself_to_domain_master_browser(time_t t)
{
    struct subnet_record *subrec;
    struct work_record *work;

    if(!we_are_a_wins_client())
    {
        DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n"));
        return;
    }

    if (!announce_timer_last)
        announce_timer_last = t;

    if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60))
    {
        DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n",
                  (int)t, (int)announce_timer_last,
                  CHECK_TIME_MST_ANNOUNCE * 60 ));
        return;
    }

    announce_timer_last = t;

    /* Look over all our broadcast subnets to see if any of them
       has the state set as local master browser. */

    for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
    {
        for (work = subrec->workgrouplist; work; work = work->next)
        {
            if (AM_LOCAL_MASTER_BROWSER(work))
            {
                DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \
workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));

                /* Look in nmbd_browsersync.c for the rest of this code. */
                announce_and_sync_with_domain_master_browser(subrec, work);
            }
        }
    }
}
Example #12
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 */
}
static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
				     register_name_success_function success_fn,
				     register_name_fail_function fail_fn)
{
	/*
	  If we are adding a group name, we just send multiple
	  register name packets to the WINS server (this is an
	  internet group name.

	  If we are adding a unique name, We need first to add 
	  our names to the unicast subnet namelist. This is 
	  because when a WINS server receives a multihomed 
	  registration request, the first thing it does is to 
	  send a name query to the registering machine, to see 
	  if it has put the name in it's local namelist.
	  We need the name there so the query response code in
	  nmbd_incomingrequests.c will find it.

	  We are adding this name prematurely (we don't really
	  have it yet), but as this is on the unicast subnet
	  only we will get away with this (only the WINS server
	  will ever query names from us on this subnet).
	*/
	int num_ips=0;
	int i, t;
	struct subnet_record *subrec;
	char **wins_tags;
	struct in_addr *ip_list;
	unstring name;

	for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
		num_ips++;
	
	if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
		DEBUG(0,("multihomed_register_name: malloc fail !\n"));
		return;
	}

	for (subrec = FIRST_SUBNET, i = 0; 
	     subrec;
	     subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
		ip_list[i] = subrec->myip;
	}

	pull_ascii_nstring(name, sizeof(name), nmbname->name);
	add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
			   nb_flags, lp_max_ttl(), SELF_NAME,
			   num_ips, ip_list);

	/* get the list of wins tags - we try to register for each of them */
	wins_tags = wins_srv_tags();

	/* Now try and register the name for each wins tag.  Note that
	   at this point we only register our first IP with each wins
	   group. We will register the rest from
	   wins_next_registration() when we get the reply for this
	   one. That follows the way W2K does things (tridge)
	*/
	for (t=0; wins_tags && wins_tags[t]; t++) {
		multihomed_register_one(nmbname, nb_flags,
					success_fn, fail_fn,
					ip_list[0],
					wins_tags[t]);
	}

	wins_srv_tags_free(wins_tags);
	
	SAFE_FREE(ip_list);
}