Source code of Windows XP (NT5)
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.

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