Blob


1 /* $OpenBSD: agentx_control.c,v 1.8 2026/03/02 19:28:01 rsadowski Exp $ */
3 /*
4 * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
5 * Copyright (c) 2008 - 2014 Reyk Floeter <reyk@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/queue.h>
23 #include <sys/time.h>
24 #include <sys/un.h>
26 #include <netinet/in.h>
28 #include <agentx.h>
29 #include <limits.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdint.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <syslog.h>
36 #include <unistd.h>
37 #include <event.h>
38 #include <imsg.h>
40 #include "relayd.h"
41 #include "log.h"
43 #define RELAYD_MIB "1.3.6.1.4.1.30155.3"
44 #define SNMP_ELEMENT(x...) do { \
45 if (snmp_element(RELAYD_MIB x) == -1) \
46 goto done; \
47 } while (0)
49 /*
50 static struct snmp_oid hosttrapoid = {
51 { 1, 3, 6, 1, 4, 1, 30155, 3, 1, 0 },
52 10
53 };
54 */
56 #define RELAYDINFO AGENTX_ENTERPRISES, 30155, 3, 2
57 #define RELAYDREDIRECTS RELAYDINFO, 1
58 #define RELAYDREDIRECTENTRY RELAYDREDIRECTS, 1
59 #define RELAYDREDIRECTINDEX RELAYDREDIRECTENTRY, 1
60 #define RELAYDREDIRECTSTATUS RELAYDREDIRECTENTRY, 2
61 #define RELAYDREDIRECTNAME RELAYDREDIRECTENTRY, 3
62 #define RELAYDREDIRECTCNT RELAYDREDIRECTENTRY, 4
63 #define RELAYDREDIRECTAVG RELAYDREDIRECTENTRY, 5
64 #define RELAYDREDIRECTLAST RELAYDREDIRECTENTRY, 6
65 #define RELAYDREDIRECTAVGHOUR RELAYDREDIRECTENTRY, 7
66 #define RELAYDREDIRECTLASTHOUR RELAYDREDIRECTENTRY, 8
67 #define RELAYDREDIRECTAVGDAY RELAYDREDIRECTENTRY, 9
68 #define RELAYDREDIRECTLASTDAY RELAYDREDIRECTENTRY, 10
69 #define RELAYDRELAYS RELAYDINFO, 2
70 #define RELAYDRELAYENTRY RELAYDRELAYS, 1
71 #define RELAYDRELAYINDEX RELAYDRELAYENTRY, 1
72 #define RELAYDRELAYSTATUS RELAYDRELAYENTRY, 2
73 #define RELAYDRELAYNAME RELAYDRELAYENTRY, 3
74 #define RELAYDRELAYCNT RELAYDRELAYENTRY, 4
75 #define RELAYDRELAYAVG RELAYDRELAYENTRY, 5
76 #define RELAYDRELAYLAST RELAYDRELAYENTRY, 6
77 #define RELAYDRELAYAVGHOUR RELAYDRELAYENTRY, 7
78 #define RELAYDRELAYLASTHOUR RELAYDRELAYENTRY, 8
79 #define RELAYDRELAYAVGDAY RELAYDRELAYENTRY, 9
80 #define RELAYDRELAYLASTDAY RELAYDRELAYENTRY, 10
81 #define RELAYDROUTERS RELAYDINFO, 3
82 #define RELAYDROUTERENTRY RELAYDROUTERS, 1
83 #define RELAYDROUTERINDEX RELAYDROUTERENTRY, 1
84 #define RELAYDROUTERTABLEINDEX RELAYDROUTERENTRY, 2
85 #define RELAYDROUTERSTATUS RELAYDROUTERENTRY, 3
86 #define RELAYDROUTERNAME RELAYDROUTERENTRY, 4
87 #define RELAYDROUTERLABEL RELAYDROUTERENTRY, 5
88 #define RELAYDROUTERRTABLE RELAYDROUTERENTRY, 6
89 #define RELAYDNETROUTES RELAYDINFO, 4
90 #define RELAYDNETROUTEENTRY RELAYDNETROUTES, 1
91 #define RELAYDNETROUTEINDEX RELAYDNETROUTEENTRY, 1
92 #define RELAYDNETROUTEADDR RELAYDNETROUTEENTRY, 2
93 #define RELAYDNETROUTEADDRTYPE RELAYDNETROUTEENTRY, 3
94 #define RELAYDNETROUTEPREFIXLEN RELAYDNETROUTEENTRY, 4
95 #define RELAYDNETROUTEROUTERINDEX RELAYDNETROUTEENTRY, 5
96 #define RELAYDHOSTS RELAYDINFO, 5
97 #define RELAYDHOSTENTRY RELAYDHOSTS, 1
98 #define RELAYDHOSTINDEX RELAYDHOSTENTRY, 1
99 #define RELAYDHOSTPARENTINDEX RELAYDHOSTENTRY, 2
100 #define RELAYDHOSTTABLEINDEX RELAYDHOSTENTRY, 3
101 #define RELAYDHOSTNAME RELAYDHOSTENTRY, 4
102 #define RELAYDHOSTADDRESS RELAYDHOSTENTRY, 5
103 #define RELAYDHOSTADDRESSTYPE RELAYDHOSTENTRY, 6
104 #define RELAYDHOSTSTATUS RELAYDHOSTENTRY, 7
105 #define RELAYDHOSTCHECKCNT RELAYDHOSTENTRY, 8
106 #define RELAYDHOSTUPCNT RELAYDHOSTENTRY, 9
107 #define RELAYDHOSTERRNO RELAYDHOSTENTRY, 10
108 #define RELAYDSESSIONS RELAYDINFO, 6
109 #define RELAYDSESSIONENTRY RELAYDSESSIONS, 1
110 #define RELAYDSESSIONINDEX RELAYDSESSIONENTRY, 1
111 #define RELAYDSESSIONRELAYINDEX RELAYDSESSIONENTRY, 2
112 #define RELAYDSESSIONINADDR RELAYDSESSIONENTRY, 3
113 #define RELAYDSESSIONINADDRTYPE RELAYDSESSIONENTRY, 4
114 #define RELAYDSESSIONOUTADDR RELAYDSESSIONENTRY, 5
115 #define RELAYDSESSIONOUTADDRTYPE RELAYDSESSIONENTRY, 6
116 #define RELAYDSESSIONPORTIN RELAYDSESSIONENTRY, 7
117 #define RELAYDSESSIONPORTOUT RELAYDSESSIONENTRY, 8
118 #define RELAYDSESSIONAGE RELAYDSESSIONENTRY, 9
119 #define RELAYDSESSIONIDLE RELAYDSESSIONENTRY, 10
120 #define RELAYDSESSIONSTATUS RELAYDSESSIONENTRY, 11
121 #define RELAYDSESSIONPID RELAYDSESSIONENTRY, 12
122 #define RELAYDTABLES RELAYDINFO, 7
123 #define RELAYDTABLEENTRY RELAYDTABLES, 1
124 #define RELAYDTABLEINDEX RELAYDTABLEENTRY, 1
125 #define RELAYDTABLENAME RELAYDTABLEENTRY, 2
126 #define RELAYDTABLESTATUS RELAYDTABLEENTRY, 3
128 void agentx_nofd(struct agentx *, void *, int);
130 struct relayd *env;
132 struct agentx *sa = NULL;
133 struct agentx_index *relaydRedirectIdx, *relaydRelayIdx;
134 struct agentx_index *relaydRouterIdx, *relaydNetRouteIdx;
135 struct agentx_index *relaydHostIdx, *relaydSessionRelayIdx;
136 struct agentx_index *relaydSessionIdx, *relaydTableIdx;
138 struct agentx_object *relaydRedirectIndex, *relaydRedirectStatus;
139 struct agentx_object *relaydRedirectName, *relaydRedirectCnt;
140 struct agentx_object *relaydRedirectAvg, *relaydRedirectLast;
141 struct agentx_object *relaydRedirectAvgHour, *relaydRedirectLastHour;
142 struct agentx_object *relaydRedirectAvgDay, *relaydRedirectLastDay;
144 struct agentx_object *relaydRelayIndex, *relaydRelayStatus;
145 struct agentx_object *relaydRelayName, *relaydRelayCnt;
146 struct agentx_object *relaydRelayAvg, *relaydRelayLast;
147 struct agentx_object *relaydRelayAvgHour, *relaydRelayLastHour;
148 struct agentx_object *relaydRelayAvgDay, *relaydRelayLastDay;
150 struct agentx_object *relaydRouterIndex, *relaydRouterTableIndex;
151 struct agentx_object *relaydRouterStatus, *relaydRouterName;
152 struct agentx_object *relaydRouterLabel, *relaydRouterRtable;
154 struct agentx_object *relaydNetRouteIndex, *relaydNetRouteAddr;
155 struct agentx_object *relaydNetRouteAddrType, *relaydNetRoutePrefixLen;
156 struct agentx_object *relaydNetRouteRouterIndex;
158 struct agentx_object *relaydHostIndex, *relaydHostParentIndex;
159 struct agentx_object *relaydHostTableIndex, *relaydHostName;
160 struct agentx_object *relaydHostAddress, *relaydHostAddressType;
161 struct agentx_object *relaydHostStatus, *relaydHostCheckCnt;
162 struct agentx_object *relaydHostUpCnt, *relaydHostErrno;
164 struct agentx_object *relaydSessionIndex, *relaydSessionRelayIndex;
165 struct agentx_object *relaydSessionInAddr, *relaydSessionInAddrType;
166 struct agentx_object *relaydSessionOutAddr, *relaydSessionOutAddrType;
167 struct agentx_object *relaydSessionPortIn, *relaydSessionPortOut;
168 struct agentx_object *relaydSessionAge, *relaydSessionIdle;
169 struct agentx_object *relaydSessionStatus, *relaydSessionPid;
171 struct agentx_object *relaydTableIndex, *relaydTableName, *relaydTableStatus;
173 void *sstodata(struct sockaddr_storage *);
174 size_t sstolen(struct sockaddr_storage *);
176 struct rdr *agentxctl_rdr_byidx(uint32_t, enum agentx_request_type);
177 void agentxctl_redirect(struct agentx_varbind *);
178 struct relay *agentxctl_relay_byidx(uint32_t, enum agentx_request_type);
179 void agentxctl_relay(struct agentx_varbind *);
180 struct router *agentxctl_router_byidx(uint32_t, enum agentx_request_type);
181 void agentxctl_router(struct agentx_varbind *);
182 struct netroute *agentxctl_netroute_byidx(uint32_t, enum agentx_request_type);
183 void agentxctl_netroute(struct agentx_varbind *);
184 struct host *agentxctl_host_byidx(uint32_t, enum agentx_request_type);
185 void agentxctl_host(struct agentx_varbind *);
186 struct rsession *agentxctl_session_byidx(uint32_t, uint32_t,
187 enum agentx_request_type);
188 void agentxctl_session(struct agentx_varbind *);
189 struct table *agentxctl_table_byidx(uint32_t, enum agentx_request_type);
190 void agentxctl_table(struct agentx_varbind *);
192 void agentx_sock(int, short, void *);
193 #if 0
194 int snmp_element(const char *, enum snmp_type, void *, int64_t,
195 struct agentx_pdu *);
196 int snmp_string2oid(const char *, struct snmp_oid *);
197 #endif
199 void
200 agentx_init(struct relayd *nenv)
202 struct agentx_session *sas;
203 struct agentx_context *sac;
204 struct agentx_region *sar;
205 struct agentx_index *session_idxs[2];
206 static int freed;
208 agentx_log_fatal = fatalx;
209 agentx_log_warn = log_warnx;
210 agentx_log_info = log_info;
211 agentx_log_debug = log_debug;
213 env = nenv;
215 if ((env->sc_conf.flags & F_AGENTX) == 0) {
216 if (sa != NULL && !freed) {
217 agentx_free(sa);
218 freed = 1;
220 return;
222 if (sa != NULL)
223 return;
225 freed = 0;
226 if ((sa = agentx(agentx_nofd, NULL)) == NULL)
227 fatal("%s: agentx alloc", __func__);
228 if ((sas = agentx_session(sa, NULL, 0, "relayd", 0)) == NULL)
229 fatal("%s: agentx session alloc", __func__);
230 if ((sac = agentx_context(sas,
231 env->sc_conf.agentx_context[0] == '\0' ? NULL :
232 env->sc_conf.agentx_context)) == NULL)
233 fatal("%s: agentx context alloc", __func__);
234 sar = agentx_region(sac, AGENTX_OID(RELAYDINFO), 0);
235 if (sar == NULL)
236 fatal("%s: agentx region alloc", __func__);
237 if ((relaydRedirectIdx = agentx_index_integer_dynamic(sar,
238 AGENTX_OID(RELAYDREDIRECTINDEX))) == NULL ||
239 (relaydRelayIdx = agentx_index_integer_dynamic(sar,
240 AGENTX_OID(RELAYDRELAYINDEX))) == NULL ||
241 (relaydRouterIdx = agentx_index_integer_dynamic(sar,
242 AGENTX_OID(RELAYDROUTERINDEX))) == NULL ||
243 (relaydNetRouteIdx = agentx_index_integer_dynamic(sar,
244 AGENTX_OID(RELAYDNETROUTEINDEX))) == NULL ||
245 (relaydHostIdx = agentx_index_integer_dynamic(sar,
246 AGENTX_OID(RELAYDHOSTINDEX))) == NULL ||
247 (relaydSessionIdx = agentx_index_integer_dynamic(sar,
248 AGENTX_OID(RELAYDSESSIONINDEX))) == NULL ||
249 (relaydSessionRelayIdx = agentx_index_integer_dynamic(sar,
250 AGENTX_OID(RELAYDSESSIONRELAYINDEX))) == NULL ||
251 (relaydTableIdx = agentx_index_integer_dynamic(sar,
252 AGENTX_OID(RELAYDTABLEINDEX))) == NULL)
253 fatal("%s: agentx index alloc", __func__);
254 session_idxs[0] = relaydSessionRelayIdx;
255 session_idxs[1] = relaydSessionIdx;
256 if ((relaydRedirectIndex = agentx_object(sar,
257 AGENTX_OID(RELAYDREDIRECTINDEX), &relaydRedirectIdx, 1, 0,
258 agentxctl_redirect)) == NULL ||
259 (relaydRedirectStatus = agentx_object(sar,
260 AGENTX_OID(RELAYDREDIRECTSTATUS), &relaydRedirectIdx, 1, 0,
261 agentxctl_redirect)) == NULL ||
262 (relaydRedirectName = agentx_object(sar,
263 AGENTX_OID(RELAYDREDIRECTNAME), &relaydRedirectIdx, 1, 0,
264 agentxctl_redirect)) == NULL ||
265 (relaydRedirectCnt = agentx_object(sar,
266 AGENTX_OID(RELAYDREDIRECTCNT), &relaydRedirectIdx, 1, 0,
267 agentxctl_redirect)) == NULL ||
268 (relaydRedirectAvg = agentx_object(sar,
269 AGENTX_OID(RELAYDREDIRECTAVG), &relaydRedirectIdx, 1, 0,
270 agentxctl_redirect)) == NULL ||
271 (relaydRedirectLast = agentx_object(sar,
272 AGENTX_OID(RELAYDREDIRECTLAST), &relaydRedirectIdx, 1, 0,
273 agentxctl_redirect)) == NULL ||
274 (relaydRedirectAvgHour = agentx_object(sar,
275 AGENTX_OID(RELAYDREDIRECTAVGHOUR), &relaydRedirectIdx, 1, 0,
276 agentxctl_redirect)) == NULL ||
277 (relaydRedirectLastHour = agentx_object(sar,
278 AGENTX_OID(RELAYDREDIRECTLASTHOUR), &relaydRedirectIdx, 1, 0,
279 agentxctl_redirect)) == NULL ||
280 (relaydRedirectAvgDay = agentx_object(sar,
281 AGENTX_OID(RELAYDREDIRECTAVGDAY), &relaydRedirectIdx, 1, 0,
282 agentxctl_redirect)) == NULL ||
283 (relaydRedirectLastDay = agentx_object(sar,
284 AGENTX_OID(RELAYDREDIRECTLASTDAY), &relaydRedirectIdx, 1, 0,
285 agentxctl_redirect)) == NULL ||
286 (relaydRelayIndex = agentx_object(sar,
287 AGENTX_OID(RELAYDRELAYINDEX), &relaydRelayIdx, 1, 0,
288 agentxctl_relay)) == NULL ||
289 (relaydRelayStatus = agentx_object(sar,
290 AGENTX_OID(RELAYDRELAYSTATUS), &relaydRelayIdx, 1, 0,
291 agentxctl_relay)) == NULL ||
292 (relaydRelayName = agentx_object(sar,
293 AGENTX_OID(RELAYDRELAYNAME), &relaydRelayIdx, 1, 0,
294 agentxctl_relay)) == NULL ||
295 (relaydRelayCnt = agentx_object(sar,
296 AGENTX_OID(RELAYDRELAYCNT), &relaydRelayIdx, 1, 0,
297 agentxctl_relay)) == NULL ||
298 (relaydRelayAvg = agentx_object(sar,
299 AGENTX_OID(RELAYDRELAYAVG), &relaydRelayIdx, 1, 0,
300 agentxctl_relay)) == NULL ||
301 (relaydRelayLast = agentx_object(sar,
302 AGENTX_OID(RELAYDRELAYLAST), &relaydRelayIdx, 1, 0,
303 agentxctl_relay)) == NULL ||
304 (relaydRelayAvgHour = agentx_object(sar,
305 AGENTX_OID(RELAYDRELAYAVGHOUR), &relaydRelayIdx, 1, 0,
306 agentxctl_relay)) == NULL ||
307 (relaydRelayLastHour = agentx_object(sar,
308 AGENTX_OID(RELAYDRELAYLASTHOUR), &relaydRelayIdx, 1, 0,
309 agentxctl_relay)) == NULL ||
310 (relaydRelayAvgDay = agentx_object(sar,
311 AGENTX_OID(RELAYDRELAYAVGDAY), &relaydRelayIdx, 1, 0,
312 agentxctl_relay)) == NULL ||
313 (relaydRelayLastDay = agentx_object(sar,
314 AGENTX_OID(RELAYDRELAYLASTDAY), &relaydRelayIdx, 1, 0,
315 agentxctl_relay)) == NULL ||
316 (relaydRouterIndex = agentx_object(sar,
317 AGENTX_OID(RELAYDROUTERINDEX), &relaydRouterIdx, 1, 0,
318 agentxctl_router)) == NULL ||
319 (relaydRouterTableIndex = agentx_object(sar,
320 AGENTX_OID(RELAYDROUTERTABLEINDEX), &relaydRouterIdx, 1, 0,
321 agentxctl_router)) == NULL ||
322 (relaydRouterStatus = agentx_object(sar,
323 AGENTX_OID(RELAYDROUTERSTATUS), &relaydRouterIdx, 1, 0,
324 agentxctl_router)) == NULL ||
325 (relaydRouterName = agentx_object(sar,
326 AGENTX_OID(RELAYDROUTERNAME), &relaydRouterIdx, 1, 0,
327 agentxctl_router)) == NULL ||
328 (relaydRouterLabel = agentx_object(sar,
329 AGENTX_OID(RELAYDROUTERLABEL), &relaydRouterIdx, 1, 0,
330 agentxctl_router)) == NULL ||
331 (relaydRouterRtable = agentx_object(sar,
332 AGENTX_OID(RELAYDROUTERRTABLE), &relaydRouterIdx, 1, 0,
333 agentxctl_router)) == NULL ||
334 (relaydNetRouteIndex = agentx_object(sar,
335 AGENTX_OID(RELAYDNETROUTEINDEX), &relaydNetRouteIdx, 1, 0,
336 agentxctl_netroute)) == NULL ||
337 (relaydNetRouteAddr = agentx_object(sar,
338 AGENTX_OID(RELAYDNETROUTEADDR), &relaydNetRouteIdx, 1, 0,
339 agentxctl_netroute)) == NULL ||
340 (relaydNetRouteAddrType = agentx_object(sar,
341 AGENTX_OID(RELAYDNETROUTEADDRTYPE), &relaydNetRouteIdx, 1, 0,
342 agentxctl_netroute)) == NULL ||
343 (relaydNetRoutePrefixLen = agentx_object(sar,
344 AGENTX_OID(RELAYDNETROUTEPREFIXLEN), &relaydNetRouteIdx, 1, 0,
345 agentxctl_netroute)) == NULL ||
346 (relaydNetRouteRouterIndex = agentx_object(sar,
347 AGENTX_OID(RELAYDNETROUTEROUTERINDEX), &relaydNetRouteIdx, 1, 0,
348 agentxctl_netroute)) == NULL ||
349 (relaydHostIndex = agentx_object(sar,
350 AGENTX_OID(RELAYDHOSTINDEX), &relaydHostIdx, 1, 0,
351 agentxctl_host)) == NULL ||
352 (relaydHostParentIndex = agentx_object(sar,
353 AGENTX_OID(RELAYDHOSTPARENTINDEX), &relaydHostIdx, 1, 0,
354 agentxctl_host)) == NULL ||
355 (relaydHostTableIndex = agentx_object(sar,
356 AGENTX_OID(RELAYDHOSTTABLEINDEX), &relaydHostIdx, 1, 0,
357 agentxctl_host)) == NULL ||
358 (relaydHostName = agentx_object(sar,
359 AGENTX_OID(RELAYDHOSTNAME), &relaydHostIdx, 1, 0,
360 agentxctl_host)) == NULL ||
361 (relaydHostAddress = agentx_object(sar,
362 AGENTX_OID(RELAYDHOSTADDRESS), &relaydHostIdx, 1, 0,
363 agentxctl_host)) == NULL ||
364 (relaydHostAddressType = agentx_object(sar,
365 AGENTX_OID(RELAYDHOSTADDRESSTYPE), &relaydHostIdx, 1, 0,
366 agentxctl_host)) == NULL ||
367 (relaydHostStatus = agentx_object(sar,
368 AGENTX_OID(RELAYDHOSTSTATUS), &relaydHostIdx, 1, 0,
369 agentxctl_host)) == NULL ||
370 (relaydHostCheckCnt = agentx_object(sar,
371 AGENTX_OID(RELAYDHOSTCHECKCNT), &relaydHostIdx, 1, 0,
372 agentxctl_host)) == NULL ||
373 (relaydHostUpCnt = agentx_object(sar,
374 AGENTX_OID(RELAYDHOSTUPCNT), &relaydHostIdx, 1, 0,
375 agentxctl_host)) == NULL ||
376 (relaydHostErrno = agentx_object(sar,
377 AGENTX_OID(RELAYDHOSTERRNO), &relaydHostIdx, 1, 0,
378 agentxctl_host)) == NULL ||
379 (relaydSessionIndex = agentx_object(sar,
380 AGENTX_OID(RELAYDSESSIONINDEX), session_idxs, 2, 0,
381 agentxctl_session)) == NULL ||
382 (relaydSessionRelayIndex = agentx_object(sar,
383 AGENTX_OID(RELAYDSESSIONRELAYINDEX), session_idxs, 2, 0,
384 agentxctl_session)) == NULL ||
385 (relaydSessionInAddr = agentx_object(sar,
386 AGENTX_OID(RELAYDSESSIONINADDR), session_idxs, 2, 0,
387 agentxctl_session)) == NULL ||
388 (relaydSessionInAddrType = agentx_object(sar,
389 AGENTX_OID(RELAYDSESSIONINADDRTYPE), session_idxs, 2, 0,
390 agentxctl_session)) == NULL ||
391 (relaydSessionOutAddr = agentx_object(sar,
392 AGENTX_OID(RELAYDSESSIONOUTADDR), session_idxs, 2, 0,
393 agentxctl_session)) == NULL ||
394 (relaydSessionOutAddrType = agentx_object(sar,
395 AGENTX_OID(RELAYDSESSIONOUTADDRTYPE), session_idxs, 2, 0,
396 agentxctl_session)) == NULL ||
397 (relaydSessionPortIn = agentx_object(sar,
398 AGENTX_OID(RELAYDSESSIONPORTIN), session_idxs, 2, 0,
399 agentxctl_session)) == NULL ||
400 (relaydSessionPortOut = agentx_object(sar,
401 AGENTX_OID(RELAYDSESSIONPORTOUT), session_idxs, 2, 0,
402 agentxctl_session)) == NULL ||
403 (relaydSessionAge = agentx_object(sar,
404 AGENTX_OID(RELAYDSESSIONAGE), session_idxs, 2, 0,
405 agentxctl_session)) == NULL ||
406 (relaydSessionIdle = agentx_object(sar,
407 AGENTX_OID(RELAYDSESSIONIDLE), session_idxs, 2, 0,
408 agentxctl_session)) == NULL ||
409 (relaydSessionStatus = agentx_object(sar,
410 AGENTX_OID(RELAYDSESSIONSTATUS), session_idxs, 2, 0,
411 agentxctl_session)) == NULL ||
412 (relaydSessionPid = agentx_object(sar,
413 AGENTX_OID(RELAYDSESSIONPID), session_idxs, 2, 0,
414 agentxctl_session)) == NULL ||
415 (relaydTableIndex = agentx_object(sar,
416 AGENTX_OID(RELAYDTABLEINDEX), &relaydTableIdx, 1, 0,
417 agentxctl_table)) == NULL ||
418 (relaydTableName = agentx_object(sar,
419 AGENTX_OID(RELAYDTABLENAME), &relaydTableIdx, 1, 0,
420 agentxctl_table)) == NULL ||
421 (relaydTableStatus = agentx_object(sar,
422 AGENTX_OID(RELAYDTABLESTATUS), &relaydTableIdx, 1, 0,
423 agentxctl_table)) == NULL)
424 fatal("%s: agentx object alloc", __func__);
427 void
428 agentx_nofd(struct agentx *usa, void *cookie, int close)
430 if (!close)
431 proc_compose(env->sc_ps, PROC_PARENT, IMSG_AGENTXSOCK, NULL, 0);
432 else {
433 sa = NULL;
434 agentx_init(env);
435 event_del(&(env->sc_agentxev));
439 void
440 agentx_setsock(struct relayd *lenv, enum privsep_procid id)
442 struct sockaddr_un sun;
443 int s = -1;
445 if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
446 goto done;
448 bzero(&sun, sizeof(sun));
449 sun.sun_family = AF_UNIX;
450 if (strlcpy(sun.sun_path, lenv->sc_conf.agentx_path,
451 sizeof(sun.sun_path)) >= sizeof(sun.sun_path))
452 fatalx("invalid socket path");
454 if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
455 close(s);
456 s = -1;
458 done:
459 proc_compose_imsg(lenv->sc_ps, id, -1, IMSG_AGENTXSOCK, -1, s, NULL, 0);
462 void
463 agentx_getsock(struct imsg *imsg)
465 struct timeval tv = AGENTX_RECONNECT_TIMEOUT;
466 int fd;
468 fd = imsg_get_fd(imsg);
469 if (fd == -1)
470 goto retry;
472 event_del(&(env->sc_agentxev));
473 event_set(&(env->sc_agentxev), fd, EV_READ | EV_PERSIST,
474 agentx_sock, env);
475 event_add(&(env->sc_agentxev), NULL);
477 agentx_connect(sa, fd);
479 retry:
480 evtimer_set(&env->sc_agentxev, agentx_sock, env);
481 evtimer_add(&env->sc_agentxev, &tv);
484 void
485 agentx_sock(int fd, short event, void *arg)
487 if (event & EV_TIMEOUT) {
488 proc_compose(env->sc_ps, PROC_PARENT, IMSG_AGENTXSOCK, NULL, 0);
489 return;
491 if (event & EV_WRITE) {
492 event_del(&(env->sc_agentxev));
493 event_set(&(env->sc_agentxev), fd, EV_READ | EV_PERSIST,
494 agentx_sock, NULL);
495 event_add(&(env->sc_agentxev), NULL);
496 agentx_write(sa);
498 if (event & EV_READ)
499 agentx_read(sa);
500 return;
503 void *
504 sstodata(struct sockaddr_storage *ss)
506 if (ss->ss_family == AF_INET)
507 return &((struct sockaddr_in *)ss)->sin_addr;
508 if (ss->ss_family == AF_INET6)
509 return &((struct sockaddr_in6 *)ss)->sin6_addr;
510 return NULL;
513 size_t
514 sstolen(struct sockaddr_storage *ss)
516 if (ss->ss_family == AF_INET)
517 return sizeof(((struct sockaddr_in *)ss)->sin_addr);
518 if (ss->ss_family == AF_INET6)
519 return sizeof(((struct sockaddr_in6 *)ss)->sin6_addr);
520 return 0;
523 struct rdr *
524 agentxctl_rdr_byidx(uint32_t instanceidx, enum agentx_request_type type)
526 struct rdr *rdr;
528 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
529 if (rdr->conf.id == instanceidx) {
530 if (type == AGENTX_REQUEST_TYPE_GET ||
531 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
532 return rdr;
533 else
534 return TAILQ_NEXT(rdr, entry);
535 } else if (rdr->conf.id > instanceidx) {
536 if (type == AGENTX_REQUEST_TYPE_GET)
537 return NULL;
538 return rdr;
542 return NULL;
546 void
547 agentxctl_redirect(struct agentx_varbind *sav)
549 struct rdr *rdr;
551 rdr = agentxctl_rdr_byidx(agentx_varbind_get_index_integer(sav,
552 relaydRedirectIdx), agentx_varbind_request(sav));
553 if (rdr == NULL || rdr->conf.id > INT32_MAX) {
554 agentx_varbind_notfound(sav);
555 return;
557 agentx_varbind_set_index_integer(sav, relaydRedirectIdx,
558 rdr->conf.id);
559 if (agentx_varbind_get_object(sav) == relaydRedirectIndex)
560 agentx_varbind_integer(sav, rdr->conf.id);
561 else if (agentx_varbind_get_object(sav) == relaydRedirectStatus) {
562 if (rdr->conf.flags & F_DISABLE)
563 agentx_varbind_integer(sav, 1);
564 else if (rdr->conf.flags & F_DOWN)
565 agentx_varbind_integer(sav, 2);
566 else if (rdr->conf.flags & F_BACKUP)
567 agentx_varbind_integer(sav, 3);
568 else
569 agentx_varbind_integer(sav, 0);
570 } else if (agentx_varbind_get_object(sav) == relaydRedirectName)
571 agentx_varbind_string(sav, rdr->conf.name);
572 else if (agentx_varbind_get_object(sav) == relaydRedirectCnt)
573 agentx_varbind_counter64(sav, rdr->stats.cnt);
574 else if (agentx_varbind_get_object(sav) == relaydRedirectAvg)
575 agentx_varbind_gauge32(sav, rdr->stats.avg);
576 else if (agentx_varbind_get_object(sav) == relaydRedirectLast)
577 agentx_varbind_gauge32(sav, rdr->stats.last);
578 else if (agentx_varbind_get_object(sav) == relaydRedirectAvgHour)
579 agentx_varbind_gauge32(sav, rdr->stats.avg_hour);
580 else if (agentx_varbind_get_object(sav) == relaydRedirectLastHour)
581 agentx_varbind_gauge32(sav, rdr->stats.last_hour);
582 else if (agentx_varbind_get_object(sav) == relaydRedirectAvgDay)
583 agentx_varbind_gauge32(sav, rdr->stats.avg_day);
584 else if (agentx_varbind_get_object(sav) == relaydRedirectLastDay)
585 agentx_varbind_gauge32(sav, rdr->stats.last_day);
588 struct relay *
589 agentxctl_relay_byidx(uint32_t instanceidx, enum agentx_request_type type)
591 struct relay *rly;
593 TAILQ_FOREACH(rly, env->sc_relays, rl_entry) {
594 if (rly->rl_conf.id == instanceidx) {
595 if (type == AGENTX_REQUEST_TYPE_GET ||
596 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
597 return rly;
598 else
599 return TAILQ_NEXT(rly, rl_entry);
600 } else if (rly->rl_conf.id > instanceidx) {
601 if (type == AGENTX_REQUEST_TYPE_GET)
602 return NULL;
603 return rly;
607 return NULL;
610 void
611 agentxctl_relay(struct agentx_varbind *sav)
613 struct relay *rly;
614 uint64_t value = 0;
615 int i, nrelay = env->sc_conf.prefork_relay;
617 rly = agentxctl_relay_byidx(agentx_varbind_get_index_integer(sav,
618 relaydRelayIdx), agentx_varbind_request(sav));
619 if (rly == NULL || rly->rl_conf.id > INT32_MAX) {
620 agentx_varbind_notfound(sav);
621 return;
623 agentx_varbind_set_index_integer(sav, relaydRelayIdx,
624 rly->rl_conf.id);
625 if (agentx_varbind_get_object(sav) == relaydRelayIndex)
626 agentx_varbind_integer(sav, rly->rl_conf.id);
627 else if (agentx_varbind_get_object(sav) == relaydRelayStatus) {
628 if (rly->rl_up == HOST_UP)
629 agentx_varbind_integer(sav, 1);
630 else
631 agentx_varbind_integer(sav, 0);
632 } else if (agentx_varbind_get_object(sav) == relaydRelayName)
633 agentx_varbind_string(sav, rly->rl_conf.name);
634 else if (agentx_varbind_get_object(sav) == relaydRelayCnt) {
635 for (i = 0; i < nrelay; i++)
636 value += rly->rl_stats[i].cnt;
637 agentx_varbind_counter64(sav, value);
638 } else if (agentx_varbind_get_object(sav) == relaydRelayAvg) {
639 for (i = 0; i < nrelay; i++)
640 value += rly->rl_stats[i].avg;
641 agentx_varbind_gauge32(sav, (uint32_t)value);
642 } else if (agentx_varbind_get_object(sav) == relaydRelayLast) {
643 for (i = 0; i < nrelay; i++)
644 value += rly->rl_stats[i].last;
645 agentx_varbind_gauge32(sav, (uint32_t)value);
646 } else if (agentx_varbind_get_object(sav) == relaydRelayAvgHour) {
647 for (i = 0; i < nrelay; i++)
648 value += rly->rl_stats[i].avg_hour;
649 agentx_varbind_gauge32(sav, (uint32_t)value);
650 } else if (agentx_varbind_get_object(sav) == relaydRelayLastHour) {
651 for (i = 0; i < nrelay; i++)
652 value += rly->rl_stats[i].last_hour;
653 agentx_varbind_gauge32(sav, (uint32_t)value);
654 } else if (agentx_varbind_get_object(sav) == relaydRelayAvgDay) {
655 for (i = 0; i < nrelay; i++)
656 value += rly->rl_stats[i].avg_day;
657 agentx_varbind_gauge32(sav, (uint32_t)value);
658 } else if (agentx_varbind_get_object(sav) == relaydRelayLastDay) {
659 for (i = 0; i < nrelay; i++)
660 value += rly->rl_stats[i].last_day;
661 agentx_varbind_gauge32(sav, (uint32_t)value);
665 struct router *
666 agentxctl_router_byidx(uint32_t instanceidx, enum agentx_request_type type)
668 struct router *router;
670 TAILQ_FOREACH(router, env->sc_rts, rt_entry) {
671 if (router->rt_conf.id == instanceidx) {
672 if (type == AGENTX_REQUEST_TYPE_GET ||
673 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
674 return router;
675 else
676 return TAILQ_NEXT(router, rt_entry);
677 } else if (router->rt_conf.id > instanceidx) {
678 if (type == AGENTX_REQUEST_TYPE_GET)
679 return NULL;
680 return router;
684 return NULL;
687 void
688 agentxctl_router(struct agentx_varbind *sav)
690 struct router *router;
692 router = agentxctl_router_byidx(agentx_varbind_get_index_integer(sav,
693 relaydRouterIdx), agentx_varbind_request(sav));
694 if (router == NULL || router->rt_conf.id > INT32_MAX) {
695 agentx_varbind_notfound(sav);
696 return;
698 agentx_varbind_set_index_integer(sav, relaydRouterIdx,
699 router->rt_conf.id);
700 if (agentx_varbind_get_object(sav) == relaydRouterIndex)
701 agentx_varbind_integer(sav, router->rt_conf.id);
702 else if (agentx_varbind_get_object(sav) == relaydRouterTableIndex) {
703 if (router->rt_conf.gwtable > INT32_MAX)
704 agentx_varbind_integer(sav, -1);
705 else
706 agentx_varbind_integer(sav, router->rt_conf.gwtable);
707 } else if (agentx_varbind_get_object(sav) == relaydRouterStatus) {
708 if (router->rt_conf.flags & F_DISABLE)
709 agentx_varbind_integer(sav, 1);
710 else
711 agentx_varbind_integer(sav, 0);
712 } else if (agentx_varbind_get_object(sav) == relaydRouterName)
713 agentx_varbind_string(sav, router->rt_conf.name);
714 else if (agentx_varbind_get_object(sav) == relaydRouterLabel)
715 agentx_varbind_string(sav, router->rt_conf.label);
716 else if (agentx_varbind_get_object(sav) == relaydRouterRtable)
717 agentx_varbind_integer(sav, router->rt_conf.rtable);
720 struct netroute *
721 agentxctl_netroute_byidx(uint32_t instanceidx, enum agentx_request_type type)
723 struct netroute *nr;
725 TAILQ_FOREACH(nr, env->sc_routes, nr_route) {
726 if (nr->nr_conf.id == instanceidx) {
727 if (type == AGENTX_REQUEST_TYPE_GET ||
728 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
729 return nr;
730 else
731 return TAILQ_NEXT(nr, nr_entry);
732 } else if (nr->nr_conf.id > instanceidx) {
733 if (type == AGENTX_REQUEST_TYPE_GET)
734 return NULL;
735 return nr;
739 return NULL;
742 void
743 agentxctl_netroute(struct agentx_varbind *sav)
745 struct netroute *nr;
747 nr = agentxctl_netroute_byidx(agentx_varbind_get_index_integer(sav,
748 relaydNetRouteIdx), agentx_varbind_request(sav));
749 if (nr == NULL || nr->nr_conf.id > INT32_MAX) {
750 agentx_varbind_notfound(sav);
751 return;
753 agentx_varbind_set_index_integer(sav, relaydNetRouteIdx,
754 nr->nr_conf.id);
755 if (agentx_varbind_get_object(sav) == relaydNetRouteIndex)
756 agentx_varbind_integer(sav, nr->nr_conf.id);
757 else if (agentx_varbind_get_object(sav) == relaydNetRouteAddr)
758 agentx_varbind_nstring(sav, sstodata(&nr->nr_conf.ss),
759 sstolen(&nr->nr_conf.ss));
760 else if (agentx_varbind_get_object(sav) == relaydNetRouteAddrType) {
761 if (nr->nr_conf.ss.ss_family == AF_INET)
762 agentx_varbind_integer(sav, 1);
763 else if (nr->nr_conf.ss.ss_family == AF_INET6)
764 agentx_varbind_integer(sav, 2);
765 } else if (agentx_varbind_get_object(sav) == relaydNetRoutePrefixLen)
766 agentx_varbind_integer(sav, nr->nr_conf.prefixlen);
767 else if (agentx_varbind_get_object(sav) == relaydNetRouteRouterIndex) {
768 if (nr->nr_conf.routerid > INT32_MAX)
769 agentx_varbind_integer(sav, -1);
770 else
771 agentx_varbind_integer(sav, nr->nr_conf.routerid);
775 struct host *
776 agentxctl_host_byidx(uint32_t instanceidx, enum agentx_request_type type)
778 struct host *host;
780 TAILQ_FOREACH(host, &(env->sc_hosts), globalentry) {
781 if (host->conf.id == instanceidx) {
782 if (type == AGENTX_REQUEST_TYPE_GET ||
783 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
784 return host;
785 else
786 return TAILQ_NEXT(host, globalentry);
787 } else if (host->conf.id > instanceidx) {
788 if (type == AGENTX_REQUEST_TYPE_GET)
789 return NULL;
790 return host;
794 return NULL;
797 void
798 agentxctl_host(struct agentx_varbind *sav)
800 struct host *host;
802 host = agentxctl_host_byidx(agentx_varbind_get_index_integer(sav,
803 relaydHostIdx), agentx_varbind_request(sav));
804 if (host == NULL || host->conf.id > INT32_MAX) {
805 agentx_varbind_notfound(sav);
806 return;
808 agentx_varbind_set_index_integer(sav, relaydHostIdx,
809 host->conf.id);
810 if (agentx_varbind_get_object(sav) == relaydHostIndex)
811 agentx_varbind_integer(sav, host->conf.id);
812 else if (agentx_varbind_get_object(sav) == relaydHostParentIndex) {
813 if (host->conf.parentid > INT32_MAX)
814 agentx_varbind_integer(sav, -1);
815 else
816 agentx_varbind_integer(sav, host->conf.parentid);
817 } else if (agentx_varbind_get_object(sav) == relaydHostTableIndex) {
818 if (host->conf.tableid > INT32_MAX)
819 agentx_varbind_integer(sav, -1);
820 else
821 agentx_varbind_integer(sav, host->conf.tableid);
822 } else if (agentx_varbind_get_object(sav) == relaydHostName)
823 agentx_varbind_string(sav, host->conf.name);
824 else if (agentx_varbind_get_object(sav) == relaydHostAddress)
825 agentx_varbind_nstring(sav, sstodata(&host->conf.ss),
826 sstolen(&host->conf.ss));
827 else if (agentx_varbind_get_object(sav) == relaydHostAddressType) {
828 if (host->conf.ss.ss_family == AF_INET)
829 agentx_varbind_integer(sav, 1);
830 else if (host->conf.ss.ss_family == AF_INET6)
831 agentx_varbind_integer(sav, 2);
832 } else if (agentx_varbind_get_object(sav) == relaydHostStatus) {
833 if (host->flags & F_DISABLE)
834 agentx_varbind_integer(sav, 1);
835 else if (host->up == HOST_UP)
836 agentx_varbind_integer(sav, 0);
837 else if (host->up == HOST_DOWN)
838 agentx_varbind_integer(sav, 2);
839 else
840 agentx_varbind_integer(sav, 3);
841 } else if (agentx_varbind_get_object(sav) == relaydHostCheckCnt)
842 agentx_varbind_counter64(sav, host->check_cnt);
843 else if (agentx_varbind_get_object(sav) == relaydHostUpCnt)
844 agentx_varbind_counter64(sav, host->up_cnt);
845 else if (agentx_varbind_get_object(sav) == relaydHostErrno)
846 agentx_varbind_integer(sav, host->he);
849 /*
850 * Every session is spawned in one of multiple processes.
851 * However, there is no central session id registration, so not every session
852 * is shown here
853 */
854 struct rsession *
855 agentxctl_session_byidx(uint32_t sessidx, uint32_t relayidx,
856 enum agentx_request_type type)
858 struct rsession *session;
860 TAILQ_FOREACH(session, &(env->sc_sessions), se_entry) {
861 if (session->se_id == sessidx) {
862 if (type == AGENTX_REQUEST_TYPE_GET) {
863 if (relayidx != session->se_relayid)
864 return NULL;
865 return session;
867 if (type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) {
868 if (relayidx <= session->se_relayid)
869 return session;
870 return TAILQ_NEXT(session, se_entry);
872 if (relayidx < session->se_relayid)
873 return session;
874 return TAILQ_NEXT(session, se_entry);
875 } else if (session->se_id > sessidx) {
876 if (type == AGENTX_REQUEST_TYPE_GET)
877 return NULL;
878 return session;
882 return NULL;
885 void
886 agentxctl_session(struct agentx_varbind *sav)
888 struct timeval tv, now;
889 struct rsession *session;
891 session = agentxctl_session_byidx(agentx_varbind_get_index_integer(sav,
892 relaydSessionIdx), agentx_varbind_get_index_integer(sav,
893 relaydSessionRelayIdx), agentx_varbind_request(sav));
894 if (session == NULL || session->se_id > INT32_MAX ||
895 session->se_relayid > INT32_MAX) {
896 agentx_varbind_notfound(sav);
897 return;
900 agentx_varbind_set_index_integer(sav, relaydSessionIdx,
901 session->se_id);
902 agentx_varbind_set_index_integer(sav, relaydSessionRelayIdx,
903 session->se_relayid);
904 if (agentx_varbind_get_object(sav) == relaydSessionIndex)
905 agentx_varbind_integer(sav, session->se_id);
906 else if (agentx_varbind_get_object(sav) == relaydSessionRelayIndex)
907 agentx_varbind_integer(sav, session->se_relayid);
908 else if (agentx_varbind_get_object(sav) == relaydSessionInAddr)
909 agentx_varbind_nstring(sav, sstodata(&(session->se_in.ss)),
910 sstolen(&(session->se_in.ss)));
911 else if (agentx_varbind_get_object(sav) == relaydSessionInAddrType) {
912 if (session->se_in.ss.ss_family == AF_INET)
913 agentx_varbind_integer(sav, 1);
914 else if (session->se_in.ss.ss_family == AF_INET6)
915 agentx_varbind_integer(sav, 2);
916 } else if (agentx_varbind_get_object(sav) == relaydSessionOutAddr)
917 agentx_varbind_nstring(sav, sstodata(&(session->se_out.ss)),
918 sstolen(&(session->se_out.ss)));
919 else if (agentx_varbind_get_object(sav) == relaydSessionOutAddrType) {
920 if (session->se_out.ss.ss_family == AF_INET)
921 agentx_varbind_integer(sav, 1);
922 else if (session->se_out.ss.ss_family == AF_INET6)
923 agentx_varbind_integer(sav, 2);
924 else
925 agentx_varbind_integer(sav, 0);
926 } else if (agentx_varbind_get_object(sav) == relaydSessionPortIn)
927 agentx_varbind_integer(sav, session->se_in.port);
928 else if (agentx_varbind_get_object(sav) == relaydSessionPortOut)
929 agentx_varbind_integer(sav, session->se_out.port);
930 else if (agentx_varbind_get_object(sav) == relaydSessionAge) {
931 getmonotime(&now);
932 timersub(&now, &session->se_tv_start, &tv);
933 agentx_varbind_timeticks(sav,
934 tv.tv_sec * 100 + tv.tv_usec / 10000);
935 } else if (agentx_varbind_get_object(sav) == relaydSessionIdle) {
936 getmonotime(&now);
937 timersub(&now, &session->se_tv_last, &tv);
938 agentx_varbind_timeticks(sav,
939 tv.tv_sec * 100 + tv.tv_usec / 10000);
940 } else if (agentx_varbind_get_object(sav) == relaydSessionStatus) {
941 if (session->se_done)
942 agentx_varbind_integer(sav, 1);
943 else
944 agentx_varbind_integer(sav, 0);
945 } else if (agentx_varbind_get_object(sav) == relaydSessionPid)
946 agentx_varbind_integer(sav, session->se_pid);
949 struct table *
950 agentxctl_table_byidx(uint32_t instanceidx, enum agentx_request_type type)
952 struct table *table;
954 TAILQ_FOREACH(table, env->sc_tables, entry) {
955 if (table->conf.id == instanceidx) {
956 if (type == AGENTX_REQUEST_TYPE_GET ||
957 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)
958 return table;
959 else
960 return TAILQ_NEXT(table, entry);
961 } else if (table->conf.id > instanceidx) {
962 if (type == AGENTX_REQUEST_TYPE_GET)
963 return NULL;
964 return table;
968 return NULL;
971 void
972 agentxctl_table(struct agentx_varbind *sav)
974 struct table *table;
976 table = agentxctl_table_byidx(agentx_varbind_get_index_integer(sav,
977 relaydTableIdx), agentx_varbind_request(sav));
978 if (table == NULL || table->conf.id > INT32_MAX) {
979 agentx_varbind_notfound(sav);
980 return;
982 agentx_varbind_set_index_integer(sav, relaydTableIdx,
983 table->conf.id);
984 if (agentx_varbind_get_object(sav) == relaydTableIndex)
985 agentx_varbind_integer(sav, table->conf.id);
986 else if (agentx_varbind_get_object(sav) == relaydTableName)
987 agentx_varbind_string(sav, table->conf.name);
988 else if (agentx_varbind_get_object(sav) == relaydTableStatus) {
989 if (TAILQ_EMPTY(&table->hosts))
990 agentx_varbind_integer(sav, 1);
991 else if (table->conf.flags & F_DISABLE)
992 agentx_varbind_integer(sav, 2);
993 else
994 agentx_varbind_integer(sav, 0);
998 #if 0
1000 int
1001 snmp_element(const char *oidstr, enum snmp_type type, void *buf, int64_t val,
1002 struct agentx_pdu *pdu)
1004 u_int32_t d;
1005 u_int64_t l;
1006 struct snmp_oid oid;
1008 DPRINTF("%s: oid %s type %d buf %p val %lld", __func__,
1009 oidstr, type, buf, val);
1011 if (snmp_string2oid(oidstr, &oid) == -1)
1012 return -1;
1014 switch (type) {
1015 case SNMP_GAUGE32:
1016 case SNMP_NSAPADDR:
1017 case SNMP_INTEGER32:
1018 case SNMP_UINTEGER32:
1019 d = (u_int32_t)val;
1020 if (snmp_agentx_varbind(pdu, &oid, AGENTX_INTEGER,
1021 &d, sizeof(d)) == -1)
1022 return -1;
1023 break;
1025 case SNMP_COUNTER32:
1026 d = (u_int32_t)val;
1027 if (snmp_agentx_varbind(pdu, &oid, AGENTX_COUNTER32,
1028 &d, sizeof(d)) == -1)
1029 return -1;
1030 break;
1032 case SNMP_TIMETICKS:
1033 d = (u_int32_t)val;
1034 if (snmp_agentx_varbind(pdu, &oid, AGENTX_TIME_TICKS,
1035 &d, sizeof(d)) == -1)
1036 return -1;
1037 break;
1039 case SNMP_COUNTER64:
1040 l = (u_int64_t)val;
1041 if (snmp_agentx_varbind(pdu, &oid, AGENTX_COUNTER64,
1042 &l, sizeof(l)) == -1)
1043 return -1;
1044 break;
1046 case SNMP_IPADDR:
1047 case SNMP_OPAQUE:
1048 d = (u_int32_t)val;
1049 if (snmp_agentx_varbind(pdu, &oid, AGENTX_OPAQUE,
1050 buf, strlen(buf)) == -1)
1051 return -1;
1052 break;
1054 case SNMP_OBJECT: {
1055 struct snmp_oid oid1;
1057 if (snmp_string2oid(buf, &oid1) == -1)
1058 return -1;
1059 if (snmp_agentx_varbind(pdu, &oid, AGENTX_OBJECT_IDENTIFIER,
1060 &oid1, sizeof(oid1)) == -1)
1061 return -1;
1064 case SNMP_BITSTRING:
1065 case SNMP_OCTETSTRING:
1066 if (snmp_agentx_varbind(pdu, &oid, AGENTX_OCTET_STRING,
1067 buf, strlen(buf)) == -1)
1068 return -1;
1069 break;
1071 case SNMP_NULL:
1072 /* no data beyond the OID itself */
1073 if (snmp_agentx_varbind(pdu, &oid, AGENTX_NULL,
1074 NULL, 0) == -1)
1075 return -1;
1078 return 0;
1082 * SNMP traps for relayd
1085 void
1086 snmp_hosttrap(struct relayd *env, struct table *table, struct host *host)
1088 struct agentx_pdu *pdu;
1090 if (snmp_agentx == NULL || env->sc_snmp == -1)
1091 return;
1094 * OPENBSD-RELAYD-MIB host status trap
1095 * XXX The trap format needs some tweaks and other OIDs
1098 if ((pdu = snmp_agentx_notify_pdu(&hosttrapoid)) == NULL)
1099 return;
1101 SNMP_ELEMENT(".1.0", SNMP_NULL, NULL, 0, pdu);
1102 SNMP_ELEMENT(".1.1.0", SNMP_OCTETSTRING, host->conf.name, 0, pdu);
1103 SNMP_ELEMENT(".1.2.0", SNMP_INTEGER32, NULL, host->up, pdu);
1104 SNMP_ELEMENT(".1.3.0", SNMP_INTEGER32, NULL, host->last_up, pdu);
1105 SNMP_ELEMENT(".1.4.0", SNMP_INTEGER32, NULL, host->up_cnt, pdu);
1106 SNMP_ELEMENT(".1.5.0", SNMP_INTEGER32, NULL, host->check_cnt, pdu);
1107 SNMP_ELEMENT(".1.6.0", SNMP_OCTETSTRING, table->conf.name, 0, pdu);
1108 SNMP_ELEMENT(".1.7.0", SNMP_INTEGER32, NULL, table->up, pdu);
1109 if (!host->conf.retry)
1110 goto done;
1111 SNMP_ELEMENT(".1.8.0", SNMP_INTEGER32, NULL, host->conf.retry, pdu);
1112 SNMP_ELEMENT(".1.9.0", SNMP_INTEGER32, NULL, host->retry_cnt, pdu);
1114 done:
1115 snmp_agentx_send(snmp_agentx, pdu);
1116 snmp_event_add(env, EV_WRITE);
1119 int
1120 snmp_string2oid(const char *oidstr, struct snmp_oid *o)
1122 char *sp, *p, str[BUFSIZ];
1123 const char *errstr;
1125 if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
1126 return -1;
1127 bzero(o, sizeof(*o));
1129 for (p = sp = str; p != NULL; sp = p) {
1130 if ((p = strpbrk(p, ".-")) != NULL)
1131 *p++ = '\0';
1132 o->o_id[o->o_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
1133 if (errstr || o->o_n > SNMP_MAX_OID_LEN)
1134 return -1;
1137 return 0;
1139 #endif