Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}