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