ipaux.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "ip.h"
  8. #include "ipv6.h"
  9. /*
  10. * well known IP addresses
  11. */
  12. uchar IPv4bcast[IPaddrlen] = {
  13. 0, 0, 0, 0,
  14. 0, 0, 0, 0,
  15. 0, 0, 0xff, 0xff,
  16. 0xff, 0xff, 0xff, 0xff
  17. };
  18. uchar IPv4allsys[IPaddrlen] = {
  19. 0, 0, 0, 0,
  20. 0, 0, 0, 0,
  21. 0, 0, 0xff, 0xff,
  22. 0xe0, 0, 0, 0x01
  23. };
  24. uchar IPv4allrouter[IPaddrlen] = {
  25. 0, 0, 0, 0,
  26. 0, 0, 0, 0,
  27. 0, 0, 0xff, 0xff,
  28. 0xe0, 0, 0, 0x02
  29. };
  30. uchar IPallbits[IPaddrlen] = {
  31. 0xff, 0xff, 0xff, 0xff,
  32. 0xff, 0xff, 0xff, 0xff,
  33. 0xff, 0xff, 0xff, 0xff,
  34. 0xff, 0xff, 0xff, 0xff
  35. };
  36. uchar IPnoaddr[IPaddrlen];
  37. /*
  38. * prefix of all v4 addresses
  39. */
  40. uchar v4prefix[IPaddrlen] = {
  41. 0, 0, 0, 0,
  42. 0, 0, 0, 0,
  43. 0, 0, 0xff, 0xff,
  44. 0, 0, 0, 0
  45. };
  46. char *v6hdrtypes[Maxhdrtype] =
  47. {
  48. [HBH] "HopbyHop",
  49. [ICMP] "ICMP",
  50. [IGMP] "IGMP",
  51. [GGP] "GGP",
  52. [IPINIP] "IP",
  53. [ST] "ST",
  54. [TCP] "TCP",
  55. [UDP] "UDP",
  56. [ISO_TP4] "ISO_TP4",
  57. [RH] "Routinghdr",
  58. [FH] "Fraghdr",
  59. [IDRP] "IDRP",
  60. [RSVP] "RSVP",
  61. [AH] "Authhdr",
  62. [ESP] "ESP",
  63. [ICMPv6] "ICMPv6",
  64. [NNH] "Nonexthdr",
  65. [ISO_IP] "ISO_IP",
  66. [IGRP] "IGRP",
  67. [OSPF] "OSPF",
  68. };
  69. /*
  70. * well known IPv6 addresses
  71. */
  72. uchar v6Unspecified[IPaddrlen] = {
  73. 0, 0, 0, 0,
  74. 0, 0, 0, 0,
  75. 0, 0, 0, 0,
  76. 0, 0, 0, 0
  77. };
  78. uchar v6loopback[IPaddrlen] = {
  79. 0, 0, 0, 0,
  80. 0, 0, 0, 0,
  81. 0, 0, 0, 0,
  82. 0, 0, 0, 0x01
  83. };
  84. uchar v6linklocal[IPaddrlen] = {
  85. 0xfe, 0x80, 0, 0,
  86. 0, 0, 0, 0,
  87. 0, 0, 0, 0,
  88. 0, 0, 0, 0
  89. };
  90. uchar v6linklocalmask[IPaddrlen] = {
  91. 0xff, 0xff, 0xff, 0xff,
  92. 0xff, 0xff, 0xff, 0xff,
  93. 0, 0, 0, 0,
  94. 0, 0, 0, 0
  95. };
  96. int v6llpreflen = 8; // link-local prefix length
  97. uchar v6sitelocal[IPaddrlen] = {
  98. 0xfe, 0xc0, 0, 0,
  99. 0, 0, 0, 0,
  100. 0, 0, 0, 0,
  101. 0, 0, 0, 0
  102. };
  103. uchar v6sitelocalmask[IPaddrlen] = {
  104. 0xff, 0xff, 0xff, 0xff,
  105. 0xff, 0xff, 0xff, 0xff,
  106. 0, 0, 0, 0,
  107. 0, 0, 0, 0
  108. };
  109. int v6slpreflen = 6; // site-local prefix length
  110. uchar v6glunicast[IPaddrlen] = {
  111. 0x08, 0, 0, 0,
  112. 0, 0, 0, 0,
  113. 0, 0, 0, 0,
  114. 0, 0, 0, 0
  115. };
  116. uchar v6multicast[IPaddrlen] = {
  117. 0xff, 0, 0, 0,
  118. 0, 0, 0, 0,
  119. 0, 0, 0, 0,
  120. 0, 0, 0, 0
  121. };
  122. uchar v6multicastmask[IPaddrlen] = {
  123. 0xff, 0, 0, 0,
  124. 0, 0, 0, 0,
  125. 0, 0, 0, 0,
  126. 0, 0, 0, 0
  127. };
  128. int v6mcpreflen = 1; // multicast prefix length
  129. uchar v6allnodesN[IPaddrlen] = {
  130. 0xff, 0x01, 0, 0,
  131. 0, 0, 0, 0,
  132. 0, 0, 0, 0,
  133. 0, 0, 0, 0x01
  134. };
  135. uchar v6allnodesNmask[IPaddrlen] = {
  136. 0xff, 0xff, 0, 0,
  137. 0, 0, 0, 0,
  138. 0, 0, 0, 0,
  139. 0, 0, 0, 0
  140. };
  141. int v6aNpreflen = 2; // all nodes (N) prefix
  142. uchar v6allnodesL[IPaddrlen] = {
  143. 0xff, 0x02, 0, 0,
  144. 0, 0, 0, 0,
  145. 0, 0, 0, 0,
  146. 0, 0, 0, 0x01
  147. };
  148. uchar v6allnodesLmask[IPaddrlen] = {
  149. 0xff, 0xff, 0, 0,
  150. 0, 0, 0, 0,
  151. 0, 0, 0, 0,
  152. 0, 0, 0, 0
  153. };
  154. int v6aLpreflen = 2; // all nodes (L) prefix
  155. uchar v6allroutersN[IPaddrlen] = {
  156. 0xff, 0x01, 0, 0,
  157. 0, 0, 0, 0,
  158. 0, 0, 0, 0,
  159. 0, 0, 0, 0x02
  160. };
  161. uchar v6allroutersL[IPaddrlen] = {
  162. 0xff, 0x02, 0, 0,
  163. 0, 0, 0, 0,
  164. 0, 0, 0, 0,
  165. 0, 0, 0, 0x02
  166. };
  167. uchar v6allroutersS[IPaddrlen] = {
  168. 0xff, 0x05, 0, 0,
  169. 0, 0, 0, 0,
  170. 0, 0, 0, 0,
  171. 0, 0, 0, 0x02
  172. };
  173. uchar v6solicitednode[IPaddrlen] = {
  174. 0xff, 0x02, 0, 0,
  175. 0, 0, 0, 0,
  176. 0, 0, 0, 0x01,
  177. 0xff, 0, 0, 0
  178. };
  179. uchar v6solicitednodemask[IPaddrlen] = {
  180. 0xff, 0xff, 0xff, 0xff,
  181. 0xff, 0xff, 0xff, 0xff,
  182. 0xff, 0xff, 0xff, 0xff,
  183. 0xff, 0x0, 0x0, 0x0
  184. };
  185. int v6snpreflen = 13;
  186. ushort
  187. ptclcsum(Block *bp, int offset, int len)
  188. {
  189. uchar *addr;
  190. ulong losum, hisum;
  191. ushort csum;
  192. int odd, blocklen, x;
  193. /* Correct to front of data area */
  194. while(bp != nil && offset && offset >= BLEN(bp)) {
  195. offset -= BLEN(bp);
  196. bp = bp->next;
  197. }
  198. if(bp == nil)
  199. return 0;
  200. addr = bp->rp + offset;
  201. blocklen = BLEN(bp) - offset;
  202. if(bp->next == nil) {
  203. if(blocklen < len)
  204. len = blocklen;
  205. return ~ptclbsum(addr, len) & 0xffff;
  206. }
  207. losum = 0;
  208. hisum = 0;
  209. odd = 0;
  210. while(len) {
  211. x = blocklen;
  212. if(len < x)
  213. x = len;
  214. csum = ptclbsum(addr, x);
  215. if(odd)
  216. hisum += csum;
  217. else
  218. losum += csum;
  219. odd = (odd+x) & 1;
  220. len -= x;
  221. bp = bp->next;
  222. if(bp == nil)
  223. break;
  224. blocklen = BLEN(bp);
  225. addr = bp->rp;
  226. }
  227. losum += hisum>>8;
  228. losum += (hisum&0xff)<<8;
  229. while((csum = losum>>16) != 0)
  230. losum = csum + (losum & 0xffff);
  231. return ~losum & 0xffff;
  232. }
  233. enum
  234. {
  235. Isprefix= 16,
  236. };
  237. static uchar prefixvals[256] =
  238. {
  239. [0x00] 0 | Isprefix,
  240. [0x80] 1 | Isprefix,
  241. [0xC0] 2 | Isprefix,
  242. [0xE0] 3 | Isprefix,
  243. [0xF0] 4 | Isprefix,
  244. [0xF8] 5 | Isprefix,
  245. [0xFC] 6 | Isprefix,
  246. [0xFE] 7 | Isprefix,
  247. [0xFF] 8 | Isprefix,
  248. };
  249. int
  250. eipfmt(Fmt *f)
  251. {
  252. char buf[5*8];
  253. static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
  254. static char *ifmt = "%d.%d.%d.%d";
  255. uchar *p, ip[16];
  256. ulong *lp;
  257. ushort s;
  258. int i, j, n, eln, eli;
  259. switch(f->r) {
  260. case 'E': /* Ethernet address */
  261. p = va_arg(f->args, uchar*);
  262. snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
  263. return fmtstrcpy(f, buf);
  264. case 'I': /* Ip address */
  265. p = va_arg(f->args, uchar*);
  266. common:
  267. if(memcmp(p, v4prefix, 12) == 0){
  268. snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
  269. return fmtstrcpy(f, buf);
  270. }
  271. /* find longest elision */
  272. eln = eli = -1;
  273. for(i = 0; i < 16; i += 2){
  274. for(j = i; j < 16; j += 2)
  275. if(p[j] != 0 || p[j+1] != 0)
  276. break;
  277. if(j > i && j - i > eln){
  278. eli = i;
  279. eln = j - i;
  280. }
  281. }
  282. /* print with possible elision */
  283. n = 0;
  284. for(i = 0; i < 16; i += 2){
  285. if(i == eli){
  286. n += sprint(buf+n, "::");
  287. i += eln;
  288. if(i >= 16)
  289. break;
  290. } else if(i != 0)
  291. n += sprint(buf+n, ":");
  292. s = (p[i]<<8) + p[i+1];
  293. n += sprint(buf+n, "%ux", s);
  294. }
  295. return fmtstrcpy(f, buf);
  296. case 'i': /* v6 address as 4 longs */
  297. lp = va_arg(f->args, ulong*);
  298. for(i = 0; i < 4; i++)
  299. hnputl(ip+4*i, *lp++);
  300. p = ip;
  301. goto common;
  302. case 'V': /* v4 ip address */
  303. p = va_arg(f->args, uchar*);
  304. snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
  305. return fmtstrcpy(f, buf);
  306. case 'M': /* ip mask */
  307. p = va_arg(f->args, uchar*);
  308. /* look for a prefix mask */
  309. for(i = 0; i < 16; i++)
  310. if(p[i] != 0xff)
  311. break;
  312. if(i < 16){
  313. if((prefixvals[p[i]] & Isprefix) == 0)
  314. goto common;
  315. for(j = i+1; j < 16; j++)
  316. if(p[j] != 0)
  317. goto common;
  318. n = 8*i + (prefixvals[p[i]] & ~Isprefix);
  319. } else
  320. n = 8*16;
  321. /* got one, use /xx format */
  322. snprint(buf, sizeof buf, "/%d", n);
  323. return fmtstrcpy(f, buf);
  324. }
  325. return fmtstrcpy(f, "(eipfmt)");
  326. }
  327. #define CLASS(p) ((*(uchar*)(p))>>6)
  328. extern char*
  329. v4parseip(uchar *to, char *from)
  330. {
  331. int i;
  332. char *p;
  333. p = from;
  334. for(i = 0; i < 4 && *p; i++){
  335. to[i] = strtoul(p, &p, 0);
  336. if(*p == '.')
  337. p++;
  338. }
  339. switch(CLASS(to)){
  340. case 0: /* class A - 1 uchar net */
  341. case 1:
  342. if(i == 3){
  343. to[3] = to[2];
  344. to[2] = to[1];
  345. to[1] = 0;
  346. } else if(i == 2){
  347. to[3] = to[1];
  348. to[1] = 0;
  349. }
  350. break;
  351. case 2: /* class B - 2 uchar net */
  352. if(i == 3){
  353. to[3] = to[2];
  354. to[2] = 0;
  355. }
  356. break;
  357. }
  358. return p;
  359. }
  360. int
  361. isv4(uchar *ip)
  362. {
  363. return memcmp(ip, v4prefix, IPv4off) == 0;
  364. }
  365. /*
  366. * the following routines are unrolled with no memset's to speed
  367. * up the usual case
  368. */
  369. void
  370. v4tov6(uchar *v6, uchar *v4)
  371. {
  372. v6[0] = 0;
  373. v6[1] = 0;
  374. v6[2] = 0;
  375. v6[3] = 0;
  376. v6[4] = 0;
  377. v6[5] = 0;
  378. v6[6] = 0;
  379. v6[7] = 0;
  380. v6[8] = 0;
  381. v6[9] = 0;
  382. v6[10] = 0xff;
  383. v6[11] = 0xff;
  384. v6[12] = v4[0];
  385. v6[13] = v4[1];
  386. v6[14] = v4[2];
  387. v6[15] = v4[3];
  388. }
  389. int
  390. v6tov4(uchar *v4, uchar *v6)
  391. {
  392. if(v6[0] == 0
  393. && v6[1] == 0
  394. && v6[2] == 0
  395. && v6[3] == 0
  396. && v6[4] == 0
  397. && v6[5] == 0
  398. && v6[6] == 0
  399. && v6[7] == 0
  400. && v6[8] == 0
  401. && v6[9] == 0
  402. && v6[10] == 0xff
  403. && v6[11] == 0xff)
  404. {
  405. v4[0] = v6[12];
  406. v4[1] = v6[13];
  407. v4[2] = v6[14];
  408. v4[3] = v6[15];
  409. return 0;
  410. } else {
  411. memset(v4, 0, 4);
  412. return -1;
  413. }
  414. }
  415. ulong
  416. parseip(uchar *to, char *from)
  417. {
  418. int i, elipsis = 0, v4 = 1;
  419. ulong x;
  420. char *p, *op;
  421. memset(to, 0, IPaddrlen);
  422. p = from;
  423. for(i = 0; i < 16 && *p; i+=2){
  424. op = p;
  425. x = strtoul(p, &p, 16);
  426. if(*p == '.' || (*p == 0 && i == 0)){
  427. p = v4parseip(to+i, op);
  428. i += 4;
  429. break;
  430. } else {
  431. to[i] = x>>8;
  432. to[i+1] = x;
  433. }
  434. if(*p == ':'){
  435. v4 = 0;
  436. if(*++p == ':'){
  437. elipsis = i+2;
  438. p++;
  439. }
  440. }
  441. }
  442. if(i < 16){
  443. memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis);
  444. memset(&to[elipsis], 0, 16-i);
  445. }
  446. if(v4){
  447. to[10] = to[11] = 0xff;
  448. return nhgetl(to+12);
  449. } else
  450. return 6;
  451. }
  452. /*
  453. * hack to allow ip v4 masks to be entered in the old
  454. * style
  455. */
  456. ulong
  457. parseipmask(uchar *to, char *from)
  458. {
  459. ulong x;
  460. int i;
  461. uchar *p;
  462. if(*from == '/'){
  463. /* as a number of prefix bits */
  464. i = atoi(from+1);
  465. if(i < 0)
  466. i = 0;
  467. if(i > 128)
  468. i = 128;
  469. memset(to, 0, IPaddrlen);
  470. for(p = to; i >= 8; i -= 8)
  471. *p++ = 0xff;
  472. if(i > 0)
  473. *p = ~((1<<(8-i))-1);
  474. x = nhgetl(to+IPv4off);
  475. } else {
  476. /* as a straight bit mask */
  477. x = parseip(to, from);
  478. if(memcmp(to, v4prefix, IPv4off) == 0)
  479. memset(to, 0xff, IPv4off);
  480. }
  481. return x;
  482. }
  483. void
  484. maskip(uchar *from, uchar *mask, uchar *to)
  485. {
  486. int i;
  487. for(i = 0; i < IPaddrlen; i++)
  488. to[i] = from[i] & mask[i];
  489. }
  490. uchar classmask[4][16] = {
  491. 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0x00,0x00,0x00,
  492. 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0x00,0x00,0x00,
  493. 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0x00,0x00,
  494. 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x00,
  495. };
  496. uchar*
  497. defmask(uchar *ip)
  498. {
  499. if(isv4(ip))
  500. return classmask[ip[IPv4off]>>6];
  501. else {
  502. if(ipcmp(ip, v6loopback) == 0)
  503. return IPallbits;
  504. else if(memcmp(ip, v6linklocal, v6llpreflen) == 0)
  505. return v6linklocalmask;
  506. else if(memcmp(ip, v6sitelocal, v6slpreflen) == 0)
  507. return v6sitelocalmask;
  508. else if(memcmp(ip, v6solicitednode, v6snpreflen) == 0)
  509. return v6solicitednodemask;
  510. else if(memcmp(ip, v6multicast, v6mcpreflen) == 0)
  511. return v6multicastmask;
  512. return IPallbits;
  513. }
  514. }
  515. void
  516. ipv62smcast(uchar *smcast, uchar *a)
  517. {
  518. assert(IPaddrlen == 16);
  519. memmove(smcast, v6solicitednode, IPaddrlen);
  520. smcast[13] = a[13];
  521. smcast[14] = a[14];
  522. smcast[15] = a[15];
  523. }
  524. /*
  525. * parse a hex mac address
  526. */
  527. int
  528. parsemac(uchar *to, char *from, int len)
  529. {
  530. char nip[4];
  531. char *p;
  532. int i;
  533. p = from;
  534. memset(to, 0, len);
  535. for(i = 0; i < len; i++){
  536. if(p[0] == '\0' || p[1] == '\0')
  537. break;
  538. nip[0] = p[0];
  539. nip[1] = p[1];
  540. nip[2] = '\0';
  541. p += 2;
  542. to[i] = strtoul(nip, 0, 16);
  543. if(*p == ':')
  544. p++;
  545. }
  546. return i;
  547. }
  548. /*
  549. * hashing tcp, udp, ... connections
  550. */
  551. ulong
  552. iphash(uchar *sa, ushort sp, uchar *da, ushort dp)
  553. {
  554. return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash;
  555. }
  556. void
  557. iphtadd(Ipht *ht, Conv *c)
  558. {
  559. ulong hv;
  560. Iphash *h;
  561. hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
  562. h = smalloc(sizeof(*h));
  563. if(ipcmp(c->raddr, IPnoaddr) != 0)
  564. h->match = IPmatchexact;
  565. else {
  566. if(ipcmp(c->laddr, IPnoaddr) != 0){
  567. if(c->lport == 0)
  568. h->match = IPmatchaddr;
  569. else
  570. h->match = IPmatchpa;
  571. } else {
  572. if(c->lport == 0)
  573. h->match = IPmatchany;
  574. else
  575. h->match = IPmatchport;
  576. }
  577. }
  578. h->c = c;
  579. lock(ht);
  580. h->next = ht->tab[hv];
  581. ht->tab[hv] = h;
  582. unlock(ht);
  583. }
  584. void
  585. iphtrem(Ipht *ht, Conv *c)
  586. {
  587. ulong hv;
  588. Iphash **l, *h;
  589. hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
  590. lock(ht);
  591. for(l = &ht->tab[hv]; (*l) != nil; l = &(*l)->next)
  592. if((*l)->c == c){
  593. h = *l;
  594. (*l) = h->next;
  595. free(h);
  596. break;
  597. }
  598. unlock(ht);
  599. }
  600. /* look for a matching conversation with the following precedence
  601. * connected && raddr,rport,laddr,lport
  602. * announced && laddr,lport
  603. * announced && *,lport
  604. * announced && laddr,*
  605. * announced && *,*
  606. */
  607. Conv*
  608. iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp)
  609. {
  610. ulong hv;
  611. Iphash *h;
  612. Conv *c;
  613. /* exact 4 pair match (connection) */
  614. hv = iphash(sa, sp, da, dp);
  615. lock(ht);
  616. for(h = ht->tab[hv]; h != nil; h = h->next){
  617. if(h->match != IPmatchexact)
  618. continue;
  619. c = h->c;
  620. if(sp == c->rport && dp == c->lport
  621. && ipcmp(sa, c->raddr) == 0 && ipcmp(da, c->laddr) == 0){
  622. unlock(ht);
  623. return c;
  624. }
  625. }
  626. /* match local address and port */
  627. hv = iphash(IPnoaddr, 0, da, dp);
  628. for(h = ht->tab[hv]; h != nil; h = h->next){
  629. if(h->match != IPmatchpa)
  630. continue;
  631. c = h->c;
  632. if(dp == c->lport && ipcmp(da, c->laddr) == 0){
  633. unlock(ht);
  634. return c;
  635. }
  636. }
  637. /* match just port */
  638. hv = iphash(IPnoaddr, 0, IPnoaddr, dp);
  639. for(h = ht->tab[hv]; h != nil; h = h->next){
  640. if(h->match != IPmatchport)
  641. continue;
  642. c = h->c;
  643. if(dp == c->lport){
  644. unlock(ht);
  645. return c;
  646. }
  647. }
  648. /* match local address */
  649. hv = iphash(IPnoaddr, 0, da, 0);
  650. for(h = ht->tab[hv]; h != nil; h = h->next){
  651. if(h->match != IPmatchaddr)
  652. continue;
  653. c = h->c;
  654. if(ipcmp(da, c->laddr) == 0){
  655. unlock(ht);
  656. return c;
  657. }
  658. }
  659. /* look for something that matches anything */
  660. hv = iphash(IPnoaddr, 0, IPnoaddr, 0);
  661. for(h = ht->tab[hv]; h != nil; h = h->next){
  662. if(h->match != IPmatchany)
  663. continue;
  664. c = h->c;
  665. unlock(ht);
  666. return c;
  667. }
  668. unlock(ht);
  669. return nil;
  670. }