1 /* $OpenBSD: agentx_control.c,v 1.5 2021/08/31 13:19:29 martijn 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 int 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 return 0; 477 retry: 478 evtimer_set(&env->sc_agentxev, agentx_sock, env); 479 evtimer_add(&env->sc_agentxev, &tv); 480 return 0; 481 } 482 483 void 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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