/* $OpenBSD: mib.c,v 1.9 2024/05/22 08:44:02 martijn Exp $ */ /* * Copyright (c) 2025 Wolfgang Hottgenroth * Copyright (c) 2022 Martijn van Duren * Copyright (c) 2012 Joel Knight * Copyright (c) 2007, 2008, 2012 Reyk Floeter * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include MUST BE INCLUDED ONLY ONCE, WILL BE INCLUDED IN mib.h #include "mib.h" #include "log.h" struct event connev; void snmp_connect(struct agentx *, void *, int); void snmp_tryconnect(int, short, void *); void snmp_read(int, short, void *); int main(int argc, char *argv[]) { struct agentx *sa; struct agentx_context *sac; struct agentx_session *sas; struct passwd *pw; struct group *gr; int ch; int verbose = 0, daemonize = 1; log_init(2, LOG_DAEMON); agentx_log_fatal = fatalx; agentx_log_warn = log_warnx; agentx_log_info = log_info; agentx_log_debug = log_debug; while ((ch = getopt(argc, argv, "dv")) != -1) { switch (ch) { case 'd': daemonize = 0; break; case 'v': verbose++; break; default: fatalx("usage: subagent_ntpd [-dv]\n"); } } if ((pw = getpwnam("_snmpd")) == NULL) fatal("can't find _snmpd user"); if ((gr = getgrnam("_agentx")) == NULL) fatal("can't find _agentx group"); event_init(); if ((sa = agentx(snmp_connect, NULL)) == NULL) fatal("agentx"); if ((sas = agentx_session(sa, NULL, 0, "Hottis NTP Metrics for OpenNTPD", 0)) == NULL) fatal("agentx_session"); if ((sac = agentx_context(sas, NULL)) == NULL) fatal("agentx_context"); /* Can't pledge: kvm_getfiles */ if (unveil(NULL, NULL) == -1) fatal("unveil"); if (setgid(gr->gr_gid) == -1) fatal("setgid"); if (setuid(pw->pw_uid) == -1) fatal("setuid"); mib_register(sac); if (daemonize) { log_init(0, LOG_DAEMON); daemon(0, 0); } log_setverbose(verbose); event_dispatch(); } void snmp_connect(struct agentx *sa, void *cookie, int close) { if (close) { event_del(&connev); return; } snmp_tryconnect(-1, 0, sa); } void snmp_tryconnect(int fd, short event, void *cookie) { struct timeval timeout = {3, 0}; struct agentx *sa = cookie; struct sockaddr_un sun; sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; strlcpy(sun.sun_path, AGENTX_MASTER_PATH, sizeof(sun.sun_path)); if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 || connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { if (fd != -1) close(fd); log_warn("Failed to connect to snmpd"); evtimer_set(&connev, snmp_tryconnect, sa); evtimer_add(&connev, &timeout); return; } event_set(&connev, fd, EV_READ | EV_PERSIST, snmp_read, sa); event_add(&connev, NULL); agentx_connect(sa, fd); } void snmp_read(int fd, short event, void *cookie) { struct agentx *sa = cookie; agentx_read(sa); }