vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

ipaux.c (6233B)


      1 #include	"u.h"
      2 #include	"lib.h"
      3 #include	"mem.h"
      4 #include	"dat.h"
      5 #include	"fns.h"
      6 #include	"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 (ulong)(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 }