ipaux.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "ip.h"
  16. #include "ipv6.h"
  17. char *v6hdrtypes[Maxhdrtype] =
  18. {
  19. [HBH] "HopbyHop",
  20. [ICMP] "ICMP",
  21. [IGMP] "IGMP",
  22. [GGP] "GGP",
  23. [IPINIP] "IP",
  24. [ST] "ST",
  25. [TCP] "TCP",
  26. [UDP] "UDP",
  27. [ISO_TP4] "ISO_TP4",
  28. [RH] "Routinghdr",
  29. [FH] "Fraghdr",
  30. [IDRP] "IDRP",
  31. [RSVP] "RSVP",
  32. [AH] "Authhdr",
  33. [ESP] "ESP",
  34. [ICMPv6] "ICMPv6",
  35. [NNH] "Nonexthdr",
  36. [ISO_IP] "ISO_IP",
  37. [IGRP] "IGRP",
  38. [OSPF] "OSPF",
  39. };
  40. /*
  41. * well known IPv6 addresses
  42. */
  43. uint8_t v6Unspecified[IPaddrlen] = {
  44. 0, 0, 0, 0,
  45. 0, 0, 0, 0,
  46. 0, 0, 0, 0,
  47. 0, 0, 0, 0
  48. };
  49. uint8_t v6loopback[IPaddrlen] = {
  50. 0, 0, 0, 0,
  51. 0, 0, 0, 0,
  52. 0, 0, 0, 0,
  53. 0, 0, 0, 0x01
  54. };
  55. uint8_t v6linklocal[IPaddrlen] = {
  56. 0xfe, 0x80, 0, 0,
  57. 0, 0, 0, 0,
  58. 0, 0, 0, 0,
  59. 0, 0, 0, 0
  60. };
  61. uint8_t v6linklocalmask[IPaddrlen] = {
  62. 0xff, 0xff, 0xff, 0xff,
  63. 0xff, 0xff, 0xff, 0xff,
  64. 0, 0, 0, 0,
  65. 0, 0, 0, 0
  66. };
  67. int v6llpreflen = 8; /* link-local prefix length in bytes */
  68. uint8_t v6multicast[IPaddrlen] = {
  69. 0xff, 0, 0, 0,
  70. 0, 0, 0, 0,
  71. 0, 0, 0, 0,
  72. 0, 0, 0, 0
  73. };
  74. uint8_t v6multicastmask[IPaddrlen] = {
  75. 0xff, 0, 0, 0,
  76. 0, 0, 0, 0,
  77. 0, 0, 0, 0,
  78. 0, 0, 0, 0
  79. };
  80. int v6mcpreflen = 1; /* multicast prefix length */
  81. uint8_t v6allnodesN[IPaddrlen] = {
  82. 0xff, 0x01, 0, 0,
  83. 0, 0, 0, 0,
  84. 0, 0, 0, 0,
  85. 0, 0, 0, 0x01
  86. };
  87. uint8_t v6allroutersN[IPaddrlen] = {
  88. 0xff, 0x01, 0, 0,
  89. 0, 0, 0, 0,
  90. 0, 0, 0, 0,
  91. 0, 0, 0, 0x02
  92. };
  93. uint8_t v6allnodesNmask[IPaddrlen] = {
  94. 0xff, 0xff, 0, 0,
  95. 0, 0, 0, 0,
  96. 0, 0, 0, 0,
  97. 0, 0, 0, 0
  98. };
  99. int v6aNpreflen = 2; /* all nodes (N) prefix */
  100. uint8_t v6allnodesL[IPaddrlen] = {
  101. 0xff, 0x02, 0, 0,
  102. 0, 0, 0, 0,
  103. 0, 0, 0, 0,
  104. 0, 0, 0, 0x01
  105. };
  106. uint8_t v6allroutersL[IPaddrlen] = {
  107. 0xff, 0x02, 0, 0,
  108. 0, 0, 0, 0,
  109. 0, 0, 0, 0,
  110. 0, 0, 0, 0x02
  111. };
  112. uint8_t v6allnodesLmask[IPaddrlen] = {
  113. 0xff, 0xff, 0, 0,
  114. 0, 0, 0, 0,
  115. 0, 0, 0, 0,
  116. 0, 0, 0, 0
  117. };
  118. int v6aLpreflen = 2; /* all nodes (L) prefix */
  119. uint8_t v6solicitednode[IPaddrlen] = {
  120. 0xff, 0x02, 0, 0,
  121. 0, 0, 0, 0,
  122. 0, 0, 0, 0x01,
  123. 0xff, 0, 0, 0
  124. };
  125. uint8_t v6solicitednodemask[IPaddrlen] = {
  126. 0xff, 0xff, 0xff, 0xff,
  127. 0xff, 0xff, 0xff, 0xff,
  128. 0xff, 0xff, 0xff, 0xff,
  129. 0xff, 0x0, 0x0, 0x0
  130. };
  131. int v6snpreflen = 13;
  132. uint16_t
  133. ptclcsum(Block *bp, int offset, int len)
  134. {
  135. uint8_t *addr;
  136. uint32_t losum, hisum;
  137. uint16_t csum;
  138. int odd, blocklen, x;
  139. /* Correct to front of data area */
  140. while(bp != nil && offset && offset >= BLEN(bp)) {
  141. offset -= BLEN(bp);
  142. bp = bp->next;
  143. }
  144. if(bp == nil)
  145. return 0;
  146. addr = bp->rp + offset;
  147. blocklen = BLEN(bp) - offset;
  148. if(bp->next == nil) {
  149. if(blocklen < len)
  150. len = blocklen;
  151. return ~ptclbsum(addr, len) & 0xffff;
  152. }
  153. losum = 0;
  154. hisum = 0;
  155. odd = 0;
  156. while(len) {
  157. x = blocklen;
  158. if(len < x)
  159. x = len;
  160. csum = ptclbsum(addr, x);
  161. if(odd)
  162. hisum += csum;
  163. else
  164. losum += csum;
  165. odd = (odd+x) & 1;
  166. len -= x;
  167. bp = bp->next;
  168. if(bp == nil)
  169. break;
  170. blocklen = BLEN(bp);
  171. addr = bp->rp;
  172. }
  173. losum += hisum>>8;
  174. losum += (hisum&0xff)<<8;
  175. while((csum = losum>>16) != 0)
  176. losum = csum + (losum & 0xffff);
  177. return ~losum & 0xffff;
  178. }
  179. enum
  180. {
  181. Isprefix= 16,
  182. };
  183. #define CLASS(p) ((*(uint8_t*)(p))>>6)
  184. void
  185. ipv62smcast(uint8_t *smcast, uint8_t *a)
  186. {
  187. assert(IPaddrlen == 16);
  188. memmove(smcast, v6solicitednode, IPaddrlen);
  189. smcast[13] = a[13];
  190. smcast[14] = a[14];
  191. smcast[15] = a[15];
  192. }
  193. /*
  194. * parse a hex mac address
  195. */
  196. int
  197. parsemac(uint8_t *to, char *from, int len)
  198. {
  199. char nip[4];
  200. char *p;
  201. int i;
  202. p = from;
  203. memset(to, 0, len);
  204. for(i = 0; i < len; i++){
  205. if(p[0] == '\0' || p[1] == '\0')
  206. break;
  207. nip[0] = p[0];
  208. nip[1] = p[1];
  209. nip[2] = '\0';
  210. p += 2;
  211. to[i] = strtoul(nip, 0, 16);
  212. if(*p == ':')
  213. p++;
  214. }
  215. return i;
  216. }
  217. /*
  218. * hashing tcp, udp, ... connections
  219. */
  220. uint32_t
  221. iphash(uint8_t *sa, uint16_t sp, uint8_t *da, uint16_t dp)
  222. {
  223. return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nipht;
  224. }
  225. void
  226. iphtadd(Ipht *ht, Conv *c)
  227. {
  228. uint32_t hv;
  229. Iphash *h;
  230. hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
  231. h = smalloc(sizeof(*h));
  232. if(ipcmp(c->raddr, IPnoaddr) != 0)
  233. h->match = IPmatchexact;
  234. else {
  235. if(ipcmp(c->laddr, IPnoaddr) != 0){
  236. if(c->lport == 0)
  237. h->match = IPmatchaddr;
  238. else
  239. h->match = IPmatchpa;
  240. } else {
  241. if(c->lport == 0)
  242. h->match = IPmatchany;
  243. else
  244. h->match = IPmatchport;
  245. }
  246. }
  247. h->c = c;
  248. lock(ht);
  249. h->next = ht->tab[hv];
  250. ht->tab[hv] = h;
  251. unlock(ht);
  252. }
  253. void
  254. iphtrem(Ipht *ht, Conv *c)
  255. {
  256. uint32_t hv;
  257. Iphash **l, *h;
  258. hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
  259. lock(ht);
  260. for(l = &ht->tab[hv]; (*l) != nil; l = &(*l)->next)
  261. if((*l)->c == c){
  262. h = *l;
  263. (*l) = h->next;
  264. free(h);
  265. break;
  266. }
  267. unlock(ht);
  268. }
  269. /* look for a matching conversation with the following precedence
  270. * connected && raddr,rport,laddr,lport
  271. * announced && laddr,lport
  272. * announced && *,lport
  273. * announced && laddr,*
  274. * announced && *,*
  275. */
  276. Conv*
  277. iphtlook(Ipht *ht, uint8_t *sa, uint16_t sp, uint8_t *da, uint16_t dp)
  278. {
  279. uint32_t hv;
  280. Iphash *h;
  281. Conv *c;
  282. /* exact 4 pair match (connection) */
  283. hv = iphash(sa, sp, da, dp);
  284. lock(ht);
  285. for(h = ht->tab[hv]; h != nil; h = h->next){
  286. if(h->match != IPmatchexact)
  287. continue;
  288. c = h->c;
  289. if(sp == c->rport && dp == c->lport
  290. && ipcmp(sa, c->raddr) == 0 && ipcmp(da, c->laddr) == 0){
  291. unlock(ht);
  292. return c;
  293. }
  294. }
  295. /* match local address and port */
  296. hv = iphash(IPnoaddr, 0, da, dp);
  297. for(h = ht->tab[hv]; h != nil; h = h->next){
  298. if(h->match != IPmatchpa)
  299. continue;
  300. c = h->c;
  301. if(dp == c->lport && ipcmp(da, c->laddr) == 0){
  302. unlock(ht);
  303. return c;
  304. }
  305. }
  306. /* match just port */
  307. hv = iphash(IPnoaddr, 0, IPnoaddr, dp);
  308. for(h = ht->tab[hv]; h != nil; h = h->next){
  309. if(h->match != IPmatchport)
  310. continue;
  311. c = h->c;
  312. if(dp == c->lport){
  313. unlock(ht);
  314. return c;
  315. }
  316. }
  317. /* match local address */
  318. hv = iphash(IPnoaddr, 0, da, 0);
  319. for(h = ht->tab[hv]; h != nil; h = h->next){
  320. if(h->match != IPmatchaddr)
  321. continue;
  322. c = h->c;
  323. if(ipcmp(da, c->laddr) == 0){
  324. unlock(ht);
  325. return c;
  326. }
  327. }
  328. /* look for something that matches anything */
  329. hv = iphash(IPnoaddr, 0, IPnoaddr, 0);
  330. for(h = ht->tab[hv]; h != nil; h = h->next){
  331. if(h->match != IPmatchany)
  332. continue;
  333. c = h->c;
  334. unlock(ht);
  335. return c;
  336. }
  337. unlock(ht);
  338. return nil;
  339. }