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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>