summaryrefslogtreecommitdiffstats
path: root/proto/ospf/lsalib.c
diff options
context:
space:
mode:
authorOndrej Filip <feela@network.cz>2000-04-01 04:45:49 +0200
committerOndrej Filip <feela@network.cz>2000-04-01 04:45:49 +0200
commit499cb346f6fb29f9157e12942484c8b4362597c3 (patch)
tree90032d28f0f772e47b2e69703fe27ae876647a46 /proto/ospf/lsalib.c
parentac4b4683aee8e5aa566b0b5f99bd940bc10d9b71 (diff)
downloadbird-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.c69
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);
+}
+