📄 ipmux.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include "ip.h"#define DPRINT if(0)printtypedef struct Ipmuxrock Ipmuxrock;typedef struct Ipmux Ipmux;typedef struct Ip4hdr Ip4hdr;typedef struct Ip6hdr Ip6hdr;enum{ IPHDR = 20, /* sizeof(Ip4hdr) */};struct Ip4hdr{ uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* ip->identification */ uchar frag[2]; /* Fragment information */ uchar ttl; /* Time to live */ uchar proto; /* Protocol */ uchar cksum[2]; /* Header checksum */ uchar src[4]; /* IP source */ uchar dst[4]; /* IP destination */ uchar data[1]; /* start of data */};Ip4hdr *ipoff = 0;struct Ip6hdr{ uchar vcf[4]; /* version, class label, and flow label */ uchar ploadlen[2]; /* payload length */ uchar proto; /* next header, i.e. proto */ uchar ttl; /* hop limit, i.e. ttl */ uchar src[16]; /* IP source */ uchar dst[16]; /* IP destination */};enum{ Tproto, Tdata, Tiph, Tdst, Tsrc, Tifc, Cother = 0, Cbyte, /* single byte */ Cmbyte, /* single byte with mask */ Cshort, /* single short */ Cmshort, /* single short with mask */ Clong, /* single long */ Cmlong, /* single long with mask */ Cifc, Cmifc,};char *ftname[] = {[Tproto] "proto",[Tdata] "data",[Tiph] "iph",[Tdst] "dst",[Tsrc] "src",[Tifc] "ifc",};/* * a node in the decision tree */struct Ipmux{ Ipmux *yes; Ipmux *no; uchar type; /* type of field(Txxxx) */ uchar ctype; /* tupe of comparison(Cxxxx) */ uchar len; /* length in bytes of item to compare */ uchar n; /* number of items val points to */ short off; /* offset of comparison */ short eoff; /* end offset of comparison */ uchar skiphdr; /* should offset start after ipheader */ uchar *val; uchar *mask; uchar *e; /* val+n*len*/ int ref; /* so we can garbage collect */ Conv *conv;};/* * someplace to hold per conversation data */struct Ipmuxrock{ Ipmux *chain;};static int ipmuxsprint(Ipmux*, int, char*, int);static void ipmuxkick(void *x);static char*skipwhite(char *p){ while(*p == ' ' || *p == '\t') p++; return p;}static char*follows(char *p, char c){ char *f; f = strchr(p, c); if(f == nil) return nil; *f++ = 0; f = skipwhite(f); if(*f == 0) return nil; return f;}static Ipmux*parseop(char **pp){ char *p = *pp; int type, off, end, len; Ipmux *f; p = skipwhite(p); if(strncmp(p, "dst", 3) == 0){ type = Tdst; off = (ulong)(ipoff->dst); len = IPv4addrlen; p += 3; } else if(strncmp(p, "src", 3) == 0){ type = Tsrc; off = (ulong)(ipoff->src); len = IPv4addrlen; p += 3; } else if(strncmp(p, "ifc", 3) == 0){ type = Tifc; off = -IPv4addrlen; len = IPv4addrlen; p += 3; } else if(strncmp(p, "proto", 5) == 0){ type = Tproto; off = (ulong)&(ipoff->proto); len = 1; p += 5; } else if(strncmp(p, "data", 4) == 0 || strncmp(p, "iph", 3) == 0){ if(strncmp(p, "data", 4) == 0) { type = Tdata; p += 4; } else { type = Tiph; p += 3; } p = skipwhite(p); if(*p != '[') return nil; p++; off = strtoul(p, &p, 0); if(off < 0 || off > (64-IPHDR)) return nil; p = skipwhite(p); if(*p != ':') end = off; else { p++; p = skipwhite(p); end = strtoul(p, &p, 0); if(end < off) return nil; p = skipwhite(p); } if(*p != ']') return nil; p++; len = end - off + 1; } else return nil; f = smalloc(sizeof(*f)); f->type = type; f->len = len; f->off = off; f->val = nil; f->mask = nil; f->n = 1; f->ref = 1; if(type == Tdata) f->skiphdr = 1; else f->skiphdr = 0; return f; }static inthtoi(char x){ if(x >= '0' && x <= '9') x -= '0'; else if(x >= 'a' && x <= 'f') x -= 'a' - 10; else if(x >= 'A' && x <= 'F') x -= 'A' - 10; else x = 0; return x;}static inthextoi(char *p){ return (htoi(p[0])<<4) | htoi(p[1]);}static voidparseval(uchar *v, char *p, int len){ while(*p && len-- > 0){ *v++ = hextoi(p); p += 2; }}static Ipmux*parsemux(char *p){ int n, nomask; Ipmux *f; char *val; char *mask; char *vals[20]; uchar *v; /* parse operand */ f = parseop(&p); if(f == nil) return nil; /* find value */ val = follows(p, '='); if(val == nil) goto parseerror; /* parse mask */ mask = follows(p, '&'); if(mask != nil){ switch(f->type){ case Tsrc: case Tdst: case Tifc: f->mask = smalloc(f->len); v4parseip(f->mask, mask); break; case Tdata: case Tiph: f->mask = smalloc(f->len); parseval(f->mask, mask, f->len); break; default: goto parseerror; } nomask = 0; } else { nomask = 1; f->mask = smalloc(f->len); memset(f->mask, 0xff, f->len); } /* parse vals */ f->n = getfields(val, vals, sizeof(vals)/sizeof(char*), 1, "|"); if(f->n == 0) goto parseerror; f->val = smalloc(f->n*f->len); v = f->val; for(n = 0; n < f->n; n++){ switch(f->type){ case Tsrc: case Tdst: case Tifc: v4parseip(v, vals[n]); break; case Tproto: case Tdata: case Tiph: parseval(v, vals[n], f->len); break; } v += f->len; } f->eoff = f->off + f->len; f->e = f->val + f->n*f->len; f->ctype = Cother; if(f->n == 1){ switch(f->len){ case 1: f->ctype = nomask ? Cbyte : Cmbyte; break; case 2: f->ctype = nomask ? Cshort : Cmshort; break; case 4: if(f->type == Tifc) f->ctype = nomask ? Cifc : Cmifc; else f->ctype = nomask ? Clong : Cmlong; break; } } return f;parseerror: if(f->mask) free(f->mask); if(f->val) free(f->val); free(f); return nil;}/* * Compare relative ordering of two ipmuxs. This doesn't compare the * values, just the fields being looked at. * * returns: <0 if a is a more specific match * 0 if a and b are matching on the same fields * >0 if b is a more specific match */static intipmuxcmp(Ipmux *a, Ipmux *b){ int n; /* compare types, lesser ones are more important */ n = a->type - b->type; if(n != 0) return n; /* compare offsets, call earlier ones more specific */ n = (a->off+((int)a->skiphdr)*(ulong)ipoff->data) - (b->off+((int)b->skiphdr)*(ulong)ipoff->data); if(n != 0) return n; /* compare match lengths, longer ones are more specific */ n = b->len - a->len; if(n != 0) return n; /* * if we get here we have two entries matching * the same bytes of the record. Now check * the mask for equality. Longer masks are * more specific. */ if(a->mask != nil && b->mask == nil) return -1; if(a->mask == nil && b->mask != nil) return 1; if(a->mask != nil && b->mask != nil){ n = memcmp(b->mask, a->mask, a->len); if(n != 0) return n; } return 0;}/* * Compare the values of two ipmuxs. We're assuming that ipmuxcmp * returned 0 comparing them. */static intipmuxvalcmp(Ipmux *a, Ipmux *b){ int n; n = b->len*b->n - a->len*a->n; if(n != 0) return n; return memcmp(a->val, b->val, a->len*a->n);} /* * add onto an existing ipmux chain in the canonical comparison * order */static voidipmuxchain(Ipmux **l, Ipmux *f){ for(; *l; l = &(*l)->yes) if(ipmuxcmp(f, *l) < 0) break; f->yes = *l; *l = f;}/* * copy a tree */static Ipmux*ipmuxcopy(Ipmux *f){ Ipmux *nf; if(f == nil) return nil; nf = smalloc(sizeof *nf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -