diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/ip/ipaux.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/ip/ipaux.c')
-rwxr-xr-x | sys/src/9/ip/ipaux.c | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/sys/src/9/ip/ipaux.c b/sys/src/9/ip/ipaux.c new file mode 100755 index 000000000..75a4fd4f2 --- /dev/null +++ b/sys/src/9/ip/ipaux.c @@ -0,0 +1,368 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "ip.h" +#include "ipv6.h" + +char *v6hdrtypes[Maxhdrtype] = +{ + [HBH] "HopbyHop", + [ICMP] "ICMP", + [IGMP] "IGMP", + [GGP] "GGP", + [IPINIP] "IP", + [ST] "ST", + [TCP] "TCP", + [UDP] "UDP", + [ISO_TP4] "ISO_TP4", + [RH] "Routinghdr", + [FH] "Fraghdr", + [IDRP] "IDRP", + [RSVP] "RSVP", + [AH] "Authhdr", + [ESP] "ESP", + [ICMPv6] "ICMPv6", + [NNH] "Nonexthdr", + [ISO_IP] "ISO_IP", + [IGRP] "IGRP", + [OSPF] "OSPF", +}; + +/* + * well known IPv6 addresses + */ +uchar v6Unspecified[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +uchar v6loopback[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01 +}; + +uchar v6linklocal[IPaddrlen] = { + 0xfe, 0x80, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +uchar v6linklocalmask[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +int v6llpreflen = 8; /* link-local prefix length in bytes */ + +uchar v6multicast[IPaddrlen] = { + 0xff, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +uchar v6multicastmask[IPaddrlen] = { + 0xff, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +int v6mcpreflen = 1; /* multicast prefix length */ + +uchar v6allnodesN[IPaddrlen] = { + 0xff, 0x01, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01 +}; +uchar v6allroutersN[IPaddrlen] = { + 0xff, 0x01, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x02 +}; +uchar v6allnodesNmask[IPaddrlen] = { + 0xff, 0xff, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +int v6aNpreflen = 2; /* all nodes (N) prefix */ + +uchar v6allnodesL[IPaddrlen] = { + 0xff, 0x02, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01 +}; +uchar v6allroutersL[IPaddrlen] = { + 0xff, 0x02, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x02 +}; +uchar v6allnodesLmask[IPaddrlen] = { + 0xff, 0xff, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +int v6aLpreflen = 2; /* all nodes (L) prefix */ + +uchar v6solicitednode[IPaddrlen] = { + 0xff, 0x02, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01, + 0xff, 0, 0, 0 +}; +uchar v6solicitednodemask[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0, 0x0, 0x0 +}; +int v6snpreflen = 13; + +ushort +ptclcsum(Block *bp, int offset, int len) +{ + uchar *addr; + ulong losum, hisum; + ushort csum; + int odd, blocklen, x; + + /* Correct to front of data area */ + while(bp != nil && offset && offset >= BLEN(bp)) { + offset -= BLEN(bp); + bp = bp->next; + } + if(bp == nil) + return 0; + + addr = bp->rp + offset; + blocklen = BLEN(bp) - offset; + + if(bp->next == nil) { + if(blocklen < len) + len = blocklen; + return ~ptclbsum(addr, len) & 0xffff; + } + + losum = 0; + hisum = 0; + + odd = 0; + while(len) { + x = blocklen; + if(len < x) + x = len; + + csum = ptclbsum(addr, x); + if(odd) + hisum += csum; + else + losum += csum; + odd = (odd+x) & 1; + len -= x; + + bp = bp->next; + if(bp == nil) + break; + blocklen = BLEN(bp); + addr = bp->rp; + } + + losum += hisum>>8; + losum += (hisum&0xff)<<8; + while((csum = losum>>16) != 0) + losum = csum + (losum & 0xffff); + + return ~losum & 0xffff; +} + +enum +{ + Isprefix= 16, +}; + +#define CLASS(p) ((*(uchar*)(p))>>6) + +void +ipv62smcast(uchar *smcast, uchar *a) +{ + assert(IPaddrlen == 16); + memmove(smcast, v6solicitednode, IPaddrlen); + smcast[13] = a[13]; + smcast[14] = a[14]; + smcast[15] = a[15]; +} + + +/* + * parse a hex mac address + */ +int +parsemac(uchar *to, char *from, int len) +{ + char nip[4]; + char *p; + int i; + + p = from; + memset(to, 0, len); + for(i = 0; i < len; i++){ + if(p[0] == '\0' || p[1] == '\0') + break; + + nip[0] = p[0]; + nip[1] = p[1]; + nip[2] = '\0'; + p += 2; + + to[i] = strtoul(nip, 0, 16); + if(*p == ':') + p++; + } + return i; +} + +/* + * hashing tcp, udp, ... connections + */ +ulong +iphash(uchar *sa, ushort sp, uchar *da, ushort dp) +{ + return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash; +} + +void +iphtadd(Ipht *ht, Conv *c) +{ + ulong hv; + Iphash *h; + + hv = iphash(c->raddr, c->rport, c->laddr, c->lport); + h = smalloc(sizeof(*h)); + if(ipcmp(c->raddr, IPnoaddr) != 0) + h->match = IPmatchexact; + else { + if(ipcmp(c->laddr, IPnoaddr) != 0){ + if(c->lport == 0) + h->match = IPmatchaddr; + else + h->match = IPmatchpa; + } else { + if(c->lport == 0) + h->match = IPmatchany; + else + h->match = IPmatchport; + } + } + h->c = c; + + lock(ht); + h->next = ht->tab[hv]; + ht->tab[hv] = h; + unlock(ht); +} + +void +iphtrem(Ipht *ht, Conv *c) +{ + ulong hv; + Iphash **l, *h; + + hv = iphash(c->raddr, c->rport, c->laddr, c->lport); + lock(ht); + for(l = &ht->tab[hv]; (*l) != nil; l = &(*l)->next) + if((*l)->c == c){ + h = *l; + (*l) = h->next; + free(h); + break; + } + unlock(ht); +} + +/* look for a matching conversation with the following precedence + * connected && raddr,rport,laddr,lport + * announced && laddr,lport + * announced && *,lport + * announced && laddr,* + * announced && *,* + */ +Conv* +iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp) +{ + ulong hv; + Iphash *h; + Conv *c; + + /* exact 4 pair match (connection) */ + hv = iphash(sa, sp, da, dp); + lock(ht); + for(h = ht->tab[hv]; h != nil; h = h->next){ + if(h->match != IPmatchexact) + continue; + c = h->c; + if(sp == c->rport && dp == c->lport + && ipcmp(sa, c->raddr) == 0 && ipcmp(da, c->laddr) == 0){ + unlock(ht); + return c; + } + } + + /* match local address and port */ + hv = iphash(IPnoaddr, 0, da, dp); + for(h = ht->tab[hv]; h != nil; h = h->next){ + if(h->match != IPmatchpa) + continue; + c = h->c; + if(dp == c->lport && ipcmp(da, c->laddr) == 0){ + unlock(ht); + return c; + } + } + + /* match just port */ + hv = iphash(IPnoaddr, 0, IPnoaddr, dp); + for(h = ht->tab[hv]; h != nil; h = h->next){ + if(h->match != IPmatchport) + continue; + c = h->c; + if(dp == c->lport){ + unlock(ht); + return c; + } + } + + /* match local address */ + hv = iphash(IPnoaddr, 0, da, 0); + for(h = ht->tab[hv]; h != nil; h = h->next){ + if(h->match != IPmatchaddr) + continue; + c = h->c; + if(ipcmp(da, c->laddr) == 0){ + unlock(ht); + return c; + } + } + + /* look for something that matches anything */ + hv = iphash(IPnoaddr, 0, IPnoaddr, 0); + for(h = ht->tab[hv]; h != nil; h = h->next){ + if(h->match != IPmatchany) + continue; + c = h->c; + unlock(ht); + return c; + } + unlock(ht); + return nil; +} |