Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3725 lines
116 KiB

  1. /* Copyright (c) 1993, Microsoft Corporation, all rights reserved
  2. **
  3. ** rasipcp.c
  4. ** Remote Access PPP Internet Protocol Control Protocol
  5. ** Core routines
  6. **
  7. ** 11/05/93 Steve Cobb
  8. */
  9. #include <nt.h>
  10. #include <ntrtl.h>
  11. #include <nturtl.h>
  12. #include <windows.h>
  13. #include <lmcons.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <llinfo.h>
  17. #include <rasman.h>
  18. #include <ddwanarp.h>
  19. #include <rtutils.h>
  20. #include <dhcpcapi.h>
  21. #include <devioctl.h>
  22. #include <rasppp.h>
  23. #include <uiip.h>
  24. #include <pppcp.h>
  25. #define INCL_HOSTWIRE
  26. #define INCL_PARAMBUF
  27. #define INCL_RASAUTHATTRIBUTES
  28. #include <ppputil.h>
  29. #include <raserror.h>
  30. #include <mprlog.h>
  31. #include <dnsapi.h>
  32. #include "rassrvr.h"
  33. #include "tcpreg.h"
  34. #include "helper.h"
  35. #include "rastcp.h"
  36. #define RASIPCPGLOBALS
  37. #include "rasipcp.h"
  38. #define REGKEY_Ipcp \
  39. "SYSTEM\\CurrentControlSet\\Services\\RasMan\\PPP\\ControlProtocols\\BuiltIn"
  40. #define REGKEY_Params "SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\IP"
  41. #define REGKEY_Linkage "SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Linkage"
  42. #define REGKEY_Disabled "SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Linkage\\Disabled"
  43. #define REGVAL_NsAddrs "RequestNameServerAddresses"
  44. #define REGVAL_Unnumbered "Unnumbered"
  45. #define REGVAL_VjComp "RequestVJCompression"
  46. #define REGVAL_VjComp2 "AcceptVJCompression"
  47. #define REGVAL_AllowVJOverVPN "AllowVJOverVPN"
  48. #define REGVAL_HardIp "AllowClientIPAddresses"
  49. #define REGVAL_RegisterRoutersWithWINS "RegisterRoutersWithWINSServers"
  50. #define REGVAL_Bind "Bind"
  51. #define ID_NetBTNdisWan "NetBT_NdisWan"
  52. // DHCP Options. (from dhcp.h)
  53. // dhcp.h lives in the sockets project. These are standard and
  54. // cannot change, so its safe to put them here.
  55. #define OPTION_SUBNET_MASK 1
  56. #define OPTION_DNS_NAME_SERVERS 6
  57. #define OPTION_NETBIOS_NAME_SERVERS 44
  58. #define OPTION_DNS_DOMAIN_NAME 15
  59. #define OPTION_VENDOR_SPEC_INFO 43
  60. //Route Plumbing option
  61. #define OPTION_VENDOR_ROUTE_PLUMB 249
  62. #define CLASSA_ADDR(a) (( (*((unsigned char *)&(a))) & 0x80) == 0)
  63. #define CLASSB_ADDR(a) (( (*((unsigned char *)&(a))) & 0xc0) == 0x80)
  64. #define CLASSC_ADDR(a) (( (*((unsigned char *)&(a))) & 0xe0) == 0xc0)
  65. #define CLASSE_ADDR(a) ((( (*((uchar *)&(a))) & 0xf0) == 0xf0) && \
  66. ((a) != 0xffffffff))
  67. /* Gurdeepian dword byte-swapping macro.
  68. **
  69. ** Note that in this module all IP addresses are stored in on the net form
  70. ** which is the opposite of Intel format.
  71. */
  72. #define net_long(x) (((((unsigned long)(x))&0xffL)<<24) | \
  73. ((((unsigned long)(x))&0xff00L)<<8) | \
  74. ((((unsigned long)(x))&0xff0000L)>>8) | \
  75. ((((unsigned long)(x))&0xff000000L)>>24))
  76. typedef struct _IPCP_DHCP_INFORM
  77. {
  78. WCHAR* wszDevice;
  79. HCONN hConnection;
  80. BOOL fUseDhcpInformDomainName;
  81. } IPCP_DHCP_INFORM;
  82. /*---------------------------------------------------------------------------
  83. ** External entry points
  84. **---------------------------------------------------------------------------
  85. */
  86. DWORD
  87. IpcpInit(
  88. IN BOOL fInitialize)
  89. /* Called to initialize/uninitialize this CP. In the former case,
  90. ** fInitialize will be TRUE; in the latter case, it will be FALSE.
  91. */
  92. {
  93. static DWORD dwRefCount = 0;
  94. DWORD dwErr;
  95. if (fInitialize)
  96. {
  97. if (0 == dwRefCount)
  98. {
  99. if ((dwErr = HelperInitialize(&HDhcpDll)) != NO_ERROR)
  100. {
  101. return(dwErr);
  102. }
  103. PDhcpRequestOptions = (DHCPREQUESTOPTIONS)
  104. GetProcAddress(HDhcpDll, "DhcpRequestOptions");
  105. if (NULL == PDhcpRequestOptions)
  106. {
  107. return(GetLastError());
  108. }
  109. PDhcpNotifyConfigChange2 = (DHCPNOTIFYCONFIGCHANGEEX)
  110. GetProcAddress(HDhcpDll, "DhcpNotifyConfigChangeEx");
  111. if (NULL == PDhcpNotifyConfigChange2)
  112. {
  113. return(GetLastError());
  114. }
  115. PDhcpRequestParams = (DHCPREQUESTPARAMS)
  116. GetProcAddress(HDhcpDll, "DhcpRequestParams");
  117. if(NULL == PDhcpRequestParams)
  118. {
  119. return (GetLastError());
  120. }
  121. ClearTcpipInfo();
  122. DwIpcpTraceId = TraceRegister("RASIPCP");
  123. }
  124. dwRefCount++;
  125. }
  126. else
  127. {
  128. dwRefCount--;
  129. if (0 == dwRefCount)
  130. {
  131. HelperUninitialize();
  132. // Ignore errors
  133. HDhcpDll = NULL;
  134. PDhcpRequestOptions = NULL;
  135. PDhcpNotifyConfigChange2 = NULL;
  136. PDhcpRequestParams = NULL;
  137. if (HRasArp != INVALID_HANDLE_VALUE)
  138. CloseHandle( HRasArp );
  139. HRasArp = INVALID_HANDLE_VALUE;
  140. TraceDeregister(DwIpcpTraceId);
  141. DwIpcpTraceId = INVALID_TRACEID;
  142. }
  143. }
  144. return(NO_ERROR);
  145. }
  146. DWORD
  147. IpcpGetInfo(
  148. IN DWORD dwProtocolId,
  149. OUT PPPCP_INFO* pInfo )
  150. /* IpcpGetInfo entry point called by the PPP engine by name. See RasCp
  151. ** interface documentation.
  152. */
  153. {
  154. ZeroMemory( pInfo, sizeof(*pInfo) );
  155. pInfo->Protocol = (DWORD )PPP_IPCP_PROTOCOL;
  156. lstrcpy(pInfo->SzProtocolName, "IPCP");
  157. pInfo->Recognize = 7;
  158. pInfo->RasCpInit = IpcpInit;
  159. pInfo->RasCpBegin = IpcpBegin;
  160. pInfo->RasCpReset = IpcpReset;
  161. pInfo->RasCpEnd = IpcpEnd;
  162. pInfo->RasCpThisLayerFinished = IpcpThisLayerFinished;
  163. pInfo->RasCpThisLayerUp = IpcpThisLayerUp;
  164. pInfo->RasCpPreDisconnectCleanup = IpcpPreDisconnectCleanup;
  165. pInfo->RasCpMakeConfigRequest = IpcpMakeConfigRequest;
  166. pInfo->RasCpMakeConfigResult = IpcpMakeConfigResult;
  167. pInfo->RasCpConfigAckReceived = IpcpConfigAckReceived;
  168. pInfo->RasCpConfigNakReceived = IpcpConfigNakReceived;
  169. pInfo->RasCpConfigRejReceived = IpcpConfigRejReceived;
  170. pInfo->RasCpGetNegotiatedInfo = IpcpGetNegotiatedInfo;
  171. pInfo->RasCpProjectionNotification = IpcpProjectionNotification;
  172. pInfo->RasCpChangeNotification = IpcpChangeNotification;
  173. return 0;
  174. }
  175. DWORD
  176. IpcpChangeNotification(
  177. VOID )
  178. {
  179. HelperChangeNotification();
  180. return(NO_ERROR);
  181. }
  182. DWORD
  183. IpcpBegin(
  184. OUT VOID** ppWorkBuf,
  185. IN VOID* pInfo )
  186. /* RasCpBegin entry point called by the PPP engine thru the passed
  187. ** address. See RasCp interface documentation.
  188. */
  189. {
  190. DWORD dwErr;
  191. PPPCP_INIT* pInit = (PPPCP_INIT* )pInfo;
  192. IPCPWB* pwb;
  193. RAS_AUTH_ATTRIBUTE * pAttribute;
  194. BOOL fVPN = FALSE;
  195. BOOL fVJAttributePresent = FALSE;
  196. TraceIp("IPCP: IpcpBegin");
  197. /* Allocate work buffer.
  198. */
  199. if (!(pwb = (IPCPWB* )LocalAlloc( LPTR, sizeof(IPCPWB) )))
  200. {
  201. return( ERROR_NOT_ENOUGH_MEMORY );
  202. }
  203. pwb->fServer = pInit->fServer;
  204. pwb->hport = pInit->hPort;
  205. pwb->hConnection = pInit->hConnection;
  206. pwb->hIPInterface = pInit->hInterface;
  207. pwb->IfType = pInit->IfType;
  208. pwb->fDisableNetbt = pInit->fDisableNetbt;
  209. if (0 == MultiByteToWideChar(
  210. CP_ACP,
  211. 0,
  212. pInit->pszUserName,
  213. -1,
  214. pwb->wszUserName,
  215. UNLEN+1 ) )
  216. {
  217. dwErr = GetLastError();
  218. TraceIp("MultiByteToWideChar(%s) failed: %d",
  219. pInit->pszUserName, dwErr);
  220. LocalFree( pwb );
  221. return( dwErr );
  222. }
  223. if (0 == MultiByteToWideChar(
  224. CP_ACP,
  225. 0,
  226. pInit->pszPortName,
  227. -1,
  228. pwb->wszPortName,
  229. MAX_PORT_NAME+1 ) )
  230. {
  231. dwErr = GetLastError();
  232. TraceIp("MultiByteToWideChar(%s) failed: %d",
  233. pInit->pszPortName, dwErr);
  234. LocalFree( pwb );
  235. return( dwErr );
  236. }
  237. if ( pwb->fServer )
  238. {
  239. HKEY hkey;
  240. DWORD dwType;
  241. DWORD dwValue;
  242. DWORD cb = sizeof(DWORD);
  243. BOOL FClientMaySelectIpAddress = FALSE;
  244. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Params, &hkey ) == 0)
  245. {
  246. if (RegQueryValueEx(
  247. hkey, REGVAL_HardIp, NULL, &dwType,
  248. (LPBYTE )&dwValue, &cb ) == 0
  249. && dwType == REG_DWORD
  250. && cb == sizeof(DWORD)
  251. && dwValue)
  252. {
  253. FClientMaySelectIpAddress = TRUE;
  254. }
  255. RegCloseKey( hkey );
  256. }
  257. TraceIp("IPCP: Hard IP=%d",FClientMaySelectIpAddress);
  258. pwb->IpAddressToHandout = ( FClientMaySelectIpAddress )
  259. ? net_long( 0xFFFFFFFF )
  260. : net_long( 0xFFFFFFFE );
  261. //
  262. // Is there an IP address parameter ?
  263. //
  264. pAttribute = RasAuthAttributeGet( raatFramedIPAddress,
  265. pInit->pAttributes );
  266. if ( pAttribute != NULL )
  267. {
  268. pwb->IpAddressToHandout = net_long( PtrToUlong(pAttribute->Value) );
  269. TraceIp("IPCP: Using IP address attribute 0x%x",
  270. pwb->IpAddressToHandout );
  271. }
  272. }
  273. else
  274. {
  275. //
  276. // We are a router or client dialing out, let other side always choose
  277. // their address
  278. //
  279. pwb->IpAddressToHandout = net_long( 0xFFFFFFFF );
  280. }
  281. pwb->fRegisterWithWINS = 1;
  282. if ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  283. {
  284. HKEY hkey;
  285. DWORD dwType;
  286. DWORD dwValue;
  287. DWORD cb = sizeof(DWORD);
  288. pwb->fRegisterWithWINS = 0;
  289. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Ipcp, &hkey ) == 0)
  290. {
  291. if (RegQueryValueEx(
  292. hkey, REGVAL_RegisterRoutersWithWINS, NULL,
  293. &dwType, (LPBYTE )&dwValue, &cb ) == 0
  294. && dwType == REG_DWORD
  295. && cb == sizeof(DWORD)
  296. && dwValue != 0)
  297. {
  298. TraceIp("IPCP: Will register routers with WINS");
  299. pwb->fRegisterWithWINS = 1;
  300. }
  301. RegCloseKey( hkey );
  302. }
  303. }
  304. /* Allocate a route between the MAC and the TCP/IP stack.
  305. */
  306. if ((dwErr = RasAllocateRoute(
  307. pwb->hport, IP, !pwb->fServer, &pwb->routeinfo )) != 0)
  308. {
  309. TraceIp("IPCP: RasAllocateRoute=%d",dwErr);
  310. LocalFree( (HLOCAL )pwb );
  311. return dwErr;
  312. }
  313. /* Lookup the compression capabilities.
  314. */
  315. if ((dwErr = RasPortGetProtocolCompression(
  316. pwb->hport, IP, &pwb->rpcSend, &pwb->rpcReceive )) != 0)
  317. {
  318. TraceIp("IPCP: RasPortGetProtocolCompression=%d",dwErr);
  319. pwb->dwErrInBegin = dwErr;
  320. *ppWorkBuf = pwb;
  321. return 0;
  322. }
  323. if (0 == pwb->rpcSend.RP_ProtocolType.RP_IP.RP_IPCompressionProtocol)
  324. {
  325. HKEY hkey;
  326. DWORD dwType;
  327. DWORD dwValue;
  328. DWORD cb = sizeof(DWORD);
  329. fVPN = TRUE;
  330. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Ipcp, &hkey ) == 0)
  331. {
  332. /* VJ header compression is a history based scheme and since
  333. we can't reliably detect lost frames over vpn's we have
  334. dropped support for vj over vpn's.
  335. */
  336. if (RegQueryValueEx(
  337. hkey, REGVAL_AllowVJOverVPN, NULL,
  338. &dwType, (LPBYTE )&dwValue, &cb ) == 0
  339. && dwType == REG_DWORD
  340. && cb == sizeof(DWORD)
  341. && dwValue == 1)
  342. {
  343. TraceIp("IPCP: AllowVJOverVPN is TRUE");
  344. pwb->rpcSend.RP_ProtocolType.RP_IP.RP_IPCompressionProtocol = 0x2D;
  345. pwb->rpcReceive.RP_ProtocolType.RP_IP.RP_IPCompressionProtocol = 0x2D;
  346. fVPN = FALSE;
  347. }
  348. RegCloseKey( hkey );
  349. }
  350. }
  351. if ( pwb->fServer )
  352. {
  353. HANDLE hAttribute;
  354. pAttribute = RasAuthAttributeGetFirst(raatFramedCompression,
  355. pInit->pAttributes, &hAttribute );
  356. while (NULL != pAttribute)
  357. {
  358. switch (PtrToUlong(pAttribute->Value))
  359. {
  360. case 0:
  361. /* Don't request or accept VJ compression.
  362. */
  363. TraceIp("IPCP: VJ disabled by RADIUS");
  364. pwb->fIpCompressionRejected = TRUE;
  365. memset( &pwb->rpcSend, '\0', sizeof(pwb->rpcSend) );
  366. fVJAttributePresent = TRUE;
  367. break;
  368. case 1:
  369. TraceIp("IPCP: VJ required by RADIUS");
  370. fVJAttributePresent = TRUE;
  371. break;
  372. default:
  373. break;
  374. }
  375. if (fVJAttributePresent)
  376. {
  377. break;
  378. }
  379. pAttribute = RasAuthAttributeGetNext(&hAttribute,
  380. raatFramedCompression);
  381. }
  382. }
  383. if (fVJAttributePresent)
  384. {
  385. // Nothing
  386. }
  387. else if (fVPN)
  388. {
  389. TraceIp("IPCP: VJ disabled for VPN");
  390. pwb->fIpCompressionRejected = TRUE;
  391. memset( &pwb->rpcSend, '\0', sizeof(pwb->rpcSend) );
  392. }
  393. else
  394. {
  395. /* Look up "request VJ compresion" flag in registry.
  396. */
  397. {
  398. HKEY hkey;
  399. DWORD dwType;
  400. DWORD dwValue;
  401. DWORD cb = sizeof(DWORD);
  402. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Ipcp, &hkey ) == 0)
  403. {
  404. if (RegQueryValueEx(
  405. hkey, REGVAL_VjComp, NULL,
  406. &dwType, (LPBYTE )&dwValue, &cb ) == 0
  407. && dwType == REG_DWORD
  408. && cb == sizeof(DWORD)
  409. && dwValue == 0)
  410. {
  411. TraceIp("IPCP: VJ requests disabled");
  412. pwb->fIpCompressionRejected = TRUE;
  413. }
  414. RegCloseKey( hkey );
  415. }
  416. }
  417. /* Look up "accept VJ compresion" flag in registry.
  418. */
  419. {
  420. HKEY hkey;
  421. DWORD dwType;
  422. DWORD dwValue;
  423. DWORD cb = sizeof(DWORD);
  424. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Ipcp, &hkey ) == 0)
  425. {
  426. if (RegQueryValueEx(
  427. hkey, REGVAL_VjComp2, NULL,
  428. &dwType, (LPBYTE )&dwValue, &cb ) == 0
  429. && dwType == REG_DWORD
  430. && cb == sizeof(DWORD)
  431. && dwValue == 0)
  432. {
  433. TraceIp("IPCP: VJ will not be accepted");
  434. memset( &pwb->rpcSend, '\0', sizeof(pwb->rpcSend) );
  435. }
  436. RegCloseKey( hkey );
  437. }
  438. }
  439. }
  440. TraceIp("IPCP: Compress capabilities: s=$%x,%d,%d r=$%x,%d,%d",
  441. (int)Protocol(pwb->rpcSend),(int)MaxSlotId(pwb->rpcSend),
  442. (int)CompSlotId(pwb->rpcSend),(int)Protocol(pwb->rpcReceive),
  443. (int)MaxSlotId(pwb->rpcReceive),CompSlotId(pwb->rpcReceive));
  444. //
  445. // If we are receiving a call from a client or another router, or we
  446. // are a router dialing out.
  447. //
  448. if ( ( pwb->fServer ) ||
  449. ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) )
  450. {
  451. /* Look up the DNS server, WINS server, and "this server" addresses.
  452. ** This is done once at the beginning since these addresses are the
  453. ** same for a given route regardless of the IP addresses.
  454. */
  455. TraceIp("IPCP: Server address lookup...");
  456. TraceIp("IPCP: RasSrvrQueryServerAddresses...");
  457. dwErr = RasSrvrQueryServerAddresses( &(pwb->IpInfoRemote) );
  458. TraceIp("IPCP: RasSrvrQueryServerAddresses done(%d)",dwErr);
  459. if (dwErr != 0)
  460. {
  461. pwb->dwErrInBegin = dwErr;
  462. *ppWorkBuf = pwb;
  463. return 0;
  464. }
  465. else
  466. {
  467. TraceIp("IPCP:Dns=%08x,Wins=%08x,DnsB=%08x,WinsB=%08x,"
  468. "Server=%08x,Mask=%08x",
  469. pwb->IpInfoRemote.nboDNSAddress,
  470. pwb->IpInfoRemote.nboWINSAddress,
  471. pwb->IpInfoRemote.nboDNSAddressBackup,
  472. pwb->IpInfoRemote.nboWINSAddressBackup,
  473. pwb->IpInfoRemote.nboServerIpAddress,
  474. pwb->IpInfoRemote.nboServerSubnetMask);
  475. }
  476. //
  477. // If this is not a router interface, then we use the server address
  478. // as a local address
  479. //
  480. if ( ( pwb->fServer ) && ( pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER ) )
  481. {
  482. /* Request server's own IP address. (RAS client's don't care what
  483. ** the server's address is, but some other vendors like
  484. ** MorningStar won't connect unless you tell them)
  485. */
  486. pwb->IpAddressLocal = pwb->IpInfoRemote.nboServerIpAddress;
  487. }
  488. }
  489. //
  490. // We are a client\router dialing out or a router dialing in,
  491. //
  492. if ( ( !pwb->fServer ) || ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) )
  493. {
  494. //
  495. // See if registry indicates "no WINS/DNS requests" mode for clients
  496. // dialing out.
  497. //
  498. HKEY hkey;
  499. DWORD dwType;
  500. DWORD dwValue;
  501. DWORD cb = sizeof(DWORD);
  502. if ( RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Ipcp, &hkey ) == 0)
  503. {
  504. if ( RegQueryValueEx(
  505. hkey, REGVAL_NsAddrs, NULL,
  506. &dwType, (LPBYTE )&dwValue, &cb ) == 0
  507. && dwType == REG_DWORD
  508. && cb == sizeof(DWORD)
  509. && dwValue == 0)
  510. {
  511. TraceIp("IPCP: WINS/DNS requests disabled");
  512. pwb->fIpaddrDnsRejected = TRUE;
  513. pwb->fIpaddrWinsRejected = TRUE;
  514. pwb->fIpaddrDnsBackupRejected = TRUE;
  515. pwb->fIpaddrWinsBackupRejected = TRUE;
  516. }
  517. RegCloseKey( hkey );
  518. }
  519. /* Read the parameters sent from the UI in the parameters buffer.
  520. */
  521. pwb->fPrioritizeRemote = TRUE;
  522. if (pInit->pszzParameters)
  523. {
  524. DWORD dwIpSource;
  525. CHAR szIpAddress[ 16 ];
  526. WCHAR wszIpAddress[ 16 ];
  527. BOOL fVjCompression;
  528. DWORD dwDnsFlags;
  529. CHAR szDnsSuffix[DNS_SUFFIX_SIZE + 1];
  530. TraceIp("IPCP: UI parameters...");
  531. DUMPB(pInit->pszzParameters,PARAMETERBUFLEN);
  532. FindFlagInParamBuf(
  533. pInit->pszzParameters, PBUFKEY_IpPrioritizeRemote,
  534. &pwb->fPrioritizeRemote );
  535. pwb->fUnnumbered = FALSE;
  536. if ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  537. {
  538. if ( RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Ipcp, &hkey ) == 0)
  539. {
  540. if ( RegQueryValueEx(
  541. hkey, REGVAL_Unnumbered, NULL,
  542. &dwType, (LPBYTE )&dwValue, &cb ) == 0
  543. && dwType == REG_DWORD
  544. && cb == sizeof(DWORD)
  545. && dwValue != 0)
  546. {
  547. TraceIp("Unnumbered");
  548. pwb->fUnnumbered = TRUE;
  549. }
  550. RegCloseKey( hkey );
  551. }
  552. }
  553. {
  554. if (FindLongInParamBuf(
  555. pInit->pszzParameters, PBUFKEY_IpDnsFlags,
  556. &dwDnsFlags ))
  557. {
  558. if (dwDnsFlags & 0x1)
  559. {
  560. pwb->fRegisterWithDNS = 1;
  561. }
  562. if ( (dwDnsFlags & 0x2)
  563. || (dwDnsFlags & 0x4) )
  564. {
  565. pwb->fRegisterAdapterDomainName = 1;
  566. }
  567. }
  568. }
  569. {
  570. if (FindStringInParamBuf(
  571. pInit->pszzParameters, PBUFKEY_IpDnsSuffix,
  572. szDnsSuffix, DNS_SUFFIX_SIZE + 1 ))
  573. {
  574. strncpy(pwb->szDnsSuffix, szDnsSuffix, DNS_SUFFIX_SIZE);
  575. }
  576. }
  577. {
  578. fVjCompression = TRUE;
  579. FindFlagInParamBuf(
  580. pInit->pszzParameters, PBUFKEY_IpVjCompression,
  581. &fVjCompression );
  582. if (!fVjCompression)
  583. {
  584. /* Don't request or accept VJ compression.
  585. */
  586. TraceIp("IPCP: VJ disabled");
  587. pwb->fIpCompressionRejected = TRUE;
  588. memset( &pwb->rpcSend, '\0', sizeof(pwb->rpcSend) );
  589. }
  590. }
  591. if( !pwb->fIpCompressionRejected
  592. && !Protocol(pwb->rpcReceive))
  593. {
  594. pwb->fIpCompressionRejected = TRUE;
  595. }
  596. dwIpSource = PBUFVAL_ServerAssigned;
  597. FindLongInParamBuf(
  598. pInit->pszzParameters, PBUFKEY_IpAddressSource,
  599. &dwIpSource );
  600. if (dwIpSource == PBUFVAL_RequireSpecific)
  601. {
  602. if (FindStringInParamBuf(
  603. pInit->pszzParameters, PBUFKEY_IpAddress,
  604. szIpAddress, 16 ))
  605. {
  606. mbstowcs( wszIpAddress, szIpAddress, 16 );
  607. pwb->IpAddressLocal
  608. = IpAddressFromAbcdWsz( wszIpAddress );
  609. }
  610. }
  611. dwIpSource = PBUFVAL_ServerAssigned;
  612. FindLongInParamBuf(
  613. pInit->pszzParameters, PBUFKEY_IpNameAddressSource,
  614. &dwIpSource );
  615. if (dwIpSource == PBUFVAL_RequireSpecific)
  616. {
  617. //
  618. //check to see if DNS or WINS or both have been
  619. //requested specific and set the flags accordingly
  620. //so that we only request proper addresses
  621. //from the server
  622. //
  623. if (FindStringInParamBuf(
  624. pInit->pszzParameters, PBUFKEY_IpDnsAddress,
  625. szIpAddress, 16 ))
  626. {
  627. mbstowcs( wszIpAddress, szIpAddress, 16 );
  628. pwb->IpInfoLocal.nboDNSAddress
  629. = IpAddressFromAbcdWsz( wszIpAddress );
  630. }
  631. if (FindStringInParamBuf(
  632. pInit->pszzParameters, PBUFKEY_IpDns2Address,
  633. szIpAddress, 16 ))
  634. {
  635. mbstowcs( wszIpAddress, szIpAddress, 16 );
  636. pwb->IpInfoLocal.nboDNSAddressBackup
  637. = IpAddressFromAbcdWsz( wszIpAddress );
  638. }
  639. if (FindStringInParamBuf(
  640. pInit->pszzParameters, PBUFKEY_IpWinsAddress,
  641. szIpAddress, 16 ))
  642. {
  643. mbstowcs( wszIpAddress, szIpAddress, 16 );
  644. pwb->IpInfoLocal.nboWINSAddress
  645. = IpAddressFromAbcdWsz( wszIpAddress );
  646. }
  647. if (FindStringInParamBuf(
  648. pInit->pszzParameters, PBUFKEY_IpWins2Address,
  649. szIpAddress, 16 ))
  650. {
  651. mbstowcs( wszIpAddress, szIpAddress, 16 );
  652. pwb->IpInfoLocal.nboWINSAddressBackup
  653. = IpAddressFromAbcdWsz( wszIpAddress );
  654. }
  655. if ( pwb->IpInfoLocal.nboDNSAddress ||
  656. pwb->IpInfoLocal.nboDNSAddressBackup
  657. )
  658. {
  659. //Specific DNS address has been passed in
  660. pwb->fIpaddrDnsRejected = TRUE;
  661. pwb->fIpaddrDnsBackupRejected = TRUE;
  662. }
  663. if ( pwb->IpInfoLocal.nboWINSAddress ||
  664. pwb->IpInfoLocal.nboWINSAddressBackup
  665. )
  666. {
  667. //Specific WINS address has been requested
  668. pwb->fIpaddrWinsRejected = TRUE;
  669. pwb->fIpaddrWinsBackupRejected = TRUE;
  670. }
  671. }
  672. }
  673. TraceIp( "IPCP:a=%08x,f=%d",
  674. pwb->IpAddressLocal,pwb->fPrioritizeRemote);
  675. }
  676. /* Register work buffer with engine.
  677. */
  678. *ppWorkBuf = pwb;
  679. return 0;
  680. }
  681. DWORD
  682. IpcpThisLayerFinished(
  683. IN VOID* pWorkBuf )
  684. /* RasCpThisLayerFinished entry point called by the PPP engine thru the
  685. ** passed address. See RasCp interface documentation.
  686. */
  687. {
  688. DWORD dwErr = 0;
  689. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  690. TraceIp("IPCP: IpcpThisLayerFinished...");
  691. //
  692. // If this is a server or a router dialing in or out then we release this
  693. // address
  694. //
  695. if ( ( pwb->fServer ) ||
  696. ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER ))
  697. {
  698. if (pwb->IpAddressRemote != 0)
  699. {
  700. TraceIp("IPCP: RasSrvrReleaseAddress...");
  701. RasSrvrReleaseAddress(pwb->IpAddressRemote,
  702. pwb->wszUserName,
  703. pwb->wszPortName,
  704. ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) ?
  705. FALSE : TRUE);
  706. TraceIp("IPCP: RasSrvrReleaseAddress done");
  707. pwb->IpAddressRemote = 0;
  708. }
  709. //
  710. // Set ConfigActive to false only for server
  711. //
  712. if ( ( pwb->fServer ) &&
  713. ( pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER ))
  714. {
  715. pwb->fRasConfigActive = FALSE;
  716. }
  717. }
  718. //
  719. // If we are a client dialing out or a router dialing in or out then we
  720. // notify DHCP of releasing this address.
  721. //
  722. if ( ( !pwb->fServer ) ||
  723. ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER ))
  724. {
  725. dwErr = DeActivateRasConfig( pwb );
  726. if (dwErr == 0)
  727. {
  728. pwb->fRasConfigActive = FALSE;
  729. }
  730. }
  731. if (pwb->fRouteActivated)
  732. {
  733. TraceIp("IPCP: RasDeAllocateRoute...");
  734. RasDeAllocateRoute( pwb->hConnection, IP );
  735. pwb->fRouteActivated = FALSE;
  736. }
  737. if ( pwb->pbDhcpRoutes )
  738. {
  739. //Parse the dhcp routes and remove the routes from stack
  740. TraceIp("IPCP: RasDeAllocateDhcpRoute...");
  741. RasTcpSetDhcpRoutes ( pwb->pbDhcpRoutes , pwb->IpAddressLocal, FALSE );
  742. LocalFree (pwb->pbDhcpRoutes );
  743. pwb->pbDhcpRoutes = NULL;
  744. }
  745. TraceIp("IPCP: IpcpThisLayerFinished done(%d)",dwErr);
  746. return dwErr;
  747. }
  748. DWORD
  749. IpcpEnd(
  750. IN VOID* pWorkBuf )
  751. /* RasCpEnd entry point called by the PPP engine thru the passed address.
  752. ** See RasCp interface documentation.
  753. */
  754. {
  755. DWORD dwErr = 0;
  756. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  757. TraceIp("IPCP: IpcpEnd...");
  758. dwErr = IpcpThisLayerFinished( pWorkBuf );
  759. LocalFree( (HLOCAL )pWorkBuf );
  760. TraceIp("IPCP: IpcpEnd done(%d)",dwErr);
  761. return dwErr;
  762. }
  763. DWORD
  764. IpcpReset(
  765. IN VOID* pWorkBuf )
  766. /* Called to reset negotiations. See RasCp interface documentation.
  767. **
  768. ** Returns 0 if successful, otherwise a non-0 error code.
  769. */
  770. {
  771. /* RasPpp.dll requires this to exist even though it does nothing
  772. ** (complaints to Gibbs).
  773. */
  774. return 0;
  775. }
  776. DWORD
  777. IpcpThisLayerUp(
  778. IN VOID* pWorkBuf )
  779. /* Called when the CP is entering Open state. See RasCp interface
  780. ** documentation.
  781. **
  782. ** Returns 0 if successful, otherwise a non-0 error code.
  783. */
  784. {
  785. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  786. TraceIp("IPCP: IpcpThisLayerUp");
  787. if (pwb->fRasConfigActive || pwb->fExpectingProjection)
  788. {
  789. TraceIp("IPCP: Link already up...ignored.");
  790. return 0;
  791. }
  792. /* Can't route until we know the result of the projection. Shouldn't
  793. ** activate until just before we route or WANARP reports errors. See
  794. ** IpcpProjectionResult.
  795. */
  796. pwb->fExpectingProjection = TRUE;
  797. TraceIp("IPCP: IpcpThisLayerUp done");
  798. return 0;
  799. }
  800. DWORD
  801. IpcpPreDisconnectCleanup(
  802. IN VOID* pWorkBuf )
  803. {
  804. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  805. DWORD dwErr = NO_ERROR;
  806. TraceIp("IPCP: IpcpPreDisconnectCleanup");
  807. if ( ( pwb->fServer )
  808. || ( pwb->pwszDevice == NULL )
  809. || ( !pwb->fRegisterWithDNS ))
  810. {
  811. return( NO_ERROR );
  812. }
  813. if ( ( dwErr = ResetNetBTConfigInfo( pwb ) ) != NO_ERROR )
  814. {
  815. TraceIp("IPCP: ResetNetBTConfigInfo=%d",dwErr);
  816. }
  817. else
  818. {
  819. if ((dwErr = ReconfigureTcpip( pwb->pwszDevice, FALSE, 0, 0)) != 0)
  820. {
  821. TraceIp("IPCP: ReconfigureTcpip=%d", dwErr);
  822. }
  823. }
  824. return(dwErr);
  825. }
  826. DWORD
  827. IpcpMakeConfigRequest(
  828. IN VOID* pWorkBuf,
  829. OUT PPP_CONFIG* pSendBuf,
  830. IN DWORD cbSendBuf )
  831. /* Makes a configure-request packet in 'pSendBuf'. See RasCp interface
  832. ** documentation.
  833. **
  834. ** Returns 0 if successful, otherwise a non-0 error code.
  835. */
  836. {
  837. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  838. WORD cbPacket = PPP_CONFIG_HDR_LEN;
  839. BYTE* pbThis = pSendBuf->Data;
  840. TraceIp("IPCP: IpcpMakeConfigRequest");
  841. RTASSERT(cbSendBuf>PPP_CONFIG_HDR_LEN+(IPADDRESSOPTIONLEN*3));
  842. if (pwb->dwErrInBegin != 0)
  843. {
  844. TraceIp("IPCP: Deferred IpcpBegin error=%d",pwb->dwErrInBegin);
  845. return pwb->dwErrInBegin;
  846. }
  847. if (++pwb->cRequestsWithoutResponse >= 5)
  848. {
  849. TraceIp("IPCP: Tossing MS options (request timeouts)");
  850. pwb->fTryWithoutExtensions = TRUE;
  851. pwb->fIpaddrDnsRejected = TRUE;
  852. pwb->fIpaddrWinsRejected = TRUE;
  853. pwb->fIpaddrDnsBackupRejected = TRUE;
  854. pwb->fIpaddrWinsBackupRejected = TRUE;
  855. }
  856. if (!pwb->fIpCompressionRejected )
  857. {
  858. /* Request IP compression for both client and server.
  859. */
  860. AddIpCompressionOption( pbThis, &pwb->rpcReceive );
  861. cbPacket += IPCOMPRESSIONOPTIONLEN;
  862. pbThis += IPCOMPRESSIONOPTIONLEN;
  863. }
  864. //
  865. // We always negotiate this option, it will be 0 for clients and routers
  866. // dialing out and routers dialing in, it will be the server's address
  867. // for clients dialing in. We don't negotiate this option if we want
  868. // unnumbered IPCP.
  869. //
  870. if (!pwb->fIpaddrRejected && !pwb->fUnnumbered)
  871. {
  872. AddIpAddressOption(
  873. pbThis, OPTION_IpAddress, pwb->IpAddressLocal );
  874. cbPacket += IPADDRESSOPTIONLEN;
  875. pbThis += IPADDRESSOPTIONLEN;
  876. }
  877. //
  878. // If we are client dialing out we need WINS and DNS addresses
  879. //
  880. if ( !pwb->fServer )
  881. {
  882. /* The client asks the server to provide a DNS address and WINS
  883. ** address (and depending on user's UI selections, an IP address) by
  884. ** sending 0's for these options.
  885. */
  886. if (!pwb->fIpaddrDnsRejected)
  887. {
  888. AddIpAddressOption(
  889. pbThis, OPTION_DnsIpAddress,
  890. pwb->IpInfoLocal.nboDNSAddress );
  891. cbPacket += IPADDRESSOPTIONLEN;
  892. pbThis += IPADDRESSOPTIONLEN;
  893. }
  894. if (!pwb->fIpaddrWinsRejected)
  895. {
  896. AddIpAddressOption(
  897. pbThis, OPTION_WinsIpAddress,
  898. pwb->IpInfoLocal.nboWINSAddress );
  899. cbPacket += IPADDRESSOPTIONLEN;
  900. pbThis += IPADDRESSOPTIONLEN;
  901. }
  902. if (!pwb->fIpaddrDnsBackupRejected)
  903. {
  904. AddIpAddressOption(
  905. pbThis, OPTION_DnsBackupIpAddress,
  906. pwb->IpInfoLocal.nboDNSAddressBackup );
  907. cbPacket += IPADDRESSOPTIONLEN;
  908. pbThis += IPADDRESSOPTIONLEN;
  909. }
  910. if (!pwb->fIpaddrWinsBackupRejected)
  911. {
  912. AddIpAddressOption(
  913. pbThis, OPTION_WinsBackupIpAddress,
  914. pwb->IpInfoLocal.nboWINSAddressBackup );
  915. cbPacket += IPADDRESSOPTIONLEN;
  916. }
  917. }
  918. pSendBuf->Code = CONFIG_REQ;
  919. HostToWireFormat16( cbPacket, pSendBuf->Length );
  920. TraceIp("IPCP: ConfigRequest...");
  921. DUMPB(pSendBuf,cbPacket);
  922. return 0;
  923. }
  924. DWORD
  925. IpcpMakeConfigResult(
  926. IN VOID* pWorkBuf,
  927. IN PPP_CONFIG* pReceiveBuf,
  928. OUT PPP_CONFIG* pSendBuf,
  929. IN DWORD cbSendBuf,
  930. IN BOOL fRejectNaks )
  931. /* Makes a configure-ack, -nak, or -reject packet in 'pSendBuf'. See
  932. ** RasCp interface documentation.
  933. **
  934. ** Implements the Stefanian rule, i.e. accept only configure requests that
  935. ** exactly match the previously acknowledged request after this layer up
  936. ** has been called. This is necessary because the RAS route cannot be
  937. ** deallocated when the port is open (NDISWAN driver limitation), so
  938. ** renegotiation with different parameters is not possible once the route
  939. ** has been activated.
  940. **
  941. ** Returns 0 if successful, otherwise a non-0 error code.
  942. */
  943. {
  944. DWORD dwErr;
  945. BOOL f;
  946. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  947. TraceIp("IPCP: IpcpMakeConfigResult for...");
  948. DUMPB(pReceiveBuf,(pReceiveBuf)?WireToHostFormat16(pReceiveBuf->Length):0);
  949. pwb->cRequestsWithoutResponse = 0;
  950. /* Check if there's reason to reject the request and if so, do it.
  951. */
  952. if ((dwErr = RejectCheck(
  953. pwb, pReceiveBuf, pSendBuf, cbSendBuf, &f )) != 0)
  954. {
  955. TraceIp("IPCP: ConfigResult...");
  956. DUMPB(pSendBuf,WireToHostFormat16(pSendBuf->Length));
  957. return dwErr;
  958. }
  959. if (f)
  960. return (pwb->fRasConfigActive) ? ERROR_PPP_NOT_CONVERGING : 0;
  961. /* Check if there's reason to nak the request and if so, do it (or
  962. ** reject instead of nak if indicated by engine).
  963. */
  964. if ((dwErr = NakCheck(
  965. pwb, pReceiveBuf, pSendBuf, cbSendBuf, &f, fRejectNaks )) != 0)
  966. {
  967. TraceIp("IPCP: ConfigResult...");
  968. DUMPB(pSendBuf,WireToHostFormat16(pSendBuf->Length));
  969. return dwErr;
  970. }
  971. if (f)
  972. return (pwb->fRasConfigActive) ? ERROR_PPP_NOT_CONVERGING : 0;
  973. /* Acknowledge the request.
  974. */
  975. {
  976. WORD cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  977. CopyMemory( pSendBuf, pReceiveBuf, cbPacket );
  978. pSendBuf->Code = CONFIG_ACK;
  979. }
  980. TraceIp("IPCP: ConfigResult...");
  981. DUMPB(pSendBuf,WireToHostFormat16(pSendBuf->Length));
  982. return 0;
  983. }
  984. DWORD
  985. IpcpConfigAckReceived(
  986. IN VOID* pWorkBuf,
  987. IN PPP_CONFIG* pReceiveBuf )
  988. /* Examines received configure-ack in 'pReceiveBuf'. See RasCp interface
  989. ** documentation.
  990. **
  991. ** Returns 0 if successful, otherwise a non-0 error code.
  992. */
  993. {
  994. DWORD dwErr = 0;
  995. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  996. WORD cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  997. WORD cbLeft = cbPacket - PPP_CONFIG_HDR_LEN;
  998. PPP_OPTION UNALIGNED* pROption = (PPP_OPTION UNALIGNED* )pReceiveBuf->Data;
  999. BOOL fIpCompressionOk = pwb->fIpCompressionRejected;
  1000. BOOL fIpaddrOk = pwb->fIpaddrRejected || pwb->fUnnumbered;
  1001. BOOL fIpaddrDnsOk = pwb->fIpaddrDnsRejected;
  1002. BOOL fIpaddrWinsOk = pwb->fIpaddrWinsRejected;
  1003. BOOL fIpaddrDnsBackupOk = pwb->fIpaddrDnsBackupRejected;
  1004. BOOL fIpaddrWinsBackupOk = pwb->fIpaddrWinsBackupRejected;
  1005. TraceIp("IPCP: IpcpConfigAckReceived...");
  1006. DUMPB(pReceiveBuf,cbPacket);
  1007. pwb->cRequestsWithoutResponse = 0;
  1008. while (cbLeft > 0)
  1009. {
  1010. if (cbLeft < pROption->Length)
  1011. return ERROR_PPP_INVALID_PACKET;
  1012. if (pROption->Type == OPTION_IpCompression)
  1013. {
  1014. WORD wProtocol;
  1015. if (pROption->Length != IPCOMPRESSIONOPTIONLEN)
  1016. return ERROR_PPP_INVALID_PACKET;
  1017. wProtocol = WireToHostFormat16U(pROption->Data );
  1018. if (wProtocol != Protocol(pwb->rpcReceive)
  1019. || pROption->Data[ 2 ] != MaxSlotId(pwb->rpcReceive)
  1020. || pROption->Data[ 3 ] != CompSlotId(pwb->rpcReceive))
  1021. {
  1022. return ERROR_PPP_INVALID_PACKET;
  1023. }
  1024. fIpCompressionOk = TRUE;
  1025. }
  1026. else if (pROption->Type == OPTION_IpAddress)
  1027. {
  1028. IPADDR ipaddr;
  1029. if (pROption->Length != IPADDRESSOPTIONLEN)
  1030. return ERROR_PPP_INVALID_PACKET;
  1031. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  1032. if (ipaddr != 0 && ipaddr == pwb->IpAddressLocal )
  1033. fIpaddrOk = TRUE;
  1034. }
  1035. else if (!pwb->fServer)
  1036. {
  1037. //
  1038. // We are a client dialing out
  1039. //
  1040. switch (pROption->Type)
  1041. {
  1042. case OPTION_DnsIpAddress:
  1043. {
  1044. IPADDR ipaddr;
  1045. if (pROption->Length != IPADDRESSOPTIONLEN)
  1046. return ERROR_PPP_INVALID_PACKET;
  1047. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  1048. if (ipaddr == pwb->IpInfoLocal.nboDNSAddress)
  1049. fIpaddrDnsOk = TRUE;
  1050. break;
  1051. }
  1052. case OPTION_WinsIpAddress:
  1053. {
  1054. IPADDR ipaddr;
  1055. if (pROption->Length != IPADDRESSOPTIONLEN)
  1056. return ERROR_PPP_INVALID_PACKET;
  1057. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  1058. if (ipaddr == pwb->IpInfoLocal.nboWINSAddress)
  1059. fIpaddrWinsOk = TRUE;
  1060. break;
  1061. }
  1062. case OPTION_DnsBackupIpAddress:
  1063. {
  1064. IPADDR ipaddr;
  1065. if (pROption->Length != IPADDRESSOPTIONLEN)
  1066. return ERROR_PPP_INVALID_PACKET;
  1067. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  1068. if (ipaddr == pwb->IpInfoLocal.nboDNSAddressBackup)
  1069. {
  1070. fIpaddrDnsBackupOk = TRUE;
  1071. }
  1072. break;
  1073. }
  1074. case OPTION_WinsBackupIpAddress:
  1075. {
  1076. IPADDR ipaddr;
  1077. if (pROption->Length != IPADDRESSOPTIONLEN)
  1078. return ERROR_PPP_INVALID_PACKET;
  1079. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  1080. if (ipaddr == pwb->IpInfoLocal.nboWINSAddressBackup)
  1081. {
  1082. fIpaddrWinsBackupOk = TRUE;
  1083. }
  1084. break;
  1085. }
  1086. default:
  1087. {
  1088. TraceIp("IPCP: Unrecognized option ACKed?");
  1089. return ERROR_PPP_INVALID_PACKET;
  1090. }
  1091. }
  1092. }
  1093. else
  1094. {
  1095. TraceIp("IPCP: Unrecognized option ACKed?");
  1096. return ERROR_PPP_INVALID_PACKET;
  1097. }
  1098. if (pROption->Length && pROption->Length < cbLeft)
  1099. cbLeft -= pROption->Length;
  1100. else
  1101. cbLeft = 0;
  1102. pROption = (PPP_OPTION* )((BYTE* )pROption + pROption->Length);
  1103. }
  1104. if ( !fIpCompressionOk
  1105. || !fIpaddrOk
  1106. || ( !pwb->fServer
  1107. && ( !fIpaddrDnsOk
  1108. || !fIpaddrWinsOk
  1109. || !fIpaddrDnsBackupOk
  1110. || !fIpaddrWinsBackupOk)))
  1111. {
  1112. dwErr = ERROR_PPP_INVALID_PACKET;
  1113. }
  1114. TraceIp("IPCP: IpcpConfigAckReceived done(%d)",dwErr);
  1115. return dwErr;
  1116. }
  1117. DWORD
  1118. IpcpConfigNakReceived(
  1119. IN VOID* pWorkBuf,
  1120. IN PPP_CONFIG* pReceiveBuf )
  1121. /* Examines received configure-nak in 'pReceiveBuf'. See RasCp interface
  1122. ** documentation.
  1123. **
  1124. ** Returns 0 if successful, otherwise a non-0 error code.
  1125. */
  1126. {
  1127. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  1128. PPP_OPTION* pROption = (PPP_OPTION* )pReceiveBuf->Data;
  1129. WORD cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  1130. WORD cbLeft = cbPacket - PPP_CONFIG_HDR_LEN;
  1131. TraceIp("IPCP: IpcpConfigNakReceived");
  1132. TraceIp("IPCP: Nak received...");
  1133. DUMPB(pReceiveBuf,(pReceiveBuf)?WireToHostFormat16(pReceiveBuf->Length):0);
  1134. pwb->cRequestsWithoutResponse = 0;
  1135. while (cbLeft > 0)
  1136. {
  1137. if (cbLeft < pROption->Length)
  1138. return ERROR_PPP_INVALID_PACKET;
  1139. if (pROption->Type == OPTION_IpCompression)
  1140. {
  1141. WORD wProtocol = WireToHostFormat16( pROption->Data );
  1142. if (wProtocol == COMPRESSION_VanJacobson)
  1143. {
  1144. /* He can send Van Jacobson but not with the slot parameters
  1145. ** we suggested.
  1146. */
  1147. if (pROption->Length != IPCOMPRESSIONOPTIONLEN)
  1148. return ERROR_PPP_INVALID_PACKET;
  1149. if (pROption->Data[ 2 ] <= MaxSlotId(pwb->rpcReceive))
  1150. {
  1151. /* We can accept his suggested MaxSlotID when it is less
  1152. ** than or the same as what we can do.
  1153. */
  1154. MaxSlotId(pwb->rpcReceive) = pROption->Data[ 2 ];
  1155. }
  1156. if (CompSlotId(pwb->rpcReceive))
  1157. {
  1158. /* We can compress the slot-ID or not, so just accept
  1159. ** whatever he wants to do.
  1160. */
  1161. CompSlotId(pwb->rpcReceive) = pROption->Data[ 3 ];
  1162. }
  1163. }
  1164. }
  1165. else if ( ( !pwb->fServer ) ||
  1166. ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) )
  1167. {
  1168. switch (pROption->Type)
  1169. {
  1170. case OPTION_IpAddress:
  1171. {
  1172. IPADDR ipaddr;
  1173. if (pROption->Length != IPADDRESSOPTIONLEN)
  1174. return ERROR_PPP_INVALID_PACKET;
  1175. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  1176. if (ipaddr == 0)
  1177. {
  1178. if (pwb->IpAddressLocal == 0)
  1179. {
  1180. /* Server naked us with zero when we asked it to
  1181. ** assign us an address, meaning he doesn't know
  1182. ** how to assign us an address but we can provide
  1183. ** an alternate address if we want. Currently we
  1184. ** don't support a backup address here.
  1185. */
  1186. return ERROR_PPP_NO_ADDRESS_ASSIGNED;
  1187. }
  1188. else
  1189. {
  1190. /* Server naked us with zero when we asked for a
  1191. ** specific address, meaning he doesn't know how
  1192. ** to assign us an address but we can provide an
  1193. ** alternate address if we want. Currently we
  1194. ** don't support a backup address here.
  1195. */
  1196. return ERROR_PPP_REQUIRED_ADDRESS_REJECTED;
  1197. }
  1198. }
  1199. if (pwb->IpAddressLocal != 0)
  1200. {
  1201. /* We asked for a specific address (per user's
  1202. ** instructions) but server says we can't have it and
  1203. ** is trying to give us another. No good, tell user
  1204. ** we can't get the address he requires.
  1205. */
  1206. return ERROR_PPP_REQUIRED_ADDRESS_REJECTED;
  1207. }
  1208. /* Accept the address suggested by server.
  1209. */
  1210. pwb->IpAddressLocal = ipaddr;
  1211. break;
  1212. }
  1213. case OPTION_DnsIpAddress:
  1214. {
  1215. if (pROption->Length != IPADDRESSOPTIONLEN)
  1216. return ERROR_PPP_INVALID_PACKET;
  1217. //
  1218. // Use this only if we asked for it
  1219. //
  1220. if ( !pwb->fIpaddrDnsRejected )
  1221. {
  1222. /* Accept the DNS address suggested by server.
  1223. */
  1224. CopyMemory( &pwb->IpInfoLocal.nboDNSAddress,
  1225. pROption->Data, sizeof(IPADDR) );
  1226. }
  1227. break;
  1228. }
  1229. case OPTION_WinsIpAddress:
  1230. {
  1231. if (pROption->Length != IPADDRESSOPTIONLEN)
  1232. return ERROR_PPP_INVALID_PACKET;
  1233. //
  1234. // Use this only if we asked for it
  1235. //
  1236. if ( !pwb->fIpaddrWinsRejected )
  1237. {
  1238. /* Accept the WINS address suggested by server.
  1239. */
  1240. CopyMemory( &pwb->IpInfoLocal.nboWINSAddress,
  1241. pROption->Data, sizeof(IPADDR) );
  1242. }
  1243. break;
  1244. }
  1245. case OPTION_DnsBackupIpAddress:
  1246. {
  1247. if (pROption->Length != IPADDRESSOPTIONLEN)
  1248. return ERROR_PPP_INVALID_PACKET;
  1249. //
  1250. // Use this only if we asked for it
  1251. //
  1252. if ( !pwb->fIpaddrDnsBackupRejected )
  1253. {
  1254. /* Accept the DNS backup address suggested by server.
  1255. */
  1256. CopyMemory( &pwb->IpInfoLocal.nboDNSAddressBackup,
  1257. pROption->Data, sizeof(IPADDR) );
  1258. }
  1259. break;
  1260. }
  1261. case OPTION_WinsBackupIpAddress:
  1262. {
  1263. if (pROption->Length != IPADDRESSOPTIONLEN)
  1264. return ERROR_PPP_INVALID_PACKET;
  1265. //
  1266. // Use this only if we asked for it
  1267. //
  1268. if ( !pwb->fIpaddrWinsBackupRejected )
  1269. {
  1270. /* Accept the WINS backup address suggested by server.
  1271. */
  1272. CopyMemory( &pwb->IpInfoLocal.nboWINSAddressBackup,
  1273. pROption->Data, sizeof(IPADDR) );
  1274. }
  1275. break;
  1276. }
  1277. default:
  1278. TraceIp("IPCP: Unrequested option NAKed?");
  1279. break;
  1280. }
  1281. }
  1282. if (pROption->Length && pROption->Length < cbLeft)
  1283. cbLeft -= pROption->Length;
  1284. else
  1285. cbLeft = 0;
  1286. pROption = (PPP_OPTION* )((BYTE* )pROption + pROption->Length);
  1287. }
  1288. return 0;
  1289. }
  1290. DWORD
  1291. IpcpConfigRejReceived(
  1292. IN VOID* pWorkBuf,
  1293. IN PPP_CONFIG* pReceiveBuf )
  1294. /* Examines received configure-reject in 'pReceiveBuf'. See RasCp
  1295. ** interface documentation.
  1296. **
  1297. ** Returns 0 if successful, otherwise a non-0 error code.
  1298. */
  1299. {
  1300. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  1301. PPP_OPTION* pROption = (PPP_OPTION* )pReceiveBuf->Data;
  1302. WORD cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  1303. WORD cbLeft = cbPacket - PPP_CONFIG_HDR_LEN;
  1304. TraceIp("IPCP: IpcpConfigRejReceived");
  1305. TraceIp("IPCP: Rej received...");
  1306. DUMPB(pReceiveBuf,(pReceiveBuf)?WireToHostFormat16(pReceiveBuf->Length):0);
  1307. pwb->cRequestsWithoutResponse = 0;
  1308. while (cbLeft > 0)
  1309. {
  1310. if (pROption->Type == OPTION_IpCompression)
  1311. {
  1312. TraceIp("IPCP: IP compression was rejected");
  1313. pwb->fIpCompressionRejected = TRUE;
  1314. Protocol(pwb->rpcReceive) = 0;
  1315. MaxSlotId(pwb->rpcReceive) = 0;
  1316. CompSlotId(pwb->rpcReceive) = 0;
  1317. }
  1318. else if ( ( pwb->fServer ) &&
  1319. ( pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER ) )
  1320. {
  1321. switch (pROption->Type)
  1322. {
  1323. case OPTION_IpAddress:
  1324. {
  1325. /* He can't handle a server address option. No problem,
  1326. ** it's informational only.
  1327. */
  1328. TraceIp("IPCP: Server IP address was rejected");
  1329. pwb->fIpaddrRejected = TRUE;
  1330. break;
  1331. }
  1332. default:
  1333. TraceIp("IPCP: Unrequested option rejected?");
  1334. break;
  1335. }
  1336. }
  1337. else
  1338. {
  1339. switch (pROption->Type)
  1340. {
  1341. case OPTION_IpAddress:
  1342. {
  1343. TraceIp("IPCP: IP was rejected");
  1344. if (pwb->IpAddressLocal != 0)
  1345. {
  1346. /* We accept rejection of the IP address if we know
  1347. ** what address we want to use and use it anyway.
  1348. ** Some router implementations require a
  1349. ** certain IP address but can't handle this option to
  1350. ** confirm that.
  1351. */
  1352. pwb->fIpaddrRejected = TRUE;
  1353. break;
  1354. }
  1355. if ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  1356. {
  1357. pwb->fUnnumbered = TRUE;
  1358. break;
  1359. }
  1360. else if (pwb->fTryWithoutExtensions)
  1361. {
  1362. /* He doesn't know how to give us an IP address, but
  1363. ** we can't accept no for an answer. Have to bail.
  1364. */
  1365. return ERROR_PPP_NO_ADDRESS_ASSIGNED;
  1366. }
  1367. else
  1368. {
  1369. /* When we request that server assign us an address,
  1370. ** this is a required option. If it's rejected assume
  1371. ** all the Microsoft extension options were rejected
  1372. ** and try again. Other vendors will not test this
  1373. ** case explicitly and may have bugs in their reject
  1374. ** code.
  1375. */
  1376. TraceIp("IPCP: Tossing MS options (no address)");
  1377. pwb->fTryWithoutExtensions = TRUE;
  1378. pwb->fIpaddrDnsRejected = TRUE;
  1379. pwb->fIpaddrWinsRejected = TRUE;
  1380. pwb->fIpaddrDnsBackupRejected = TRUE;
  1381. pwb->fIpaddrWinsBackupRejected = TRUE;
  1382. return 0;
  1383. }
  1384. }
  1385. case OPTION_DnsIpAddress:
  1386. {
  1387. /* He doesn't know how to give us a DNS address, but we
  1388. ** can live with that.
  1389. */
  1390. TraceIp("IPCP: DNS was rejected");
  1391. pwb->fIpaddrDnsRejected = TRUE;
  1392. break;
  1393. }
  1394. case OPTION_WinsIpAddress:
  1395. {
  1396. /* He doesn't know how to give us a WINS address, but we
  1397. ** can live with that.
  1398. */
  1399. TraceIp("IPCP: WINS was rejected");
  1400. pwb->fIpaddrWinsRejected = TRUE;
  1401. break;
  1402. }
  1403. case OPTION_DnsBackupIpAddress:
  1404. {
  1405. /* He doesn't know how to give us a backup DNS address,
  1406. ** but we can live with that.
  1407. */
  1408. TraceIp("IPCP: DNS backup was rejected");
  1409. pwb->fIpaddrDnsBackupRejected = TRUE;
  1410. break;
  1411. }
  1412. case OPTION_WinsBackupIpAddress:
  1413. {
  1414. /* He doesn't know how to give us a backup WINS address,
  1415. ** but we can live with that.
  1416. */
  1417. TraceIp("IPCP: WINS backup was rejected");
  1418. pwb->fIpaddrWinsBackupRejected = TRUE;
  1419. break;
  1420. }
  1421. default:
  1422. TraceIp("IPCP: Unrequested option rejected?");
  1423. break;
  1424. }
  1425. }
  1426. if (pROption->Length && pROption->Length <= cbLeft)
  1427. cbLeft -= pROption->Length;
  1428. else
  1429. {
  1430. if (pwb->fTryWithoutExtensions)
  1431. cbLeft = 0;
  1432. else
  1433. {
  1434. /* If an invalid packet is detected, assume all the Microsoft
  1435. ** extension options were rejected and try again. Other
  1436. ** vendors will not test this case explicitly and may have
  1437. ** bugs in their reject code.
  1438. */
  1439. TraceIp("IPCP: Tossing MS options (length)");
  1440. pwb->fTryWithoutExtensions = TRUE;
  1441. pwb->fIpaddrDnsRejected = TRUE;
  1442. pwb->fIpaddrWinsRejected = TRUE;
  1443. pwb->fIpaddrDnsBackupRejected = TRUE;
  1444. pwb->fIpaddrWinsBackupRejected = TRUE;
  1445. return 0;
  1446. }
  1447. }
  1448. pROption = (PPP_OPTION* )((BYTE* )pROption + pROption->Length);
  1449. }
  1450. return 0;
  1451. }
  1452. DWORD
  1453. IpcpGetNegotiatedInfo(
  1454. IN VOID* pWorkBuf,
  1455. OUT PPP_IPCP_RESULT * pIpCpResult
  1456. )
  1457. /* Returns the negotiated IP address in string form followed by the
  1458. ** server's IP address, if known. The two addresses are null-terminated
  1459. ** strings in back to back 15 + 1 character arrays.
  1460. **
  1461. ** Returns 0 if successful, otherwise a non-0 error code. "No address
  1462. ** active" is considered successful, and an empty address string is
  1463. ** returned.
  1464. */
  1465. {
  1466. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  1467. TraceIp("IPCP: IpcpGetNetworkAddress...");
  1468. if (pwb->fRasConfigActive || pwb->fExpectingProjection)
  1469. {
  1470. pIpCpResult->fSendVJHCompression = Protocol(pwb->rpcSend);
  1471. pIpCpResult->fReceiveVJHCompression = Protocol(pwb->rpcReceive);
  1472. pIpCpResult->dwLocalAddress = pwb->IpAddressLocal;
  1473. pIpCpResult->dwLocalWINSAddress = pwb->IpInfoLocal.nboWINSAddress;
  1474. pIpCpResult->dwLocalWINSBackupAddress
  1475. = pwb->IpInfoLocal.nboWINSAddressBackup;
  1476. pIpCpResult->dwLocalDNSAddress = pwb->IpInfoLocal.nboDNSAddress;
  1477. pIpCpResult->dwLocalDNSBackupAddress
  1478. = pwb->IpInfoLocal.nboDNSAddressBackup;
  1479. pIpCpResult->dwRemoteAddress = pwb->IpAddressRemote;
  1480. pIpCpResult->dwRemoteWINSAddress = pwb->IpInfoRemote.nboWINSAddress;
  1481. pIpCpResult->dwRemoteWINSBackupAddress
  1482. = pwb->IpInfoRemote.nboWINSAddressBackup;
  1483. pIpCpResult->dwRemoteDNSAddress = pwb->IpInfoRemote.nboDNSAddress;
  1484. pIpCpResult->dwRemoteDNSBackupAddress
  1485. = pwb->IpInfoRemote.nboDNSAddressBackup;
  1486. }
  1487. TraceIp("IPCP: IpcpGetNetworkAddress done");
  1488. return 0;
  1489. }
  1490. DWORD
  1491. IpcpDhcpInform(
  1492. IN IPCPWB* pwb,
  1493. IN PPP_DHCP_INFORM* pDhcpInform)
  1494. {
  1495. TCPIP_INFO* ptcpip = NULL;
  1496. IPADDR nboMask;
  1497. IPADDR nboIpAddr;
  1498. DWORD dwErr;
  1499. DWORD dwDomainNameSize;
  1500. size_t size;
  1501. DWORD dwIndex;
  1502. // Get current TCPIP setup info from registry.
  1503. TraceIp("IpcpDhcpInform:LoadTcpipInfo(Device=%ws)",pDhcpInform->wszDevice);
  1504. dwErr = LoadTcpipInfo( &ptcpip, pDhcpInform->wszDevice,
  1505. FALSE /* fAdapterOnly */ );
  1506. TraceIp("IpcpDhcpInform:LoadTcpipInfo done(%d)",dwErr);
  1507. if (dwErr != 0)
  1508. {
  1509. goto LDone;
  1510. }
  1511. TraceIp("IpcpDhcpInform: Old Dns=%ws",
  1512. ptcpip->wszDNSNameServers ? ptcpip->wszDNSNameServers : L"");
  1513. for (dwIndex = 0; dwIndex < pDhcpInform->dwNumDNSAddresses; dwIndex++)
  1514. {
  1515. dwErr = PrependDwIpAddress(
  1516. &ptcpip->wszDNSNameServers,
  1517. pDhcpInform->pdwDNSAddresses[dwIndex]);
  1518. if (dwErr)
  1519. {
  1520. TraceIp("IpcpDhcpInform: PrependDwIpAddress done(%d)",dwErr);
  1521. goto LDone;
  1522. }
  1523. }
  1524. TraceIp("IpcpDhcpInform: New Dns=%ws",
  1525. ptcpip->wszDNSNameServers ? ptcpip->wszDNSNameServers : L"");
  1526. if (pDhcpInform->dwWINSAddress1)
  1527. {
  1528. PrintMwsz("IpcpDhcpInform: Old Wins=", ptcpip->mwszNetBIOSNameServers);
  1529. if (pDhcpInform->dwWINSAddress2)
  1530. {
  1531. dwErr = PrependDwIpAddressToMwsz(
  1532. &ptcpip->mwszNetBIOSNameServers,
  1533. pDhcpInform->dwWINSAddress2);
  1534. if (dwErr)
  1535. {
  1536. TraceIp("IpcpDhcpInform: PrependDwIpAddress done(%d)",dwErr);
  1537. goto LDone;
  1538. }
  1539. }
  1540. dwErr = PrependDwIpAddressToMwsz(
  1541. &ptcpip->mwszNetBIOSNameServers,
  1542. pDhcpInform->dwWINSAddress1);
  1543. if (dwErr)
  1544. {
  1545. TraceIp("IpcpDhcpInform: PrependDwIpAddress done(%d)",dwErr);
  1546. goto LDone;
  1547. }
  1548. PrintMwsz("IpcpDhcpInform: New Wins=", ptcpip->mwszNetBIOSNameServers);
  1549. }
  1550. if (pDhcpInform->szDomainName)
  1551. {
  1552. dwDomainNameSize = strlen(pDhcpInform->szDomainName) + 1;
  1553. LocalFree(ptcpip->wszDNSDomainName);
  1554. ptcpip->wszDNSDomainName = LocalAlloc(LPTR, sizeof(WCHAR) * dwDomainNameSize);
  1555. if (NULL == ptcpip->wszDNSDomainName)
  1556. {
  1557. dwErr = GetLastError();
  1558. TraceIp("IpcpDhcpInform: LocalAlloc done(%d)", dwErr);
  1559. goto LDone;
  1560. }
  1561. if (0 == MultiByteToWideChar(
  1562. CP_ACP,
  1563. 0,
  1564. pDhcpInform->szDomainName,
  1565. -1,
  1566. ptcpip->wszDNSDomainName,
  1567. dwDomainNameSize ) )
  1568. {
  1569. dwErr = GetLastError();
  1570. TraceIp("IpcpDhcpInform: Error %d converting domain name %s",
  1571. dwErr,
  1572. pDhcpInform->szDomainName);
  1573. goto LDone;
  1574. }
  1575. }
  1576. ptcpip->fDisableNetBIOSoverTcpip = pwb->fDisableNetbt;
  1577. // Set TCPIP setup info in registry and release the buffer.
  1578. TraceIp("IpcpDhcpInform: SaveTcpipInfo...");
  1579. dwErr = SaveTcpipInfo( ptcpip );
  1580. TraceIp("IpcpDhcpInform: SaveTcpipInfo done(%d)",dwErr);
  1581. if (dwErr != 0)
  1582. {
  1583. goto LDone;
  1584. }
  1585. dwErr = ReconfigureTcpip(pDhcpInform->wszDevice, FALSE, 0, 0);
  1586. if (NO_ERROR != dwErr)
  1587. {
  1588. TraceIp("IpcpDhcpInform: ReconfigureTcpip=%d",dwErr);
  1589. goto LDone;
  1590. }
  1591. nboIpAddr = pwb->IpAddressLocal;
  1592. if ( !pwb->fPrioritizeRemote )
  1593. {
  1594. // We have added this route only if there is
  1595. // no default route and so remove it if
  1596. // there is no default route
  1597. // Remove the old route with the guessed mask
  1598. nboMask = RasTcpDeriveMask(nboIpAddr);
  1599. if (nboMask != 0)
  1600. {
  1601. RasTcpSetRoute(
  1602. nboIpAddr & nboMask,
  1603. nboIpAddr,
  1604. nboMask,
  1605. nboIpAddr,
  1606. FALSE,
  1607. 1,
  1608. TRUE);
  1609. }
  1610. }
  1611. // Add the new route with the precise mask
  1612. nboMask = pDhcpInform->dwSubnetMask;
  1613. if (nboMask != 0)
  1614. {
  1615. RasTcpSetRoute(
  1616. nboIpAddr & nboMask,
  1617. nboIpAddr,
  1618. nboMask,
  1619. nboIpAddr,
  1620. TRUE,
  1621. 1,
  1622. TRUE);
  1623. }
  1624. pwb->dwNumDNSAddresses = pDhcpInform->dwNumDNSAddresses;
  1625. pwb->pdwDNSAddresses = pDhcpInform->pdwDNSAddresses;
  1626. if ( pDhcpInform->pbDhcpRoutes )
  1627. {
  1628. //Parse the dhcp routes and plumb ths stack
  1629. RasTcpSetDhcpRoutes ( pDhcpInform->pbDhcpRoutes, pwb->IpAddressLocal, TRUE );
  1630. pwb->pbDhcpRoutes = pDhcpInform->pbDhcpRoutes;
  1631. }
  1632. LDone:
  1633. FreeTcpipInfo(&ptcpip);
  1634. return(dwErr);
  1635. }
  1636. DWORD
  1637. ResetNetBTConfigInfo(
  1638. IN IPCPWB* pwb )
  1639. /*
  1640. ** Will reset all the NetBT information in the registry to 0
  1641. */
  1642. {
  1643. TCPIP_INFO* ptcpip = NULL;
  1644. DWORD dwErr;
  1645. /* Get current TCPIP setup info from registry.
  1646. */
  1647. TraceIp("IPCP: LoadTcpipInfo...");
  1648. dwErr = LoadTcpipInfo( &ptcpip, pwb->pwszDevice, TRUE /* fAdapterOnly */ );
  1649. TraceIp("IPCP: LoadTcpipInfo done(%d)",dwErr);
  1650. if (dwErr)
  1651. {
  1652. goto LDone;
  1653. }
  1654. ptcpip->fChanged = TRUE ;
  1655. /* Set TCPIP setup info in registry and release the buffer.
  1656. */
  1657. TraceIp("IPCP: SaveTcpipInfo...");
  1658. dwErr = SaveTcpipInfo( ptcpip );
  1659. TraceIp("IPCP: SaveTcpipInfo done(%d)",dwErr);
  1660. LDone:
  1661. FreeTcpipInfo( &ptcpip );
  1662. pwb->dwNumDNSAddresses = 0;
  1663. LocalFree(pwb->pdwDNSAddresses);
  1664. pwb->pdwDNSAddresses = NULL;
  1665. return( dwErr );
  1666. }
  1667. VOID
  1668. DhcpInform(
  1669. PVOID pContext
  1670. )
  1671. {
  1672. IPCP_DHCP_INFORM* pIpcpDhcpInform = (IPCP_DHCP_INFORM*)pContext;
  1673. PPPE_MESSAGE PppMessage;
  1674. DWORD dwIndex;
  1675. DWORD dwCurOffset;
  1676. DWORD dwDomainNameSize;
  1677. DWORD dwNumDNSAddresses = 0;
  1678. IPADDR* pnboDNSAddresses = NULL;
  1679. IPADDR nboWINSAddress1 = 0;
  1680. IPADDR nboWINSAddress2 = 0;
  1681. IPADDR nboSubnetMask = 0;
  1682. CHAR* szDomainName = NULL;
  1683. //
  1684. // Route Information obtained from DHCP option 133
  1685. //
  1686. PBYTE pbRouteInfo = NULL;
  1687. DWORD dwErr;
  1688. BOOL fFree = TRUE;
  1689. BOOL fSendMessage = FALSE;
  1690. int i;
  1691. DHCPCAPI_PARAMS DhcpRequestedOptions[6] =
  1692. {
  1693. {
  1694. 0,
  1695. OPTION_DNS_NAME_SERVERS,
  1696. FALSE,
  1697. NULL,
  1698. 0
  1699. },
  1700. {
  1701. 0,
  1702. OPTION_NETBIOS_NAME_SERVERS,
  1703. FALSE,
  1704. NULL,
  1705. 0
  1706. },
  1707. {
  1708. 0,
  1709. OPTION_VENDOR_SPEC_INFO,
  1710. FALSE,
  1711. NULL,
  1712. 0
  1713. },
  1714. {
  1715. 0,
  1716. OPTION_SUBNET_MASK,
  1717. FALSE,
  1718. NULL,
  1719. 0
  1720. },
  1721. {
  1722. 0,
  1723. OPTION_VENDOR_ROUTE_PLUMB,
  1724. FALSE,
  1725. NULL,
  1726. 0
  1727. },
  1728. {
  1729. 0,
  1730. OPTION_DNS_DOMAIN_NAME,
  1731. FALSE,
  1732. NULL,
  1733. 0
  1734. }
  1735. };
  1736. DHCPCAPI_PARAMS_ARRAY DhcpRequestedOptionsArray =
  1737. {
  1738. 5,
  1739. DhcpRequestedOptions
  1740. };
  1741. DHCPCAPI_PARAMS_ARRAY DhcpSendOptionsArray =
  1742. {
  1743. 0,
  1744. NULL
  1745. };
  1746. PBYTE pRequestBuffer = NULL;
  1747. DWORD dwBufferSize = 2048;
  1748. DHCPCAPI_PARAMS *pParam;
  1749. if(pIpcpDhcpInform->fUseDhcpInformDomainName)
  1750. {
  1751. DhcpRequestedOptionsArray.nParams = 6;
  1752. }
  1753. //
  1754. // Allocate a 2k buffer upfront and pass it to the
  1755. // api. Loop allocating if buffer is not big enough.
  1756. //
  1757. pRequestBuffer = LocalAlloc(LPTR, dwBufferSize);
  1758. if(NULL == pRequestBuffer)
  1759. {
  1760. TraceIp("DhcpInform:LocalAlloc=%d", GetLastError());
  1761. goto LDhcpInformEnd;
  1762. }
  1763. TraceIp("DhcpRequestParams(%ws)...", pIpcpDhcpInform->wszDevice);
  1764. do
  1765. {
  1766. dwErr = PDhcpRequestParams(
  1767. DHCPCAPI_REQUEST_SYNCHRONOUS,
  1768. NULL,
  1769. pIpcpDhcpInform->wszDevice,
  1770. NULL,
  1771. DhcpSendOptionsArray,
  1772. DhcpRequestedOptionsArray,
  1773. pRequestBuffer,
  1774. &dwBufferSize,
  1775. NULL);
  1776. if(ERROR_MORE_DATA == dwErr)
  1777. {
  1778. LocalFree(pRequestBuffer);
  1779. pRequestBuffer = LocalAlloc(LPTR, dwBufferSize);
  1780. if(NULL == pRequestBuffer)
  1781. {
  1782. dwErr = GetLastError();
  1783. }
  1784. }
  1785. } while(ERROR_MORE_DATA == dwErr);
  1786. TraceIp("DhcpRequestParams done(%d)", dwErr);
  1787. if(NO_ERROR != dwErr)
  1788. {
  1789. goto LDhcpInformEnd;
  1790. }
  1791. //
  1792. // DhcpRequestParams fills in all the available parameters
  1793. // and leaves the other parameters alone. Since the
  1794. // parameters are NULL initialized, its fine to quit the
  1795. // for loop when we get the first parameter with NULL data
  1796. // or 0 nBytesData. This is per DHCP dev - information is not
  1797. // correct in msdn.
  1798. //
  1799. for(dwIndex = 0;
  1800. dwIndex < DhcpRequestedOptionsArray.nParams;
  1801. dwIndex++)
  1802. {
  1803. pParam = &DhcpRequestedOptions[dwIndex];
  1804. switch(pParam->OptionId)
  1805. {
  1806. case OPTION_DNS_DOMAIN_NAME:
  1807. dwDomainNameSize = pParam->nBytesData;
  1808. if(0 == dwDomainNameSize)
  1809. {
  1810. goto LDhcpInformEnd;
  1811. }
  1812. if(NULL != szDomainName)
  1813. {
  1814. LocalFree(szDomainName);
  1815. }
  1816. szDomainName = LocalAlloc(LPTR, dwDomainNameSize + 1);
  1817. if(NULL == szDomainName)
  1818. {
  1819. fSendMessage = FALSE;
  1820. TraceIp("DhcpInform: LocalAlloc=%d", GetLastError());
  1821. goto LDhcpInformEnd;
  1822. }
  1823. CopyMemory(szDomainName, pParam->Data, pParam->nBytesData);
  1824. fSendMessage = TRUE;
  1825. TraceIp("DhcpInform: DOMAIN_NAME %s", szDomainName);
  1826. break;
  1827. case OPTION_DNS_NAME_SERVERS:
  1828. if( 0 == pParam->nBytesData)
  1829. {
  1830. goto LDhcpInformEnd;
  1831. }
  1832. if(0 != (pParam->nBytesData % 4))
  1833. {
  1834. TraceIp("Invalid DOMAIN_NAME_SERVERS size %d",
  1835. pParam->nBytesData);
  1836. fSendMessage = FALSE;
  1837. goto LDhcpInformEnd;
  1838. }
  1839. if(NULL != pnboDNSAddresses)
  1840. {
  1841. LocalFree(pnboDNSAddresses);
  1842. dwNumDNSAddresses = 0;
  1843. }
  1844. pnboDNSAddresses = LocalAlloc(LPTR,
  1845. sizeof(IPADDR)
  1846. * pParam->nBytesData / 4);
  1847. if(NULL == pnboDNSAddresses)
  1848. {
  1849. fSendMessage = FALSE;
  1850. TraceIp("DhcpInform: LocalAlloc=%d', GetLastError()");
  1851. goto LDhcpInformEnd;
  1852. }
  1853. for(dwCurOffset = 0;
  1854. dwCurOffset < pParam->nBytesData;
  1855. dwCurOffset += 4, dwNumDNSAddresses++)
  1856. {
  1857. pnboDNSAddresses[dwNumDNSAddresses] =
  1858. (pParam->Data[dwCurOffset])
  1859. + (pParam->Data[dwCurOffset + 1] << 8)
  1860. + (pParam->Data[dwCurOffset + 2] << 16)
  1861. + (pParam->Data[dwCurOffset + 3] << 24);
  1862. TraceIp("DhcpInform: DOMAIN_NAME_SERVER 0x%x",
  1863. pnboDNSAddresses[dwNumDNSAddresses]);
  1864. fSendMessage = TRUE;
  1865. }
  1866. RTASSERT((pParam->nBytesData / 4) == dwNumDNSAddresses);
  1867. break;
  1868. case OPTION_NETBIOS_NAME_SERVERS:
  1869. if(0 == pParam->nBytesData)
  1870. {
  1871. goto LDhcpInformEnd;
  1872. }
  1873. if(0 != (pParam->nBytesData % 4))
  1874. {
  1875. fSendMessage = FALSE;
  1876. TraceIp("Invalid NETBIOS_NAME_SERVER size %d",
  1877. pParam->nBytesData);
  1878. goto LDhcpInformEnd;
  1879. }
  1880. dwCurOffset = 0;
  1881. for(i = 0; i < 2; i++)
  1882. {
  1883. IPADDR *paddr;
  1884. if(0 == i)
  1885. {
  1886. paddr = &nboWINSAddress1;
  1887. }
  1888. else
  1889. {
  1890. paddr = &nboWINSAddress2;
  1891. }
  1892. *paddr =
  1893. (pParam->Data[dwCurOffset])
  1894. + (pParam->Data[dwCurOffset + 1] << 8)
  1895. + (pParam->Data[dwCurOffset + 2] << 16)
  1896. + (pParam->Data[dwCurOffset + 3] << 24);
  1897. TraceIp("DhcpInform: NETBIOS_NAME_SERVER 0x%x",
  1898. *paddr);
  1899. fSendMessage = TRUE;
  1900. dwCurOffset += 4;
  1901. if(dwCurOffset == pParam->nBytesData)
  1902. {
  1903. break;
  1904. }
  1905. }
  1906. break;
  1907. case OPTION_SUBNET_MASK:
  1908. if(0 == pParam->nBytesData)
  1909. {
  1910. goto LDhcpInformEnd;
  1911. }
  1912. if(0 != (pParam->nBytesData % 4))
  1913. {
  1914. fSendMessage = FALSE;
  1915. TraceIp("Invalid OPTION_SUBNET_MASK size %d",
  1916. pParam->nBytesData);
  1917. goto LDhcpInformEnd;
  1918. }
  1919. nboSubnetMask = pParam->Data[0]
  1920. + (pParam->Data[1] << 8)
  1921. + (pParam->Data[2] << 16)
  1922. + (pParam->Data[3] << 24);
  1923. TraceIp("DhcpInform: OPTION_SUBNET_MASK 0x%x",
  1924. nboSubnetMask);
  1925. fSendMessage = TRUE;
  1926. break;
  1927. case OPTION_VENDOR_ROUTE_PLUMB:
  1928. if(0 == pParam->nBytesData)
  1929. {
  1930. goto LDhcpInformEnd;
  1931. }
  1932. //
  1933. // This option should be at least 5 bytes in length.
  1934. //
  1935. if(pParam->nBytesData < 5)
  1936. {
  1937. fSendMessage = FALSE;
  1938. TraceIp("Invalid OPTION_VENDOR_ROUTE_PLUMB size %d",
  1939. pParam->nBytesData);
  1940. goto LDhcpInformEnd;
  1941. }
  1942. TraceIp("DhcpInform: OPTION_VENDOR_ROUTE_PLUMB Code "
  1943. "Len 0x%x",
  1944. pParam->nBytesData);
  1945. pbRouteInfo = LocalAlloc(LPTR, pParam->nBytesData + sizeof(DWORD));
  1946. if(NULL == pbRouteInfo)
  1947. {
  1948. fSendMessage = FALSE;
  1949. TraceIp("DhcpInform: LocalAlloc=%d", GetLastError());
  1950. goto LDhcpInformEnd;
  1951. }
  1952. CopyMemory(pbRouteInfo + sizeof(DWORD),
  1953. pParam->Data, pParam->nBytesData);
  1954. *((DWORD *) pbRouteInfo) = pParam->nBytesData;
  1955. fSendMessage = TRUE;
  1956. break;
  1957. default:
  1958. break;
  1959. }
  1960. }
  1961. LDhcpInformEnd:
  1962. if (fSendMessage)
  1963. {
  1964. PppMessage.dwMsgId = PPPEMSG_DhcpInform;
  1965. PppMessage.hConnection = pIpcpDhcpInform->hConnection;
  1966. PppMessage.ExtraInfo.DhcpInform.wszDevice = pIpcpDhcpInform->wszDevice;
  1967. PppMessage.ExtraInfo.DhcpInform.dwNumDNSAddresses = dwNumDNSAddresses;
  1968. PppMessage.ExtraInfo.DhcpInform.pdwDNSAddresses = pnboDNSAddresses;
  1969. PppMessage.ExtraInfo.DhcpInform.dwWINSAddress1 = nboWINSAddress1;
  1970. PppMessage.ExtraInfo.DhcpInform.dwWINSAddress2 = nboWINSAddress2;
  1971. PppMessage.ExtraInfo.DhcpInform.dwSubnetMask = nboSubnetMask;
  1972. PppMessage.ExtraInfo.DhcpInform.szDomainName = szDomainName;
  1973. PppMessage.ExtraInfo.DhcpInform.pbDhcpRoutes = pbRouteInfo;
  1974. dwErr = SendPPPMessageToEngine(&PppMessage);
  1975. if (dwErr != NO_ERROR)
  1976. {
  1977. TraceIp("DhcpInform: SendPPPMessageToEngine=%d",dwErr);
  1978. goto LDhcpInformEnd;
  1979. }
  1980. fFree = FALSE;
  1981. }
  1982. if (fFree)
  1983. {
  1984. LocalFree(pIpcpDhcpInform->wszDevice);
  1985. LocalFree(pnboDNSAddresses);
  1986. LocalFree(szDomainName);
  1987. LocalFree(pbRouteInfo);
  1988. }
  1989. if(NULL != pRequestBuffer)
  1990. {
  1991. LocalFree(pRequestBuffer);
  1992. }
  1993. LocalFree(pIpcpDhcpInform);
  1994. }
  1995. DWORD
  1996. IpcpProjectionNotification(
  1997. IN VOID* pWorkBuf,
  1998. IN VOID* pProjectionResult )
  1999. /* Called when projection result of all CPs is known.
  2000. **
  2001. ** Returns 0 if successful, otherwise a non-0 error code.
  2002. */
  2003. {
  2004. DWORD dwErr = 0;
  2005. IPCPWB* pwb = (IPCPWB* )pWorkBuf;
  2006. BOOL fSetDefaultRoute = FALSE;
  2007. TraceIp("IPCP: IpcpProjectionNotification");
  2008. if (pwb->fExpectingProjection)
  2009. {
  2010. CHAR szBuf[sizeof(PROTOCOL_CONFIG_INFO) + sizeof(IP_WAN_LINKUP_INFO)];
  2011. PROTOCOL_CONFIG_INFO* pProtocol = (PROTOCOL_CONFIG_INFO* )szBuf;
  2012. IP_WAN_LINKUP_INFO UNALIGNED *pLinkUp = (PIP_WAN_LINKUP_INFO)pProtocol->P_Info;
  2013. PPP_PROJECTION_RESULT* p = (PPP_PROJECTION_RESULT* )pProjectionResult;
  2014. /* Activate the route between the TCP/IP stack and the RAS MAC.
  2015. */
  2016. pProtocol->P_Length = sizeof(IP_WAN_LINKUP_INFO);
  2017. pLinkUp->duUsage = ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  2018. ? DU_ROUTER
  2019. : (pwb->fServer) ? DU_CALLIN : DU_CALLOUT;
  2020. pLinkUp->dwUserIfIndex = HandleToULong(pwb->hIPInterface);
  2021. pLinkUp->dwLocalMask = 0xFFFFFFFF;
  2022. pLinkUp->dwLocalAddr = pwb->IpAddressLocal;
  2023. pLinkUp->dwRemoteAddr = pwb->IpAddressRemote;
  2024. pLinkUp->fFilterNetBios =
  2025. (pwb->fServer && p->nbf.dwError == 0);
  2026. pLinkUp->fDefaultRoute = pwb->fPrioritizeRemote;
  2027. TraceIp("IPCP: RasActivateRoute(u=%x,a=%x,nf=%d)...",
  2028. pLinkUp->duUsage,pLinkUp->dwLocalAddr,
  2029. pLinkUp->fFilterNetBios);
  2030. TraceIp("IPCP: RasActivateRoute ICB# == %d",
  2031. pLinkUp->dwUserIfIndex);
  2032. dwErr = RasActivateRoute(pwb->hport,IP,&pwb->routeinfo,pProtocol);
  2033. TraceIp("IPCP: RasActivateRoute done(%d)",dwErr);
  2034. if ( dwErr == 0 )
  2035. {
  2036. pwb->fRouteActivated = TRUE;
  2037. /* Find the device name within the adapter name, e.g. ndiswan00.
  2038. ** This is used to identify adapters in the TcpipInfo calls later.
  2039. */
  2040. pwb->pwszDevice = wcschr(&pwb->routeinfo.RI_AdapterName[1], L'\\');
  2041. if ( !pwb->pwszDevice )
  2042. {
  2043. TraceIp("IPCP: No device?");
  2044. dwErr = ERROR_INVALID_PARAMETER;
  2045. }
  2046. else
  2047. {
  2048. ++pwb->pwszDevice;
  2049. }
  2050. }
  2051. //
  2052. // If we are a client or a router dialing in or out we need to plumb
  2053. // the registry.
  2054. //
  2055. if ( ( dwErr == 0 ) &&
  2056. ((!pwb->fServer) || (pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER)))
  2057. {
  2058. do
  2059. {
  2060. TCPIP_INFO* ptcpip;
  2061. /* Get current TCPIP setup info from registry.
  2062. */
  2063. TraceIp("IPCP:LoadTcpipInfo(Device=%ws)",pwb->pwszDevice);
  2064. dwErr = LoadTcpipInfo( &ptcpip, pwb->pwszDevice,
  2065. TRUE /* fAdapterOnly */ );
  2066. TraceIp("IPCP: LoadTcpipInfo done(%d)",dwErr);
  2067. if (dwErr != 0)
  2068. break;
  2069. //
  2070. // We first save the IP address and call
  2071. // DhcpNotifyConfigChange, then set WINS/DNS and call
  2072. // DhcpNotifyConfigChange to work around Windows 2000 bug
  2073. // 381884.
  2074. //
  2075. AbcdWszFromIpAddress(pwb->IpAddressLocal, ptcpip->wszIPAddress);
  2076. AbcdWszFromIpAddress(pLinkUp->dwLocalMask, ptcpip->wszSubnetMask);
  2077. ptcpip->fDisableNetBIOSoverTcpip = pwb->fDisableNetbt;
  2078. ptcpip->fChanged = TRUE ;
  2079. TraceIp("IPCP: SaveTcpipInfo...");
  2080. dwErr = SaveTcpipInfo( ptcpip );
  2081. TraceIp("IPCP: SaveTcpipInfo done(%d)",dwErr);
  2082. if (dwErr)
  2083. {
  2084. ResetNetBTConfigInfo( pwb );
  2085. FreeTcpipInfo( &ptcpip );
  2086. break;
  2087. }
  2088. #if 0
  2089. if (!pwb->fUnnumbered)
  2090. {
  2091. /* Tell TCPIP components to reconfigure themselves.
  2092. */
  2093. if ((dwErr = ReconfigureTcpip(pwb->pwszDevice,
  2094. TRUE,
  2095. pwb->IpAddressLocal,
  2096. pLinkUp->dwLocalMask)) != NO_ERROR)
  2097. {
  2098. TraceIp("IPCP: ReconfigureTcpip=%d",dwErr);
  2099. ResetNetBTConfigInfo( pwb );
  2100. FreeTcpipInfo( &ptcpip );
  2101. break;
  2102. }
  2103. }
  2104. #endif
  2105. /* Make the LAN the default interface in multi-homed case.
  2106. */
  2107. if(pLinkUp->duUsage != DU_ROUTER)
  2108. {
  2109. BOOL fAddRoute = TRUE;
  2110. RASMAN_INFO *pInfo = LocalAlloc(LPTR, sizeof(RASMAN_INFO));
  2111. if(NULL != pInfo)
  2112. {
  2113. dwErr = RasGetInfo(NULL, pwb->hport, pInfo);
  2114. if(ERROR_SUCCESS != dwErr)
  2115. {
  2116. TraceIp("IPCP: HelperSetDefaultInterfaceNet, RasGetInfo "
  2117. "failed 0x%x", dwErr);
  2118. }
  2119. if(RAS_DEVICE_CLASS(pInfo->RI_rdtDeviceType)
  2120. == RDT_Tunnel)
  2121. {
  2122. fAddRoute = FALSE;
  2123. }
  2124. LocalFree(pInfo);
  2125. }
  2126. //
  2127. // Do the change metric and add subnet route stuff
  2128. // for non router cases only
  2129. //
  2130. TraceIp("IPCP: HelperSetDefaultInterfaceNet(a=%08x,f=%d)",
  2131. pwb->IpAddressLocal,pwb->fPrioritizeRemote);
  2132. dwErr = HelperSetDefaultInterfaceNet(
  2133. pwb->IpAddressLocal,
  2134. (fAddRoute) ?
  2135. pwb->IpAddressRemote :
  2136. 0,
  2137. pwb->fPrioritizeRemote,
  2138. pwb->pwszDevice);
  2139. TraceIp("IPCP: HelperSetDefaultInterfaceNet done(%d)",
  2140. dwErr);
  2141. if ( dwErr != NO_ERROR )
  2142. {
  2143. // ResetNetBTConfigInfo( pwb );
  2144. // FreeTcpipInfo( &ptcpip );
  2145. break;
  2146. }
  2147. fSetDefaultRoute = TRUE;
  2148. }
  2149. #if 0
  2150. /* Get current TCPIP setup info from registry.
  2151. */
  2152. TraceIp("IPCP:LoadTcpipInfo(Device=%ws)",pwb->pwszDevice);
  2153. dwErr = LoadTcpipInfo( &ptcpip, pwb->pwszDevice,
  2154. TRUE /* fAdapterOnly */ );
  2155. TraceIp("IPCP: LoadTcpipInfo done(%d)",dwErr);
  2156. if (dwErr != 0)
  2157. break;
  2158. AbcdWszFromIpAddress(pwb->IpAddressLocal, ptcpip->wszIPAddress);
  2159. AbcdWszFromIpAddress(pLinkUp->dwLocalMask, ptcpip->wszSubnetMask);
  2160. #endif
  2161. ptcpip->fChanged = FALSE ;
  2162. /* Add the negotiated DNS and backup DNS server (if any)
  2163. ** at the head of the list of DNS servers. (Backup is
  2164. ** done first so the the non-backup will wind up first)
  2165. */
  2166. if (pwb->IpInfoLocal.nboDNSAddressBackup)
  2167. {
  2168. dwErr = PrependDwIpAddress(
  2169. &ptcpip->wszDNSNameServers,
  2170. pwb->IpInfoLocal.nboDNSAddressBackup );
  2171. if (dwErr)
  2172. {
  2173. FreeTcpipInfo( &ptcpip );
  2174. break;
  2175. }
  2176. }
  2177. if (pwb->IpInfoLocal.nboDNSAddress)
  2178. {
  2179. dwErr = PrependDwIpAddress(
  2180. &ptcpip->wszDNSNameServers,
  2181. pwb->IpInfoLocal.nboDNSAddress );
  2182. if (dwErr)
  2183. {
  2184. FreeTcpipInfo( &ptcpip );
  2185. break;
  2186. }
  2187. }
  2188. TraceIp("IPCP: New Dns=%ws",
  2189. ptcpip->wszDNSNameServers ? ptcpip->wszDNSNameServers : L"");
  2190. if (!pwb->fRegisterWithWINS)
  2191. {
  2192. // Ignore the WINS server addresses. If we save them, then
  2193. // registration will happen automatically.
  2194. }
  2195. else
  2196. {
  2197. /* Set the WINS and backup WINS server addresses to
  2198. ** the negotiated addresses (if any).
  2199. */
  2200. if (pwb->IpInfoLocal.nboWINSAddressBackup)
  2201. {
  2202. dwErr = PrependDwIpAddressToMwsz(
  2203. &ptcpip->mwszNetBIOSNameServers,
  2204. pwb->IpInfoLocal.nboWINSAddressBackup );
  2205. if (dwErr)
  2206. {
  2207. FreeTcpipInfo( &ptcpip );
  2208. break;
  2209. }
  2210. }
  2211. if (pwb->IpInfoLocal.nboWINSAddress)
  2212. {
  2213. dwErr = PrependDwIpAddressToMwsz(
  2214. &ptcpip->mwszNetBIOSNameServers,
  2215. pwb->IpInfoLocal.nboWINSAddress );
  2216. if (dwErr)
  2217. {
  2218. FreeTcpipInfo( &ptcpip );
  2219. break;
  2220. }
  2221. }
  2222. PrintMwsz("IPCP: New Wins=",
  2223. ptcpip->mwszNetBIOSNameServers);
  2224. }
  2225. // The DNS API's are called in rasSrvrInitAdapterName also.
  2226. if (pwb->fRegisterWithDNS)
  2227. {
  2228. DnsEnableDynamicRegistration(pwb->pwszDevice);
  2229. TraceIp("DnsEnableDynamicRegistration");
  2230. }
  2231. else
  2232. {
  2233. DnsDisableDynamicRegistration(pwb->pwszDevice);
  2234. TraceIp("DnsDisableDynamicRegistration");
  2235. }
  2236. if (pwb->fRegisterAdapterDomainName)
  2237. {
  2238. DnsEnableAdapterDomainNameRegistration(pwb->pwszDevice);
  2239. TraceIp("DnsEnableAdapterDomainNameRegistration");
  2240. }
  2241. else
  2242. {
  2243. DnsDisableAdapterDomainNameRegistration(pwb->pwszDevice);
  2244. TraceIp("DnsDisableAdapterDomainNameRegistration");
  2245. }
  2246. if (pwb->szDnsSuffix[0] != 0)
  2247. {
  2248. DWORD dwDomainNameSize;
  2249. dwDomainNameSize = strlen(pwb->szDnsSuffix) + 1;
  2250. ptcpip->wszDNSDomainName = LocalAlloc(LPTR, sizeof(WCHAR) * dwDomainNameSize);
  2251. if (NULL != ptcpip->wszDNSDomainName)
  2252. {
  2253. MultiByteToWideChar(
  2254. CP_ACP,
  2255. 0,
  2256. pwb->szDnsSuffix,
  2257. -1,
  2258. ptcpip->wszDNSDomainName,
  2259. dwDomainNameSize );
  2260. }
  2261. }
  2262. TraceIp("IPCP: SaveTcpipInfo...");
  2263. dwErr = SaveTcpipInfo( ptcpip );
  2264. TraceIp("IPCP: SaveTcpipInfo done(%d)",dwErr);
  2265. FreeTcpipInfo( &ptcpip );
  2266. if (dwErr != 0)
  2267. {
  2268. break;
  2269. }
  2270. if (!pwb->fUnnumbered)
  2271. {
  2272. /* Tell TCPIP components to reconfigure themselves.
  2273. */
  2274. if ((dwErr = ReconfigureTcpip(pwb->pwszDevice,
  2275. TRUE,
  2276. pwb->IpAddressLocal,
  2277. pLinkUp->dwLocalMask)) != NO_ERROR)
  2278. {
  2279. TraceIp("IPCP: ReconfigureTcpip=%d",dwErr);
  2280. // This will fail if the dhcp client is not running.
  2281. // dwErr = NO_ERROR;
  2282. ResetNetBTConfigInfo( pwb );
  2283. break;
  2284. }
  2285. }
  2286. /* Adjust the metric for Multicast class D Addresses */
  2287. if ( (!pwb->fServer)
  2288. )
  2289. {
  2290. dwErr = RasTcpAdjustMulticastRouteMetric ( pwb->IpAddressLocal, TRUE );
  2291. if ( NO_ERROR != dwErr )
  2292. {
  2293. TraceIp("IPCP: =RasTcpAdjustMulticastRouteMetric%d",dwErr);
  2294. dwErr = NO_ERROR;
  2295. }
  2296. }
  2297. /* Do DHCPINFORM only for clients */
  2298. while ((!pwb->fServer) &&
  2299. (pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER))
  2300. {
  2301. IPCP_DHCP_INFORM* pIpcpDhcpInform = NULL;
  2302. BOOL fErr = TRUE;
  2303. pIpcpDhcpInform = LocalAlloc(LPTR, sizeof(IPCP_DHCP_INFORM));
  2304. if (NULL == pIpcpDhcpInform)
  2305. {
  2306. TraceIp("IPCP: LocalAlloc 1 =%d",GetLastError());
  2307. goto LWhileEnd;
  2308. }
  2309. pIpcpDhcpInform->fUseDhcpInformDomainName =
  2310. (pwb->szDnsSuffix[0] == 0);
  2311. pIpcpDhcpInform->wszDevice = LocalAlloc(LPTR,
  2312. sizeof(WCHAR) * (wcslen(pwb->pwszDevice) + 1));
  2313. if (NULL == pIpcpDhcpInform->wszDevice)
  2314. {
  2315. TraceIp("IPCP: LocalAlloc 2 =%d",GetLastError());
  2316. goto LWhileEnd;
  2317. }
  2318. wcscpy(pIpcpDhcpInform->wszDevice, pwb->pwszDevice);
  2319. pIpcpDhcpInform->hConnection = pwb->hConnection;
  2320. dwErr = RtlQueueWorkItem(DhcpInform, pIpcpDhcpInform,
  2321. WT_EXECUTELONGFUNCTION);
  2322. if (dwErr != STATUS_SUCCESS)
  2323. {
  2324. TraceIp("IPCP: RtlQueueWorkItem=%d",dwErr);
  2325. goto LWhileEnd;
  2326. }
  2327. fErr = FALSE;
  2328. LWhileEnd:
  2329. if (fErr)
  2330. {
  2331. if (pIpcpDhcpInform)
  2332. {
  2333. LocalFree(pIpcpDhcpInform->wszDevice);
  2334. }
  2335. LocalFree(pIpcpDhcpInform);
  2336. }
  2337. break;
  2338. }
  2339. }
  2340. while (FALSE);
  2341. }
  2342. if (dwErr == 0)
  2343. {
  2344. pwb->fRasConfigActive = TRUE;
  2345. /* Tell MAC about any negotiated compression parameters.
  2346. */
  2347. if (pwb->fIpCompressionRejected)
  2348. {
  2349. Protocol(pwb->rpcReceive) = NO_PROTOCOL_COMPRESSION;
  2350. MaxSlotId(pwb->rpcReceive) = 0;
  2351. CompSlotId(pwb->rpcReceive) = 0;
  2352. }
  2353. if (!pwb->fSendCompression)
  2354. {
  2355. Protocol(pwb->rpcSend) = NO_PROTOCOL_COMPRESSION;
  2356. MaxSlotId(pwb->rpcSend) = 0;
  2357. CompSlotId(pwb->rpcSend) = 0;
  2358. }
  2359. //if (Protocol(pwb->rpcSend) != 0 || Protocol(pwb->rpcReceive) != 0)
  2360. {
  2361. TraceIp("IPCP:RasPortSetProtocolCompression(s=%d,%d r=%d,%d)",
  2362. (int)MaxSlotId(pwb->rpcSend),(int)CompSlotId(pwb->rpcSend),
  2363. (int)MaxSlotId(pwb->rpcReceive),
  2364. (int)CompSlotId(pwb->rpcReceive));
  2365. dwErr = RasPortSetProtocolCompression(
  2366. pwb->hport, IP, &pwb->rpcSend, &pwb->rpcReceive );
  2367. TraceIp("IPCP: RasPortSetProtocolCompression done(%d)",dwErr);
  2368. }
  2369. if ( ( ( pwb->fServer ) ||
  2370. ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) )
  2371. && ( pwb->IpAddressRemote != 0 ))
  2372. {
  2373. WCHAR* pwsz[5];
  2374. WCHAR wszIPAddress[MAXIPSTRLEN + 1];
  2375. WCHAR wszSubnet[MAXIPSTRLEN + 1];
  2376. WCHAR wszMask[MAXIPSTRLEN + 1];
  2377. /* Register addresses in server's routing tables.
  2378. */
  2379. TraceIp("IPCP: RasSrvrActivateIp...");
  2380. dwErr = RasSrvrActivateIp( pwb->IpAddressRemote,
  2381. pLinkUp->duUsage );
  2382. TraceIp("IPCP: RasSrvrActivateIp done(%d)",dwErr);
  2383. }
  2384. if ( pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  2385. {
  2386. WCHAR* pwsz[2];
  2387. if ( pwb->IpAddressRemote == 0 )
  2388. {
  2389. pwsz[0] = pwb->wszPortName;
  2390. pwsz[1] = pwb->wszUserName;
  2391. LogEventW(EVENTLOG_WARNING_TYPE,
  2392. ROUTERLOG_REMOTE_UNNUMBERED_IPCP, 2,
  2393. pwsz);
  2394. }
  2395. if ( pwb->IpAddressLocal == 0 )
  2396. {
  2397. pwsz[0] = pwb->wszPortName;
  2398. pwsz[1] = pwb->wszUserName;
  2399. LogEventW(EVENTLOG_WARNING_TYPE,
  2400. ROUTERLOG_LOCAL_UNNUMBERED_IPCP, 2,
  2401. pwsz);
  2402. }
  2403. }
  2404. }
  2405. pwb->fExpectingProjection = FALSE;
  2406. if (dwErr != NO_ERROR)
  2407. {
  2408. if(pwb->fRouteActivated)
  2409. {
  2410. TraceIp("IPCP: RasDeAllocateRoute...");
  2411. RasDeAllocateRoute( pwb->hConnection, IP );
  2412. pwb->fRouteActivated = FALSE;
  2413. }
  2414. if(fSetDefaultRoute)
  2415. {
  2416. HelperResetDefaultInterfaceNet(
  2417. pwb->IpAddressLocal,
  2418. pwb->fPrioritizeRemote);
  2419. }
  2420. }
  2421. }
  2422. return dwErr;
  2423. }
  2424. /*---------------------------------------------------------------------------
  2425. ** Internal routines (alphabetically)
  2426. **---------------------------------------------------------------------------
  2427. */
  2428. VOID
  2429. AddIpAddressOption(
  2430. OUT BYTE UNALIGNED* pbBuf,
  2431. IN BYTE bOption,
  2432. IN IPADDR ipaddr )
  2433. /* Write an IP address 'ipaddr' configuration option of type 'bOption' at
  2434. ** location 'pbBuf'.
  2435. */
  2436. {
  2437. *pbBuf++ = bOption;
  2438. *pbBuf++ = IPADDRESSOPTIONLEN;
  2439. *((IPADDR UNALIGNED* )pbBuf) = ipaddr;
  2440. }
  2441. VOID
  2442. AddIpCompressionOption(
  2443. OUT BYTE UNALIGNED* pbBuf,
  2444. IN RAS_PROTOCOLCOMPRESSION* prpc )
  2445. /* Write an IP compression protocol configuration as described in '*prpc'
  2446. ** at location 'pbBuf'.
  2447. */
  2448. {
  2449. *pbBuf++ = OPTION_IpCompression;
  2450. *pbBuf++ = IPCOMPRESSIONOPTIONLEN;
  2451. HostToWireFormat16U( Protocol(*prpc), pbBuf );
  2452. pbBuf += 2;
  2453. *pbBuf++ = MaxSlotId(*prpc);
  2454. *pbBuf = CompSlotId(*prpc);
  2455. }
  2456. /*
  2457. Notes:
  2458. DeActivates the active RAS configuration, if any.
  2459. */
  2460. DWORD
  2461. DeActivateRasConfig(
  2462. IN IPCPWB* pwb
  2463. )
  2464. {
  2465. DWORD dwErr = NO_ERROR;
  2466. if (!pwb->fRasConfigActive)
  2467. {
  2468. goto LDone;
  2469. }
  2470. TraceIp("DeActivateRasConfig");
  2471. dwErr = ResetNetBTConfigInfo(pwb);
  2472. if (NO_ERROR != dwErr)
  2473. {
  2474. goto LDone;
  2475. }
  2476. /* Adjust the metric for Multicast class D Addresses */
  2477. if ( (!pwb->fServer)
  2478. )
  2479. {
  2480. RasTcpAdjustMulticastRouteMetric ( pwb->IpAddressLocal, FALSE );
  2481. //The route will be automatically removed when the interface disapperars
  2482. }
  2483. dwErr = ReconfigureTcpip(pwb->pwszDevice, TRUE, 0, 0);
  2484. if (NO_ERROR != dwErr)
  2485. {
  2486. // Ignore errors. You may get a 15 here.
  2487. dwErr = NO_ERROR;
  2488. }
  2489. if (pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER)
  2490. {
  2491. TraceIp("HelperResetDefaultInterfaceNet(0x%x, %sPrioritizeRemote)",
  2492. pwb->IpAddressLocal,
  2493. pwb->fPrioritizeRemote ? "" : "!");
  2494. dwErr = HelperResetDefaultInterfaceNet(
  2495. pwb->IpAddressLocal, pwb->fPrioritizeRemote);
  2496. if (NO_ERROR != dwErr)
  2497. {
  2498. TraceIp("HelperResetDefaultInterfaceNet failed and returned %d",
  2499. dwErr);
  2500. }
  2501. }
  2502. LDone:
  2503. return(dwErr);
  2504. }
  2505. DWORD
  2506. NakCheck(
  2507. IN IPCPWB* pwb,
  2508. IN PPP_CONFIG* pReceiveBuf,
  2509. OUT PPP_CONFIG* pSendBuf,
  2510. IN DWORD cbSendBuf,
  2511. OUT BOOL* pfNak,
  2512. IN BOOL fRejectNaks )
  2513. /* Check to see if received packet 'pReceiveBuf' should be Naked and if
  2514. ** so, build a Nak packet with suggested values in 'pSendBuf'. If
  2515. ** 'fRejectNaks' is set the original options are placed in a Reject packet
  2516. ** instead. '*pfNak' is set true if either a Nak or Rej packet was
  2517. ** created.
  2518. **
  2519. ** Note: This routine assumes that corrupt packets have already been
  2520. ** weeded out.
  2521. **
  2522. ** Returns 0 if successful, otherwise a non-0 error code.
  2523. */
  2524. {
  2525. PPP_OPTION UNALIGNED* pROption = (PPP_OPTION UNALIGNED* )pReceiveBuf->Data;
  2526. PPP_OPTION UNALIGNED* pSOption = (PPP_OPTION UNALIGNED* )pSendBuf->Data;
  2527. /* (server only) The address the client requests, then if NAKed, the non-0
  2528. ** address we NAK with. If this is 0 after the packet has been processed,
  2529. ** the IP-Address option was not negotiated.
  2530. */
  2531. IPADDR ipaddrClient = 0;
  2532. DWORD dwErr = 0;
  2533. WORD cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  2534. WORD cbLeft = cbPacket - PPP_CONFIG_HDR_LEN;
  2535. TraceIp("IPCP: NakCheck");
  2536. *pfNak = FALSE;
  2537. while (cbLeft > 0)
  2538. {
  2539. RTASSERT(cbLeft>=pROption->Length);
  2540. if (pROption->Type == OPTION_IpCompression)
  2541. {
  2542. BOOL fNakCompression = FALSE;
  2543. if (WireToHostFormat16U(pROption->Data )
  2544. == COMPRESSION_VanJacobson)
  2545. {
  2546. RTASSERT((pROption->Length==IPCOMPRESSIONOPTIONLEN));
  2547. /* He wants to receive Van Jacobson. We know we can do it or
  2548. ** it would have already been rejected, but make sure we can
  2549. ** handle his slot parameters.
  2550. */
  2551. if (pROption->Data[ 2 ] <= MaxSlotId(pwb->rpcSend))
  2552. {
  2553. /* We can accept his suggested MaxSlotID when it is less
  2554. ** than or the same as what we can send.
  2555. */
  2556. MaxSlotId(pwb->rpcSend) = pROption->Data[ 2 ];
  2557. }
  2558. else
  2559. fNakCompression = TRUE;
  2560. if (CompSlotId(pwb->rpcSend))
  2561. {
  2562. /* We can compress the slot-ID or not, so just accept
  2563. ** whatever he wants us to send.
  2564. */
  2565. CompSlotId(pwb->rpcSend) = pROption->Data[ 3 ];
  2566. }
  2567. else if (pROption->Data[ 3 ])
  2568. fNakCompression = TRUE;
  2569. }
  2570. else
  2571. fNakCompression = TRUE;
  2572. if (fNakCompression)
  2573. {
  2574. TraceIp("IPCP: Naking IP compression");
  2575. *pfNak = TRUE;
  2576. if (fRejectNaks)
  2577. {
  2578. CopyMemory(
  2579. (VOID* )pSOption, (VOID* )pROption, pROption->Length );
  2580. }
  2581. else
  2582. {
  2583. pSOption->Type = OPTION_IpCompression;
  2584. pSOption->Length = IPCOMPRESSIONOPTIONLEN;
  2585. HostToWireFormat16U(
  2586. (WORD )COMPRESSION_VanJacobson,
  2587. pSOption->Data );
  2588. pSOption->Data[ 2 ] = MaxSlotId(pwb->rpcSend);
  2589. pSOption->Data[ 3 ] = CompSlotId(pwb->rpcSend);
  2590. pSOption =
  2591. (PPP_OPTION UNALIGNED* )((BYTE* )pSOption +
  2592. pSOption->Length);
  2593. }
  2594. pwb->fSendCompression = FALSE;
  2595. }
  2596. else
  2597. {
  2598. pwb->fSendCompression = TRUE;
  2599. }
  2600. }
  2601. else if ((pwb->fServer) || (pwb->IfType == ROUTER_IF_TYPE_FULL_ROUTER))
  2602. {
  2603. switch (pROption->Type)
  2604. {
  2605. case OPTION_IpAddress:
  2606. {
  2607. RTASSERT(pROption->Length==IPADDRESSOPTIONLEN);
  2608. CopyMemory( &ipaddrClient, pROption->Data, sizeof(IPADDR) );
  2609. if (pwb->IpAddressRemote != 0)
  2610. {
  2611. if ( ipaddrClient == pwb->IpAddressRemote )
  2612. {
  2613. //
  2614. // If we have already allocated what the user
  2615. // wants, we are done with this option.
  2616. //
  2617. break;
  2618. }
  2619. else if ( ipaddrClient == 0 )
  2620. {
  2621. ipaddrClient = pwb->IpAddressRemote;
  2622. *pfNak = TRUE;
  2623. CopyMemory(
  2624. (VOID* )pSOption, (VOID* )pROption,
  2625. pROption->Length );
  2626. if (!fRejectNaks)
  2627. {
  2628. TraceIp("IPCP: Naking IP");
  2629. CopyMemory( pSOption->Data,
  2630. &pwb->IpAddressRemote,
  2631. sizeof(IPADDR) );
  2632. }
  2633. pSOption =
  2634. (PPP_OPTION UNALIGNED* )((BYTE* )pSOption +
  2635. pROption->Length);
  2636. break;
  2637. }
  2638. else
  2639. {
  2640. TraceIp("IPCP: RasSrvrReleaseAddress...");
  2641. RasSrvrReleaseAddress(
  2642. pwb->IpAddressRemote,
  2643. pwb->wszUserName,
  2644. pwb->wszPortName,
  2645. FALSE );
  2646. TraceIp("IPCP: RasSrvrReleaseAddress done");
  2647. pwb->IpAddressRemote = 0;
  2648. }
  2649. }
  2650. //
  2651. // If client is requesting an IP address, check to see
  2652. // if we are allowed to give it to him.
  2653. //
  2654. if ( ( ipaddrClient != 0 ) &&
  2655. ( pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER ) &&
  2656. ( pwb->IpAddressToHandout == net_long( 0xFFFFFFFE ) ) )
  2657. {
  2658. TraceIp("IPCP: Clients not allowed to request IPaddr");
  2659. ipaddrClient = 0;
  2660. }
  2661. TraceIp("IPCP: RasSrvrAcquireAddress(%08x)...",
  2662. ipaddrClient);
  2663. dwErr = RasSrvrAcquireAddress(
  2664. pwb->hport,
  2665. ((pwb->IpAddressToHandout != net_long(0xFFFFFFFF))&&
  2666. (pwb->IpAddressToHandout != net_long(0xFFFFFFFE)))
  2667. ? pwb->IpAddressToHandout
  2668. : ipaddrClient,
  2669. &(pwb->IpAddressRemote),
  2670. pwb->wszUserName,
  2671. pwb->wszPortName );
  2672. TraceIp("IPCP: RasSrvrAcquireAddress done(%d)",
  2673. dwErr);
  2674. if (dwErr != 0)
  2675. {
  2676. return dwErr;
  2677. }
  2678. if (ipaddrClient != 0)
  2679. {
  2680. TraceIp("IPCP: Hard IP requested");
  2681. if ( ipaddrClient == pwb->IpAddressRemote )
  2682. {
  2683. /* Good. Client's asking for the address we
  2684. ** want to give him.
  2685. */
  2686. TraceIp("IPCP: Accepting IP");
  2687. break;
  2688. }
  2689. else
  2690. {
  2691. //
  2692. // Otherwise we could not give the user the
  2693. // address he/she requested. Nak with this address.
  2694. //
  2695. TraceIp("IPCP: 3rd party DLL changed IP");
  2696. }
  2697. }
  2698. else
  2699. {
  2700. TraceIp("IPCP: Server IP requested");
  2701. }
  2702. ipaddrClient = pwb->IpAddressRemote;
  2703. *pfNak = TRUE;
  2704. CopyMemory(
  2705. (VOID* )pSOption, (VOID* )pROption,
  2706. pROption->Length );
  2707. if (!fRejectNaks)
  2708. {
  2709. TraceIp("IPCP: Naking IP");
  2710. CopyMemory( pSOption->Data,
  2711. &pwb->IpAddressRemote,
  2712. sizeof(IPADDR) );
  2713. }
  2714. pSOption =
  2715. (PPP_OPTION UNALIGNED* )((BYTE* )pSOption +
  2716. pROption->Length);
  2717. break;
  2718. }
  2719. case OPTION_DnsIpAddress:
  2720. case OPTION_WinsIpAddress:
  2721. case OPTION_DnsBackupIpAddress:
  2722. case OPTION_WinsBackupIpAddress:
  2723. {
  2724. if (NakCheckNameServerOption(
  2725. pwb, fRejectNaks, pROption, &pSOption ))
  2726. {
  2727. *pfNak = TRUE;
  2728. }
  2729. break;
  2730. }
  2731. default:
  2732. TraceIp("IPCP: Unknown option?");
  2733. break;
  2734. }
  2735. }
  2736. if (pROption->Length && pROption->Length < cbLeft)
  2737. cbLeft -= pROption->Length;
  2738. else
  2739. cbLeft = 0;
  2740. pROption =
  2741. (PPP_OPTION UNALIGNED* )((BYTE* )pROption + pROption->Length);
  2742. }
  2743. if ( pwb->fServer
  2744. && ( pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER )
  2745. && ipaddrClient == 0 )
  2746. {
  2747. /* ipaddrClient is 0 iff there is no OPTION_IpAddress */
  2748. TraceIp("IPCP: No IP option");
  2749. /* If client doesn't provide or asked to be assigned an IP address,
  2750. ** suggest one so he'll tell us what he wants.
  2751. */
  2752. if ( pwb->IpAddressRemote == 0 )
  2753. {
  2754. TraceIp("IPCP: RasSrvrAcquireAddress(0)...");
  2755. dwErr = RasSrvrAcquireAddress(
  2756. pwb->hport,
  2757. 0,
  2758. &(pwb->IpAddressRemote),
  2759. pwb->wszUserName,
  2760. pwb->wszPortName );
  2761. TraceIp("IPCP: RasSrvrAcquireAddress done(%d)",dwErr);
  2762. if (dwErr != 0)
  2763. return dwErr;
  2764. }
  2765. /* Time to reject instead of nak and client is still not requesting an
  2766. ** IP address. We simply allocate an IP address and ACK this request
  2767. */
  2768. if ( !fRejectNaks )
  2769. {
  2770. AddIpAddressOption(
  2771. (BYTE UNALIGNED* )pSOption, OPTION_IpAddress,
  2772. pwb->IpAddressRemote );
  2773. pSOption =
  2774. (PPP_OPTION UNALIGNED* )((BYTE* )pSOption + IPADDRESSOPTIONLEN);
  2775. *pfNak = TRUE;
  2776. }
  2777. }
  2778. if (*pfNak)
  2779. {
  2780. pSendBuf->Code = (fRejectNaks) ? CONFIG_REJ : CONFIG_NAK;
  2781. HostToWireFormat16(
  2782. (WORD )((BYTE* )pSOption - (BYTE* )pSendBuf), pSendBuf->Length );
  2783. }
  2784. return 0;
  2785. }
  2786. BOOL
  2787. NakCheckNameServerOption(
  2788. IN IPCPWB* pwb,
  2789. IN BOOL fRejectNaks,
  2790. IN PPP_OPTION UNALIGNED* pROption,
  2791. OUT PPP_OPTION UNALIGNED** ppSOption )
  2792. /* Check a name server option for possible naking. 'pwb' the work buffer
  2793. ** stored for us by the engine. 'fRejectNaks' is set the original options
  2794. ** are placed in a Reject packet instead. 'pROption' is the address of
  2795. ** the received option. '*ppSOption' is the address of the option to be
  2796. ** sent, if there's a problem.
  2797. **
  2798. ** Returns true if the name server address option should be naked or
  2799. ** rejected, false if it's OK.
  2800. */
  2801. {
  2802. IPADDR ipaddr;
  2803. IPADDR* pipaddrWant;
  2804. switch (pROption->Type)
  2805. {
  2806. case OPTION_DnsIpAddress:
  2807. pipaddrWant = &pwb->IpInfoRemote.nboDNSAddress;
  2808. break;
  2809. case OPTION_WinsIpAddress:
  2810. pipaddrWant = &pwb->IpInfoRemote.nboWINSAddress;
  2811. break;
  2812. case OPTION_DnsBackupIpAddress:
  2813. pipaddrWant = &pwb->IpInfoRemote.nboDNSAddressBackup;
  2814. break;
  2815. case OPTION_WinsBackupIpAddress:
  2816. pipaddrWant = &pwb->IpInfoRemote.nboWINSAddressBackup;
  2817. break;
  2818. default:
  2819. RTASSERT((!"Bogus option"));
  2820. return FALSE;
  2821. }
  2822. RTASSERT(pROption->Length==IPADDRESSOPTIONLEN);
  2823. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  2824. if (ipaddr == *pipaddrWant)
  2825. {
  2826. /* Good. Client's asking for the address we want to give him.
  2827. */
  2828. return FALSE;
  2829. }
  2830. /* Not our expected address value, so Nak it.
  2831. */
  2832. TraceIp("IPCP: Naking $%x",(int)pROption->Type);
  2833. CopyMemory( (VOID* )*ppSOption, (VOID* )pROption, pROption->Length );
  2834. if (!fRejectNaks)
  2835. CopyMemory( (*ppSOption)->Data, pipaddrWant, sizeof(IPADDR) );
  2836. *ppSOption =
  2837. (PPP_OPTION UNALIGNED* )((BYTE* )*ppSOption + pROption->Length);
  2838. return TRUE;
  2839. }
  2840. DWORD
  2841. RejectCheck(
  2842. IN IPCPWB* pwb,
  2843. IN PPP_CONFIG* pReceiveBuf,
  2844. OUT PPP_CONFIG* pSendBuf,
  2845. IN DWORD cbSendBuf,
  2846. OUT BOOL* pfReject )
  2847. /* Check received packet 'pReceiveBuf' options to see if any should be
  2848. ** rejected and if so, build a Rej packet in 'pSendBuf'. '*pfReject' is
  2849. ** set true if a Rej packet was created.
  2850. **
  2851. ** Returns 0 if successful, otherwise a non-0 error code.
  2852. */
  2853. {
  2854. PPP_OPTION UNALIGNED* pROption = (PPP_OPTION UNALIGNED* )pReceiveBuf->Data;
  2855. PPP_OPTION UNALIGNED* pSOption = (PPP_OPTION UNALIGNED* )pSendBuf->Data;
  2856. WORD cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  2857. WORD cbLeft = cbPacket - PPP_CONFIG_HDR_LEN;
  2858. TraceIp("IPCP: RejectCheck");
  2859. *pfReject = FALSE;
  2860. while (cbLeft > 0)
  2861. {
  2862. if (cbLeft < pROption->Length)
  2863. return ERROR_PPP_INVALID_PACKET;
  2864. if (pROption->Type == OPTION_IpCompression)
  2865. {
  2866. WORD wProtocol =
  2867. WireToHostFormat16U(pROption->Data );
  2868. if (wProtocol != COMPRESSION_VanJacobson
  2869. || pROption->Length != IPCOMPRESSIONOPTIONLEN
  2870. || Protocol(pwb->rpcSend) == 0)
  2871. {
  2872. TraceIp("IPCP: Rejecting IP compression");
  2873. *pfReject = TRUE;
  2874. CopyMemory(
  2875. (VOID* )pSOption, (VOID* )pROption, pROption->Length );
  2876. pSOption = (PPP_OPTION UNALIGNED* )((BYTE* )pSOption +
  2877. pROption->Length);
  2878. }
  2879. }
  2880. else if (pwb->fServer)
  2881. {
  2882. //
  2883. // This is a client/router dialing in
  2884. //
  2885. switch (pROption->Type)
  2886. {
  2887. case OPTION_IpAddress:
  2888. case OPTION_DnsIpAddress:
  2889. case OPTION_WinsIpAddress:
  2890. case OPTION_DnsBackupIpAddress:
  2891. case OPTION_WinsBackupIpAddress:
  2892. {
  2893. IPADDR ipaddr;
  2894. BOOL fBadLength = (pROption->Length != IPADDRESSOPTIONLEN);
  2895. if (!fBadLength)
  2896. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  2897. if (fBadLength
  2898. || (!ipaddr
  2899. && ((pROption->Type == OPTION_DnsIpAddress
  2900. && !pwb->IpInfoRemote.nboDNSAddress)
  2901. || (pROption->Type == OPTION_WinsIpAddress
  2902. && !pwb->IpInfoRemote.nboWINSAddress)
  2903. || (pROption->Type == OPTION_DnsBackupIpAddress
  2904. && !pwb->IpInfoRemote.nboDNSAddressBackup)
  2905. || (pROption->Type == OPTION_WinsBackupIpAddress
  2906. && !pwb->IpInfoRemote.nboWINSAddressBackup))))
  2907. {
  2908. /* messed up IP address option, reject it.
  2909. */
  2910. TraceIp("IPCP: Rejecting $%x",(int )pROption->Type);
  2911. *pfReject = TRUE;
  2912. CopyMemory(
  2913. (VOID* )pSOption, (VOID* )pROption,
  2914. pROption->Length );
  2915. pSOption = (PPP_OPTION UNALIGNED* )((BYTE* )pSOption +
  2916. pROption->Length);
  2917. }
  2918. break;
  2919. }
  2920. default:
  2921. {
  2922. /* Unknown option, reject it.
  2923. */
  2924. TraceIp("IPCP: Rejecting $%x",(int )pROption->Type);
  2925. *pfReject = TRUE;
  2926. CopyMemory(
  2927. (VOID* )pSOption, (VOID* )pROption, pROption->Length );
  2928. pSOption =
  2929. (PPP_OPTION UNALIGNED* )((BYTE* )pSOption +
  2930. pROption->Length);
  2931. break;
  2932. }
  2933. }
  2934. }
  2935. else
  2936. {
  2937. //
  2938. // This is a client/router dialing out
  2939. //
  2940. IPADDR ipaddr;
  2941. BOOL fBad = (pROption->Type != OPTION_IpAddress
  2942. || pROption->Length != IPADDRESSOPTIONLEN);
  2943. if (!fBad)
  2944. CopyMemory( &ipaddr, pROption->Data, sizeof(IPADDR) );
  2945. if ( fBad
  2946. || ( !ipaddr
  2947. && (pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER)))
  2948. {
  2949. /* Client rejects everything except a non-zero IP address
  2950. ** which is accepted because some peers (such as Shiva) can't
  2951. ** handle rejection of this option.
  2952. */
  2953. TraceIp("IPCP: Rejecting %d",(int )pROption->Type);
  2954. *pfReject = TRUE;
  2955. CopyMemory(
  2956. (VOID* )pSOption, (VOID* )pROption, pROption->Length );
  2957. pSOption = (PPP_OPTION UNALIGNED* )((BYTE* )pSOption +
  2958. pROption->Length);
  2959. }
  2960. else
  2961. {
  2962. /* Store the server's IP address as some applications may be
  2963. ** able to make use of it (e.g. Compaq does), though they are
  2964. ** not guaranteed to receive it from all IPCP implementations.
  2965. */
  2966. if (pwb->IfType != ROUTER_IF_TYPE_FULL_ROUTER)
  2967. {
  2968. pwb->IpAddressRemote = ipaddr;
  2969. }
  2970. }
  2971. }
  2972. if (pROption->Length && pROption->Length < cbLeft)
  2973. cbLeft -= pROption->Length;
  2974. else
  2975. cbLeft = 0;
  2976. pROption =
  2977. (PPP_OPTION UNALIGNED* )((BYTE* )pROption +
  2978. pROption->Length);
  2979. }
  2980. if (*pfReject)
  2981. {
  2982. pSendBuf->Code = CONFIG_REJ;
  2983. HostToWireFormat16(
  2984. (WORD )((BYTE* )pSOption - (BYTE* )pSendBuf), pSendBuf->Length );
  2985. }
  2986. return 0;
  2987. }
  2988. DWORD
  2989. ReconfigureTcpip(
  2990. IN WCHAR* pwszDevice,
  2991. IN BOOL fNewIpAddress,
  2992. IN IPADDR ipaddr,
  2993. IN IPADDR ipMask
  2994. )
  2995. /* Reconfigure running TCP/IP components.
  2996. **
  2997. ** Returns 0 if successful, otherwise a non-0 error code.
  2998. */
  2999. {
  3000. DWORD dwErr;
  3001. TraceIp("IPCP: ReconfigureTcpip(%08x, %08x)",
  3002. ipaddr, ipMask);
  3003. dwErr = PDhcpNotifyConfigChange2(NULL, pwszDevice, fNewIpAddress, 0,
  3004. ipaddr, ipMask, IgnoreFlag,
  3005. NOTIFY_FLG_DO_DNS);
  3006. TraceIp("IPCP: ReconfigureTcpip done(%d)",dwErr);
  3007. return dwErr;
  3008. }
  3009. VOID
  3010. TraceIp(
  3011. CHAR * Format,
  3012. ...
  3013. )
  3014. {
  3015. va_list arglist;
  3016. va_start(arglist, Format);
  3017. TraceVprintfEx( DwIpcpTraceId,
  3018. PPPIPCP_TRACE | TRACE_USE_MASK
  3019. | TRACE_USE_MSEC | TRACE_USE_DATE,
  3020. Format,
  3021. arglist);
  3022. va_end(arglist);
  3023. }
  3024. VOID
  3025. TraceIpDump(
  3026. LPVOID lpData,
  3027. DWORD dwByteCount
  3028. )
  3029. {
  3030. TraceDumpEx( DwIpcpTraceId,
  3031. PPPIPCP_TRACE | TRACE_USE_MASK | TRACE_USE_MSEC,
  3032. lpData, dwByteCount, 1, FALSE, NULL );
  3033. }
  3034. VOID
  3035. PrintMwsz(
  3036. CHAR* sz,
  3037. WCHAR* mwsz
  3038. )
  3039. {
  3040. WCHAR* wsz;
  3041. DWORD dwLength;
  3042. if (NULL == mwsz)
  3043. {
  3044. TraceIp("%s", sz);
  3045. return;
  3046. }
  3047. dwLength = MwszLength(mwsz);
  3048. wsz = LocalAlloc(LPTR, dwLength * sizeof(WCHAR));
  3049. if (NULL == wsz)
  3050. {
  3051. TraceIp("LocalAlloc failed and returned %d", GetLastError());
  3052. return;
  3053. }
  3054. CopyMemory(wsz, mwsz, dwLength * sizeof(WCHAR));
  3055. dwLength -= 2;
  3056. while (dwLength != 0)
  3057. {
  3058. dwLength--;
  3059. if (0 == wsz[dwLength])
  3060. {
  3061. wsz[dwLength] = L' ';
  3062. }
  3063. }
  3064. TraceIp("%s %ws", sz, wsz);
  3065. LocalFree(wsz);
  3066. }