示例#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);
        }
示例#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());
        }