1 #include <net-snmp/net-snmp-config.h>
10 #ifdef HAVE_NETINET_IN_H
11 #include <netinet/in.h>
14 #include <net-snmp/net-snmp-includes.h>
15 #include <net-snmp/agent/net-snmp-agent-includes.h>
19 static struct simple_proxy *proxies = NULL;
21 oid testoid[] = { 1, 3, 6, 1, 4, 1, 2021, 8888, 1 };
24 * this must be standardized somewhere, right?
31 proxyOptProc(int argc, char *const *argv, int opt)
40 context_string = argv[optind - 1];
42 config_perror("No context name passed to -Cn");
46 config_perror("unknown argument passed to -C");
60 proxy_parse_config(const char *token, char *line)
63 * proxy args [base-oid] [remap-to-remote-oid]
66 netsnmp_session session, *ss;
67 struct simple_proxy *newp, **listpp;
68 char args[MAX_ARGS][SPRINT_MAX_LEN], *argv[MAX_ARGS];
71 netsnmp_handler_registration *reg;
73 context_string = NULL;
75 DEBUGMSGTL(("proxy_config", "entering\n"));
78 * create the argv[] like array
80 strcpy(argv[0] = args[0], "snmpd-proxy"); /* bogus entry for getopt() */
81 for (argn = 1, cp = line; cp && argn < MAX_ARGS;
82 cp = copy_nword(cp, argv[argn] = args[argn++], SPRINT_MAX_LEN)) {
85 for (arg = 0; arg < argn; arg++) {
86 DEBUGMSGTL(("proxy_args", "final args: %d = %s\n", arg,
90 DEBUGMSGTL(("proxy_config", "parsing args: %d\n", argn));
91 arg = snmp_parse_args(argn, argv, &session, "C:", proxyOptProc);
92 DEBUGMSGTL(("proxy_config", "done parsing args\n"));
95 config_perror("missing base oid");
101 * usm_set_reportErrorOnUnknownID(0);
103 * hack, stupid v3 ASIs.
106 * XXX: on a side note, we don't really need to be a reference
107 * platform any more so the proper thing to do would be to fix
108 * snmplib/snmpusm.c to pass in the pdu type to usm_process_incoming
109 * so this isn't needed.
111 ss = snmp_open(&session);
113 * usm_set_reportErrorOnUnknownID(1);
117 * diagnose snmp_open errors with the input netsnmp_session pointer
119 snmp_sess_perror("snmpget", &session);
124 newp = (struct simple_proxy *) calloc(1, sizeof(struct simple_proxy));
127 DEBUGMSGTL(("proxy_init", "name = %s\n", args[arg]));
128 newp->name_len = MAX_OID_LEN;
129 if (!snmp_parse_oid(args[arg++], newp->name, &newp->name_len)) {
130 snmp_perror("proxy");
131 config_perror("illegal proxy oid specified\n");
136 DEBUGMSGTL(("proxy_init", "base = %s\n", args[arg]));
137 newp->base_len = MAX_OID_LEN;
138 if (!snmp_parse_oid(args[arg++], newp->base, &newp->base_len)) {
139 snmp_perror("proxy");
140 config_perror("illegal variable name specified (base oid)\n");
145 DEBUGMSGTL(("proxy_init", "registering at: "));
146 DEBUGMSGOID(("proxy_init", newp->name, newp->name_len));
147 DEBUGMSG(("proxy_init", "\n"));
157 snmp_oid_compare(newp->name, newp->name_len,
158 (*listpp)->name, (*listpp)->name_len) > 0) {
159 listpp = &((*listpp)->next);
163 * listpp should be next in line from us.
167 * make our next in the link point to the current link
169 newp->next = *listpp;
172 * replace current link with us
176 reg = netsnmp_create_handler_registration("proxy",
181 reg->handler->myvoid = newp;
183 reg->contextName = strdup(context_string);
185 netsnmp_register_handler(reg);
189 proxy_free_config(void)
191 struct simple_proxy *rm;
194 * XXX: finish me (needs unregister_mib())
201 SNMP_FREE(rm->variables);
202 snmp_close(rm->sess);
210 snmpd_register_config_handler("proxy", proxy_parse_config,
212 "[snmpcmd args] host oid [remoteoid]");
216 proxy_handler(netsnmp_mib_handler *handler,
217 netsnmp_handler_registration *reginfo,
218 netsnmp_agent_request_info *reqinfo,
219 netsnmp_request_info *requests)
223 struct simple_proxy *sp;
226 netsnmp_request_info *request = requests;
228 DEBUGMSGTL(("proxy", "proxy handler starting, mode = %d\n",
231 switch (reqinfo->mode) {
234 case MODE_GETBULK: /* WWWXXX */
235 pdu = snmp_pdu_create(reqinfo->mode);
238 case MODE_SET_COMMIT:
239 pdu = snmp_pdu_create(SNMP_MSG_SET);
243 snmp_log(LOG_WARNING, "unsupported mode for proxy called\n");
244 return SNMP_ERR_NOERROR;
247 sp = (struct simple_proxy *) handler->myvoid;
250 netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
251 return SNMP_ERR_NOERROR;
255 ourname = request->requestvb->name;
256 ourlength = request->requestvb->name_length;
258 if (sp->base_len > 0) {
259 if ((ourlength - sp->name_len + sp->base_len) > MAX_OID_LEN) {
264 "proxy oid request length is too long\n");
265 return SNMP_ERR_NOERROR;
270 DEBUGMSGTL(("proxy", "length=%d, base_len=%d, name_len=%d\n",
271 ourlength, sp->base_len, sp->name_len));
272 if (ourlength > (int) sp->name_len)
273 memcpy(&(sp->base[sp->base_len]), &(ourname[sp->name_len]),
274 sizeof(oid) * (ourlength - sp->name_len));
275 ourlength = ourlength - sp->name_len + sp->base_len;
279 snmp_pdu_add_variable(pdu, ourname, ourlength,
280 request->requestvb->type,
281 request->requestvb->val.string,
282 request->requestvb->val_len);
283 request->delegated = 1;
284 request = request->next;
288 * send the request out
290 DEBUGMSGTL(("proxy", "sending pdu\n"));
291 snmp_async_send(sp->sess, pdu, proxy_got_response,
292 netsnmp_create_delegated_cache(handler, reginfo,
295 return SNMP_ERR_NOERROR;
299 proxy_got_response(int operation, netsnmp_session * sess, int reqid,
300 netsnmp_pdu *pdu, void *cb_data)
302 netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) cb_data;
303 netsnmp_request_info *requests, *request;
304 netsnmp_variable_list *vars, *var;
306 struct simple_proxy *sp;
307 oid myname[MAX_OID_LEN];
308 size_t myname_len = MAX_OID_LEN;
310 cache = netsnmp_handler_check_cache(cache);
311 requests = cache->requests;
314 sp = (struct simple_proxy *) cache->localinfo;
317 DEBUGMSGTL(("proxy", "a proxy request was no longer valid.\n"));
318 return SNMP_ERR_NOERROR;
322 if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
324 * WWWXXX: don't leave requests delayed if operation is
325 * something like TIMEOUT
327 vars = pdu->variables;
330 * update the original request varbinds with the results
332 for (var = vars, request = requests;
334 request = request->next, var = var->next_variable) {
335 snmp_set_var_typed_value(request->requestvb, var->type,
336 var->val.string, var->val_len);
338 DEBUGMSGTL(("proxy", "got response... "));
339 DEBUGMSGOID(("proxy", var->name, var->name_length));
340 DEBUGMSG(("proxy", "\n"));
341 request->delegated = 0;
344 * copy the oid it belongs to
347 (var->name_length < sp->base_len ||
348 snmp_oid_compare(var->name, sp->base_len, sp->base,
349 sp->base_len) != 0)) {
350 DEBUGMSGTL(("proxy", "out of registered range... "));
351 DEBUGMSGOID(("proxy", var->name, sp->base_len));
352 DEBUGMSG(("proxy", " (%d) != ", sp->base_len));
353 DEBUGMSGOID(("proxy", sp->base, sp->base_len));
354 DEBUGMSG(("proxy", "\n"));
357 } else if (!sp->base_len &&
358 (var->name_length < sp->name_len ||
359 snmp_oid_compare(var->name, sp->name_len, sp->name,
360 sp->name_len) != 0)) {
361 DEBUGMSGTL(("proxy", "out of registered base range...\n"));
363 * or not if its out of our search range
369 * XXX: oid size maxed?
371 memcpy(myname, sp->name, sizeof(oid) * sp->name_len);
373 sp->name_len + var->name_length - sp->base_len;
374 if (myname_len > MAX_OID_LEN) {
375 snmp_log(LOG_WARNING,
376 "proxy OID return length too long.\n");
377 netsnmp_set_request_error(cache->reqinfo, requests,
381 netsnmp_free_delegated_cache(cache);
385 if (var->name_length > sp->base_len)
386 memcpy(&myname[sp->name_len],
387 &var->name[sp->base_len],
388 sizeof(oid) * (var->name_length -
390 snmp_set_var_objid(request->requestvb, myname,
393 snmp_set_var_objid(request->requestvb, var->name,
399 if (request || var) {
401 * ack, this is bad. The # of varbinds don't match and
402 * there is no way to fix the problem
407 "response to proxy request illegal. We're screwed.\n");
408 netsnmp_set_request_error(cache->reqinfo, requests,
418 DEBUGMSGTL(("proxy", "no response received: op = %d\n",
422 netsnmp_free_delegated_cache(cache);