Annotation of embedaddon/bird/proto/ospf/lsreq.c, revision 1.1
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), 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>