2541 lines
54 KiB
C
2541 lines
54 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
nmsmsgf.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the functions for formatting and unformatting
|
||
the various messages that are sent and/or received from nbt nodes.
|
||
It also contains the function called by the NBT threads to service
|
||
a name request
|
||
|
||
Functions:
|
||
|
||
NmsMsgfProcNbtReq
|
||
GetName
|
||
GetOtherInfo
|
||
NmsMsgfFrmNamRspMsg
|
||
FrmNamRegRsp
|
||
FrmNamRelRsp
|
||
FrmNamQueryRsp
|
||
FormatQueryRspBuff
|
||
FormatName
|
||
NmsMsgfFrmNamQueryReq
|
||
NmsMsgfFrmNamRelReq
|
||
NmsMsgfFrmWACK
|
||
NmsMsgfUfmNamRsp
|
||
|
||
Author:
|
||
|
||
Pradeep Bahl (PradeepB) Dec-1992
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
/*
|
||
Includes
|
||
*/
|
||
|
||
#include "wins.h"
|
||
#include "nms.h"
|
||
#include "nmsdb.h"
|
||
#include "winsevt.h"
|
||
#include "winscnf.h"
|
||
#include "winsmsc.h"
|
||
#include "nmsmsgf.h"
|
||
#include "nmsnmh.h"
|
||
#include "nmschl.h"
|
||
#include "comm.h"
|
||
#include "winsintf.h"
|
||
|
||
|
||
/*
|
||
defines
|
||
*/
|
||
|
||
|
||
#define NAME_HEADER_SIZE 12 /* header size (bytes before the Ques
|
||
* name section of a name packet
|
||
*/
|
||
|
||
#define NAME_FORMAT_MASK 0xC0 /*top two bits of a byte*/
|
||
#define NODE_TYPE_MASK 0x60 /*bit 13 and 14 of NBFLAGs field */
|
||
#define SHIFT_NODE_BITS 5 //shift the node bits in the byte
|
||
//containing them by this amount
|
||
#define LENGTH_MASK 0x3F /*6 LSBs of the top byte of the
|
||
* QuesNamSec field
|
||
*/
|
||
#define GROUP_BIT_MASK 0x80 /*bit 7 of the 1st byte (MSB)of the
|
||
*16 bit NBFLAGS field
|
||
*/
|
||
/*
|
||
* Max length of a Name (including label length octets) in RFC packet
|
||
*/
|
||
#define RFC_MAX_NAM_LEN 255
|
||
|
||
//
|
||
// Max size of internal name as derived from the rfc packet name
|
||
//
|
||
#define MAX_SIZE_INTERNAL_NAME (RFC_MAX_NAM_LEN - 16)
|
||
//This should be = (255 - 16)
|
||
//since the max size of the netbios
|
||
//name (with scope attached) can be
|
||
//be 255. The first 32 bytes
|
||
//are encoded. These map to 16
|
||
//bytes in the internal name
|
||
|
||
|
||
/*
|
||
* Max length of a label in a name
|
||
*/
|
||
#define RFC_MAX_LABEL_LEN 63
|
||
|
||
|
||
/*
|
||
* Sizes of the various fields in the name service packets received or sent
|
||
* by the WINS server. These sizes are specified in RFC 1002
|
||
*/
|
||
#define RFC_LEN_QTYP (2)
|
||
#define RFC_LEN_QCLS (2)
|
||
#define RFC_LEN_TTL (4)
|
||
#define RFC_LEN_RDLEN (2)
|
||
#define RFC_LEN_NBFLAGS (2)
|
||
#define RFC_LEN_NBADD (4)
|
||
#define RFC_LEN_RRTYP (2)
|
||
#define RFC_LEN_RRCLS (2)
|
||
#define RFC_LEN_RRPTR (2)
|
||
|
||
#define RFC_LEN_QTYP_N_QCLS (RFC_LEN_QTYP + RFC_LEN_QCLS) /* page 10 -
|
||
*RFC 1002
|
||
*/
|
||
#define RFC_LEN_RRTYP_N_RRCLS (RFC_LEN_RRTYP + RFC_LEN_RRCLS) /* page 11 -
|
||
*RFC 1002
|
||
*/
|
||
|
||
/*
|
||
* The following is used by FrmNamQueryRsp in its calculation to determine
|
||
* if the name query buffer would be big enough for the response
|
||
*/
|
||
|
||
#define RFC_LEN_TTL_N_RDLEN (RFC_LEN_TTL + RFC_LEN_RDLEN)
|
||
|
||
#define RFC_LEN_RR_N_TTL (RFC_LEN_RRTYP_N_RRCLS + RFC_LEN_TTL)
|
||
|
||
#define RFC_LEN_RR_N_TTL_N_RDLEN_N_NBF (RFC_LEN_RR_N_TTL + \
|
||
RFC_LEN_RDLEN + RFC_LEN_NBFLAGS)
|
||
|
||
|
||
//
|
||
// Length of NBFLAGS and the NB address
|
||
//
|
||
#define RFC_LEN_NBF_N_NBA (RFC_LEN_NBFLAGS + RFC_LEN_NBADD)
|
||
|
||
#define RFC_LEN_RDLEN_N_NBF (RFC_LEN_RDLEN + RFC_LEN_NBFLAGS)
|
||
//
|
||
// Length of the RDLEN, NB flags and NB address section. Page 13 of RFC 1002
|
||
//
|
||
#define RFC_LEN_RDLEN_N_NBF_N_NBA (RFC_LEN_RDLEN + RFC_LEN_NBF_N_NBA)
|
||
/*
|
||
* Size of the TTL, RDLEN, NB Flags and NB address section
|
||
*/
|
||
#define RFC_LEN_TTL_N_RDLEN_N_NBF_N_NBA (RFC_LEN_TTL + RFC_LEN_RDLEN_N_NBF_N_NBA)
|
||
|
||
/*
|
||
The value of the 3rd and 4 th byte of the first long of the response packets
|
||
for the different name requests. The bytes are numbered from the start of
|
||
the pkt.
|
||
|
||
Note: for a negative response the Rcode value (4 LSBs of the 4th byte of the
|
||
message) has to be ORed with the LBFW values
|
||
|
||
*/
|
||
#define RFC_NAM_REG_RSP_OPC (0xAD) /*+ve registration response*/
|
||
#define RFC_NAM_REG_RSP_4THB (0x80) /*4th byte of the above pkt */
|
||
#define RFC_NAM_REL_RSP_OPC (0xB4) /*+ve release response*/
|
||
#define RFC_NAM_REL_RSP_4THB (0x00) /*4th byte of the above pkt*/
|
||
|
||
|
||
#define RFC_NAM_QUERY_RSP_OPC_NO_T (0x85) /*+ve query resp (complete)*/
|
||
#define RFC_NAM_QUERY_RSP_OPC_T (0x87) /*+ve query resp (truncated)*/
|
||
#define RFC_NAM_QUERY_RSP_4THB (0x80) /*4th byte of the above pkt */
|
||
|
||
|
||
/*
|
||
* Values of different fields in RFC response packet
|
||
*/
|
||
|
||
|
||
/*
|
||
QD Count and AN count fields of the Name Reg. Rsp pkt
|
||
*/
|
||
#define RFC_NAM_REG_RSP_QDCNT_1STB (0x00)
|
||
#define RFC_NAM_REG_RSP_QDCNT_2NDB (0x00)
|
||
#define RFC_NAM_REG_RSP_ANCNT_1STB (0x00)
|
||
#define RFC_NAM_REG_RSP_ANCNT_2NDB (0x01)
|
||
|
||
/*
|
||
NS Count and AR count fields of the Name Reg. Rsp pkt
|
||
*/
|
||
|
||
#define RFC_NAM_REG_RSP_NSCNT_1STB (0x00)
|
||
#define RFC_NAM_REG_RSP_NSCNT_2NDB (0x00)
|
||
#define RFC_NAM_REG_RSP_ARCNT_1STB (0x00)
|
||
#define RFC_NAM_REG_RSP_ARCNT_2NDB (0x00)
|
||
|
||
/*
|
||
QD Count and AN count fields of the Name Rel. Rsp pkt
|
||
*/
|
||
#define RFC_NAM_REL_RSP_QDCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_RSP_QDCNT_2NDB (0x00)
|
||
#define RFC_NAM_REL_RSP_ANCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_RSP_ANCNT_2NDB (0x01)
|
||
|
||
/*
|
||
NS Count and AR count fields of the Name Rel. Rsp pkt
|
||
*/
|
||
|
||
#define RFC_NAM_REL_RSP_NSCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_RSP_NSCNT_2NDB (0x00)
|
||
#define RFC_NAM_REL_RSP_ARCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_RSP_ARCNT_2NDB (0x00)
|
||
|
||
/*
|
||
QD Count and AN count fields of the Name Query. Rsp pkt
|
||
*/
|
||
|
||
#define RFC_NAM_QUERY_RSP_QDCNT_1STB (0x00)
|
||
#define RFC_NAM_QUERY_RSP_QDCNT_2NDB (0x00)
|
||
#define RFC_NAM_QUERY_RSP_ANCNT_1STB (0x00)
|
||
|
||
#define RFC_NAM_QUERY_POS_RSP_ANCNT_2NDB (0x01)
|
||
#define RFC_NAM_QUERY_NEG_RSP_ANCNT_2NDB (0x00)
|
||
|
||
/*
|
||
NS Count and AR count fields of the Name Query. Rsp pkt
|
||
*/
|
||
#define RFC_NAM_QUERY_RSP_NSCNT_1STB (0x00)
|
||
#define RFC_NAM_QUERY_RSP_NSCNT_2NDB (0x00)
|
||
#define RFC_NAM_QUERY_RSP_ARCNT_1STB (0x00)
|
||
#define RFC_NAM_QUERY_RSP_ARCNT_2NDB (0x00)
|
||
|
||
|
||
|
||
/*
|
||
* NB and IN fields of the name query response pkt
|
||
* Page 21 and 22 of RFC 1002
|
||
*/
|
||
|
||
/*
|
||
Positive name query response
|
||
*/
|
||
#define RFC_NAM_QUERY_POS_RSP_NB_1STB (0x00)
|
||
#define RFC_NAM_QUERY_POS_RSP_NB_2NDB (0x20)
|
||
#define RFC_NAM_QUERY_POS_RSP_IN_1STB (0x00)
|
||
#define RFC_NAM_QUERY_POS_RSP_IN_2NDB (0x01)
|
||
|
||
/*
|
||
Negative name query response
|
||
*/
|
||
#define RFC_NAM_QUERY_NEG_RSP_NB_1STB (0x00)
|
||
#define RFC_NAM_QUERY_NEG_RSP_NB_2NDB (0x0A)
|
||
#define RFC_NAM_QUERY_NEG_RSP_IN_1STB (0x00)
|
||
#define RFC_NAM_QUERY_NEG_RSP_IN_2NDB (0x01)
|
||
|
||
/*
|
||
name query request opcode byte and 4th byte
|
||
*/
|
||
#define RFC_NAM_QUERY_REQ_OPCB (0x01)
|
||
#define RFC_NAM_QUERY_REQ_4THB (0x0)
|
||
|
||
/*
|
||
name query request QDCOUNT and ANCOUNT bytes
|
||
*/
|
||
#define RFC_NAM_QUERY_REQ_QDCNT_1STB (0x00)
|
||
#define RFC_NAM_QUERY_REQ_QDCNT_2NDB (0x01)
|
||
#define RFC_NAM_QUERY_REQ_ANCNT_1STB (0x00)
|
||
#define RFC_NAM_QUERY_REQ_ANCNT_2NDB (0x00)
|
||
|
||
/*
|
||
name query request NSCOUNT and ARCOUNT bytes
|
||
*/
|
||
#define RFC_NAM_QUERY_REQ_NSCNT_1STB (0x00)
|
||
#define RFC_NAM_QUERY_REQ_NSCNT_2NDB (0x00)
|
||
#define RFC_NAM_QUERY_REQ_ARCNT_1STB (0x00)
|
||
#define RFC_NAM_QUERY_REQ_ARCNT_2NDB (0x00)
|
||
|
||
/*
|
||
name query request QTYP and QCLS bytes
|
||
*/
|
||
#define RFC_NAM_QUERY_REQ_QTYP_1STB (0x00)
|
||
#define RFC_NAM_QUERY_REQ_QTYP_2NDB (0x20)
|
||
#define RFC_NAM_QUERY_REQ_QCLS_1STB (0x00)
|
||
#define RFC_NAM_QUERY_REQ_QCLS_2NDB (0x01)
|
||
|
||
/*
|
||
name release request opcode byte and 4th byte
|
||
*/
|
||
#define RFC_NAM_REL_REQ_OPCB (0x30)
|
||
#define RFC_NAM_REL_REQ_4THB (0x00)
|
||
|
||
/*
|
||
name release request QDCOUNT and ANCOUNT bytes
|
||
*/
|
||
#define RFC_NAM_REL_REQ_QDCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_QDCNT_2NDB (0x01)
|
||
#define RFC_NAM_REL_REQ_ANCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_ANCNT_2NDB (0x00)
|
||
|
||
/*
|
||
name release request NSCOUNT and ARCOUNT bytes
|
||
*/
|
||
#define RFC_NAM_REL_REQ_NSCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_NSCNT_2NDB (0x00)
|
||
#define RFC_NAM_REL_REQ_ARCNT_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_ARCNT_2NDB (0x01)
|
||
|
||
/*
|
||
name release request QTYP and QCLS bytes
|
||
*/
|
||
#define RFC_NAM_REL_REQ_QTYP_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_QTYP_2NDB (0x20)
|
||
#define RFC_NAM_REL_REQ_QCLS_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_QCLS_2NDB (0x01)
|
||
/*
|
||
name Release request RRTYP and RRCLS bytes
|
||
*/
|
||
#define RFC_NAM_REL_REQ_RRTYP_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_RRTYP_2NDB (0x20)
|
||
#define RFC_NAM_REL_REQ_RRCLS_1STB (0x00)
|
||
#define RFC_NAM_REL_REQ_RRCLS_2NDB (0x01)
|
||
|
||
/*
|
||
WACK opcode byte and 4th byte
|
||
*/
|
||
#define RFC_WACK_OPCB (0xBC)
|
||
#define RFC_WACK_4THB (0x0)
|
||
|
||
/*
|
||
WACK QDCOUNT and ANCOUNT bytes
|
||
*/
|
||
#define RFC_WACK_QDCNT_1STB (0x0)
|
||
#define RFC_WACK_QDCNT_2NDB (0x0)
|
||
#define RFC_WACK_ANCNT_1STB (0x0)
|
||
#define RFC_WACK_ANCNT_2NDB (0x1)
|
||
|
||
/*
|
||
WACK NSCOUNT and ARCOUNT bytes
|
||
*/
|
||
#define RFC_WACK_NSCNT_1STB (0x0)
|
||
#define RFC_WACK_NSCNT_2NDB (0x0)
|
||
#define RFC_WACK_ARCNT_1STB (0x0)
|
||
#define RFC_WACK_ARCNT_2NDB (0x0)
|
||
/*
|
||
WACK RRTYP and RRCLS bytes
|
||
*/
|
||
#define RFC_WACK_RRTYP_1STB (0x00)
|
||
#define RFC_WACK_RRTYP_2NDB (0x20)
|
||
#define RFC_WACK_RRCLS_1STB (0x00)
|
||
#define RFC_WACK_RRCLS_2NDB (0x01)
|
||
|
||
// WACK RDLENGTH Field
|
||
|
||
#define RFC_WACK_RDLENGTH_1STB (0x0)
|
||
#define RFC_WACK_RDLENGTH_2NDB (0x02)
|
||
|
||
/*
|
||
Local variable declarations
|
||
*/
|
||
|
||
|
||
/*
|
||
Local function declarations
|
||
*/
|
||
/*
|
||
*GetName -- Extract name out of packet
|
||
*/
|
||
STATIC
|
||
VOID
|
||
GetName(
|
||
IN OUT LPBYTE *ppName,
|
||
IN OUT LPBYTE pName,
|
||
OUT LPDWORD pNameLen
|
||
);
|
||
/*
|
||
* Format Name - Format (encode) name for placing in RFC packet
|
||
*/
|
||
STATIC
|
||
VOID
|
||
FormatName(
|
||
IN LPBYTE pNameToFormat,
|
||
IN DWORD LengthOfName,
|
||
IN OUT LPBYTE *ppFormattedName
|
||
);
|
||
/*
|
||
* GetOtherInfo -- Get information (excluding the name) from the pkt
|
||
*/
|
||
STATIC
|
||
STATUS
|
||
GetOtherInfo(
|
||
IN NMSMSGF_NAM_REQ_TYP_E Opcode_e,
|
||
IN LPBYTE pRR, /*point to the RR_NAME section in the
|
||
*name registration packet
|
||
*/
|
||
IN INT QuesNamSecLen, //Size of Ques name section
|
||
OUT LPBOOL pfGrp, //Flag -- unique/group entry
|
||
OUT PNMSMSGF_CNT_ADD_T pCntAdd, //Address
|
||
OUT PNMSMSGF_NODE_TYP_E pNodeTyp_e //Node Type if unique
|
||
);
|
||
|
||
/*
|
||
* FrmNamRegRsp - Format name registration response
|
||
*/
|
||
STATIC
|
||
STATUS
|
||
FrmNamRegRsp(
|
||
PCOMM_HDL_T pDlgHdl,
|
||
PNMSMSGF_RSP_INFO_T pRspInfo
|
||
);
|
||
|
||
|
||
/*
|
||
* FrmNamRelRsp - Format name release response
|
||
*/
|
||
STATIC
|
||
STATUS
|
||
FrmNamRelRsp(
|
||
PCOMM_HDL_T pDlgHdl,
|
||
PNMSMSGF_RSP_INFO_T pRspInfo
|
||
);
|
||
|
||
#if 0
|
||
/*
|
||
* FrmNamQueryRsp - Format name query response
|
||
*/
|
||
STATIC
|
||
STATUS
|
||
FrmNamQueryRsp(
|
||
IN PCOMM_HDL_T pDlgHdl,
|
||
PNMSMSGF_RSP_INFO_T pRspInfo
|
||
);
|
||
#endif
|
||
|
||
/*
|
||
* FormatQueryRspBuff - Format name query response buffer
|
||
*/
|
||
STATIC
|
||
STATUS
|
||
FormatQueryRspBuff(
|
||
IN LPBYTE pDest,
|
||
IN LPBYTE pSrc,
|
||
IN PNMSMSGF_RSP_INFO_T pRspInfo,
|
||
IN BOOL fTrunc
|
||
);
|
||
|
||
|
||
|
||
/*
|
||
function definitions
|
||
*/
|
||
|
||
STATUS
|
||
NmsMsgfProcNbtReq(
|
||
PCOMM_HDL_T pDlgHdl,
|
||
MSG_T pMsg,
|
||
MSG_LEN_T MsgLen
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called by an nbt request thread after it dequeues an nbt
|
||
request message from the work-queue. The function unformats the message
|
||
and then calls the appropriate function to process it.
|
||
|
||
|
||
Arguments:
|
||
pDlgHdl - Dlg Handle
|
||
pMsg - Message Buffer (contains that RFC packet containing
|
||
the request received from an NBT node)
|
||
MsgLen - Length of above buffer
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
|
||
NbtThdInitFn() in nms.c
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Success status codes -- WINS_SUCCESS
|
||
Error status codes -- WINS_FAILURE
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NMSMSGF_NAM_REQ_TYP_E Opcode;
|
||
BYTE Name[NMSDB_MAX_NAM_LEN];
|
||
DWORD NameLen; /*length of name */
|
||
DWORD QuesNamSecLen; /*length of question
|
||
*name section in
|
||
*packet
|
||
*/
|
||
NMSMSGF_NODE_TYP_E NodeTyp_e = NMSMSGF_E_PNODE;
|
||
// BOOL fRefresh;
|
||
|
||
NMSMSGF_CNT_ADD_T CntAdd;
|
||
COMM_ADD_T Address;
|
||
BOOL fGrp; /*flag indicating whether the name
|
||
*is a Unique/Group Netbios name.
|
||
*fGrp is TRUE if the name is a
|
||
*group name, else it is FALSE
|
||
*/
|
||
BOOL fBuffFreed = FALSE; //indicates whether buffer has
|
||
//been freed or not
|
||
|
||
LPBYTE pTmp = (LPBYTE)pMsg;
|
||
LPBYTE pTmp2;
|
||
|
||
DBGENTER("NmsMsgfProcNbtReq\n");
|
||
|
||
try {
|
||
// get the opcode
|
||
Opcode = (NMS_OPCODE_MASK & *(pTmp + 2)) >> 3;
|
||
|
||
#ifdef JIM
|
||
{
|
||
BYTE TransId = *pTmp;
|
||
ASSERT(TransId == 0x80);
|
||
}
|
||
#endif
|
||
|
||
/*
|
||
* make pTmp point to the Question Section. All name request
|
||
* packets have a name header of standard size (RFC 1002) at the top
|
||
*/
|
||
pTmp += NAME_HEADER_SIZE;
|
||
|
||
/*
|
||
* Extract the name ind store in Name. GetName will update pTmp to
|
||
* point just beyond the name in the question section
|
||
*/
|
||
pTmp2 = pTmp; /*save pTmp so that when GetName returns we can
|
||
* determine the length of the question name section
|
||
*/
|
||
|
||
GetName(
|
||
&pTmp,
|
||
Name,
|
||
&NameLen
|
||
);
|
||
|
||
QuesNamSecLen = (ULONG) (pTmp - pTmp2);
|
||
|
||
pTmp += RFC_LEN_QTYP_N_QCLS; /* skip past the ques. type and ques.
|
||
* class fields We don't need to examine
|
||
* these. The question type field
|
||
* will always be NB and question class
|
||
*field will always be INTERNET
|
||
*/
|
||
#ifdef TESTWITHUB
|
||
//
|
||
// Check if the broadcast bit is set. If yes, drop the pkt.
|
||
//
|
||
if (*(pMsg + 3) & 0x10)
|
||
{
|
||
DBGPRINT2(SPEC, "Broadcast pkt BEING DROPPED; name is (%s). Opcode is (%d)\n", Name, Opcode);
|
||
#if 0
|
||
printf("Broadcast pkt BEING DROPPED; name is (%s). Opcode is (%d)\n", Name, Opcode);
|
||
#endif
|
||
ECommFreeBuff(pMsg);
|
||
ECommEndDlg(pDlgHdl);
|
||
return(WINS_SUCCESS);
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Let us set the flag to TRUE. If any of the following called
|
||
// functions raises an exception, then it is a requirement that
|
||
// it does so only after freeing the buffer (i.e. it must catch
|
||
// all exceptions, free the buffer and then reraise the
|
||
// exception - if it wants)
|
||
//
|
||
fBuffFreed = TRUE;
|
||
|
||
//
|
||
// If the 16th character is a 1B switch it with the 1st character.
|
||
// This is done to support Browsing. Browsers want a list of all
|
||
// names with 16th character being 1B. Putting 1B as the
|
||
// 1st character enables WINS to find all 1B names quickly.
|
||
//
|
||
NMSMSGF_MODIFY_NAME_IF_REQD_M(Name);
|
||
|
||
/*
|
||
* Switch on the type of request as determined by the Opcode
|
||
*/
|
||
switch(Opcode)
|
||
{
|
||
|
||
/*
|
||
name registration and refresh are handled the same way
|
||
*/
|
||
case(NMSMSGF_E_NAM_REF):
|
||
case(NMSMSGF_E_NAM_REF_UB):
|
||
DBGPRINT0(FLOW, "It is a name refresh request\n");
|
||
|
||
case(NMSMSGF_E_NAM_REG): /* fall through */
|
||
case(NMSMSGF_E_MULTIH_REG): /* fall through */
|
||
|
||
/*
|
||
* Get the flag indicating whether the request is a group
|
||
* registration or a unique name registration. The IP
|
||
* address(es) is (are) also retrieved
|
||
*/
|
||
GetOtherInfo(
|
||
Opcode,
|
||
pTmp,
|
||
QuesNamSecLen,
|
||
&fGrp,
|
||
&CntAdd,
|
||
&NodeTyp_e
|
||
);
|
||
//
|
||
// If it is not a group or a multihomed registration or
|
||
//
|
||
if (!fGrp && (Opcode != NMSMSGF_E_MULTIH_REG))
|
||
{
|
||
/*
|
||
* Register the unique name
|
||
*/
|
||
NmsNmhNamRegInd(
|
||
pDlgHdl,
|
||
Name,
|
||
NameLen,
|
||
CntAdd.Add,
|
||
(BYTE)NodeTyp_e,
|
||
pMsg,
|
||
MsgLen,
|
||
QuesNamSecLen,
|
||
Opcode == NMSMSGF_E_NAM_REG ? FALSE : TRUE,
|
||
NMSDB_ENTRY_IS_NOT_STATIC,
|
||
FALSE //is it admin flag ?
|
||
);
|
||
}
|
||
else //it is a group or is mutihomed
|
||
{
|
||
/*
|
||
* Register the group name
|
||
*/
|
||
NmsNmhNamRegGrp(
|
||
pDlgHdl,
|
||
Name,
|
||
NameLen,
|
||
&CntAdd,
|
||
(BYTE)NodeTyp_e,
|
||
pMsg,
|
||
MsgLen,
|
||
QuesNamSecLen,
|
||
fGrp ? NMSDB_NORM_GRP_ENTRY : (Opcode == NMSMSGF_E_MULTIH_REG) ? NMSDB_MULTIHOMED_ENTRY : NMSDB_NORM_GRP_ENTRY,
|
||
//passing NMSDB_NORM_GRP_ENTRY for spec. grp is fine
|
||
//see NmsNmhNamRegGrp()
|
||
Opcode == NMSMSGF_E_NAM_REG ? FALSE : TRUE,
|
||
NMSDB_ENTRY_IS_NOT_STATIC,
|
||
FALSE //is it admin ?
|
||
);
|
||
}
|
||
|
||
break;
|
||
|
||
case(NMSMSGF_E_NAM_QUERY):
|
||
|
||
#if 0
|
||
Address.AddTyp_e = COMM_ADD_E_TCPUDPIP;
|
||
Address.AddLen = sizeof(COMM_IP_ADD_T);
|
||
COMM_GET_IPADD_M(pDlgHdl, &Address.Add.IPAdd);
|
||
#endif
|
||
|
||
#if 0
|
||
//
|
||
// NOTE: Multiple NBT threads could be doing this simultaneously
|
||
//
|
||
// This is the best I can do without a critical section
|
||
//
|
||
FUTURES("The count may not be correct when retrieved by an RPC thread")
|
||
WinsIntfStat.Counters.NoOfQueries++;
|
||
#endif
|
||
/*
|
||
Query the name
|
||
*/
|
||
NmsNmhNamQuery(
|
||
pDlgHdl,
|
||
Name,
|
||
NameLen,
|
||
pMsg,
|
||
MsgLen,
|
||
QuesNamSecLen,
|
||
FALSE, // is it admin flag
|
||
NULL //should be non NULL only in
|
||
//an RPC thread
|
||
);
|
||
break;
|
||
|
||
|
||
case(NMSMSGF_E_NAM_REL):
|
||
|
||
GetOtherInfo(
|
||
NMSMSGF_E_NAM_REL,
|
||
pTmp,
|
||
QuesNamSecLen,
|
||
&fGrp,
|
||
&CntAdd,
|
||
&NodeTyp_e
|
||
);
|
||
|
||
|
||
//
|
||
// We should pass down to NmsNmhNamRel function the
|
||
// address of the client requesting name release, not
|
||
// the address passed in the RFC pkt. The address
|
||
// will be used by NmsDbRelRow to check if the client
|
||
// is authorized to release the record
|
||
//
|
||
Address.AddTyp_e = COMM_ADD_E_TCPUDPIP;
|
||
Address.AddLen = sizeof(COMM_IP_ADD_T);
|
||
COMM_GET_IPADD_M(pDlgHdl, &Address.Add.IPAdd);
|
||
|
||
/*
|
||
* Release the name
|
||
*/
|
||
NmsNmhNamRel(
|
||
pDlgHdl,
|
||
Name,
|
||
NameLen,
|
||
&Address,
|
||
fGrp,
|
||
pMsg,
|
||
MsgLen,
|
||
QuesNamSecLen,
|
||
FALSE //is it admin flag ?
|
||
);
|
||
break;
|
||
|
||
default:
|
||
|
||
fBuffFreed = FALSE;
|
||
DBGPRINT1(EXC, "NmsMsgfProcNbtReq: Invalid Opcode\n", Opcode);
|
||
WINS_RAISE_EXC_M(WINS_EXC_PKT_FORMAT_ERR);
|
||
WINSEVT_LOG_M(Opcode, WINS_EVT_INVALID_OPCODE);
|
||
|
||
break;
|
||
}
|
||
|
||
}
|
||
except(EXCEPTION_EXECUTE_HANDLER) {
|
||
DBGPRINTEXC("NmsMsgfProcNbtReq");
|
||
|
||
if (GetExceptionCode() == WINS_EXC_NBT_ERR)
|
||
{
|
||
WINS_RERAISE_EXC_M();
|
||
}
|
||
|
||
//
|
||
// Free the message buffer if not already freed, delete the
|
||
// dialogue if it is a UDP dialogue.
|
||
//
|
||
if (!fBuffFreed)
|
||
{
|
||
ECommFreeBuff(pMsg);
|
||
ECommEndDlg(pDlgHdl);
|
||
}
|
||
}
|
||
|
||
|
||
DBGLEAVE("NmsMsgfProcNbtReq\n");
|
||
return(WINS_SUCCESS);
|
||
}
|
||
|
||
|
||
VOID
|
||
GetName(
|
||
IN OUT LPBYTE *ppName,
|
||
IN OUT LPBYTE pName,
|
||
OUT LPDWORD pNameLen
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called to retrieve the name from the name
|
||
request packet.
|
||
|
||
Arguments:
|
||
|
||
ppName -- address of ptr to question section in datagram received
|
||
pName -- Address of array to hold the name. It is assumed that this is
|
||
atleast NMSMSGF_RFC_MAX_NAM_LEN long.
|
||
pNameLen -- address of variable to hold length of name
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
NmsNmhProcNbtReq
|
||
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
None
|
||
--*/
|
||
|
||
{
|
||
|
||
INT HighTwoBits; //First two bits of Question Name section
|
||
INT Length; //length of label in Question Name section
|
||
BYTE ch;
|
||
LPBYTE pNmInPkt = *ppName;
|
||
INT inLen = NMSMSGF_RFC_MAX_NAM_LEN; // Store the length of the name.
|
||
|
||
|
||
*pNameLen = 0;
|
||
|
||
/*
|
||
Get the high two bits of the first byte of the Question_NAME
|
||
section. The bits have to be 00. If they are not, something
|
||
is really wrong.
|
||
*/
|
||
|
||
if ((HighTwoBits = (NAME_FORMAT_MASK & *pNmInPkt)) != 0)
|
||
{
|
||
goto BadFormat;
|
||
}
|
||
|
||
/*
|
||
* Get the length of the label. Length, extracted this way, is
|
||
* guranteed to be <= 63.
|
||
*/
|
||
Length = LENGTH_MASK & *pNmInPkt;
|
||
|
||
|
||
pNmInPkt++; //increment past the length byte
|
||
|
||
|
||
/*
|
||
* Decode the first label of the name (the netbios name without the
|
||
* scope).
|
||
*/
|
||
|
||
while(Length > 0 )
|
||
{
|
||
ch = *pNmInPkt++ - 'A';
|
||
*pName++ = (ch << 4) | (*pNmInPkt++ - 'A');
|
||
(*pNameLen)++;
|
||
Length -= 2;
|
||
}
|
||
|
||
inLen -= Length;
|
||
|
||
/*
|
||
Extract the netbios scope if present
|
||
The netbios scope is not in encoded form
|
||
*/
|
||
while(TRUE)
|
||
{
|
||
/*
|
||
* if length byte is not 0, there is a netbios scope.
|
||
* We make sure that if the packet is ill-formed (i.e. the
|
||
* length of the name (including the length bytes) is > 255, we raise
|
||
* an exception. Since *pNameLen is counting the number of bytes
|
||
* in the name that we are forming, we need to compare it with
|
||
* (255 - 16) = 239 since the first 32 bytes of the netbios name
|
||
* map to 16 bytes of our internal name.
|
||
*/
|
||
if (*pNmInPkt != 0)
|
||
{
|
||
if (*pNameLen > MAX_SIZE_INTERNAL_NAME)
|
||
{
|
||
goto BadFormat;
|
||
}
|
||
|
||
if ( --inLen <= 0) {
|
||
goto BadFormat;
|
||
}
|
||
*pName++ = '.';
|
||
(*pNameLen)++;
|
||
Length = LENGTH_MASK & *pNmInPkt;
|
||
|
||
// check that the we have enough space remaining in the input buffer.
|
||
//
|
||
if ( (inLen -= Length) <= 0 ) {
|
||
goto BadFormat;
|
||
}
|
||
|
||
++pNmInPkt; //increment past length byte
|
||
|
||
while(Length-- != 0)
|
||
{
|
||
*pName++ = *pNmInPkt++;
|
||
(*pNameLen)++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
++pNmInPkt; //increment past end byte (00)
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (--inLen >= 0) {
|
||
*pName++ = 0; /* EOS */
|
||
} else {
|
||
goto BadFormat;
|
||
}
|
||
|
||
(*pNameLen)++; //include 0 in the name's length so that it is stored
|
||
//in the db. Check out FormatName too since it expects
|
||
//the length to include this 0
|
||
|
||
*ppName = pNmInPkt; //init the ppName ptr to point just past the name
|
||
|
||
return;
|
||
|
||
BadFormat:
|
||
// log error and raise an exception
|
||
WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_PKT_FORMAT_ERR);
|
||
WINS_RAISE_EXC_M(WINS_EXC_PKT_FORMAT_ERR);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
|
||
STATUS
|
||
GetOtherInfo(
|
||
NMSMSGF_NAM_REQ_TYP_E Opcode_e,
|
||
IN LPBYTE pRR, /*point to the RR_NAME section in the
|
||
*name registration packet
|
||
*/
|
||
IN INT QuesNamSecLen, /*size of Ques name section*/
|
||
OUT LPBOOL pfGrp, /*flag -- unique/group entry */
|
||
OUT PNMSMSGF_CNT_ADD_T pCntAdd, /*Counted address array*/
|
||
OUT PNMSMSGF_NODE_TYP_E pNodeTyp_e
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
The function is called to retrieve information other than the
|
||
the name from the pkt
|
||
|
||
Arguments:
|
||
pRR - address of RR_NAME section in the request packet
|
||
QuesNamSecLen - length of the question names section in the request pkt
|
||
pfGrp - TRUE if it is a group registration request
|
||
pAddress - Address contained in the request
|
||
NodeTyp_e - Type of node doing the registeration (P, B, M)
|
||
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
NmsMsgfProcNbtReq
|
||
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Success status codes -- WINS_SUCCESS
|
||
Error status codes -- WINS_FAILURE
|
||
|
||
--*/
|
||
|
||
{
|
||
INT HighTwoBits;
|
||
BYTE *pTmp = pRR;
|
||
LONG UNALIGNED *pTmpL;
|
||
|
||
|
||
/*
|
||
* RR_NAME section should contain a pointer to the Question Section. So
|
||
* we could skip it. We are not, however, just in case another
|
||
* implementation of NBT does not follow the recommendations of the
|
||
* RFC and passes us the full name in RR_NAME section
|
||
*/
|
||
if ((HighTwoBits = NAME_FORMAT_MASK & *pTmp) == 0)
|
||
{
|
||
|
||
/*
|
||
* skip the name (same size as in question_name section) and the
|
||
* RR_TYPE, RR_CLASS, TTL and RDLENGTH fields
|
||
*/
|
||
pTmp += QuesNamSecLen + RFC_LEN_RRTYP_N_RRCLS +
|
||
RFC_LEN_TTL + RFC_LEN_RDLEN;
|
||
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* skip the pointer bytes (2), RR_TYPE, RR_CLASS, TTL, and
|
||
* RDLENGTH flds
|
||
*/
|
||
pTmp += RFC_LEN_RRPTR + RFC_LEN_RRTYP_N_RRCLS + RFC_LEN_TTL
|
||
+ RFC_LEN_RDLEN;
|
||
}
|
||
|
||
|
||
/*
|
||
* RFC 1002 - page 12 and 14.
|
||
*
|
||
* First 16 buts of the RData section (right after the RDLEN section
|
||
* has its top most bit set to 0 if the registration is for a group
|
||
*/
|
||
*pfGrp = GROUP_BIT_MASK & *pTmp; // get the group bit
|
||
|
||
/*
|
||
*Next two MS bits indicate the node type
|
||
*/
|
||
*pNodeTyp_e = (NODE_TYPE_MASK & *pTmp) >> SHIFT_NODE_BITS;
|
||
|
||
/*
|
||
* Get the IP address. IP address is 2 bytes away,
|
||
*/
|
||
pTmp += 2;
|
||
|
||
NONPORT("Port when porting to NON TCP/IP protocols")
|
||
|
||
pCntAdd->NoOfAdds = 1;
|
||
|
||
/*
|
||
* Use ntohl to get the address which is a long in the correct
|
||
* byte order
|
||
*/
|
||
pTmpL = (LPLONG)pTmp;
|
||
pCntAdd->Add[0].Add.IPAdd = ntohl(*pTmpL);
|
||
pCntAdd->Add[0].AddTyp_e = COMM_ADD_E_TCPUDPIP;
|
||
pCntAdd->Add[0].AddLen = sizeof(COMM_IP_ADD_T);
|
||
|
||
if (Opcode_e == NMSMSGF_E_MULTIH_REG)
|
||
{
|
||
USHORT RdLen;
|
||
USHORT NoOfAddsLeft;
|
||
|
||
//
|
||
// We are going to register a group of addresses
|
||
//
|
||
|
||
//
|
||
// Extract the RDLEN (decrement the pointer)
|
||
//
|
||
RdLen = (USHORT)((*(pTmp - RFC_LEN_RDLEN_N_NBF) << 8) +
|
||
*(pTmp - RFC_LEN_RDLEN_N_NBF + 1));
|
||
|
||
NoOfAddsLeft = ((RdLen - RFC_LEN_NBFLAGS)/COMM_IP_ADD_SIZE) - 1;
|
||
if (NoOfAddsLeft >= NMSMSGF_MAX_NO_MULTIH_ADDS)
|
||
{
|
||
DBGPRINT0(FLOW, "The packet for multi-homed registration has more than the max. number of ip addresses supported for a multi-homed client. \n");
|
||
|
||
WINSEVT_LOG_M(
|
||
NoOfAddsLeft,
|
||
WINS_EVT_LIMIT_MULTIH_ADD_REACHED
|
||
);
|
||
NoOfAddsLeft = NMSMSGF_MAX_NO_MULTIH_ADDS - 1;
|
||
}
|
||
|
||
//
|
||
// Get the remaining addresses
|
||
//
|
||
pTmp += RFC_LEN_NBADD;
|
||
for(
|
||
; //null first expr
|
||
pCntAdd->NoOfAdds < (DWORD)(NoOfAddsLeft + 1);
|
||
pTmp += RFC_LEN_NBADD, pCntAdd->NoOfAdds++
|
||
)
|
||
{
|
||
|
||
pCntAdd->Add[pCntAdd->NoOfAdds].Add.IPAdd =
|
||
ntohl(*((LPLONG)pTmp));
|
||
pCntAdd->Add[pCntAdd->NoOfAdds].AddTyp_e =
|
||
COMM_ADD_E_TCPUDPIP;
|
||
pCntAdd->Add[pCntAdd->NoOfAdds].AddLen =
|
||
sizeof(COMM_IP_ADD_T);
|
||
}
|
||
}
|
||
|
||
return(WINS_SUCCESS);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
STATUS
|
||
NmsMsgfFrmNamRspMsg(
|
||
PCOMM_HDL_T pDlgHdl,
|
||
NMSMSGF_NAM_REQ_TYP_E NamRspTyp_e,
|
||
PNMSMSGF_RSP_INFO_T pRspInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This function is called to format a response message for sending
|
||
to an nbt node.
|
||
|
||
Arguments:
|
||
pDlgHdl -- Dlg Handle
|
||
NameRspTye_e -- Type of response message (registration, query, release)
|
||
that needs to be formatted.
|
||
pRspInfo -- Response Info.
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
NmsNmhNamRegInd, NmsNmhNamRegGrp, NmsNmhNamRel, NmsNmhNamQuery
|
||
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
Success status codes -- WINS_SUCCESS
|
||
Error status codes -- WINS_FAILURE
|
||
|
||
--*/
|
||
|
||
{
|
||
STATUS RetStat = WINS_SUCCESS;
|
||
LPBYTE pReqBuff = pRspInfo->pMsg;
|
||
LPBYTE pNewBuff = pReqBuff;
|
||
|
||
//
|
||
// Switch on type of response
|
||
//
|
||
switch(NamRspTyp_e)
|
||
{
|
||
case(NMSMSGF_E_NAM_REG): /* fall through */
|
||
case(NMSMSGF_E_NAM_REF):
|
||
case(NMSMSGF_E_NAM_REF_UB):
|
||
|
||
(VOID)FrmNamRegRsp(
|
||
pDlgHdl,
|
||
pRspInfo
|
||
);
|
||
break;
|
||
|
||
case(NMSMSGF_E_NAM_QUERY):
|
||
|
||
#if 0
|
||
FrmNamQueryRsp(
|
||
pDlgHdl,
|
||
pRspInfo
|
||
);
|
||
#endif
|
||
(VOID)FormatQueryRspBuff(
|
||
pNewBuff, //ptr to buffer to fill
|
||
pReqBuff, // ptr to req buffer
|
||
pRspInfo,
|
||
FALSE //no danger of truncation since
|
||
//we never send more than 25 ip add
|
||
//in the response
|
||
);
|
||
|
||
break;
|
||
|
||
case(NMSMSGF_E_NAM_REL):
|
||
|
||
(VOID)FrmNamRelRsp(
|
||
pDlgHdl,
|
||
pRspInfo
|
||
);
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
// error
|
||
RetStat = WINS_FAILURE;
|
||
break;
|
||
}
|
||
|
||
return(RetStat);
|
||
}
|
||
|
||
|
||
STATUS
|
||
FrmNamRegRsp(
|
||
PCOMM_HDL_T pDlgHdl,
|
||
PNMSMSGF_RSP_INFO_T pRspInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This function formats a positive or a negative name registration
|
||
response.
|
||
|
||
Arguments:
|
||
|
||
pDlgHdl -- Dialogue Handle
|
||
pRspInfo -- Information used to format the response pkt
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
NmsMsgfFrmNamRspMsg
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Success status codes --
|
||
Error status codes --
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
LPBYTE pTmpB = pRspInfo->pMsg + 2;
|
||
BYTE SavedByte;
|
||
|
||
|
||
/*
|
||
We will use the same buffer that carried the request. Simple
|
||
moves will be done. These should be faster than doing
|
||
all the construction from scratch
|
||
*/
|
||
|
||
|
||
/*
|
||
Set the the Transaction Id, Opcode, NMFlags and Rcode field
|
||
*/
|
||
*pTmpB++ = RFC_NAM_REG_RSP_OPC;
|
||
*pTmpB++ = RFC_NAM_REG_RSP_4THB + pRspInfo->Rcode_e;
|
||
|
||
|
||
/*
|
||
Set the QD count and the AN count fields
|
||
*/
|
||
*pTmpB++ = RFC_NAM_REG_RSP_QDCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REG_RSP_QDCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_REG_RSP_ANCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REG_RSP_ANCNT_2NDB;
|
||
|
||
/*
|
||
Set the NSCOUNT and ARCOUNT fields
|
||
*/
|
||
*pTmpB++ = RFC_NAM_REG_RSP_NSCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REG_RSP_NSCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_REG_RSP_ARCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REG_RSP_ARCNT_2NDB;
|
||
|
||
/*
|
||
Increment the pointer past the Question_Class Section
|
||
RR_NAME, RR_TYPE, and RR_CLASS of response are same as
|
||
Question_Name, Question_Type, and Question_Class of
|
||
nbt request.
|
||
*/
|
||
|
||
pTmpB += pRspInfo->QuesNamSecLen + RFC_LEN_QTYP_N_QCLS;
|
||
|
||
SavedByte = *pTmpB & NAME_FORMAT_MASK; //save the format bits of RR section
|
||
|
||
CHECK("In case of a negative response, does it matter what I put in the TTL")
|
||
CHECK("field. It shouldn't matter -- RFC is silent about this")
|
||
//
|
||
// put the TTL in the response
|
||
//
|
||
*pTmpB++ = (BYTE)(pRspInfo->RefreshInterval >> 24);
|
||
*pTmpB++ = (BYTE)((pRspInfo->RefreshInterval >> 16) & 0xFF);
|
||
*pTmpB++ = (BYTE)((pRspInfo->RefreshInterval >> 8) & 0xFF);
|
||
*pTmpB++ = (BYTE)(pRspInfo->RefreshInterval & 0xFF);
|
||
|
||
/*
|
||
Move memory that is after RR_NAME into appropriate place
|
||
|
||
First we check what form the name in the RR_NAME section is.
|
||
It should be in pointer form (pointer to the QuesNamSec) but
|
||
could be in the regular form.
|
||
*/
|
||
|
||
if (SavedByte == 0)
|
||
{
|
||
DWORD RRSecLen = pRspInfo->QuesNamSecLen + RFC_LEN_QTYP_N_QCLS;
|
||
|
||
// RR_NAME is as big as the Question_name section.
|
||
WINSMSC_MOVE_MEMORY_M(
|
||
pTmpB,
|
||
pTmpB + RRSecLen,
|
||
RFC_LEN_RDLEN_N_NBF_N_NBA
|
||
);
|
||
|
||
}
|
||
else
|
||
{
|
||
// RR_NAME is a ptr so it takes up 2 bytes.
|
||
WINSMSC_MOVE_MEMORY_M(
|
||
pTmpB,
|
||
pTmpB + RFC_LEN_RRPTR + RFC_LEN_RRTYP_N_RRCLS,
|
||
RFC_LEN_RDLEN_N_NBF_N_NBA
|
||
);
|
||
}
|
||
|
||
pTmpB += RFC_LEN_RDLEN_N_NBF_N_NBA;
|
||
pRspInfo->MsgLen = (ULONG) (pTmpB - (LPBYTE)pRspInfo->pMsg);
|
||
|
||
return(WINS_SUCCESS);
|
||
}
|
||
|
||
|
||
|
||
STATUS
|
||
FrmNamRelRsp(
|
||
PCOMM_HDL_T pDlgHdl,
|
||
PNMSMSGF_RSP_INFO_T pRspInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function formats a positive or negative name query response.
|
||
The request buffer is made use of for the response.
|
||
|
||
Arguments:
|
||
|
||
pDlgHdl -- Dialogue Handle
|
||
pRspInfo -- Response Info
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
NmsMsgfFrmRspMsg()
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Success status codes --
|
||
Error status codes --
|
||
|
||
--*/
|
||
|
||
{
|
||
LPBYTE pTmpB = pRspInfo->pMsg + 2;
|
||
//LPBYTE pTmpB2;
|
||
|
||
|
||
/*
|
||
We will use the same buffer that carried the request. Simple
|
||
moves will be done. These should be faster than doing
|
||
all the construction from scratch
|
||
*/
|
||
|
||
/*
|
||
Set the the Transaction Id, Opcode, NMFlags and Rcode field
|
||
*/
|
||
*pTmpB++ = RFC_NAM_REL_RSP_OPC;
|
||
*pTmpB++ = RFC_NAM_REL_RSP_4THB + pRspInfo->Rcode_e;
|
||
|
||
|
||
/*
|
||
Set the QD count and the AN count fields
|
||
*/
|
||
*pTmpB++ = RFC_NAM_REL_RSP_QDCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_RSP_QDCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_REL_RSP_ANCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_RSP_ANCNT_2NDB;
|
||
|
||
/*
|
||
Set the NSCOUNT and ARCOUNT fields
|
||
*/
|
||
*pTmpB++ = RFC_NAM_REL_RSP_NSCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_RSP_NSCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_REL_RSP_ARCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_RSP_ARCNT_2NDB;
|
||
|
||
|
||
/*
|
||
Increment the pointer past the Question_Class Section
|
||
RR_NAME, RR_TYPE, and RR_CLASS of response are same as
|
||
Question_Name, Question_Type, and Question_Class of
|
||
nbt request.
|
||
*/
|
||
pTmpB += pRspInfo->QuesNamSecLen + RFC_LEN_QTYP_N_QCLS;
|
||
|
||
if ((*pTmpB & NAME_FORMAT_MASK) == 0)
|
||
{
|
||
DWORD RRSecLen = pRspInfo->QuesNamSecLen + RFC_LEN_QTYP_N_QCLS;
|
||
|
||
// RR_NAME is as big as the Question_name section.
|
||
WINSMSC_MOVE_MEMORY_M(
|
||
pTmpB,
|
||
pTmpB + RRSecLen,
|
||
RFC_LEN_TTL_N_RDLEN_N_NBF_N_NBA
|
||
);
|
||
}
|
||
else
|
||
{
|
||
// RR_NAME is a ptr so it takes up 2 bytes. 2 + 4 = 6
|
||
WINSMSC_MOVE_MEMORY_M(
|
||
pTmpB,
|
||
pTmpB + RFC_LEN_RRPTR + RFC_LEN_RRTYP_N_RRCLS,
|
||
RFC_LEN_TTL_N_RDLEN_N_NBF_N_NBA
|
||
);
|
||
}
|
||
pTmpB += RFC_LEN_TTL_N_RDLEN_N_NBF_N_NBA;
|
||
|
||
#if 0
|
||
// not needed. We always return the NBFLAGS and Address of the requestor
|
||
pTmpB2 = pTmpB - RFC_LEN_NBFLAGS - RFC_LEN_NBADD;
|
||
|
||
//
|
||
// Set the NBFLAGS field
|
||
//
|
||
if (pRspInfo->EntTyp == NMSDB_SPEC_GRP_ENTRY)
|
||
{
|
||
*pTmpB2++ = 0x80;
|
||
*pTmpB2++ = 0x00;
|
||
}
|
||
else
|
||
{
|
||
COMM_IP_ADD_T IPAdd = pRspInfo->pNodeAdds->Mem[0].Add.Add.IPAdd;
|
||
if (pRspInfo->EntTyp == NMSDB_NORM_GRP_ENTRY)
|
||
{
|
||
*pTmpB2++ = 0x80;
|
||
}
|
||
else //it is a unique entry
|
||
{
|
||
*pTmpB2++ = pRspInfo->NodeTyp_e << NMSDB_SHIFT_NODE_TYP;
|
||
}
|
||
*pTmpB2++ = 0x00;
|
||
|
||
*pTmpB2++ = (BYTE)(IPAdd >> 24); //MSB
|
||
*pTmpB2++ = (BYTE)((IPAdd >> 16) % 256);
|
||
*pTmpB2++ = (BYTE)((IPAdd >> 8) % 256);
|
||
*pTmpB2++ = (BYTE)(IPAdd % 256); //LSB
|
||
|
||
}
|
||
#endif
|
||
|
||
pRspInfo->MsgLen = (ULONG) (pTmpB - (LPBYTE)pRspInfo->pMsg);
|
||
return(WINS_SUCCESS);
|
||
|
||
}
|
||
|
||
|
||
#if 0
|
||
|
||
STATUS
|
||
FrmNamQueryRsp(
|
||
IN PCOMM_HDL_T pDlgHdl,
|
||
IN PNMSMSGF_RSP_INFO_T pRspInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This function formats a name query response
|
||
|
||
Arguments:
|
||
pDlgHdl -- Dialogue Handle
|
||
pRspInfo -- Response Info
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
NmsNmhFrmRspMsg()
|
||
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Success status codes -- WINS_SUCCESS
|
||
Error status codes -- WINS_FAILURE
|
||
|
||
Comments: Not used currently. Will make use of it when we have the
|
||
potential to send more data than can fit in a query response
|
||
datagram
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fTrunc = FALSE;
|
||
LPBYTE pReqBuff = pRspInfo->pMsg;
|
||
LPBYTE pNewBuff = pReqBuff;
|
||
STATUS RetStat = WINS_SUCCESS;
|
||
|
||
FUTURES("Currently, since we never send more than 25 addresses, there is no")
|
||
FUTURES(" danger of overflowing the buffer. In the future, if we ever change")
|
||
FUTURES("that, we should unconditinalize the code below, compile it and check")
|
||
FUTURES("it out. It needs to be modified. The computation of the size")
|
||
FUTURES("is faulty")
|
||
DWORD RspLen = 0;
|
||
BYTE *pTmpB = NULL;
|
||
|
||
|
||
|
||
|
||
/*
|
||
If this is to be sent as a datagram we will use the same buffer
|
||
that carries the request.
|
||
|
||
If it is to be sent on a TCP connection
|
||
we will still use the same buffer if it is a negative name query
|
||
response. If, however, a positive name query response has to be
|
||
sent, we will allocate a buffer storing the response
|
||
|
||
*/
|
||
|
||
|
||
if ((!COMM_IS_TCP_MSG_M(pDlgHdl))
|
||
{
|
||
|
||
/*
|
||
In the following there is no need to check fGrp flag but
|
||
let us do it for insurance
|
||
*/
|
||
if ((Rcode_e == NMSMSGF_E_SUCCESS) && (NodeAdds.fGrp))
|
||
{
|
||
/*
|
||
Check if we need to set the truncation bit in the
|
||
datagram.
|
||
|
||
To do the above,
|
||
|
||
Compute the size of the buffer required to house all
|
||
the information and compare with the datagram size
|
||
*/
|
||
|
||
if (
|
||
(
|
||
RspLen = pDlgHdl->MsgLen + RFC_LEN_TTL_N_RDLEN +
|
||
(NodeAdds.NoOfMems * sizeof(COMM_IP_ADD_T))
|
||
)
|
||
> COMM_DATAGRAM_SIZE
|
||
)
|
||
{
|
||
fTrunc = TRUE;
|
||
}
|
||
}
|
||
}
|
||
else // TCP message with Rcode_e of success
|
||
{
|
||
|
||
if (
|
||
(
|
||
RspLen = *pMsgLen + RFC_LEN_TTL_N_RDLEN +
|
||
(NodeAdds.NoOfMems * sizeof(COMM_IP_ADD))
|
||
)
|
||
> COMM_DATAGRAM_SIZE
|
||
)
|
||
{
|
||
WinsMscAlloc(RspLen, &pNewBuff);
|
||
if (pNewBuff == NULL)
|
||
{
|
||
return(WINS_FAILURE);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
*ppMsg = pNewBuff;
|
||
Status = FormatQueryRspBuff(
|
||
pNewBuff, //ptr to buffer to fill
|
||
pReqBuff, // ptr to req buffer
|
||
pRspInfo,
|
||
ftrunc
|
||
);
|
||
|
||
WinsMscHeapFree(
|
||
CommUdpBuffHeapHdl,
|
||
pReqBuff
|
||
); // get rid of the old buffer
|
||
|
||
|
||
return(Status);
|
||
|
||
}
|
||
|
||
RetStat = FormatQueryRspBuff(
|
||
pNewBuff, //ptr to buffer to fill
|
||
pReqBuff, // ptr to req buffer
|
||
pRspInfo,
|
||
fTrunc
|
||
);
|
||
|
||
return(RetStat);
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
STATUS
|
||
FormatQueryRspBuff(
|
||
IN LPBYTE pDest,
|
||
IN LPBYTE pSrc,
|
||
IN PNMSMSGF_RSP_INFO_T pRspInfo,
|
||
IN BOOL fTrunc
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This function formats the response for a name query request
|
||
|
||
Arguments:
|
||
pDest - Buffer to contain the formatted response
|
||
pSrc - Buffer containing the formatted request
|
||
pRspInfo - Response Information
|
||
fTrunc - whether the response packet is to have the truncation bit set
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
FrmNamQueryRsp()
|
||
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Success status codes -- WINS_SUCCESS
|
||
Error status codes -- WINS_FAILURE
|
||
--*/
|
||
|
||
{
|
||
|
||
DWORD no;
|
||
LPBYTE pDestB = pDest;
|
||
DWORD LenOfAdds;
|
||
DWORD IPAdd;
|
||
|
||
*pDestB++ = *pSrc;
|
||
*pDestB++ = *(pSrc + 1);
|
||
|
||
/*
|
||
The Transaction Id, Opcode, NMFlags and Rcode field
|
||
*/
|
||
*pDestB++ =
|
||
( *(pSrc + 2) |
|
||
((fTrunc == FALSE)
|
||
? RFC_NAM_QUERY_RSP_OPC_NO_T
|
||
: RFC_NAM_QUERY_RSP_OPC_T)
|
||
);
|
||
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_4THB + pRspInfo->Rcode_e;
|
||
|
||
/*
|
||
* Set the QD count and the AN count fields
|
||
*/
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_QDCNT_1STB;
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_QDCNT_2NDB;
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_ANCNT_1STB;
|
||
|
||
*pDestB++ = (pRspInfo->Rcode_e == NMSMSGF_E_SUCCESS) ?
|
||
RFC_NAM_QUERY_POS_RSP_ANCNT_2NDB
|
||
: RFC_NAM_QUERY_NEG_RSP_ANCNT_2NDB;
|
||
|
||
/*
|
||
Set the NSCOUNT and ARCOUNT fields
|
||
*/
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_NSCNT_1STB;
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_NSCNT_2NDB;
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_ARCNT_1STB;
|
||
*pDestB++ = RFC_NAM_QUERY_RSP_ARCNT_2NDB;
|
||
|
||
pSrc += pDestB - pDest;
|
||
|
||
/*
|
||
Increment the counter past the Question_Name Section (which is known
|
||
as the RR_NAME section here).
|
||
|
||
Use MoveMemory here instead of Copy Memory. Move Memory handles
|
||
overlapped copies which will happen if pDest and pSrc are
|
||
pointing to the same buffer
|
||
*/
|
||
|
||
WINSMSC_MOVE_MEMORY_M(
|
||
pDestB,
|
||
pSrc,
|
||
pRspInfo->QuesNamSecLen
|
||
);
|
||
|
||
pDestB += pRspInfo->QuesNamSecLen;
|
||
|
||
if (pRspInfo->Rcode_e == NMSMSGF_E_SUCCESS)
|
||
{
|
||
*pDestB++ = RFC_NAM_QUERY_POS_RSP_NB_1STB; //RFC 1002 -- page 22
|
||
*pDestB++ = RFC_NAM_QUERY_POS_RSP_NB_2NDB; //RFC 1002 -- page 22
|
||
*pDestB++ = RFC_NAM_QUERY_POS_RSP_IN_1STB; //RFC 1002 -- page 22
|
||
*pDestB++ = RFC_NAM_QUERY_POS_RSP_IN_2NDB; //RFC 1002 -- page 22
|
||
}
|
||
else
|
||
{
|
||
*pDestB++ = RFC_NAM_QUERY_NEG_RSP_NB_1STB; //RFC 1002 -- page 22
|
||
*pDestB++ = RFC_NAM_QUERY_NEG_RSP_NB_2NDB; //RFC 1002 -- page 22
|
||
*pDestB++ = RFC_NAM_QUERY_NEG_RSP_IN_1STB; //RFC 1002 -- page 22
|
||
*pDestB++ = RFC_NAM_QUERY_NEG_RSP_IN_2NDB; //RFC 1002 -- page 22
|
||
}
|
||
|
||
if (!fTrunc)
|
||
{
|
||
|
||
if (pRspInfo->Rcode_e == NMSMSGF_E_SUCCESS)
|
||
{
|
||
|
||
CHECK("In case of a negative response, does it matter what I put in the TTL")
|
||
CHECK("field. It shouldn't matter -- RFC is silent about this")
|
||
/*
|
||
Put 0 in the TTL field. TTL field will not be looked at by the
|
||
Client.
|
||
*/
|
||
*pDestB++ = 0;
|
||
*pDestB++ = 0;
|
||
*pDestB++ = 0;
|
||
*pDestB++ = 0;
|
||
|
||
//
|
||
// Get the RDLENGTH value
|
||
//
|
||
LenOfAdds = pRspInfo->pNodeAdds->NoOfMems *
|
||
(RFC_LEN_NBFLAGS + sizeof(COMM_IP_ADD_T));
|
||
|
||
*pDestB++ = (BYTE)(LenOfAdds >> 8); //MSB
|
||
*pDestB++ = (BYTE)(LenOfAdds % 256); //LSB
|
||
|
||
//
|
||
// Put the NBFLAGS here
|
||
//
|
||
if (
|
||
(pRspInfo->EntTyp != NMSDB_UNIQUE_ENTRY)
|
||
)
|
||
{
|
||
BYTE Nbflags;
|
||
DWORD StartIndex;
|
||
if ( pRspInfo->EntTyp == NMSDB_MULTIHOMED_ENTRY)
|
||
{
|
||
Nbflags =
|
||
pRspInfo->NodeTyp_e << NMSDB_SHIFT_NODE_TYP;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// it is a group (normal/special)
|
||
//
|
||
Nbflags = 0x80;
|
||
}
|
||
//
|
||
// It is a group (normal or special) or a multihomed
|
||
// entry
|
||
//
|
||
if (pRspInfo->pNodeAdds->NoOfMems &&
|
||
WinsCnf.fRandomize1CList &&
|
||
NMSDB_SPEC_GRP_ENTRY == pRspInfo->EntTyp ) {
|
||
StartIndex = rand() % pRspInfo->pNodeAdds->NoOfMems;;
|
||
} else {
|
||
StartIndex = 0;
|
||
}
|
||
for (no = StartIndex; no < pRspInfo->pNodeAdds->NoOfMems; no++)
|
||
{
|
||
|
||
*pDestB++ = Nbflags;
|
||
*pDestB++ = 0x0;
|
||
IPAdd = pRspInfo->pNodeAdds->Mem[no].Add.Add.IPAdd;
|
||
NMSMSGF_INSERT_IPADD_M(pDestB, IPAdd);
|
||
}
|
||
for (no = 0; no < StartIndex; no++)
|
||
{
|
||
|
||
*pDestB++ = Nbflags;
|
||
*pDestB++ = 0x0;
|
||
IPAdd = pRspInfo->pNodeAdds->Mem[no].Add.Add.IPAdd;
|
||
NMSMSGF_INSERT_IPADD_M(pDestB, IPAdd);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// It is a unique entry
|
||
//
|
||
*pDestB++ = pRspInfo->NodeTyp_e << NMSDB_SHIFT_NODE_TYP;
|
||
*pDestB++ = 0x0;
|
||
IPAdd = pRspInfo->pNodeAdds->Mem[0].Add.Add.IPAdd;
|
||
NMSMSGF_INSERT_IPADD_M(pDestB, IPAdd);
|
||
}
|
||
}
|
||
else //this is a negative name query response
|
||
{
|
||
/*
|
||
Put 0 in the TTL field. TTL field will not be looked at by the
|
||
Client.
|
||
*/
|
||
*pDestB++ = 0;
|
||
*pDestB++ = 0;
|
||
*pDestB++ = 0;
|
||
*pDestB++ = 0;
|
||
|
||
/*
|
||
Put 0 in the RDLENGTH field since we are not passing any
|
||
address(es)
|
||
*/
|
||
*pDestB++ = 0;
|
||
*pDestB++ = 0;
|
||
|
||
}
|
||
CHECK("When a truncated response is sent to the client, is it ok to not")
|
||
CHECK("Send any field after the RR_NAME section. RFC is silent about this")
|
||
CHECK("For now, it is ok, since we will never have a situation where a ")
|
||
CHECK("truncated response needs to be sent")
|
||
|
||
pRspInfo->MsgLen = (ULONG) (pDestB - pDest);
|
||
|
||
}
|
||
else
|
||
{
|
||
//this is a truncated response (does not have any field after
|
||
//RR_NAME section
|
||
pRspInfo->MsgLen = (ULONG) (pDestB - pDest);
|
||
}
|
||
|
||
return(WINS_SUCCESS);
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
FormatName(
|
||
IN LPBYTE pNameToFormat,
|
||
IN DWORD NamLen,
|
||
IN OUT LPBYTE *ppFormattedName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This function is called to format a name
|
||
|
||
|
||
Arguments:
|
||
pNameToFormat -- Name to format
|
||
LengthOfName -- Length of Name
|
||
pFormattedName -- Name after it has been formatted
|
||
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
|
||
Return Value:
|
||
|
||
Success status codes --
|
||
Error status codes --
|
||
|
||
Error Handling:
|
||
|
||
Called by:
|
||
|
||
Side Effects:
|
||
|
||
Comments:
|
||
Note: This function should be called to format only those names
|
||
whose length as indicated by NameLen includes the ending
|
||
0. All names stored in the database are valid.
|
||
|
||
--*/
|
||
|
||
{
|
||
LPBYTE pTmpB = *ppFormattedName;
|
||
DWORD Length;
|
||
LPBYTE pSaveAdd = pTmpB; //save address of length octet
|
||
|
||
|
||
FUTURES("take out the check below to improve performance")
|
||
//
|
||
// If NamLen is more then what is prescribed in RFC 1002,
|
||
// there is something really wrong. This calls for raising
|
||
// an exception
|
||
//
|
||
if (NamLen > RFC_MAX_NAM_LEN)
|
||
{
|
||
WINS_RAISE_EXC_M(WINS_FATAL_ERR);
|
||
}
|
||
|
||
pTmpB++; //skip the length octet. We will write to
|
||
//it later. We have stored the address in
|
||
//pSaveAdd
|
||
NamLen--; //decrement Namelen since we always store
|
||
//0 at the end of the name. NameLen includes
|
||
//this extra byte
|
||
for (
|
||
Length = 0;
|
||
(*pNameToFormat != '.') && (NamLen != 0);
|
||
Length += 2, NamLen--
|
||
)
|
||
{
|
||
*pTmpB++ = 'A' + (*pNameToFormat >> 4);
|
||
*pTmpB++ = 'A' + (*pNameToFormat++ & 0x0F);
|
||
}
|
||
|
||
*pSaveAdd = (BYTE)Length;
|
||
|
||
while(NamLen != 0)
|
||
{
|
||
|
||
pNameToFormat++; //increment past the '.'
|
||
pSaveAdd = pTmpB++; //save add; skip past length octet
|
||
|
||
NamLen--; //to account for the '.'
|
||
|
||
for (
|
||
Length = 0;
|
||
(*pNameToFormat != '.') && (NamLen != 0);
|
||
Length++, NamLen--
|
||
)
|
||
{
|
||
*pTmpB++ = *pNameToFormat++;
|
||
}
|
||
|
||
FUTURES("take out the check below to improve performance")
|
||
//
|
||
// Make sure there is no weirdness
|
||
//
|
||
if (Length > RFC_MAX_LABEL_LEN)
|
||
{
|
||
WINS_RAISE_EXC_M(WINS_FATAL_ERR);
|
||
}
|
||
|
||
*pSaveAdd = (BYTE)Length;
|
||
if (NamLen == 0)
|
||
{
|
||
break; //reached end of name
|
||
}
|
||
|
||
}
|
||
|
||
*pTmpB++ = EOS;
|
||
*ppFormattedName = pTmpB;
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
NmsMsgfFrmNamQueryReq(
|
||
IN DWORD TransId,
|
||
IN MSG_T pMsg,
|
||
OUT PMSG_LEN_T pMsgLen,
|
||
IN LPBYTE pNameToFormat,
|
||
IN DWORD NameLen
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function formats a name query request packet
|
||
|
||
Arguments:
|
||
TransId - Transaction Id. to use
|
||
pMsg - Msg Buffer to format
|
||
pMsgLen - Length of formatted message
|
||
pNameToFormat - Name to format
|
||
NameLen - Length of Name
|
||
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
|
||
Return Value:
|
||
None
|
||
|
||
Error Handling:
|
||
|
||
Called by:
|
||
HandleWrkItm in nmschl.c
|
||
|
||
Side Effects:
|
||
|
||
Comments:
|
||
None
|
||
--*/
|
||
|
||
{
|
||
LPBYTE pTmpB = pMsg;
|
||
|
||
/*
|
||
* Put the Transaction Id in
|
||
*/
|
||
*pTmpB++ = (BYTE)(TransId >> 8);
|
||
*pTmpB++ = (BYTE)(TransId & 0xFF);
|
||
|
||
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_OPCB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_4THB;
|
||
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_QDCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_QDCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_ANCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_ANCNT_2NDB;
|
||
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_NSCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_NSCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_ARCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_ARCNT_2NDB;
|
||
|
||
FormatName(pNameToFormat, NameLen, &pTmpB);
|
||
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_QTYP_1STB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_QTYP_2NDB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_QCLS_1STB;
|
||
*pTmpB++ = RFC_NAM_QUERY_REQ_QCLS_2NDB;
|
||
|
||
*pMsgLen = (ULONG) (pTmpB - pMsg);
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
NmsMsgfFrmNamRelReq(
|
||
IN DWORD TransId,
|
||
IN MSG_T pMsg,
|
||
OUT PMSG_LEN_T pMsgLen,
|
||
IN LPBYTE pNameToFormat,
|
||
IN DWORD NameLen,
|
||
IN NMSMSGF_NODE_TYP_E NodeTyp_e,
|
||
IN PCOMM_ADD_T pNodeAdd
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function formats a name release request packet
|
||
|
||
Arguments:
|
||
TransId - Transaction Id. to use
|
||
pMsg - Msg Buffer to format
|
||
pMsgLen - Length of formatted message
|
||
pNameToFormat - Name to format
|
||
NameLen - Length of Name
|
||
NodeTyp_e - Type of Node
|
||
NodeAdd - IP address of node
|
||
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
|
||
Return Value:
|
||
None
|
||
|
||
Error Handling:
|
||
|
||
Called by:
|
||
HandleWrkItm() in nmschl.c
|
||
Side Effects:
|
||
|
||
Comments:
|
||
None
|
||
--*/
|
||
{
|
||
|
||
LPBYTE pTmpB = pMsg;
|
||
|
||
|
||
/*
|
||
* Put the Transaction Id in
|
||
*/
|
||
*pTmpB++ = (BYTE)(TransId >> 8);
|
||
*pTmpB++ = (BYTE)(TransId & 0xFF);
|
||
|
||
*pTmpB++ = RFC_NAM_REL_REQ_OPCB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_4THB;
|
||
|
||
*pTmpB++ = RFC_NAM_REL_REQ_QDCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_QDCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_ANCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_ANCNT_2NDB;
|
||
|
||
*pTmpB++ = RFC_NAM_REL_REQ_NSCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_NSCNT_2NDB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_ARCNT_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_ARCNT_2NDB;
|
||
|
||
FormatName(pNameToFormat, NameLen, &pTmpB);
|
||
|
||
*pTmpB++ = RFC_NAM_REL_REQ_QTYP_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_QTYP_2NDB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_QCLS_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_QCLS_2NDB;
|
||
|
||
|
||
*pTmpB++ = 0xC0;
|
||
*pTmpB++ = 0x0C; //Name is at offset 12 from start of message
|
||
|
||
*pTmpB++ = RFC_NAM_REL_REQ_RRTYP_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_RRTYP_2NDB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_RRCLS_1STB;
|
||
*pTmpB++ = RFC_NAM_REL_REQ_RRCLS_2NDB;
|
||
|
||
//
|
||
// TTL
|
||
//
|
||
*pTmpB++ = 0;
|
||
*pTmpB++ = 0;
|
||
*pTmpB++ = 0;
|
||
*pTmpB++ = 0;
|
||
|
||
//
|
||
// RDLENGTH field
|
||
//
|
||
*pTmpB++ = 0x0;
|
||
*pTmpB++ = 0x6; //number of bytes to follow
|
||
|
||
|
||
//
|
||
// NBFLAGS word (Bit 15 is Group bit (0); bit 13 and 14 are node
|
||
// type bits, rest of the bits are reserved
|
||
//
|
||
*pTmpB++ = NodeTyp_e << 13;
|
||
*pTmpB++ = 0;
|
||
|
||
//
|
||
// Store the IP address. MSB first, LSB last (Network Byte Order)
|
||
//
|
||
NMSMSGF_INSERT_IPADD_M(pTmpB, pNodeAdd->Add.IPAdd);
|
||
|
||
*pMsgLen = (ULONG) (pTmpB - pMsg);
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
NmsMsgfFrmWACK(
|
||
IN LPBYTE pBuff,
|
||
OUT LPDWORD pBuffLen,
|
||
IN MSG_T pMsg,
|
||
IN DWORD QuesNamSecLen,
|
||
IN DWORD WackTtl
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
This function is called to format a WACK for a name registration
|
||
request.
|
||
|
||
Arguments:
|
||
|
||
Buff - Buffer to be filled up with WACK msg fields
|
||
pBuffLen - size of Buffer
|
||
pMsg - Request Message received
|
||
QuesNamSecLen - Length of Ques Nam Sec of the request message
|
||
WackTtl - TTL in msecs
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
Error Handling:
|
||
|
||
Called by:
|
||
NmsChlHdlNamReg()
|
||
|
||
Side Effects:
|
||
|
||
Comments:
|
||
|
||
--*/
|
||
|
||
{
|
||
LPBYTE pTmpB = pBuff;
|
||
LPBYTE pName = pMsg + NAME_HEADER_SIZE;
|
||
DWORD Ttl;
|
||
|
||
//
|
||
// Compute the TTL in secs (WackTtl is in msecs)
|
||
//
|
||
Ttl = WackTtl / 1000;
|
||
if (WackTtl % 1000 > 0)
|
||
{
|
||
Ttl++;
|
||
}
|
||
|
||
/*
|
||
* Put the Transaction Id in
|
||
*/
|
||
*pTmpB++ = *pMsg;
|
||
*pTmpB++ = *(pMsg + 1);
|
||
|
||
|
||
*pTmpB++ = RFC_WACK_OPCB;
|
||
*pTmpB++ = RFC_WACK_4THB;
|
||
|
||
*pTmpB++ = RFC_WACK_QDCNT_1STB;
|
||
*pTmpB++ = RFC_WACK_QDCNT_2NDB;
|
||
*pTmpB++ = RFC_WACK_ANCNT_1STB;
|
||
*pTmpB++ = RFC_WACK_ANCNT_2NDB;
|
||
|
||
*pTmpB++ = RFC_WACK_NSCNT_1STB;
|
||
*pTmpB++ = RFC_WACK_NSCNT_2NDB;
|
||
*pTmpB++ = RFC_WACK_ARCNT_1STB;
|
||
*pTmpB++ = RFC_WACK_ARCNT_2NDB;
|
||
|
||
WINSMSC_COPY_MEMORY_M(
|
||
pTmpB,
|
||
pName,
|
||
QuesNamSecLen
|
||
);
|
||
|
||
pTmpB += QuesNamSecLen;
|
||
|
||
|
||
*pTmpB++ = RFC_WACK_RRTYP_1STB;
|
||
*pTmpB++ = RFC_WACK_RRTYP_2NDB;
|
||
*pTmpB++ = RFC_WACK_RRCLS_1STB;
|
||
*pTmpB++ = RFC_WACK_RRCLS_2NDB;
|
||
|
||
//
|
||
// TTL
|
||
//
|
||
*pTmpB++ = (BYTE)(Ttl >> 24);
|
||
*pTmpB++ = (BYTE)((Ttl >> 16) % 256);
|
||
*pTmpB++ = (BYTE)((Ttl >> 8) % 256);
|
||
*pTmpB++ = (BYTE)(Ttl % 256);
|
||
|
||
|
||
*pTmpB++ = RFC_WACK_RDLENGTH_1STB;
|
||
*pTmpB++ = RFC_WACK_RDLENGTH_2NDB;
|
||
|
||
|
||
//
|
||
// Store the Opcode and NM_FLAGS field. These fields can
|
||
// be retrieved directly from the 3rd and 4th byte of the message
|
||
//
|
||
*pTmpB++ = *(pMsg + 2);
|
||
*pTmpB++ = *(pMsg + 3);
|
||
|
||
|
||
*pBuffLen = (ULONG) (pTmpB - pBuff);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
STATUS
|
||
NmsMsgfUfmNamRsp(
|
||
IN LPBYTE pMsg,
|
||
OUT PNMSMSGF_NAM_REQ_TYP_E pOpcode_e,
|
||
OUT LPDWORD pTransId,
|
||
OUT LPBYTE pName,
|
||
OUT LPDWORD pNameLen,
|
||
OUT PNMSMSGF_CNT_ADD_T pCntAdd,
|
||
//OUT PCOMM_IP_ADD_T pIpAdd,
|
||
OUT PNMSMSGF_ERR_CODE_E pRcode_e,
|
||
OUT BOOL *fGroup
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
The function unformats the response message
|
||
|
||
Arguments:
|
||
pMsg - Msg received (to unformat)
|
||
pOpcde_e - Opcode
|
||
pTransId - Transaction Id.
|
||
pName - Name
|
||
pNameLen - Name length returned.
|
||
pIpAdd - IP address
|
||
pRcode_e - error type (or success)
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
Called by:
|
||
ProcRsp in NmsChl.c
|
||
|
||
|
||
Comments:
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Success status codes -- WINS_SUCCESS
|
||
Error status codes -- WINS_FAILURE
|
||
|
||
--*/
|
||
|
||
{
|
||
LPBYTE pTmpB = pMsg;
|
||
|
||
//
|
||
// get the opcode. Extracts the 4 bits in the 3rd byte (bit 11-bit 14)
|
||
//
|
||
*pOpcode_e = (NMS_OPCODE_MASK & *(pTmpB + 2)) >> 3;
|
||
|
||
if ( (*pOpcode_e != NMSMSGF_E_NAM_QUERY) &&
|
||
(*pOpcode_e != NMSMSGF_E_NAM_REL)
|
||
)
|
||
{
|
||
|
||
*pOpcode_e = NMSMSGF_E_INV_REQ;
|
||
return(WINS_FAILURE);
|
||
|
||
}
|
||
|
||
//
|
||
// Get the transaction id
|
||
//
|
||
*pTransId = (DWORD)((*pTmpB << 8) + *(pTmpB + 1));
|
||
// *pTransId |= (DWORD)(*(pTmpB + 1));
|
||
|
||
//
|
||
// get the Rcode_e
|
||
//
|
||
*pRcode_e = *(pTmpB + 3) % 16;
|
||
|
||
|
||
/*
|
||
* make pTmpB point to the RR Section. All name request/response
|
||
* packets have a name header of standard size (RFC 1002) at the top
|
||
*/
|
||
|
||
pTmpB += NAME_HEADER_SIZE;
|
||
|
||
/*
|
||
* Extract the name ind store in Name. GetName will update pTmp to
|
||
* point just beyond the name in the RR section
|
||
*/
|
||
|
||
GetName(
|
||
&pTmpB,
|
||
pName,
|
||
pNameLen
|
||
);
|
||
|
||
|
||
//
|
||
// If it is a negative name query response we are done
|
||
//
|
||
if (
|
||
(*pOpcode_e == NMSMSGF_E_NAM_QUERY) &&
|
||
(*pRcode_e != NMSMSGF_E_SUCCESS)
|
||
)
|
||
{
|
||
return(WINS_SUCCESS);
|
||
}
|
||
else
|
||
{
|
||
DWORD i;
|
||
|
||
pTmpB += RFC_LEN_RR_N_TTL;
|
||
|
||
pCntAdd->NoOfAdds =
|
||
((*pTmpB << 8) + *(pTmpB + 1))/RFC_LEN_NBF_N_NBA;
|
||
pTmpB += RFC_LEN_RDLEN;
|
||
// 15th bit in NBFLAGS indicates if this is a group name
|
||
*fGroup = (*pTmpB & 0x80 ? TRUE:FALSE);
|
||
pTmpB += RFC_LEN_NBFLAGS;
|
||
|
||
//
|
||
// we have either positive query response or a response to a
|
||
// release
|
||
//
|
||
for ( i = 0;
|
||
#if 0
|
||
i < min(pCntAdd->NoOfAdds, NMSMSGF_MAX_NO_MULTIH_ADDS);
|
||
#endif
|
||
i < min(pCntAdd->NoOfAdds, NMSMSGF_MAX_ADDRESSES_IN_UDP_PKT);
|
||
i++
|
||
)
|
||
{
|
||
//
|
||
// Get the IP address. This macro will increment pTmpB by
|
||
// 4
|
||
//
|
||
NMSMSGF_RETRIEVE_IPADD_M(pTmpB, pCntAdd->Add[i].Add.IPAdd);
|
||
pCntAdd->Add[i].AddTyp_e = COMM_ADD_E_TCPUDPIP;
|
||
pCntAdd->Add[i].AddLen = sizeof(PCOMM_IP_ADD_T);
|
||
pTmpB += RFC_LEN_NBFLAGS;
|
||
}
|
||
}
|
||
|
||
return(WINS_SUCCESS);
|
||
}
|
||
|
||
|
||
VOID
|
||
NmsMsgfSndNamRsp(
|
||
PCOMM_HDL_T pDlgHdl,
|
||
LPBYTE pMsg,
|
||
DWORD MsgLen,
|
||
DWORD BlockOfReq
|
||
)
|
||
{
|
||
NMSMSGF_NAM_REQ_TYP_E Opcode;
|
||
DWORD NameLen; //length of name
|
||
DWORD QuesNamSecLen; //length of question name section in
|
||
//packet
|
||
DWORD Length;
|
||
|
||
LPBYTE pTmp = (LPBYTE)pMsg;
|
||
LPBYTE pTmp2;
|
||
NMSMSGF_RSP_INFO_T RspInfo;
|
||
static DWORD sNoOfTimes = 0;
|
||
|
||
DBGPRINT1(DET, "NmsMsgfSndNamRsp: BlockOfReq is (%d)\n", BlockOfReq);
|
||
// get the opcode
|
||
Opcode = (NMS_OPCODE_MASK & *(pTmp + 2)) >> 3;
|
||
|
||
//
|
||
// if it is a release request, we drop the datagram
|
||
//
|
||
if (Opcode == NMSMSGF_E_NAM_REL)
|
||
{
|
||
ECommFreeBuff(pMsg);
|
||
ECommEndDlg(pDlgHdl);
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* make pTmp point to the Question Section. All name request
|
||
* packets have a name header of standard size (RFC 1002) at the top
|
||
*/
|
||
pTmp += NAME_HEADER_SIZE;
|
||
pTmp2 = pTmp;
|
||
|
||
NameLen = LENGTH_MASK & *pTmp;
|
||
pTmp += NameLen + 1; //pt pTmp to past the first label
|
||
NameLen /= 2;
|
||
|
||
while (TRUE)
|
||
{
|
||
if (*pTmp != 0)
|
||
{
|
||
if (NameLen > MAX_SIZE_INTERNAL_NAME)
|
||
{
|
||
ECommFreeBuff(pMsg);
|
||
ECommEndDlg(pDlgHdl);
|
||
return;
|
||
}
|
||
Length = LENGTH_MASK & *pTmp;
|
||
NameLen += Length + 1;
|
||
pTmp += Length + 1; //increment past length and label
|
||
}
|
||
else
|
||
{
|
||
pTmp++;
|
||
break;
|
||
}
|
||
}
|
||
|
||
QuesNamSecLen = (ULONG) (pTmp - pTmp2);
|
||
|
||
|
||
RspInfo.RefreshInterval = 300 * BlockOfReq; // 5 mts
|
||
RspInfo.Rcode_e = NMSMSGF_E_SUCCESS;
|
||
RspInfo.pMsg = pMsg;
|
||
RspInfo.MsgLen = MsgLen;
|
||
RspInfo.QuesNamSecLen = QuesNamSecLen;
|
||
|
||
NmsNmhSndNamRegRsp( pDlgHdl, &RspInfo );
|
||
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
#if 0
|
||
STATUS
|
||
NmsMsgfFrmNamRegReq(
|
||
IN DWORD TransId,
|
||
IN MSG_T pMsg,
|
||
OUT PMSG_LEN_T pMsgLen,
|
||
IN LPBYTE pNameToFormat,
|
||
IN DWORD NameLen,
|
||
IN NMSMSGF_NODE_TYP_E NodeTyp_e,
|
||
IN PCOMM_ADD_T pNodeAdd
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called to format a name registration request
|
||
|
||
Arguments:
|
||
|
||
|
||
Externals Used:
|
||
None
|
||
|
||
|
||
Return Value:
|
||
|
||
Success status codes --
|
||
Error status codes --
|
||
|
||
Error Handling:
|
||
|
||
Called by:
|
||
|
||
Side Effects:
|
||
|
||
Comments:
|
||
This fn gets called when a remote WINS has to be told to
|
||
increment the version number of
|
||
--*/
|
||
{
|
||
|
||
//
|
||
// Lets format a name release request since this is exactly the
|
||
// same as a name registration request except for the 2nd and
|
||
// 3rd bytes (counting from 0) which house the opcode and
|
||
// nmflags. We will set these bytes apprropriately after
|
||
// the following call
|
||
//
|
||
NmsMsgfNamRelReq(
|
||
TransId,
|
||
pMsg,
|
||
pMsgLen,
|
||
pNameToFormat,
|
||
NameLen,
|
||
NodeTyp_e,
|
||
pNodeAdd
|
||
);
|
||
|
||
|
||
*(pMsg + 2) = 0x29;
|
||
*(pMsg + 3) = 0x00;
|
||
|
||
return;
|
||
}
|
||
#endif
|
||
|