1 /* $OpenBSD: agentx_control.c,v 1.6 2022/08/31 16:17:18 dv 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 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 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 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 462 agentx_getsock(struct imsg *imsg) 463 { 464 struct timeval tv = AGENTX_RECONNECT_TIMEOUT; 465 466 if (imsg->fd == -1) 467 goto retry; 468 469 event_del(&(env->sc_agentxev)); 470 event_set(&(env->sc_agentxev), imsg->fd, EV_READ | EV_PERSIST, 471 agentx_sock, env); 472 event_add(&(env->sc_agentxev), NULL); 473 474 agentx_connect(sa, imsg->fd); 475 476 retry: 477 evtimer_set(&env->sc_agentxev, agentx_sock, env); 478 evtimer_add(&env->sc_agentxev, &tv); 479 } 480 481 void 482 agentx_sock(int fd, short event, void *arg) 483 { 484 if (event & EV_TIMEOUT) { 485 proc_compose(env->sc_ps, PROC_PARENT, IMSG_AGENTXSOCK, NULL, 0); 486 return; 487 } 488 if (event & EV_WRITE) { 489 event_del(&(env->sc_agentxev)); 490 event_set(&(env->sc_agentxev), fd, EV_READ | EV_PERSIST, 491 agentx_sock, NULL); 492 event_add(&(env->sc_agentxev), NULL); 493 agentx_write(sa); 494 } 495 if (event & EV_READ) 496 agentx_read(sa); 497 return; 498 } 499 500 void * 501 sstodata(struct sockaddr_storage *ss) 502 { 503 if (ss->ss_family == AF_INET) 504 return &((struct sockaddr_in *)ss)->sin_addr; 505 if (ss->ss_family == AF_INET6) 506 return &((struct sockaddr_in6 *)ss)->sin6_addr; 507 return NULL; 508 } 509 510 size_t 511 sstolen(struct sockaddr_storage *ss) 512 { 513 if (ss->ss_family == AF_INET) 514 return sizeof(((struct sockaddr_in *)ss)->sin_addr); 515 if (ss->ss_family == AF_INET6) 516 return sizeof(((struct sockaddr_in6 *)ss)->sin6_addr); 517 return 0; 518 } 519 520 struct rdr * 521 agentxctl_rdr_byidx(uint32_t instanceidx, enum agentx_request_type type) 522 { 523 struct rdr *rdr; 524 525 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) { 526 if (rdr->conf.id == instanceidx) { 527 if (type == AGENTX_REQUEST_TYPE_GET || 528 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) 529 return rdr; 530 else 531 return TAILQ_NEXT(rdr, entry); 532 } else if (rdr->conf.id > instanceidx) { 533 if (type == AGENTX_REQUEST_TYPE_GET) 534 return NULL; 535 return rdr; 536 } 537 } 538 539 return NULL; 540 } 541 542 543 void 544 agentxctl_redirect(struct agentx_varbind *sav) 545 { 546 struct rdr *rdr; 547 548 rdr = agentxctl_rdr_byidx(agentx_varbind_get_index_integer(sav, 549 relaydRedirectIdx), agentx_varbind_request(sav)); 550 if (rdr == NULL || rdr->conf.id > INT32_MAX) { 551 agentx_varbind_notfound(sav); 552 return; 553 } 554 agentx_varbind_set_index_integer(sav, relaydRedirectIdx, 555 rdr->conf.id); 556 if (agentx_varbind_get_object(sav) == relaydRedirectIndex) 557 agentx_varbind_integer(sav, rdr->conf.id); 558 else if (agentx_varbind_get_object(sav) == relaydRedirectStatus) { 559 if (rdr->conf.flags & F_DISABLE) 560 agentx_varbind_integer(sav, 1); 561 else if (rdr->conf.flags & F_DOWN) 562 agentx_varbind_integer(sav, 2); 563 else if (rdr->conf.flags & F_BACKUP) 564 agentx_varbind_integer(sav, 3); 565 else 566 agentx_varbind_integer(sav, 0); 567 } else if (agentx_varbind_get_object(sav) == relaydRedirectName) 568 agentx_varbind_string(sav, rdr->conf.name); 569 else if (agentx_varbind_get_object(sav) == relaydRedirectCnt) 570 agentx_varbind_counter64(sav, rdr->stats.cnt); 571 else if (agentx_varbind_get_object(sav) == relaydRedirectAvg) 572 agentx_varbind_gauge32(sav, rdr->stats.avg); 573 else if (agentx_varbind_get_object(sav) == relaydRedirectLast) 574 agentx_varbind_gauge32(sav, rdr->stats.last); 575 else if (agentx_varbind_get_object(sav) == relaydRedirectAvgHour) 576 agentx_varbind_gauge32(sav, rdr->stats.avg_hour); 577 else if (agentx_varbind_get_object(sav) == relaydRedirectLastHour) 578 agentx_varbind_gauge32(sav, rdr->stats.last_hour); 579 else if (agentx_varbind_get_object(sav) == relaydRedirectAvgDay) 580 agentx_varbind_gauge32(sav, rdr->stats.avg_day); 581 else if (agentx_varbind_get_object(sav) == relaydRedirectLastDay) 582 agentx_varbind_gauge32(sav, rdr->stats.last_day); 583 } 584 585 struct relay * 586 agentxctl_relay_byidx(uint32_t instanceidx, enum agentx_request_type type) 587 { 588 struct relay *rly; 589 590 TAILQ_FOREACH(rly, env->sc_relays, rl_entry) { 591 if (rly->rl_conf.id == instanceidx) { 592 if (type == AGENTX_REQUEST_TYPE_GET || 593 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) 594 return rly; 595 else 596 return TAILQ_NEXT(rly, rl_entry); 597 } else if (rly->rl_conf.id > instanceidx) { 598 if (type == AGENTX_REQUEST_TYPE_GET) 599 return NULL; 600 return rly; 601 } 602 } 603 604 return NULL; 605 } 606 607 void 608 agentxctl_relay(struct agentx_varbind *sav) 609 { 610 struct relay *rly; 611 uint64_t value = 0; 612 int i, nrelay = env->sc_conf.prefork_relay; 613 614 rly = agentxctl_relay_byidx(agentx_varbind_get_index_integer(sav, 615 relaydRelayIdx), agentx_varbind_request(sav)); 616 if (rly == NULL || rly->rl_conf.id > INT32_MAX) { 617 agentx_varbind_notfound(sav); 618 return; 619 } 620 agentx_varbind_set_index_integer(sav, relaydRelayIdx, 621 rly->rl_conf.id); 622 if (agentx_varbind_get_object(sav) == relaydRelayIndex) 623 agentx_varbind_integer(sav, rly->rl_conf.id); 624 else if (agentx_varbind_get_object(sav) == relaydRelayStatus) { 625 if (rly->rl_up == HOST_UP) 626 agentx_varbind_integer(sav, 1); 627 else 628 agentx_varbind_integer(sav, 0); 629 } else if (agentx_varbind_get_object(sav) == relaydRelayName) 630 agentx_varbind_string(sav, rly->rl_conf.name); 631 else if (agentx_varbind_get_object(sav) == relaydRelayCnt) { 632 for (i = 0; i < nrelay; i++) 633 value += rly->rl_stats[i].cnt; 634 agentx_varbind_counter64(sav, value); 635 } else if (agentx_varbind_get_object(sav) == relaydRelayAvg) { 636 for (i = 0; i < nrelay; i++) 637 value += rly->rl_stats[i].avg; 638 agentx_varbind_gauge32(sav, (uint32_t)value); 639 } else if (agentx_varbind_get_object(sav) == relaydRelayLast) { 640 for (i = 0; i < nrelay; i++) 641 value += rly->rl_stats[i].last; 642 agentx_varbind_gauge32(sav, (uint32_t)value); 643 } else if (agentx_varbind_get_object(sav) == relaydRelayAvgHour) { 644 for (i = 0; i < nrelay; i++) 645 value += rly->rl_stats[i].avg_hour; 646 agentx_varbind_gauge32(sav, (uint32_t)value); 647 } else if (agentx_varbind_get_object(sav) == relaydRelayLastHour) { 648 for (i = 0; i < nrelay; i++) 649 value += rly->rl_stats[i].last_hour; 650 agentx_varbind_gauge32(sav, (uint32_t)value); 651 } else if (agentx_varbind_get_object(sav) == relaydRelayAvgDay) { 652 for (i = 0; i < nrelay; i++) 653 value += rly->rl_stats[i].avg_day; 654 agentx_varbind_gauge32(sav, (uint32_t)value); 655 } else if (agentx_varbind_get_object(sav) == relaydRelayLastDay) { 656 for (i = 0; i < nrelay; i++) 657 value += rly->rl_stats[i].last_day; 658 agentx_varbind_gauge32(sav, (uint32_t)value); 659 } 660 } 661 662 struct router * 663 agentxctl_router_byidx(uint32_t instanceidx, enum agentx_request_type type) 664 { 665 struct router *router; 666 667 TAILQ_FOREACH(router, env->sc_rts, rt_entry) { 668 if (router->rt_conf.id == instanceidx) { 669 if (type == AGENTX_REQUEST_TYPE_GET || 670 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) 671 return router; 672 else 673 return TAILQ_NEXT(router, rt_entry); 674 } else if (router->rt_conf.id > instanceidx) { 675 if (type == AGENTX_REQUEST_TYPE_GET) 676 return NULL; 677 return router; 678 } 679 } 680 681 return NULL; 682 } 683 684 void 685 agentxctl_router(struct agentx_varbind *sav) 686 { 687 struct router *router; 688 689 router = agentxctl_router_byidx(agentx_varbind_get_index_integer(sav, 690 relaydRouterIdx), agentx_varbind_request(sav)); 691 if (router == NULL || router->rt_conf.id > INT32_MAX) { 692 agentx_varbind_notfound(sav); 693 return; 694 } 695 agentx_varbind_set_index_integer(sav, relaydRouterIdx, 696 router->rt_conf.id); 697 if (agentx_varbind_get_object(sav) == relaydRouterIndex) 698 agentx_varbind_integer(sav, router->rt_conf.id); 699 else if (agentx_varbind_get_object(sav) == relaydRouterTableIndex) { 700 if (router->rt_conf.gwtable > INT32_MAX) 701 agentx_varbind_integer(sav, -1); 702 else 703 agentx_varbind_integer(sav, router->rt_conf.gwtable); 704 } else if (agentx_varbind_get_object(sav) == relaydRouterStatus) { 705 if (router->rt_conf.flags & F_DISABLE) 706 agentx_varbind_integer(sav, 1); 707 else 708 agentx_varbind_integer(sav, 0); 709 } else if (agentx_varbind_get_object(sav) == relaydRouterName) 710 agentx_varbind_string(sav, router->rt_conf.name); 711 else if (agentx_varbind_get_object(sav) == relaydRouterLabel) 712 agentx_varbind_string(sav, router->rt_conf.label); 713 else if (agentx_varbind_get_object(sav) == relaydRouterRtable) 714 agentx_varbind_integer(sav, router->rt_conf.rtable); 715 } 716 717 struct netroute * 718 agentxctl_netroute_byidx(uint32_t instanceidx, enum agentx_request_type type) 719 { 720 struct netroute *nr; 721 722 TAILQ_FOREACH(nr, env->sc_routes, nr_route) { 723 if (nr->nr_conf.id == instanceidx) { 724 if (type == AGENTX_REQUEST_TYPE_GET || 725 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) 726 return nr; 727 else 728 return TAILQ_NEXT(nr, nr_entry); 729 } else if (nr->nr_conf.id > instanceidx) { 730 if (type == AGENTX_REQUEST_TYPE_GET) 731 return NULL; 732 return nr; 733 } 734 } 735 736 return NULL; 737 } 738 739 void 740 agentxctl_netroute(struct agentx_varbind *sav) 741 { 742 struct netroute *nr; 743 744 nr = agentxctl_netroute_byidx(agentx_varbind_get_index_integer(sav, 745 relaydNetRouteIdx), agentx_varbind_request(sav)); 746 if (nr == NULL || nr->nr_conf.id > INT32_MAX) { 747 agentx_varbind_notfound(sav); 748 return; 749 } 750 agentx_varbind_set_index_integer(sav, relaydNetRouteIdx, 751 nr->nr_conf.id); 752 if (agentx_varbind_get_object(sav) == relaydNetRouteIndex) 753 agentx_varbind_integer(sav, nr->nr_conf.id); 754 else if (agentx_varbind_get_object(sav) == relaydNetRouteAddr) 755 agentx_varbind_nstring(sav, sstodata(&nr->nr_conf.ss), 756 sstolen(&nr->nr_conf.ss)); 757 else if (agentx_varbind_get_object(sav) == relaydNetRouteAddrType) { 758 if (nr->nr_conf.ss.ss_family == AF_INET) 759 agentx_varbind_integer(sav, 1); 760 else if (nr->nr_conf.ss.ss_family == AF_INET6) 761 agentx_varbind_integer(sav, 2); 762 } else if (agentx_varbind_get_object(sav) == relaydNetRoutePrefixLen) 763 agentx_varbind_integer(sav, nr->nr_conf.prefixlen); 764 else if (agentx_varbind_get_object(sav) == relaydNetRouteRouterIndex) { 765 if (nr->nr_conf.routerid > INT32_MAX) 766 agentx_varbind_integer(sav, -1); 767 else 768 agentx_varbind_integer(sav, nr->nr_conf.routerid); 769 } 770 } 771 772 struct host * 773 agentxctl_host_byidx(uint32_t instanceidx, enum agentx_request_type type) 774 { 775 struct host *host; 776 777 TAILQ_FOREACH(host, &(env->sc_hosts), globalentry) { 778 if (host->conf.id == instanceidx) { 779 if (type == AGENTX_REQUEST_TYPE_GET || 780 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) 781 return host; 782 else 783 return TAILQ_NEXT(host, globalentry); 784 } else if (host->conf.id > instanceidx) { 785 if (type == AGENTX_REQUEST_TYPE_GET) 786 return NULL; 787 return host; 788 } 789 } 790 791 return NULL; 792 } 793 794 void 795 agentxctl_host(struct agentx_varbind *sav) 796 { 797 struct host *host; 798 799 host = agentxctl_host_byidx(agentx_varbind_get_index_integer(sav, 800 relaydHostIdx), agentx_varbind_request(sav)); 801 if (host == NULL || host->conf.id > INT32_MAX) { 802 agentx_varbind_notfound(sav); 803 return; 804 } 805 agentx_varbind_set_index_integer(sav, relaydHostIdx, 806 host->conf.id); 807 if (agentx_varbind_get_object(sav) == relaydHostIndex) 808 agentx_varbind_integer(sav, host->conf.id); 809 else if (agentx_varbind_get_object(sav) == relaydHostParentIndex) { 810 if (host->conf.parentid > INT32_MAX) 811 agentx_varbind_integer(sav, -1); 812 else 813 agentx_varbind_integer(sav, host->conf.parentid); 814 } else if (agentx_varbind_get_object(sav) == relaydHostTableIndex) { 815 if (host->conf.tableid > INT32_MAX) 816 agentx_varbind_integer(sav, -1); 817 else 818 agentx_varbind_integer(sav, host->conf.tableid); 819 } else if (agentx_varbind_get_object(sav) == relaydHostName) 820 agentx_varbind_string(sav, host->conf.name); 821 else if (agentx_varbind_get_object(sav) == relaydHostAddress) 822 agentx_varbind_nstring(sav, sstodata(&host->conf.ss), 823 sstolen(&host->conf.ss)); 824 else if (agentx_varbind_get_object(sav) == relaydHostAddressType) { 825 if (host->conf.ss.ss_family == AF_INET) 826 agentx_varbind_integer(sav, 1); 827 else if (host->conf.ss.ss_family == AF_INET6) 828 agentx_varbind_integer(sav, 2); 829 } else if (agentx_varbind_get_object(sav) == relaydHostStatus) { 830 if (host->flags & F_DISABLE) 831 agentx_varbind_integer(sav, 1); 832 else if (host->up == HOST_UP) 833 agentx_varbind_integer(sav, 0); 834 else if (host->up == HOST_DOWN) 835 agentx_varbind_integer(sav, 2); 836 else 837 agentx_varbind_integer(sav, 3); 838 } else if (agentx_varbind_get_object(sav) == relaydHostCheckCnt) 839 agentx_varbind_counter64(sav, host->check_cnt); 840 else if (agentx_varbind_get_object(sav) == relaydHostUpCnt) 841 agentx_varbind_counter64(sav, host->up_cnt); 842 else if (agentx_varbind_get_object(sav) == relaydHostErrno) 843 agentx_varbind_integer(sav, host->he); 844 } 845 846 /* 847 * Every session is spawned in one of multiple processes. 848 * However, there is no central session id registration, so not every session 849 * is shown here 850 */ 851 struct rsession * 852 agentxctl_session_byidx(uint32_t sessidx, uint32_t relayidx, 853 enum agentx_request_type type) 854 { 855 struct rsession *session; 856 857 TAILQ_FOREACH(session, &(env->sc_sessions), se_entry) { 858 if (session->se_id == sessidx) { 859 if (type == AGENTX_REQUEST_TYPE_GET) { 860 if (relayidx != session->se_relayid) 861 return NULL; 862 return session; 863 } 864 if (type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) { 865 if (relayidx <= session->se_relayid) 866 return session; 867 return TAILQ_NEXT(session, se_entry); 868 } 869 if (relayidx < session->se_relayid) 870 return session; 871 return TAILQ_NEXT(session, se_entry); 872 } else if (session->se_id > sessidx) { 873 if (type == AGENTX_REQUEST_TYPE_GET) 874 return NULL; 875 return session; 876 } 877 } 878 879 return NULL; 880 } 881 882 void 883 agentxctl_session(struct agentx_varbind *sav) 884 { 885 struct timeval tv, now; 886 struct rsession *session; 887 888 session = agentxctl_session_byidx(agentx_varbind_get_index_integer(sav, 889 relaydSessionIdx), agentx_varbind_get_index_integer(sav, 890 relaydSessionRelayIdx), agentx_varbind_request(sav)); 891 if (session == NULL || session->se_id > INT32_MAX || 892 session->se_relayid > INT32_MAX) { 893 agentx_varbind_notfound(sav); 894 return; 895 } 896 897 agentx_varbind_set_index_integer(sav, relaydSessionIdx, 898 session->se_id); 899 agentx_varbind_set_index_integer(sav, relaydSessionRelayIdx, 900 session->se_relayid); 901 if (agentx_varbind_get_object(sav) == relaydSessionIndex) 902 agentx_varbind_integer(sav, session->se_id); 903 else if (agentx_varbind_get_object(sav) == relaydSessionRelayIndex) 904 agentx_varbind_integer(sav, session->se_relayid); 905 else if (agentx_varbind_get_object(sav) == relaydSessionInAddr) 906 agentx_varbind_nstring(sav, sstodata(&(session->se_in.ss)), 907 sstolen(&(session->se_in.ss))); 908 else if (agentx_varbind_get_object(sav) == relaydSessionInAddrType) { 909 if (session->se_in.ss.ss_family == AF_INET) 910 agentx_varbind_integer(sav, 1); 911 else if (session->se_in.ss.ss_family == AF_INET6) 912 agentx_varbind_integer(sav, 2); 913 } else if (agentx_varbind_get_object(sav) == relaydSessionOutAddr) 914 agentx_varbind_nstring(sav, sstodata(&(session->se_out.ss)), 915 sstolen(&(session->se_out.ss))); 916 else if (agentx_varbind_get_object(sav) == relaydSessionOutAddrType) { 917 if (session->se_out.ss.ss_family == AF_INET) 918 agentx_varbind_integer(sav, 1); 919 else if (session->se_out.ss.ss_family == AF_INET6) 920 agentx_varbind_integer(sav, 2); 921 else 922 agentx_varbind_integer(sav, 0); 923 } else if (agentx_varbind_get_object(sav) == relaydSessionPortIn) 924 agentx_varbind_integer(sav, session->se_in.port); 925 else if (agentx_varbind_get_object(sav) == relaydSessionPortOut) 926 agentx_varbind_integer(sav, session->se_out.port); 927 else if (agentx_varbind_get_object(sav) == relaydSessionAge) { 928 getmonotime(&now); 929 timersub(&now, &session->se_tv_start, &tv); 930 agentx_varbind_timeticks(sav, 931 tv.tv_sec * 100 + tv.tv_usec / 10000); 932 } else if (agentx_varbind_get_object(sav) == relaydSessionIdle) { 933 getmonotime(&now); 934 timersub(&now, &session->se_tv_last, &tv); 935 agentx_varbind_timeticks(sav, 936 tv.tv_sec * 100 + tv.tv_usec / 10000); 937 } else if (agentx_varbind_get_object(sav) == relaydSessionStatus) { 938 if (session->se_done) 939 agentx_varbind_integer(sav, 1); 940 else 941 agentx_varbind_integer(sav, 0); 942 } else if (agentx_varbind_get_object(sav) == relaydSessionPid) 943 agentx_varbind_integer(sav, session->se_pid); 944 } 945 946 struct table * 947 agentxctl_table_byidx(uint32_t instanceidx, enum agentx_request_type type) 948 { 949 struct table *table; 950 951 TAILQ_FOREACH(table, env->sc_tables, entry) { 952 if (table->conf.id == instanceidx) { 953 if (type == AGENTX_REQUEST_TYPE_GET || 954 type == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) 955 return table; 956 else 957 return TAILQ_NEXT(table, entry); 958 } else if (table->conf.id > instanceidx) { 959 if (type == AGENTX_REQUEST_TYPE_GET) 960 return NULL; 961 return table; 962 } 963 } 964 965 return NULL; 966 } 967 968 void 969 agentxctl_table(struct agentx_varbind *sav) 970 { 971 struct table *table; 972 973 table = agentxctl_table_byidx(agentx_varbind_get_index_integer(sav, 974 relaydTableIdx), agentx_varbind_request(sav)); 975 if (table == NULL || table->conf.id > INT32_MAX) { 976 agentx_varbind_notfound(sav); 977 return; 978 } 979 agentx_varbind_set_index_integer(sav, relaydTableIdx, 980 table->conf.id); 981 if (agentx_varbind_get_object(sav) == relaydTableIndex) 982 agentx_varbind_integer(sav, table->conf.id); 983 else if (agentx_varbind_get_object(sav) == relaydTableName) 984 agentx_varbind_string(sav, table->conf.name); 985 else if (agentx_varbind_get_object(sav) == relaydTableStatus) { 986 if (TAILQ_EMPTY(&table->hosts)) 987 agentx_varbind_integer(sav, 1); 988 else if (table->conf.flags & F_DISABLE) 989 agentx_varbind_integer(sav, 2); 990 else 991 agentx_varbind_integer(sav, 0); 992 } 993 994 } 995 #if 0 996 997 int 998 snmp_element(const char *oidstr, enum snmp_type type, void *buf, int64_t val, 999 struct agentx_pdu *pdu) 1000 { 1001 u_int32_t d; 1002 u_int64_t l; 1003 struct snmp_oid oid; 1004 1005 DPRINTF("%s: oid %s type %d buf %p val %lld", __func__, 1006 oidstr, type, buf, val); 1007 1008 if (snmp_string2oid(oidstr, &oid) == -1) 1009 return -1; 1010 1011 switch (type) { 1012 case SNMP_GAUGE32: 1013 case SNMP_NSAPADDR: 1014 case SNMP_INTEGER32: 1015 case SNMP_UINTEGER32: 1016 d = (u_int32_t)val; 1017 if (snmp_agentx_varbind(pdu, &oid, AGENTX_INTEGER, 1018 &d, sizeof(d)) == -1) 1019 return -1; 1020 break; 1021 1022 case SNMP_COUNTER32: 1023 d = (u_int32_t)val; 1024 if (snmp_agentx_varbind(pdu, &oid, AGENTX_COUNTER32, 1025 &d, sizeof(d)) == -1) 1026 return -1; 1027 break; 1028 1029 case SNMP_TIMETICKS: 1030 d = (u_int32_t)val; 1031 if (snmp_agentx_varbind(pdu, &oid, AGENTX_TIME_TICKS, 1032 &d, sizeof(d)) == -1) 1033 return -1; 1034 break; 1035 1036 case SNMP_COUNTER64: 1037 l = (u_int64_t)val; 1038 if (snmp_agentx_varbind(pdu, &oid, AGENTX_COUNTER64, 1039 &l, sizeof(l)) == -1) 1040 return -1; 1041 break; 1042 1043 case SNMP_IPADDR: 1044 case SNMP_OPAQUE: 1045 d = (u_int32_t)val; 1046 if (snmp_agentx_varbind(pdu, &oid, AGENTX_OPAQUE, 1047 buf, strlen(buf)) == -1) 1048 return -1; 1049 break; 1050 1051 case SNMP_OBJECT: { 1052 struct snmp_oid oid1; 1053 1054 if (snmp_string2oid(buf, &oid1) == -1) 1055 return -1; 1056 if (snmp_agentx_varbind(pdu, &oid, AGENTX_OBJECT_IDENTIFIER, 1057 &oid1, sizeof(oid1)) == -1) 1058 return -1; 1059 } 1060 1061 case SNMP_BITSTRING: 1062 case SNMP_OCTETSTRING: 1063 if (snmp_agentx_varbind(pdu, &oid, AGENTX_OCTET_STRING, 1064 buf, strlen(buf)) == -1) 1065 return -1; 1066 break; 1067 1068 case SNMP_NULL: 1069 /* no data beyond the OID itself */ 1070 if (snmp_agentx_varbind(pdu, &oid, AGENTX_NULL, 1071 NULL, 0) == -1) 1072 return -1; 1073 } 1074 1075 return 0; 1076 } 1077 1078 /* 1079 * SNMP traps for relayd 1080 */ 1081 1082 void 1083 snmp_hosttrap(struct relayd *env, struct table *table, struct host *host) 1084 { 1085 struct agentx_pdu *pdu; 1086 1087 if (snmp_agentx == NULL || env->sc_snmp == -1) 1088 return; 1089 1090 /* 1091 * OPENBSD-RELAYD-MIB host status trap 1092 * XXX The trap format needs some tweaks and other OIDs 1093 */ 1094 1095 if ((pdu = snmp_agentx_notify_pdu(&hosttrapoid)) == NULL) 1096 return; 1097 1098 SNMP_ELEMENT(".1.0", SNMP_NULL, NULL, 0, pdu); 1099 SNMP_ELEMENT(".1.1.0", SNMP_OCTETSTRING, host->conf.name, 0, pdu); 1100 SNMP_ELEMENT(".1.2.0", SNMP_INTEGER32, NULL, host->up, pdu); 1101 SNMP_ELEMENT(".1.3.0", SNMP_INTEGER32, NULL, host->last_up, pdu); 1102 SNMP_ELEMENT(".1.4.0", SNMP_INTEGER32, NULL, host->up_cnt, pdu); 1103 SNMP_ELEMENT(".1.5.0", SNMP_INTEGER32, NULL, host->check_cnt, pdu); 1104 SNMP_ELEMENT(".1.6.0", SNMP_OCTETSTRING, table->conf.name, 0, pdu); 1105 SNMP_ELEMENT(".1.7.0", SNMP_INTEGER32, NULL, table->up, pdu); 1106 if (!host->conf.retry) 1107 goto done; 1108 SNMP_ELEMENT(".1.8.0", SNMP_INTEGER32, NULL, host->conf.retry, pdu); 1109 SNMP_ELEMENT(".1.9.0", SNMP_INTEGER32, NULL, host->retry_cnt, pdu); 1110 1111 done: 1112 snmp_agentx_send(snmp_agentx, pdu); 1113 snmp_event_add(env, EV_WRITE); 1114 } 1115 1116 int 1117 snmp_string2oid(const char *oidstr, struct snmp_oid *o) 1118 { 1119 char *sp, *p, str[BUFSIZ]; 1120 const char *errstr; 1121 1122 if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str)) 1123 return -1; 1124 bzero(o, sizeof(*o)); 1125 1126 for (p = sp = str; p != NULL; sp = p) { 1127 if ((p = strpbrk(p, ".-")) != NULL) 1128 *p++ = '\0'; 1129 o->o_id[o->o_n++] = strtonum(sp, 0, UINT_MAX, &errstr); 1130 if (errstr || o->o_n > SNMP_MAX_OID_LEN) 1131 return -1; 1132 } 1133 1134 return 0; 1135 } 1136 #endif 1137