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
inet_start(void)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
inet_stop(int force __unused)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
deactivate_port(struct inet_port * p)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
inet_activate(struct tport * tp)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
inet_destroy_port(struct tport * tp)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
inet_alloc_buf(struct port_input * pi)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
inet_read_msg(struct port_input * pi,struct msghdr * msg,char * cbuf)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
inet_recv(struct tport * tp,struct port_input * pi)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
inet_send(struct tport * tp,const u_char * buf,size_t len,struct port_input * pi)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
ipv4_create(struct inet_port * port,struct inet_port_params * params)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
ipv4_input(int fd __unused,void * udata)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
ipv4_activate_sock(struct port_sock * sock)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
ipv4_activate(struct inet_port * p)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
ipv4_deactivate(struct inet_port * p)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
ipv4_parse_ctrl(struct port_sock * sock,const struct msghdr * msg)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
ipv4_setsrc(struct port_sock * sock,struct msghdr * msg,char * cbuf)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
ipv6_create_common(struct inet_port * port,struct inet_port_params * params,u_int scope_id)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
ipv6_create(struct inet_port * port,struct inet_port_params * params)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
ipv6_input(int fd __unused,void * udata)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
ipv6_activate_sock(struct port_sock * sock)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
ipv6_activate(struct inet_port * p)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
ipv6_deactivate(struct inet_port * p)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
ipv6_parse_ctrl(struct port_sock * sock,const struct msghdr * msg)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
ipv6_setsrc(struct port_sock * sock,struct msghdr * msg,char * cbuf)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
ipv6z_create(struct inet_port * port,struct inet_port_params * params)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
dns_create(struct inet_port * port,struct inet_port_params * params)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
dns_activate(struct inet_port * port)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
dns_deactivate(struct inet_port * port)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
inet_create(struct inet_port_params * params,struct inet_port ** pp)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
create_and_go(struct snmp_context * ctx,struct inet_port_params * params)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
create_and_wait(struct snmp_context * ctx,struct inet_port_params * params)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
inet_port_set(struct snmp_context * ctx,struct inet_port * port,struct inet_port_params * params,enum RowStatus nstatus)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
op_snmp_trans_inet(struct snmp_context * ctx,struct snmp_value * value,u_int sub,u_int iidx __unused,enum snmp_op op)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