void lsa_generate_checksum(struct ospf_lsa_header *lsa, const u8 *body) { struct fletcher16_context ctx; struct ospf_lsa_header hdr; u16 len = lsa->length; /* * lsa and body are in the host order, we need to compute Fletcher-16 checksum * for data in the network order. We also skip the initial age field. */ lsa_hton_hdr(lsa, &hdr); hdr.checksum = 0; fletcher16_init(&ctx); fletcher16_update(&ctx, (u8 *) &hdr + 2, sizeof(struct ospf_lsa_header) - 2); fletcher16_update_n32(&ctx, body, len - sizeof(struct ospf_lsa_header)); lsa->checksum = fletcher16_final(&ctx, len, OFFSETOF(struct ospf_lsa_header, checksum)); }
/* FIXME This is VERY uneficient, I have huge endianity problems */ void lsasum_calculate(struct ospf_lsa_header *h, void *body) { u16 length = h->length; // log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length); lsa_hton_hdr(h, h); lsa_hton_body1(body, length - sizeof(struct ospf_lsa_header)); /* char buf[1024]; memcpy(buf, h, sizeof(struct ospf_lsa_header)); memcpy(buf + sizeof(struct ospf_lsa_header), body, length - sizeof(struct ospf_lsa_header)); buf_dump("CALC", buf, length); */ (void) lsasum_check(h, body, 1); // log(L_WARN "Checksum result %4x", h->checksum); lsa_ntoh_hdr(h, h); lsa_ntoh_body1(body, length - sizeof(struct ospf_lsa_header)); }
static void ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) { struct ospf_iface *ifa = n->ifa; struct ospf_packet *pkt; uint length; u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu; /* Update DBDES buffer */ if (n->ldd_bsize != ifa->tx_length) { mb_free(n->ldd_buffer); n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length); n->ldd_bsize = ifa->tx_length; } pkt = n->ldd_buffer; ospf_pkt_fill_hdr(ifa, pkt, DBDES_P); if (ospf_is_v2(p)) { struct ospf_dbdes2_packet *ps = (void *) pkt; ps->iface_mtu = htons(iface_mtu); ps->options = ifa->oa->options; ps->imms = 0; /* Will be set later */ ps->ddseq = htonl(n->dds); length = sizeof(struct ospf_dbdes2_packet); } else /* OSPFv3 */ { struct ospf_dbdes3_packet *ps = (void *) pkt; ps->options = htonl(ifa->oa->options); ps->iface_mtu = htons(iface_mtu); ps->padding = 0; ps->imms = 0; /* Will be set later */ ps->ddseq = htonl(n->dds); length = sizeof(struct ospf_dbdes3_packet); } /* Prepare DBDES body */ if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M)) { struct ospf_lsa_header *lsas; struct top_hash_entry *en; uint i = 0, lsa_max; ospf_dbdes_body(p, pkt, &lsas, &lsa_max); en = (void *) s_get(&(n->dbsi)); while (i < lsa_max) { if (!SNODE_VALID(en)) { n->myimms &= ~DBDES_M; /* Unset More bit */ break; } if ((en->lsa.age < LSA_MAXAGE) && lsa_flooding_allowed(en->lsa_type, en->domain, ifa)) { lsa_hton_hdr(&(en->lsa), lsas + i); i++; } en = SNODE_NEXT(en); } s_put(&(n->dbsi), SNODE en); length += i * sizeof(struct ospf_lsa_header); } if (ospf_is_v2(p)) ((struct ospf_dbdes2_packet *) pkt)->imms = n->myimms; else ((struct ospf_dbdes3_packet *) pkt)->imms = n->myimms; pkt->length = htons(length); }