Exemplo n.º 1
0
BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question)
{
	struct name_record *namerec = NULL;
	struct in_addr dns_ip;
	unstring qname;

	pull_ascii_nstring(qname, sizeof(qname), question->name);

	DEBUG(3,("DNS search for %s - ", nmb_namestr(question)));

        /* Unblock TERM signal so we can be killed in DNS lookup. */
        BlockSignals(False, SIGTERM);

	dns_ip.s_addr = interpret_addr(qname);

        /* Re-block TERM signal. */
        BlockSignals(True, SIGTERM);

	namerec = add_dns_result(question, dns_ip);
	if(namerec == NULL) {
		send_wins_name_query_response(NAM_ERR, p, NULL);
	} else {
		send_wins_name_query_response(0, p, namerec);
	}
	return False;
}
Exemplo n.º 2
0
/***************************************************************************
queue a DNS query
  ****************************************************************************/
BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
		     struct name_record **n)
{
	if (in_dns || fd_in == -1)
		return False;

	if (!dns_current) {
		if (!write_child(p)) {
			DEBUG(3,("failed to send DNS query to child!\n"));
			return False;
		}
		dns_current = p;
		p->locked = True;
	} else {
		p->locked = True;
		p->next = dns_queue;
		p->prev = NULL;
		if (p->next)
			p->next->prev = p;
		dns_queue = p;
	}

	DEBUG(3,("added DNS query for %s\n", nmb_namestr(question)));
	return True;
}
Exemplo n.º 3
0
/*
  when releasing a name with WINS we need to send the release to each of
  the WINS groups
*/
static void wins_release_name(struct name_record *namerec,
			      release_name_success_function success_fn,
			      release_name_fail_function fail_fn,
			      struct userdata_struct *userdata)			      
{
	int t, i;
	char **wins_tags;

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

	for (t=0;wins_tags && wins_tags[t]; t++) {
		for (i = 0; i < namerec->data.num_ips; i++) {
			struct in_addr wins_ip = wins_srv_ip_tag(wins_tags[t], namerec->data.ip[i]);

			bool last_one = ((i==namerec->data.num_ips - 1) && !wins_tags[t+1]);
			if (queue_release_name(unicast_subnet,
					       release_name_response,
					       release_name_timeout_response,
					       last_one?success_fn : NULL,
					       last_one? fail_fn : NULL,
					       last_one? userdata : NULL,
					       &namerec->name,
					       namerec->data.nb_flags,
					       namerec->data.ip[i],
					       wins_ip) == NULL) {
				DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
					 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
			}
		}
	}

	wins_srv_tags_free(wins_tags);
}
Exemplo n.º 4
0
static void release_name_timeout_response(struct subnet_record *subrec,
					  struct response_record *rrec)
{
	/* a release is *always* considered to be successful when it
	   times out. This doesn't cause problems as if a WINS server
	   doesn't respond and someone else wants the name then the
	   normal WACK/name query from the WINS server will cope */
	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
	bool bcast = sent_nmb->header.nm_flags.bcast;
	struct nmb_name *question_name = &sent_nmb->question.question_name;
	struct in_addr released_ip;

	/* Get the ip address we were trying to release. */
	putip((char*)&released_ip ,&sent_nmb->additional->rdata[2]);

	if (!bcast) {
		/* mark the WINS server temporarily dead */
		wins_srv_died(rrec->packet->ip, released_ip);
	}

	DEBUG(5,("release_name_timeout_response: success in releasing name %s on subnet %s.\n",
		 nmb_namestr(question_name), subrec->subnet_name));

	if (rrec->success_fn) {
		(*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, released_ip);
	}

	standard_success_release( subrec, rrec->userdata, question_name, released_ip);
	remove_response_record(subrec, rrec);
}
void process_name_release_request(struct subnet_record *subrec, 
                                  struct packet_struct *p)
{
	struct nmb_packet *nmb = &p->packet.nmb;
	struct in_addr owner_ip;
	struct nmb_name *question = &nmb->question.question_name;
	unstring qname;
	BOOL bcast = nmb->header.nm_flags.bcast;
	uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
	BOOL group = (nb_flags & NB_GROUP) ? True : False;
	struct name_record *namerec;
	int rcode = 0;
  
	putip((char *)&owner_ip,&nmb->additional->rdata[2]);  
  
	if(!bcast) {
		/* We should only get broadcast name release packets here.
		   Anyone trying to release unicast should be going to a WINS
		   server. If the code gets here, then either we are not a wins
		   server and they sent it anyway, or we are a WINS server and
		   the request was malformed. Either way, log an error here.
		   and send an error reply back.
		*/
		DEBUG(0,("process_name_release_request: unicast name release request \
received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
			nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));      

		send_name_release_response(FMT_ERR, p);
		return;
	}
Exemplo n.º 6
0
void release_name(struct subnet_record *subrec, struct name_record *namerec,
		  release_name_success_function success_fn,
		  release_name_fail_function fail_fn,
		  struct userdata_struct *userdata)
{
	int i;

	/* Ensure it's a SELF name, and in the ACTIVE state. */
	if ((namerec->data.source != SELF_NAME) || !NAME_IS_ACTIVE(namerec)) {
		DEBUG(0,("release_name: Cannot release name %s from subnet %s. Source was %d \n",
			 nmb_namestr(&namerec->name), subrec->subnet_name, namerec->data.source)); 
		return;
	}

	/* Set the name into the deregistering state. */
	namerec->data.nb_flags |= NB_DEREG;

	/* wins releases are a bit different */
	if (subrec == unicast_subnet) {
		wins_release_name(namerec, success_fn, fail_fn, userdata);
		return;
	}

	/*  
	 * Go through and release the name for all known ip addresses.
	 * Only call the success/fail function on the last one (it should
	 * only be done once).
	 */
	for (i = 0; i < namerec->data.num_ips; i++) {
		if (queue_release_name(subrec,
				       release_name_response,
				       release_name_timeout_response,
				       (i == (namerec->data.num_ips - 1)) ? success_fn : NULL,
				       (i == (namerec->data.num_ips - 1)) ? fail_fn : NULL,
				       (i == (namerec->data.num_ips - 1)) ? userdata : NULL,
				       &namerec->name,
				       namerec->data.nb_flags,
				       namerec->data.ip[i],
				       subrec->bcast_ip) == NULL) {
			DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
				 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
		}
	}
}
Exemplo n.º 7
0
/****************************************************************************
  Function called when a query for *<1b> name fails.
  ****************************************************************************/
static void find_all_domain_master_names_query_fail(struct subnet_record *subrec,
                                    struct response_record *rrec,
                                    struct nmb_name *question_name, int fail_code)
{
	if( DEBUGLVL( 10 ) ) {
		dbgtext( "find_domain_master_name_query_fail:\n" );
		dbgtext( "WINS server did not reply to a query for name " );
		dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
		dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
	}
}
Exemplo n.º 8
0
static void multihomed_register_one(struct nmb_name *nmbname,
				    uint16 nb_flags,
				    register_name_success_function success_fn,
				    register_name_fail_function fail_fn,
				    struct in_addr ip,
				    const char *tag)
{
	struct userdata_struct *userdata;
	struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
	fstring ip_str;

	userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
	if (!userdata) {
		DEBUG(0,("Failed to allocate userdata structure!\n"));
		return;
	}
	ZERO_STRUCTP(userdata);
	userdata->userdata_len = strlen(tag) + 1;
	strlcpy(userdata->data, tag, userdata->userdata_len);	

	fstrcpy(ip_str, inet_ntoa(ip));

	DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
		 nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));

	if (queue_register_multihomed_name(unicast_subnet,
					   register_name_response,
					   register_name_timeout_response,
					   success_fn,
					   fail_fn,
					   userdata,
					   nmbname,
					   nb_flags,
					   ip,
					   wins_ip) == NULL) {
		DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n", 
			 nmb_namestr(nmbname), inet_ntoa(ip)));		
	}

	free(userdata);
}
Exemplo n.º 9
0
static void find_domain_master_name_query_fail(struct subnet_record *subrec,
                                    struct response_record *rrec,
                                    struct nmb_name *question_name, int fail_code)
{
	if( DEBUGLVL( 0 ) ) {
		dbgtext( "find_domain_master_name_query_fail:\n" );
		dbgtext( "Unable to find the Domain Master Browser name " );
		dbgtext( "%s for the workgroup %s.\n",
			nmb_namestr(question_name), question_name->name );
		dbgtext( "Unable to sync browse lists in this workgroup.\n" );
	}
}
Exemplo n.º 10
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);
}
Exemplo n.º 11
0
static void register_name_timeout_response(struct subnet_record *subrec,
					   struct response_record *rrec)
{
	/*
	 * If we are registering unicast, then NOT getting a response is an
	 * error - we do not have the name. If we are registering broadcast,
	 * then we don't expect to get a response.
	 */

	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
	bool bcast = sent_nmb->header.nm_flags.bcast;
	bool success = False;
	struct nmb_name *question_name = &sent_nmb->question.question_name;
	uint16_t nb_flags = 0;
	int ttl = 0;
	struct in_addr registered_ip;
	
	if (bcast) {
		if(rrec->num_msgs == 0) {
			/* Not receiving a message is success for broadcast registration. */
			success = True; 

			/* Pull the success values from the original request packet. */
			nb_flags = get_nb_flags(sent_nmb->additional->rdata);
			ttl = sent_nmb->additional->ttl;
			putip(&registered_ip,&sent_nmb->additional->rdata[2]);
		}
	} else {
		/* wins timeouts are special */
		wins_registration_timeout(subrec, rrec);
		return;
	}

	DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
		 success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
	if(success) {
		/* Enter the registered name into the subnet name database before calling
		   the success function. */
		standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
		if( rrec->success_fn)
			(*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
	} else {
		struct nmb_name qname = *question_name;
		if( rrec->fail_fn)
			(*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
		/* Remove the name. */
		standard_fail_register( subrec, &qname);
	}

	/* Ensure we don't retry. */
	remove_response_record(subrec, rrec);
}
Exemplo n.º 12
0
static void sync_with_dmb(struct work_record *work)
{
  if( DEBUGLVL( 2 ) )
  {
    dbgtext( "sync_with_dmb:\n" );
    dbgtext( "Initiating sync with domain master browser " );
    dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
    dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
    dbgtext( "for workgroup %s\n", work->work_group );
  }

  sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type, 
                    work->dmb_addr, False, True);
}
Exemplo n.º 13
0
void register_name(struct subnet_record *subrec,
                   const char *name, int type, uint16 nb_flags,
                   register_name_success_function success_fn,
                   register_name_fail_function fail_fn,
                   struct userdata_struct *userdata)
{
	struct nmb_name nmbname;
	nstring nname;

	errno = 0;
	push_ascii_nstring(nname, name);
        if (errno == E2BIG) {
		unstring tname;
		pull_ascii_nstring(tname, sizeof(tname), nname);
		DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
			name, tname));
		make_nmb_name(&nmbname, tname, type);
	} else {
		make_nmb_name(&nmbname, name, type);
	}

	/* Always set the NB_ACTIVE flag on the name we are
	   registering. Doesn't make sense without it.
	*/
	
	nb_flags |= NB_ACTIVE;
	
	if (subrec == unicast_subnet) {
		/* we now always do multi-homed registration if we are
		   registering to a WINS server. This copes much
		   better with complex WINS setups */
		multihomed_register_name(&nmbname, nb_flags,
					 success_fn, fail_fn);
		return;
	}
	
	if (queue_register_name(subrec,
				register_name_response,
				register_name_timeout_response,
				success_fn,
				fail_fn,
				userdata,
				&nmbname,
				nb_flags) == NULL) {
		DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
			 nmb_namestr(&nmbname)));
	}
}
Exemplo n.º 14
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);
}
Exemplo n.º 15
0
static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
{
  pstring outbuf;
  char *p;

  if(ismyip(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++;

  StrnCpy(p,global_myname,15);
  strupper(p);
  p = skip_string(p,1);

  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 );
  }

  send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
		global_myname, 0x0, work->dmb_name.name, 0x0, 
		work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);

}
Exemplo n.º 16
0
/***************************************************************************
  we use this when we can't do async DNS lookups
  ****************************************************************************/
BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
		     struct name_record **n)
{
	char *qname = question->name;
	struct in_addr dns_ip;

	DEBUG(3,("DNS search for %s - ", nmb_namestr(question)));

        /* Unblock TERM signal so we can be killed in DNS lookup. */
        BlockSignals(False, SIGTERM);

	dns_ip.s_addr = interpret_addr(qname);

        /* Re-block TERM signal. */
        BlockSignals(True, SIGTERM);

	*n = add_dns_result(question, dns_ip);
        if(*n == NULL)
          send_wins_name_query_response(NAM_ERR, p, NULL);
        else
          send_wins_name_query_response(0, p, *n);
	return False;
}
Exemplo n.º 17
0
/****************************************************************************
  send a session request.  see rfc1002.txt 4.3 and 4.3.2
****************************************************************************/
BOOL cli_session_request(struct cli_state *cli,
			 const struct nmb_name *calling,
			 const struct nmb_name *called)
{
	char *p;
	int len = 4;
	extern pstring user_socket_options;
	io_struct ps;
	uchar nb_type;

	ZERO_STRUCT(ps);
	io_init(&ps, 4096, MARSHALL);

	/* send a session request (RFC 1002) */

	smb_set_nbnames(cli->hnd, calling, called);

	/* put in the destination name */
	p = ps.data_p;
	name_mangle(called->name, p, called->name_type);
	len += name_len(p);

	/* and my name */
	p = ps.data_p + len-4;
	name_mangle(calling->name, p, calling->name_type);
	len += name_len(p);

	ps.data_offset = len;
	smb_send_smb(cli->hnd, &ps, 0x81);
	io_free(&ps);

	DEBUG(5, ("Sent session request: %s to %s\n",
			nmb_namestr(calling), nmb_namestr(called)));

	if (!smb_receive_smb(cli->hnd, &ps, &nb_type))
		return False;

	if (nb_type == 0x84)
	{
		int fd;
		/* C. Hoch  9/14/95 Start */
		/* For information, here is the response structure.
		 * We do the byte-twiddling to for portability.
		 struct RetargetResponse{
		 unsigned char type;
		 unsigned char flags;
		 int16 length;
		 int32 ip_addr;
		 int16 port;
		 };
		 */
		int port = (CVAL(ps.data_p, 4) << 8) + CVAL(ps.data_p, 5);
		/* SESSION RETARGET */
		putip((char *)&cli->dest_ip, ps.data_p);

		fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port,
					LONG_CONNECT_TIMEOUT);
		if (fd == -1 || !smb_set_fd(cli->hnd, fd))
			return False;

		cli->dbg(3, "Retargeted\n");

		set_socket_options(fd, user_socket_options);

		/* Try again */
		{
			static int depth;
			BOOL ret;
			if (depth > 4)
			{
				cli->dbg( 0,
					  "Retarget recursion - failing\n");
				return False;
			}
			depth++;
			ret = cli_session_request(cli, calling, called);
			depth--;
			return ret;
		}
	}			/* C. Hoch 9/14/95 End */

	if (nb_type != 0x82)
	{
		/* This is the wrong place to put the error... JRA. */
		cli->rap_error = CVAL(ps.data_p, 0);
		return False;
	}
	return (True);
}
Exemplo n.º 18
0
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);
}
Exemplo n.º 19
0
static void wins_registration_timeout(struct subnet_record *subrec,
				      struct response_record *rrec)
{
	struct userdata_struct *userdata = rrec->userdata;
	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
	struct nmb_name *nmbname = &sent_nmb->question.question_name;
	struct in_addr register_ip;
	fstring src_addr;

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

	fstrcpy(src_addr, inet_ntoa(register_ip));

	DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n", 
		 inet_ntoa(rrec->packet->ip), src_addr));

	/* mark it temporarily dead for this source address */
	wins_srv_died(rrec->packet->ip, register_ip);

	/* if we have some userdata then use that to work out what
	   wins server to try next */
	if (userdata) {
		const char *tag = (const char *)userdata->data;

		/* try the next wins server in our failover list for
		   this tag */
		rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
	}

	/* if we have run out of wins servers for this tag then they
	   must all have timed out. We treat this as *success*, not
	   failure, and go into our standard name refresh mode. This
	   copes with all the wins servers being down */
	if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
		uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
		int ttl = sent_nmb->additional->ttl;

		standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
		if(rrec->success_fn) {
			(*(register_name_success_function)rrec->success_fn)(subrec, 
									    rrec->userdata, 
									    nmbname, 
									    nb_flags, 
									    ttl, 
									    register_ip);
		}

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

		/* don't need to send this packet any more */
		remove_response_record(subrec, rrec);
		return;
	}
	
	/* we will be moving to the next WINS server for this group,
	   send it immediately */
	rrec->repeat_count = 2;
	rrec->repeat_time = time(NULL) + 1;
	rrec->in_expiration_processing = False;

	DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
		 nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));

	/* notice that we don't remove the response record. This keeps
	   us trying to register with each of our failover wins servers */
}
static void fail_register(struct subnet_record *subrec, struct response_record *rrec,
                          struct nmb_name *nmbname)
{  
	DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n",
		nmb_namestr(nmbname), subrec->subnet_name));
}  
Exemplo n.º 21
0
static void my_name_register_failed(struct subnet_record *subrec,
                              struct response_record *rrec, struct nmb_name *nmbname)
{
	DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n",
		nmb_namestr(nmbname), subrec->subnet_name));
}
Exemplo n.º 22
0
void register_name(struct subnet_record *subrec,
                   const char *name, int type, uint16_t nb_flags,
                   register_name_success_function success_fn,
                   register_name_fail_function fail_fn,
                   struct userdata_struct *userdata)
{
	struct nmb_name nmbname;
	nstring nname;
	size_t converted_size;

	errno = 0;
	converted_size = push_ascii_nstring(nname, name);
	if (converted_size != (size_t)-1) {
		/* Success. */
		make_nmb_name(&nmbname, name, type);
	} else if (errno == E2BIG) {
		/*
		 * Name converted to CH_DOS is too large.
		 * try to truncate.
		 */
		char *converted_str_dos = NULL;
		char *converted_str_unix = NULL;
		bool ok;

		converted_size = 0;

		ok = convert_string_talloc(talloc_tos(),
				CH_UNIX,
				CH_DOS,
				name,
				strlen(name)+1,
				&converted_str_dos,
				&converted_size);
		if (!ok) {
			DEBUG(0,("register_name: NetBIOS name %s cannot be "
				"converted. Failing to register name.\n",
				name));
			return;
		}

		/*
		 * As it's now CH_DOS codepage
		 * we truncate by writing '\0' at
		 * MAX_NETBIOSNAME_LEN-1 and then
		 * convert back to CH_UNIX which we
		 * need for the make_nmb_name() call.
		 */
		if (converted_size >= MAX_NETBIOSNAME_LEN) {
			converted_str_dos[MAX_NETBIOSNAME_LEN-1] = '\0';
		}

		ok = convert_string_talloc(talloc_tos(),
				CH_DOS,
				CH_UNIX,
				converted_str_dos,
				strlen(converted_str_dos)+1,
				&converted_str_unix,
				&converted_size);
		if (!ok) {
			DEBUG(0,("register_name: NetBIOS name %s cannot be "
				"converted back to CH_UNIX. "
				"Failing to register name.\n",
				converted_str_dos));
			TALLOC_FREE(converted_str_dos);
			return;
		}

		make_nmb_name(&nmbname, converted_str_unix, type);

		TALLOC_FREE(converted_str_dos);
		TALLOC_FREE(converted_str_unix);
	} else {
		/*
		 * Generic conversion error. Fail to register.
		 */
		DEBUG(0,("register_name: NetBIOS name %s cannot be "
			"converted (%s). Failing to register name.\n",
			name, strerror(errno)));
		return;
	}

	/* Always set the NB_ACTIVE flag on the name we are
	   registering. Doesn't make sense without it.
	*/
	
	nb_flags |= NB_ACTIVE;
	
	if (subrec == unicast_subnet) {
		/* we now always do multi-homed registration if we are
		   registering to a WINS server. This copes much
		   better with complex WINS setups */
		multihomed_register_name(&nmbname, nb_flags,
					 success_fn, fail_fn);
		return;
	}
	
	if (queue_register_name(subrec,
				register_name_response,
				register_name_timeout_response,
				success_fn,
				fail_fn,
				userdata,
				&nmbname,
				nb_flags) == NULL) {
		DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
			 nmb_namestr(&nmbname)));
	}
}
Exemplo n.º 23
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);
}
Exemplo n.º 24
0
bool cli_send_mailslot(struct messaging_context *msg_ctx,
		       bool unique, const char *mailslot,
		       uint16 priority,
		       char *buf, int len,
		       const char *srcname, int src_type,
		       const char *dstname, int dest_type,
		       const struct sockaddr_storage *dest_ss)
{
	struct packet_struct p;
	struct dgram_packet *dgram = &p.packet.dgram;
	char *ptr, *p2;
	char tmp[4];
	pid_t nmbd_pid;
	char addr[INET6_ADDRSTRLEN];

	if ((nmbd_pid = pidfile_pid("nmbd")) == 0) {
		DEBUG(3, ("No nmbd found\n"));
		return False;
	}

	if (dest_ss->ss_family != AF_INET) {
		DEBUG(3, ("cli_send_mailslot: can't send to IPv6 address.\n"));
		return false;
	}

	memset((char *)&p, '\0', sizeof(p));

	/*
	 * Next, build the DGRAM ...
	 */

	/* DIRECT GROUP or UNIQUE datagram. */
	dgram->header.msg_type = unique ? 0x10 : 0x11;
	dgram->header.flags.node_type = M_NODE;
	dgram->header.flags.first = True;
	dgram->header.flags.more = False;
	dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) +
		((unsigned)sys_getpid()%(unsigned)100);
	/* source ip is filled by nmbd */
	dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
	dgram->header.packet_offset = 0;

	make_nmb_name(&dgram->source_name,srcname,src_type);
	make_nmb_name(&dgram->dest_name,dstname,dest_type);

	ptr = &dgram->data[0];

	/* Setup the smb part. */
	ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
	memcpy(tmp,ptr,4);

	if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) {
		DEBUG(0, ("cli_send_mailslot: Cannot write beyond end of packet\n"));
		return False;
	}

	cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True);
	memcpy(ptr,tmp,4);

	SCVAL(ptr,smb_com,SMBtrans);
	SSVAL(ptr,smb_vwv1,len);
	SSVAL(ptr,smb_vwv11,len);
	SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
	SSVAL(ptr,smb_vwv13,3);
	SSVAL(ptr,smb_vwv14,1);
	SSVAL(ptr,smb_vwv15,priority);
	SSVAL(ptr,smb_vwv16,2);
	p2 = smb_buf(ptr);
	fstrcpy(p2,mailslot);
	p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2);
	if (!p2) {
		return False;
	}

	memcpy(p2,buf,len);
	p2 += len;

	dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */

	p.packet_type = DGRAM_PACKET;
	p.ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;
	p.timestamp = time(NULL);

	DEBUG(4,("send_mailslot: Sending to mailslot %s from %s ",
		 mailslot, nmb_namestr(&dgram->source_name)));
	print_sockaddr(addr, sizeof(addr), dest_ss);

	DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), addr));

	return NT_STATUS_IS_OK(messaging_send_buf(msg_ctx,
						  pid_to_procid(nmbd_pid),
						  MSG_SEND_PACKET,
						  (uint8 *)&p, sizeof(p)));
}
Exemplo n.º 25
0
NTSTATUS cli_full_connection(struct cli_state **output_cli, 
			     const char *my_name, const char *dest_host, 
			     struct in_addr *dest_ip, int port,
			     const char *service, const char *service_type,
			     const char *user, const char *domain, 
			     const char *password, int pass_len) 
{
	struct ntuser_creds creds;
	NTSTATUS nt_status;
	struct nmb_name calling;
	struct nmb_name called;
	struct cli_state *cli;
	struct in_addr ip;
	
	if (!output_cli)
		DEBUG(0, ("output_cli is NULL!?!"));

	*output_cli = NULL;
	
	make_nmb_name(&calling, my_name, 0x0);
	make_nmb_name(&called , dest_host, 0x20);

again:

	if (!(cli = cli_initialise(NULL)))
		return NT_STATUS_NO_MEMORY;
	
	if (cli_set_port(cli, port) != port) {
		cli_shutdown(cli);
		return NT_STATUS_UNSUCCESSFUL;
	}

	ip = *dest_ip;
	
	DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
	
	if (!cli_connect(cli, dest_host, &ip)) {
		DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
			 nmb_namestr(&called), inet_ntoa(*dest_ip)));
		cli_shutdown(cli);
		return NT_STATUS_UNSUCCESSFUL;
	}

	if (!cli_session_request(cli, &calling, &called)) {
		char *p;
		DEBUG(1,("session request to %s failed (%s)\n", 
			 called.name, cli_errstr(cli)));
		cli_shutdown(cli);
		if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
			*p = 0;
			goto again;
		}
		if (strcmp(called.name, "*SMBSERVER")) {
			make_nmb_name(&called , "*SMBSERVER", 0x20);
			goto again;
		}
		return NT_STATUS_UNSUCCESSFUL;
	}

	if (!cli_negprot(cli)) {
		DEBUG(1,("failed negprot\n"));
		nt_status = NT_STATUS_UNSUCCESSFUL;
		cli_shutdown(cli);
		return nt_status;
	}

	if (!cli_session_setup(cli, user, password, pass_len, password, pass_len, 
			       domain)) {
		DEBUG(1,("failed session setup\n"));
		nt_status = cli_nt_error(cli);
		cli_shutdown(cli);
		if (NT_STATUS_IS_OK(nt_status)) 
			nt_status = NT_STATUS_UNSUCCESSFUL;
		return nt_status;
	} 

	if (service) {
		if (!cli_send_tconX(cli, service, service_type,
				    password, pass_len)) {
			DEBUG(1,("failed tcon_X\n"));
			nt_status = cli_nt_error(cli);
			cli_shutdown(cli);
			if (NT_STATUS_IS_OK(nt_status)) 
				nt_status = NT_STATUS_UNSUCCESSFUL;
			return nt_status;
		}
	}

	init_creds(&creds, user, domain, password, pass_len);
	cli_init_creds(cli, &creds);

	*output_cli = cli;
	return NT_STATUS_OK;
}
Exemplo n.º 26
0
		   server. If the code gets here, then either we are not a wins
		   server and they sent it anyway, or we are a WINS server and
		   the request was malformed. Either way, log an error here.
		   and send an error reply back.
		*/
		DEBUG(0,("process_name_release_request: unicast name release request \
received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
			nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));      

		send_name_release_response(FMT_ERR, p);
		return;
	}

	DEBUG(3,("process_name_release_request: Name release on name %s, \
subnet %s from owner IP %s\n",
		nmb_namestr(&nmb->question.question_name),
		subrec->subnet_name, inet_ntoa(owner_ip)));
  
	/* If someone is releasing a broadcast group name, just ignore it. */
	if( group && !ismyip(owner_ip) )
		return;

	/*
	 * Code to work around a bug in FTP OnNet software NBT implementation.
	 * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
	 * names and *don't set the group bit* !!!!!
	 */

	pull_ascii_nstring(qname, sizeof(qname), question->name);
	if( !group && !ismyip(owner_ip) && strequal(qname, lp_workgroup()) && 
			((question->name_type == 0x0) || (question->name_type == 0x1e))) {
Exemplo n.º 27
0
int cli_send_mailslot(int dgram_sock, BOOL unique, const char *mailslot, 
		      char *buf, int len,
		      const char *srcname, int src_type, 
		      const char *dstname, int dest_type,
		      struct in_addr dest_ip, struct in_addr src_ip,
		      int dest_port, int src_port)
{
  struct packet_struct p;
  struct dgram_packet *dgram = &p.packet.dgram;
  char *ptr, *p2;
  char tmp[4];

  memset((char *)&p, '\0', sizeof(p));

  /*
   * Next, build the DGRAM ...
   */

  /* DIRECT GROUP or UNIQUE datagram. */
  dgram->header.msg_type = unique ? 0x10 : 0x11; 
  dgram->header.flags.node_type = M_NODE;
  dgram->header.flags.first = True;
  dgram->header.flags.more = False;
  dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100);
  dgram->header.source_ip.s_addr = src_ip.s_addr;
  dgram->header.source_port = ntohs(src_port);
  dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
  dgram->header.packet_offset = 0;
  
  make_nmb_name(&dgram->source_name,srcname,src_type);
  make_nmb_name(&dgram->dest_name,dstname,dest_type);

  ptr = &dgram->data[0];

  /* Setup the smb part. */
  ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
  memcpy(tmp,ptr,4);
  set_message(ptr,17,17 + len,True);
  memcpy(ptr,tmp,4);

  SCVAL(ptr,smb_com,SMBtrans);
  SSVAL(ptr,smb_vwv1,len);
  SSVAL(ptr,smb_vwv11,len);
  SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
  SSVAL(ptr,smb_vwv13,3);
  SSVAL(ptr,smb_vwv14,1);
  SSVAL(ptr,smb_vwv15,1);
  SSVAL(ptr,smb_vwv16,2);
  p2 = smb_buf(ptr);
  fstrcpy(p2,mailslot);
  p2 = skip_string(p2,1);

  memcpy(p2,buf,len);
  p2 += len;

  dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */

  p.ip = dest_ip;
  p.port = dest_port;
  p.fd = dgram_sock;
  p.timestamp = time(NULL);
  p.packet_type = DGRAM_PACKET;

  DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot,
                    nmb_namestr(&dgram->source_name), inet_ntoa(src_ip)));
  DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip)));

  return send_packet(&p);

}
Exemplo n.º 28
0
static bool cli_prep_mailslot(bool unique, const char *mailslot,
		       uint16_t priority,
		       char *buf, int len,
		       const char *srcname, int src_type,
		       const char *dstname, int dest_type,
		       const struct sockaddr_storage *dest_ss,
		       int dgm_id,
		       struct packet_struct *p)
{
	struct dgram_packet *dgram = &p->packet.dgram;
	char *ptr, *p2;
	char tmp[4];
	char addr[INET6_ADDRSTRLEN];

	ZERO_STRUCTP(p);

	/*
	 * Next, build the DGRAM ...
	 */

	/* DIRECT GROUP or UNIQUE datagram. */
	dgram->header.msg_type = unique ? 0x10 : 0x11;
	dgram->header.flags.node_type = M_NODE;
	dgram->header.flags.first = True;
	dgram->header.flags.more = False;
	dgram->header.dgm_id = dgm_id;
	/* source ip is filled by nmbd */
	dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
	dgram->header.packet_offset = 0;

	make_nmb_name(&dgram->source_name,srcname,src_type);
	make_nmb_name(&dgram->dest_name,dstname,dest_type);

	ptr = &dgram->data[0];

	/* Setup the smb part. */
	ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
	memcpy(tmp,ptr,4);

	if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) {
		DEBUG(0, ("cli_send_mailslot: Cannot write beyond end of packet\n"));
		return False;
	}

	cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True);
	memcpy(ptr,tmp,4);

	SCVAL(ptr,smb_com,SMBtrans);
	SSVAL(ptr,smb_vwv1,len);
	SSVAL(ptr,smb_vwv11,len);
	SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
	SSVAL(ptr,smb_vwv13,3);
	SSVAL(ptr,smb_vwv14,1);
	SSVAL(ptr,smb_vwv15,priority);
	SSVAL(ptr,smb_vwv16,2);
	p2 = smb_buf(ptr);
	fstrcpy(p2,mailslot);
	p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2);
	if (!p2) {
		return False;
	}

	memcpy(p2,buf,len);
	p2 += len;

	dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */

	p->packet_type = DGRAM_PACKET;
	p->ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;
	p->timestamp = time(NULL);

	DEBUG(4,("send_mailslot: Sending to mailslot %s from %s ",
		 mailslot, nmb_namestr(&dgram->source_name)));
	print_sockaddr(addr, sizeof(addr), dest_ss);

	DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), addr));

	return true;
}
Exemplo n.º 29
0
/****************************************************************************
establishes a connection right up to doing tconX, reading in a password.
****************************************************************************/
BOOL cli_establish_connection(struct cli_state *cli,
			      char *dest_host, struct in_addr *dest_ip,
			      struct nmb_name *calling,
			      struct nmb_name *called, char *service,
			      char *service_type, BOOL do_shutdown,
			      BOOL do_tcon)
{
	cli->dbg(5,
		 "cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
		 nmb_namestr(calling), nmb_namestr(called),
		 inet_ntoa(*dest_ip), cli->user_name, cli->domain);

	/* establish connection */

	if ((!cli->initialised))
	{
		return False;
	}

	if (!cli_connect(cli, dest_host, dest_ip))
	{
		cli->dbg(1,
			 "cli_establish_connection: failed to connect to %s (%s)\n",
			 nmb_namestr(calling), inet_ntoa(*dest_ip));
		return False;
	}

	if (!cli_session_request(cli, calling, called))
	{
		cli->dbg(1, "failed session request\n");
		if (do_shutdown)
			cli_shutdown(cli);
		return False;
	}

	if (!cli_negprot(cli))
	{
		cli->dbg(1, "failed negprot\n");
		if (do_shutdown)
			cli_shutdown(cli);
		return False;
	}

	if (cli->pwd.cleartext || cli->pwd.null_pwd)
	{
		fstring passwd;
		int pass_len;

		if (cli->pwd.null_pwd)
		{
			/* attempt null session */
			passwd[0] = 0;
			pass_len = 1;
		}
		else
		{
			/* attempt clear-text session */
			pwd_get_cleartext(&(cli->pwd), passwd);
			pass_len = strlen(passwd);
		}

		/* attempt clear-text session */
		if (!cli_session_setup(cli, cli->user_name,
				       passwd, pass_len,
				       NULL, 0, cli->domain))
		{
			cli->dbg(1, "failed session setup\n");
			if (do_shutdown)
			{
				cli_shutdown(cli);
			}
			return False;
		}
		if (do_tcon)
		{
			if (!cli_send_tconX(cli, service, service_type,
					    (char *)passwd, strlen(passwd)))
			{
				cli->dbg(1, "failed tcon_X\n");
				if (do_shutdown)
				{
					cli_shutdown(cli);
				}
				return False;
			}
		}
	}
	else
	{
		/* attempt encrypted session */
		unsigned char nt_sess_pwd[24];
		unsigned char lm_sess_pwd[24];

		/* creates (storing a copy of) and then obtains a 24 byte password OWF */
		pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
		pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);

		/* attempt encrypted session */
		if (!cli_session_setup(cli, cli->user_name,
				       (char *)lm_sess_pwd,
				       sizeof(lm_sess_pwd),
				       (char *)nt_sess_pwd,
				       sizeof(nt_sess_pwd), cli->domain))
		{
			cli->dbg(1, "failed session setup\n");
			if (do_shutdown)
				cli_shutdown(cli);
			return False;
		}

		if (do_tcon)
		{
			if (!cli_send_tconX(cli, service, service_type,
					    (char *)nt_sess_pwd,
					    sizeof(nt_sess_pwd)))
			{
				cli->dbg(1, "failed tcon_X\n");
				if (do_shutdown)
					cli_shutdown(cli);
				return False;
			}
		}
	}

	if (do_shutdown)
		cli_shutdown(cli);

	return True;
}
Exemplo n.º 30
0
  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", nmb_namestr(answer_name), nmb_namestr(question_name)));
    return;
  }

  DEBUG(5,("node_status_response: response from name %s on subnet %s.\n",
        nmb_namestr(answer_name), subrec->subnet_name));

  /* Just send the whole answer resource record for the success function
     to parse. */
  if(rrec->success_fn)
    (*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip);

  /* Ensure we don't retry. */
  remove_response_record(subrec, rrec);
}

/****************************************************************************
 Deal with a timeout when requesting a node status.
****************************************************************************/
static void node_status_timeout_response(struct subnet_record *subrec,
                       struct response_record *rrec)