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

582 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. ip6util.c
  5. Abstract:
  6. Some IP6 utilities
  7. Author:
  8. Jiandong Ruan
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #ifndef isxdigit_W
  13. #define isxdigit_W(x) \
  14. ((x >= L'0' && x <= L'9') || \
  15. (x >= L'a' && x <= L'f') || \
  16. (x >= L'A' && x <= L'F'))
  17. #endif
  18. #ifndef isdigit_W
  19. #define isdigit_W(x) (x >= L'0' && x <= L'9')
  20. #endif
  21. ULONG __inline
  22. xdigit2hex(WCHAR ch)
  23. {
  24. ASSERT(isxdigit_W(ch));
  25. if (ch <= L'9') {
  26. return (ch - L'0');
  27. } else if (ch >= L'A' && ch <= L'F') {
  28. return (ch - L'A') + 10;
  29. } else {
  30. return (ch - L'a') + 10;
  31. }
  32. }
  33. BOOL
  34. inet_addr6W(
  35. IN WCHAR *str,
  36. IN OUT PSMB_IP6_ADDRESS addr
  37. )
  38. /*++
  39. Routine Description:
  40. Convert an unicode string into a IP6 address (network order).
  41. The L(3) grammar of the IP6 address:
  42. start: head COLON COLON tail
  43. head: hexs
  44. tail: hexs
  45. hexs: hex COLON hexs
  46. |
  47. COLON: ':'
  48. A 5-state automata is used to parse the string,
  49. states: {S, A, B, C, D}
  50. Starting state: S
  51. Accepting state: {S, B, C}
  52. state transition rules:
  53. S ==> S on a hex digit
  54. S ==> A on a COLON
  55. A ==> S on a hex digit
  56. A ==> B on a COLON
  57. B ==> C on a hex digit
  58. C ==> C on a hex digit
  59. C ==> D on a COLON
  60. D ==> C on a hex digit
  61. Arguments:
  62. str The unicode string containing the IP6 address
  63. addr The output IP6 address
  64. Return Value:
  65. TRUE if the string is accepted by the automata and an IP6 address (network order)
  66. is return in the 'addr'
  67. FALSE if the string is rejected by the automata
  68. result in 'addr' is undetermined.
  69. --*/
  70. {
  71. enum { STATE_S, STATE_A, STATE_B, STATE_C, STATE_D } state;
  72. int i, num, tail;
  73. ULONG hex;
  74. WCHAR ch;
  75. state = STATE_S;
  76. addr->sin6_scope_id = 0;
  77. num = 0;
  78. tail = 0;
  79. hex = 0;
  80. while ((ch = *str++)) {
  81. if (ch == '%') {
  82. break;
  83. }
  84. if (!isxdigit_W(ch) && ch != L':') {
  85. return FALSE;
  86. }
  87. switch(state) {
  88. case STATE_S:
  89. if (L':' == ch) {
  90. state = STATE_A;
  91. } else {
  92. hex <<= 4;
  93. hex |= xdigit2hex(ch);
  94. if (hex > 0xFFFFU) {
  95. return FALSE;
  96. }
  97. }
  98. break;
  99. case STATE_A:
  100. if (L':' == ch) {
  101. state = STATE_B;
  102. } else {
  103. if (num >= 8) {
  104. return FALSE;
  105. }
  106. addr->sin6_addr[num++] = htons((USHORT)hex);
  107. hex = xdigit2hex(ch);
  108. state = STATE_S;
  109. }
  110. break;
  111. case STATE_B:
  112. if (L':' == ch) {
  113. return FALSE;
  114. }
  115. if (num >= 8) {
  116. return FALSE;
  117. }
  118. addr->sin6_addr[num++] = htons((USHORT)hex);
  119. tail = num;
  120. hex = xdigit2hex(ch);
  121. state = STATE_C;
  122. break;
  123. case STATE_C:
  124. if (L':' == ch) {
  125. state = STATE_D;
  126. } else {
  127. hex <<= 4;
  128. hex |= xdigit2hex(ch);
  129. if (hex > 0xFFFFU) {
  130. return FALSE;
  131. }
  132. }
  133. break;
  134. case STATE_D:
  135. if (L':' == ch) {
  136. return FALSE;
  137. }
  138. if (num >= 8) {
  139. return FALSE;
  140. }
  141. addr->sin6_addr[num++] = htons((USHORT)hex);
  142. hex = xdigit2hex(ch);
  143. state = STATE_C;
  144. break;
  145. }
  146. }
  147. //
  148. // Reject it since it ends up with a rejecting state.
  149. //
  150. if (state == STATE_A || state == STATE_D) {
  151. return FALSE;
  152. }
  153. if (num >= 8) {
  154. return FALSE;
  155. }
  156. addr->sin6_addr[num++] = htons((USHORT)hex);
  157. if (state == STATE_B) {
  158. for (i = num; i < 8; i++) {
  159. addr->sin6_addr[i] = 0;
  160. }
  161. return TRUE;
  162. } else if (state == STATE_S) {
  163. return (8 == num);
  164. }
  165. ASSERT (state == STATE_C);
  166. ASSERT(tail <= num);
  167. for (i = num - 1; i >= tail; i--) {
  168. addr->sin6_addr[8 - num + i] = addr->sin6_addr[i];
  169. }
  170. for (i = tail; i < 8 - num + tail; i++) {
  171. addr->sin6_addr[i] = 0;
  172. }
  173. //
  174. // Parse the scope ID
  175. //
  176. if (ch == '%') {
  177. LONG scope_id;
  178. scope_id = 0;
  179. while ((ch = *str++)) {
  180. if (!isdigit_W(ch)) {
  181. return FALSE;
  182. }
  183. scope_id = scope_id * 10 + (ch - L'0');
  184. }
  185. addr->sin6_scope_id = scope_id;
  186. }
  187. return TRUE;
  188. }
  189. BOOL
  190. inet_ntoa6W(
  191. OUT WCHAR *Buffer,
  192. IN DWORD Size,
  193. IN PSMB_IP6_ADDRESS addr
  194. )
  195. {
  196. USHORT ch, tmp;
  197. int i, tail, len, curtail, curlen;
  198. DWORD j, k;
  199. tail = 8;
  200. len = 0;
  201. curtail = curlen = 0;
  202. for (i = 0; i < 8; i++) {
  203. if (0 == addr->sin6_addr[i]) {
  204. curlen++;
  205. } else {
  206. if (curlen > len) {
  207. tail = curtail;
  208. len = curlen;
  209. }
  210. curtail = i + 1;
  211. curlen = 0;
  212. }
  213. }
  214. if (curlen > len) {
  215. tail = curtail;
  216. len = curlen;
  217. }
  218. j = 0;
  219. for (i = 0; i < tail; i++) {
  220. ch = htons(addr->sin6_addr[i]);
  221. if (ch) {
  222. k = 4;
  223. while (0 == (ch & 0xf000)) {
  224. ch <<= 4;
  225. k--;
  226. }
  227. } else {
  228. k = 1;
  229. }
  230. while (j < Size) {
  231. tmp = (ch & 0xf000) >> 12;
  232. ch <<= 4;
  233. if (tmp < 10) {
  234. Buffer[j] = L'0' + tmp;
  235. } else {
  236. Buffer[j] = L'A' + (tmp - 10);
  237. }
  238. j++;
  239. k--;
  240. if (k == 0) {
  241. break;
  242. }
  243. }
  244. if (k) {
  245. Buffer[Size-1] = L'\0';
  246. return FALSE;
  247. }
  248. if (i != tail - 1) {
  249. if (j < Size) {
  250. Buffer[j++] = L':';
  251. } else {
  252. Buffer[Size-1] = L'\0';
  253. return FALSE;
  254. }
  255. }
  256. }
  257. if (tail == 8) {
  258. if (j < Size) {
  259. Buffer[j] = L'\0';
  260. return TRUE;
  261. } else {
  262. Buffer[Size-1] = L'\0';
  263. return FALSE;
  264. }
  265. }
  266. if (j < Size) {
  267. Buffer[j++] = L':';
  268. } else {
  269. Buffer[Size-1] = L'\0';
  270. return FALSE;
  271. }
  272. if (tail + len >= 8) {
  273. if (j < Size) {
  274. Buffer[j++] = L':';
  275. } else {
  276. Buffer[Size-1] = L'\0';
  277. return FALSE;
  278. }
  279. }
  280. for (i = tail + len; i < 8; i++) {
  281. if (j < Size) {
  282. Buffer[j++] = L':';
  283. } else {
  284. Buffer[Size-1] = L'\0';
  285. return FALSE;
  286. }
  287. ch = htons(addr->sin6_addr[i]);
  288. if (ch) {
  289. k = 4;
  290. while (0 == (ch & 0xf000)) {
  291. ch <<= 4;
  292. k--;
  293. }
  294. } else {
  295. k = 1;
  296. }
  297. while (j < Size) {
  298. tmp = (ch & 0xf000) >> 12;
  299. ch <<= 4;
  300. if (tmp < 10) {
  301. Buffer[j] = L'0' + tmp;
  302. } else {
  303. Buffer[j] = L'A' + (tmp - 10);
  304. }
  305. j++;
  306. k--;
  307. if (k == 0) {
  308. break;
  309. }
  310. }
  311. if (k) {
  312. Buffer[Size-1] = L'\0';
  313. return FALSE;
  314. }
  315. }
  316. if (j < Size) {
  317. Buffer[j] = L'\0';
  318. return TRUE;
  319. } else {
  320. Buffer[Size-1] = L'\0';
  321. return FALSE;
  322. }
  323. }
  324. BOOL
  325. inet_ntoa6(
  326. OUT CHAR *Buffer,
  327. IN DWORD Size,
  328. IN PSMB_IP6_ADDRESS addr
  329. )
  330. {
  331. DWORD i;
  332. WCHAR wBuf[40];
  333. if (!inet_ntoa6W(wBuf, 40, addr)) {
  334. return FALSE;
  335. }
  336. //
  337. // Don't call Rtl routine to convert
  338. // Unicode into Oem because we may
  339. // run at DISPATCH level
  340. //
  341. // For this particular case, we can
  342. // simply do type-cast coping.
  343. //
  344. for (i = 0; i < Size; i++) {
  345. Buffer[i] = (BYTE)(wBuf[i]);
  346. if (wBuf[i] == 0) {
  347. return TRUE;
  348. }
  349. }
  350. //
  351. // Buffer is too small
  352. //
  353. Buffer[Size-1] = 0;
  354. return FALSE;
  355. }
  356. /*********************************************************************************
  357. * inet_addr Copy from winsocket
  358. *********************************************************************************/
  359. /*
  360. * Internet address interpretation routine.
  361. * All the network library routines call this
  362. * routine to interpret entries in the data bases
  363. * which are expected to be an address.
  364. * The value returned is in network order.
  365. */
  366. unsigned long PASCAL
  367. inet_addrW(
  368. IN WCHAR *cp
  369. )
  370. /*++
  371. Routine Description:
  372. This function interprets the character string specified by the cp
  373. parameter. This string represents a numeric Internet address
  374. expressed in the Internet standard ".'' notation. The value
  375. returned is a number suitable for use as an Internet address. All
  376. Internet addresses are returned in network order (bytes ordered from
  377. left to right).
  378. Internet Addresses
  379. Values specified using the "." notation take one of the following
  380. forms:
  381. a.b.c.d a.b.c a.b a
  382. When four parts are specified, each is interpreted as a byte of data
  383. and assigned, from left to right, to the four bytes of an Internet
  384. address. Note that when an Internet address is viewed as a 32-bit
  385. integer quantity on the Intel architecture, the bytes referred to
  386. above appear as "d.c.b.a''. That is, the bytes on an Intel
  387. processor are ordered from right to left.
  388. Note: The following notations are only used by Berkeley, and nowhere
  389. else on the Internet. In the interests of compatibility with their
  390. software, they are supported as specified.
  391. When a three part address is specified, the last part is interpreted
  392. as a 16-bit quantity and placed in the right most two bytes of the
  393. network address. This makes the three part address format
  394. convenient for specifying Class B network addresses as
  395. "128.net.host''.
  396. When a two part address is specified, the last part is interpreted
  397. as a 24-bit quantity and placed in the right most three bytes of the
  398. network address. This makes the two part address format convenient
  399. for specifying Class A network addresses as "net.host''.
  400. When only one part is given, the value is stored directly in the
  401. network address without any byte rearrangement.
  402. Arguments:
  403. cp - A character string representing a number expressed in the
  404. Internet standard "." notation.
  405. Return Value:
  406. If no error occurs, inet_addr() returns an in_addr structure
  407. containing a suitable binary representation of the Internet address
  408. given. Otherwise, it returns the value INADDR_NONE.
  409. --*/
  410. {
  411. register unsigned long val, base, n;
  412. register WCHAR c;
  413. unsigned long parts[4], *pp = parts;
  414. again:
  415. /*
  416. * Collect number up to ``.''.
  417. * Values are specified as for C:
  418. * 0x=hex, 0=octal, other=decimal.
  419. */
  420. val = 0; base = 10;
  421. if (*cp == L'0') {
  422. base = 8, cp++;
  423. if (*cp == L'x' || *cp == L'X')
  424. base = 16, cp++;
  425. }
  426. while (c = *cp) {
  427. if (isdigit(c)) {
  428. val = (val * base) + (c - L'0');
  429. cp++;
  430. continue;
  431. }
  432. if (base == 16 && isxdigit(c)) {
  433. val = (val << 4) + (c + 10 - (islower(c) ? L'a' : L'A'));
  434. cp++;
  435. continue;
  436. }
  437. break;
  438. }
  439. if (*cp == L'.') {
  440. /*
  441. * Internet format:
  442. * a.b.c.d
  443. * a.b.c (with c treated as 16-bits)
  444. * a.b (with b treated as 24 bits)
  445. */
  446. /* GSS - next line was corrected on 8/5/89, was 'parts + 4' */
  447. if (pp >= parts + 3) {
  448. return ((unsigned long) -1);
  449. }
  450. *pp++ = val, cp++;
  451. goto again;
  452. }
  453. /*
  454. * Check for trailing characters.
  455. */
  456. if (*cp && !isspace(*cp)) {
  457. return (INADDR_NONE);
  458. }
  459. *pp++ = val;
  460. /*
  461. * Concoct the address according to
  462. * the number of parts specified.
  463. */
  464. n = (unsigned long)(pp - parts);
  465. switch ((int) n) {
  466. case 1: /* a -- 32 bits */
  467. val = parts[0];
  468. break;
  469. case 2: /* a.b -- 8.24 bits */
  470. if ((parts[0] > 0xff) || (parts[1] > 0xffffff)) {
  471. return(INADDR_NONE);
  472. }
  473. val = (parts[0] << 24) | (parts[1] & 0xffffff);
  474. break;
  475. case 3: /* a.b.c -- 8.8.16 bits */
  476. if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
  477. (parts[2] > 0xffff)) {
  478. return(INADDR_NONE);
  479. }
  480. val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
  481. (parts[2] & 0xffff);
  482. break;
  483. case 4: /* a.b.c.d -- 8.8.8.8 bits */
  484. if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
  485. (parts[2] > 0xff) || (parts[3] > 0xff)) {
  486. return(INADDR_NONE);
  487. }
  488. val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
  489. ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
  490. break;
  491. default:
  492. return (INADDR_NONE);
  493. }
  494. val = htonl(val);
  495. return (val);
  496. }