1: /*
2: * BIRD -- OSPF
3: *
4: * (c) 1999--2005 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: #include "nest/password.h"
13: #include "lib/md5.h"
14: #include "lib/mac.h"
15: #include "lib/socket.h"
16:
17: void
18: ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
19: {
20: struct ospf_proto *p = ifa->oa->po;
21: struct ospf_packet *pkt;
22:
23: pkt = (struct ospf_packet *) buf;
24:
25: pkt->version = ospf_get_version(p);
26: pkt->type = h_type;
27: pkt->length = htons(ospf_pkt_maxsize(ifa));
28: pkt->routerid = htonl(p->router_id);
29: pkt->areaid = htonl(ifa->oa->areaid);
30: pkt->checksum = 0;
31: pkt->instance_id = ifa->instance_id;
32: pkt->autype = ifa->autype;
33: }
34:
35: /* We assume OSPFv2 in ospf_pkt_finalize() */
36: static void
37: ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
38: {
39: struct password_item *pass = NULL;
40: union ospf_auth *auth = (void *) (pkt + 1);
41:
42: pkt->checksum = 0;
43: pkt->autype = ifa->autype;
44: bzero(auth, sizeof(union ospf_auth));
45:
46: /* Compatibility note: auth may contain anything if autype is
47: none, but nonzero values do not work with Mikrotik OSPF */
48:
49: switch (ifa->autype)
50: {
51: case OSPF_AUTH_SIMPLE:
52: pass = password_find(ifa->passwords, 1);
53: if (!pass)
54: {
55: log(L_ERR "No suitable password found for authentication");
56: return;
57: }
58: strncpy(auth->password, pass->password, sizeof(auth->password));
59:
60: case OSPF_AUTH_NONE:
61: {
62: void *body = (void *) (auth + 1);
63: uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth);
64: pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
65: }
66: break;
67:
68: case OSPF_AUTH_CRYPT:
69: pass = password_find(ifa->passwords, 0);
70: if (!pass)
71: {
72: log(L_ERR "No suitable password found for authentication");
73: return;
74: }
75:
76: /* Perhaps use random value to prevent replay attacks after
77: reboot when system does not have independent RTC? */
78: if (!ifa->csn)
79: {
80: ifa->csn = (u32) now;
81: ifa->csn_use = now;
82: }
83:
84: /* We must have sufficient delay between sending a packet and increasing
85: CSN to prevent reordering of packets (in a network) with different CSNs */
86: if ((now - ifa->csn_use) > 1)
87: ifa->csn++;
88:
89: ifa->csn_use = now;
90:
91: uint auth_len = mac_type_length(pass->alg);
92: byte *auth_tail = ((byte *) pkt + *plen);
93: *plen += auth_len;
94:
95: ASSERT(*plen < ifa->sk->tbsize);
96:
97: auth->c32.zero = 0;
98: auth->c32.keyid = pass->id;
99: auth->c32.len = auth_len;
100: auth->c32.csn = htonl(ifa->csn);
101:
102: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
103: if (pass->alg < ALG_HMAC)
104: strncpy(auth_tail, pass->password, auth_len);
105: else
106: memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
107:
108: mac_fill(pass->alg, pass->password, pass->length,
109: (byte *) pkt, *plen, auth_tail);
110: break;
111:
112: default:
113: bug("Unknown authentication type");
114: }
115: }
116:
117:
118: /* We assume OSPFv2 in ospf_pkt_checkauth() */
119: static int
120: ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len)
121: {
122: struct ospf_proto *p = ifa->oa->po;
123: union ospf_auth *auth = (void *) (pkt + 1);
124: struct password_item *pass = NULL;
125: const char *err_dsc = NULL;
126: uint err_val = 0;
127:
128: uint plen = ntohs(pkt->length);
129: u8 autype = pkt->autype;
130:
131: if (autype != ifa->autype)
132: DROP("authentication method mismatch", autype);
133:
134: switch (autype)
135: {
136: case OSPF_AUTH_NONE:
137: return 1;
138:
139: case OSPF_AUTH_SIMPLE:
140: pass = password_find(ifa->passwords, 1);
141: if (!pass)
142: DROP1("no password found");
143:
144: if (!password_verify(pass, auth->password, sizeof(auth->password)))
145: DROP("wrong password", pass->id);
146:
147: return 1;
148:
149: case OSPF_AUTH_CRYPT:
150: pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
151: if (!pass)
152: DROP("no suitable password found", auth->c32.keyid);
153:
154: uint auth_len = mac_type_length(pass->alg);
155:
156: if (plen + auth->c32.len > len)
157: DROP("packet length mismatch", len);
158:
159: if (auth->c32.len != auth_len)
160: DROP("wrong authentication length", auth->c32.len);
161:
162: u32 rcv_csn = ntohl(auth->c32.csn);
163: if (n && (rcv_csn < n->csn))
164: // DROP("lower sequence number", rcv_csn);
165: {
166: /* We want to report both new and old CSN */
167: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
168: "lower sequence number (rcv %u, old %u)",
169: n->rid, ifa->ifname, rcv_csn, n->csn);
170: return 0;
171: }
172:
173: byte *auth_tail = ((byte *) pkt) + plen;
174: byte *auth_data = alloca(auth_len);
175: memcpy(auth_data, auth_tail, auth_len);
176:
177: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
178: if (pass->alg < ALG_HMAC)
179: strncpy(auth_tail, pass->password, auth_len);
180: else
181: memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
182:
183: if (!mac_verify(pass->alg, pass->password, pass->length,
184: (byte *) pkt, plen + auth_len, auth_data))
185: DROP("wrong authentication code", pass->id);
186:
187: if (n)
188: n->csn = rcv_csn;
189:
190: return 1;
191:
192: default:
193: bug("Unknown authentication type");
194: }
195:
196: drop:
197: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
198: (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
199:
200: return 0;
201: }
202:
203: /**
204: * ospf_rx_hook
205: * @sk: socket we received the packet.
206: * @len: size of the packet
207: *
208: * This is the entry point for messages from neighbors. Many checks (like
209: * authentication, checksums, size) are done before the packet is passed to
210: * non generic functions.
211: */
212: int
213: ospf_rx_hook(sock *sk, uint len)
214: {
215: /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
216: out other packets at kernel level and we receive all packets on all sockets */
217: if (sk->lifindex != sk->iface->index)
218: return 1;
219:
220: DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
221: sk->iface->name, sk->faddr, sk->laddr);
222:
223: /* Initially, the packet is associated with the 'master' iface */
224: struct ospf_iface *ifa = sk->data;
225: struct ospf_proto *p = ifa->oa->po;
226: const char *err_dsc = NULL;
227: uint err_val = 0;
228:
229: /* Should not happen */
230: if (ifa->state <= OSPF_IS_LOOP)
231: return 1;
232:
233: int src_local, dst_local, dst_mcast;
234: src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
235: dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
236: dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
237:
238: if (ospf_is_v2(p))
239: {
240: /* First, we eliminate packets with strange address combinations.
241: * In OSPFv2, they might be for other ospf_ifaces (with different IP
242: * prefix) on the same real iface, so we don't log it. We enforce
243: * that (src_local || dst_local), therefore we are eliminating all
244: * such cases.
245: */
246: if (dst_mcast && !src_local)
247: return 1;
248: if (!dst_mcast && !dst_local)
249: return 1;
250:
251: /* Ignore my own broadcast packets */
252: if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
253: return 1;
254: }
255: else
256: {
257: /* In OSPFv3, src_local and dst_local mean link-local.
258: * RFC 5340 says that local (non-vlink) packets use
259: * link-local src address, but does not enforce it. Strange.
260: */
261: if (dst_mcast && !src_local)
262: LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
263: sk->faddr, ifa->ifname);
264: }
265:
266: /* Second, we check packet length, checksum, and the protocol version */
267: struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len);
268:
269:
270: if (pkt == NULL)
271: DROP("bad IP header", len);
272:
273: if (ifa->check_ttl && (sk->rcv_ttl < 255))
274: DROP("wrong TTL", sk->rcv_ttl);
275:
276: if (len < sizeof(struct ospf_packet))
277: DROP("too short", len);
278:
279: if (pkt->version != ospf_get_version(p))
280: DROP("version mismatch", pkt->version);
281:
282: uint plen = ntohs(pkt->length);
283: if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
284: DROP("invalid length", plen);
285:
286: if (sk->flags & SKF_TRUNCATED)
287: {
288: /* If we have dynamic buffers and received truncated message, we expand RX buffer */
289:
290: uint bs = plen + 256;
291: bs = BIRD_ALIGN(bs, 1024);
292:
293: if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
294: sk_set_rbsize(sk, bs);
295:
296: DROP("truncated", plen);
297: }
298:
299: if (plen > len)
300: DROP("length mismatch", plen);
301:
302: if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
303: {
304: uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth);
305: uint blen = plen - hlen;
306: void *body = ((void *) pkt) + hlen;
307:
308: if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
309: DROP1("invalid checksum");
310: }
311:
312: /* Third, we resolve associated iface and handle vlinks. */
313:
314: u32 areaid = ntohl(pkt->areaid);
315: u32 rid = ntohl(pkt->routerid);
316: u8 instance_id = pkt->instance_id;
317:
318: if (areaid == ifa->oa->areaid)
319: {
320: /* Matching area ID */
321:
322: if (instance_id != ifa->instance_id)
323: return 1;
324:
325: /* It is real iface, source should be local (in OSPFv2) */
326: if (ospf_is_v2(p) && !src_local)
327: DROP1("strange source address");
328:
329: goto found;
330: }
331: else if ((areaid == 0) && !dst_mcast)
332: {
333: /* Backbone area ID and possible vlink packet */
334:
335: if ((p->areano == 1) || !oa_is_ext(ifa->oa))
336: return 1;
337:
338: struct ospf_iface *iff = NULL;
339: WALK_LIST(iff, p->iface_list)
340: {
341: if ((iff->type == OSPF_IT_VLINK) &&
342: (iff->voa == ifa->oa) &&
343: (iff->instance_id == instance_id) &&
344: (iff->vid == rid))
345: {
346: /* Vlink should be UP */
347: if (iff->state != OSPF_IS_PTP)
348: return 1;
349:
350: ifa = iff;
351: goto found;
352: }
353: }
354:
355: /*
356: * Cannot find matching vlink. It is either misconfigured vlink; NBMA or
357: * PtMP with misconfigured area ID, or packet for some other instance (that
358: * is possible even if instance_id == ifa->instance_id, because it may be
359: * also vlink packet in the other instance, which is different namespace).
360: */
361:
362: return 1;
363: }
364: else
365: {
366: /* Non-matching area ID but cannot be vlink packet */
367:
368: if (instance_id != ifa->instance_id)
369: return 1;
370:
371: DROP("area mismatch", areaid);
372: }
373:
374:
375: found:
376: if (ifa->stub) /* This shouldn't happen */
377: return 1;
378:
379: if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
380: return 1;
381:
382: if (rid == p->router_id)
383: DROP1("my own router ID");
384:
385: if (rid == 0)
386: DROP1("zero router ID");
387:
388: /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
389: uint t = ifa->type;
390: struct ospf_neighbor *n;
391: if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
392: n = find_neigh_by_ip(ifa, sk->faddr);
393: else
394: n = find_neigh(ifa, rid);
395:
396: if (!n && (pkt->type != HELLO_P))
397: {
398: OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
399: rid, ifa->ifname, sk->faddr);
400: return 1;
401: }
402:
403: /* ospf_pkt_checkauth() has its own error logging */
404: if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len))
405: return 1;
406:
407: switch (pkt->type)
408: {
409: case HELLO_P:
410: ospf_receive_hello(pkt, ifa, n, sk->faddr);
411: break;
412:
413: case DBDES_P:
414: ospf_receive_dbdes(pkt, ifa, n);
415: break;
416:
417: case LSREQ_P:
418: ospf_receive_lsreq(pkt, ifa, n);
419: break;
420:
421: case LSUPD_P:
422: ospf_receive_lsupd(pkt, ifa, n);
423: break;
424:
425: case LSACK_P:
426: ospf_receive_lsack(pkt, ifa, n);
427: break;
428:
429: default:
430: DROP("invalid packet type", pkt->type);
431: };
432: return 1;
433:
434: drop:
435: LOG_PKT("Bad packet from %I via %s - %s (%u)",
436: sk->faddr, ifa->ifname, err_dsc, err_val);
437:
438: return 1;
439: }
440:
441: /*
442: void
443: ospf_tx_hook(sock * sk)
444: {
445: struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
446: // struct proto *p = (struct proto *) (ifa->oa->p);
447: log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
448: }
449: */
450:
451: void
452: ospf_err_hook(sock * sk, int err)
453: {
454: struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
455: struct ospf_proto *p = ifa->oa->po;
456: log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
457: }
458:
459: void
460: ospf_verr_hook(sock *sk, int err)
461: {
462: struct ospf_proto *p = (struct ospf_proto *) (sk->data);
463: log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
464: }
465:
466: void
467: ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
468: {
469: sock *sk = ifa->sk;
470: struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
471: uint plen = ntohs(pkt->length);
472:
473: if (ospf_is_v2(ifa->oa->po))
474: ospf_pkt_finalize(ifa, pkt, &plen);
475:
476: int done = sk_send_to(sk, plen, dst, 0);
477: if (!done)
478: log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
479: }
480:
481: void
482: ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
483: {
484: struct ospf_neighbor *n;
485:
486: WALK_LIST(n, ifa->neigh_list)
487: if (n->state >= state)
488: ospf_send_to(ifa, n->ip);
489: }
490:
491: void
492: ospf_send_to_bdr(struct ospf_iface *ifa)
493: {
494: if (ipa_nonzero(ifa->drip))
495: ospf_send_to(ifa, ifa->drip);
496: if (ipa_nonzero(ifa->bdrip))
497: ospf_send_to(ifa, ifa->bdrip);
498: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>