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