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