]> git.proxmox.com Git - mirror_frr.git/blob - ldpd/packet.c
71eeb1adb61c00d51c62312462295d5ab033ec75
[mirror_frr.git] / ldpd / packet.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 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
8 */
9
10 #include <zebra.h>
11
12 #include "ldpd.h"
13 #include "ldpe.h"
14 #include "log.h"
15
16 #include "sockopt.h"
17
18 static struct iface *disc_find_iface(unsigned int, int,
19 union ldpd_addr *);
20 static void session_read(struct event *thread);
21 static void session_write(struct event *thread);
22 static ssize_t session_get_pdu(struct ibuf_read *, char **);
23 static void tcp_close(struct tcp_conn *);
24 static struct pending_conn *pending_conn_new(int, int, union ldpd_addr *);
25 static void pending_conn_timeout(struct event *thread);
26
27 int
28 gen_ldp_hdr(struct ibuf *buf, uint16_t size)
29 {
30 struct ldp_hdr ldp_hdr;
31
32 memset(&ldp_hdr, 0, sizeof(ldp_hdr));
33 ldp_hdr.version = htons(LDP_VERSION);
34 /* exclude the 'Version' and 'PDU Length' fields from the total */
35 ldp_hdr.length = htons(size - LDP_HDR_DEAD_LEN);
36 ldp_hdr.lsr_id = ldp_rtr_id_get(leconf);
37 ldp_hdr.lspace_id = 0;
38
39 return (ibuf_add(buf, &ldp_hdr, LDP_HDR_SIZE));
40 }
41
42 int
43 gen_msg_hdr(struct ibuf *buf, uint16_t type, uint16_t size)
44 {
45 static int msgcnt = 0;
46 struct ldp_msg msg;
47
48 memset(&msg, 0, sizeof(msg));
49 msg.type = htons(type);
50 /* exclude the 'Type' and 'Length' fields from the total */
51 msg.length = htons(size - LDP_MSG_DEAD_LEN);
52 msg.id = htonl(++msgcnt);
53
54 return (ibuf_add(buf, &msg, sizeof(msg)));
55 }
56
57 /* send packets */
58 int
59 send_packet(int fd, int af, union ldpd_addr *dst, struct iface_af *ia,
60 void *pkt, size_t len)
61 {
62 union sockunion su;
63
64 switch (af) {
65 case AF_INET:
66 if (ia && IN_MULTICAST(ntohl(dst->v4.s_addr))) {
67 /* set outgoing interface for multicast traffic */
68 if (sock_set_ipv4_mcast(ia->iface) == -1) {
69 log_debug("%s: error setting multicast interface, %s", __func__, ia->iface->name);
70 return (-1);
71 }
72 }
73 break;
74 case AF_INET6:
75 if (ia && IN6_IS_ADDR_MULTICAST(&dst->v6)) {
76 /* set outgoing interface for multicast traffic */
77 if (sock_set_ipv6_mcast(ia->iface) == -1) {
78 log_debug("%s: error setting multicast interface, %s", __func__, ia->iface->name);
79 return (-1);
80 }
81 }
82 break;
83 default:
84 fatalx("send_packet: unknown af");
85 }
86
87 addr2sa(af, dst, LDP_PORT, &su);
88 if (sendto(fd, pkt, len, 0, &su.sa, sockaddr_len(&su.sa)) == -1) {
89 log_warn("%s: error sending packet to %s", __func__,
90 log_sockaddr(&su.sa));
91 return (-1);
92 }
93
94 return (0);
95 }
96
97 /* Discovery functions */
98 void disc_recv_packet(struct event *thread)
99 {
100 int fd = EVENT_FD(thread);
101 struct event **threadp = EVENT_ARG(thread);
102
103 union {
104 struct cmsghdr hdr;
105 #ifdef HAVE_STRUCT_SOCKADDR_DL
106 char buf[CMSG_SPACE(sizeof(struct sockaddr_dl))];
107 #else
108 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
109 #endif
110 } cmsgbuf;
111 struct msghdr m;
112 struct sockaddr_storage from;
113 struct iovec iov;
114 char *buf;
115 #ifndef MSG_MCAST
116 struct cmsghdr *cmsg;
117 #endif
118 ssize_t r;
119 int multicast;
120 int af;
121 union ldpd_addr src;
122 unsigned int ifindex = 0;
123 struct iface *iface = NULL;
124 uint16_t len;
125 struct ldp_hdr ldp_hdr;
126 uint16_t pdu_len;
127 struct ldp_msg msg;
128 uint16_t msg_len;
129 struct in_addr lsr_id;
130
131 /* reschedule read */
132 event_add_read(master, disc_recv_packet, threadp, fd, threadp);
133
134 /* setup buffer */
135 memset(&m, 0, sizeof(m));
136 iov.iov_base = buf = pkt_ptr;
137 iov.iov_len = IBUF_READ_SIZE;
138 m.msg_name = &from;
139 m.msg_namelen = sizeof(from);
140 m.msg_iov = &iov;
141 m.msg_iovlen = 1;
142 m.msg_control = &cmsgbuf.buf;
143 m.msg_controllen = sizeof(cmsgbuf.buf);
144
145 if ((r = recvmsg(fd, &m, 0)) == -1) {
146 if (errno != EAGAIN && errno != EINTR)
147 log_debug("%s: read error: %s", __func__,
148 strerror(errno));
149 return;
150 }
151
152 sa2addr((struct sockaddr *)&from, &af, &src, NULL);
153 #ifdef MSG_MCAST
154 multicast = (m.msg_flags & MSG_MCAST) ? 1 : 0;
155 #else
156 multicast = 0;
157 for (cmsg = CMSG_FIRSTHDR(&m); cmsg != NULL;
158 cmsg = CMSG_NXTHDR(&m, cmsg)) {
159 #if defined(HAVE_IP_PKTINFO)
160 if (af == AF_INET && cmsg->cmsg_level == IPPROTO_IP &&
161 cmsg->cmsg_type == IP_PKTINFO) {
162 struct in_pktinfo *pktinfo;
163
164 pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
165 if (IN_MULTICAST(ntohl(pktinfo->ipi_addr.s_addr)))
166 multicast = 1;
167 break;
168 }
169 #elif defined(HAVE_IP_RECVDSTADDR)
170 if (af == AF_INET && cmsg->cmsg_level == IPPROTO_IP &&
171 cmsg->cmsg_type == IP_RECVDSTADDR) {
172 struct in_addr *addr;
173
174 addr = (struct in_addr *)CMSG_DATA(cmsg);
175 if (IN_MULTICAST(ntohl(addr->s_addr)))
176 multicast = 1;
177 break;
178 }
179 #else
180 #error "Unsupported socket API"
181 #endif
182 if (af == AF_INET6 && cmsg->cmsg_level == IPPROTO_IPV6 &&
183 cmsg->cmsg_type == IPV6_PKTINFO) {
184 struct in6_pktinfo *pktinfo;
185
186 pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
187 if (IN6_IS_ADDR_MULTICAST(&pktinfo->ipi6_addr))
188 multicast = 1;
189 break;
190 }
191 }
192 #endif /* MSG_MCAST */
193 if (bad_addr(af, &src)) {
194 log_debug("%s: invalid source address: %s", __func__,
195 log_addr(af, &src));
196 return;
197 }
198 ifindex = getsockopt_ifindex(af, &m);
199
200 /* find a matching interface */
201 if (multicast) {
202 iface = disc_find_iface(ifindex, af, &src);
203 if (iface == NULL)
204 return;
205 }
206
207 /* check packet size */
208 len = (uint16_t)r;
209 if (len < (LDP_HDR_SIZE + LDP_MSG_SIZE) || len > LDP_MAX_LEN) {
210 log_debug("%s: bad packet size, source %s", __func__,
211 log_addr(af, &src));
212 return;
213 }
214
215 /* LDP header sanity checks */
216 memcpy(&ldp_hdr, buf, sizeof(ldp_hdr));
217 if (ntohs(ldp_hdr.version) != LDP_VERSION) {
218 log_debug("%s: invalid LDP version %d, source %s", __func__,
219 ntohs(ldp_hdr.version), log_addr(af, &src));
220 return;
221 }
222 if (ntohs(ldp_hdr.lspace_id) != 0) {
223 log_debug("%s: invalid label space %u, source %s", __func__,
224 ntohs(ldp_hdr.lspace_id), log_addr(af, &src));
225 return;
226 }
227 /* check "PDU Length" field */
228 pdu_len = ntohs(ldp_hdr.length);
229 if ((pdu_len < (LDP_HDR_PDU_LEN + LDP_MSG_SIZE)) ||
230 (pdu_len > (len - LDP_HDR_DEAD_LEN))) {
231 log_debug("%s: invalid LDP packet length %u, source %s",
232 __func__, ntohs(ldp_hdr.length), log_addr(af, &src));
233 return;
234 }
235 buf += LDP_HDR_SIZE;
236 len -= LDP_HDR_SIZE;
237
238 lsr_id.s_addr = ldp_hdr.lsr_id;
239
240 /*
241 * For UDP, we process only the first message of each packet. This does
242 * not impose any restrictions since LDP uses UDP only for sending Hello
243 * packets.
244 */
245 memcpy(&msg, buf, sizeof(msg));
246
247 /* check "Message Length" field */
248 msg_len = ntohs(msg.length);
249 if (msg_len < LDP_MSG_LEN || ((msg_len + LDP_MSG_DEAD_LEN) > pdu_len)) {
250 log_debug("%s: invalid LDP message length %u, source %s",
251 __func__, ntohs(msg.length), log_addr(af, &src));
252 return;
253 }
254 buf += LDP_MSG_SIZE;
255 len -= LDP_MSG_SIZE;
256
257 /* switch LDP packet type */
258 switch (ntohs(msg.type)) {
259 case MSG_TYPE_HELLO:
260 recv_hello(lsr_id, &msg, af, &src, iface, multicast, buf, len);
261 break;
262 default:
263 log_debug("%s: unknown LDP packet type, source %s", __func__,
264 log_addr(af, &src));
265 }
266 }
267
268 static struct iface *
269 disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src)
270 {
271 struct iface *iface;
272 struct iface_af *ia;
273
274 iface = if_lookup(leconf, ifindex);
275 if (iface == NULL)
276 return (NULL);
277
278 ia = iface_af_get(iface, af);
279 if (!ia->enabled)
280 return (NULL);
281
282 /*
283 * RFC 7552 - Section 5.1:
284 * "Link-local IPv6 address MUST be used as the source IP address in
285 * IPv6 LDP Link Hellos".
286 */
287 if (af == AF_INET6 && !IN6_IS_ADDR_LINKLOCAL(&src->v6))
288 return (NULL);
289
290 return (iface);
291 }
292
293 void session_accept(struct event *thread)
294 {
295 int fd = EVENT_FD(thread);
296 struct sockaddr_storage src;
297 socklen_t len = sizeof(src);
298 int newfd;
299 int af;
300 union ldpd_addr addr;
301 struct nbr *nbr;
302 struct pending_conn *pconn;
303
304 newfd = accept(fd, (struct sockaddr *)&src, &len);
305 if (newfd == -1) {
306 /*
307 * Pause accept if we are out of file descriptors, or
308 * libevent will haunt us here too.
309 */
310 if (errno == ENFILE || errno == EMFILE) {
311 accept_pause();
312 } else if (errno != EWOULDBLOCK && errno != EINTR &&
313 errno != ECONNABORTED)
314 log_debug("%s: accept error: %s", __func__,
315 strerror(errno));
316 return;
317 }
318 sock_set_nonblock(newfd);
319
320 sa2addr((struct sockaddr *)&src, &af, &addr, NULL);
321
322 /*
323 * Since we don't support label spaces, we can identify this neighbor
324 * just by its source address. This way we don't need to wait for its
325 * Initialization message to know who we are talking to.
326 */
327 nbr = nbr_find_addr(af, &addr);
328 if (nbr == NULL) {
329 /*
330 * According to RFC 5036, we would need to send a No Hello
331 * Error Notification message and close this TCP connection
332 * right now. But doing so would trigger the backoff exponential
333 * timer in the remote peer, which would considerably slow down
334 * the session establishment process. The trick here is to wait
335 * five seconds before sending the Notification Message. There's
336 * a good chance that the remote peer will send us a Hello
337 * message within this interval, so it's worth waiting before
338 * taking a more drastic measure.
339 */
340 pconn = pending_conn_find(af, &addr);
341 if (pconn)
342 close(newfd);
343 else
344 pending_conn_new(newfd, af, &addr);
345 return;
346 }
347 /* protection against buggy implementations */
348 if (nbr_session_active_role(nbr)) {
349 close(newfd);
350 return;
351 }
352 if (nbr->state != NBR_STA_PRESENT) {
353 log_debug("%s: lsr-id %pI4: rejecting additional transport connection", __func__, &nbr->id);
354 close(newfd);
355 return;
356 }
357
358 session_accept_nbr(nbr, newfd);
359 }
360
361 void
362 session_accept_nbr(struct nbr *nbr, int fd)
363 {
364 #ifdef __OpenBSD__
365 struct nbr_params *nbrp;
366 int opt;
367 socklen_t len;
368
369 nbrp = nbr_params_find(leconf, nbr->id);
370 if (nbr_gtsm_check(fd, nbr, nbrp)) {
371 close(fd);
372 return;
373 }
374
375 if (nbrp && nbrp->auth.method == AUTH_MD5SIG) {
376 if (sysdep.no_pfkey || sysdep.no_md5sig) {
377 log_warnx("md5sig configured but not available");
378 close(fd);
379 return;
380 }
381
382 len = sizeof(opt);
383 if (getsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, &opt, &len) == -1)
384 fatal("getsockopt TCP_MD5SIG");
385 if (!opt) { /* non-md5'd connection! */
386 log_warnx("connection attempt without md5 signature");
387 close(fd);
388 return;
389 }
390 }
391 #endif
392
393 nbr->tcp = tcp_new(fd, nbr);
394 nbr_fsm(nbr, NBR_EVT_MATCH_ADJ);
395 }
396
397 static void session_read(struct event *thread)
398 {
399 int fd = EVENT_FD(thread);
400 struct nbr *nbr = EVENT_ARG(thread);
401 struct tcp_conn *tcp = nbr->tcp;
402 struct ldp_hdr *ldp_hdr;
403 struct ldp_msg *msg;
404 char *buf = NULL, *pdu;
405 ssize_t n, len;
406 uint16_t pdu_len, msg_len, msg_size, max_pdu_len;
407 int ret;
408
409 event_add_read(master, session_read, nbr, fd, &tcp->rev);
410
411 if ((n = read(fd, tcp->rbuf->buf + tcp->rbuf->wpos,
412 sizeof(tcp->rbuf->buf) - tcp->rbuf->wpos)) == -1) {
413 if (errno != EINTR && errno != EAGAIN) {
414 log_warn("%s: read error", __func__);
415 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
416 return;
417 }
418 /* retry read */
419 return;
420 }
421 if (n == 0) {
422 /* connection closed */
423 log_debug("%s: connection closed by remote end", __func__);
424 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
425 return;
426 }
427 tcp->rbuf->wpos += n;
428
429 while ((len = session_get_pdu(tcp->rbuf, &buf)) > 0) {
430 pdu = buf;
431 ldp_hdr = (struct ldp_hdr *)pdu;
432 if (ntohs(ldp_hdr->version) != LDP_VERSION) {
433 session_shutdown(nbr, S_BAD_PROTO_VER, 0, 0);
434 free(buf);
435 return;
436 }
437
438 pdu_len = ntohs(ldp_hdr->length);
439 /*
440 * RFC 5036 - Section 3.5.3:
441 * "Prior to completion of the negotiation, the maximum
442 * allowable length is 4096 bytes".
443 */
444 if (nbr->state == NBR_STA_OPER)
445 max_pdu_len = nbr->max_pdu_len;
446 else
447 max_pdu_len = LDP_MAX_LEN;
448 if (pdu_len < (LDP_HDR_PDU_LEN + LDP_MSG_SIZE) ||
449 pdu_len > max_pdu_len) {
450 session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0);
451 free(buf);
452 return;
453 }
454 pdu_len -= LDP_HDR_PDU_LEN;
455 if (ldp_hdr->lsr_id != nbr->id.s_addr ||
456 ldp_hdr->lspace_id != 0) {
457 session_shutdown(nbr, S_BAD_LDP_ID, 0, 0);
458 free(buf);
459 return;
460 }
461 pdu += LDP_HDR_SIZE;
462 len -= LDP_HDR_SIZE;
463
464 nbr_fsm(nbr, NBR_EVT_PDU_RCVD);
465
466 while (len >= LDP_MSG_SIZE) {
467 uint16_t type;
468
469 msg = (struct ldp_msg *)pdu;
470 type = ntohs(msg->type);
471 msg_len = ntohs(msg->length);
472 if (msg_len < LDP_MSG_LEN ||
473 (msg_len + LDP_MSG_DEAD_LEN) > pdu_len) {
474 session_shutdown(nbr, S_BAD_MSG_LEN, msg->id,
475 msg->type);
476 free(buf);
477 return;
478 }
479 msg_size = msg_len + LDP_MSG_DEAD_LEN;
480 pdu_len -= msg_size;
481
482 /* check for error conditions earlier */
483 switch (type) {
484 case MSG_TYPE_INIT:
485 if ((nbr->state != NBR_STA_INITIAL) &&
486 (nbr->state != NBR_STA_OPENSENT)) {
487 session_shutdown(nbr, S_SHUTDOWN,
488 msg->id, msg->type);
489 free(buf);
490 return;
491 }
492 break;
493 case MSG_TYPE_KEEPALIVE:
494 if ((nbr->state == NBR_STA_INITIAL) ||
495 (nbr->state == NBR_STA_OPENSENT)) {
496 session_shutdown(nbr, S_SHUTDOWN,
497 msg->id, msg->type);
498 free(buf);
499 return;
500 }
501 break;
502 case MSG_TYPE_NOTIFICATION:
503 break;
504 default:
505 if (nbr->state != NBR_STA_OPER) {
506 session_shutdown(nbr, S_SHUTDOWN,
507 msg->id, msg->type);
508 free(buf);
509 return;
510 }
511 break;
512 }
513
514 /* switch LDP packet type */
515 switch (type) {
516 case MSG_TYPE_NOTIFICATION:
517 ret = recv_notification(nbr, pdu, msg_size);
518 break;
519 case MSG_TYPE_INIT:
520 ret = recv_init(nbr, pdu, msg_size);
521 break;
522 case MSG_TYPE_KEEPALIVE:
523 ret = recv_keepalive(nbr, pdu, msg_size);
524 break;
525 case MSG_TYPE_CAPABILITY:
526 ret = recv_capability(nbr, pdu, msg_size);
527 break;
528 case MSG_TYPE_ADDR:
529 case MSG_TYPE_ADDRWITHDRAW:
530 ret = recv_address(nbr, pdu, msg_size);
531 break;
532 case MSG_TYPE_LABELMAPPING:
533 case MSG_TYPE_LABELREQUEST:
534 case MSG_TYPE_LABELWITHDRAW:
535 case MSG_TYPE_LABELRELEASE:
536 case MSG_TYPE_LABELABORTREQ:
537 ret = recv_labelmessage(nbr, pdu, msg_size,
538 type);
539 break;
540 default:
541 log_debug("%s: unknown LDP message from nbr %pI4",
542 __func__, &nbr->id);
543 if (!(ntohs(msg->type) & UNKNOWN_FLAG)) {
544 nbr->stats.unknown_msg++;
545 send_notification(nbr->tcp,
546 S_UNKNOWN_MSG, msg->id, msg->type);
547 }
548 /* ignore the message */
549 ret = 0;
550 break;
551 }
552
553 if (ret == -1) {
554 /* parser failed, giving up */
555 free(buf);
556 return;
557 }
558
559 /* no errors - update per neighbor message counters */
560 switch (type) {
561 case MSG_TYPE_NOTIFICATION:
562 nbr->stats.notif_rcvd++;
563 break;
564 case MSG_TYPE_KEEPALIVE:
565 nbr->stats.kalive_rcvd++;
566 break;
567 case MSG_TYPE_CAPABILITY:
568 nbr->stats.capability_rcvd++;
569 break;
570 case MSG_TYPE_ADDR:
571 nbr->stats.addr_rcvd++;
572 break;
573 case MSG_TYPE_ADDRWITHDRAW:
574 nbr->stats.addrwdraw_rcvd++;
575 break;
576 case MSG_TYPE_LABELMAPPING:
577 nbr->stats.labelmap_rcvd++;
578 break;
579 case MSG_TYPE_LABELREQUEST:
580 nbr->stats.labelreq_rcvd++;
581 break;
582 case MSG_TYPE_LABELWITHDRAW:
583 nbr->stats.labelwdraw_rcvd++;
584 break;
585 case MSG_TYPE_LABELRELEASE:
586 nbr->stats.labelrel_rcvd++;
587 break;
588 case MSG_TYPE_LABELABORTREQ:
589 nbr->stats.labelabreq_rcvd++;
590 break;
591 default:
592 break;
593 }
594
595 /* Analyse the next message */
596 pdu += msg_size;
597 len -= msg_size;
598 }
599 free(buf);
600 buf = NULL;
601 if (len != 0) {
602 session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0);
603 return;
604 }
605 }
606
607 /* shouldn't happen, session_get_pdu should be > 0 if buf was
608 * allocated - but let's get rid of the SA warning.
609 */
610 free(buf);
611 }
612
613 static void session_write(struct event *thread)
614 {
615 struct tcp_conn *tcp = EVENT_ARG(thread);
616 struct nbr *nbr = tcp->nbr;
617
618 tcp->wbuf.ev = NULL;
619
620 if (msgbuf_write(&tcp->wbuf.wbuf) <= 0)
621 if (errno != EAGAIN && nbr)
622 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
623
624 if (nbr == NULL && !tcp->wbuf.wbuf.queued) {
625 /*
626 * We are done sending the notification message, now we can
627 * close the socket.
628 */
629 tcp_close(tcp);
630 return;
631 }
632
633 evbuf_event_add(&tcp->wbuf);
634 }
635
636 void
637 session_shutdown(struct nbr *nbr, uint32_t status, uint32_t msg_id,
638 uint32_t msg_type)
639 {
640 switch (nbr->state) {
641 case NBR_STA_PRESENT:
642 if (nbr_pending_connect(nbr))
643 EVENT_OFF(nbr->ev_connect);
644 break;
645 case NBR_STA_INITIAL:
646 case NBR_STA_OPENREC:
647 case NBR_STA_OPENSENT:
648 /* update SNMP session counters during initialization */
649 leconf->stats.session_attempts++;
650 send_notification(nbr->tcp, status, msg_id, msg_type);
651
652 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
653 break;
654 case NBR_STA_OPER:
655 send_notification(nbr->tcp, status, msg_id, msg_type);
656
657 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
658 break;
659 default:
660 fatalx("session_shutdown: unknown neighbor state");
661 }
662 }
663
664 void
665 session_close(struct nbr *nbr)
666 {
667 log_debug("%s: closing session with lsr-id %pI4", __func__,
668 &nbr->id);
669
670 ldp_sync_fsm_nbr_event(nbr, LDP_SYNC_EVT_SESSION_CLOSE);
671
672 tcp_close(nbr->tcp);
673 nbr_stop_ktimer(nbr);
674 nbr_stop_ktimeout(nbr);
675 nbr_stop_itimeout(nbr);
676 }
677
678 static ssize_t
679 session_get_pdu(struct ibuf_read *r, char **b)
680 {
681 struct ldp_hdr l;
682 size_t av, dlen, left;
683
684 av = r->wpos;
685 if (av < sizeof(l))
686 return (0);
687
688 memcpy(&l, r->buf, sizeof(l));
689 dlen = ntohs(l.length) + LDP_HDR_DEAD_LEN;
690 if (dlen > av)
691 return (0);
692
693 if ((*b = malloc(dlen)) == NULL)
694 return (-1);
695
696 memcpy(*b, r->buf, dlen);
697 if (dlen < av) {
698 left = av - dlen;
699 memmove(r->buf, r->buf + dlen, left);
700 r->wpos = left;
701 } else
702 r->wpos = 0;
703
704 return (dlen);
705 }
706
707 struct tcp_conn *
708 tcp_new(int fd, struct nbr *nbr)
709 {
710 struct tcp_conn *tcp;
711 struct sockaddr_storage ss;
712 socklen_t len = sizeof(ss);
713
714 if ((tcp = calloc(1, sizeof(*tcp))) == NULL)
715 fatal(__func__);
716
717 tcp->fd = fd;
718 evbuf_init(&tcp->wbuf, tcp->fd, session_write, tcp);
719
720 if (nbr) {
721 if ((tcp->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL)
722 fatal(__func__);
723
724 event_add_read(master, session_read, nbr, tcp->fd, &tcp->rev);
725 tcp->nbr = nbr;
726 }
727
728 if (getsockname(fd, (struct sockaddr *)&ss, &len) != 0)
729 log_warn("%s: getsockname", __func__);
730 else
731 sa2addr((struct sockaddr *)&ss, NULL, NULL, &tcp->lport);
732 if (getpeername(fd, (struct sockaddr *)&ss, &len) != 0)
733 log_warn("%s: getpeername", __func__);
734 else
735 sa2addr((struct sockaddr *)&ss, NULL, NULL, &tcp->rport);
736
737 return (tcp);
738 }
739
740 static void
741 tcp_close(struct tcp_conn *tcp)
742 {
743 /* try to flush write buffer */
744 msgbuf_write(&tcp->wbuf.wbuf);
745 evbuf_clear(&tcp->wbuf);
746
747 if (tcp->nbr) {
748 EVENT_OFF(tcp->rev);
749 free(tcp->rbuf);
750 tcp->nbr->tcp = NULL;
751 }
752
753 close(tcp->fd);
754 accept_unpause();
755 free(tcp);
756 }
757
758 static struct pending_conn *
759 pending_conn_new(int fd, int af, union ldpd_addr *addr)
760 {
761 struct pending_conn *pconn;
762
763 if ((pconn = calloc(1, sizeof(*pconn))) == NULL)
764 fatal(__func__);
765
766 pconn->fd = fd;
767 pconn->af = af;
768 pconn->addr = *addr;
769 TAILQ_INSERT_TAIL(&global.pending_conns, pconn, entry);
770 pconn->ev_timeout = NULL;
771 event_add_timer(master, pending_conn_timeout, pconn,
772 PENDING_CONN_TIMEOUT, &pconn->ev_timeout);
773
774 return (pconn);
775 }
776
777 void
778 pending_conn_del(struct pending_conn *pconn)
779 {
780 EVENT_OFF(pconn->ev_timeout);
781 TAILQ_REMOVE(&global.pending_conns, pconn, entry);
782 free(pconn);
783 }
784
785 struct pending_conn *
786 pending_conn_find(int af, union ldpd_addr *addr)
787 {
788 struct pending_conn *pconn;
789
790 TAILQ_FOREACH(pconn, &global.pending_conns, entry)
791 if (af == pconn->af &&
792 ldp_addrcmp(af, addr, &pconn->addr) == 0)
793 return (pconn);
794
795 return (NULL);
796 }
797
798 static void pending_conn_timeout(struct event *thread)
799 {
800 struct pending_conn *pconn = EVENT_ARG(thread);
801 struct tcp_conn *tcp;
802
803 pconn->ev_timeout = NULL;
804
805 log_debug("%s: no adjacency with remote end: %s", __func__,
806 log_addr(pconn->af, &pconn->addr));
807
808 /*
809 * Create a write buffer detached from any neighbor to send a
810 * notification message reliably.
811 */
812 tcp = tcp_new(pconn->fd, NULL);
813 send_notification(tcp, S_NO_HELLO, 0, 0);
814 msgbuf_write(&tcp->wbuf.wbuf);
815
816 pending_conn_del(pconn);
817 }