diff options
author | Ondrej Filip <feela@network.cz> | 2000-04-01 04:45:49 +0200 |
---|---|---|
committer | Ondrej Filip <feela@network.cz> | 2000-04-01 04:45:49 +0200 |
commit | 499cb346f6fb29f9157e12942484c8b4362597c3 (patch) | |
tree | 90032d28f0f772e47b2e69703fe27ae876647a46 /proto/ospf/lsalib.c | |
parent | ac4b4683aee8e5aa566b0b5f99bd940bc10d9b71 (diff) | |
download | bird-499cb346f6fb29f9157e12942484c8b4362597c3.tar bird-499cb346f6fb29f9157e12942484c8b4362597c3.zip |
LSA checksum works. But it's very uneficient on little endian systems.
Diffstat (limited to 'proto/ospf/lsalib.c')
-rw-r--r-- | proto/ospf/lsalib.c | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index f74cb76..d7ae1c6 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -44,16 +44,18 @@ htonlsab(void *h, void *n, u8 type, u16 len) { struct ospf_lsa_rt *hrt, *nrt; struct ospf_lsa_rt_link *hrtl,*nrtl; + u16 links; nrt=n; hrt=h; + links=hrt->links; nrt->VEB=hrt->VEB; nrt->padding=0; nrt->links=htons(hrt->links); nrtl=(struct ospf_lsa_rt_link *)(nrt+1); hrtl=(struct ospf_lsa_rt_link *)(hrt+1); - for(i=0;i<hrt->links;i++) + for(i=0;i<links;i++) { (nrtl+i)->id=htonl((hrtl+i)->id); (nrtl+i)->data=htonl((hrtl+i)->data); @@ -137,16 +139,17 @@ ntohlsab(void *n, void *h, u8 type, u16 len) { struct ospf_lsa_rt *hrt, *nrt; struct ospf_lsa_rt_link *hrtl,*nrtl; + u16 links; nrt=n; hrt=h; hrt->VEB=nrt->VEB; hrt->padding=0; - hrt->links=ntohs(nrt->links); + links=hrt->links=ntohs(nrt->links); nrtl=(struct ospf_lsa_rt_link *)(nrt+1); hrtl=(struct ospf_lsa_rt_link *)(hrt+1); - for(i=0;i<hrt->links;i++) + for(i=0;i<links;i++) { (hrtl+i)->id=ntohl((nrtl+i)->id); (hrtl+i)->data=ntohl((nrtl+i)->data); @@ -220,3 +223,63 @@ ntohlsab(void *n, void *h, u8 type, u16 len) } }; +#define MODX 4102 /* larges signed value without overflow */ + +/* Fletcher Checksum -- Refer to RFC1008. */ +#define MODX 4102 +#define LSA_CHECKSUM_OFFSET 15 + +/* FIXME This is VERY uneficient, I have huge endianity problems */ + +void +lsasum_calculate(struct ospf_lsa_header *h,void *body,struct proto_ospf *po) +{ + u8 *sp, *ep, *p, *q, *b; + int c0 = 0, c1 = 0; + int x, y; + u16 length; + + h->checksum = 0; + b=body; + length = h->length-2; + sp = (char *) &h->options; + + htonlsah(h,h); + htonlsab(b,b,h->type,length+2); + + for (ep = sp + length; sp < ep; sp = q) + { + q = sp + MODX; + if (q > ep) + q = ep; + for (p = sp; p < q; p++) + { + if(p<(u8 *)(h+1)) + { + c0 += *p; + /*DBG("XXXXXX: %u\t%u\n", p-sp, *p);*/ + } + else + { + c0 += *(b+(p-sp)-sizeof(struct ospf_lsa_header)+2); + /*DBG("YYYYYY: %u\t%u\n", p-sp,*(b+(p-sp)-sizeof(struct ospf_lsa_header)+2));*/ + } + c1 += c0; + } + c0 %= 255; + c1 %= 255; + } + + x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255; + if (x <= 0) + x += 255; + y = 510 - c0 - x; + if (y > 255) + y -= 255; + + h->checksum = x + (y << 8); + + ntohlsah(h,h); + ntohlsab(b,b,h->type,length+2); +} + |