static void register_name_response(struct subnet_record *subrec,
                       struct response_record *rrec, struct packet_struct *p)
{
  /* 
   * If we are registering broadcast, then getting a response is an
   * error - we do not have the name. If we are registering unicast,
   * then we expect to get a response.
   */

  struct nmb_packet *nmb = &p->packet.nmb;
  BOOL bcast = nmb->header.nm_flags.bcast;
  BOOL success = True;
  struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
  struct nmb_name *answer_name = &nmb->answers->rr_name;
  int ttl = 0;
  uint16 nb_flags = 0;
  struct in_addr registered_ip;

  /* Sanity check. Ensure that the answer name in the incoming packet is the
     same as the requested name in the outgoing packet. */

  if(!nmb_name_equal(question_name, answer_name))
  {
    DEBUG(0,("register_name_response: Answer name %s differs from question \
name %s.\n", namestr(answer_name), namestr(question_name)));
    return;
  }
Example #2
0
BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
                                     struct in_addr *pdest_ip)
{
	struct nmb_name calling, called;

	make_nmb_name(&calling, srchost, 0x0);

	/*
	 * If the called name is an IP address
	 * then use *SMBSERVER immediately.
	 */

	if(is_ipaddress(desthost))
		make_nmb_name(&called, "*SMBSERVER", 0x20);
	else
		make_nmb_name(&called, desthost, 0x20);

	if (!cli_session_request(cli, &calling, &called)) {
	
		struct nmb_name smbservername;

		make_nmb_name(&smbservername , "*SMBSERVER", 0x20);

		/*
		 * If the name wasn't *SMBSERVER then
		 * try with *SMBSERVER if the first name fails.
		 */

		if (nmb_name_equal(&called, &smbservername)) {

			/*
			 * The name used was *SMBSERVER, don't bother with another name.
			 */

			DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER with error %s.\n", 
				desthost, cli_errstr(cli) ));
			return False;
		}

		/*
		 * We need to close the connection here but can't call cli_shutdown as
		 * will free an allocated cli struct. cli_close_connection was invented
		 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <*****@*****.**>.
		 */

		cli_close_connection(cli);

		if (!cli_initialise(cli) || !cli_connect(cli, desthost, pdest_ip) ||
       			!cli_session_request(cli, &calling, &smbservername)) {
			DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER with error %s\n", 
				desthost, cli_errstr(cli) ));
			return False;
		}
	}

	return True;
}
/****************************************************************************
 Deal with a successful node status response.
****************************************************************************/
static void node_status_response(struct subnet_record *subrec,
                       struct response_record *rrec, struct packet_struct *p)
{
  struct nmb_packet *nmb = &p->packet.nmb;
  struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
  struct nmb_name *answer_name = &nmb->answers->rr_name;

  /* Sanity check. Ensure that the answer name in the incoming packet is the
     same as the requested name in the outgoing packet. */

  if(!nmb_name_equal(question_name, answer_name))
  {
    DEBUG(0,("node_status_response: Answer name %s differs from question \
name %s.\n", namestr(answer_name), namestr(question_name)));
    return;
  }
static void register_name_response(struct subnet_record *subrec,
                       struct response_record *rrec, struct packet_struct *p)
{
	/* 
	 * If we are registering broadcast, then getting a response is an
	 * error - we do not have the name. If we are registering unicast,
	 * then we expect to get a response.
	 */

	struct nmb_packet *nmb = &p->packet.nmb;
	BOOL bcast = nmb->header.nm_flags.bcast;
	BOOL success = True;
	struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
	struct nmb_name *answer_name = &nmb->answers->rr_name;
	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
	int ttl = 0;
	uint16 nb_flags = 0;
	struct in_addr register_ip;
	fstring reg_name;
	
	putip(&register_ip,&sent_nmb->additional->rdata[2]);
	fstrcpy(reg_name, inet_ntoa(register_ip));
	
	if (subrec == unicast_subnet) {
		/* we know that this wins server is definately alive - for the moment! */
		wins_srv_alive(rrec->packet->ip, register_ip);
	}

	/* Sanity check. Ensure that the answer name in the incoming packet is the
	   same as the requested name in the outgoing packet. */

	if(!question_name || !answer_name) {
		DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
			 question_name ? "question_name" : "answer_name" ));
		return;
	}

	if(!nmb_name_equal(question_name, answer_name)) {
		DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", 
			 nmb_namestr(answer_name), nmb_namestr(question_name)));
		return;
	}

	if(bcast) {
		/*
		 * Special hack to cope with old Samba nmbd's.
		 * Earlier versions of Samba (up to 1.9.16p11) respond 
		 * to a broadcast name registration of WORKGROUP<1b> when 
		 * they should not. Hence, until these versions are gone, 
		 * we should treat such errors as success for this particular
		 * case only. [email protected].
		 */
		
#if 1 /* OLD_SAMBA_SERVER_HACK */
		unstring ans_name;
		pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name);
		if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) &&
		   (answer_name->name_type == 0x1b)) {
			/* Pretend we did not get this. */
			rrec->num_msgs--;

			DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", 
				 nmb_namestr(answer_name)));
			return;
		}
#endif /* OLD_SAMBA_SERVER_HACK */

		/* Someone else has the name. Log the problem. */
		DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n", 
			 nmb_namestr(answer_name), 
			 reg_name,
			 subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
		success = False;
	} else {
		/* Unicast - check to see if the response allows us to have the name. */
		if (nmb->header.opcode == NMB_WACK_OPCODE) {
			/* WINS server is telling us to wait. Pretend we didn't get
			   the response but don't send out any more register requests. */

			DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", 
				 inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));

			rrec->repeat_count = 0;
			/* How long we should wait for. */
			rrec->repeat_time = p->timestamp + nmb->answers->ttl;
			rrec->num_msgs--;
			return;
		} else if (nmb->header.rcode != 0) {
			/* Error code - we didn't get the name. */
			success = False;

			DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", 
				 subrec==unicast_subnet?"WINS ":"",
				 inet_ntoa(p->ip), 
				 nmb_namestr(answer_name), 
				 reg_name,
				 nmb->header.rcode));
		} else {
			success = True;
			/* Get the data we need to pass to the success function. */
			nb_flags = get_nb_flags(nmb->answers->rdata);
			ttl = nmb->answers->ttl;

			/* send off a registration for the next IP, if any */
			wins_next_registration(rrec);
		}
	} 

	DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
		 success ? "success" : "failure", 
		 subrec==unicast_subnet?"WINS ":"",
		 nmb_namestr(answer_name), 
		 reg_name,
		 inet_ntoa(rrec->packet->ip)));

	if(success) {
		/* Enter the registered name into the subnet name database before calling
		   the success function. */
		standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
		if( rrec->success_fn)
			(*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
	} else {
		if( rrec->fail_fn)
			(*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
		/* Remove the name. */
		standard_fail_register( subrec, rrec, question_name);
	}

	/* Ensure we don't retry. */
	remove_response_record(subrec, rrec);
}
Example #5
0
/***************************************************************************
  check the DNS queue
  ****************************************************************************/
void run_dns_queue(void)
{
	struct query_record r;
	struct packet_struct *p, *p2;
	struct name_record *namerec;
	int size;

	if (fd_in == -1)
		return;

        /* Allow SIGTERM to kill us. */
        BlockSignals(False, SIGTERM);

	if (!process_exists(child_pid)) {
		close(fd_in);
		start_async_dns();
	}

	if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) {
		if (size) {
			DEBUG(0,("Incomplete DNS answer from child!\n"));
			fd_in = -1;
		}
                BlockSignals(True, SIGTERM);
		return;
	}

        BlockSignals(True, SIGTERM);

	namerec = add_dns_result(&r.name, r.result);

	if (dns_current) {
		if (query_current(&r)) {
			DEBUG(3,("DNS calling send_wins_name_query_response\n"));
			in_dns = 1;
                        if(namerec == NULL)
                          send_wins_name_query_response(NAM_ERR, dns_current, NULL);
                        else
			  send_wins_name_query_response(0,dns_current,namerec);
			in_dns = 0;
		}

		dns_current->locked = False;
		free_packet(dns_current);
		dns_current = NULL;
	}

	/* loop over the whole dns queue looking for entries that
	   match the result we just got */
	for (p = dns_queue; p;) {
		struct nmb_packet *nmb = &p->packet.nmb;
		struct nmb_name *question = &nmb->question.question_name;

		if (nmb_name_equal(question, &r.name)) {
			DEBUG(3,("DNS calling send_wins_name_query_response\n"));
			in_dns = 1;
                        if(namerec == NULL)
			  send_wins_name_query_response(NAM_ERR, p, NULL);
                        else
                          send_wins_name_query_response(0,p,namerec);
			in_dns = 0;
			p->locked = False;

			if (p->prev)
				p->prev->next = p->next;
			else
				dns_queue = p->next;
			if (p->next)
				p->next->prev = p->prev;
			p2 = p->next;
			free_packet(p);
			p = p2;
		} else {
			p = p->next;
		}
	}

	if (dns_queue) {
		dns_current = dns_queue;
		dns_queue = dns_queue->next;
		if (dns_queue) dns_queue->prev = NULL;
		dns_current->next = NULL;

		if (!write_child(dns_current)) {
			DEBUG(3,("failed to send DNS query to child!\n"));
			return;
		}
	}

}
Example #6
0
/***************************************************************************
check if a particular name is already being queried
  ****************************************************************************/
static BOOL query_current(struct query_record *r)
{
	return dns_current &&
		nmb_name_equal(&r->name, 
			   &dns_current->packet.nmb.question.question_name);
}
Example #7
0
static void release_name_response(struct subnet_record *subrec,
				  struct response_record *rrec, struct packet_struct *p)
{
	/* 
	 * If we are releasing broadcast, then getting a response is an
	 * error. If we are releasing unicast, then we expect to get a response.
	 */
	struct nmb_packet *nmb = &p->packet.nmb;
	bool bcast = nmb->header.nm_flags.bcast;
	bool success = True;
	struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
	struct nmb_name *answer_name = &nmb->answers->rr_name;
	struct in_addr released_ip;

	/* Sanity check. Ensure that the answer name in the incoming packet is the
	   same as the requested name in the outgoing packet. */
	if (!nmb_name_equal(question_name, answer_name)) {
		DEBUG(0,("release_name_response: Answer name %s differs from question name %s.\n", 
			 nmb_namestr(answer_name), nmb_namestr(question_name)));
		return;
	}

	if (bcast) {
		/* Someone sent a response to a bcast release? ignore it. */
		return;
	}

	/* Unicast - check to see if the response allows us to release the name. */
	if (nmb->header.rcode != 0) {
		/* Error code - we were told not to release the name ! What now ! */
		success = False;

		DEBUG(0,("release_name_response: WINS server at IP %s rejected our \
name release of name %s with error code %d.\n", 
			 inet_ntoa(p->ip), 
			 nmb_namestr(answer_name), nmb->header.rcode));
	} else if (nmb->header.opcode == NMB_WACK_OPCODE) {
		/* WINS server is telling us to wait. Pretend we didn't get
		   the response but don't send out any more release requests. */

		DEBUG(5,("release_name_response: WACK from WINS server %s in releasing \
name %s on subnet %s.\n", 
			 inet_ntoa(p->ip), nmb_namestr(answer_name), subrec->subnet_name));

		rrec->repeat_count = 0;
		/* How long we should wait for. */
		rrec->repeat_time = p->timestamp + nmb->answers->ttl;
		rrec->num_msgs--;
		return;
	}

	DEBUG(5,("release_name_response: %s in releasing name %s on subnet %s.\n",
		 success ? "success" : "failure", nmb_namestr(answer_name), subrec->subnet_name));
	if (success) {
		putip((char*)&released_ip ,&nmb->answers->rdata[2]);

		if(rrec->success_fn)
			(*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, released_ip);
		standard_success_release( subrec, rrec->userdata, answer_name, released_ip);
	} else {
		/* We have no standard_fail_release - maybe we should add one ? */
		if (rrec->fail_fn) {
			(*(release_name_fail_function)rrec->fail_fn)(subrec, rrec, answer_name);
		}
	}

	remove_response_record(subrec, rrec);
}