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
63extern const struct transport_def inet_trans;
64
65struct inet_port;
66struct inet_port_params;
67struct port_sock;
68
69typedef int create_func(struct inet_port *, struct inet_port_params *);
70typedef void input_func(int, void *);
71typedef int activate_func(struct inet_port *);
72typedef void deactivate_func(struct inet_port *);
73typedef void parse_ctrl_func(struct port_sock *, const struct msghdr *);
74typedef void setsrc_func(struct port_sock *, struct msghdr *, char *);
75
76static create_func ipv4_create;
77static input_func ipv4_input;
78static activate_func ipv4_activate;
79static deactivate_func ipv4_deactivate;
80static parse_ctrl_func ipv4_parse_ctrl;
81static setsrc_func ipv4_setsrc;
82
83static create_func ipv6_create;
84static input_func ipv6_input;
85static activate_func ipv6_activate;
86static deactivate_func ipv6_deactivate;
87static parse_ctrl_func ipv6_parse_ctrl;
88static setsrc_func ipv6_setsrc;
89
90static create_func ipv6z_create;
91
92static create_func dns_create;
93static activate_func dns_activate;
94static deactivate_func dns_deactivate;
95
96struct 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};
130static_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 */
140struct 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};
168static_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 */
175static struct transport *my_trans;
176
177/** set operation */
178enum {
179	SET_CREATED,
180	SET_ACTIVATED,
181	SET_DEACTIVATE,
182	SET_DESTROY,
183};
184
185/** length of the control data buffer */
186static 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 */
193static 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 */
203static int
204inet_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 */
215static int
216inet_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 */
229static void
230deactivate_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 */
245static int
246inet_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 */
258static void
259inet_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 */
279static int
280inet_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 */
306static int
307inet_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 */
350static ssize_t
351inet_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 addr		destination address
379 * \param addlen	destination address length
380 *
381 * \return number of bytes sent
382 */
383static ssize_t
384inet_send2(struct tport *tp, const u_char *buf, size_t len,
385    struct port_input *pi)
386{
387	struct inet_port *p = __containerof(tp, struct inet_port, tport);
388	struct port_sock *s = (pi == NULL) ?  TAILQ_FIRST(&p->socks) :
389	    __containerof(pi, struct port_sock, input);
390
391	struct iovec iov;
392
393	iov.iov_base = __DECONST(void*, buf);
394	iov.iov_len = len;
395
396	struct msghdr msg;
397
398	msg.msg_flags = 0;
399	msg.msg_iov = &iov;
400	msg.msg_iovlen = 1;
401	msg.msg_name = (void *)pi->peer;
402	msg.msg_namelen = pi->peerlen;
403
404	char cbuf[XMIT_CBUF_SIZE];
405	if (s->set_ret_source) {
406		s->setsrc(s, &msg, cbuf);
407	} else {
408		msg.msg_control = NULL;
409		msg.msg_controllen = 0;
410	}
411
412	return (sendmsg(s->input.fd, &msg, 0));
413}
414
415/** exported to daemon */
416const struct transport_def inet_trans = {
417	"inet",
418	OIDX_begemotSnmpdTransInet,
419	inet_start,
420	inet_stop,
421	inet_destroy_port,
422	inet_activate,
423	NULL,
424	inet_recv,
425	inet_send2,
426};
427
428struct inet_port_params {
429	/** index oid */
430	struct asn_oid index;
431
432	/** internet address type */
433	enum InetAddressType type;
434
435	/** internet address */
436	u_char *addr;
437
438	/** length of address */
439	size_t addr_len;
440
441	/** port number */
442	uint32_t port;
443
444	/** protocol */
445	enum BegemotSnmpdTransportProto proto;
446};
447
448/**
449 * IPv4 creation stuff. Parse the index, fill socket address and creates
450 * a port_sock.
451 *
452 * \param port		the port to create
453 * \param params	parameters from the SNMP SET
454 *
455 * \return SNMP error
456 */
457static int
458ipv4_create(struct inet_port *port, struct inet_port_params *params)
459{
460
461	if (params->addr_len != 4)
462		return (SNMP_ERR_INCONS_VALUE);
463
464	struct port_sock *sock = calloc(1, sizeof(struct port_sock));
465	if (sock == NULL)
466		return (SNMP_ERR_GENERR);
467
468	snmpd_input_init(&sock->input);
469
470	TAILQ_INSERT_HEAD(&port->socks, sock, link);
471
472	struct sockaddr_in *sin =
473	    (struct sockaddr_in *)&sock->bind_addr;
474
475	sin->sin_len = sizeof(struct sockaddr_in);
476	sin->sin_family = AF_INET;
477	sin->sin_port = htons(params->port);
478	memcpy(&sin->sin_addr, params->addr, 4); /* network byte order */
479
480	sock->port = port;
481
482	return (SNMP_ERR_NOERROR);
483}
484
485/*
486 * An IPv4 inet port is ready. Delegate to the generic code to read the data
487 * and react.
488 *
489 * \param fd	file descriptor that is ready
490 * \param udata	inet_port pointer
491 */
492static void
493ipv4_input(int fd __unused, void *udata)
494{
495	struct port_sock *sock = udata;
496
497	sock->input.peerlen = sizeof(struct sockaddr_in);
498	snmpd_input(&sock->input, &sock->port->tport);
499}
500
501/**
502 * Activate an IPv4 socket.
503 *
504 * \param sock	thhe socket to activate
505 *
506 * \return error code
507 */
508static int
509ipv4_activate_sock(struct port_sock *sock)
510{
511	if ((sock->input.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
512		syslog(LOG_ERR, "creating UDP4 socket: %m");
513		return (SNMP_ERR_RES_UNAVAIL);
514	}
515
516	const struct sockaddr_in *sin =
517	    (const struct sockaddr_in *)&sock->bind_addr;
518
519	if (sin->sin_addr.s_addr == INADDR_ANY) {
520		/* need to know from which address to return */
521		static const int on = 1;
522
523		if (setsockopt(sock->input.fd, IPPROTO_IP, IP_RECVDSTADDR, &on,
524		    sizeof(on)) == -1) {
525			syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m");
526			(void)close(sock->input.fd);
527			sock->input.fd = -1;
528			return (SNMP_ERR_GENERR);
529		}
530		sock->set_ret_source = true;
531	}
532
533	if (bind(sock->input.fd, (const struct sockaddr *)sin, sizeof(*sin))) {
534		if (errno == EADDRNOTAVAIL) {
535			(void)close(sock->input.fd);
536			sock->input.fd = -1;
537			return (SNMP_ERR_INCONS_NAME);
538		}
539		syslog(LOG_ERR, "bind: %s:%u %m", inet_ntoa(sin->sin_addr),
540		    ntohs(sin->sin_port));
541		(void)close(sock->input.fd);
542		sock->input.fd = -1;
543		return (SNMP_ERR_GENERR);
544	}
545
546	if ((sock->input.id = fd_select(sock->input.fd, ipv4_input,
547	    sock, NULL)) == NULL) {
548		(void)close(sock->input.fd);
549		sock->input.fd = -1;
550		return (SNMP_ERR_GENERR);
551	}
552	sock->input.peer = (struct sockaddr *)&sock->ret_dest;
553
554	sock->parse_ctrl = ipv4_parse_ctrl;
555	sock->setsrc = ipv4_setsrc;
556
557	return (SNMP_ERR_NOERROR);
558}
559
560/**
561 * Open an IPv4 socket. Make the socket, bind it and put it on the select
562 * list. The socket struct has already been created during creation.
563 *
564 * \param p	inet port
565 *
566 * \return SNMP error code
567 */
568static int
569ipv4_activate(struct inet_port *p)
570{
571	struct port_sock *sock = TAILQ_FIRST(&p->socks);
572	assert(sock);
573	assert(!TAILQ_NEXT(sock, link));
574
575	const int ret = ipv4_activate_sock(sock);
576	if (ret == SNMP_ERR_NOERROR)
577		p->row_status = RowStatus_active;
578
579	return (ret);
580}
581
582/**
583 * Close an IPv4 socket. Keep the sock object.
584 *
585 * \param p	inet port
586 */
587static void
588ipv4_deactivate(struct inet_port *p)
589{
590	struct port_sock *sock = TAILQ_FIRST(&p->socks);
591	assert(sock);
592	assert(!TAILQ_NEXT(sock, link));
593
594	snmpd_input_close(&sock->input);
595
596	p->row_status = RowStatus_notInService;
597}
598
599/**
600 * Parse the control data received with a UDPv4 packet. This may contain
601 * credentials (for a local connection) and the address of the interface
602 * the message was received on. If there are credentials set the priv flag
603 * if the effective UID is zero.
604 *
605 * \param sock	the sock object
606 * \param msg	the received message
607 */
608static void
609ipv4_parse_ctrl(struct port_sock *sock, const struct msghdr *msg)
610{
611	struct sockcred *cred = NULL;
612
613	for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
614	    cmsg = CMSG_NXTHDR(msg, cmsg)) {
615
616		if (cmsg->cmsg_level == IPPROTO_IP &&
617		    cmsg->cmsg_type == IP_RECVDSTADDR) {
618			memcpy(&sock->ret_source.a4, CMSG_DATA(cmsg),
619			    sizeof(struct in_addr));
620
621		} else if (cmsg->cmsg_level == SOL_SOCKET &&
622		    cmsg->cmsg_type == SCM_CREDS) {
623			cred = (struct sockcred *)(void *)CMSG_DATA(cmsg);
624		}
625	}
626
627	sock->input.priv = 0;
628	if (sock->input.cred && cred)
629		/* remote end has sent credentials */
630		sock->input.priv = (cred->sc_euid == 0);
631}
632
633/**
634 * Set the source address option for IPv4 sockets.
635 *
636 * \param sock	socket object
637 * \param msg	message
638 */
639static void
640ipv4_setsrc(struct port_sock *sock, struct msghdr *msg, char *cbuf)
641{
642	struct cmsghdr *cmsg;
643
644	msg->msg_control = cbuf;
645	msg->msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
646
647	/* select outgoing interface by setting source address */
648	cmsg = CMSG_FIRSTHDR(msg);
649	cmsg->cmsg_level = IPPROTO_IP;
650	cmsg->cmsg_type = IP_SENDSRCADDR;
651	cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
652	memcpy(CMSG_DATA(cmsg), &sock->ret_source.a4,
653	    sizeof(struct in_addr));
654}
655
656/**
657 * Common part of IPv6 creation. This is used by both ipv6_create() and
658 * ipv6z_create().
659 *
660 * \param port		the table row
661 * \param params	creation parameters
662 * \param scope_id	scope_id (0 or from index)
663 *
664 * \return SNMP_ERR_NOERROR if port has been created, error code otherwise
665 */
666static int
667ipv6_create_common(struct inet_port *port, struct inet_port_params *params,
668    u_int scope_id)
669{
670	struct port_sock *sock = calloc(1, sizeof(struct port_sock));
671
672	if (sock == NULL)
673		return (SNMP_ERR_GENERR);
674
675	struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&sock->bind_addr;
676
677	sin->sin6_len = sizeof(struct sockaddr_in6);
678	sin->sin6_family = AF_INET6;
679	sin->sin6_port = htons(params->port);
680	sin->sin6_flowinfo = 0;
681	sin->sin6_scope_id = scope_id;
682
683	memcpy(sin->sin6_addr.s6_addr, params->addr, 16);
684
685	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && scope_id == 0) {
686		char buf[INET6_ADDRSTRLEN];
687		syslog(LOG_INFO, "%s: link local address used without scope "
688		    "index: %s", __func__, inet_ntop(AF_INET6,
689		    &sin->sin6_addr, buf, sizeof(buf)));
690		free(sock);
691		return (SNMP_ERR_NO_CREATION);
692	}
693
694	sock->port = port;
695
696	snmpd_input_init(&sock->input);
697	TAILQ_INSERT_HEAD(&port->socks, sock, link);
698
699	return (SNMP_ERR_NOERROR);
700}
701
702/**
703 * IPv6 creation stuff. Parse the index, fill socket address and creates
704 * a port_sock.
705 *
706 * \param port		the port to create
707 * \param params	parameters from the SNMP SET
708 *
709 * \return SNMP error
710 */
711static int
712ipv6_create(struct inet_port *port, struct inet_port_params *params)
713{
714	if (params->addr_len != 16)
715		return (SNMP_ERR_INCONS_VALUE);
716
717	const int ret = ipv6_create_common(port, params, 0);
718	if (ret != SNMP_ERR_NOERROR)
719		return (ret);
720
721	return (SNMP_ERR_NOERROR);
722}
723
724/*
725 * An IPv6 inet port is ready. Delegate to the generic code to read the data
726 * and react.
727 *
728 * \param fd	file descriptor that is ready
729 * \param udata	inet_port pointer
730 */
731static void
732ipv6_input(int fd __unused, void *udata)
733{
734	struct port_sock *sock = udata;
735
736	sock->input.peerlen = sizeof(struct sockaddr_in6);
737	snmpd_input(&sock->input, &sock->port->tport);
738}
739
740/**
741 * Activate an IPv6 socket.
742 *
743 * \param sock	thhe socket to activate
744 *
745 * \return error code
746 */
747static int
748ipv6_activate_sock(struct port_sock *sock)
749{
750	if ((sock->input.fd = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) {
751		syslog(LOG_ERR, "creating UDP6 socket: %m");
752		return (SNMP_ERR_RES_UNAVAIL);
753	}
754
755	const struct sockaddr_in6 *sin =
756	    (const struct sockaddr_in6 *)&sock->bind_addr;
757
758	if (memcmp(&sin->sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) {
759		/* need to know from which address to return */
760		static const int on = 1;
761
762		if (setsockopt(sock->input.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
763		    &on, sizeof(on)) == -1) {
764			syslog(LOG_ERR, "setsockopt(IP6_PKTINFO): %m");
765			(void)close(sock->input.fd);
766			sock->input.fd = -1;
767			return (SNMP_ERR_GENERR);
768		}
769		sock->set_ret_source = true;
770	}
771
772	if (bind(sock->input.fd, (const struct sockaddr *)sin, sizeof(*sin))) {
773		if (community != COMM_INITIALIZE && errno == EADDRNOTAVAIL) {
774			(void)close(sock->input.fd);
775			sock->input.fd = -1;
776			return (SNMP_ERR_INCONS_NAME);
777		}
778		char buf[INET6_ADDRSTRLEN];
779		syslog(LOG_ERR, "bind: %s:%u:%u %m", inet_ntop(AF_INET6,
780		    &sin->sin6_addr, buf, sizeof(buf)), sin->sin6_scope_id,
781		    ntohs(sin->sin6_port));
782		(void)close(sock->input.fd);
783		sock->input.fd = -1;
784		return (SNMP_ERR_GENERR);
785	}
786	if ((sock->input.id = fd_select(sock->input.fd, ipv6_input,
787	    sock, NULL)) == NULL) {
788		(void)close(sock->input.fd);
789		sock->input.fd = -1;
790		return (SNMP_ERR_GENERR);
791	}
792	sock->input.peer = (struct sockaddr *)&sock->ret_dest;
793
794	sock->parse_ctrl = ipv6_parse_ctrl;
795	sock->setsrc = ipv6_setsrc;
796
797	return (SNMP_ERR_NOERROR);
798}
799
800/**
801 * Open an IPv6 socket.
802 *
803 * \param port	inet port
804 *
805 * \return SNMP error code
806 */
807static int
808ipv6_activate(struct inet_port *p)
809{
810	struct port_sock *sock = TAILQ_FIRST(&p->socks);
811	assert(sock);
812
813	const int ret = ipv6_activate_sock(sock);
814
815	if (ret == SNMP_ERR_NOERROR)
816		p->row_status = RowStatus_active;
817	return (ret);
818}
819
820/**
821 * Close an IPv6 socket. Keep the sock object.
822 *
823 * \param p	inet port
824 */
825static void
826ipv6_deactivate(struct inet_port *p)
827{
828	struct port_sock *sock = TAILQ_FIRST(&p->socks);
829	assert(sock);
830	assert(!TAILQ_NEXT(sock, link));
831
832	snmpd_input_close(&sock->input);
833
834	p->row_status = RowStatus_notInService;
835}
836
837/**
838 * IPv6 specific part of message processing. The control data may contain
839 * credentials and packet info that contains the destination address of
840 * the packet.
841 *
842 * \param sock	the sock object
843 * \param msg	the received message
844 */
845static void
846ipv6_parse_ctrl(struct port_sock *sock, const struct msghdr *msg)
847{
848	struct sockcred *cred = NULL;
849
850	for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
851	    cmsg = CMSG_NXTHDR(msg, cmsg)) {
852
853		if (cmsg->cmsg_level == IPPROTO_IPV6 &&
854		    cmsg->cmsg_type == IPV6_PKTINFO) {
855			const struct in6_pktinfo *info =
856			    (const struct in6_pktinfo *)(const void *)
857			    CMSG_DATA(cmsg);
858			sock->ret_source.a6.ipi6_addr = info->ipi6_addr;
859			sock->ret_source.a6.ipi6_ifindex =
860			    !IN6_IS_ADDR_LINKLOCAL(&info->ipi6_addr) ? 0:
861			    info->ipi6_ifindex;
862		} else if (cmsg->cmsg_level == SOL_SOCKET &&
863		    cmsg->cmsg_type == SCM_CREDS) {
864			cred = (struct sockcred *)(void *)CMSG_DATA(cmsg);
865		}
866	}
867
868	sock->input.priv = 0;
869	if (sock->input.cred && cred)
870		/* remote end has sent credentials */
871		sock->input.priv = (cred->sc_euid == 0);
872}
873
874/**
875 * Set the source address option for IPv4 sockets.
876 *
877 * \param sock	socket object
878 * \param msg	message
879 */
880static void
881ipv6_setsrc(struct port_sock *sock, struct msghdr *msg, char *cbuf)
882{
883	struct cmsghdr *cmsg;
884
885	msg->msg_control = cbuf;
886	msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
887
888	/* select outgoing interface by setting source address */
889	cmsg = CMSG_FIRSTHDR(msg);
890	cmsg->cmsg_level = IPPROTO_IPV6;
891	cmsg->cmsg_type = IPV6_PKTINFO;
892	cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
893	memcpy(CMSG_DATA(cmsg), &sock->ret_source.a6,
894	    sizeof(struct in6_pktinfo));
895}
896
897/**
898 * IPv6z creation stuff. Parse the index, fill socket address and creates
899 * a port_sock.
900 *
901 * \param port		the port to create
902 * \param params	parameters from the SNMP SET
903 *
904 * \return SNMP error
905 */
906static int
907ipv6z_create(struct inet_port *port, struct inet_port_params *params)
908{
909	if (params->addr_len != 20)
910		return (SNMP_ERR_INCONS_VALUE);
911
912	u_int scope_id = 0;
913	for (u_int i = 16; i < 20; i++) {
914		scope_id <<= 8;
915		scope_id |= params->addr[i];
916	}
917
918	const int ret = ipv6_create_common(port, params, scope_id);
919	if (ret != SNMP_ERR_NOERROR)
920		return (ret);
921
922	return (SNMP_ERR_NOERROR);
923}
924
925/**
926 * DNS name creation stuff. Parse the index and save the string.
927 * This does not create a socket struct.
928 *
929 * \param port		the port to create
930 * \param params	parameters from the SNMP SET
931 *
932 * \return SNMP error
933 */
934static int
935dns_create(struct inet_port *port, struct inet_port_params *params)
936{
937	if (params->addr_len > 64)
938		return (SNMP_ERR_INCONS_VALUE);
939
940	if (strnlen(params->addr, params->addr_len) !=
941	    params->addr_len)
942		return (SNMP_ERR_INCONS_VALUE);
943
944	if ((port->dns_addr = realloc(params->addr,
945	    params->addr_len + 1)) == NULL)
946		return (SNMP_ERR_GENERR);
947
948	port->dns_addr[params->addr_len] = '\0';
949	params->addr = NULL;
950
951	port->dns_port = htons(params->port);
952
953	return (SNMP_ERR_NOERROR);
954}
955
956/**
957 * Open sockets. This loops through all the addresses returned by getaddrinfo
958 * and opens a socket for each of them.
959 *
960 * \param port	inet port
961 *
962 * \return SNMP error code
963 */
964static int
965dns_activate(struct inet_port *port)
966{
967	struct addrinfo hints;
968	memset(&hints, 0, sizeof(hints));
969	hints.ai_family = AF_UNSPEC;
970	hints.ai_socktype = SOCK_DGRAM;		// XXX udp-only
971	hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_NUMERICSERV;
972
973	char portbuf[8];
974	sprintf(portbuf, "%hu", ntohs(port->dns_port));
975
976	struct addrinfo *res0;
977	int error = getaddrinfo(port->dns_addr[0] == '\0'
978	    ? NULL : port->dns_addr,
979	    portbuf, &hints, &res0);
980
981	if (error) {
982		syslog(LOG_ERR, "cannot resolve address '%s': %s",
983		    port->dns_addr, gai_strerror(error));
984		return (SNMP_ERR_GENERR);
985	}
986
987	for (struct addrinfo *res = res0; res != NULL; res = res->ai_next) {
988		if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
989			continue;
990
991		struct port_sock *sock = calloc(1, sizeof(struct port_sock));
992		if (sock == NULL)
993			return (SNMP_ERR_GENERR);
994
995		snmpd_input_init(&sock->input);
996		sock->port = port;
997
998		int ret = SNMP_ERR_NOERROR;
999
1000		if (res->ai_family == AF_INET) {
1001			*(struct sockaddr_in *)&sock->bind_addr =
1002			    *(struct sockaddr_in *)(void *)res->ai_addr;
1003			ret = ipv4_activate_sock(sock);
1004		} else {
1005			*(struct sockaddr_in6 *)&sock->bind_addr =
1006			    *(struct sockaddr_in6 *)(void *)res->ai_addr;
1007			ret = ipv6_activate_sock(sock);
1008		}
1009
1010		if (ret != SNMP_ERR_NOERROR)
1011			free(sock);
1012		else
1013			TAILQ_INSERT_HEAD(&port->socks, sock, link);
1014	}
1015
1016	if (!TAILQ_EMPTY(&port->socks))
1017		port->row_status = RowStatus_active;
1018
1019	freeaddrinfo(res0);
1020	return (SNMP_ERR_GENERR);
1021}
1022
1023/**
1024 * Deactive the socket. Close all open sockets and delete all sock objects.
1025 *
1026 * \param port	inet port
1027 */
1028static void
1029dns_deactivate(struct inet_port *port)
1030{
1031	while (!TAILQ_EMPTY(&port->socks)) {
1032		struct port_sock *sock = TAILQ_FIRST(&port->socks);
1033		TAILQ_REMOVE(&port->socks, sock, link);
1034		snmpd_input_close(&sock->input);
1035		free(sock);
1036	}
1037	port->row_status = RowStatus_notInService;
1038}
1039
1040static int
1041inet_create(struct inet_port_params *params, struct inet_port **pp)
1042{
1043	int err = SNMP_ERR_NOERROR;
1044	struct inet_port *port = NULL;
1045
1046	if (params->port > 0xffff) {
1047		err = SNMP_ERR_NO_CREATION;
1048		goto fail;
1049	}
1050
1051	if ((port = malloc(sizeof(*port))) == NULL) {
1052		err =  SNMP_ERR_GENERR;
1053		goto fail;
1054	}
1055	memset(port, 0, sizeof(*port));
1056	TAILQ_INIT(&port->socks);
1057
1058	port->proto = params->proto;
1059	port->tport.index = params->index;
1060
1061	switch (params->type) {
1062
1063	  case InetAddressType_ipv4:
1064		port->create = ipv4_create;
1065		port->activate = ipv4_activate;
1066		port->deactivate = ipv4_deactivate;
1067		break;
1068
1069	  case InetAddressType_ipv6:
1070		port->create = ipv6_create;
1071		port->activate = ipv6_activate;
1072		port->deactivate = ipv6_deactivate;
1073		break;
1074
1075	  case InetAddressType_ipv6z:
1076		port->create = ipv6z_create;
1077		port->activate = ipv6_activate;
1078		port->deactivate = ipv6_deactivate;
1079		break;
1080
1081	  case InetAddressType_dns:
1082		port->create = dns_create;
1083		port->activate = dns_activate;
1084		port->deactivate = dns_deactivate;
1085		break;
1086
1087	  default:
1088		err = SNMP_ERR_NO_CREATION;
1089		goto fail;
1090	}
1091
1092	if ((err = port->create(port, params)) != SNMP_ERR_NOERROR)
1093		goto fail;
1094
1095	*pp = port;
1096	trans_insert_port(my_trans, &port->tport);
1097	return (err);
1098
1099fail:
1100	free(port->dns_addr);
1101	free(port);
1102	return (err);
1103}
1104
1105static int
1106create_and_go(struct snmp_context *ctx, struct inet_port_params *params)
1107{
1108	int err;
1109	struct inet_port *port;
1110
1111	if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR)
1112		return (err);
1113
1114	port->row_status = RowStatus_createAndGo;
1115	ctx->scratch->ptr1 = port;
1116
1117	if (community == COMM_INITIALIZE)
1118		return (err);
1119
1120	return (inet_activate(&port->tport));
1121}
1122
1123static int
1124create_and_wait(struct snmp_context *ctx, struct inet_port_params *params)
1125{
1126	int err;
1127	struct inet_port *port;
1128
1129	if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR)
1130		return (err);
1131
1132	port->row_status = RowStatus_createAndWait;
1133	ctx->scratch->ptr1 = port;
1134
1135	return (err);
1136}
1137
1138/**
1139 * This is called to set a RowStatus value in the port table during
1140 * SET processing.
1141 *
1142 * When this is called during initialization time and the RowStatus is set
1143 * to CreateAndGo, the port is actually not activated. This is done when
1144 * the main code calls the init() for all ports later.
1145 */
1146static int
1147inet_port_set(struct snmp_context *ctx, struct inet_port *port,
1148    struct inet_port_params *params, enum RowStatus nstatus)
1149{
1150	switch (nstatus) {
1151
1152	  case RowStatus_createAndGo:
1153		if (port != NULL)
1154			return (SNMP_ERR_INCONS_VALUE);
1155		ctx->scratch->int1 = SET_CREATED;
1156		return (create_and_go(ctx, params));
1157
1158	  case RowStatus_createAndWait:
1159		if (port != NULL)
1160			return (SNMP_ERR_INCONS_VALUE);
1161		ctx->scratch->int1 = SET_CREATED;
1162		return (create_and_wait(ctx, params));
1163
1164	  case RowStatus_active:
1165		if (port == NULL)
1166			return (SNMP_ERR_INCONS_VALUE);
1167
1168		switch (port->row_status) {
1169
1170		  case RowStatus_notReady:
1171			/* this can not happend */
1172			abort();
1173
1174		  case RowStatus_notInService:
1175			ctx->scratch->int1 = SET_ACTIVATED;
1176			return (inet_activate(&port->tport));
1177
1178		  case RowStatus_active:
1179			return (SNMP_ERR_NOERROR);
1180
1181		  case RowStatus_createAndGo:
1182		  case RowStatus_createAndWait:
1183		  case RowStatus_destroy:
1184			abort();
1185		}
1186		break;
1187
1188	  case RowStatus_notInService:
1189		if (port == NULL)
1190			return (SNMP_ERR_INCONS_VALUE);
1191
1192		switch (port->row_status) {
1193
1194		  case RowStatus_notReady:
1195			/* this can not happend */
1196			abort();
1197
1198		  case RowStatus_notInService:
1199			return (SNMP_ERR_NOERROR);
1200
1201		  case RowStatus_active:
1202			/* this is done during commit */
1203			ctx->scratch->int1 = SET_DEACTIVATE;
1204			return (SNMP_ERR_NOERROR);
1205
1206		  case RowStatus_createAndGo:
1207		  case RowStatus_createAndWait:
1208		  case RowStatus_destroy:
1209			abort();
1210		}
1211		break;
1212
1213	  case RowStatus_destroy:
1214		/* this is done during commit */
1215		ctx->scratch->int1 = SET_DESTROY;
1216		return (SNMP_ERR_NOERROR);
1217
1218	  case RowStatus_notReady:
1219		return (SNMP_ERR_WRONG_VALUE);
1220	}
1221	abort();
1222}
1223
1224/*
1225 * Port table
1226 */
1227int
1228op_snmp_trans_inet(struct snmp_context *ctx, struct snmp_value *value,
1229    u_int sub, u_int iidx __unused, enum snmp_op op)
1230{
1231	asn_subid_t which = value->var.subs[sub - 1];
1232	struct inet_port *port;
1233	struct inet_port_params params;
1234	int ret;
1235
1236	switch (op) {
1237
1238	  case SNMP_OP_GETNEXT:
1239		if ((port = (struct inet_port *)trans_next_port(my_trans,
1240		    &value->var, sub)) == NULL)
1241			return (SNMP_ERR_NOSUCHNAME);
1242		index_append(&value->var, sub, &port->tport.index);
1243		goto fetch;
1244
1245	  case SNMP_OP_GET:
1246		if ((port = (struct inet_port *)trans_find_port(my_trans,
1247		    &value->var, sub)) == NULL)
1248			return (SNMP_ERR_NOSUCHNAME);
1249		goto fetch;
1250
1251	  case SNMP_OP_SET:
1252		port = (struct inet_port *)trans_find_port(my_trans,
1253		    &value->var, sub);
1254
1255		if (which != LEAF_begemotSnmpdTransInetStatus)
1256			abort();
1257		if (!isok_RowStatus(value->v.integer))
1258			return (SNMP_ERR_WRONG_VALUE);
1259
1260		if (index_decode(&value->var, sub, iidx, &params.type,
1261		    &params.addr, &params.addr_len, &params.port,
1262		    &params.proto))
1263			return (SNMP_ERR_NO_CREATION);
1264
1265		asn_slice_oid(&params.index, &value->var, sub, value->var.len);
1266
1267		ret = inet_port_set(ctx, port, &params,
1268		    (enum RowStatus)value->v.integer);
1269
1270		free(params.addr);
1271		return (ret);
1272
1273	  case SNMP_OP_ROLLBACK:
1274		if ((port = (struct inet_port *)trans_find_port(my_trans,
1275		    &value->var, sub)) == NULL)
1276			/* cannot happen */
1277			abort();
1278
1279		switch (ctx->scratch->int1) {
1280
1281		  case SET_CREATED:
1282			/* newly created */
1283			assert(port != NULL);
1284			inet_destroy_port(&port->tport);
1285			return (SNMP_ERR_NOERROR);
1286
1287		  case SET_DESTROY:
1288			/* do it now */
1289			assert(port != NULL);
1290			return (SNMP_ERR_NOERROR);
1291
1292		  case SET_ACTIVATED:
1293			deactivate_port(port);
1294			return (SNMP_ERR_NOERROR);
1295
1296		  case SET_DEACTIVATE:
1297			return (SNMP_ERR_NOERROR);
1298		}
1299		abort();
1300
1301	  case SNMP_OP_COMMIT:
1302		if ((port = (struct inet_port *)trans_find_port(my_trans,
1303		    &value->var, sub)) == NULL)
1304			/* cannot happen */
1305			abort();
1306
1307		switch (ctx->scratch->int1) {
1308
1309		  case SET_CREATED:
1310			/* newly created */
1311			assert(port != NULL);
1312			return (SNMP_ERR_NOERROR);
1313
1314		  case SET_DESTROY:
1315			/* do it now */
1316			assert(port != NULL);
1317			inet_destroy_port(&port->tport);
1318			return (SNMP_ERR_NOERROR);
1319
1320		  case SET_ACTIVATED:
1321			return (SNMP_ERR_NOERROR);
1322
1323		  case SET_DEACTIVATE:
1324			deactivate_port(port);
1325			return (SNMP_ERR_NOERROR);
1326		}
1327		abort();
1328	}
1329	abort();
1330
1331  fetch:
1332	switch (which) {
1333
1334	  case LEAF_begemotSnmpdTransInetStatus:
1335		value->v.integer = port->row_status;
1336		break;
1337
1338	  default:
1339		abort();
1340	}
1341
1342	return (SNMP_ERR_NOERROR);
1343}
1344