windows-nt/Source/XPSP1/NT/net/wlbs/nlbmgr/provider/new.cpp

560 lines
13 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "private.h"
#include "new.tmh"
#define NLB_MAX_PORT_STRING_SIZE 128 // in WCHARS, including ending NULL
BOOL
gen_port_rule_string(
IN PWLBS_PORT_RULE pPr,
OUT LPWSTR pString // At least NLB_MAX_PORT_STRING_SIZE wchars
);
BOOL
parse_port_rule_string(
IN LPCWSTR pString,
OUT PWLBS_PORT_RULE pPr
);
VOID
test_port_rule_string(VOID)
{
LPCWSTR RuleStrings[] =
{
L"",
L" \t \n ",
L"n=v",
L" \t \n n=v",
L" \t \n n \t \n = \t \n v",
L"na=v1 nb=v2 nc=v3",
L"\t na \t = \t v1 \t nb \t \n =\t \n v2 \t \n nc \t = \n v3 ",
#if 1
L"ip=1.1.1.1 protocol=TCP start=80 end=288 mode=SINGLE"
L" priority=1",
L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
L" affinity=SINGLE load=80",
L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
L" affinity=NONE load=80",
L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
L" affinity=CLASSC",
L"ip=1.1.1.1 protocol=BOTH start=80 end=288 mode=DISABLED",
#endif // 0
NULL // Must be last
};
for (LPCWSTR *ppRs = RuleStrings; *ppRs!=NULL; ppRs++)
{
LPCWSTR szRule = *ppRs;
WCHAR szGenString[NLB_MAX_PORT_STRING_SIZE];
printf("ORIG: %ws\n", szRule);
WLBS_PORT_RULE Pr;
BOOL fRet;
fRet = parse_port_rule_string(
szRule,
&Pr
);
if (fRet == FALSE)
{
printf("parse_port_rule_string returned FAILURE.\n");
continue;
}
fRet = gen_port_rule_string(
&Pr,
szGenString
);
if (fRet == FALSE)
{
printf("gen_port_rule_string returned FAILURE.\n");
continue;
}
printf("GEN: %ws\n", szGenString);
}
}
BOOL
gen_port_rule_string(
IN PWLBS_PORT_RULE pPr,
OUT LPWSTR pString // At least NLB_MAX_PORT_STRING_SIZE wchars
)
{
BOOL fRet = FALSE;
LPCWSTR szProtocol = L"";
LPCWSTR szMode = L"";
LPCWSTR szAffinity = L"";
ZeroMemory(pString, NLB_MAX_PORT_STRING_SIZE*sizeof(WCHAR));
switch(pPr->protocol)
{
case CVY_TCP:
szProtocol = L"TCP";
break;
case CVY_UDP:
szProtocol = L"UDP";
break;
case CVY_TCP_UDP:
szProtocol = L"BOTH";
break;
default:
goto end; // bad parse
}
switch(pPr->mode)
{
case CVY_SINGLE:
szMode = L"SINGLE";
break;
case CVY_MULTI:
szMode = L"MULTIPLE";
switch(pPr->mode_data.multi.affinity)
{
case CVY_AFFINITY_NONE:
szAffinity = L"NONE";
break;
case CVY_AFFINITY_SINGLE:
szAffinity = L"SINGLE";
break;
case CVY_AFFINITY_CLASSC:
szAffinity = L"CLASSC";
break;
default:
goto end; // bad parse
}
break;
case CVY_NEVER:
szMode = L"DISABLED";
break;
default:
goto end; // bad parse
}
*pString = 0;
_snwprintf(
pString,
NLB_MAX_PORT_STRING_SIZE-1,
L"ip=%ws protocol=%ws start=%u end=%u mode=%ws ",
pPr->virtual_ip_addr,
szProtocol,
pPr->start_port,
pPr->end_port,
szMode
);
UINT Len = wcslen(pString);
if (Len >= (NLB_MAX_PORT_STRING_SIZE-1))
{
goto end; // not enough space.
}
if (pPr->mode == CVY_MULTI)
{
if (pPr->mode_data.multi.equal_load)
{
_snwprintf(
pString+Len,
(NLB_MAX_PORT_STRING_SIZE-1-Len),
L"affinity=%ws",
szAffinity
);
}
else
{
_snwprintf(
pString+Len,
(NLB_MAX_PORT_STRING_SIZE-1-Len),
L"affinity=%ws load=%u",
szAffinity,
pPr->mode_data.multi.load
);
}
}
else if (pPr->mode == CVY_SINGLE)
{
_snwprintf(
pString+Len,
(NLB_MAX_PORT_STRING_SIZE-1-Len),
L"priority=%u",
pPr->mode_data.single.priority
);
}
if (pString[NLB_MAX_PORT_STRING_SIZE-1] !=0)
{
// out of space
goto end;
}
fRet = TRUE;
end:
return fRet;
}
BOOL
parse_port_rule_string(
IN LPCWSTR pString,
OUT PWLBS_PORT_RULE pPr
)
{
//
// Look for following name=value pairs
//
// ip=1.1.1.1
// protocol=[TCP|UDP|BOTH]
// start=122
// end=122
// mode=[SINGLE|MULTIPLE|DISABLED]
// affinity=[NONE|SINGLE|CLASSC]
// load=80
// priority=1"
//
#define INVALID_VALUE ((DWORD)-1)
LPWSTR psz = NULL;
WCHAR szCleanedString[2*NLB_MAX_PORT_STRING_SIZE];
WCHAR c;
BOOL fRet = FALSE;
DWORD protocol= INVALID_VALUE;
DWORD start_port= INVALID_VALUE;
DWORD end_port= INVALID_VALUE;
DWORD mode= INVALID_VALUE;
DWORD affinity= INVALID_VALUE;
DWORD load= INVALID_VALUE;
DWORD priority= INVALID_VALUE;
ZeroMemory(pPr, sizeof(*pPr));
//
// Set szCleanedString to be a version of pString in "canonical" form:
// extraneous whitespace stripped out and whitspace represented by a
// single '\b' character.
{
UINT Len = wcslen(pString);
if (Len > (sizeof(szCleanedString)/sizeof(WCHAR)))
{
goto end;
}
wcscpy(szCleanedString, pString);
//
// convert different forms of whitespace into blanks
//
for (psz=szCleanedString; (c=*psz)!=0; psz++)
{
if (c == ' ' || c == '\t' || c == '\n')
{
*psz = ' ';
}
}
//
// convert runs of whitespace into a single blank
// also get rid of initial whitespace
//
LPWSTR psz1 = szCleanedString;
BOOL fRun = TRUE; // initial value of TRUE gets rid of initial space
for (psz=szCleanedString; (c=*psz)!=0; psz++)
{
if (c == ' ')
{
if (fRun)
{
continue;
}
else
{
fRun = TRUE;
}
}
else if (c == '=')
{
if (fRun)
{
//
// The '=' was preceed by whitespace -- delete that
// whitespace. We keep fRun TRUE so subsequent whitespace
// is eliminated.
//
if (psz1 == szCleanedString)
{
// we're just starting, and we get an '=' -- bad
goto end;
}
psz1--;
if (*psz1 != ' ')
{
ASSERT(*psz1 == '=');
goto end; // two equals in a row, not accepted!
}
}
}
else // non blank and non '=' chracter
{
fRun = FALSE;
}
*psz1++ = c;
}
*psz1=0;
}
wprintf(L"CLEANED: \"%ws\"\n", szCleanedString);
//
// Now actually do the parse.
//
psz = szCleanedString;
while(*psz!=0)
{
WCHAR Name[32];
WCHAR Value[32];
//
// Look for the Name in Name=Value pair.
//
if (swscanf(psz, L"%16[a-zA-Z]=%16[0-9.a-zA-Z]", Name, Value) != 2)
{
// bad parse;
goto end;
}
//
// Skip past the name=value pair -- it contains no blanks
//
for (; (c=*psz)!=NULL; psz++)
{
if (c==' ')
{
psz++; // to skip past the blank
break;
}
}
//
// Now look for the specific name/values
//
// ip=1.1.1.1
// protocol=[TCP|UDP|BOTH]
// start=122
// end=122
// mode=[SINGLE|MULTIPLE|DISABLED]
// affinity=[NONE|SINGLE|CLASSC]
// load=80
// priority=1"
//
if (!_wcsicmp(Name, L"ip"))
{
if (swscanf(Value, L"%15[0-9.]", pPr->virtual_ip_addr) != 1)
{
goto end;
}
}
else if (!_wcsicmp(Name, L"protocol"))
{
if (!_wcsicmp(Value, L"TCP"))
{
protocol = CVY_TCP;
}
else if (!_wcsicmp(Value, L"UDP"))
{
protocol = CVY_UDP;
}
else if (!_wcsicmp(Value, L"BOTH"))
{
protocol = CVY_TCP_UDP;
}
else
{
// bad parse;
goto end;
}
}
else if (!_wcsicmp(Name, L"protocol"))
{
}
else if (!_wcsicmp(Name, L"start"))
{
if (swscanf(Value, L"%u", &start_port)!=1)
{
// bad parse;
goto end;
}
if (start_port > 65535)
{
// bad parse;
goto end;
}
}
else if (!_wcsicmp(Name, L"end"))
{
if (swscanf(Value, L"%u", &end_port)!=1)
{
// bad parse;
goto end;
}
if (end_port > 65535)
{
// bad parse;
goto end;
}
}
else if (!_wcsicmp(Name, L"mode"))
{
if (!_wcsicmp(Value, L"SINGLE"))
{
mode = CVY_SINGLE;
}
else if (!_wcsicmp(Value, L"MULTIPLE"))
{
mode = CVY_MULTI;
}
else if (!_wcsicmp(Value, L"DISABLED"))
{
mode = CVY_NEVER;
}
else
{
// bad parse;
goto end;
}
}
else if (!_wcsicmp(Name, L"affinity"))
{
if (!_wcsicmp(Value, L"NONE"))
{
affinity = CVY_AFFINITY_NONE;
}
else if (!_wcsicmp(Value, L"SINGLE"))
{
affinity = CVY_AFFINITY_SINGLE;
}
else if (!_wcsicmp(Value, L"CLASSC"))
{
affinity = CVY_AFFINITY_CLASSC;
}
else
{
// bad parse;
goto end;
}
}
else if (!_wcsicmp(Name, L"load"))
{
if (swscanf(Value, L"%u", &load)!=1)
{
if (load > 100)
{
// bad parse;
goto end;
}
}
}
else if (!_wcsicmp(Name, L"priority"))
{
if (swscanf(Value, L"%u", &priority)!=1)
{
if (priority > 31)
{
// bad parse;
goto end;
}
}
}
else
{
// bad parse
goto end;
}
printf("SUCCESSFUL PARSE: %ws = %ws\n", Name, Value);
}
//
// Set up the PARAMS structure, doing extra parameter validation along the
// way.
//
switch(mode)
{
case CVY_SINGLE:
if (load != INVALID_VALUE || affinity != INVALID_VALUE)
{
goto end; // bad parse;
}
if ((priority < CVY_MIN_PRIORITY) || (priority > CVY_MAX_PRIORITY))
{
goto end; // bad parse
}
pPr->mode_data.single.priority = priority;
break;
case CVY_MULTI:
if (priority != INVALID_VALUE)
{
goto end; // bad parse;
}
switch(affinity)
{
case CVY_AFFINITY_NONE:
break;
case CVY_AFFINITY_SINGLE:
break;
case CVY_AFFINITY_CLASSC:
break;
case INVALID_VALUE:
default:
goto end; // bad parse;
}
pPr->mode_data.multi.affinity = affinity;
if (load == INVALID_VALUE)
{
// this means it's unassigned, which means equal.
pPr->mode_data.multi.equal_load = 1;
}
else if (load > CVY_MAX_LOAD)
{
goto end; // bad parse
}
else
{
pPr->mode_data.multi.load = load;
}
break;
case CVY_NEVER:
if (load != INVALID_VALUE || affinity != INVALID_VALUE
|| priority != INVALID_VALUE)
{
goto end; // bad parse;
}
break;
case INVALID_VALUE:
default:
goto end; // bad parse;
}
pPr->mode = mode;
pPr->end_port = end_port;
pPr->start_port = start_port;
pPr->protocol = protocol;
fRet = TRUE;
end:
return fRet;
}