1 /* 2 * Copyright (c) 2018 3 * Hartmut Brandt. 4 * All rights reserved. 5 * 6 * Author: Harti Brandt <harti@freebsd.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Begemot: bsnmp/snmpd/trans_udp.c,v 1.5 2005/10/04 08:46:56 brandt_h Exp $ 30 * 31 * Internet transport 32 */ 33 34 #include <sys/param.h> 35 #include <sys/socket.h> 36 #include <sys/types.h> 37 38 #include <assert.h> 39 #include <errno.h> 40 #include <netdb.h> 41 #include <stdbool.h> 42 #include <stddef.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <syslog.h> 46 #include <unistd.h> 47 48 #include <stdio.h> 49 50 #include <arpa/inet.h> 51 52 #include "asn1.h" 53 #include "snmp.h" 54 #include "snmpmod.h" 55 56 #include "snmpd.h" 57 58 #define SNMPTREE_TYPES 59 #define SNMPENUM_FUNCS 60 #include "tree.h" 61 #include "oid.h" 62 63 extern const struct transport_def inet_trans; 64 65 struct inet_port; 66 struct inet_port_params; 67 struct port_sock; 68 69 typedef int create_func(struct inet_port *, struct inet_port_params *); 70 typedef void input_func(int, void *); 71 typedef int activate_func(struct inet_port *); 72 typedef void deactivate_func(struct inet_port *); 73 typedef void parse_ctrl_func(struct port_sock *, const struct msghdr *); 74 typedef void setsrc_func(struct port_sock *, struct msghdr *, char *); 75 76 static create_func ipv4_create; 77 static input_func ipv4_input; 78 static activate_func ipv4_activate; 79 static deactivate_func ipv4_deactivate; 80 static parse_ctrl_func ipv4_parse_ctrl; 81 static setsrc_func ipv4_setsrc; 82 83 static create_func ipv6_create; 84 static input_func ipv6_input; 85 static activate_func ipv6_activate; 86 static deactivate_func ipv6_deactivate; 87 static parse_ctrl_func ipv6_parse_ctrl; 88 static setsrc_func ipv6_setsrc; 89 90 static create_func ipv6z_create; 91 92 static create_func dns_create; 93 static activate_func dns_activate; 94 static deactivate_func dns_deactivate; 95 96 struct port_sock { 97 /* common input stuff; must be first */ 98 struct port_input input; 99 100 /** link field */ 101 TAILQ_ENTRY(port_sock) link; 102 103 /** pointer to parent */ 104 struct inet_port *port; 105 106 /** bind address */ 107 struct sockaddr_storage bind_addr; 108 109 /** reply destination */ 110 struct sockaddr_storage ret_dest; 111 112 /** need to set source address in reply; set for INADDR_ANY */ 113 bool set_ret_source; 114 115 /** address of the receive interface */ 116 union { 117 /** IPv4 case */ 118 struct in_addr a4; 119 120 /** IPv6 case */ 121 struct in6_pktinfo a6; 122 } ret_source; 123 124 /** parse control message */ 125 parse_ctrl_func *parse_ctrl; 126 127 /** set source address for a send() */ 128 setsrc_func *setsrc; 129 }; 130 static_assert(offsetof(struct port_sock, input) == 0, 131 "input not first in port_sock"); 132 133 /** 134 * Table row for the inet ports. 135 * 136 * When actived each row can have one or several open sockets. For ipv6, 137 * ipv4 and ipv6z addresses it is always one, for dns addresses more than 138 * one socket can be open. 139 */ 140 struct inet_port { 141 /** common i/o port stuff (must be first) */ 142 struct tport tport; 143 144 /** transport protocol */ 145 enum BegemotSnmpdTransportProto proto; 146 147 /** row status */ 148 enum RowStatus row_status; 149 150 /** socket list */ 151 TAILQ_HEAD(, port_sock) socks; 152 153 /** value for InetAddressType::dns */ 154 char *dns_addr; 155 156 /** port number in dns case; network byte order */ 157 uint16_t dns_port; 158 159 /** create a port */ 160 create_func *create; 161 162 /** activate a port */ 163 activate_func *activate; 164 165 /** deactivate port */ 166 deactivate_func *deactivate; 167 }; 168 static_assert(offsetof(struct inet_port, tport) == 0, 169 "tport not first in inet_port"); 170 171 /** to be used in bind_addr field */ 172 #define AF_DNS AF_VENDOR00 173 174 /** registered transport */ 175 static struct transport *my_trans; 176 177 /** set operation */ 178 enum { 179 SET_CREATED, 180 SET_ACTIVATED, 181 SET_DEACTIVATE, 182 SET_DESTROY, 183 }; 184 185 /** length of the control data buffer */ 186 static const size_t RECV_CBUF_SIZE = 187 MAX(CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + 188 CMSG_SPACE(sizeof(struct in_addr)), 189 CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + 190 CMSG_SPACE(sizeof(struct in6_pktinfo))); 191 192 /** length of the control data buffer */ 193 static const size_t XMIT_CBUF_SIZE = 194 MAX(CMSG_SPACE(sizeof(struct in_addr)), 195 CMSG_SPACE(sizeof(struct in6_pktinfo))); 196 197 /** 198 * Start the transport. This registers the transport with the 199 * transport table. 200 * 201 * \return SNMP error code 202 */ 203 static int 204 inet_start(void) 205 { 206 return (trans_register(&inet_trans, &my_trans)); 207 } 208 209 /** 210 * Stop the transport. This tries to unregister the transport which 211 * in turn fails if the list of ports is not empty. 212 * 213 * \return SNMP error code 214 */ 215 static int 216 inet_stop(int force __unused) 217 { 218 if (my_trans != NULL) 219 if (trans_unregister(my_trans) != 0) 220 return (SNMP_ERR_GENERR); 221 return (SNMP_ERR_NOERROR); 222 } 223 224 /** 225 * Deactivate SNMP port. 226 * 227 * \param tp port to close 228 */ 229 static void 230 deactivate_port(struct inet_port *p) 231 { 232 p->deactivate(p); 233 } 234 235 /* 236 * This function activates a port. For ports opened via the config files 237 * this is called just before entering the event loop. For ports create 238 * during runtime this is called when the RowStatus is set to Active or 239 * as second step for CreateAndGo. 240 * 241 * \param tp transport port 242 * 243 * \return SNMP error code 244 */ 245 static int 246 inet_activate(struct tport *tp) 247 { 248 struct inet_port *port = (struct inet_port *)tp; 249 250 return (port->activate(port)); 251 } 252 253 /* 254 * Close the SNMP port if it is open and destroy it. 255 * 256 * \param tp port to close 257 */ 258 static void 259 inet_destroy_port(struct tport *tp) 260 { 261 struct inet_port *port = (struct inet_port *)tp; 262 263 deactivate_port(port); 264 265 trans_remove_port(tp); 266 267 free(port->dns_addr); 268 free(port); 269 } 270 271 /** 272 * If the input struct has no buffer allocated yet, do it now. If allocation 273 * fails, read the data into a local buffer and drop it. 274 * 275 * \param pi input struct 276 * 277 * \return -1 if allocation fails, 0 otherwise 278 */ 279 static int 280 inet_alloc_buf(struct port_input *pi) 281 { 282 char drop_buf[2000]; 283 284 if (pi->buf == NULL) { 285 if ((pi->buf = buf_alloc(0)) == NULL) { 286 (void)recvfrom(pi->fd, drop_buf, sizeof(drop_buf), 287 0, NULL, NULL); 288 return (-1); 289 } 290 pi->buflen = buf_size(0); 291 } 292 return (0); 293 } 294 295 /** 296 * Read message into input buffer. Get also the source address and any 297 * control data that is available. If the message is truncated, increment 298 * corresponding statistics. 299 * 300 * \param pi input object 301 * \param msg message object to fill 302 * \param cbuf control data buffer 303 * 304 * \return -1 when something goes wrong, 0 othersise 305 */ 306 static int 307 inet_read_msg(struct port_input *pi, struct msghdr *msg, char *cbuf) 308 { 309 struct iovec iov[1]; 310 311 iov[0].iov_base = pi->buf; 312 iov[0].iov_len = pi->buflen; 313 314 msg->msg_name = pi->peer; 315 msg->msg_namelen = pi->peerlen; 316 msg->msg_iov = iov; 317 msg->msg_iovlen = 1; 318 msg->msg_control = cbuf; 319 msg->msg_controllen = RECV_CBUF_SIZE; 320 msg->msg_flags = 0; 321 322 memset(cbuf, 0, RECV_CBUF_SIZE); 323 324 const ssize_t len = recvmsg(pi->fd, msg, 0); 325 326 if (len == -1 || len == 0) 327 /* receive error */ 328 return (-1); 329 330 if (msg->msg_flags & MSG_TRUNC) { 331 /* truncated - drop */ 332 snmpd_stats.silentDrops++; 333 snmpd_stats.inTooLong++; 334 return (-1); 335 } 336 337 pi->length = (size_t)len; 338 339 return (0); 340 } 341 342 /* 343 * Input available on socket. 344 * 345 * \param tp transport port 346 * \param pi input struct 347 * 348 * \return number of bytes received 349 */ 350 static ssize_t 351 inet_recv(struct tport *tp, struct port_input *pi) 352 { 353 struct inet_port *port = __containerof(tp, struct inet_port, tport); 354 struct port_sock *sock = __containerof(pi, struct port_sock, input); 355 356 assert(port->proto == BegemotSnmpdTransportProto_udp); 357 358 if (inet_alloc_buf(pi) == -1) 359 return (-1); 360 361 char cbuf[RECV_CBUF_SIZE]; 362 struct msghdr msg; 363 364 if (inet_read_msg(pi, &msg, cbuf) == -1) 365 return (-1); 366 367 sock->parse_ctrl(sock, &msg); 368 369 return (0); 370 } 371 372 /* 373 * Send message. 374 * 375 * \param tp port 376 * \param buf data to send 377 * \param len number of bytes to send 378 * \param pi destination 379 * 380 * \return number of bytes sent 381 */ 382 static ssize_t 383 inet_send(struct tport *tp, const u_char *buf, size_t len, 384 struct port_input *pi) 385 { 386 struct inet_port *p = __containerof(tp, struct inet_port, tport); 387 struct port_sock *s = (pi->fd == -1) ? TAILQ_FIRST(&p->socks) : 388 __containerof(pi, struct port_sock, input); 389 390 struct iovec iov; 391 392 iov.iov_base = __DECONST(void*, buf); 393 iov.iov_len = len; 394 395 struct msghdr msg; 396 397 msg.msg_flags = 0; 398 msg.msg_iov = &iov; 399 msg.msg_iovlen = 1; 400 msg.msg_name = (void *)pi->peer; 401 msg.msg_namelen = pi->peerlen; 402 403 char cbuf[XMIT_CBUF_SIZE]; 404 if (s->set_ret_source) { 405 s->setsrc(s, &msg, cbuf); 406 } else { 407 msg.msg_control = NULL; 408 msg.msg_controllen = 0; 409 } 410 411 return (sendmsg(s->input.fd, &msg, 0)); 412 } 413 414 /** exported to daemon */ 415 const struct transport_def inet_trans = { 416 .name = "inet", 417 .id = OIDX_begemotSnmpdTransInet, 418 .start = inet_start, 419 .stop = inet_stop, 420 .close_port = inet_destroy_port, 421 .init_port = inet_activate, 422 .recv = inet_recv, 423 .send = inet_send, 424 }; 425 426 struct inet_port_params { 427 /** index oid */ 428 struct asn_oid index; 429 430 /** internet address type */ 431 enum InetAddressType type; 432 433 /** internet address */ 434 u_char *addr; 435 436 /** length of address */ 437 size_t addr_len; 438 439 /** port number */ 440 uint32_t port; 441 442 /** protocol */ 443 enum BegemotSnmpdTransportProto proto; 444 }; 445 446 /** 447 * IPv4 creation stuff. Parse the index, fill socket address and creates 448 * a port_sock. 449 * 450 * \param port the port to create 451 * \param params parameters from the SNMP SET 452 * 453 * \return SNMP error 454 */ 455 static int 456 ipv4_create(struct inet_port *port, struct inet_port_params *params) 457 { 458 459 if (params->addr_len != 4) 460 return (SNMP_ERR_INCONS_VALUE); 461 462 struct port_sock *sock = calloc(1, sizeof(struct port_sock)); 463 if (sock == NULL) 464 return (SNMP_ERR_GENERR); 465 466 snmpd_input_init(&sock->input); 467 468 TAILQ_INSERT_HEAD(&port->socks, sock, link); 469 470 struct sockaddr_in *sin = 471 (struct sockaddr_in *)&sock->bind_addr; 472 473 sin->sin_len = sizeof(struct sockaddr_in); 474 sin->sin_family = AF_INET; 475 sin->sin_port = htons(params->port); 476 memcpy(&sin->sin_addr, params->addr, 4); /* network byte order */ 477 478 sock->port = port; 479 480 return (SNMP_ERR_NOERROR); 481 } 482 483 /* 484 * An IPv4 inet port is ready. Delegate to the generic code to read the data 485 * and react. 486 * 487 * \param fd file descriptor that is ready 488 * \param udata inet_port pointer 489 */ 490 static void 491 ipv4_input(int fd __unused, void *udata) 492 { 493 struct port_sock *sock = udata; 494 495 sock->input.peerlen = sizeof(struct sockaddr_in); 496 snmpd_input(&sock->input, &sock->port->tport); 497 } 498 499 /** 500 * Activate an IPv4 socket. 501 * 502 * \param sock thhe socket to activate 503 * 504 * \return error code 505 */ 506 static int 507 ipv4_activate_sock(struct port_sock *sock) 508 { 509 if ((sock->input.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { 510 syslog(LOG_ERR, "creating UDP4 socket: %m"); 511 return (SNMP_ERR_RES_UNAVAIL); 512 } 513 514 const struct sockaddr_in *sin = 515 (const struct sockaddr_in *)&sock->bind_addr; 516 517 if (sin->sin_addr.s_addr == INADDR_ANY) { 518 /* need to know from which address to return */ 519 static const int on = 1; 520 521 if (setsockopt(sock->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on, 522 sizeof(on)) == -1) { 523 syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m"); 524 (void)close(sock->input.fd); 525 sock->input.fd = -1; 526 return (SNMP_ERR_GENERR); 527 } 528 sock->set_ret_source = true; 529 } 530 531 if (bind(sock->input.fd, (const struct sockaddr *)sin, sizeof(*sin))) { 532 if (errno == EADDRNOTAVAIL) { 533 (void)close(sock->input.fd); 534 sock->input.fd = -1; 535 return (SNMP_ERR_INCONS_NAME); 536 } 537 syslog(LOG_ERR, "bind: %s:%u %m", inet_ntoa(sin->sin_addr), 538 ntohs(sin->sin_port)); 539 (void)close(sock->input.fd); 540 sock->input.fd = -1; 541 return (SNMP_ERR_GENERR); 542 } 543 544 if ((sock->input.id = fd_select(sock->input.fd, ipv4_input, 545 sock, NULL)) == NULL) { 546 (void)close(sock->input.fd); 547 sock->input.fd = -1; 548 return (SNMP_ERR_GENERR); 549 } 550 sock->input.peer = (struct sockaddr *)&sock->ret_dest; 551 552 sock->parse_ctrl = ipv4_parse_ctrl; 553 sock->setsrc = ipv4_setsrc; 554 555 return (SNMP_ERR_NOERROR); 556 } 557 558 /** 559 * Open an IPv4 socket. Make the socket, bind it and put it on the select 560 * list. The socket struct has already been created during creation. 561 * 562 * \param p inet port 563 * 564 * \return SNMP error code 565 */ 566 static int 567 ipv4_activate(struct inet_port *p) 568 { 569 struct port_sock *sock = TAILQ_FIRST(&p->socks); 570 assert(sock); 571 assert(!TAILQ_NEXT(sock, link)); 572 573 const int ret = ipv4_activate_sock(sock); 574 if (ret == SNMP_ERR_NOERROR) 575 p->row_status = RowStatus_active; 576 577 return (ret); 578 } 579 580 /** 581 * Close an IPv4 socket. Keep the sock object. 582 * 583 * \param p inet port 584 */ 585 static void 586 ipv4_deactivate(struct inet_port *p) 587 { 588 struct port_sock *sock = TAILQ_FIRST(&p->socks); 589 assert(sock); 590 assert(!TAILQ_NEXT(sock, link)); 591 592 snmpd_input_close(&sock->input); 593 594 p->row_status = RowStatus_notInService; 595 } 596 597 /** 598 * Parse the control data received with a UDPv4 packet. This may contain 599 * credentials (for a local connection) and the address of the interface 600 * the message was received on. If there are credentials set the priv flag 601 * if the effective UID is zero. 602 * 603 * \param sock the sock object 604 * \param msg the received message 605 */ 606 static void 607 ipv4_parse_ctrl(struct port_sock *sock, const struct msghdr *msg) 608 { 609 struct sockcred *cred = NULL; 610 611 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 612 cmsg = CMSG_NXTHDR(msg, cmsg)) { 613 614 if (cmsg->cmsg_level == IPPROTO_IP && 615 cmsg->cmsg_type == IP_RECVDSTADDR) { 616 memcpy(&sock->ret_source.a4, CMSG_DATA(cmsg), 617 sizeof(struct in_addr)); 618 619 } else if (cmsg->cmsg_level == SOL_SOCKET && 620 cmsg->cmsg_type == SCM_CREDS) { 621 cred = (struct sockcred *)(void *)CMSG_DATA(cmsg); 622 } 623 } 624 625 sock->input.priv = 0; 626 if (sock->input.cred && cred) 627 /* remote end has sent credentials */ 628 sock->input.priv = (cred->sc_euid == 0); 629 } 630 631 /** 632 * Set the source address option for IPv4 sockets. 633 * 634 * \param sock socket object 635 * \param msg message 636 */ 637 static void 638 ipv4_setsrc(struct port_sock *sock, struct msghdr *msg, char *cbuf) 639 { 640 struct cmsghdr *cmsg; 641 642 msg->msg_control = cbuf; 643 msg->msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); 644 645 /* select outgoing interface by setting source address */ 646 cmsg = CMSG_FIRSTHDR(msg); 647 cmsg->cmsg_level = IPPROTO_IP; 648 cmsg->cmsg_type = IP_SENDSRCADDR; 649 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); 650 memcpy(CMSG_DATA(cmsg), &sock->ret_source.a4, 651 sizeof(struct in_addr)); 652 } 653 654 /** 655 * Common part of IPv6 creation. This is used by both ipv6_create() and 656 * ipv6z_create(). 657 * 658 * \param port the table row 659 * \param params creation parameters 660 * \param scope_id scope_id (0 or from index) 661 * 662 * \return SNMP_ERR_NOERROR if port has been created, error code otherwise 663 */ 664 static int 665 ipv6_create_common(struct inet_port *port, struct inet_port_params *params, 666 u_int scope_id) 667 { 668 struct port_sock *sock = calloc(1, sizeof(struct port_sock)); 669 670 if (sock == NULL) 671 return (SNMP_ERR_GENERR); 672 673 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&sock->bind_addr; 674 675 sin->sin6_len = sizeof(struct sockaddr_in6); 676 sin->sin6_family = AF_INET6; 677 sin->sin6_port = htons(params->port); 678 sin->sin6_flowinfo = 0; 679 sin->sin6_scope_id = scope_id; 680 681 memcpy(sin->sin6_addr.s6_addr, params->addr, 16); 682 683 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && scope_id == 0) { 684 char buf[INET6_ADDRSTRLEN]; 685 syslog(LOG_INFO, "%s: link local address used without scope " 686 "index: %s", __func__, inet_ntop(AF_INET6, 687 &sin->sin6_addr, buf, sizeof(buf))); 688 free(sock); 689 return (SNMP_ERR_NO_CREATION); 690 } 691 692 sock->port = port; 693 694 snmpd_input_init(&sock->input); 695 TAILQ_INSERT_HEAD(&port->socks, sock, link); 696 697 return (SNMP_ERR_NOERROR); 698 } 699 700 /** 701 * IPv6 creation stuff. Parse the index, fill socket address and creates 702 * a port_sock. 703 * 704 * \param port the port to create 705 * \param params parameters from the SNMP SET 706 * 707 * \return SNMP error 708 */ 709 static int 710 ipv6_create(struct inet_port *port, struct inet_port_params *params) 711 { 712 if (params->addr_len != 16) 713 return (SNMP_ERR_INCONS_VALUE); 714 715 const int ret = ipv6_create_common(port, params, 0); 716 if (ret != SNMP_ERR_NOERROR) 717 return (ret); 718 719 return (SNMP_ERR_NOERROR); 720 } 721 722 /* 723 * An IPv6 inet port is ready. Delegate to the generic code to read the data 724 * and react. 725 * 726 * \param fd file descriptor that is ready 727 * \param udata inet_port pointer 728 */ 729 static void 730 ipv6_input(int fd __unused, void *udata) 731 { 732 struct port_sock *sock = udata; 733 734 sock->input.peerlen = sizeof(struct sockaddr_in6); 735 snmpd_input(&sock->input, &sock->port->tport); 736 } 737 738 /** 739 * Activate an IPv6 socket. 740 * 741 * \param sock thhe socket to activate 742 * 743 * \return error code 744 */ 745 static int 746 ipv6_activate_sock(struct port_sock *sock) 747 { 748 if ((sock->input.fd = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) { 749 syslog(LOG_ERR, "creating UDP6 socket: %m"); 750 return (SNMP_ERR_RES_UNAVAIL); 751 } 752 753 const struct sockaddr_in6 *sin = 754 (const struct sockaddr_in6 *)&sock->bind_addr; 755 756 if (memcmp(&sin->sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) { 757 /* need to know from which address to return */ 758 static const int on = 1; 759 760 if (setsockopt(sock->input.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, 761 &on, sizeof(on)) == -1) { 762 syslog(LOG_ERR, "setsockopt(IP6_PKTINFO): %m"); 763 (void)close(sock->input.fd); 764 sock->input.fd = -1; 765 return (SNMP_ERR_GENERR); 766 } 767 sock->set_ret_source = true; 768 } 769 770 if (bind(sock->input.fd, (const struct sockaddr *)sin, sizeof(*sin))) { 771 if (community != COMM_INITIALIZE && errno == EADDRNOTAVAIL) { 772 (void)close(sock->input.fd); 773 sock->input.fd = -1; 774 return (SNMP_ERR_INCONS_NAME); 775 } 776 char buf[INET6_ADDRSTRLEN]; 777 syslog(LOG_ERR, "bind: %s:%u:%u %m", inet_ntop(AF_INET6, 778 &sin->sin6_addr, buf, sizeof(buf)), sin->sin6_scope_id, 779 ntohs(sin->sin6_port)); 780 (void)close(sock->input.fd); 781 sock->input.fd = -1; 782 return (SNMP_ERR_GENERR); 783 } 784 if ((sock->input.id = fd_select(sock->input.fd, ipv6_input, 785 sock, NULL)) == NULL) { 786 (void)close(sock->input.fd); 787 sock->input.fd = -1; 788 return (SNMP_ERR_GENERR); 789 } 790 sock->input.peer = (struct sockaddr *)&sock->ret_dest; 791 792 sock->parse_ctrl = ipv6_parse_ctrl; 793 sock->setsrc = ipv6_setsrc; 794 795 return (SNMP_ERR_NOERROR); 796 } 797 798 /** 799 * Open an IPv6 socket. 800 * 801 * \param port inet port 802 * 803 * \return SNMP error code 804 */ 805 static int 806 ipv6_activate(struct inet_port *p) 807 { 808 struct port_sock *sock = TAILQ_FIRST(&p->socks); 809 assert(sock); 810 811 const int ret = ipv6_activate_sock(sock); 812 813 if (ret == SNMP_ERR_NOERROR) 814 p->row_status = RowStatus_active; 815 return (ret); 816 } 817 818 /** 819 * Close an IPv6 socket. Keep the sock object. 820 * 821 * \param p inet port 822 */ 823 static void 824 ipv6_deactivate(struct inet_port *p) 825 { 826 struct port_sock *sock = TAILQ_FIRST(&p->socks); 827 assert(sock); 828 assert(!TAILQ_NEXT(sock, link)); 829 830 snmpd_input_close(&sock->input); 831 832 p->row_status = RowStatus_notInService; 833 } 834 835 /** 836 * IPv6 specific part of message processing. The control data may contain 837 * credentials and packet info that contains the destination address of 838 * the packet. 839 * 840 * \param sock the sock object 841 * \param msg the received message 842 */ 843 static void 844 ipv6_parse_ctrl(struct port_sock *sock, const struct msghdr *msg) 845 { 846 struct sockcred *cred = NULL; 847 848 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 849 cmsg = CMSG_NXTHDR(msg, cmsg)) { 850 851 if (cmsg->cmsg_level == IPPROTO_IPV6 && 852 cmsg->cmsg_type == IPV6_PKTINFO) { 853 const struct in6_pktinfo *info = 854 (const struct in6_pktinfo *)(const void *) 855 CMSG_DATA(cmsg); 856 sock->ret_source.a6.ipi6_addr = info->ipi6_addr; 857 sock->ret_source.a6.ipi6_ifindex = 858 !IN6_IS_ADDR_LINKLOCAL(&info->ipi6_addr) ? 0: 859 info->ipi6_ifindex; 860 861 } else if (cmsg->cmsg_level == SOL_SOCKET && 862 cmsg->cmsg_type == SCM_CREDS) { 863 cred = (struct sockcred *)(void *)CMSG_DATA(cmsg); 864 } 865 } 866 867 sock->input.priv = 0; 868 if (sock->input.cred && cred) 869 /* remote end has sent credentials */ 870 sock->input.priv = (cred->sc_euid == 0); 871 } 872 873 /** 874 * Set the source address option for IPv4 sockets. 875 * 876 * \param sock socket object 877 * \param msg message 878 */ 879 static void 880 ipv6_setsrc(struct port_sock *sock, struct msghdr *msg, char *cbuf) 881 { 882 struct cmsghdr *cmsg; 883 884 msg->msg_control = cbuf; 885 msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 886 887 /* select outgoing interface by setting source address */ 888 cmsg = CMSG_FIRSTHDR(msg); 889 cmsg->cmsg_level = IPPROTO_IPV6; 890 cmsg->cmsg_type = IPV6_PKTINFO; 891 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 892 memcpy(CMSG_DATA(cmsg), &sock->ret_source.a6, 893 sizeof(struct in6_pktinfo)); 894 } 895 896 /** 897 * IPv6z creation stuff. Parse the index, fill socket address and creates 898 * a port_sock. 899 * 900 * \param port the port to create 901 * \param params parameters from the SNMP SET 902 * 903 * \return SNMP error 904 */ 905 static int 906 ipv6z_create(struct inet_port *port, struct inet_port_params *params) 907 { 908 if (params->addr_len != 20) 909 return (SNMP_ERR_INCONS_VALUE); 910 911 u_int scope_id = 0; 912 for (u_int i = 16; i < 20; i++) { 913 scope_id <<= 8; 914 scope_id |= params->addr[i]; 915 } 916 917 const int ret = ipv6_create_common(port, params, scope_id); 918 if (ret != SNMP_ERR_NOERROR) 919 return (ret); 920 921 return (SNMP_ERR_NOERROR); 922 } 923 924 /** 925 * DNS name creation stuff. Parse the index and save the string. 926 * This does not create a socket struct. 927 * 928 * \param port the port to create 929 * \param params parameters from the SNMP SET 930 * 931 * \return SNMP error 932 */ 933 static int 934 dns_create(struct inet_port *port, struct inet_port_params *params) 935 { 936 if (params->addr_len > 64) 937 return (SNMP_ERR_INCONS_VALUE); 938 939 if (strnlen(params->addr, params->addr_len) != 940 params->addr_len) 941 return (SNMP_ERR_INCONS_VALUE); 942 943 if ((port->dns_addr = realloc(params->addr, 944 params->addr_len + 1)) == NULL) 945 return (SNMP_ERR_GENERR); 946 947 port->dns_addr[params->addr_len] = '\0'; 948 params->addr = NULL; 949 950 port->dns_port = htons(params->port); 951 952 return (SNMP_ERR_NOERROR); 953 } 954 955 /** 956 * Open sockets. This loops through all the addresses returned by getaddrinfo 957 * and opens a socket for each of them. 958 * 959 * \param port inet port 960 * 961 * \return SNMP error code 962 */ 963 static int 964 dns_activate(struct inet_port *port) 965 { 966 struct addrinfo hints; 967 memset(&hints, 0, sizeof(hints)); 968 hints.ai_family = AF_UNSPEC; 969 hints.ai_socktype = SOCK_DGRAM; // XXX udp-only 970 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_NUMERICSERV; 971 972 char portbuf[8]; 973 sprintf(portbuf, "%hu", ntohs(port->dns_port)); 974 975 struct addrinfo *res0; 976 int error = getaddrinfo(port->dns_addr[0] == '\0' 977 ? NULL : port->dns_addr, 978 portbuf, &hints, &res0); 979 980 if (error) { 981 syslog(LOG_ERR, "cannot resolve address '%s': %s", 982 port->dns_addr, gai_strerror(error)); 983 return (SNMP_ERR_GENERR); 984 } 985 986 for (struct addrinfo *res = res0; res != NULL; res = res->ai_next) { 987 if (res->ai_family != AF_INET && res->ai_family != AF_INET6) 988 continue; 989 990 struct port_sock *sock = calloc(1, sizeof(struct port_sock)); 991 if (sock == NULL) 992 return (SNMP_ERR_GENERR); 993 994 snmpd_input_init(&sock->input); 995 sock->port = port; 996 997 int ret = SNMP_ERR_NOERROR; 998 999 if (res->ai_family == AF_INET) { 1000 *(struct sockaddr_in *)&sock->bind_addr = 1001 *(struct sockaddr_in *)(void *)res->ai_addr; 1002 ret = ipv4_activate_sock(sock); 1003 } else { 1004 *(struct sockaddr_in6 *)&sock->bind_addr = 1005 *(struct sockaddr_in6 *)(void *)res->ai_addr; 1006 ret = ipv6_activate_sock(sock); 1007 } 1008 1009 if (ret != SNMP_ERR_NOERROR) 1010 free(sock); 1011 else 1012 TAILQ_INSERT_HEAD(&port->socks, sock, link); 1013 } 1014 1015 if (!TAILQ_EMPTY(&port->socks)) 1016 port->row_status = RowStatus_active; 1017 1018 freeaddrinfo(res0); 1019 return (SNMP_ERR_GENERR); 1020 } 1021 1022 /** 1023 * Deactive the socket. Close all open sockets and delete all sock objects. 1024 * 1025 * \param port inet port 1026 */ 1027 static void 1028 dns_deactivate(struct inet_port *port) 1029 { 1030 while (!TAILQ_EMPTY(&port->socks)) { 1031 struct port_sock *sock = TAILQ_FIRST(&port->socks); 1032 TAILQ_REMOVE(&port->socks, sock, link); 1033 snmpd_input_close(&sock->input); 1034 free(sock); 1035 } 1036 port->row_status = RowStatus_notInService; 1037 } 1038 1039 static int 1040 inet_create(struct inet_port_params *params, struct inet_port **pp) 1041 { 1042 int err = SNMP_ERR_NOERROR; 1043 struct inet_port *port = NULL; 1044 1045 if (params->port > 0xffff) { 1046 err = SNMP_ERR_NO_CREATION; 1047 goto fail; 1048 } 1049 1050 if ((port = malloc(sizeof(*port))) == NULL) { 1051 err = SNMP_ERR_GENERR; 1052 goto fail; 1053 } 1054 memset(port, 0, sizeof(*port)); 1055 TAILQ_INIT(&port->socks); 1056 1057 port->proto = params->proto; 1058 port->tport.index = params->index; 1059 1060 switch (params->type) { 1061 1062 case InetAddressType_ipv4: 1063 port->create = ipv4_create; 1064 port->activate = ipv4_activate; 1065 port->deactivate = ipv4_deactivate; 1066 break; 1067 1068 case InetAddressType_ipv6: 1069 port->create = ipv6_create; 1070 port->activate = ipv6_activate; 1071 port->deactivate = ipv6_deactivate; 1072 break; 1073 1074 case InetAddressType_ipv6z: 1075 port->create = ipv6z_create; 1076 port->activate = ipv6_activate; 1077 port->deactivate = ipv6_deactivate; 1078 break; 1079 1080 case InetAddressType_dns: 1081 port->create = dns_create; 1082 port->activate = dns_activate; 1083 port->deactivate = dns_deactivate; 1084 break; 1085 1086 default: 1087 err = SNMP_ERR_NO_CREATION; 1088 goto fail; 1089 } 1090 1091 if ((err = port->create(port, params)) != SNMP_ERR_NOERROR) 1092 goto fail; 1093 1094 *pp = port; 1095 trans_insert_port(my_trans, &port->tport); 1096 return (err); 1097 1098 fail: 1099 free(port->dns_addr); 1100 free(port); 1101 return (err); 1102 } 1103 1104 static int 1105 create_and_go(struct snmp_context *ctx, struct inet_port_params *params) 1106 { 1107 int err; 1108 struct inet_port *port; 1109 1110 if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR) 1111 return (err); 1112 1113 port->row_status = RowStatus_createAndGo; 1114 ctx->scratch->ptr1 = port; 1115 1116 if (community == COMM_INITIALIZE) 1117 return (err); 1118 1119 return (inet_activate(&port->tport)); 1120 } 1121 1122 static int 1123 create_and_wait(struct snmp_context *ctx, struct inet_port_params *params) 1124 { 1125 int err; 1126 struct inet_port *port; 1127 1128 if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR) 1129 return (err); 1130 1131 port->row_status = RowStatus_createAndWait; 1132 ctx->scratch->ptr1 = port; 1133 1134 return (err); 1135 } 1136 1137 /** 1138 * This is called to set a RowStatus value in the port table during 1139 * SET processing. 1140 * 1141 * When this is called during initialization time and the RowStatus is set 1142 * to CreateAndGo, the port is actually not activated. This is done when 1143 * the main code calls the init() for all ports later. 1144 */ 1145 static int 1146 inet_port_set(struct snmp_context *ctx, struct inet_port *port, 1147 struct inet_port_params *params, enum RowStatus nstatus) 1148 { 1149 switch (nstatus) { 1150 1151 case RowStatus_createAndGo: 1152 if (port != NULL) 1153 return (SNMP_ERR_INCONS_VALUE); 1154 ctx->scratch->int1 = SET_CREATED; 1155 return (create_and_go(ctx, params)); 1156 1157 case RowStatus_createAndWait: 1158 if (port != NULL) 1159 return (SNMP_ERR_INCONS_VALUE); 1160 ctx->scratch->int1 = SET_CREATED; 1161 return (create_and_wait(ctx, params)); 1162 1163 case RowStatus_active: 1164 if (port == NULL) 1165 return (SNMP_ERR_INCONS_VALUE); 1166 1167 switch (port->row_status) { 1168 1169 case RowStatus_notReady: 1170 /* this can not happend */ 1171 abort(); 1172 1173 case RowStatus_notInService: 1174 ctx->scratch->int1 = SET_ACTIVATED; 1175 return (inet_activate(&port->tport)); 1176 1177 case RowStatus_active: 1178 return (SNMP_ERR_NOERROR); 1179 1180 case RowStatus_createAndGo: 1181 case RowStatus_createAndWait: 1182 case RowStatus_destroy: 1183 abort(); 1184 } 1185 break; 1186 1187 case RowStatus_notInService: 1188 if (port == NULL) 1189 return (SNMP_ERR_INCONS_VALUE); 1190 1191 switch (port->row_status) { 1192 1193 case RowStatus_notReady: 1194 /* this can not happend */ 1195 abort(); 1196 1197 case RowStatus_notInService: 1198 return (SNMP_ERR_NOERROR); 1199 1200 case RowStatus_active: 1201 /* this is done during commit */ 1202 ctx->scratch->int1 = SET_DEACTIVATE; 1203 return (SNMP_ERR_NOERROR); 1204 1205 case RowStatus_createAndGo: 1206 case RowStatus_createAndWait: 1207 case RowStatus_destroy: 1208 abort(); 1209 } 1210 break; 1211 1212 case RowStatus_destroy: 1213 /* this is done during commit */ 1214 ctx->scratch->int1 = SET_DESTROY; 1215 return (SNMP_ERR_NOERROR); 1216 1217 case RowStatus_notReady: 1218 return (SNMP_ERR_WRONG_VALUE); 1219 } 1220 abort(); 1221 } 1222 1223 /* 1224 * Port table 1225 */ 1226 int 1227 op_snmp_trans_inet(struct snmp_context *ctx, struct snmp_value *value, 1228 u_int sub, u_int iidx __unused, enum snmp_op op) 1229 { 1230 asn_subid_t which = value->var.subs[sub - 1]; 1231 struct inet_port *port; 1232 struct inet_port_params params; 1233 int ret; 1234 1235 switch (op) { 1236 1237 case SNMP_OP_GETNEXT: 1238 if ((port = (struct inet_port *)trans_next_port(my_trans, 1239 &value->var, sub)) == NULL) 1240 return (SNMP_ERR_NOSUCHNAME); 1241 index_append(&value->var, sub, &port->tport.index); 1242 goto fetch; 1243 1244 case SNMP_OP_GET: 1245 if ((port = (struct inet_port *)trans_find_port(my_trans, 1246 &value->var, sub)) == NULL) 1247 return (SNMP_ERR_NOSUCHNAME); 1248 goto fetch; 1249 1250 case SNMP_OP_SET: 1251 port = (struct inet_port *)trans_find_port(my_trans, 1252 &value->var, sub); 1253 1254 if (which != LEAF_begemotSnmpdTransInetStatus) 1255 abort(); 1256 if (!isok_RowStatus(value->v.integer)) 1257 return (SNMP_ERR_WRONG_VALUE); 1258 1259 if (index_decode(&value->var, sub, iidx, ¶ms.type, 1260 ¶ms.addr, ¶ms.addr_len, ¶ms.port, 1261 ¶ms.proto)) 1262 return (SNMP_ERR_NO_CREATION); 1263 1264 asn_slice_oid(¶ms.index, &value->var, sub, value->var.len); 1265 1266 ret = inet_port_set(ctx, port, ¶ms, 1267 (enum RowStatus)value->v.integer); 1268 1269 free(params.addr); 1270 return (ret); 1271 1272 case SNMP_OP_ROLLBACK: 1273 if ((port = (struct inet_port *)trans_find_port(my_trans, 1274 &value->var, sub)) == NULL) 1275 /* cannot happen */ 1276 abort(); 1277 1278 switch (ctx->scratch->int1) { 1279 1280 case SET_CREATED: 1281 /* newly created */ 1282 assert(port != NULL); 1283 inet_destroy_port(&port->tport); 1284 return (SNMP_ERR_NOERROR); 1285 1286 case SET_DESTROY: 1287 /* do it now */ 1288 assert(port != NULL); 1289 return (SNMP_ERR_NOERROR); 1290 1291 case SET_ACTIVATED: 1292 deactivate_port(port); 1293 return (SNMP_ERR_NOERROR); 1294 1295 case SET_DEACTIVATE: 1296 return (SNMP_ERR_NOERROR); 1297 } 1298 abort(); 1299 1300 case SNMP_OP_COMMIT: 1301 if ((port = (struct inet_port *)trans_find_port(my_trans, 1302 &value->var, sub)) == NULL) 1303 /* cannot happen */ 1304 abort(); 1305 1306 switch (ctx->scratch->int1) { 1307 1308 case SET_CREATED: 1309 /* newly created */ 1310 assert(port != NULL); 1311 return (SNMP_ERR_NOERROR); 1312 1313 case SET_DESTROY: 1314 /* do it now */ 1315 assert(port != NULL); 1316 inet_destroy_port(&port->tport); 1317 return (SNMP_ERR_NOERROR); 1318 1319 case SET_ACTIVATED: 1320 return (SNMP_ERR_NOERROR); 1321 1322 case SET_DEACTIVATE: 1323 deactivate_port(port); 1324 return (SNMP_ERR_NOERROR); 1325 } 1326 abort(); 1327 } 1328 abort(); 1329 1330 fetch: 1331 switch (which) { 1332 1333 case LEAF_begemotSnmpdTransInetStatus: 1334 value->v.integer = port->row_status; 1335 break; 1336 1337 default: 1338 abort(); 1339 } 1340 1341 return (SNMP_ERR_NOERROR); 1342 } 1343