ipaux.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) 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 }