]>
Commit | Line | Data |
---|---|---|
4364b47e OF |
1 | /* |
2 | * BIRD -- OSPF | |
3 | * | |
e6ea2e37 | 4 | * (c) 1999--2005 Ondrej Filip <feela@network.cz> |
4364b47e OF |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #include "ospf.h" | |
3e2bd0f1 OF |
10 | #include "nest/password.h" |
11 | #include "lib/md5.h" | |
4364b47e OF |
12 | |
13 | void | |
3e2bd0f1 | 14 | ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type) |
4364b47e | 15 | { |
8a70a13e | 16 | struct proto_ospf *po = ifa->oa->po; |
4364b47e | 17 | struct ospf_packet *pkt; |
4364b47e | 18 | |
00bd27a1 | 19 | pkt = (struct ospf_packet *) buf; |
4364b47e | 20 | |
00bd27a1 | 21 | pkt->version = OSPF_VERSION; |
4364b47e | 22 | |
00bd27a1 OF |
23 | pkt->type = h_type; |
24 | ||
8a70a13e | 25 | pkt->routerid = htonl(po->router_id); |
3b16080c | 26 | pkt->areaid = htonl(ifa->oa->areaid); |
c3226991 OZ |
27 | |
28 | #ifdef OSPFv3 | |
29 | pkt->instance_id = ifa->instance_id; | |
30 | #endif | |
31 | ||
32 | #ifdef OSPFv2 | |
2e10a170 | 33 | pkt->autype = htons(ifa->autype); |
c3226991 OZ |
34 | #endif |
35 | ||
00bd27a1 | 36 | pkt->checksum = 0; |
4364b47e OF |
37 | } |
38 | ||
3e2bd0f1 OF |
39 | unsigned |
40 | ospf_pkt_maxsize(struct ospf_iface *ifa) | |
41 | { | |
e6ea2e37 | 42 | unsigned mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu; |
d5356072 | 43 | unsigned headers = SIZE_OF_IP_HEADER; |
c3226991 OZ |
44 | |
45 | #ifdef OSPFv2 | |
d5356072 OZ |
46 | if (ifa->autype == OSPF_AUTH_CRYPT) |
47 | headers += OSPF_AUTH_CRYPT_SIZE; | |
c3226991 OZ |
48 | #endif |
49 | ||
d5356072 | 50 | return mtu - headers; |
3e2bd0f1 OF |
51 | } |
52 | ||
c3226991 OZ |
53 | #ifdef OSPFv2 |
54 | ||
55 | static void | |
3e2bd0f1 | 56 | ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) |
4364b47e | 57 | { |
b21f68b4 | 58 | struct password_item *passwd = NULL; |
3e2bd0f1 OF |
59 | void *tail; |
60 | struct MD5Context ctxt; | |
61 | char password[OSPF_AUTH_CRYPT_SIZE]; | |
62 | ||
2e10a170 | 63 | pkt->autype = htons(ifa->autype); |
3e2bd0f1 OF |
64 | |
65 | switch(ifa->autype) | |
66 | { | |
3e2bd0f1 | 67 | case OSPF_AUTH_SIMPLE: |
32d3228d | 68 | bzero(&pkt->u, sizeof(union ospf_auth)); |
b21f68b4 | 69 | passwd = password_find(ifa->passwords, 1); |
32d3228d OF |
70 | if (!passwd) |
71 | { | |
72 | log( L_ERR "No suitable password found for authentication" ); | |
73 | return; | |
74 | } | |
75 | password_cpy(pkt->u.password, passwd->password, sizeof(union ospf_auth)); | |
69b27ed6 | 76 | case OSPF_AUTH_NONE: |
7969ea3b | 77 | pkt->checksum = 0; |
32d3228d OF |
78 | pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) - |
79 | sizeof(union ospf_auth), (pkt + 1), | |
3e2bd0f1 OF |
80 | ntohs(pkt->length) - |
81 | sizeof(struct ospf_packet), NULL); | |
3e2bd0f1 OF |
82 | break; |
83 | case OSPF_AUTH_CRYPT: | |
b21f68b4 | 84 | passwd = password_find(ifa->passwords, 0); |
3e2bd0f1 OF |
85 | if (!passwd) |
86 | { | |
87 | log( L_ERR "No suitable password found for authentication" ); | |
88 | return; | |
89 | } | |
90 | ||
91 | pkt->checksum = 0; | |
92 | ||
024c310b OZ |
93 | /* Perhaps use random value to prevent replay attacks after |
94 | reboot when system does not have independent RTC? */ | |
3e2bd0f1 | 95 | if (!ifa->csn) |
024c310b OZ |
96 | { |
97 | ifa->csn = (u32) now; | |
98 | ifa->csn_use = now; | |
99 | } | |
100 | ||
101 | /* We must have sufficient delay between sending a packet and increasing | |
102 | CSN to prevent reordering of packets (in a network) with different CSNs */ | |
103 | if ((now - ifa->csn_use) > 1) | |
104 | ifa->csn++; | |
105 | ||
106 | ifa->csn_use = now; | |
3e2bd0f1 OF |
107 | |
108 | pkt->u.md5.keyid = passwd->id; | |
109 | pkt->u.md5.len = OSPF_AUTH_CRYPT_SIZE; | |
110 | pkt->u.md5.zero = 0; | |
024c310b | 111 | pkt->u.md5.csn = htonl(ifa->csn); |
3e2bd0f1 OF |
112 | tail = ((void *)pkt) + ntohs(pkt->length); |
113 | MD5Init(&ctxt); | |
114 | MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length)); | |
115 | password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE); | |
116 | MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); | |
117 | MD5Final(tail, &ctxt); | |
3e2bd0f1 OF |
118 | break; |
119 | default: | |
120 | bug("Unknown authentication type"); | |
121 | } | |
4364b47e OF |
122 | } |
123 | ||
9831e591 | 124 | static int |
69b27ed6 | 125 | ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size) |
c1824c4d | 126 | { |
86c84d76 | 127 | struct proto_ospf *po = ifa->oa->po; |
3e2bd0f1 OF |
128 | struct proto *p = &po->proto; |
129 | struct password_item *pass = NULL, *ptmp; | |
130 | void *tail; | |
131 | char md5sum[OSPF_AUTH_CRYPT_SIZE]; | |
132 | char password[OSPF_AUTH_CRYPT_SIZE]; | |
133 | struct MD5Context ctxt; | |
134 | ||
135 | ||
2e10a170 | 136 | if (pkt->autype != htons(ifa->autype)) |
2e10a170 | 137 | { |
3e2bd0f1 OF |
138 | OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", ntohs(pkt->autype)); |
139 | return 0; | |
2e10a170 | 140 | } |
c1824c4d | 141 | |
3e2bd0f1 OF |
142 | switch(ifa->autype) |
143 | { | |
144 | case OSPF_AUTH_NONE: | |
145 | return 1; | |
146 | break; | |
147 | case OSPF_AUTH_SIMPLE: | |
b21f68b4 | 148 | pass = password_find(ifa->passwords, 1); |
3b108f18 | 149 | if (!pass) |
3e2bd0f1 OF |
150 | { |
151 | OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found"); | |
152 | return 0; | |
153 | } | |
32d3228d | 154 | password_cpy(password, pass->password, sizeof(union ospf_auth)); |
4364b47e | 155 | |
32d3228d | 156 | if (memcmp(pkt->u.password, password, sizeof(union ospf_auth))) |
3e2bd0f1 | 157 | { |
32d3228d OF |
158 | char ppass[sizeof(union ospf_auth) + 1]; |
159 | bzero(ppass, (sizeof(union ospf_auth) + 1)); | |
160 | memcpy(ppass, pkt->u.password, sizeof(union ospf_auth)); | |
161 | OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords (%s)", ppass); | |
3e2bd0f1 OF |
162 | return 0; |
163 | } | |
32d3228d | 164 | return 1; |
3e2bd0f1 OF |
165 | break; |
166 | case OSPF_AUTH_CRYPT: | |
167 | if (pkt->u.md5.len != OSPF_AUTH_CRYPT_SIZE) | |
168 | { | |
169 | OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest"); | |
170 | return 0; | |
171 | } | |
3b108f18 | 172 | |
885b3d61 | 173 | if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE > size) |
3e2bd0f1 | 174 | { |
f39e3bfd | 175 | OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)", |
5d3f5552 | 176 | ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size); |
3e2bd0f1 OF |
177 | return 0; |
178 | } | |
179 | ||
3e2bd0f1 OF |
180 | tail = ((void *)pkt) + ntohs(pkt->length); |
181 | ||
3b108f18 | 182 | if (ifa->passwords) |
3e2bd0f1 | 183 | { |
3b108f18 OZ |
184 | WALK_LIST(ptmp, *(ifa->passwords)) |
185 | { | |
186 | if (pkt->u.md5.keyid != ptmp->id) continue; | |
187 | if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue; | |
188 | pass = ptmp; | |
189 | break; | |
190 | } | |
3e2bd0f1 OF |
191 | } |
192 | ||
3b108f18 | 193 | if (!pass) |
3e2bd0f1 OF |
194 | { |
195 | OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found"); | |
196 | return 0; | |
197 | } | |
198 | ||
3b108f18 | 199 | if (n) |
3e2bd0f1 | 200 | { |
024c310b OZ |
201 | u32 rcv_csn = ntohl(pkt->u.md5.csn); |
202 | if(rcv_csn < n->csn) | |
203 | { | |
204 | OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn); | |
205 | return 0; | |
206 | } | |
207 | ||
208 | n->csn = rcv_csn; | |
3e2bd0f1 OF |
209 | } |
210 | ||
211 | MD5Init(&ctxt); | |
212 | MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length)); | |
213 | password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE); | |
214 | MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); | |
215 | MD5Final(md5sum, &ctxt); | |
bc956fca | 216 | if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE)) |
3e2bd0f1 OF |
217 | { |
218 | OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest"); | |
219 | return 0; | |
220 | } | |
221 | return 1; | |
222 | break; | |
223 | default: | |
224 | OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type"); | |
225 | return 0; | |
226 | } | |
4364b47e OF |
227 | } |
228 | ||
c3226991 OZ |
229 | #else |
230 | ||
231 | /* OSPFv3 authentication not yet supported */ | |
232 | ||
233 | static inline void | |
234 | ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) | |
235 | { } | |
236 | ||
237 | static int | |
238 | ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size) | |
239 | { return 1; } | |
353729f5 OZ |
240 | |
241 | #endif | |
242 | ||
c3226991 | 243 | |
351feeb5 OF |
244 | /** |
245 | * ospf_rx_hook | |
353729f5 | 246 | * @sk: socket we received the packet. |
351feeb5 OF |
247 | * @size: size of the packet |
248 | * | |
baa5dd6c OF |
249 | * This is the entry point for messages from neighbors. Many checks (like |
250 | * authentication, checksums, size) are done before the packet is passed to | |
351feeb5 OF |
251 | * non generic functions. |
252 | */ | |
4364b47e | 253 | int |
353729f5 | 254 | ospf_rx_hook(sock *sk, int size) |
4364b47e | 255 | { |
353729f5 | 256 | char *mesg = "OSPF: Bad packet from "; |
4364b47e | 257 | |
e7b76b97 OZ |
258 | /* We want just packets from sk->iface. Unfortunately, on BSD we |
259 | cannot filter out other packets at kernel level and we receive | |
260 | all packets on all sockets */ | |
261 | if (sk->lifindex != sk->iface->index) | |
262 | return 1; | |
263 | ||
264 | DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n", | |
265 | sk->iface->name, sk->faddr, sk->laddr); | |
266 | ||
267 | /* Initially, the packet is associated with the 'master' iface */ | |
268 | struct ospf_iface *ifa = sk->data; | |
269 | struct proto_ospf *po = ifa->oa->po; | |
54305181 | 270 | // struct proto *p = &po->proto; |
e7b76b97 | 271 | |
ab164971 OZ |
272 | int src_local, dst_local UNUSED, dst_mcast; |
273 | src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen); | |
274 | dst_local = ipa_equal(sk->laddr, ifa->addr->ip); | |
275 | dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters); | |
e7b76b97 OZ |
276 | |
277 | #ifdef OSPFv2 | |
278 | /* First, we eliminate packets with strange address combinations. | |
279 | * In OSPFv2, they might be for other ospf_ifaces (with different IP | |
280 | * prefix) on the same real iface, so we don't log it. We enforce | |
281 | * that (src_local || dst_local), therefore we are eliminating all | |
282 | * such cases. | |
283 | */ | |
284 | if (dst_mcast && !src_local) | |
285 | return 1; | |
286 | if (!dst_mcast && !dst_local) | |
287 | return 1; | |
00bd27a1 | 288 | |
e7b76b97 OZ |
289 | #else /* OSPFv3 */ |
290 | ||
291 | /* In OSPFv3, src_local and dst_local mean link-local. | |
292 | * RFC 5340 says that local (non-vlink) packets use | |
293 | * link-local src address, but does not enforce it. Strange. | |
294 | */ | |
295 | if (dst_mcast && !src_local) | |
296 | log(L_WARN "OSPF: Received multicast packet from %I (not link-local)", sk->faddr); | |
297 | #endif | |
298 | ||
299 | /* Second, we check packet size, checksum, and the protocol version */ | |
353729f5 | 300 | struct ospf_packet *ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size); |
3b16080c | 301 | |
0e9617e4 OZ |
302 | if (ps == NULL) |
303 | { | |
304 | log(L_ERR "%s%I - bad IP header", mesg, sk->faddr); | |
305 | return 1; | |
306 | } | |
307 | ||
2e10a170 OF |
308 | if ((unsigned) size < sizeof(struct ospf_packet)) |
309 | { | |
5e3436d2 OF |
310 | log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size); |
311 | return 1; | |
2e10a170 | 312 | } |
00bd27a1 | 313 | |
353729f5 | 314 | int osize = ntohs(ps->length); |
a6bc04d5 | 315 | if ((osize > size) || ((osize % 4) != 0)) |
2e10a170 | 316 | { |
a6bc04d5 | 317 | log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, osize, size); |
5e3436d2 | 318 | return 1; |
2e10a170 | 319 | } |
00bd27a1 | 320 | |
353729f5 OZ |
321 | if ((unsigned) size > sk->rbsize) |
322 | { | |
323 | log(L_ERR "%s%I - too large (%d vs %d)", mesg, sk->faddr, size, sk->rbsize); | |
324 | return 1; | |
325 | } | |
326 | ||
00bd27a1 | 327 | if (ps->version != OSPF_VERSION) |
2e10a170 | 328 | { |
5e3436d2 OF |
329 | log(L_ERR "%s%I - version %u", mesg, sk->faddr, ps->version); |
330 | return 1; | |
2e10a170 | 331 | } |
00bd27a1 | 332 | |
c3226991 | 333 | #ifdef OSPFv2 |
bc956fca OF |
334 | if ((ps->autype != htons(OSPF_AUTH_CRYPT)) && |
335 | (!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet), | |
a6bc04d5 | 336 | osize - sizeof(struct ospf_packet), NULL))) |
2e10a170 | 337 | { |
5e3436d2 OF |
338 | log(L_ERR "%s%I - bad checksum", mesg, sk->faddr); |
339 | return 1; | |
2e10a170 | 340 | } |
c3226991 | 341 | #endif |
00bd27a1 | 342 | |
353729f5 | 343 | |
e7b76b97 OZ |
344 | /* Third, we resolve associated iface and handle vlinks. */ |
345 | ||
346 | u32 areaid = ntohl(ps->areaid); | |
347 | u32 rid = ntohl(ps->routerid); | |
348 | ||
349 | if ((areaid == ifa->oa->areaid) | |
350 | #ifdef OSPFv3 | |
bed41728 | 351 | && (ps->instance_id == ifa->instance_id) |
e7b76b97 OZ |
352 | #endif |
353 | ) | |
354 | { | |
355 | /* It is real iface, source should be local (in OSPFv2) */ | |
356 | #ifdef OSPFv2 | |
357 | if (!src_local) | |
358 | return 1; | |
359 | #endif | |
360 | } | |
361 | else if (dst_mcast || (areaid != 0)) | |
362 | { | |
363 | /* Obvious mismatch */ | |
364 | ||
365 | #ifdef OSPFv2 | |
366 | /* We ignore mismatch in OSPFv3, because there might be | |
367 | other instance with different instance ID */ | |
368 | log(L_ERR "%s%I - area does not match (%R vs %R)", | |
369 | mesg, sk->faddr, areaid, ifa->oa->areaid); | |
370 | #endif | |
371 | return 1; | |
372 | } | |
373 | else | |
2e10a170 | 374 | { |
e7b76b97 OZ |
375 | /* Some vlink? */ |
376 | struct ospf_iface *iff = NULL; | |
377 | ||
378 | WALK_LIST(iff, po->iface_list) | |
353729f5 | 379 | { |
e7b76b97 OZ |
380 | if ((iff->type == OSPF_IT_VLINK) && |
381 | (iff->voa == ifa->oa) && | |
382 | #ifdef OSPFv3 | |
383 | (iff->instance_id == ps->instance_id) && | |
384 | #endif | |
385 | (iff->vid == rid)) | |
386 | { | |
387 | /* Vlink should be UP */ | |
388 | if (iff->state != OSPF_IS_PTP) | |
389 | return 1; | |
390 | ||
391 | ifa = iff; | |
392 | goto found; | |
393 | } | |
353729f5 OZ |
394 | } |
395 | ||
e7b76b97 | 396 | #ifdef OSPFv2 |
ed76033c | 397 | log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr); |
e7b76b97 | 398 | #endif |
5e3436d2 | 399 | return 1; |
2e10a170 | 400 | } |
00bd27a1 | 401 | |
e7b76b97 | 402 | found: |
353729f5 OZ |
403 | if (ifa->stub) /* This shouldn't happen */ |
404 | return 1; | |
405 | ||
406 | if (ipa_equal(sk->laddr, AllDRouters) && (ifa->sk_dr == 0)) | |
c3226991 | 407 | return 1; |
c3226991 | 408 | |
e7b76b97 | 409 | if (rid == po->router_id) |
2e10a170 | 410 | { |
5e3436d2 OF |
411 | log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr); |
412 | return 1; | |
2e10a170 | 413 | } |
00bd27a1 | 414 | |
e7b76b97 | 415 | if (rid == 0) |
2e10a170 | 416 | { |
5e3436d2 OF |
417 | log(L_ERR "%s%I - router id = 0.0.0.0", mesg, sk->faddr); |
418 | return 1; | |
419 | } | |
420 | ||
9d1ee138 OZ |
421 | #ifdef OSPFv2 |
422 | /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */ | |
423 | struct ospf_neighbor *n; | |
919f5411 | 424 | if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)) |
9d1ee138 OZ |
425 | n = find_neigh_by_ip(ifa, sk->faddr); |
426 | else | |
427 | n = find_neigh(ifa, rid); | |
428 | #else | |
e7b76b97 | 429 | struct ospf_neighbor *n = find_neigh(ifa, rid); |
9d1ee138 | 430 | #endif |
5e3436d2 OF |
431 | |
432 | if(!n && (ps->type != HELLO_P)) | |
433 | { | |
ed76033c | 434 | log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)", |
353729f5 | 435 | sk->faddr, ifa->iface->name); |
5e3436d2 | 436 | return 1; |
2e10a170 | 437 | } |
00bd27a1 | 438 | |
69b27ed6 | 439 | if (!ospf_pkt_checkauth(n, ifa, ps, size)) |
3e2bd0f1 | 440 | { |
ed76033c | 441 | log(L_ERR "%s%I - authentication failed", mesg, sk->faddr); |
3e2bd0f1 OF |
442 | return 1; |
443 | } | |
444 | ||
351feeb5 | 445 | /* Dump packet |
00bd27a1 OF |
446 | pu8=(u8 *)(sk->rbuf+5*4); |
447 | for(i=0;i<ntohs(ps->length);i+=4) | |
448 | DBG("%s: received %u,%u,%u,%u\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2], | |
449 | pu8[i+3]); | |
450 | DBG("%s: received size: %u\n",p->name,size); | |
451 | */ | |
452 | ||
453 | switch (ps->type) | |
2e10a170 OF |
454 | { |
455 | case HELLO_P: | |
456 | DBG("%s: Hello received.\n", p->name); | |
c3226991 | 457 | ospf_hello_receive(ps, ifa, n, sk->faddr); |
2e10a170 OF |
458 | break; |
459 | case DBDES_P: | |
460 | DBG("%s: Database description received.\n", p->name); | |
c3226991 | 461 | ospf_dbdes_receive(ps, ifa, n); |
2e10a170 OF |
462 | break; |
463 | case LSREQ_P: | |
464 | DBG("%s: Link state request received.\n", p->name); | |
c3226991 | 465 | ospf_lsreq_receive(ps, ifa, n); |
2e10a170 OF |
466 | break; |
467 | case LSUPD_P: | |
468 | DBG("%s: Link state update received.\n", p->name); | |
c3226991 | 469 | ospf_lsupd_receive(ps, ifa, n); |
2e10a170 OF |
470 | break; |
471 | case LSACK_P: | |
472 | DBG("%s: Link state ack received.\n", p->name); | |
c3226991 | 473 | ospf_lsack_receive(ps, ifa, n); |
2e10a170 OF |
474 | break; |
475 | default: | |
5e3436d2 OF |
476 | log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type); |
477 | return 1; | |
2e10a170 | 478 | }; |
5e3436d2 | 479 | return 1; |
4364b47e OF |
480 | } |
481 | ||
482 | void | |
2e10a170 | 483 | ospf_tx_hook(sock * sk) |
4364b47e | 484 | { |
353729f5 OZ |
485 | // struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); |
486 | // struct proto *p = (struct proto *) (ifa->oa->po); | |
487 | log(L_ERR "OSPF: TX_Hook called"); | |
4364b47e OF |
488 | } |
489 | ||
490 | void | |
2eef9e88 | 491 | ospf_err_hook(sock * sk, int err) |
4364b47e | 492 | { |
353729f5 OZ |
493 | // struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); |
494 | // struct proto *p = (struct proto *) (ifa->oa->po); | |
495 | log(L_ERR "OSPF: Socket error: %m", err); | |
4364b47e OF |
496 | } |
497 | ||
67315ef6 | 498 | void |
f9c799a0 | 499 | ospf_send_to_agt(struct ospf_iface *ifa, u8 state) |
67315ef6 OF |
500 | { |
501 | struct ospf_neighbor *n; | |
502 | ||
353729f5 OZ |
503 | WALK_LIST(n, ifa->neigh_list) |
504 | if (n->state >= state) | |
505 | ospf_send_to(ifa, n->ip); | |
00bd27a1 | 506 | } |
eb436e16 OF |
507 | |
508 | void | |
f9c799a0 | 509 | ospf_send_to_bdr(struct ospf_iface *ifa) |
eb436e16 | 510 | { |
3b16080c | 511 | if (!ipa_equal(ifa->drip, IPA_NONE)) |
f9c799a0 | 512 | ospf_send_to(ifa, ifa->drip); |
3b16080c | 513 | if (!ipa_equal(ifa->bdrip, IPA_NONE)) |
f9c799a0 | 514 | ospf_send_to(ifa, ifa->bdrip); |
eb436e16 | 515 | } |
98ac6176 OF |
516 | |
517 | void | |
353729f5 | 518 | ospf_send_to(struct ospf_iface *ifa, ip_addr dst) |
98ac6176 | 519 | { |
f9c799a0 | 520 | sock *sk = ifa->sk; |
3e2bd0f1 | 521 | struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf; |
c3226991 | 522 | int len = ntohs(pkt->length); |
3e2bd0f1 | 523 | |
c3226991 OZ |
524 | #ifdef OSPFv2 |
525 | if (ifa->autype == OSPF_AUTH_CRYPT) | |
526 | len += OSPF_AUTH_CRYPT_SIZE; | |
527 | #endif | |
528 | ||
529 | ospf_pkt_finalize(ifa, pkt); | |
f15cb99c | 530 | if (sk->tbuf != sk->tpos) |
353729f5 | 531 | log(L_ERR "Aiee, old packet was overwritten in TX buffer"); |
f15cb99c | 532 | |
353729f5 | 533 | sk_send_to(sk, len, dst, 0); |
98ac6176 OF |
534 | } |
535 |