]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/hello.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / ldpd / hello.c
1 // SPDX-License-Identifier: ISC
2 /* $OpenBSD$ */
3
4 /*
5 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
6 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
7 */
8
9 #include <zebra.h>
10
11 #include "ldpd.h"
12 #include "ldpe.h"
13 #include "log.h"
14 #include "ldp_debug.h"
15
16 static int gen_hello_prms_tlv(struct ibuf *buf, uint16_t, uint16_t);
17 static int gen_opt4_hello_prms_tlv(struct ibuf *, uint16_t, uint32_t);
18 static int gen_opt16_hello_prms_tlv(struct ibuf *, uint16_t, uint8_t *);
19 static int gen_ds_hello_prms_tlv(struct ibuf *, uint32_t);
20 static int tlv_decode_hello_prms(char *, uint16_t, uint16_t *, uint16_t *);
21 static int tlv_decode_opt_hello_prms(char *, uint16_t, int *, int,
22 union ldpd_addr *, uint32_t *, uint16_t *);
23
24 int
25 send_hello(enum hello_type type, struct iface_af *ia, struct tnbr *tnbr)
26 {
27 int af;
28 union ldpd_addr dst;
29 uint16_t size, holdtime = 0, flags = 0;
30 int fd = 0;
31 struct ibuf *buf;
32 int err = 0;
33
34 switch (type) {
35 case HELLO_LINK:
36 af = ia->af;
37 holdtime = if_get_hello_holdtime(ia);
38 flags = 0;
39 fd = (ldp_af_global_get(&global, af))->ldp_disc_socket;
40
41 /* multicast destination address */
42 switch (af) {
43 case AF_INET:
44 if (!(leconf->ipv4.flags & F_LDPD_AF_NO_GTSM))
45 flags |= F_HELLO_GTSM;
46 dst.v4 = global.mcast_addr_v4;
47 break;
48 case AF_INET6:
49 dst.v6 = global.mcast_addr_v6;
50 break;
51 default:
52 fatalx("send_hello: unknown af");
53 }
54 break;
55 case HELLO_TARGETED:
56 af = tnbr->af;
57 holdtime = tnbr_get_hello_holdtime(tnbr);
58 flags = F_HELLO_TARGETED;
59 if ((tnbr->flags & F_TNBR_CONFIGURED) || tnbr->pw_count
60 || tnbr->rlfa_count)
61 flags |= F_HELLO_REQ_TARG;
62 fd = (ldp_af_global_get(&global, af))->ldp_edisc_socket;
63
64 /* unicast destination address */
65 dst = tnbr->addr;
66 break;
67 default:
68 fatalx("send_hello: unknown hello type");
69 }
70
71 /* calculate message size */
72 size = LDP_HDR_SIZE + LDP_MSG_SIZE + sizeof(struct hello_prms_tlv);
73 switch (af) {
74 case AF_INET:
75 size += sizeof(struct hello_prms_opt4_tlv);
76 break;
77 case AF_INET6:
78 size += sizeof(struct hello_prms_opt16_tlv);
79 break;
80 default:
81 fatalx("send_hello: unknown af");
82 }
83 size += sizeof(struct hello_prms_opt4_tlv);
84 if (ldp_is_dual_stack(leconf))
85 size += sizeof(struct hello_prms_opt4_tlv);
86
87 /* generate message */
88 if ((buf = ibuf_open(size)) == NULL)
89 fatal(__func__);
90
91 err |= gen_ldp_hdr(buf, size);
92 size -= LDP_HDR_SIZE;
93 err |= gen_msg_hdr(buf, MSG_TYPE_HELLO, size);
94 err |= gen_hello_prms_tlv(buf, holdtime, flags);
95
96 /*
97 * RFC 7552 - Section 6.1:
98 * "An LSR MUST include only the transport address whose address
99 * family is the same as that of the IP packet carrying the Hello
100 * message".
101 */
102 switch (af) {
103 case AF_INET:
104 err |= gen_opt4_hello_prms_tlv(buf, TLV_TYPE_IPV4TRANSADDR,
105 leconf->ipv4.trans_addr.v4.s_addr);
106 break;
107 case AF_INET6:
108 err |= gen_opt16_hello_prms_tlv(buf, TLV_TYPE_IPV6TRANSADDR,
109 leconf->ipv6.trans_addr.v6.s6_addr);
110 break;
111 default:
112 fatalx("send_hello: unknown af");
113 }
114
115 err |= gen_opt4_hello_prms_tlv(buf, TLV_TYPE_CONFIG,
116 htonl(global.conf_seqnum));
117
118 /*
119 * RFC 7552 - Section 6.1.1:
120 * "A Dual-stack LSR (i.e., an LSR supporting Dual-stack LDP for a peer)
121 * MUST include the Dual-Stack capability TLV in all of its LDP Hellos".
122 */
123 if (ldp_is_dual_stack(leconf))
124 err |= gen_ds_hello_prms_tlv(buf, leconf->trans_pref);
125
126 if (err) {
127 ibuf_free(buf);
128 return (-1);
129 }
130
131 switch (type) {
132 case HELLO_LINK:
133 debug_hello_send("iface %s (%s) holdtime %u", ia->iface->name,
134 af_name(ia->af), holdtime);
135 break;
136 case HELLO_TARGETED:
137 debug_hello_send("targeted-neighbor %s (%s) holdtime %u",
138 log_addr(tnbr->af, &tnbr->addr), af_name(tnbr->af),
139 holdtime);
140 break;
141 default:
142 fatalx("send_hello: unknown hello type");
143 }
144
145 send_packet(fd, af, &dst, ia, buf->buf, buf->wpos);
146 ibuf_free(buf);
147
148 return (0);
149 }
150
151 void
152 recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
153 union ldpd_addr *src, struct iface *iface, int multicast, char *buf,
154 uint16_t len)
155 {
156 struct adj *adj = NULL;
157 struct nbr *nbr, *nbrt;
158 uint16_t holdtime = 0, flags = 0;
159 int tlvs_rcvd;
160 int ds_tlv;
161 union ldpd_addr trans_addr;
162 ifindex_t scope_id = 0;
163 uint32_t conf_seqnum;
164 uint16_t trans_pref;
165 int r;
166 struct hello_source source;
167 struct iface_af *ia = NULL;
168 struct tnbr *tnbr = NULL;
169
170 r = tlv_decode_hello_prms(buf, len, &holdtime, &flags);
171 if (r == -1) {
172 log_debug("%s: lsr-id %pI4: failed to decode params", __func__,
173 &lsr_id);
174 return;
175 }
176 /* safety checks */
177 if (holdtime != 0 && holdtime < MIN_HOLDTIME) {
178 log_debug("%s: lsr-id %pI4: invalid hello holdtime (%u)",
179 __func__, &lsr_id, holdtime);
180 return;
181 }
182 if (multicast && (flags & F_HELLO_TARGETED)) {
183 log_debug("%s: lsr-id %pI4: multicast targeted hello", __func__,
184 &lsr_id);
185 return;
186 }
187 if (!multicast && !((flags & F_HELLO_TARGETED))) {
188 log_debug("%s: lsr-id %pI4: unicast link hello", __func__,
189 &lsr_id);
190 return;
191 }
192 buf += r;
193 len -= r;
194
195 r = tlv_decode_opt_hello_prms(buf, len, &tlvs_rcvd, af, &trans_addr,
196 &conf_seqnum, &trans_pref);
197 if (r == -1) {
198 log_debug("%s: lsr-id %pI4: failed to decode optional params",
199 __func__, &lsr_id);
200 return;
201 }
202 if (r != len) {
203 log_debug("%s: lsr-id %pI4: unexpected data in message",
204 __func__, &lsr_id);
205 return;
206 }
207 ds_tlv = (tlvs_rcvd & F_HELLO_TLV_RCVD_DS) ? 1 : 0;
208
209 /* implicit transport address */
210 if (!(tlvs_rcvd & F_HELLO_TLV_RCVD_ADDR))
211 trans_addr = *src;
212 if (bad_addr(af, &trans_addr)) {
213 log_debug("%s: lsr-id %pI4: invalid transport address %s",
214 __func__, &lsr_id, log_addr(af, &trans_addr));
215 return;
216 }
217 if (af == AF_INET6 && IN6_IS_SCOPE_EMBED(&trans_addr.v6)) {
218 /*
219 * RFC 7552 - Section 6.1:
220 * "An LSR MUST use a global unicast IPv6 address in an IPv6
221 * Transport Address optional object of outgoing targeted
222 * Hellos and check for the same in incoming targeted Hellos
223 * (i.e., MUST discard the targeted Hello if it failed the
224 * check)".
225 */
226 if (flags & F_HELLO_TARGETED) {
227 log_debug("%s: lsr-id %pI4: invalid targeted hello transport address %s", __func__, &lsr_id,
228 log_addr(af, &trans_addr));
229 return;
230 }
231 scope_id = iface->ifindex;
232 }
233
234 memset(&source, 0, sizeof(source));
235 if (flags & F_HELLO_TARGETED) {
236 /*
237 * RFC 7552 - Section 5.2:
238 * "The link-local IPv6 addresses MUST NOT be used as the
239 * targeted LDP Hello packet's source or destination addresses".
240 */
241 if (af == AF_INET6 && IN6_IS_SCOPE_EMBED(&src->v6)) {
242 log_debug("%s: lsr-id %pI4: targeted hello with link-local source address", __func__,
243 &lsr_id);
244 return;
245 }
246
247 tnbr = tnbr_find(leconf, af, src);
248
249 /* remove the dynamic tnbr if the 'R' bit was cleared */
250 if (tnbr && (tnbr->flags & F_TNBR_DYNAMIC) &&
251 !((flags & F_HELLO_REQ_TARG))) {
252 tnbr->flags &= ~F_TNBR_DYNAMIC;
253 tnbr = tnbr_check(leconf, tnbr);
254 }
255
256 if (!tnbr) {
257 struct ldpd_af_conf *af_conf;
258
259 if (!(flags & F_HELLO_REQ_TARG))
260 return;
261 af_conf = ldp_af_conf_get(leconf, af);
262 if (!(af_conf->flags & F_LDPD_AF_THELLO_ACCEPT))
263 return;
264 if (ldpe_acl_check(af_conf->acl_thello_accept_from, af,
265 src, (af == AF_INET) ? 32 : 128) != FILTER_PERMIT)
266 return;
267
268 tnbr = tnbr_new(af, src);
269 tnbr->flags |= F_TNBR_DYNAMIC;
270 tnbr_update(tnbr);
271 RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
272 }
273
274 source.type = HELLO_TARGETED;
275 source.target = tnbr;
276 } else {
277 ia = iface_af_get(iface, af);
278 source.type = HELLO_LINK;
279 source.link.ia = ia;
280 source.link.src_addr = *src;
281 }
282
283 debug_hello_recv("%s lsr-id %pI4 transport-address %s holdtime %u%s",
284 log_hello_src(&source), &lsr_id, log_addr(af, &trans_addr),
285 holdtime, (ds_tlv) ? " (dual stack TLV present)" : "");
286
287 adj = adj_find(lsr_id, &source);
288 if (adj && adj->ds_tlv != ds_tlv) {
289 /*
290 * Transient condition, ignore packet and wait until adjacency
291 * times out.
292 */
293 return;
294 }
295 nbr = nbr_find_ldpid(lsr_id.s_addr);
296
297 /* check dual-stack tlv */
298 if (ds_tlv && trans_pref != leconf->trans_pref) {
299 /*
300 * RFC 7552 - Section 6.1.1:
301 * "If the Dual-Stack capability TLV is present and the remote
302 * preference does not match the local preference (or does not
303 * get recognized), then the LSR MUST discard the Hello message
304 * and log an error.
305 * If an LDP session was already in place, then the LSR MUST
306 * send a fatal Notification message with status code of
307 * 'Transport Connection Mismatch' and reset the session".
308 */
309 log_debug("%s: lsr-id %pI4: remote transport preference does not match the local preference", __func__, &lsr_id);
310 if (nbr)
311 session_shutdown(nbr, S_TRANS_MISMTCH, msg->id,
312 msg->type);
313 if (adj)
314 adj_del(adj, S_SHUTDOWN);
315 return;
316 }
317
318 /*
319 * Check for noncompliant dual-stack neighbor according to
320 * RFC 7552 section 6.1.1.
321 */
322 if (nbr && !ds_tlv) {
323 switch (af) {
324 case AF_INET:
325 if (nbr_adj_count(nbr, AF_INET6) > 0) {
326 session_shutdown(nbr, S_DS_NONCMPLNCE,
327 msg->id, msg->type);
328 return;
329 }
330 break;
331 case AF_INET6:
332 if (nbr_adj_count(nbr, AF_INET) > 0) {
333 session_shutdown(nbr, S_DS_NONCMPLNCE,
334 msg->id, msg->type);
335 return;
336 }
337 break;
338 default:
339 fatalx("recv_hello: unknown af");
340 }
341 }
342
343 /*
344 * Protections against misconfigured networks and buggy implementations.
345 */
346 if (nbr && nbr->af == af &&
347 (ldp_addrcmp(af, &nbr->raddr, &trans_addr) ||
348 nbr->raddr_scope != scope_id)) {
349 log_warnx("%s: lsr-id %pI4: hello packet advertising a different transport address", __func__, &lsr_id);
350 if (adj)
351 adj_del(adj, S_SHUTDOWN);
352 return;
353 }
354 if (nbr == NULL) {
355 nbrt = nbr_find_addr(af, &trans_addr);
356 if (nbrt) {
357 log_debug("%s: transport address %s is already being used by lsr-id %pI4", __func__, log_addr(af,
358 &trans_addr), &nbrt->id);
359 if (adj)
360 adj_del(adj, S_SHUTDOWN);
361 return;
362 }
363 }
364
365 if (adj == NULL) {
366 adj = adj_new(lsr_id, &source, &trans_addr);
367 if (nbr) {
368 adj->nbr = nbr;
369 RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj);
370 }
371 ldp_sync_fsm_adj_event(adj, LDP_SYNC_EVT_ADJ_NEW);
372 }
373 adj->ds_tlv = ds_tlv;
374
375 /*
376 * If the hello adjacency's address-family doesn't match the local
377 * preference, then an adjacency is still created but we don't attempt
378 * to start an LDP session.
379 */
380 if (nbr == NULL && (!ds_tlv ||
381 ((trans_pref == DUAL_STACK_LDPOV4 && af == AF_INET) ||
382 (trans_pref == DUAL_STACK_LDPOV6 && af == AF_INET6))))
383 nbr = nbr_new(lsr_id, af, ds_tlv, &trans_addr, scope_id);
384
385 /* dynamic LDPv4 GTSM negotiation as per RFC 6720 */
386 if (nbr) {
387 if (flags & F_HELLO_GTSM)
388 nbr->flags |= F_NBR_GTSM_NEGOTIATED;
389 else
390 nbr->flags &= ~F_NBR_GTSM_NEGOTIATED;
391 }
392
393 /* update neighbor's configuration sequence number */
394 if (nbr && (tlvs_rcvd & F_HELLO_TLV_RCVD_CONF)) {
395 if (conf_seqnum > nbr->conf_seqnum &&
396 nbr_pending_idtimer(nbr))
397 nbr_stop_idtimer(nbr);
398 nbr->conf_seqnum = conf_seqnum;
399 }
400
401 /* always update the holdtime to properly handle runtime changes */
402 switch (source.type) {
403 case HELLO_LINK:
404 if (holdtime == 0)
405 holdtime = LINK_DFLT_HOLDTIME;
406
407 adj->holdtime = MIN(if_get_hello_holdtime(ia), holdtime);
408 break;
409 case HELLO_TARGETED:
410 if (holdtime == 0)
411 holdtime = TARGETED_DFLT_HOLDTIME;
412
413 adj->holdtime = MIN(tnbr_get_hello_holdtime(tnbr), holdtime);
414 }
415 if (adj->holdtime != INFINITE_HOLDTIME)
416 adj_start_itimer(adj);
417 else
418 adj_stop_itimer(adj);
419
420 if (nbr && nbr->state == NBR_STA_PRESENT && !nbr_pending_idtimer(nbr) &&
421 nbr_session_active_role(nbr) && !nbr_pending_connect(nbr))
422 nbr_establish_connection(nbr);
423 }
424
425 static int
426 gen_hello_prms_tlv(struct ibuf *buf, uint16_t holdtime, uint16_t flags)
427 {
428 struct hello_prms_tlv parms;
429
430 memset(&parms, 0, sizeof(parms));
431 parms.type = htons(TLV_TYPE_COMMONHELLO);
432 parms.length = htons(sizeof(parms.holdtime) + sizeof(parms.flags));
433 parms.holdtime = htons(holdtime);
434 parms.flags = htons(flags);
435
436 return (ibuf_add(buf, &parms, sizeof(parms)));
437 }
438
439 static int
440 gen_opt4_hello_prms_tlv(struct ibuf *buf, uint16_t type, uint32_t value)
441 {
442 struct hello_prms_opt4_tlv parms;
443
444 memset(&parms, 0, sizeof(parms));
445 parms.type = htons(type);
446 parms.length = htons(sizeof(parms.value));
447 parms.value = value;
448
449 return (ibuf_add(buf, &parms, sizeof(parms)));
450 }
451
452 static int
453 gen_opt16_hello_prms_tlv(struct ibuf *buf, uint16_t type, uint8_t *value)
454 {
455 struct hello_prms_opt16_tlv parms;
456
457 memset(&parms, 0, sizeof(parms));
458 parms.type = htons(type);
459 parms.length = htons(sizeof(parms.value));
460 memcpy(&parms.value, value, sizeof(parms.value));
461
462 return (ibuf_add(buf, &parms, sizeof(parms)));
463 }
464
465 static int
466 gen_ds_hello_prms_tlv(struct ibuf *buf, uint32_t value)
467 {
468 if (leconf->flags & F_LDPD_DS_CISCO_INTEROP)
469 value = htonl(value);
470 else
471 value = htonl(value << 28);
472
473 return (gen_opt4_hello_prms_tlv(buf, TLV_TYPE_DUALSTACK, value));
474 }
475
476 static int
477 tlv_decode_hello_prms(char *buf, uint16_t len, uint16_t *holdtime,
478 uint16_t *flags)
479 {
480 struct hello_prms_tlv tlv;
481
482 if (len < sizeof(tlv))
483 return (-1);
484 memcpy(&tlv, buf, sizeof(tlv));
485
486 if (tlv.type != htons(TLV_TYPE_COMMONHELLO))
487 return (-1);
488 if (ntohs(tlv.length) != sizeof(tlv) - TLV_HDR_SIZE)
489 return (-1);
490
491 *holdtime = ntohs(tlv.holdtime);
492 *flags = ntohs(tlv.flags);
493
494 return (sizeof(tlv));
495 }
496
497 static int
498 tlv_decode_opt_hello_prms(char *buf, uint16_t len, int *tlvs_rcvd, int af,
499 union ldpd_addr *addr, uint32_t *conf_number, uint16_t *trans_pref)
500 {
501 struct tlv tlv;
502 uint16_t tlv_len;
503 int total = 0;
504
505 *tlvs_rcvd = 0;
506 memset(addr, 0, sizeof(*addr));
507 *conf_number = 0;
508 *trans_pref = 0;
509
510 /*
511 * RFC 7552 - Section 6.1:
512 * "An LSR SHOULD accept the Hello message that contains both IPv4 and
513 * IPv6 Transport Address optional objects but MUST use only the
514 * transport address whose address family is the same as that of the
515 * IP packet carrying the Hello message. An LSR SHOULD accept only
516 * the first Transport Address optional object for a given address
517 * family in the received Hello message and ignore the rest if the
518 * LSR receives more than one Transport Address optional object for a
519 * given address family".
520 */
521 while (len >= sizeof(tlv)) {
522 memcpy(&tlv, buf, TLV_HDR_SIZE);
523 tlv_len = ntohs(tlv.length);
524 if (tlv_len + TLV_HDR_SIZE > len)
525 return (-1);
526 buf += TLV_HDR_SIZE;
527 len -= TLV_HDR_SIZE;
528 total += TLV_HDR_SIZE;
529
530 switch (ntohs(tlv.type)) {
531 case TLV_TYPE_IPV4TRANSADDR:
532 if (tlv_len != sizeof(addr->v4))
533 return (-1);
534 if (af != AF_INET)
535 return (-1);
536 if (*tlvs_rcvd & F_HELLO_TLV_RCVD_ADDR)
537 break;
538 memcpy(&addr->v4, buf, sizeof(addr->v4));
539 *tlvs_rcvd |= F_HELLO_TLV_RCVD_ADDR;
540 break;
541 case TLV_TYPE_IPV6TRANSADDR:
542 if (tlv_len != sizeof(addr->v6))
543 return (-1);
544 if (af != AF_INET6)
545 return (-1);
546 if (*tlvs_rcvd & F_HELLO_TLV_RCVD_ADDR)
547 break;
548 memcpy(&addr->v6, buf, sizeof(addr->v6));
549 *tlvs_rcvd |= F_HELLO_TLV_RCVD_ADDR;
550 break;
551 case TLV_TYPE_CONFIG:
552 if (tlv_len != sizeof(uint32_t))
553 return (-1);
554 memcpy(conf_number, buf, sizeof(uint32_t));
555 *tlvs_rcvd |= F_HELLO_TLV_RCVD_CONF;
556 break;
557 case TLV_TYPE_DUALSTACK:
558 if (tlv_len != sizeof(uint32_t))
559 return (-1);
560 /*
561 * RFC 7552 - Section 6.1:
562 * "A Single-stack LSR does not need to use the
563 * Dual-Stack capability in Hello messages and SHOULD
564 * ignore this capability if received".
565 */
566 if (!ldp_is_dual_stack(leconf))
567 break;
568 /* Shame on you, Cisco! */
569 if (leconf->flags & F_LDPD_DS_CISCO_INTEROP) {
570 memcpy(trans_pref, buf + sizeof(uint16_t),
571 sizeof(uint16_t));
572 *trans_pref = ntohs(*trans_pref);
573 } else {
574 memcpy(trans_pref, buf , sizeof(uint16_t));
575 *trans_pref = ntohs(*trans_pref) >> 12;
576 }
577 *tlvs_rcvd |= F_HELLO_TLV_RCVD_DS;
578 break;
579 default:
580 /* if unknown flag set, ignore TLV */
581 if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
582 return (-1);
583 break;
584 }
585 buf += tlv_len;
586 len -= tlv_len;
587 total += tlv_len;
588 }
589
590 return (total);
591 }