Return to lsreq.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / proto / ospf |
1.1 ! misho 1: /* ! 2: * BIRD -- OSPF ! 3: * ! 4: * (c) 2000--2004 Ondrej Filip <feela@network.cz> ! 5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org> ! 6: * (c) 2009--2014 CZ.NIC z.s.p.o. ! 7: * ! 8: * Can be freely distributed and used under the terms of the GNU GPL. ! 9: */ ! 10: ! 11: #include "ospf.h" ! 12: ! 13: ! 14: /* ! 15: struct ospf_lsreq_packet ! 16: { ! 17: struct ospf_packet hdr; ! 18: // union ospf_auth auth; ! 19: ! 20: struct ospf_lsreq_header lsrs[]; ! 21: }; ! 22: */ ! 23: ! 24: ! 25: static inline void ! 26: ospf_lsreq_body(struct ospf_proto *p, struct ospf_packet *pkt, ! 27: struct ospf_lsreq_header **body, uint *count) ! 28: { ! 29: uint plen = ntohs(pkt->length); ! 30: uint hlen = ospf_pkt_hdrlen(p); ! 31: ! 32: *body = ((void *) pkt) + hlen; ! 33: *count = (plen - hlen) / sizeof(struct ospf_lsreq_header); ! 34: } ! 35: ! 36: static void ! 37: ospf_dump_lsreq(struct ospf_proto *p, struct ospf_packet *pkt) ! 38: { ! 39: struct ospf_lsreq_header *lsrs; ! 40: uint i, lsr_count; ! 41: ! 42: ASSERT(pkt->type == LSREQ_P); ! 43: ospf_dump_common(p, pkt); ! 44: ! 45: ospf_lsreq_body(p, pkt, &lsrs, &lsr_count); ! 46: for (i = 0; i < lsr_count; i++) ! 47: log(L_TRACE "%s: LSR Type: %04x, Id: %R, Rt: %R", p->p.name, ! 48: ntohl(lsrs[i].type), ntohl(lsrs[i].id), ntohl(lsrs[i].rt)); ! 49: } ! 50: ! 51: ! 52: void ! 53: ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n) ! 54: { ! 55: struct ospf_iface *ifa = n->ifa; ! 56: struct ospf_lsreq_header *lsrs; ! 57: struct top_hash_entry *req; ! 58: struct ospf_packet *pkt; ! 59: uint i, lsr_max, length; ! 60: ! 61: /* RFC 2328 10.9 */ ! 62: ! 63: /* ASSERT((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql)); */ ! 64: ! 65: pkt = ospf_tx_buffer(ifa); ! 66: ospf_pkt_fill_hdr(ifa, pkt, LSREQ_P); ! 67: ospf_lsreq_body(p, pkt, &lsrs, &lsr_max); ! 68: ! 69: i = 0; ! 70: WALK_SLIST(req, n->lsrql) ! 71: { ! 72: if (i == lsr_max) ! 73: break; ! 74: ! 75: DBG("Requesting %uth LSA: Type: %04u, ID: %R, RT: %R, SN: 0x%x, Age %u\n", ! 76: i, req->lsa_type, req->lsa.id, req->lsa.rt, req->lsa.sn, req->lsa.age); ! 77: ! 78: u32 etype = lsa_get_etype(&req->lsa, p); ! 79: lsrs[i].type = htonl(etype); ! 80: lsrs[i].rt = htonl(req->lsa.rt); ! 81: lsrs[i].id = htonl(req->lsa.id); ! 82: i++; ! 83: } ! 84: ! 85: /* We store the position to see whether requested LSAs have been received */ ! 86: n->lsrqi = req; ! 87: ! 88: length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsreq_header); ! 89: pkt->length = htons(length); ! 90: ! 91: OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet sent to nbr %R on %s", n->rid, ifa->ifname); ! 92: ospf_send_to(ifa, n->ip); ! 93: } ! 94: ! 95: ! 96: void ! 97: ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa, ! 98: struct ospf_neighbor *n) ! 99: { ! 100: struct ospf_proto *p = ifa->oa->po; ! 101: struct ospf_lsreq_header *lsrs; ! 102: uint i, lsr_count; ! 103: ! 104: /* RFC 2328 10.7 */ ! 105: ! 106: /* No need to check length, lsreq has only basic header */ ! 107: ! 108: OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet received from nbr %R on %s", n->rid, ifa->ifname); ! 109: ! 110: if (n->state < NEIGHBOR_EXCHANGE) ! 111: { ! 112: OSPF_TRACE(D_PACKETS, "LSREQ packet ignored - lesser state than Exchange"); ! 113: return; ! 114: } ! 115: ! 116: ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */ ! 117: ! 118: ospf_lsreq_body(p, pkt, &lsrs, &lsr_count); ! 119: ! 120: struct top_hash_entry *en, *entries[lsr_count]; ! 121: ! 122: for (i = 0; i < lsr_count; i++) ! 123: { ! 124: u32 id, rt, type, domain; ! 125: ! 126: id = ntohl(lsrs[i].id); ! 127: rt = ntohl(lsrs[i].rt); ! 128: lsa_get_type_domain_(ntohl(lsrs[i].type), id, ifa, &type, &domain); ! 129: ! 130: DBG("Processing requested LSA: Type: %04x, Id: %R, Rt: %R\n", type, id, rt); ! 131: ! 132: en = ospf_hash_find(p->gr, domain, id, rt, type); ! 133: if (!en) ! 134: { ! 135: LOG_LSA1("Bad LSR (Type: %04x, Id: %R, Rt: %R) in LSREQ", type, id, rt); ! 136: LOG_LSA2(" received from nbr %R on %s - LSA is missing", n->rid, ifa->ifname); ! 137: ! 138: ospf_neigh_sm(n, INM_BADLSREQ); ! 139: return; ! 140: } ! 141: ! 142: entries[i] = en; ! 143: } ! 144: ! 145: ospf_send_lsupd(p, entries, lsr_count, n); ! 146: }