void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
{
	struct smbd_server_connection *sconn = xconn->client->sconn;
	int msg_type = CVAL(inbuf,0);
	int msg_flags = CVAL(inbuf,1);
	/*
	 * We only really use 4 bytes of the outbuf, but for the smb_setlen
	 * calculation & friends (smb1_srv_send uses that) we need the full smb
	 * header.
	 */
	char outbuf[smb_size];

	memset(outbuf, '\0', sizeof(outbuf));

	smb_setlen(outbuf,0);

	switch (msg_type) {
	case NBSSrequest: /* session request */
	{
		/* inbuf_size is guarenteed to be at least 4. */
		fstring name1,name2;
		int name_type1, name_type2;
		int name_len1, name_len2;

		*name1 = *name2 = 0;

		if (xconn->transport.nbt.got_session) {
			exit_server_cleanly("multiple session request not permitted");
		}

		SCVAL(outbuf,0,NBSSpositive);
		SCVAL(outbuf,3,0);

		/* inbuf_size is guaranteed to be at least 4. */
		name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
		if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
			DEBUG(0,("Invalid name length in session request\n"));
			reply_called_name_not_present(outbuf);
			break;
		}
		name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
		if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
			DEBUG(0,("Invalid name length in session request\n"));
			reply_called_name_not_present(outbuf);
			break;
		}

		name_type1 = name_extract((unsigned char *)inbuf,
				inbuf_size,(unsigned int)4,name1);
		name_type2 = name_extract((unsigned char *)inbuf,
				inbuf_size,(unsigned int)(4 + name_len1),name2);

		if (name_type1 == -1 || name_type2 == -1) {
			DEBUG(0,("Invalid name type in session request\n"));
			reply_called_name_not_present(outbuf);
			break;
		}

		DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
			 name1, name_type1, name2, name_type2));

		if (netbios_session_retarget(xconn, name1, name_type1)) {
			exit_server_cleanly("retargeted client");
		}

		/*
		 * Windows NT/2k uses "*SMBSERVER" and XP uses
		 * "*SMBSERV" arrggg!!!
		 */
		if (strequal(name1, "*SMBSERVER     ")
		    || strequal(name1, "*SMBSERV       "))  {
			char *raddr;

			raddr = tsocket_address_inet_addr_string(sconn->remote_address,
								 talloc_tos());
			if (raddr == NULL) {
				exit_server_cleanly("could not allocate raddr");
			}

			fstrcpy(name1, raddr);
		}

		set_local_machine_name(name1, True);
		set_remote_machine_name(name2, True);

		if (is_ipaddress(sconn->remote_hostname)) {
			char *p = discard_const_p(char, sconn->remote_hostname);

			talloc_free(p);

			sconn->remote_hostname = talloc_strdup(sconn,
						get_remote_machine_name());
			if (sconn->remote_hostname == NULL) {
				exit_server_cleanly("could not copy remote name");
			}
			xconn->remote_hostname = sconn->remote_hostname;
		}

		DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
			 get_local_machine_name(), get_remote_machine_name(),
			 name_type2));

		if (name_type2 == 'R') {
			/* We are being asked for a pathworks session ---
			   no thanks! */
			reply_called_name_not_present(outbuf);
			break;
		}

		reload_services(sconn, conn_snum_used, true);
		reopen_logs();

		xconn->transport.nbt.got_session = true;
		break;
	}

	case 0x89: /* session keepalive request
		      (some old clients produce this?) */
		SCVAL(outbuf,0,NBSSkeepalive);
		SCVAL(outbuf,3,0);
		break;

	case NBSSpositive: /* positive session response */
	case NBSSnegative: /* negative session response */
	case NBSSretarget: /* retarget session response */
		DEBUG(0,("Unexpected session response\n"));
		break;

	case NBSSkeepalive: /* session keepalive */
	default:
		return;
	}

	DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
		    msg_type, msg_flags));

	if (!smb1_srv_send(xconn, outbuf, false, 0, false, NULL)) {
		exit_server_cleanly("reply_special: smb1_srv_send failed.");
	}

	if (CVAL(outbuf, 0) != 0x82) {
		exit_server_cleanly("invalid netbios session");
	}
	return;
}
void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
{
	struct smbd_server_connection *sconn = xconn->client->sconn;
	int msg_type = CVAL(inbuf,0);
	int msg_flags = CVAL(inbuf,1);
	 
	char outbuf[smb_size];

	memset(outbuf, '\0', sizeof(outbuf));

	smb_setlen(outbuf,0);

	switch (msg_type) {
	case NBSSrequest:  
	{
		 
		fstring name1,name2;
		int name_type1, name_type2;
		int name_len1, name_len2;

		*name1 = *name2 = 0;

		if (xconn->transport.nbt.got_session) {
			exit_server_cleanly("multiple session request not permitted");
		}

		SCVAL(outbuf,0,NBSSpositive);
		SCVAL(outbuf,3,0);

		 
		name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
		if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
			DEBUG(0,("Invalid name length in session request\n"));
			reply_called_name_not_present(outbuf);
			break;
		}
		name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
		if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
			DEBUG(0,("Invalid name length in session request\n"));
			reply_called_name_not_present(outbuf);
			break;
		}

		name_type1 = name_extract((unsigned char *)inbuf,
				inbuf_size,(unsigned int)4,name1);
		name_type2 = name_extract((unsigned char *)inbuf,
				inbuf_size,(unsigned int)(4 + name_len1),name2);

		if (name_type1 == -1 || name_type2 == -1) {
			DEBUG(0,("Invalid name type in session request\n"));
			reply_called_name_not_present(outbuf);
			break;
		}

		DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
			 name1, name_type1, name2, name_type2));

		if (netbios_session_retarget(xconn, name1, name_type1)) {
			exit_server_cleanly("retargeted client");
		}

		 
		if (strequal(name1, "*SMBSERVER     ")
		    || strequal(name1, "*SMBSERV       "))  {
			char *raddr;

			raddr = tsocket_address_inet_addr_string(sconn->remote_address,
								 talloc_tos());
			if (raddr == NULL) {
				exit_server_cleanly("could not allocate raddr");
			}

			fstrcpy(name1, raddr);
		}

		set_local_machine_name(name1, True);
		set_remote_machine_name(name2, True);

		if (is_ipaddress(sconn->remote_hostname)) {
			char *p = discard_const_p(char, sconn->remote_hostname);

			talloc_free(p);

			sconn->remote_hostname = talloc_strdup(sconn,
						get_remote_machine_name());
			if (sconn->remote_hostname == NULL) {
				exit_server_cleanly("could not copy remote name");
			}
			xconn->remote_hostname = sconn->remote_hostname;
		}

		DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
			 get_local_machine_name(), get_remote_machine_name(),
			 name_type2));

		if (name_type2 == 'R') {
			 
			reply_called_name_not_present(outbuf);
			break;
		}

		reload_services(sconn, conn_snum_used, true);
		reopen_logs();

		xconn->transport.nbt.got_session = true;
		break;
	}

	case 0x89:  
		SCVAL(outbuf,0,NBSSkeepalive);
		SCVAL(outbuf,3,0);
		break;

	case NBSSpositive:  
	case NBSSnegative:  
	case NBSSretarget:  
		DEBUG(0,("Unexpected session response\n"));
		break;

	case NBSSkeepalive:  
	default:
		return;
	}

	DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
		    msg_type, msg_flags));

	if (!smb1_srv_send(xconn, outbuf, false, 0, false, NULL)) {
		exit_server_cleanly("reply_special: smb1_srv_send failed.");
	}

	if (CVAL(outbuf, 0) != 0x82) {
		exit_server_cleanly("invalid netbios session");
	}
	return;
}