Example #1
0
		private string queryName(IPAddress winsaddr, string netbiosname)
		{
			fSocket = new UDPCli();

			byte[] encodedname = buildSecondLevelEncodedName(netbiosname);

			int trid = nextTRID();

			clearHeader();

			int pos = HDR_NAME_TRN_ID_2;
			setShortAt(pos, fData, trid);

			int opcode;
			int rcode;
			int nmflags = RECURSIVE_DESIRED;
			int flags = (nmflags << NM_FLAGS_SHIFT);

			pos = HDR_FLAGS_2;
			setShortAt(pos, fData, (flags & 0xffff));

			pos = HDR_QDCOUNT_2;
			setShortAt(pos, fData, 1);

			pos = QUESTION_NAME_OFF;
			for(int i=0; i<encodedname.Length; i++)
				fData[pos++] = encodedname[i];

			setShortAt(pos, fData, QUESTION_TYPE_NB);
			pos += 2;
			setShortAt(pos, fData, QUESTION_CLASS_IN);
			pos += 2;
			
			//byte[] packet = new byte[fData.Length];

			if(Debug.DebugOn && Debug.DebugLevel >= Debug.Buffer)
			{
				Debug.WriteLine(Debug.Buffer, "NBNS name query request:");
				Debug.WriteLine(Debug.Buffer, fData, 0, pos);
			}

			IPEndPoint ip = new IPEndPoint(winsaddr, NAME_SERVICE_UDP_PORT);

			fSocket.Send(fData, pos, ip);
			
			StringBuilder rrname = new StringBuilder();

			while(true)
			{
				bool bSuccess = fSocket.DoReceive(ref ip, ref fData);
				
				if(!bSuccess) // no response from server
					break;

				if(trid != getShortAt(0, fData))
					continue;

				if(Debug.DebugOn && Debug.DebugLevel >= Debug.Buffer)
				{
					Debug.WriteLine(Debug.Buffer, "NBNS response:");
					Debug.WriteLine(Debug.Buffer, fData, 0, fData.Length);
				}
				
				flags = getShortAt(2, fData);
				rcode = flags & RCODE_MASK;

				if ((flags & RESPONSE_PACKET) == 0)
					break; // not a response

				opcode  = ((flags & OPCODE_MASK) >> OPCODE_SHIFT) & 0xf;
				nmflags = ((flags & NM_FLAGS_MASK) >> NM_FLAGS_SHIFT) & 0x7f;

				if (opcode == OPCODE_WACK)
				{
					/*
					    WAIT FOR ACKNOWLEDGEMENT (WACK) RESPONSE

					                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
					    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |         NAME_TRN_ID           |1|  0x7  |1|0|0|0|0 0|0|  0x0  |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          0x0000               |           0x0001              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          0x0000               |           0x0000              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                                                               |
					    /                            RR_NAME                            /
					    /                                                               /
					    |                                                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          NULL (0x0020)        |         IN (0x0001)           |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                              TTL                              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |           0x0002              | OPCODE  |   NM_FLAGS  |  0x0  |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



					The NAME_TRN_ID of the WACK RESPONSE packet is the same
					NAME_TRN_ID of the request that the NBNS is telling the requestor
					to wait longer to complete.  The RR_NAME is the name from the
					request, if any.  If no name is available from the request then
					it is a null name, single byte of zero.

					The TTL field of the ResourceRecord is the new time to wait, in
					seconds, for the request to complete.  The RDATA field contains
					the OPCODE and NM_FLAGS of the request.

					A TTL value of 0 means that the NBNS can not estimate the time it
					may take to complete a response.
					*/
					
					// read RR_NAME
					
					pos = HDR_SIZE;
					pos = parseSecondLevelEncodedName(fData, pos, rrname);

					// skip
					pos += 4;
					int ttl = getIntAt(pos, fData);
					if(ttl == 0)
						fTimeout = UCAST_REQ_RETRY_TIMEOUT;
					else
						fTimeout = ttl;

					continue;
				}

				if (rcode == 0)
				{
					//check if redirect
					
					if((nmflags & AUTHORITATIVE_ANSWER) != 0)
					{
					    /*
					 POSITIVE NAME QUERY RESPONSE

					                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
					    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |         NAME_TRN_ID           |1|  0x0  |1|T|1|?|0 0|0|  0x0  |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          0x0000               |           0x0001              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          0x0000               |           0x0000              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                                                               |
					    /                            RR_NAME                            /
					    /                                                               /
					    |                                                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |           NB (0x0020)         |         IN (0x0001)           |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                              TTL                              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |           RDLENGTH            |                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
					    |                                                               |
					    /                       ADDR_ENTRY ARRAY                        /
					    /                                                               /
					    |                                                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

					    The ADDR_ENTRY ARRAY a sequence of zero or more ADDR_ENTRY
					    records.  Each ADDR_ENTRY record represents an owner of a name.
					    For group names there may be multiple entries.  However, the list
					    may be incomplete due to packet size limitations.  Bit 22, "T",
					    will be set to indicate truncated data.

					    Each ADDR_ENTRY has the following format:

					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          NB_FLAGS             |          NB_ADDRESS           |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |   NB_ADDRESS (continued)      |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

					*/

					    // read RR_NAME
						pos = HDR_SIZE;

						pos = parseSecondLevelEncodedName(fData, pos, rrname);

						// skip

						pos += 8;

						int rdlength = getShortAt(pos, fData);
						pos += 2;
						
						if(rdlength >= 6)
						{
							pos += 2; // skip NB_FLAGS
							fSocket = null;
							return Util.Util.GetIpAddress(fData, pos);
						}
					}
					else
					{
					 /*
					        REDIRECT NAME QUERY RESPONSE

					                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
					    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |         NAME_TRN_ID           |1|  0x0  |0|0|1|0|0 0|0|  0x0  |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          0x0000               |           0x0000              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |          0x0001               |           0x0001              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                                                               |
					    /                            RR_NAME                            /
					    /                                                               /
					    |                                                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |           NS (0x0002)         |         IN (0x0001)           |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                              TTL                              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |           RDLENGTH            |                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
					    |                                                               |
					    /                            NSD_NAME                           /
					    /                                                               /
					    |                                                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                                                               |
					    /                            RR_NAME                            /
					    /                                                               /
					    |                                                               |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |           A (0x0001)          |         IN (0x0001)           |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |                              TTL                              |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |             0x0004            |           NSD_IP_ADDR         |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					    |     NSD_IP_ADDR, continued    |
					    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

					    An end node responding to a NAME QUERY REQUEST always responds
					    with the AA and RA bits set for both the NEGATIVE and POSITIVE
					    NAME QUERY RESPONSE packets.  An end node never sends a REDIRECT
					    NAME QUERY RESPONSE packet.

					    When the requestor receives the REDIRECT NAME QUERY RESPONSE it
					    must reiterate the NAME QUERY REQUEST to the NBNS specified by
					    the NSD_IP_ADDR field of the A type RESOURCE RECORD in the
					    ADDITIONAL section of the response packet.  This is an optional
					    packet for the NBNS.

					    The NSD_NAME and the RR_NAME in the ADDITIONAL section of the
					    response packet are the same name.  Space can be optimized if
					    label string pointers are used in the RR_NAME which point to the
					    labels in the NSD_NAME.

					    The RR_NAME in the AUTHORITY section is the name of the domain
					    the NBNS called by NSD_NAME has authority over.
					*/
						Debug.WriteLine(Debug.Error, "NB redirect not implemented");
						
						fSocket = null;
						return null;
					}
				}
				else
				{
					// NEGATIVE NAME QUERY RESPONSE
					if(Debug.DebugOn && Debug.DebugLevel >= Debug.Error)
						Debug.WriteLine(Debug.Error, "WINS error: " + rcode);					
					fSocket = null;
					return null;
				}
				break;
			}
			fSocket = null;
			return null;
		}
Example #2
0
		/// <summary>
		/// This does a NB Status Request to a given host. 
		/// </summary>
		/// <param name="hostIP">IPAddress of the host to query</param>
		/// <returns>The NetBIOS name, or null if unreachable/non SMB</returns>
		public NbInfo queryStatus(IPAddress hostIP)
		{
			
			fSocket = new UDPCli();
			
			byte[] encodedname = buildSecondLevelEncodedName(NBT_STAT_QNAME, false);

			int trid = nextTRID();

			clearHeader();

			int pos = HDR_NAME_TRN_ID_2;
			setShortAt(pos, fData, trid);

			int opcode;
			int rcode;
			int nmflags = RECURSIVE_DESIRED;
			int flags = (nmflags << NM_FLAGS_SHIFT);

			pos = HDR_FLAGS_2;
			setShortAt(pos, fData, (flags & 0xffff));

			pos = HDR_QDCOUNT_2;
			setShortAt(pos, fData, 1);

			pos = QUESTION_NAME_OFF;
			for(int i=0; i<encodedname.Length; i++)
				fData[pos++] = encodedname[i];

			setShortAt(pos, fData, QUESTION_TYPE_NBSTAT);
			pos += 2;
			setShortAt(pos, fData, QUESTION_CLASS_IN);
			pos += 2;
			
			//byte[] packet = new byte[fData.Length];

			if(Debug.DebugOn && Debug.DebugLevel >= Debug.Buffer)
			{
				Debug.WriteLine(Debug.Buffer, "NBNS name query request:");
				Debug.WriteLine(Debug.Buffer, fData, 0, pos);
			}

			IPEndPoint ip = new IPEndPoint(hostIP, NAME_SERVICE_UDP_PORT);

			int sent = fSocket.Send(fData, pos, ip);
	
			while(true)
			{
				

				bool bSuccess = fSocket.DoReceive(ref ip, ref fData);
				
				if(!bSuccess)
					break;

				if(Debug.DebugOn && Debug.DebugLevel >= Debug.Buffer)
				{
					Debug.WriteLine(Debug.Buffer, "NBNS response:");
					Debug.WriteLine(Debug.Buffer, fData, 0, fData.Length);
				}
								
				if(trid != getShortAt(0, fData))
					continue;


				flags = getShortAt(2, fData);
				rcode = flags & RCODE_MASK;

				if ((flags & RESPONSE_PACKET) == 0)
					break; // not a response
				
				opcode  = ((flags & OPCODE_MASK) >> OPCODE_SHIFT) & 0xf;
				nmflags = ((flags & NM_FLAGS_MASK) >> NM_FLAGS_SHIFT) & 0x7f;

				if (rcode == 0)
				{
			    /*
					 NODE STATUS RESPONSE


					                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
					 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|         NAME_TRN_ID           |1|  0x0  |1|0|0|0|0 0|0|  0x0  |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|          0x0000               |           0x0001              |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|          0x0000               |           0x0000              |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|                                                               |
					/                            RR_NAME                            /
					|                                                               |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|        NBSTAT (0x0021)        |         IN (0x0001)           |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|                          0x00000000                           |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|          RDLENGTH             |   NUM_NAMES   |               |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               +
					|                                                               |
					+                                                               +
					/                         NODE_NAME ARRAY                       /
					+                                                               +
					|                                                               |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|                                                               |
					+                                                               +
					/                           STATISTICS                          /
					+                                                               +
					|                                                               |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

					The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries
					of NODE_NAME records.  Each NODE_NAME entry represents an active
					name in the same NetBIOS scope as the requesting name in the
					local name table of the responder.  RR_NAME is the requesting
					name.

					NODE_NAME Entry:

					                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
					 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|                                                               |
					+---                                                         ---+
					|                                                               |
					+---                    NETBIOS FORMAT NAME                  ---+
					|                                                               |
					+---                                                         ---+
					|                                                               |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
					|         NAME_FLAGS            |
					+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


					*/
	
					// Read machine name;
					string NBTname = Encoding.UTF8.GetString(fData, NBT_STAT_COMP_OFF, 15); // Get the NetBIOS name
					NBTname = NBTname.Trim();	// remove the whitespace

					// Read workgroup/domain
					string NBTgroup = Encoding.UTF8.GetString(fData, NBT_STAT_WORKGRP_OFF1, 15); // Get the NetBIOS group
					NBTgroup = NBTgroup.Trim(); // remove the whitespaces

					if(NBTname == NBTgroup) // Try the alternate location
					{
						NBTgroup = Encoding.UTF8.GetString(fData, NBT_STAT_WORKGRP_OFF2, 15);
						NBTgroup = NBTgroup.Trim();
					}
					
					NbInfo info = new NbInfo();

					info.Name = (string)NBTname.Clone();
					info.Workgroup = (string)NBTgroup.Clone();
					fSocket = null;
					return info;
					

				}
				else
				{
					// NEGATIVE NAME QUERY RESPONSE
					if(Debug.DebugOn && Debug.DebugLevel >= Debug.Error)
						Debug.WriteLine(Debug.Error, "WINS error: " + rcode);					
					fSocket = null;
					return new NbInfo();
				}
			}
			fSocket = null;
			return new NbInfo();
		}