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.

652 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. addr.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. IP address routines
  8. Author:
  9. Jim Gilroy (jamesg) June 2000
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include "ws2atm.h" // ATM addressing
  14. //
  15. // Address info table
  16. //
  17. FAMILY_INFO AddrFamilyTable[] =
  18. {
  19. AF_INET,
  20. DNS_TYPE_A,
  21. sizeof(IP4_ADDRESS),
  22. sizeof(SOCKADDR_IN),
  23. (DWORD) FIELD_OFFSET( SOCKADDR_IN, sin_addr ),
  24. //sizeof(DWORD),
  25. AF_INET6,
  26. DNS_TYPE_AAAA,
  27. sizeof(IP6_ADDRESS),
  28. sizeof(SOCKADDR_IN6),
  29. (DWORD) FIELD_OFFSET( SOCKADDR_IN6, sin6_addr ),
  30. //(2 * sizeof(DWORD)),
  31. AF_ATM,
  32. DNS_TYPE_ATMA,
  33. sizeof(ATM_ADDRESS),
  34. sizeof(SOCKADDR_ATM),
  35. sizeof(DWORD),
  36. (DWORD) FIELD_OFFSET( SOCKADDR_ATM, satm_number ),
  37. };
  38. PFAMILY_INFO
  39. FamilyInfo_GetForFamily(
  40. IN DWORD Family
  41. )
  42. /*++
  43. Routine Description:
  44. Get address family info for family.
  45. Arguments:
  46. Family -- address family
  47. Return Value:
  48. Ptr to address family info for family.
  49. NULL if family is unknown.
  50. --*/
  51. {
  52. PFAMILY_INFO pinfo = NULL;
  53. // switch on type
  54. if ( Family == AF_INET )
  55. {
  56. pinfo = pFamilyInfoIp4;
  57. }
  58. else if ( Family == AF_INET6 )
  59. {
  60. pinfo = pFamilyInfoIp6;
  61. }
  62. else if ( Family == AF_ATM )
  63. {
  64. pinfo = pFamilyInfoAtm;
  65. }
  66. return pinfo;
  67. }
  68. //
  69. // IPUNION routines
  70. //
  71. BOOL
  72. Dns_EqualIpUnion(
  73. IN PIP_UNION pIp1,
  74. IN PIP_UNION pIp2
  75. )
  76. /*++
  77. Routine Description:
  78. Test IP union for equality
  79. Arguments:
  80. pIp1 -- IP address union
  81. pIp2 -- IP address union
  82. Return Value:
  83. TRUE if Ip1 and Ip2 equal.
  84. FALSE otherwise.
  85. --*/
  86. {
  87. //
  88. // DCR: when stamp flat, can make this memory compare
  89. //
  90. // IP4 match?
  91. if ( IPUNION_IS_IP4(pIp1) )
  92. {
  93. if ( IPUNION_IS_IP4(pIp2) &&
  94. IPUNION_GET_IP4(pIp1) == IPUNION_GET_IP4(pIp2) )
  95. {
  96. return( TRUE );
  97. }
  98. }
  99. // IP6 match?
  100. else
  101. {
  102. if ( IPUNION_IS_IP6(pIp2) &&
  103. RtlEqualMemory(
  104. IPUNION_IP6_PTR(pIp1),
  105. IPUNION_IP6_PTR(pIp2),
  106. sizeof(IP6_ADDRESS) ) )
  107. {
  108. return( TRUE );
  109. }
  110. }
  111. return( FALSE );
  112. }
  113. //
  114. // Sockaddr
  115. //
  116. IP6_ADDRESS
  117. Ip6AddressFromSockaddr(
  118. IN PSOCKADDR pSockaddr
  119. )
  120. /*++
  121. Routine Description:
  122. Get IP6 address from sockaddr.
  123. If IP4 sockaddr, IP6 address is mapped.
  124. Arguments:
  125. pSockaddr -- any kind of sockaddr
  126. must have actual length for sockaddr family
  127. Return Value:
  128. IP6 address corresponding to sockaddr.
  129. If IP4 sockaddr it's IP4_MAPPED address.
  130. If not IP4 or IP6 sockaddr IP6 addresss is zero.
  131. --*/
  132. {
  133. IP6_ADDRESS ip6;
  134. //
  135. // switch on family
  136. // - IP6 gets copy
  137. // - IP4 gets IP4_MAPPED
  138. // - bogus gets zero
  139. //
  140. switch ( pSockaddr->sa_family )
  141. {
  142. case AF_INET:
  143. IP6_SET_ADDR_V4MAPPED(
  144. & ip6,
  145. ((PSOCKADDR_IN)pSockaddr)->sin_addr.s_addr );
  146. break;
  147. case AF_INET6:
  148. RtlCopyMemory(
  149. &ip6,
  150. & ((PSOCKADDR_IN6)pSockaddr)->sin6_addr,
  151. sizeof(IP6_ADDRESS) );
  152. break;
  153. default:
  154. RtlZeroMemory(
  155. &ip6,
  156. sizeof(IP6_ADDRESS) );
  157. break;
  158. }
  159. return ip6;
  160. }
  161. VOID
  162. InitSockaddrWithIp6Address(
  163. OUT PSOCKADDR pSockaddr,
  164. IN IP6_ADDRESS Ip6Addr,
  165. IN WORD Port
  166. )
  167. /*++
  168. Routine Description:
  169. Write IP6 address (straight 6 or v4 mapped) to sockaddr.
  170. Arguments:
  171. pSockaddr -- ptr to sockaddr to write to;
  172. must be at least size of SOCKADDR_IN6
  173. Ip6Addr -- IP6 addresss being written
  174. Port -- port in net byte order
  175. Return Value:
  176. None
  177. --*/
  178. {
  179. // zero
  180. RtlZeroMemory(
  181. pSockaddr,
  182. sizeof(SOCKADDR_IN6) );
  183. //
  184. // determine whether IP6 or IP4
  185. //
  186. if ( IP6_IS_ADDR_V4MAPPED( &Ip6Addr ) )
  187. {
  188. PSOCKADDR_IN psa = (PSOCKADDR_IN) pSockaddr;
  189. psa->sin_family = AF_INET;
  190. psa->sin_port = Port;
  191. psa->sin_addr.s_addr = IP6_GET_V4_ADDR( &Ip6Addr );
  192. }
  193. else // IP6
  194. {
  195. PSOCKADDR_IN6 psa = (PSOCKADDR_IN6) pSockaddr;
  196. psa->sin6_family = AF_INET6;
  197. psa->sin6_port = Port;
  198. RtlCopyMemory(
  199. &psa->sin6_addr,
  200. &Ip6Addr,
  201. sizeof(IP6_ADDRESS) );
  202. }
  203. }
  204. DNS_STATUS
  205. Dns_AddressToSockaddr(
  206. OUT PSOCKADDR pSockaddr,
  207. IN OUT PDWORD pSockaddrLength,
  208. IN BOOL fClearSockaddr,
  209. IN PBYTE pAddr,
  210. IN DWORD AddrLength,
  211. IN DWORD AddrFamily
  212. )
  213. /*++
  214. Routine Description:
  215. Convert address in ptr\family\length to sockaddr.
  216. Arguments:
  217. pSockaddr -- sockaddr buffer to recv address
  218. pSockaddrLength -- addr with length of sockaddr buffer
  219. receives the actual sockaddr length
  220. fClearSockaddr -- start with zero buffer
  221. pAddr -- ptr to address
  222. AddrLength -- address length
  223. AddrFamily -- address family (AF_INET, AF_INET6)
  224. Return Value:
  225. NO_ERROR if successful.
  226. ERROR_INSUFFICIENT_BUFFER -- if buffer too small
  227. WSAEAFNOSUPPORT -- if invalid family
  228. --*/
  229. {
  230. PFAMILY_INFO pinfo;
  231. DWORD lengthIn = *pSockaddrLength;
  232. DWORD lengthSockAddr;
  233. // clear to start
  234. if ( fClearSockaddr )
  235. {
  236. RtlZeroMemory(
  237. pSockaddr,
  238. lengthIn );
  239. }
  240. // switch on type
  241. if ( AddrFamily == AF_INET )
  242. {
  243. pinfo = pFamilyInfoIp4;
  244. }
  245. else if ( AddrFamily == AF_INET6 )
  246. {
  247. pinfo = pFamilyInfoIp6;
  248. }
  249. else if ( AddrFamily == AF_ATM )
  250. {
  251. pinfo = pFamilyInfoAtm;
  252. }
  253. else
  254. {
  255. return WSAEAFNOSUPPORT;
  256. }
  257. // validate lengths
  258. if ( AddrLength != pinfo->LengthAddr )
  259. {
  260. return DNS_ERROR_INVALID_IP_ADDRESS;
  261. }
  262. lengthSockAddr = pinfo->LengthSockaddr;
  263. *pSockaddrLength = lengthSockAddr;
  264. if ( lengthIn < lengthSockAddr )
  265. {
  266. return ERROR_INSUFFICIENT_BUFFER;
  267. }
  268. //
  269. // fill out sockaddr
  270. // - set family
  271. // - copy address to sockaddr
  272. // - return length was set above
  273. //
  274. RtlCopyMemory(
  275. (PBYTE)pSockaddr + pinfo->OffsetToAddrInSockaddr,
  276. pAddr,
  277. AddrLength );
  278. pSockaddr->sa_family = (WORD)AddrFamily;
  279. return NO_ERROR;
  280. }
  281. #if 0
  282. // without family info
  283. DNS_STATUS
  284. Dns_AddressToSockaddr(
  285. OUT PSOCKADDR pSockaddr,
  286. IN OUT PDWORD pSockaddrLength,
  287. IN BOOL fClearSockaddr,
  288. IN PBYTE pAddr,
  289. IN DWORD AddrLength,
  290. IN DWORD AddrFamily
  291. )
  292. /*++
  293. Routine Description:
  294. Convert address in ptr\family\length to sockaddr.
  295. Arguments:
  296. pSockaddr -- sockaddr buffer to recv address
  297. pSockaddrLength -- addr with length of sockaddr buffer
  298. receives the actual sockaddr length
  299. fClearSockaddr -- start with zero buffer
  300. pAddr -- ptr to address
  301. AddrLength -- address length
  302. AddrFamily -- address family (AF_INET, AF_INET6)
  303. Return Value:
  304. NO_ERROR if successful.
  305. ERROR_INSUFFICIENT_BUFFER -- if buffer too small
  306. WSAEAFNOSUPPORT -- if invalid family
  307. --*/
  308. {
  309. DWORD lengthIn = *pSockaddrLength;
  310. DWORD lengthSockAddr;
  311. DWORD lengthAddr;
  312. PBYTE paddrInSockaddr;
  313. // clear to start
  314. if ( fClearSockaddr )
  315. {
  316. RtlZeroMemory(
  317. pSockaddr,
  318. lengthIn );
  319. }
  320. // switch on type
  321. if ( Family == AF_INET )
  322. {
  323. lengthSockAddr = sizeof(SOCKADDR_IN);
  324. lengthAddr = sizeof(IP4_ADDRESS);
  325. paddrInSockaddr = (PBYTE) &((PSOCKADDR_IN)pSockaddr)->sin_addr,
  326. }
  327. else if ( Family == AF_INET6 )
  328. {
  329. lengthSockAddr = sizeof(SOCKADDR_IN6);
  330. lengthAddr = sizeof(IP6_ADDRESS);
  331. paddrInSockaddr = (PBYTE) &((PSOCKADDR_IN6)pSockaddr)->sin6_addr,
  332. }
  333. else
  334. {
  335. return WSAEAFNOSUPPORT;
  336. }
  337. // validate lengths
  338. if ( AddrLength != lengthAddr )
  339. {
  340. return DNS_ERROR_INVALID_IP_ADDRESS;
  341. }
  342. if ( lengthIn < lengthSockAddr )
  343. {
  344. *pSockaddrLength = lengthSockAddr;
  345. return ERROR_INSUFFICIENT_BUFFER;
  346. }
  347. //
  348. // fill out sockaddr
  349. // - set family
  350. // - copy address to sockaddr
  351. // - set return length
  352. //
  353. RtlCopyMemory(
  354. paddrInSockaddr,
  355. pAddr,
  356. lengthAddr );
  357. }
  358. else // IP6
  359. {
  360. if ( length < sizeof(SOCKADDR_IN) )
  361. {
  362. return ERROR_INSUFFICIENT_BUFFER;
  363. }
  364. RtlCopyMemory(
  365. & ((PSOCKADDR_IN6)pSockaddr)->sin6_addr,
  366. pAddr,
  367. AddrLength );
  368. }
  369. // DCR: ATM sockaddr
  370. pSockaddr->sa_family = Family;
  371. return NO_ERROR;
  372. }
  373. #endif
  374. BOOL
  375. Dns_SockaddrToIpUnion(
  376. OUT PIP_UNION pIpUnion,
  377. IN PSOCKADDR pSockaddr
  378. )
  379. /*++
  380. Routine Description:
  381. Build IP union from sockaddr.
  382. Arguments:
  383. pIpUnion -- ptr IP union to build
  384. pSockaddr -- sockaddr
  385. Return Value:
  386. TRUE if successfully created IP union.
  387. FALSE otherwise.
  388. --*/
  389. {
  390. PFAMILY_INFO pinfo;
  391. WORD family = pSockaddr->sa_family;
  392. BOOL fIs6;
  393. //
  394. // only support IP4 and IP6
  395. //
  396. // DCR: could add IP_UNION support to family info
  397. //
  398. if ( family == AF_INET )
  399. {
  400. fIs6 = FALSE;
  401. }
  402. else if ( family == AF_INET6 )
  403. {
  404. fIs6 = TRUE;
  405. }
  406. else
  407. {
  408. return FALSE;
  409. }
  410. //
  411. // get family info for unitary copy
  412. //
  413. pinfo = FamilyInfo_GetForFamily( family );
  414. if ( !pinfo )
  415. {
  416. DNS_ASSERT( FALSE );
  417. return FALSE;
  418. }
  419. RtlCopyMemory(
  420. (PBYTE) &pIpUnion->Addr,
  421. (PBYTE)pSockaddr + pinfo->OffsetToAddrInSockaddr,
  422. pinfo->LengthAddr );
  423. pIpUnion->IsIp6 = fIs6;
  424. return TRUE;
  425. }
  426. DWORD
  427. Family_SockaddrLength(
  428. IN WORD Family
  429. )
  430. /*++
  431. Routine Description:
  432. Extract info for family.
  433. Arguments:
  434. Family -- address family
  435. Return Value:
  436. Length of sockaddr for address family.
  437. Zero if unknown family.
  438. --*/
  439. {
  440. PFAMILY_INFO pinfo;
  441. // get family -- extract info
  442. pinfo = FamilyInfo_GetForFamily( Family );
  443. if ( pinfo )
  444. {
  445. return pinfo->LengthSockaddr;
  446. }
  447. return 0;
  448. }
  449. DWORD
  450. Sockaddr_Length(
  451. IN PSOCKADDR pSockaddr
  452. )
  453. /*++
  454. Routine Description:
  455. Get length of sockaddr.
  456. Arguments:
  457. pSockaddr -- sockaddr buffer to recv address
  458. Return Value:
  459. Length of sockaddr for address family.
  460. Zero if unknown family.
  461. --*/
  462. {
  463. return Family_SockaddrLength( pSockaddr->sa_family );
  464. }
  465. //
  466. // End addr.c
  467. //