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
863		} else if (cmsg->cmsg_level == SOL_SOCKET &&
864		    cmsg->cmsg_type == SCM_CREDS) {
865			cred = (struct sockcred *)(void *)CMSG_DATA(cmsg);
866		}
867	}
868
869	sock->input.priv = 0;
870	if (sock->input.cred && cred)
871		/* remote end has sent credentials */
872		sock->input.priv = (cred->sc_euid == 0);
873}
874
875/**
876 * Set the source address option for IPv4 sockets.
877 *
878 * \param sock	socket object
879 * \param msg	message
880 */
881static void
882ipv6_setsrc(struct port_sock *sock, struct msghdr *msg, char *cbuf)
883{
884	struct cmsghdr *cmsg;
885
886	msg->msg_control = cbuf;
887	msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
888
889	/* select outgoing interface by setting source address */
890	cmsg = CMSG_FIRSTHDR(msg);
891	cmsg->cmsg_level = IPPROTO_IPV6;
892	cmsg->cmsg_type = IPV6_PKTINFO;
893	cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
894	memcpy(CMSG_DATA(cmsg), &sock->ret_source.a6,
895	    sizeof(struct in6_pktinfo));
896}
897
898/**
899 * IPv6z creation stuff. Parse the index, fill socket address and creates
900 * a port_sock.
901 *
902 * \param port		the port to create
903 * \param params	parameters from the SNMP SET
904 *
905 * \return SNMP error
906 */
907static int
908ipv6z_create(struct inet_port *port, struct inet_port_params *params)
909{
910	if (params->addr_len != 20)
911		return (SNMP_ERR_INCONS_VALUE);
912
913	u_int scope_id = 0;
914	for (u_int i = 16; i < 20; i++) {
915		scope_id <<= 8;
916		scope_id |= params->addr[i];
917	}
918
919	const int ret = ipv6_create_common(port, params, scope_id);
920	if (ret != SNMP_ERR_NOERROR)
921		return (ret);
922
923	return (SNMP_ERR_NOERROR);
924}
925
926/**
927 * DNS name creation stuff. Parse the index and save the string.
928 * This does not create a socket struct.
929 *
930 * \param port		the port to create
931 * \param params	parameters from the SNMP SET
932 *
933 * \return SNMP error
934 */
935static int
936dns_create(struct inet_port *port, struct inet_port_params *params)
937{
938	if (params->addr_len > 64)
939		return (SNMP_ERR_INCONS_VALUE);
940
941	if (strnlen(params->addr, params->addr_len) !=
942	    params->addr_len)
943		return (SNMP_ERR_INCONS_VALUE);
944
945	if ((port->dns_addr = realloc(params->addr,
946	    params->addr_len + 1)) == NULL)
947		return (SNMP_ERR_GENERR);
948
949	port->dns_addr[params->addr_len] = '\0';
950	params->addr = NULL;
951
952	port->dns_port = htons(params->port);
953
954	return (SNMP_ERR_NOERROR);
955}
956
957/**
958 * Open sockets. This loops through all the addresses returned by getaddrinfo
959 * and opens a socket for each of them.
960 *
961 * \param port	inet port
962 *
963 * \return SNMP error code
964 */
965static int
966dns_activate(struct inet_port *port)
967{
968	struct addrinfo hints;
969	memset(&hints, 0, sizeof(hints));
970	hints.ai_family = AF_UNSPEC;
971	hints.ai_socktype = SOCK_DGRAM;		// XXX udp-only
972	hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_NUMERICSERV;
973
974	char portbuf[8];
975	sprintf(portbuf, "%hu", ntohs(port->dns_port));
976
977	struct addrinfo *res0;
978	int error = getaddrinfo(port->dns_addr[0] == '\0'
979	    ? NULL : port->dns_addr,
980	    portbuf, &hints, &res0);
981
982	if (error) {
983		syslog(LOG_ERR, "cannot resolve address '%s': %s",
984		    port->dns_addr, gai_strerror(error));
985		return (SNMP_ERR_GENERR);
986	}
987
988	for (struct addrinfo *res = res0; res != NULL; res = res->ai_next) {
989		if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
990			continue;
991
992		struct port_sock *sock = calloc(1, sizeof(struct port_sock));
993		if (sock == NULL)
994			return (SNMP_ERR_GENERR);
995
996		snmpd_input_init(&sock->input);
997		sock->port = port;
998
999		int ret = SNMP_ERR_NOERROR;
1000
1001		if (res->ai_family == AF_INET) {
1002			*(struct sockaddr_in *)&sock->bind_addr =
1003			    *(struct sockaddr_in *)(void *)res->ai_addr;
1004			ret = ipv4_activate_sock(sock);
1005		} else {
1006			*(struct sockaddr_in6 *)&sock->bind_addr =
1007			    *(struct sockaddr_in6 *)(void *)res->ai_addr;
1008			ret = ipv6_activate_sock(sock);
1009		}
1010
1011		if (ret != SNMP_ERR_NOERROR)
1012			free(sock);
1013		else
1014			TAILQ_INSERT_HEAD(&port->socks, sock, link);
1015	}
1016
1017	if (!TAILQ_EMPTY(&port->socks))
1018		port->row_status = RowStatus_active;
1019
1020	freeaddrinfo(res0);
1021	return (SNMP_ERR_GENERR);
1022}
1023
1024/**
1025 * Deactive the socket. Close all open sockets and delete all sock objects.
1026 *
1027 * \param port	inet port
1028 */
1029static void
1030dns_deactivate(struct inet_port *port)
1031{
1032	while (!TAILQ_EMPTY(&port->socks)) {
1033		struct port_sock *sock = TAILQ_FIRST(&port->socks);
1034		TAILQ_REMOVE(&port->socks, sock, link);
1035		snmpd_input_close(&sock->input);
1036		free(sock);
1037	}
1038	port->row_status = RowStatus_notInService;
1039}
1040
1041static int
1042inet_create(struct inet_port_params *params, struct inet_port **pp)
1043{
1044	int err = SNMP_ERR_NOERROR;
1045	struct inet_port *port = NULL;
1046
1047	if (params->port > 0xffff) {
1048		err = SNMP_ERR_NO_CREATION;
1049		goto fail;
1050	}
1051
1052	if ((port = malloc(sizeof(*port))) == NULL) {
1053		err =  SNMP_ERR_GENERR;
1054		goto fail;
1055	}
1056	memset(port, 0, sizeof(*port));
1057	TAILQ_INIT(&port->socks);
1058
1059	port->proto = params->proto;
1060	port->tport.index = params->index;
1061
1062	switch (params->type) {
1063
1064	  case InetAddressType_ipv4:
1065		port->create = ipv4_create;
1066		port->activate = ipv4_activate;
1067		port->deactivate = ipv4_deactivate;
1068		break;
1069
1070	  case InetAddressType_ipv6:
1071		port->create = ipv6_create;
1072		port->activate = ipv6_activate;
1073		port->deactivate = ipv6_deactivate;
1074		break;
1075
1076	  case InetAddressType_ipv6z:
1077		port->create = ipv6z_create;
1078		port->activate = ipv6_activate;
1079		port->deactivate = ipv6_deactivate;
1080		break;
1081
1082	  case InetAddressType_dns:
1083		port->create = dns_create;
1084		port->activate = dns_activate;
1085		port->deactivate = dns_deactivate;
1086		break;
1087
1088	  default:
1089		err = SNMP_ERR_NO_CREATION;
1090		goto fail;
1091	}
1092
1093	if ((err = port->create(port, params)) != SNMP_ERR_NOERROR)
1094		goto fail;
1095
1096	*pp = port;
1097	trans_insert_port(my_trans, &port->tport);
1098	return (err);
1099
1100fail:
1101	free(port->dns_addr);
1102	free(port);
1103	return (err);
1104}
1105
1106static int
1107create_and_go(struct snmp_context *ctx, struct inet_port_params *params)
1108{
1109	int err;
1110	struct inet_port *port;
1111
1112	if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR)
1113		return (err);
1114
1115	port->row_status = RowStatus_createAndGo;
1116	ctx->scratch->ptr1 = port;
1117
1118	if (community == COMM_INITIALIZE)
1119		return (err);
1120
1121	return (inet_activate(&port->tport));
1122}
1123
1124static int
1125create_and_wait(struct snmp_context *ctx, struct inet_port_params *params)
1126{
1127	int err;
1128	struct inet_port *port;
1129
1130	if ((err = inet_create(params, &port)) != SNMP_ERR_NOERROR)
1131		return (err);
1132
1133	port->row_status = RowStatus_createAndWait;
1134	ctx->scratch->ptr1 = port;
1135
1136	return (err);
1137}
1138
1139/**
1140 * This is called to set a RowStatus value in the port table during
1141 * SET processing.
1142 *
1143 * When this is called during initialization time and the RowStatus is set
1144 * to CreateAndGo, the port is actually not activated. This is done when
1145 * the main code calls the init() for all ports later.
1146 */
1147static int
1148inet_port_set(struct snmp_context *ctx, struct inet_port *port,
1149    struct inet_port_params *params, enum RowStatus nstatus)
1150{
1151	switch (nstatus) {
1152
1153	  case RowStatus_createAndGo:
1154		if (port != NULL)
1155			return (SNMP_ERR_INCONS_VALUE);
1156		ctx->scratch->int1 = SET_CREATED;
1157		return (create_and_go(ctx, params));
1158
1159	  case RowStatus_createAndWait:
1160		if (port != NULL)
1161			return (SNMP_ERR_INCONS_VALUE);
1162		ctx->scratch->int1 = SET_CREATED;
1163		return (create_and_wait(ctx, params));
1164
1165	  case RowStatus_active:
1166		if (port == NULL)
1167			return (SNMP_ERR_INCONS_VALUE);
1168
1169		switch (port->row_status) {
1170
1171		  case RowStatus_notReady:
1172			/* this can not happend */
1173			abort();
1174
1175		  case RowStatus_notInService:
1176			ctx->scratch->int1 = SET_ACTIVATED;
1177			return (inet_activate(&port->tport));
1178
1179		  case RowStatus_active:
1180			return (SNMP_ERR_NOERROR);
1181
1182		  case RowStatus_createAndGo:
1183		  case RowStatus_createAndWait:
1184		  case RowStatus_destroy:
1185			abort();
1186		}
1187		break;
1188
1189	  case RowStatus_notInService:
1190		if (port == NULL)
1191			return (SNMP_ERR_INCONS_VALUE);
1192
1193		switch (port->row_status) {
1194
1195		  case RowStatus_notReady:
1196			/* this can not happend */
1197			abort();
1198
1199		  case RowStatus_notInService:
1200			return (SNMP_ERR_NOERROR);
1201
1202		  case RowStatus_active:
1203			/* this is done during commit */
1204			ctx->scratch->int1 = SET_DEACTIVATE;
1205			return (SNMP_ERR_NOERROR);
1206
1207		  case RowStatus_createAndGo:
1208		  case RowStatus_createAndWait:
1209		  case RowStatus_destroy:
1210			abort();
1211		}
1212		break;
1213
1214	  case RowStatus_destroy:
1215		/* this is done during commit */
1216		ctx->scratch->int1 = SET_DESTROY;
1217		return (SNMP_ERR_NOERROR);
1218
1219	  case RowStatus_notReady:
1220		return (SNMP_ERR_WRONG_VALUE);
1221	}
1222	abort();
1223}
1224
1225/*
1226 * Port table
1227 */
1228int
1229op_snmp_trans_inet(struct snmp_context *ctx, struct snmp_value *value,
1230    u_int sub, u_int iidx __unused, enum snmp_op op)
1231{
1232	asn_subid_t which = value->var.subs[sub - 1];
1233	struct inet_port *port;
1234	struct inet_port_params params;
1235	int ret;
1236
1237	switch (op) {
1238
1239	  case SNMP_OP_GETNEXT:
1240		if ((port = (struct inet_port *)trans_next_port(my_trans,
1241		    &value->var, sub)) == NULL)
1242			return (SNMP_ERR_NOSUCHNAME);
1243		index_append(&value->var, sub, &port->tport.index);
1244		goto fetch;
1245
1246	  case SNMP_OP_GET:
1247		if ((port = (struct inet_port *)trans_find_port(my_trans,
1248		    &value->var, sub)) == NULL)
1249			return (SNMP_ERR_NOSUCHNAME);
1250		goto fetch;
1251
1252	  case SNMP_OP_SET:
1253		port = (struct inet_port *)trans_find_port(my_trans,
1254		    &value->var, sub);
1255
1256		if (which != LEAF_begemotSnmpdTransInetStatus)
1257			abort();
1258		if (!isok_RowStatus(value->v.integer))
1259			return (SNMP_ERR_WRONG_VALUE);
1260
1261		if (index_decode(&value->var, sub, iidx, &params.type,
1262		    &params.addr, &params.addr_len, &params.port,
1263		    &params.proto))
1264			return (SNMP_ERR_NO_CREATION);
1265
1266		asn_slice_oid(&params.index, &value->var, sub, value->var.len);
1267
1268		ret = inet_port_set(ctx, port, &params,
1269		    (enum RowStatus)value->v.integer);
1270
1271		free(params.addr);
1272		return (ret);
1273
1274	  case SNMP_OP_ROLLBACK:
1275		if ((port = (struct inet_port *)trans_find_port(my_trans,
1276		    &value->var, sub)) == NULL)
1277			/* cannot happen */
1278			abort();
1279
1280		switch (ctx->scratch->int1) {
1281
1282		  case SET_CREATED:
1283			/* newly created */
1284			assert(port != NULL);
1285			inet_destroy_port(&port->tport);
1286			return (SNMP_ERR_NOERROR);
1287
1288		  case SET_DESTROY:
1289			/* do it now */
1290			assert(port != NULL);
1291			return (SNMP_ERR_NOERROR);
1292
1293		  case SET_ACTIVATED:
1294			deactivate_port(port);
1295			return (SNMP_ERR_NOERROR);
1296
1297		  case SET_DEACTIVATE:
1298			return (SNMP_ERR_NOERROR);
1299		}
1300		abort();
1301
1302	  case SNMP_OP_COMMIT:
1303		if ((port = (struct inet_port *)trans_find_port(my_trans,
1304		    &value->var, sub)) == NULL)
1305			/* cannot happen */
1306			abort();
1307
1308		switch (ctx->scratch->int1) {
1309
1310		  case SET_CREATED:
1311			/* newly created */
1312			assert(port != NULL);
1313			return (SNMP_ERR_NOERROR);
1314
1315		  case SET_DESTROY:
1316			/* do it now */
1317			assert(port != NULL);
1318			inet_destroy_port(&port->tport);
1319			return (SNMP_ERR_NOERROR);
1320
1321		  case SET_ACTIVATED:
1322			return (SNMP_ERR_NOERROR);
1323
1324		  case SET_DEACTIVATE:
1325			deactivate_port(port);
1326			return (SNMP_ERR_NOERROR);
1327		}
1328		abort();
1329	}
1330	abort();
1331
1332  fetch:
1333	switch (which) {
1334
1335	  case LEAF_begemotSnmpdTransInetStatus:
1336		value->v.integer = port->row_status;
1337		break;
1338
1339	  default:
1340		abort();
1341	}
1342
1343	return (SNMP_ERR_NOERROR);
1344}
1345