1 /* $OpenBSD: packet.c,v 1.35 2014/07/12 19:22:32 krw Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> 5 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@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 <sys/socket.h> 22 #include <sys/uio.h> 23 24 #include <netinet/in.h> 25 #include <netinet/in_systm.h> 26 #include <netinet/ip.h> 27 #include <arpa/inet.h> 28 #include <net/if_dl.h> 29 #include <fcntl.h> 30 #include <unistd.h> 31 32 #include <errno.h> 33 #include <event.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "ldpd.h" 38 #include "ldp.h" 39 #include "log.h" 40 #include "ldpe.h" 41 42 extern struct ldpd_conf *leconf; 43 44 struct iface *disc_find_iface(unsigned int, struct in_addr); 45 ssize_t session_get_pdu(struct ibuf_read *, char **); 46 47 static int msgcnt = 0; 48 49 int 50 gen_ldp_hdr(struct ibuf *buf, u_int16_t size) 51 { 52 struct ldp_hdr ldp_hdr; 53 54 bzero(&ldp_hdr, sizeof(ldp_hdr)); 55 ldp_hdr.version = htons(LDP_VERSION); 56 57 /* We want just the size of the value */ 58 size -= TLV_HDR_LEN; 59 60 ldp_hdr.length = htons(size); 61 ldp_hdr.lsr_id = ldpe_router_id(); 62 ldp_hdr.lspace_id = 0; 63 64 return (ibuf_add(buf, &ldp_hdr, LDP_HDR_SIZE)); 65 } 66 67 int 68 gen_msg_tlv(struct ibuf *buf, u_int32_t type, u_int16_t size) 69 { 70 struct ldp_msg msg; 71 72 /* We want just the size of the value */ 73 size -= TLV_HDR_LEN; 74 75 bzero(&msg, sizeof(msg)); 76 msg.type = htons(type); 77 msg.length = htons(size); 78 if (type != MSG_TYPE_HELLO) 79 msg.msgid = htonl(++msgcnt); 80 81 return (ibuf_add(buf, &msg, sizeof(msg))); 82 } 83 84 /* send packets */ 85 int 86 send_packet(int fd, struct iface *iface, void *pkt, size_t len, 87 struct sockaddr_in *dst) 88 { 89 /* set outgoing interface for multicast traffic */ 90 if (iface && IN_MULTICAST(ntohl(dst->sin_addr.s_addr))) 91 if (if_set_mcast(iface) == -1) { 92 log_warn("send_packet: error setting multicast " 93 "interface, %s", iface->name); 94 return (-1); 95 } 96 97 if (sendto(fd, pkt, len, 0, (struct sockaddr *)dst, 98 sizeof(*dst)) == -1) { 99 log_warn("send_packet: error sending packet"); 100 return (-1); 101 } 102 103 return (0); 104 } 105 106 /* Discovery functions */ 107 void 108 disc_recv_packet(int fd, short event, void *bula) 109 { 110 union { 111 struct cmsghdr hdr; 112 char buf[CMSG_SPACE(sizeof(struct sockaddr_dl))]; 113 } cmsgbuf; 114 struct sockaddr_in src; 115 struct msghdr msg; 116 struct iovec iov; 117 struct ldp_hdr ldp_hdr; 118 struct ldp_msg ldp_msg; 119 struct iface *iface = NULL; 120 char *buf; 121 struct cmsghdr *cmsg; 122 ssize_t r; 123 u_int16_t len; 124 unsigned int ifindex = 0; 125 126 if (event != EV_READ) 127 return; 128 129 /* setup buffer */ 130 bzero(&msg, sizeof(msg)); 131 iov.iov_base = buf = pkt_ptr; 132 iov.iov_len = IBUF_READ_SIZE; 133 msg.msg_name = &src; 134 msg.msg_namelen = sizeof(src); 135 msg.msg_iov = &iov; 136 msg.msg_iovlen = 1; 137 msg.msg_control = &cmsgbuf.buf; 138 msg.msg_controllen = sizeof(cmsgbuf.buf); 139 140 if ((r = recvmsg(fd, &msg, 0)) == -1) { 141 if (errno != EAGAIN && errno != EINTR) 142 log_debug("disc_recv_packet: read error: %s", 143 strerror(errno)); 144 return; 145 } 146 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 147 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 148 if (cmsg->cmsg_level == IPPROTO_IP && 149 cmsg->cmsg_type == IP_RECVIF) { 150 ifindex = ((struct sockaddr_dl *) 151 CMSG_DATA(cmsg))->sdl_index; 152 break; 153 } 154 } 155 156 len = (u_int16_t)r; 157 158 /* find a matching interface */ 159 if ((fd == leconf->ldp_discovery_socket) && 160 (iface = disc_find_iface(ifindex, src.sin_addr)) == NULL) { 161 log_debug("disc_recv_packet: cannot find a matching interface"); 162 return; 163 } 164 165 /* LDP header sanity checks */ 166 if (len < LDP_HDR_SIZE || len > LDP_MAX_LEN) { 167 log_debug("disc_recv_packet: bad packet size"); 168 return; 169 } 170 bcopy(buf, &ldp_hdr, sizeof(ldp_hdr)); 171 172 if (ntohs(ldp_hdr.version) != LDP_VERSION) { 173 log_debug("dsc_recv_packet: invalid LDP version %d", 174 ldp_hdr.version); 175 return; 176 } 177 178 if (ntohs(ldp_hdr.length) > 179 len - sizeof(ldp_hdr.version) - sizeof(ldp_hdr.length)) { 180 log_debug("disc_recv_packet: invalid LDP packet length %u", 181 ntohs(ldp_hdr.length)); 182 return; 183 } 184 185 if (len < LDP_HDR_SIZE + LDP_MSG_LEN) { 186 log_debug("disc_recv_packet: invalid LDP packet length %d", 187 ntohs(ldp_hdr.length)); 188 return; 189 } 190 191 bcopy(buf + LDP_HDR_SIZE, &ldp_msg, sizeof(ldp_msg)); 192 193 /* switch LDP packet type */ 194 switch (ntohs(ldp_msg.type)) { 195 case MSG_TYPE_HELLO: 196 recv_hello(iface, src.sin_addr, buf, len); 197 break; 198 default: 199 log_debug("recv_packet: unknown LDP packet type, source %s", 200 inet_ntoa(src.sin_addr)); 201 } 202 } 203 204 struct iface * 205 disc_find_iface(unsigned int ifindex, struct in_addr src) 206 { 207 struct iface *iface; 208 struct if_addr *if_addr; 209 210 LIST_FOREACH(iface, &leconf->iface_list, entry) 211 LIST_FOREACH(if_addr, &iface->addr_list, iface_entry) 212 switch (iface->type) { 213 case IF_TYPE_POINTOPOINT: 214 if (ifindex == iface->ifindex && 215 if_addr->dstbrd.s_addr == src.s_addr) 216 return (iface); 217 break; 218 default: 219 if (ifindex == iface->ifindex && 220 (if_addr->addr.s_addr & 221 if_addr->mask.s_addr) == 222 (src.s_addr & if_addr->mask.s_addr)) 223 return (iface); 224 break; 225 } 226 227 return (NULL); 228 } 229 230 struct tcp_conn * 231 tcp_new(int fd, struct nbr *nbr) 232 { 233 struct tcp_conn *tcp; 234 235 if ((tcp = calloc(1, sizeof(*tcp))) == NULL) 236 fatal("tcp_new"); 237 if ((tcp->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL) 238 fatal("tcp_new"); 239 240 if (nbr) 241 tcp->nbr = nbr; 242 243 tcp->fd = fd; 244 evbuf_init(&tcp->wbuf, tcp->fd, session_write, tcp); 245 event_set(&tcp->rev, tcp->fd, EV_READ | EV_PERSIST, session_read, tcp); 246 event_add(&tcp->rev, NULL); 247 248 return (tcp); 249 } 250 251 void 252 tcp_close(struct tcp_conn *tcp) 253 { 254 evbuf_clear(&tcp->wbuf); 255 event_del(&tcp->rev); 256 close(tcp->fd); 257 free(tcp->rbuf); 258 free(tcp); 259 } 260 261 void 262 session_accept(int fd, short event, void *bula) 263 { 264 struct sockaddr_in src; 265 int newfd; 266 socklen_t len = sizeof(src); 267 268 if (!(event & EV_READ)) 269 return; 270 271 newfd = accept(fd, (struct sockaddr *)&src, &len); 272 if (newfd == -1) { 273 /* 274 * Pause accept if we are out of file descriptors, or 275 * libevent will haunt us here too. 276 */ 277 if (errno == ENFILE || errno == EMFILE) { 278 accept_pause(); 279 } else if (errno != EWOULDBLOCK && errno != EINTR && 280 errno != ECONNABORTED) 281 log_debug("sess_recv_packet: accept error: %s", 282 strerror(errno)); 283 return; 284 } 285 286 session_socket_blockmode(newfd, BM_NONBLOCK); 287 288 tcp_new(newfd, NULL); 289 } 290 291 void 292 session_read(int fd, short event, void *arg) 293 { 294 struct tcp_conn *tcp = arg; 295 struct nbr *nbr = tcp->nbr; 296 struct ldp_hdr *ldp_hdr; 297 struct ldp_msg *ldp_msg; 298 char *buf, *pdu; 299 ssize_t n, len; 300 int msg_size; 301 u_int16_t pdu_len; 302 303 if (event != EV_READ) { 304 log_debug("session_read: spurious event"); 305 return; 306 } 307 308 if ((n = read(fd, tcp->rbuf->buf + tcp->rbuf->wpos, 309 sizeof(tcp->rbuf->buf) - tcp->rbuf->wpos)) == -1) { 310 if (errno != EINTR && errno != EAGAIN) { 311 log_warn("session_read: read error"); 312 if (nbr) 313 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 314 else 315 tcp_close(tcp); 316 return; 317 } 318 /* retry read */ 319 return; 320 } 321 if (n == 0) { 322 /* connection closed */ 323 log_debug("session_read: connection closed by remote end"); 324 if (nbr) 325 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 326 else 327 tcp_close(tcp); 328 return; 329 } 330 tcp->rbuf->wpos += n; 331 332 while ((len = session_get_pdu(tcp->rbuf, &buf)) > 0) { 333 pdu = buf; 334 ldp_hdr = (struct ldp_hdr *)pdu; 335 if (ntohs(ldp_hdr->version) != LDP_VERSION) { 336 if (nbr) 337 session_shutdown(nbr, S_BAD_PROTO_VER, 0, 0); 338 else { 339 send_notification(S_BAD_PROTO_VER, tcp, 0, 0); 340 msgbuf_write(&tcp->wbuf.wbuf); 341 tcp_close(tcp); 342 } 343 free(buf); 344 return; 345 } 346 347 pdu_len = ntohs(ldp_hdr->length); 348 if (pdu_len < (LDP_HDR_PDU_LEN + LDP_MSG_LEN) || 349 pdu_len > LDP_MAX_LEN) { 350 if (nbr) 351 session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0); 352 else { 353 send_notification(S_BAD_PDU_LEN, tcp, 0, 0); 354 msgbuf_write(&tcp->wbuf.wbuf); 355 tcp_close(tcp); 356 } 357 free(buf); 358 return; 359 } 360 361 if (nbr) { 362 if (ldp_hdr->lsr_id != nbr->id.s_addr || 363 ldp_hdr->lspace_id != 0) { 364 session_shutdown(nbr, S_BAD_LDP_ID, 0, 0); 365 free(buf); 366 return; 367 } 368 } else { 369 nbr = nbr_find_ldpid(ldp_hdr->lsr_id); 370 if (!nbr) { 371 send_notification(S_NO_HELLO, tcp, 0, 0); 372 msgbuf_write(&tcp->wbuf.wbuf); 373 tcp_close(tcp); 374 free(buf); 375 return; 376 } 377 /* handle duplicate SYNs */ 378 if (nbr->tcp) { 379 tcp_close(tcp); 380 free(buf); 381 return; 382 } 383 384 nbr->tcp = tcp; 385 tcp->nbr = nbr; 386 nbr_fsm(nbr, NBR_EVT_MATCH_ADJ); 387 } 388 389 pdu += LDP_HDR_SIZE; 390 len -= LDP_HDR_SIZE; 391 392 if (nbr->state == NBR_STA_OPER) 393 nbr_fsm(nbr, NBR_EVT_PDU_RCVD); 394 395 while (len >= LDP_MSG_LEN) { 396 u_int16_t type; 397 398 ldp_msg = (struct ldp_msg *)pdu; 399 type = ntohs(ldp_msg->type); 400 401 pdu_len = ntohs(ldp_msg->length) + TLV_HDR_LEN; 402 if (pdu_len > len || 403 pdu_len < LDP_MSG_LEN - TLV_HDR_LEN) { 404 session_shutdown(nbr, S_BAD_TLV_LEN, 405 ldp_msg->msgid, ldp_msg->type); 406 free(buf); 407 return; 408 } 409 410 /* check for error conditions earlier */ 411 switch (type) { 412 case MSG_TYPE_INIT: 413 if ((nbr->state != NBR_STA_INITIAL) && 414 (nbr->state != NBR_STA_OPENSENT)) { 415 session_shutdown(nbr, S_SHUTDOWN, 416 ldp_msg->msgid, ldp_msg->type); 417 free(buf); 418 return; 419 } 420 break; 421 case MSG_TYPE_KEEPALIVE: 422 if ((nbr->state == NBR_STA_INITIAL) || 423 (nbr->state == NBR_STA_OPENSENT)) { 424 session_shutdown(nbr, S_SHUTDOWN, 425 ldp_msg->msgid, ldp_msg->type); 426 free(buf); 427 return; 428 } 429 break; 430 case MSG_TYPE_NOTIFICATION: 431 case MSG_TYPE_ADDR: 432 case MSG_TYPE_ADDRWITHDRAW: 433 case MSG_TYPE_LABELMAPPING: 434 case MSG_TYPE_LABELREQUEST: 435 case MSG_TYPE_LABELWITHDRAW: 436 case MSG_TYPE_LABELRELEASE: 437 case MSG_TYPE_LABELABORTREQ: 438 default: 439 if (nbr->state != NBR_STA_OPER) { 440 session_shutdown(nbr, S_SHUTDOWN, 441 ldp_msg->msgid, ldp_msg->type); 442 free(buf); 443 return; 444 } 445 break; 446 } 447 448 /* switch LDP packet type */ 449 switch (type) { 450 case MSG_TYPE_NOTIFICATION: 451 msg_size = recv_notification(nbr, pdu, pdu_len); 452 break; 453 case MSG_TYPE_INIT: 454 msg_size = recv_init(nbr, pdu, pdu_len); 455 break; 456 case MSG_TYPE_KEEPALIVE: 457 msg_size = recv_keepalive(nbr, pdu, pdu_len); 458 break; 459 case MSG_TYPE_ADDR: 460 case MSG_TYPE_ADDRWITHDRAW: 461 msg_size = recv_address(nbr, pdu, pdu_len); 462 break; 463 case MSG_TYPE_LABELMAPPING: 464 case MSG_TYPE_LABELREQUEST: 465 case MSG_TYPE_LABELWITHDRAW: 466 case MSG_TYPE_LABELRELEASE: 467 case MSG_TYPE_LABELABORTREQ: 468 msg_size = recv_labelmessage(nbr, pdu, 469 pdu_len, type); 470 break; 471 default: 472 log_debug("session_read: unknown LDP packet " 473 "from nbr %s", inet_ntoa(nbr->id)); 474 if (!(ntohs(ldp_msg->type) & UNKNOWN_FLAG)) { 475 session_shutdown(nbr, S_UNKNOWN_MSG, 476 ldp_msg->msgid, ldp_msg->type); 477 free(buf); 478 return; 479 } 480 /* unknown flag is set, ignore the message */ 481 msg_size = ntohs(ldp_msg->length); 482 break; 483 } 484 485 if (msg_size == -1) { 486 /* parser failed, giving up */ 487 free(buf); 488 return; 489 } 490 491 /* Analyse the next message */ 492 pdu += msg_size + TLV_HDR_LEN; 493 len -= msg_size + TLV_HDR_LEN; 494 } 495 free(buf); 496 if (len != 0) { 497 session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0); 498 return; 499 } 500 } 501 } 502 503 void 504 session_write(int fd, short event, void *arg) 505 { 506 struct tcp_conn *tcp = arg; 507 struct nbr *nbr = tcp->nbr; 508 509 if (event & EV_WRITE) { 510 if (msgbuf_write(&tcp->wbuf.wbuf) <= 0 && errno != EAGAIN) { 511 if (nbr) 512 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 513 } 514 } else 515 log_debug("session_write: spurious event"); 516 517 evbuf_event_add(&tcp->wbuf); 518 } 519 520 void 521 session_shutdown(struct nbr *nbr, u_int32_t status, u_int32_t msgid, 522 u_int32_t type) 523 { 524 log_debug("session_shutdown: nbr ID %s", inet_ntoa(nbr->id)); 525 526 send_notification_nbr(nbr, status, msgid, type); 527 528 /* try to flush write buffer, if it fails tough shit */ 529 msgbuf_write(&nbr->tcp->wbuf.wbuf); 530 531 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); 532 } 533 534 void 535 session_close(struct nbr *nbr) 536 { 537 log_debug("session_close: closing session with nbr ID %s", 538 inet_ntoa(nbr->id)); 539 540 tcp_close(nbr->tcp); 541 nbr->tcp = NULL; 542 543 nbr_stop_ktimer(nbr); 544 nbr_stop_ktimeout(nbr); 545 546 accept_unpause(); 547 } 548 549 ssize_t 550 session_get_pdu(struct ibuf_read *r, char **b) 551 { 552 struct ldp_hdr l; 553 size_t av, dlen, left; 554 555 av = r->wpos; 556 if (av < sizeof(l)) 557 return (0); 558 559 memcpy(&l, r->buf, sizeof(l)); 560 dlen = ntohs(l.length) + TLV_HDR_LEN; 561 if (dlen > av) 562 return (0); 563 564 if ((*b = malloc(dlen)) == NULL) 565 return (-1); 566 567 memcpy(*b, r->buf, dlen); 568 if (dlen < av) { 569 left = av - dlen; 570 memmove(r->buf, r->buf + dlen, left); 571 r->wpos = left; 572 } else 573 r->wpos = 0; 574 575 return (dlen); 576 } 577