On Thu, 2021-04-29 at 07:30 +0200, Martijn van Duren wrote:
> On Thu, 2021-04-29 at 11:22 +1000, Antonino Sidoti wrote:
> > Hello,
> > 
> > I was wondering what options are available to monitor OpenBSD SMTPD? Can 
> > SNMP be utilise? My monitoring system is PRTG and I am using that for most 
> > of my systems. Can someone share their way of
> > monitoring please? I run two OpenSMTP mail servers and would very much like 
> > to get some insight as to how they are performing day to day. 
> > 
> > Thanks
> > 
> > Antonino Sidoti
> 
> I've build the following diff some time ago. But isn't going in as is,
> because the other devs want something like the filter interface for this
> feature, which is understandable. But that needs to be thought out fully
> and then also implemented, which might take some time. I'm currently
> focussing on other parts of the snmp stack before I want to venture into
> smtp processes again.
> 
> Anyway, the diff adds basic agentx support around the NETWORK-SERVICE-
> MIB (RFC2788) and the MTA-MIB (RFC2789). Feel free to use it, test it,
> and to report bugs. It will probably help keep things in shape, or maybe
> even improve its shape, until we finally have that external process.
> Keep in mind that this lacks the proper peer review expected from most
> OpenBSD base code.
> 
> Usage:
> Let net-snmpd (snmpd(8) currently has no agentx support) create an
> agentx socket:
>   master agentx
> smtpd connects via the parent process, which is root, so no need for
> custom agentXPerms.

Forgot to mention: start up net-snmpd with "-I-mta_sendmail", because
you get some garbage values from net-snmpd trying to interpret some
nonexisting sendmail (at least, that's my interpretation of the
output, haven't delved in too deep)

> Then you just add the following keyword to smtpd.conf
>   agentx
> And you can walk the data:
> martijn$ snmp walk 127.0.0.1 mib_2.27
> mib_2.27.1.1.2.1 = STRING: OpenSMTPd
> mib_2.27.1.1.3.1 = STRING: 
> mib_2.27.1.1.4.1 = STRING: 6.9.0
> mib_2.27.1.1.5.1 = Timeticks: (2100) 0:00:21.00
> mib_2.27.1.1.6.1 = INTEGER: 1
> mib_2.27.1.1.7.1 = Timeticks: (0) 0:00:00.00
> mib_2.27.1.1.16.1 = STRING: OpenSMTPD is a FREE implementation of the 
> server-side SMTP protocol as defined by RFC 5321, with some additional 
> standard extensions. It allows ordinary machines to
> exchange emails with other systems speaking the SMTP protocol.
> mib_2.27.1.1.17.1 = STRING: 
> martijn$ snmp walk 127.0.0.1 mib_2.28
> mib_2.28.1.1.1.1 = Counter32: 0
> mib_2.28.1.1.2.1 = Counter32: 0
> mib_2.28.1.1.3.1 = Counter32: 0
> mib_2.28.1.1.12.1 = Counter32: 0
> 
> You can set custom (agentx-master-)path and context as well.
> 
> If you have other applications running that uses the NETWORK-SERVICES
> MIB and you want predictable indices from the applIndex you can set it
> via the applIndex keyword. Keep in mind that your other applications
> need to play nice with the indexAllocate system in any case.
> 
> If you're running on !OpenBSD let me know, I have some diffs to make
> libagentx work on at least Ubuntu and maybe others.
> 
> martijn@
> 
> Index: agentx_control.c
> ===================================================================
> RCS file: agentx_control.c
> diff -N agentx_control.c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ agentx_control.c    29 Apr 2021 05:22:14 -0000
> @@ -0,0 +1,279 @@
> +/*     $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2020 Martijn van Duren <mart...@openbsd.org>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/queue.h>
> +#include <sys/socket.h>
> +#include <sys/tree.h>
> +#include <sys/uio.h>
> +
> +#include <agentx.h>
> +#include <errno.h>
> +#include <event.h>
> +#include <imsg.h>
> +#include <limits.h>
> +#include <stdio.h>
> +
> +#include "log.h"
> +#include "smtpd.h"
> +
> +static void agentx_control_nofd(struct agentx *, void *, int);
> +static void agentx_control_tryconnect(int, short, void *);
> +static void agentx_control_read(int, short, void *);
> +static void agentx_control_emptystring(struct agentx_varbind *);
> +static void agentx_control_applName(struct agentx_varbind *);
> +static void agentx_control_applVersion(struct agentx_varbind *);
> +static void agentx_control_applUptime(struct agentx_varbind *);
> +static void agentx_control_applOperStatus(struct agentx_varbind *);
> +static void agentx_control_applLastChange(struct agentx_varbind *);
> +static void agentx_control_applDescription(struct agentx_varbind *);
> +static void agentx_control_applURL(struct agentx_varbind *);
> +static void agentx_control_mtaReceivedMessages(struct agentx_varbind *);
> +static void agentx_control_mtaStoredMessages(struct agentx_varbind *);
> +static void agentx_control_mtaTransmittedMessages(struct agentx_varbind *);
> +static void agentx_control_mtaLoopsDetected(struct agentx_varbind *);
> +
> +static struct agentx *sa;
> +static struct agentx_session *sas;
> +static struct agentx_context *sac;
> +static struct agentx_region *application, *mta;
> +static struct agentx_index *applIndex;
> +static struct event connev, rev;
> +
> +extern struct stat_digest digest;
> +
> +#define APPLICATION AGENTX_MIB2, 27
> +#define APPLTABLE APPLICATION, 1
> +#define APPLENTRY APPLTABLE, 1
> +#define APPLINDEX APPLENTRY, 1
> +#define APPLNAME APPLENTRY, 2
> +#define APPLDIRECTORYNAME APPLENTRY, 3
> +#define APPLVERSION APPLENTRY, 4
> +#define APPLUPTIME APPLENTRY, 5
> +#define APPLOPERSTATUS APPLENTRY, 6
> +#define APPLLASTCHANGE APPLENTRY, 7
> +#define APPLINBOUNDASSOCIATIONS APPLENTRY, 8
> +#define APPLOUTBOUNDASSOCIATIONS APPLENTRY, 9
> +#define APPLACCUMULATEDINBOUNDASSOCIATIONS APPLENTRY, 10
> +#define APPLACCUMULATEDOUTBOUNDASSOCIATIONS APPLENTRY, 11
> +#define APPLLASTINBOUNDACTIVITY APPLENTRY, 12
> +#define APPLlASTOUTBOUNDACTIVITY APPLENTRY, 13
> +#define APPLREJECTEDINBOUNDASSOCIATIONS APPLENTRY, 14
> +#define APPLFAILEDOUTBOUNDASSOCIATIONS APPLENTRY, 15
> +#define APPLDESCRIPTION APPLENTRY, 16
> +#define APPLURL APPLENTRY, 17
> +#define MTA AGENTX_MIB2, 28
> +#define MTATABLE MTA, 1
> +#define MTAENTRY MTATABLE, 1
> +#define MTARECEIVEDMESSAGES MTAENTRY, 1
> +#define MTASTOREDMESSAGES MTAENTRY, 2
> +#define MTATRANSMITTEDMESSAGES MTAENTRY, 3
> +#define MTARECEIVEDVOLUME MTAENTRY, 4
> +#define MTASTOREDVOLUME MTAENTRY, 5
> +#define MTATRANSMITTEDVOLUME MTAENTRY, 6
> +#define MTARECEIVEDRECIPIENTS MTAENTRY, 7
> +#define MTASTOREDRECIPIENTS MTAENTRY, 8
> +#define MTATRANSMITTEDRECIPIENTS MTAENTRY, 9
> +#define MTASUCCESSFULCONVERTEDMESSAGES MTAENTRY, 10
> +#define MTAFAILEDCONVERTEDMESSAGES MTAENTRY, 11
> +#define MTALOOPSDETECTED MTAENTRY, 12
> +
> +void
> +agentx_control(void)
> +{
> +       agentx_log_fatal = fatalx;
> +       agentx_log_warn = log_warnx;
> +       agentx_log_info = log_info;
> +       agentx_log_debug = log_debug;
> +
> +       if ((sa = agentx(agentx_control_nofd, NULL)) == NULL)
> +               fatal("Can't setup agentx");
> +       if ((sas = agentx_session(sa, NULL, 0, "OpenSMTPd", 0)) == NULL)
> +               fatal("Can't setup agentx session");
> +       if ((sac = agentx_context(sas, env->sc_agentx->context)) == NULL)
> +               fatal("Can't setup agentx context");
> +
> +        if ((application = agentx_region(sac,
> +           AGENTX_OID(APPLICATION), 0)) == NULL)
> +                fatal("agentx_mib application region");
> +        if ((mta = agentx_region(sac,
> +           AGENTX_OID(MTA, 28), 0)) == NULL)
> +                fatal("agentx_mib application region");
> +       switch (env->sc_agentx->applIndexType) {
> +       case AGENTX_INDEX_TYPE_ANY:
> +               if ((applIndex = agentx_index_integer_any(application,
> +                   AGENTX_OID(APPLINDEX))) == NULL)
> +                       fatal("agentx_index_integer_new");
> +               break;
> +       case AGENTX_INDEX_TYPE_NEW:
> +               if ((applIndex = agentx_index_integer_new(application,
> +                   AGENTX_OID(APPLINDEX))) == NULL)
> +                       fatal("agentx_index_integer_new");
> +               break;
> +       case AGENTX_INDEX_TYPE_VALUE:
> +               if ((applIndex = agentx_index_integer_value(application,
> +                   AGENTX_OID(APPLINDEX),
> +                   env->sc_agentx->applIndex)) == NULL)
> +                       fatal("agentx_index_integer_new");
> +               break;
> +       case AGENTX_INDEX_TYPE_UNDEFINED:
> +               fatalx("%s: How did I get here?", __func__);
> +       }
> +
> +        if (agentx_object(application, AGENTX_OID(APPLNAME), &applIndex, 1, 
> 0,
> +           agentx_control_applName) == NULL ||
> +            agentx_object(application, AGENTX_OID(APPLDIRECTORYNAME),
> +           &applIndex, 1, 0, agentx_control_emptystring) == NULL ||
> +            agentx_object(application, AGENTX_OID(APPLVERSION), &applIndex, 
> 1,
> +            0, agentx_control_applVersion) == NULL ||
> +            agentx_object(application, AGENTX_OID(APPLUPTIME), &applIndex, 
> 1, 0,
> +           agentx_control_applUptime) == NULL ||
> +            agentx_object(application, AGENTX_OID(APPLOPERSTATUS), 
> &applIndex,
> +           1, 0, agentx_control_applOperStatus) == NULL ||
> +            agentx_object(application, AGENTX_OID(APPLLASTCHANGE), 
> &applIndex,
> +           1, 0, agentx_control_applLastChange) == NULL ||
> +            agentx_object(application, AGENTX_OID(APPLDESCRIPTION), 
> &applIndex,
> +           1, 0, agentx_control_applDescription) == NULL ||
> +            agentx_object(application, AGENTX_OID(APPLURL), &applIndex, 1, 0,
> +           agentx_control_applURL) == NULL ||
> +           agentx_object(mta, AGENTX_OID(MTARECEIVEDMESSAGES), &applIndex, 1,
> +            0, agentx_control_mtaReceivedMessages) == NULL ||
> +           agentx_object(mta, AGENTX_OID(MTASTOREDMESSAGES), &applIndex, 1, 
> 0,
> +           agentx_control_mtaStoredMessages) == NULL ||
> +           agentx_object(mta, AGENTX_OID(MTATRANSMITTEDMESSAGES), &applIndex,
> +           1, 0, agentx_control_mtaTransmittedMessages) == NULL ||
> +           agentx_object(mta, AGENTX_OID(MTALOOPSDETECTED), &applIndex, 1, 0,
> +           agentx_control_mtaLoopsDetected) == NULL)
> +                fatal("agentx_object");
> +       
> +}
> +
> +static void
> +agentx_control_nofd(struct agentx *unused, void *cookie, int close)
> +{
> +       event_del(&rev);
> +       agentx_control_tryconnect(-1, 0, NULL);
> +}
> +
> +static void
> +agentx_control_tryconnect(int fd, short event, void *cookie)
> +{
> +       m_create(p_parent, IMSG_AGENTX_GETFD, 0, 0, -1);
> +       m_close(p_parent);
> +}
> +
> +static void
> +agentx_control_read(int fd, short event, void *cookie)
> +{
> +       agentx_read(sa);
> +}
> +
> +void
> +agentx_control_fdopen(int fd, int serrno)
> +{
> +       struct timeval timeout = {3, 0};
> +
> +       if (fd == -1) {
> +               errno = serrno;
> +               log_warn("Failed to connect to agentx master");
> +               evtimer_set(&connev, agentx_control_tryconnect, NULL);
> +               evtimer_add(&connev, &timeout);
> +               return;
> +       }
> +
> +       agentx_connect(sa, fd);
> +
> +       event_set(&rev, fd, EV_READ|EV_PERSIST, agentx_control_read, NULL);
> +       event_add(&rev, NULL);
> +}
> +
> +static void
> +agentx_control_emptystring(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_string(vb, "");
> +}
> +
> +static void
> +agentx_control_applName(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_string(vb, "OpenSMTPd");
> +}
> +
> +static void
> +agentx_control_applVersion(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_string(vb, SMTPD_VERSION);
> +}
> +
> +static void
> +agentx_control_applUptime(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_timeticks(vb, (uint32_t) ((time(NULL) - 
> digest.startup) * 100));
> +}
> +
> +static void
> +agentx_control_applOperStatus(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_integer(vb, env->sc_flags & SMTPD_SMTP_PAUSED ? 2 : 1);
> +}
> +
> +static void
> +agentx_control_applLastChange(struct agentx_varbind *vb)
> +{
> +       /* I can't find this value, so just return a 0-value for now. */
> +       agentx_varbind_timeticks(vb, 0);
> +}
> +
> +static void
> +agentx_control_applDescription(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_string(vb, "OpenSMTPD is a FREE implementation of "
> +           "the server-side SMTP protocol as defined by RFC 5321, with some "
> +           "additional standard extensions. It allows ordinary machines to "
> +           "exchange emails with other systems speaking the SMTP protocol.");
> +}
> +
> +static void
> +agentx_control_applURL(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_string(vb, "");
> +}
> +
> +static void
> +agentx_control_mtaReceivedMessages(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_counter32(vb, (uint32_t) digest.evp_enqueued);
> +}
> +
> +static void
> +agentx_control_mtaStoredMessages(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_counter32(vb,
> +           (uint32_t) (digest.evp_enqueued - digest.evp_dequeued));
> +}
> +
> +static void
> +agentx_control_mtaTransmittedMessages(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_counter32(vb, digest.evp_dequeued);
> +}
> +
> +static void
> +agentx_control_mtaLoopsDetected(struct agentx_varbind *vb)
> +{
> +       agentx_varbind_counter32(vb, digest.dlv_loop);
> +}
> Index: control.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/control.c,v
> retrieving revision 1.126
> diff -u -p -r1.126 control.c
> --- control.c   31 Dec 2020 08:27:15 -0000      1.126
> +++ control.c   29 Apr 2021 05:22:14 -0000
> @@ -73,7 +73,7 @@ extern const char *backend_stat;
>  static uint64_t                        connid = 0;
>  static struct tree             ctl_conns;
>  static struct tree             ctl_count;
> -static struct stat_digest      digest;
> +struct stat_digest             digest;
>  
>  #define        CONTROL_FD_RESERVE              5
>  #define        CONTROL_MAXCONN_PER_CLIENT      32
> @@ -87,6 +87,7 @@ control_imsg(struct mproc *p, struct ims
>         const char              *key;
>         const void              *data;
>         size_t                   sz;
> +       int                      serrno;
>  
>         if (imsg == NULL) {
>                 if (p->proc != PROC_CLIENT)
> @@ -157,6 +158,16 @@ control_imsg(struct mproc *p, struct ims
>                 if (stat_backend)
>                         stat_backend->set(key, &val);
>                 return;
> +       case IMSG_AGENTX_GETFD:
> +               serrno = 0;
> +               if (imsg->fd == -1) {
> +                       m_msg(&m, imsg);
> +                       m_get_int(&m, &serrno);
> +                       m_end(&m);
> +               }
> +
> +               agentx_control_fdopen(imsg->fd, serrno);
> +               return;
>         }
>  
>         errx(1, "control_imsg: unexpected %s imsg",
> @@ -252,6 +263,9 @@ control(void)
>         config_peer(PROC_CA);
>  
>         control_listen();
> +
> +       if (env->sc_agentx != NULL)
> +               agentx_control();
>  
>         if (pledge("stdio unix recvfd sendfd", NULL) == -1)
>                 err(1, "pledge");
> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
> retrieving revision 1.287
> diff -u -p -r1.287 parse.y
> --- parse.y     9 Apr 2021 16:43:43 -0000       1.287
> +++ parse.y     29 Apr 2021 05:22:14 -0000
> @@ -28,11 +28,13 @@
>  #include <sys/socket.h>
>  #include <sys/stat.h>
>  #include <sys/ioctl.h>
> +#include <sys/un.h>
>  
>  #include <net/if.h>
>  #include <netinet/in.h>
>  #include <arpa/inet.h>
>  
> +#include <agentx.h>
>  #include <ctype.h>
>  #include <err.h>
>  #include <errno.h>
> @@ -177,9 +179,9 @@ typedef struct {
>  
>  %}
>  
> -%token ACTION ADMD ALIAS ANY ARROW AUTH AUTH_OPTIONAL
> +%token ACTION ADMD AGENTX ALIAS ANY APPLINDEX ARROW AUTH AUTH_OPTIONAL
>  %token BACKUP BOUNCE BYPASS
> -%token CA CERT CHAIN CHROOT CIPHERS COMMIT COMPRESSION CONNECT
> +%token CA CERT CHAIN CHROOT CIPHERS COMMIT COMPRESSION CONNECT CONTEXT
>  %token DATA DATA_LINE DHE DISCONNECT DOMAIN
>  %token EHLO ENABLE ENCRYPTION ERROR EXPAND_ONLY 
>  %token FCRDNS FILTER FOR FORWARD_ONLY FROM
> @@ -192,7 +194,7 @@ typedef struct {
>  %token MAIL_FROM MAILDIR MASK_SRC MASQUERADE MATCH MAX_MESSAGE_SIZE 
> MAX_DEFERRED MBOX MDA MTA MX
>  %token NO_DSN NO_VERIFY NOOP
>  %token ON
> -%token PHASE PKI PORT PROC PROC_EXEC PROTOCOLS PROXY_V2
> +%token PATH PHASE PKI PORT PROC PROC_EXEC PROTOCOLS PROXY_V2
>  %token QUEUE QUIT
>  %token RCPT_TO RDNS RECIPIENT RECEIVEDAUTH REGEX RELAY REJECT REPORT REWRITE 
> RSET
>  %token SCHEDULER SENDER SENDERS SMTP SMTP_IN SMTP_OUT SMTPS SOCKET SRC SRS 
> SUB_ADDR_DELIM
> @@ -228,6 +230,7 @@ grammar             : /* empty */
>                 | grammar dispatcher '\n'
>                 | grammar match '\n'
>                 | grammar filter '\n'
> +               | grammar agentx '\n'
>                 | grammar error '\n'            { file->errors++; }
>                 ;
>  
> @@ -1978,6 +1981,82 @@ FILTER STRING CHAIN {
>  }
>  ;
>  
> +agentxopt      :
> +CONTEXT STRING {
> +       if (conf->sc_agentx->context != NULL) {
> +               yyerror("redefinition of agentx context");
> +               free($2);
> +               YYERROR;
> +       }
> +       conf->sc_agentx->context = $2;
> +}
> +| PATH STRING {
> +       if (strlen($2) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
> +               yyerror("agentx path too large");
> +               free($2);
> +               YYERROR;
> +       }
> +       if ($2[0] != '/') {
> +               yyerror("agentx path must be absolute");
> +               free($2);
> +               YYERROR;
> +       }
> +       if (conf->sc_agentx->path != NULL) {
> +               yyerror("redefinition of agentx path");
> +               free($2);
> +               YYERROR;
> +       }
> +       conf->sc_agentx->path = $2;
> +}
> +| APPLINDEX STRING {
> +       if (conf->sc_agentx->applIndexType != AGENTX_INDEX_TYPE_UNDEFINED) {
> +               yyerror("redefinition of agentx applIndex");
> +               YYERROR;
> +       }
> +
> +       if (strcasecmp($2, "any") == 0)
> +               conf->sc_agentx->applIndexType = AGENTX_INDEX_TYPE_ANY;
> +       else if (strcasecmp($2, "new") == 0)
> +               conf->sc_agentx->applIndexType = AGENTX_INDEX_TYPE_NEW;
> +       else {
> +               yyerror("invalid applIndex");
> +               YYERROR;
> +       }
> +}
> +| APPLINDEX NUMBER {
> +       if (conf->sc_agentx->applIndexType != AGENTX_INDEX_TYPE_UNDEFINED) {
> +               yyerror("redefinition of agentx applIndex");
> +               YYERROR;
> +       }
> +       if ($2 > INT32_MAX) {
> +               yyerror("agentx applIndex too large");
> +               YYERROR;
> +       }
> +       if ($2 < 1) {
> +               yyerror("agentx applIndex too small");
> +               YYERROR;
> +       }
> +
> +       conf->sc_agentx->applIndexType = AGENTX_INDEX_TYPE_VALUE;
> +       conf->sc_agentx->applIndex = (uint32_t) $2;
> +}
> +;
> +
> +agentxopts     : /* empty */
> +               | agentxopts agentxopt
> +               ;
> +
> +agentx:
> +AGENTX {
> +       conf->sc_agentx = xcalloc(1, sizeof(*conf->sc_agentx));
> +} agentxopts {
> +       if (conf->sc_agentx->path == NULL)
> +               conf->sc_agentx->path = AGENTX_MASTER_PATH;
> +       if (conf->sc_agentx->applIndexType == AGENTX_INDEX_TYPE_UNDEFINED)
> +               conf->sc_agentx->applIndexType = AGENTX_INDEX_TYPE_ANY;
> +}
> +;
> +
>  size           : NUMBER                {
>                         if ($1 < 0) {
>                                 yyerror("invalid size: %" PRId64, $1);
> @@ -2655,8 +2734,10 @@ lookup(char *s)
>         static const struct keywords keywords[] = {
>                 { "action",             ACTION },
>                 { "admd",               ADMD },
> +               { "agentx",             AGENTX },
>                 { "alias",              ALIAS },
>                 { "any",                ANY },
> +               { "applIndex",          APPLINDEX },
>                 { "auth",               AUTH },
>                 { "auth-optional",      AUTH_OPTIONAL },
>                 { "backup",             BACKUP },
> @@ -2670,6 +2751,7 @@ lookup(char *s)
>                 { "commit",             COMMIT },
>                 { "compression",        COMPRESSION },
>                 { "connect",            CONNECT },
> +               { "context",            CONTEXT },
>                 { "data",               DATA },
>                 { "data-line",          DATA_LINE },
>                 { "dhe",                DHE },
> @@ -2713,6 +2795,7 @@ lookup(char *s)
>                 { "no-verify",          NO_VERIFY },
>                 { "noop",               NOOP },
>                 { "on",                 ON },
> +               { "path",               PATH },
>                 { "phase",              PHASE },
>                 { "pki",                PKI },
>                 { "port",               PORT },
> Index: smtpd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd.c,v
> retrieving revision 1.338
> diff -u -p -r1.338 smtpd.c
> --- smtpd.c     21 Apr 2021 07:54:10 -0000      1.338
> +++ smtpd.c     29 Apr 2021 05:22:14 -0000
> @@ -25,6 +25,7 @@
>  #include <sys/wait.h>
>  #include <sys/stat.h>
>  #include <sys/uio.h>
> +#include <sys/un.h>
>  #include <sys/mman.h>
>  
>  #include <bsd_auth.h>
> @@ -70,6 +71,7 @@ static void parent_send_config_lka(void)
>  static void parent_send_config_dispatcher(void);
>  static void parent_send_config_ca(void);
>  static void parent_sig_handler(int, short, void *);
> +static int parent_open_agentx(void);
>  static void forkmda(struct mproc *, uint64_t, struct deliver *);
>  static int parent_forward_open(char *, char *, uid_t, gid_t);
>  static struct child *child_add(pid_t, int, const char *);
> @@ -168,7 +170,7 @@ parent_imsg(struct mproc *p, struct imsg
>         uint64_t                 reqid;
>         size_t                   sz;
>         void                    *i;
> -       int                      fd, n, v, ret;
> +       int                      fd, n, v, ret, serrno;
>  
>         if (imsg == NULL)
>                 fatalx("process %s socket closed", p->name);
> @@ -268,6 +270,16 @@ parent_imsg(struct mproc *p, struct imsg
>                 m_add_string(p_lka, procname);
>                 m_close(p_lka);
>                 return;
> +       case IMSG_AGENTX_GETFD:
> +               fd = parent_open_agentx();
> +               if (fd == -1)
> +                       serrno = errno;
> +
> +               m_create(p_control, IMSG_AGENTX_GETFD, 0, 0, fd);
> +               if (fd == -1)
> +                       m_add_int(p_control, serrno);
> +               m_close(p_control);
> +               return;
>         }
>  
>         errx(1, "parent_imsg: unexpected %s imsg from %s",
> @@ -474,6 +486,29 @@ parent_sig_handler(int sig, short event,
>         }
>  }
>  
> +static int
> +parent_open_agentx(void)
> +{
> +       int fd;
> +       struct sockaddr_un sun;
> +       int serrno;
> +
> +       sun.sun_len = sizeof(sun);
> +       sun.sun_family = AF_UNIX;
> +       strlcpy(sun.sun_path, env->sc_agentx->path, sizeof(sun.sun_path));
> +
> +       if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
> +               return -1;
> +
> +       if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
> +               serrno = errno;
> +               close(fd);
> +               errno = serrno;
> +               return -1;
> +       }
> +       return fd;
> +}
> +
>  int
>  main(int argc, char *argv[])
>  {
> @@ -639,6 +674,7 @@ main(int argc, char *argv[])
>                 errx(1, "need root privileges");
>  
>         log_init(foreground_log, LOG_MAIL);
> +       log_setverbose(tracing & TRACE_DEBUG ? 2: 1);
>         log_trace_verbose(tracing);
>         load_pki_tree();
>         load_pki_keys();
> @@ -2122,6 +2158,8 @@ imsg_to_str(int type)
>         CASE(IMSG_CA_RSA_PRIVENC);
>         CASE(IMSG_CA_RSA_PRIVDEC);
>         CASE(IMSG_CA_ECDSA_SIGN);
> +
> +       CASE(IMSG_AGENTX_GETFD);
>         default:
>                 (void)snprintf(buf, sizeof(buf), "IMSG_??? (%d)", type);
>  
> Index: smtpd.conf.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd.conf.5,v
> retrieving revision 1.260
> diff -u -p -r1.260 smtpd.conf.5
> --- smtpd.conf.5        9 Apr 2021 16:43:43 -0000       1.260
> +++ smtpd.conf.5        29 Apr 2021 05:22:14 -0000
> @@ -338,6 +338,33 @@ The Administrative Management Domain thi
>  The authservid will be forwarded to filters using it to identify or mark
>  authentication-results headers.
>  If omitted it defaults to the server name.
> +.It Ic agentx Oo Cm applIndex Ar index Oc Oo Cm context Ar context Oc Op Cm 
> path Ar path
> +Export NETWORK-SERVICES-MIB and MTA-MIB metrics via an agentx compatible
> +.Pq snmp
> +daemon by connecting to
> +.Ar path .
> +Metrics can be found under the application
> +.Pq mib-2.27
> +and mta subtree
> +.Pq mib-2.28 .
> +If
> +.Ar path
> +is omitted it will default to
> +.Pa /var/agentx/master .
> +The index on the applicationTable and mtaTable can be controlled via
> +.Cm applIndex .
> +For the first available index it can be set to
> +.Cm any ,
> +for a new unused entry it can be set to
> +.Cm new ,
> +and if a fixed position is desired it can be set to a number between 1 and
> +2,147,483,647.
> +If an index collision occurs because of a fixed position the metrics will 
> not be
> +exported.
> +.Cm applIndex
> +defaults to any.
> +.Ar Context
> +is the SNMPv3 context and can usually be omitted.
>  .It Ic bounce Cm warn-interval Ar delay Op , Ar delay ...
>  Send warning messages to the envelope sender when temporary delivery
>  failures cause a message to remain in the queue for longer than
> Index: smtpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
> retrieving revision 1.668
> diff -u -p -r1.668 smtpd.h
> --- smtpd.h     21 Apr 2021 07:54:10 -0000      1.668
> +++ smtpd.h     29 Apr 2021 05:22:14 -0000
> @@ -157,7 +157,7 @@ union lookup {
>   * Bump IMSG_VERSION whenever a change is made to enum imsg_type.
>   * This will ensure that we can never use a wrong version of smtpctl with 
> smtpd.
>   */
> -#define        IMSG_VERSION            16
> +#define        IMSG_VERSION            17
>  
>  enum imsg_type {
>         IMSG_NONE,
> @@ -327,6 +327,8 @@ enum imsg_type {
>         IMSG_CA_RSA_PRIVENC,
>         IMSG_CA_RSA_PRIVDEC,
>         IMSG_CA_ECDSA_SIGN,
> +
> +       IMSG_AGENTX_GETFD,
>  };
>  
>  enum smtp_proc_type {
> @@ -622,6 +624,8 @@ struct smtpd {
>         int                                     sc_srs_ttl;
>  
>         char                                   *sc_admd;
> +
> +       struct smtp_agentx                     *sc_agentx;
>  };
>  
>  #define        TRACE_DEBUG     0x0001
> @@ -858,6 +862,20 @@ struct mta_envelope {
>         char                             status[LINE_MAX];
>  };
>  
> +enum agentx_index_type {
> +       AGENTX_INDEX_TYPE_UNDEFINED,
> +       AGENTX_INDEX_TYPE_ANY,
> +       AGENTX_INDEX_TYPE_NEW,
> +       AGENTX_INDEX_TYPE_VALUE,
> +};
> +
> +struct smtp_agentx {
> +       const char                      *path;
> +       const char                      *context;
> +       enum agentx_index_type           applIndexType;
> +       uint32_t                         applIndex;
> +};
> +
>  struct mta_task {
>         TAILQ_ENTRY(mta_task)            entry;
>         struct mta_relay                *relay;
> @@ -1298,6 +1316,9 @@ void config_peer(enum smtp_proc_type);
>  int control(void);
>  int control_create_socket(void);
>  
> +/* agentx_control.c */
> +void agentx_control(void);
> +void agentx_control_fdopen(int, int);
>  
>  /* crypto.c */
>  int    crypto_setup(const char *, size_t);
> Index: smtpd/Makefile
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd/Makefile,v
> retrieving revision 1.113
> diff -u -p -r1.113 Makefile
> --- smtpd/Makefile      21 Apr 2021 07:54:10 -0000      1.113
> +++ smtpd/Makefile      29 Apr 2021 05:22:14 -0000
> @@ -4,7 +4,8 @@
>  
>  PROG=          smtpd
>  
> -SRCS=  aliases.c
> +SRCS=  agentx_control.c
> +SRCS+= aliases.c
>  SRCS+= bounce.c
>  SRCS+= ca.c
>  SRCS+= compress_backend.c
> @@ -79,8 +80,8 @@ SRCS+=                stat_ramstat.c
>  MAN=           sendmail.8 smtpd.8 smtpd.conf.5 table.5
>  BINDIR=                /usr/sbin
>  
> -LDADD+=                -levent -lutil -ltls -lssl -lcrypto -lz
> -DPADD+=                ${LIBEVENT} ${LIBUTIL} ${LIBTLS} ${LIBSSL} 
> ${LIBCRYPTO} ${LIBZ}
> +LDADD+=                -levent -lutil -ltls -lssl -lcrypto -lz -lagentx
> +DPADD+=                ${LIBEVENT} ${LIBUTIL} ${LIBTLS} ${LIBSSL} 
> ${LIBCRYPTO} ${LIBZ} ${LIBAGENTX}
>  
>  CFLAGS+=       -fstack-protector-all
>  CFLAGS+=       -I${.CURDIR}/..
> 
> 
> 



Reply via email to