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