summaryrefslogtreecommitdiff
path: root/sys/src/9/ip/ipaux.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/9/ip/ipaux.c368
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;
+}