xref: /freebsd/contrib/bsnmp/snmpd/trans_inet.c (revision 183d09305677b7c669eba8ed6fe8d0b879684913)
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, &params.type,
1260 		    &params.addr, &params.addr_len, &params.port,
1261 		    &params.proto))
1262 			return (SNMP_ERR_NO_CREATION);
1263 
1264 		asn_slice_oid(&params.index, &value->var, sub, value->var.len);
1265 
1266 		ret = inet_port_set(ctx, port, &params,
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