0
|
1 /*
|
|
2 * CDDL HEADER START
|
|
3 *
|
|
4 * The contents of this file are subject to the terms of the
|
|
5 * Common Development and Distribution License, Version 1.0 only
|
|
6 * (the "License"). You may not use this file except in compliance
|
|
7 * with the License.
|
|
8 *
|
|
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
10 * or http://www.opensolaris.org/os/licensing.
|
|
11 * See the License for the specific language governing permissions
|
|
12 * and limitations under the License.
|
|
13 *
|
|
14 * When distributing Covered Code, include this CDDL HEADER in each
|
|
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
16 * If applicable, add the following below this CDDL HEADER, with the
|
|
17 * fields enclosed by brackets "[]" replaced with your own identifying
|
|
18 * information: Portions Copyright [yyyy] [name of copyright owner]
|
|
19 *
|
|
20 * CDDL HEADER END
|
|
21 */
|
|
22 /*
|
|
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
|
24 * Use is subject to license terms.
|
|
25 */
|
|
26
|
|
27 #pragma ident "@(#)agent.c 1.25 05/06/12 SMI"
|
|
28
|
|
29 #include <stdio.h>
|
|
30 #include <stdlib.h>
|
|
31 #include <string.h>
|
|
32 #include <strings.h>
|
|
33 #include <sys/types.h>
|
|
34 #include <sys/socket.h>
|
|
35 #include <netinet/in.h>
|
|
36 #include <arpa/inet.h>
|
|
37
|
|
38
|
|
39 #include "impl.h"
|
|
40 #include "error.h"
|
|
41 #include "trace.h"
|
|
42 #include "snmp.h"
|
|
43 #include "pdu.h"
|
|
44 #include "request.h"
|
|
45 #include "trap.h"
|
|
46
|
|
47 #include "node.h"
|
|
48 #include "access.h"
|
|
49
|
|
50 static int ssa_mem_free = 1; /* on */
|
|
51
|
|
52 #if defined(_LP64)
|
|
53 #define COLUMN_OFFSET(x) (x) * 2
|
|
54 #else
|
|
55 #define COLUMN_OFFSET(x) (x)
|
|
56 #endif
|
|
57
|
|
58 #define OCTET_STRING 2
|
|
59
|
|
60 /***** LOCAL VARIABLES *****/
|
|
61
|
|
62 /*
|
|
63 * The idea of these cache variables is to avoid to call
|
|
64 * the same *(entry->get) function for variables contained
|
|
65 * in a single SNMP PDU.
|
|
66 *
|
|
67 * There is still a problem in this mechanism.
|
|
68 * When you query a whole table row by row and when
|
|
69 * you reached the end of the table, the *(entry->get)
|
|
70 * will be called several times:
|
|
71 * - for the first column, *(entry->get) will be called
|
|
72 * once to find that the end of the table is reached
|
|
73 * (==> the knowledge that we reached the last row is cached)
|
|
74 * and then *(entry->get) will be called on the first row of
|
|
75 * the same table (==> the first row is cached).
|
|
76 * - Same behaviour for all the remaining columns
|
|
77 *
|
|
78 * Possible solutions:
|
|
79 * - two caches but this implies the copy of the cached
|
|
80 * structures + all theis pointers
|
|
81 * - only one cache + caching the knowledge that we reached the last
|
|
82 * row ???
|
|
83 *
|
|
84 */
|
|
85
|
|
86 static Entry *cache_input_entry = NULL;
|
|
87 static Subid cache_input_index[MAX_OID_LEN];
|
|
88 static void *cache_output_pointer = NULL;
|
|
89 static int cache_output_snmp_error = -1;
|
|
90 static Subid cache_output_index[MAX_OID_LEN];
|
|
91
|
|
92
|
|
93 /***** LOCAL FUNCTIONS *****/
|
|
94
|
|
95 static int agent_get_next(SNMP_pdu *pdu, char *error_label);
|
|
96 static int agent_get_next_loop(SNMP_variable *variable, Node *node, Oid *suffix);
|
|
97 static int agent_get(SNMP_pdu *pdu, char *error_label);
|
|
98 static int agent_set(int pass, SNMP_pdu *pdu, char *error_label);
|
|
99
|
|
100
|
|
101 /****************************************************************/
|
|
102
|
|
103 /* returns: */
|
|
104 /* 0 in case of success (the pdu should be sent */
|
|
105 /* back to its originator even if an SNMP error */
|
|
106 /* was detected) */
|
|
107 /* -1 in case of failure (no pdu should be sent */
|
|
108 /* back) */
|
|
109
|
|
110 int agent_process(Address *address, SNMP_pdu *pdu)
|
|
111 {
|
|
112 int snmpEnableAuthTraps = FALSE;
|
|
113 Manager *mngr;
|
|
114
|
|
115
|
|
116 if(pdu == NULL)
|
|
117 {
|
|
118 error("BUG: agent_process(): pdu is NULL");
|
|
119 return -1;
|
|
120 }
|
|
121
|
|
122
|
|
123 /* check host */
|
|
124 if(is_valid_manager(address,&mngr) == NULL)
|
|
125 {
|
|
126 error("agent_process(): unauthorized manager (%s)",
|
|
127 ip_address_string(&(address->sin_addr)));
|
|
128
|
|
129 snmpEnableAuthTraps = request_snmpEnableAuthTraps(error_label);
|
|
130 switch(snmpEnableAuthTraps)
|
|
131 {
|
|
132 case TRUE:
|
|
133 if(trap_send_to_all_destinators(NULL,
|
|
134 SNMP_TRAP_AUTHFAIL, 0,
|
|
135 NULL, error_label))
|
|
136 {
|
|
137 error("trap_send_to_all_destinators() failed: %s\n",
|
|
138 error_label);
|
|
139 }
|
|
140 break;
|
|
141
|
|
142 case FALSE:
|
|
143 default:
|
|
144 break;
|
|
145 }
|
|
146
|
|
147 return -1;
|
|
148 }
|
|
149
|
|
150 /* if mngr == NULL -> allow requests from any hosts */
|
|
151
|
|
152 /* check pdu type */
|
|
153 if(pdu->type != GETNEXT_REQ_MSG
|
|
154 && (pdu->type != GET_REQ_MSG)
|
|
155 && (pdu->type != SET_REQ_MSG) )
|
|
156 {
|
|
157 error("agent_process(): bad PDU type (0x%x)", pdu->type);
|
|
158 return -1;
|
|
159 }
|
|
160
|
|
161
|
|
162 /* check host */
|
|
163 if(!is_valid_community(pdu->community, pdu->type,mngr))
|
|
164 {
|
|
165 /*
|
|
166 * Earlier, the community name is displayed here
|
|
167 * in this error message. But since these error
|
|
168 * messages are readable by all users, it is not advisible
|
|
169 * to display community names in the error messages.
|
|
170 */
|
|
171 error("agent_process() : bad community from %s",
|
|
172 ip_address_string(&(address->sin_addr)));
|
|
173
|
|
174 snmpEnableAuthTraps = request_snmpEnableAuthTraps(error_label);
|
|
175 switch(snmpEnableAuthTraps)
|
|
176 {
|
|
177 case TRUE:
|
|
178 if(trap_send_to_all_destinators(NULL,
|
|
179 SNMP_TRAP_AUTHFAIL, 0,
|
|
180 NULL, error_label))
|
|
181 {
|
|
182 error("trap_send_to_all_destinators() failed: %s\n",
|
|
183 error_label);
|
|
184 }
|
|
185 break;
|
|
186
|
|
187 case FALSE:
|
|
188 default:
|
|
189 break;
|
|
190 }
|
|
191
|
|
192 return -1;
|
|
193 }
|
|
194
|
|
195
|
|
196 if(cache_input_entry != NULL && cache_output_pointer != NULL)
|
|
197 if(ssa_mem_free != 0 && cache_input_entry->dealloc != NULL){
|
|
198 (*(cache_input_entry->dealloc))(cache_output_pointer);
|
|
199 cache_output_pointer = NULL;
|
|
200 }
|
|
201
|
|
202 cache_input_entry = NULL;
|
|
203
|
|
204 switch(pdu->type)
|
|
205 {
|
|
206 case GETNEXT_REQ_MSG:
|
|
207 if(agent_get_next(pdu, error_label))
|
|
208 {
|
|
209 error("agent_get_next() failed: %s", error_label);
|
|
210 return -1;
|
|
211 }
|
|
212 return 0;
|
|
213
|
|
214 case GET_REQ_MSG:
|
|
215 if(agent_get(pdu, error_label))
|
|
216 {
|
|
217 error("agent_get() failed: %s", error_label);
|
|
218 return -1;
|
|
219 }
|
|
220 return 0;
|
|
221
|
|
222 case SET_REQ_MSG:
|
|
223 switch(agent_set(FIRST_PASS, pdu, error_label))
|
|
224 {
|
|
225 case 0:
|
|
226 switch(agent_set(SECOND_PASS, pdu, error_label))
|
|
227 {
|
|
228 case 0:
|
|
229 case 1:
|
|
230 return 0;
|
|
231
|
|
232 case -1:
|
|
233 error("agent_set(SECOND_PASS) failed: %s",
|
|
234 error_label);
|
|
235 return -1;
|
|
236 }
|
|
237
|
|
238 /* never reached */
|
|
239 break;
|
|
240
|
|
241 case 1:
|
|
242 return 0;
|
|
243
|
|
244 case -1:
|
|
245 error("agent_set(FIRST_PASS) failed: %s",
|
|
246 error_label);
|
|
247 return -1;
|
|
248 }
|
|
249 }
|
|
250
|
|
251 /* never reached */
|
|
252 return -1;
|
|
253 }
|
|
254
|
|
255
|
|
256 /****************************************************************/
|
|
257
|
|
258 /* returns: */
|
|
259 /* 0 in case of success (the pdu should be sent */
|
|
260 /* back to its originator even if an SNMP error */
|
|
261 /* was detected) */
|
|
262 /* -1 in case of failure (no pdu should be sent */
|
|
263 /* back) */
|
|
264
|
|
265 static int agent_get_next(SNMP_pdu *pdu, char *error_label)
|
|
266 {
|
|
267 SNMP_variable *variable;
|
|
268 Node *node;
|
|
269 Oid suffix;
|
|
270 int index = 1;
|
|
271 int snmp_error;
|
|
272
|
|
273
|
|
274 error_label[0] = '\0';
|
|
275
|
|
276 pdu->type = GET_RSP_MSG;
|
|
277
|
|
278 for(variable = pdu->first_variable; variable; variable = variable->next_variable)
|
|
279 {
|
|
280 node = node_find(NEXT_ENTRY, &(variable->name), &suffix);
|
|
281 if(node == NULL)
|
|
282 {
|
|
283 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
284 pdu->error_index = index;
|
|
285 return 0;
|
|
286 }
|
|
287 /* we should not forget to free suffix.subids */
|
|
288
|
|
289 if(trace_level > 0)
|
|
290 {
|
|
291 trace("!! getnext(): processing the variable %s\n\n",
|
|
292 node->label);
|
|
293 }
|
|
294
|
|
295 if(variable->type != NULLOBJ)
|
|
296 {
|
|
297 error("ASN.1 type (0x%x) is not NULL for node %s",
|
|
298 variable->type, node->label);
|
|
299 variable->type = NULLOBJ;
|
|
300 }
|
|
301
|
|
302 if(variable->val.string)
|
|
303 {
|
|
304 error("val is not NULL for node %s",
|
|
305 node->label);
|
|
306 free(variable->val.string);
|
|
307 variable->val.string = NULL;
|
|
308 }
|
|
309
|
|
310 if(variable->val_len)
|
|
311 {
|
|
312 error("val_len is not 0 for node %s",
|
|
313 node->label);
|
|
314 variable->val_len = 0;
|
|
315 }
|
|
316
|
|
317 snmp_error = agent_get_next_loop(variable, node, &suffix);
|
|
318
|
|
319 if(snmp_error != SNMP_ERR_NOERROR)
|
|
320 {
|
|
321 pdu->error_status = snmp_error;
|
|
322 pdu->error_index = index;
|
|
323 return 0;
|
|
324 }
|
|
325
|
|
326 index++;
|
|
327 }
|
|
328
|
|
329 return 0;
|
|
330 }
|
|
331
|
|
332
|
|
333 /* This function will free suffix->subids */
|
|
334 /* It returns a positive snmp_error code. */
|
|
335 static int
|
|
336 agent_get_next_loop(SNMP_variable *variable, Node *node, Oid *suffix)
|
|
337 {
|
|
338 Object *object;
|
|
339 Column *column;
|
|
340 Entry *entry;
|
|
341 Integer integer = 0;
|
|
342 Integer *integer_ptr;
|
|
343 String string = { NULL, 0 };
|
|
344 String *string_ptr;
|
|
345 Oid oid = { NULL, 0 };
|
|
346 Oid *oid_ptr;
|
|
347 char *pointer;
|
|
348 int snmp_error;
|
|
349 Subid index[MAX_OID_LEN];
|
|
350 Index *pIndex;
|
|
351 int index_len;
|
|
352
|
|
353 /* create index struct */
|
|
354 IndexType index_obj;
|
|
355 int index_buffer[256];
|
|
356
|
|
357 int was_cached ;
|
|
358 int i;
|
|
359 int get_entry;
|
|
360
|
|
361 bzero(index, sizeof(Subid) * MAX_OID_LEN);
|
|
362 bzero(&index_obj, sizeof(index_obj));
|
|
363 bzero(index_buffer, sizeof(index_buffer));
|
|
364 index_obj.value = index_buffer;
|
|
365
|
|
366 if(node == NULL)
|
|
367 {
|
|
368 if(trace_level > 0)
|
|
369 {
|
|
370 trace("!! End of MIB\n\n");
|
|
371 }
|
|
372
|
|
373 SSAOidZero(suffix);
|
|
374 return SNMP_ERR_NOSUCHNAME;
|
|
375 }
|
|
376
|
|
377 if(trace_level > 0)
|
|
378 trace("!! Trying %s with suffix %s\n\n",
|
|
379 node->label, SSAOidString(suffix));
|
|
380
|
|
381 switch(node->type)
|
|
382 {
|
|
383 case OBJECT:
|
|
384 object = node->data.object;
|
|
385
|
|
386 switch(suffix->len)
|
|
387 {
|
|
388 case 0:
|
|
389 if( !(object->access & READ_FLAG) )
|
|
390 return SNMP_ERR_NOSUCHNAME;
|
|
391
|
|
392 switch(object->asn1_type)
|
|
393 {
|
|
394 case INTEGER:
|
|
395 case COUNTER:
|
|
396 case GAUGE:
|
|
397 case TIMETICKS:
|
|
398 snmp_error = (*(object->get))(&integer);
|
|
399 break;
|
|
400
|
|
401 case OBJID:
|
|
402 snmp_error = (*(object->get))(&oid);
|
|
403 if(snmp_error != SNMP_ERR_NOERROR &&
|
|
404 ssa_mem_free != 0){
|
|
405 if(object->dealloc != NULL)
|
|
406 (*(object->dealloc))(&oid);
|
|
407 }
|
|
408 break;
|
|
409
|
|
410 case STRING:
|
|
411 case IPADDRESS:
|
|
412 case OPAQUE:
|
|
413 snmp_error = (*(object->get))(&string);
|
|
414 if(snmp_error != SNMP_ERR_NOERROR &&
|
|
415 ssa_mem_free != 0){
|
|
416 if(object->dealloc != NULL)
|
|
417 (*(object->dealloc))(&string);
|
|
418 }
|
|
419 break;
|
|
420 }
|
|
421
|
|
422 if(snmp_error != SNMP_ERR_NOERROR)
|
|
423 {
|
|
424 if(snmp_error < 0)
|
|
425 {
|
|
426 error("the get() method of %s returned %d",
|
|
427 node->label,
|
|
428 snmp_error);
|
|
429 snmp_error = SNMP_ERR_GENERR;
|
|
430 }
|
|
431 return snmp_error;
|
|
432 }
|
|
433
|
|
434 /* variable->name */
|
|
435 SSAOidZero(&(variable->name));
|
|
436 variable->name.subids = (Subid *) malloc((object->name.len + 1) *
|
|
437 (int32_t)sizeof(Subid));
|
|
438 (void)memcpy(variable->name.subids, object->name.subids,
|
|
439 object->name.len * (int32_t)sizeof(Subid));
|
|
440 variable->name.subids[object->name.len] = 0;
|
|
441 variable->name.len = object->name.len + 1;
|
|
442
|
|
443 /* variable->type */
|
|
444 variable->type = object->asn1_type;
|
|
445
|
|
446 /* variable->val, variable->val_len */
|
|
447 switch(object->asn1_type)
|
|
448 {
|
|
449 case INTEGER:
|
|
450 case COUNTER:
|
|
451 case GAUGE:
|
|
452 case TIMETICKS:
|
|
453 variable->val.integer = (Integer *) malloc(sizeof(Integer));
|
|
454 *(variable->val.integer) = integer;
|
|
455 variable->val_len = sizeof(Integer);
|
|
456 break;
|
|
457
|
|
458 case OBJID:
|
|
459 variable->val.objid = (Subid *) malloc(oid.len *
|
|
460 (int32_t)sizeof(Subid));
|
|
461 (void)memcpy(variable->val.objid, oid.subids, oid.len *
|
|
462 (int32_t)sizeof(Subid));
|
|
463 variable->val_len = oid.len *
|
|
464 (int32_t)sizeof(Subid);
|
|
465 if(ssa_mem_free !=0 && object->dealloc != NULL)
|
|
466 (*(object->dealloc))(&oid);
|
|
467 break;
|
|
468
|
|
469 case STRING:
|
|
470 case IPADDRESS:
|
|
471 case OPAQUE:
|
|
472 variable->val.string = (u_char *) malloc(string.len);
|
|
473 (void)memcpy(variable->val.string, string.chars, string.len);
|
|
474 variable->val_len = string.len;
|
|
475 if(ssa_mem_free != 0 && object->dealloc != NULL)
|
|
476 (*(object->dealloc))(&string);
|
|
477 break;
|
|
478
|
|
479 }
|
|
480
|
|
481 return SNMP_ERR_NOERROR;
|
|
482
|
|
483
|
|
484 case 1:
|
|
485 if(suffix->subids[0] != 0)
|
|
486 {
|
|
487 SSAOidZero(suffix);
|
|
488 return SNMP_ERR_NOSUCHNAME;
|
|
489 }
|
|
490 SSAOidZero(suffix);
|
|
491
|
|
492 return agent_get_next_loop(variable, node->next, suffix);
|
|
493
|
|
494 default:
|
|
495 SSAOidZero(suffix);
|
|
496 return SNMP_ERR_NOSUCHNAME;
|
|
497 }
|
|
498
|
|
499
|
|
500 case COLUMN:
|
|
501 column = node->data.column;
|
|
502 entry = column->entry;
|
|
503 pIndex = entry->first_index;
|
|
504
|
|
505 if( !(column->access & READ_FLAG) )
|
|
506 {
|
|
507 SSAOidZero(suffix);
|
|
508 return SNMP_ERR_NOSUCHNAME;
|
|
509 }
|
|
510
|
|
511 if (entry->n_indexs < 0 || entry->n_indexs > MAX_OID_LEN) {
|
|
512 SSAOidZero(suffix);
|
|
513 return SNMP_ERR_NOSUCHNAME;
|
|
514 }
|
|
515
|
|
516 index_len = 0;
|
|
517 for (pIndex=entry->first_index; pIndex; pIndex=pIndex->next_index)
|
|
518 {
|
|
519 if (pIndex->index_type == OCTET_STRING)
|
|
520 index_len = index_len + (pIndex->index_len)+1; /* add extra suffix for str len */
|
|
521 else
|
|
522 index_len = index_len +1; /* one subid per index */
|
|
523 }
|
|
524 index_obj.len = index_len;
|
|
525
|
|
526 for (i=0; i < suffix->len; i++)
|
|
527 {
|
|
528 index[i] = suffix->subids[i];
|
|
529 index_obj.value[i] = suffix->subids[i];
|
|
530 }
|
|
531
|
|
532 for (i = suffix->len; i < index_len; i++) /* Zero out remainder of suffixes */
|
|
533 {
|
|
534 index[i] = 0;
|
|
535 index_obj.value[i] = 0;
|
|
536 }
|
|
537
|
|
538 for (i=0; i < index_len; i++)
|
|
539 {
|
|
540 if ((cache_input_entry == entry) && (cache_input_index[i] == index[i]))
|
|
541 was_cached = 1;
|
|
542 else
|
|
543 {
|
|
544 was_cached = 0;
|
|
545 break;
|
|
546 }
|
|
547
|
|
548 }
|
|
549
|
|
550 if (was_cached)
|
|
551 {
|
|
552 pointer = cache_output_pointer;
|
|
553 snmp_error = cache_output_snmp_error;
|
|
554 for (i=0;i < index_len; i++)
|
|
555 index[i]= cache_output_index[i];
|
|
556 }
|
|
557 else
|
|
558 {
|
|
559 if (cache_input_entry != NULL && cache_output_pointer != NULL)
|
|
560 if (ssa_mem_free!=0 && cache_input_entry->dealloc != NULL)
|
|
561 {
|
|
562 (*(cache_input_entry->dealloc))(cache_output_pointer);
|
|
563 cache_output_pointer = NULL;
|
|
564 }
|
|
565 cache_input_entry= entry;
|
|
566 for (i=0; i < index_len; i++)
|
|
567 cache_input_index[i] = index[i];
|
|
568
|
|
569 if (suffix->len == 0)
|
|
570 get_entry = FIRST_ENTRY;
|
|
571 else
|
|
572 get_entry = NEXT_ENTRY;
|
|
573
|
|
574 snmp_error = (*(entry->get)) (get_entry, &pointer,&index_obj);
|
|
575
|
|
576 for (i=0; i< index_len; i++)
|
|
577 index[i] = index_obj.value[i];
|
|
578 cache_output_pointer = pointer;
|
|
579 cache_output_snmp_error = snmp_error;
|
|
580 for (i=0; i < index_len; i++)
|
|
581 cache_output_index[i] = index[i];
|
|
582 }
|
|
583
|
|
584 if (suffix->len !=0)
|
|
585 SSAOidZero(suffix);
|
|
586
|
|
587 if(pointer == NULL)
|
|
588 {
|
|
589 if(snmp_error == END_OF_TABLE)
|
|
590 {
|
|
591 if(trace_level > 0)
|
|
592 {
|
|
593 trace("!! End of table %s\n\n",
|
|
594 node->parent->parent->label);
|
|
595 }
|
|
596 return agent_get_next_loop(variable, node->next, suffix);
|
|
597 }
|
|
598
|
|
599 if(snmp_error < 0)
|
|
600 {
|
|
601 error("the get() method of %s returned %d",
|
|
602 node->parent->label,
|
|
603 snmp_error);
|
|
604 snmp_error = SNMP_ERR_GENERR;
|
|
605 }
|
|
606 return snmp_error;
|
|
607 }
|
|
608
|
|
609 /* variable->name */
|
|
610 SSAOidZero(&(variable->name));
|
|
611 variable->name.subids = (Subid *) malloc((column->name.len + index_len) * sizeof(Subid));
|
|
612 memcpy(variable->name.subids, column->name.subids, column->name.len * sizeof(Subid));
|
|
613 for (i=0; i < index_len; i++)
|
|
614 variable->name.subids[column->name.len + i] = index[i];
|
|
615 variable->name.len = column->name.len + index_len;
|
|
616
|
|
617 /* variable->type */
|
|
618 variable->type = column->asn1_type;
|
|
619
|
|
620 /* variable->val, variable->val_len */
|
|
621 switch(column->asn1_type)
|
|
622 {
|
|
623 case INTEGER:
|
|
624 case COUNTER:
|
|
625 case GAUGE:
|
|
626 case TIMETICKS:
|
|
627 integer_ptr = (Integer *) (pointer +
|
|
628 COLUMN_OFFSET(column->offset));
|
|
629 variable->val.integer = (Integer *) malloc(sizeof(Integer));
|
|
630 *(variable->val.integer) = *integer_ptr;
|
|
631 variable->val_len = sizeof(Integer);
|
|
632 break;
|
|
633
|
|
634 case OBJID:
|
|
635 oid_ptr = (Oid *) (pointer +
|
|
636 COLUMN_OFFSET(column->offset));
|
|
637 /* fix the null subid */
|
|
638 if(oid_ptr->subids == NULL){
|
|
639 variable->val.objid = NULL;
|
|
640 }else{
|
|
641 variable->val.objid = (Subid *) malloc(oid_ptr->len *
|
|
642 (int32_t)sizeof(Subid));
|
|
643 (void)memcpy(variable->val.objid, oid_ptr->subids, oid_ptr->len *
|
|
644 (int32_t)sizeof(Subid));
|
|
645 }
|
|
646 variable->val_len = oid_ptr->len *
|
|
647 (int32_t)sizeof(Subid);
|
|
648 break;
|
|
649
|
|
650 case STRING:
|
|
651 case IPADDRESS:
|
|
652 case OPAQUE:
|
|
653 string_ptr = (String *) (pointer +
|
|
654 COLUMN_OFFSET(column->offset));
|
|
655 if(string_ptr->chars == NULL){
|
|
656 variable->val.string =(u_char*)NULL;
|
|
657 }else{
|
|
658 variable->val.string = (u_char *) malloc(string_ptr->len);
|
|
659 (void)memcpy(variable->val.string, string_ptr->chars, string_ptr->len);
|
|
660 }
|
|
661 variable->val_len = string_ptr->len;
|
|
662 break;
|
|
663 }
|
|
664
|
|
665
|
|
666 return SNMP_ERR_NOERROR;
|
|
667
|
|
668
|
|
669 case NODE:
|
|
670 return agent_get_next_loop(variable, node->next, suffix);
|
|
671 }
|
|
672
|
|
673 /* never reached */
|
|
674 return -1;
|
|
675 }
|
|
676
|
|
677
|
|
678 /****************************************************************/
|
|
679
|
|
680 /* returns: */
|
|
681 /* 0 in case of success (the pdu should be sent */
|
|
682 /* back to its originator even if an SNMP error */
|
|
683 /* was detected) */
|
|
684 /* -1 in case of failure (no pdu should be sent */
|
|
685 /* back) */
|
|
686
|
|
687 static int agent_get(SNMP_pdu *pdu, char *error_label)
|
|
688 {
|
|
689 SNMP_variable *variable;
|
|
690 Node *node;
|
|
691 Object *object;
|
|
692 Column *column;
|
|
693 Entry *entry=NULL;
|
|
694 Oid suffix;
|
|
695 int index_err = 1;
|
|
696 Integer integer;
|
|
697 Oid oid;
|
|
698 String string;
|
|
699 Integer *integer_ptr;
|
|
700 Oid *oid_ptr;
|
|
701 String *string_ptr;
|
|
702 int snmp_error;
|
|
703 char *pointer=NULL;
|
|
704 Subid index[MAX_OID_LEN];
|
|
705
|
|
706 /* create index struct */
|
|
707 IndexType index_obj;
|
|
708 int index_buffer[256];
|
|
709
|
|
710 int was_cached;
|
|
711 int i;
|
|
712 Index *pIndex;
|
|
713 int index_len;
|
|
714
|
|
715 index_obj.len = 0;
|
|
716 index_obj.type = 0;
|
|
717 index_obj.value = index_buffer;
|
|
718
|
|
719
|
|
720 error_label[0] = '\0';
|
|
721
|
|
722 pdu->type = GET_RSP_MSG;
|
|
723
|
|
724 for(variable = pdu->first_variable; variable; variable = variable->next_variable)
|
|
725 {
|
|
726 node = node_find(EXACT_ENTRY, &(variable->name), &suffix);
|
|
727 if(node == NULL)
|
|
728 {
|
|
729 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
730 pdu->error_index = index_err;
|
|
731 return 0;
|
|
732 }
|
|
733 /* we should not forget to free suffix.subids */
|
|
734
|
|
735 if(trace_level > 0)
|
|
736 {
|
|
737 trace("!! get(): processing the variable %s\n\n",
|
|
738 node->label);
|
|
739 }
|
|
740
|
|
741 if(variable->type != NULLOBJ)
|
|
742 {
|
|
743 error("agent_get(): ASN.1 type (0x%x) is not NULL for node %s",
|
|
744 variable->type,
|
|
745 node->label);
|
|
746 variable->type = NULLOBJ;
|
|
747 }
|
|
748
|
|
749 if(variable->val.string)
|
|
750 {
|
|
751 error("agent_get(): val is not NULL for node %s", node->label);
|
|
752 free(variable->val.string);
|
|
753 variable->val.string = NULL;
|
|
754 }
|
|
755
|
|
756 if(variable->val_len)
|
|
757 {
|
|
758 error("agent_get(): val_len is not 0 for node %s", node->label);
|
|
759 variable->val_len = 0;
|
|
760 }
|
|
761
|
|
762 switch(node->type)
|
|
763 {
|
|
764 case OBJECT:
|
|
765 object = node->data.object;
|
|
766
|
|
767 if( (suffix.len != 1)
|
|
768 || (suffix.subids[0] != 0) )
|
|
769 {
|
|
770 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
771 pdu->error_index = index_err;
|
|
772 SSAOidZero(&suffix);
|
|
773 return 0;
|
|
774 }
|
|
775
|
|
776 if( !(object->access & READ_FLAG) )
|
|
777 {
|
|
778 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
779 pdu->error_index = index_err;
|
|
780 SSAOidZero(&suffix);
|
|
781 return 0;
|
|
782 }
|
|
783
|
|
784 switch(object->asn1_type)
|
|
785 {
|
|
786 case INTEGER:
|
|
787 case COUNTER:
|
|
788 case GAUGE:
|
|
789 case TIMETICKS:
|
|
790 snmp_error = (*(object->get))(&integer);
|
|
791 break;
|
|
792
|
|
793 case OBJID:
|
|
794 snmp_error = (*(object->get))(&oid);
|
|
795 if(snmp_error != SNMP_ERR_NOERROR &&
|
|
796 ssa_mem_free != 0){
|
|
797 if(object->dealloc != NULL)
|
|
798 (*(object->dealloc))(&oid);
|
|
799 }
|
|
800 break;
|
|
801
|
|
802 case STRING:
|
|
803 case IPADDRESS:
|
|
804 case OPAQUE:
|
|
805 snmp_error = (*(object->get))(&string);
|
|
806 if(snmp_error != SNMP_ERR_NOERROR &&
|
|
807 ssa_mem_free != 0){
|
|
808 if(object->dealloc != NULL)
|
|
809 (*(object->dealloc))(&string);
|
|
810 }
|
|
811 break;
|
|
812 }
|
|
813
|
|
814 if(snmp_error != SNMP_ERR_NOERROR)
|
|
815 {
|
|
816 if(snmp_error < 0)
|
|
817 {
|
|
818 error("the get() method of %s returned %d",
|
|
819 node->label,
|
|
820 snmp_error);
|
|
821 snmp_error = SNMP_ERR_GENERR;
|
|
822 }
|
|
823 pdu->error_status = snmp_error;
|
|
824 pdu->error_index = index_err;
|
|
825 SSAOidZero(&suffix);
|
|
826 return 0;
|
|
827 }
|
|
828
|
|
829 /* variable->name */
|
|
830
|
|
831 /* variable->type */
|
|
832 variable->type = object->asn1_type;
|
|
833
|
|
834 /* variable->val, variable->val_len */
|
|
835 switch(object->asn1_type)
|
|
836 {
|
|
837 case INTEGER:
|
|
838 case COUNTER:
|
|
839 case GAUGE:
|
|
840 case TIMETICKS:
|
|
841 variable->val.integer = (Integer *) malloc(sizeof(Integer));
|
|
842 *(variable->val.integer) = integer;
|
|
843 variable->val_len = sizeof(Integer);
|
|
844 break;
|
|
845
|
|
846 case OBJID:
|
|
847 variable->val.objid = (Subid *) malloc(oid.len *
|
|
848 (int32_t)sizeof(Subid));
|
|
849 (void)memcpy(variable->val.objid, oid.subids, oid.len *
|
|
850 (int32_t)sizeof(Subid));
|
|
851 variable->val_len = oid.len *
|
|
852 (int32_t)sizeof(Subid);
|
|
853 if (ssa_mem_free != 0){
|
|
854 if(object->dealloc != NULL)
|
|
855 (*(object->dealloc))(&oid);
|
|
856 }
|
|
857 break;
|
|
858
|
|
859 case STRING:
|
|
860 case IPADDRESS:
|
|
861 case OPAQUE:
|
|
862 variable->val.string = (u_char *) malloc(string.len);
|
|
863 (void)memcpy(variable->val.string, string.chars, string.len);
|
|
864 variable->val_len = string.len;
|
|
865 /*if(snmp_error != SNMP_ERR_NOERROR &&*/
|
|
866 if (ssa_mem_free != 0){
|
|
867 if(object->dealloc != NULL)
|
|
868 (*(object->dealloc))(&string);
|
|
869 }
|
|
870 break;
|
|
871 }
|
|
872
|
|
873
|
|
874 break;
|
|
875
|
|
876
|
|
877 case COLUMN:
|
|
878 column = node->data.column;
|
|
879 entry = column->entry;
|
|
880 pIndex=entry->first_index;
|
|
881
|
|
882 if( !(column->access & READ_FLAG) )
|
|
883 {
|
|
884 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
885 pdu->error_index = index_err;
|
|
886 SSAOidZero(&suffix);
|
|
887 return 0;
|
|
888 }
|
|
889
|
|
890 if (suffix.subids == NULL) {
|
|
891 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
892 pdu->error_index = index_err;
|
|
893 SSAOidZero(&suffix);
|
|
894 return 0;
|
|
895 }
|
|
896
|
|
897 index_len = 0;
|
|
898 for (pIndex=entry->first_index; pIndex; pIndex=pIndex->next_index)
|
|
899 {
|
|
900 if (pIndex->index_type == OCTET_STRING)
|
|
901 index_len = index_len + (pIndex->index_len)+1; /* add extra suffix for str len */
|
|
902 else
|
|
903 index_len = index_len +1; /* one subid per index */
|
|
904 }
|
|
905
|
|
906
|
|
907 for (i=0; i < index_len; i++)
|
|
908 {
|
|
909 index[i] = suffix.subids[i];
|
|
910 index_obj.value[i] = suffix.subids[i];
|
|
911 }
|
|
912 index_obj.len = index_len;
|
|
913 for (i=0; i < index_len; i++)
|
|
914 {
|
|
915 if( (cache_input_entry == entry) && (cache_input_index[i] == index[i]) )
|
|
916 was_cached = 1;
|
|
917 else
|
|
918 {
|
|
919 was_cached = 0;
|
|
920 break;
|
|
921 }
|
|
922 }
|
|
923 if (was_cached)
|
|
924 {
|
|
925 pointer = cache_output_pointer;
|
|
926 snmp_error = cache_output_snmp_error;
|
|
927 }
|
|
928 else
|
|
929 {
|
|
930 if(cache_input_entry != NULL && cache_output_pointer != NULL)
|
|
931 if(ssa_mem_free != 0 && cache_input_entry->dealloc != NULL)
|
|
932 {
|
|
933 (*(cache_input_entry->dealloc))(cache_output_pointer);
|
|
934 cache_output_pointer = NULL;
|
|
935 }
|
|
936 cache_input_entry = entry;
|
|
937 for (i=0; i < index_len; i++)
|
|
938 cache_input_index[i] = index[i];
|
|
939 snmp_error = (*(entry->get))(EXACT_ENTRY,&pointer,&index_obj);
|
|
940 cache_output_pointer = pointer;
|
|
941 cache_output_snmp_error = snmp_error;
|
|
942 }
|
|
943
|
|
944
|
|
945 if(pointer == NULL)
|
|
946 {
|
|
947 if(snmp_error < 0)
|
|
948 {
|
|
949 error("the get() method of %s returned %d",
|
|
950 node->parent->label,
|
|
951 snmp_error);
|
|
952 snmp_error = SNMP_ERR_GENERR;
|
|
953 }
|
|
954
|
|
955 pdu->error_status = snmp_error;
|
|
956 pdu->error_index = index_err;
|
|
957 SSAOidZero(&suffix);
|
|
958 return 0;
|
|
959 }
|
|
960
|
|
961 /* variable->type */
|
|
962 variable->type = column->asn1_type;
|
|
963
|
|
964 /* variable->val, variable->val_len */
|
|
965 switch(column->asn1_type)
|
|
966 {
|
|
967 case INTEGER:
|
|
968 case COUNTER:
|
|
969 case GAUGE:
|
|
970 case TIMETICKS:
|
|
971 integer_ptr = (Integer *) (pointer +
|
|
972 COLUMN_OFFSET(column->offset));
|
|
973 variable->val.integer = (Integer *) malloc(sizeof(Integer));
|
|
974 *(variable->val.integer) = *integer_ptr;
|
|
975 variable->val_len = sizeof(Integer);
|
|
976 break;
|
|
977
|
|
978 case OBJID:
|
|
979 oid_ptr = (Oid *) (pointer +
|
|
980 COLUMN_OFFSET(column->offset));
|
|
981 variable->val.objid = (Subid *) malloc(oid_ptr->len *
|
|
982 (int32_t)sizeof(Subid));
|
|
983 (void)memcpy(variable->val.objid, oid_ptr->subids, oid_ptr->len *
|
|
984 (int32_t)sizeof(Subid));
|
|
985 variable->val_len = oid_ptr->len *
|
|
986 (int32_t)sizeof(Subid);
|
|
987 break;
|
|
988
|
|
989 case STRING:
|
|
990 case IPADDRESS:
|
|
991 case OPAQUE:
|
|
992 string_ptr = (String *) (pointer +
|
|
993 COLUMN_OFFSET(column->offset));
|
|
994 variable->val.string = (u_char *) malloc(string_ptr->len);
|
|
995 (void)memcpy(variable->val.string, string_ptr->chars, string_ptr->len);
|
|
996 variable->val_len = string_ptr->len;
|
|
997 break;
|
|
998 }
|
|
999
|
|
1000 break;
|
|
1001
|
|
1002
|
|
1003 case NODE:
|
|
1004 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
1005 pdu->error_index = index_err;
|
|
1006 SSAOidZero(&suffix);
|
|
1007 return 0;
|
|
1008 }
|
|
1009
|
|
1010 SSAOidZero(&suffix);
|
|
1011
|
|
1012 index_err++;
|
|
1013 }
|
|
1014 /* Moved this down from the column loop because the cache must be
|
|
1015 freed only when the required columns in the row are all read.
|
|
1016 - Added pointer check because pointer will point to nothing
|
|
1017 if this is a non-column get.
|
|
1018 - Added setting cache_output_pointer to NULL because if it is not
|
|
1019 NULL, the next iteration of agent_process will try to delete it */
|
|
1020 /* Bug fix 4127458 . Added check to see if entry has been initialized */
|
|
1021 if(ssa_mem_free != 0 && entry != NULL && entry->dealloc != NULL && pointer != NULL){
|
|
1022 /* remember to turn off the caching */
|
|
1023 (*(entry->dealloc))(pointer);
|
|
1024 pointer = cache_output_pointer = NULL;
|
|
1025 }
|
|
1026
|
|
1027 return 0;
|
|
1028 }
|
|
1029
|
|
1030
|
|
1031 /****************************************************************/
|
|
1032
|
|
1033 /* returns */
|
|
1034 /* 0 in case of success. If we are in the */
|
|
1035 /* FIRST_PASS, we should go to the second pass. */
|
|
1036 /* -1 in case of failure. If we are in the */
|
|
1037 /* FIRST_PASS, we should not go to the */
|
|
1038 /* second pass and no pdu should be sent back. */
|
|
1039 /* 1 If we are in the FIRST_PASS, we should not go */
|
|
1040 /* to the second pass but a pdu */
|
|
1041 /* with an SNMP error should be sent back to its */
|
|
1042 /* originator */
|
|
1043
|
|
1044 static int agent_set(int pass, SNMP_pdu *pdu, char *error_label)
|
|
1045 {
|
|
1046 SNMP_variable *variable;
|
|
1047 Node *node;
|
|
1048 Object *object;
|
|
1049 Column *column;
|
|
1050 Entry *entry;
|
|
1051 Oid suffix;
|
|
1052 int index = 1;
|
|
1053 Integer integer = 0;
|
|
1054 Oid oid = { NULL, 0 };
|
|
1055 String string = { NULL, 0 };
|
|
1056 int snmp_error;
|
|
1057 int i;
|
|
1058
|
|
1059 /* create index struct */
|
|
1060 IndexType index_obj;
|
|
1061 int index_buffer[256];
|
|
1062
|
|
1063 index_obj.len = 0;
|
|
1064 index_obj.value = index_buffer;
|
|
1065
|
|
1066 error_label[0] = '\0';
|
|
1067
|
|
1068 pdu->type = GET_RSP_MSG;
|
|
1069
|
|
1070 for(variable = pdu->first_variable; variable; variable = variable->next_variable)
|
|
1071 {
|
|
1072 node = node_find(EXACT_ENTRY, &(variable->name), &suffix);
|
|
1073 if(node == NULL)
|
|
1074 {
|
|
1075 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
1076 pdu->error_index = index;
|
|
1077 return 1;
|
|
1078 }
|
|
1079 /* we should not forget to free suffix.subids */
|
|
1080
|
|
1081 if(trace_level > 0)
|
|
1082 {
|
|
1083 trace("!! set(%s): processing the variable %s\n\n",
|
|
1084 (pass == FIRST_PASS)? "FIRST_PASS": "SECOND_PASS",
|
|
1085 node->label);
|
|
1086 }
|
|
1087
|
|
1088 /*
|
|
1089 if(variable->val.string == NULL)
|
|
1090 {
|
|
1091 (void)sprintf(error_label, "val.string is NULL for node %s",
|
|
1092 node->label);
|
|
1093 SSAOidZero(&suffix);
|
|
1094 return -1;
|
|
1095 }
|
|
1096
|
|
1097 if(variable->val_len == 0)
|
|
1098 {
|
|
1099 (void)sprintf(error_label, "val_len is 0 for node %s",
|
|
1100 node->label);
|
|
1101 SSAOidZero(&suffix);
|
|
1102 return -1;
|
|
1103 }
|
|
1104 */
|
|
1105
|
|
1106 switch(node->type)
|
|
1107 {
|
|
1108 case OBJECT:
|
|
1109 object = node->data.object;
|
|
1110
|
|
1111 /* check the ASN.1 type */
|
|
1112 if(variable->type != object->asn1_type)
|
|
1113 {
|
|
1114 (void)sprintf(error_label, "wrong ASN.1 type (0x%x) for node %s",
|
|
1115 variable->type, node->label);
|
|
1116 SSAOidZero(&suffix);
|
|
1117 return -1;
|
|
1118 }
|
|
1119
|
|
1120 /* check the suffix */
|
|
1121 if( (suffix.len != 1)
|
|
1122 || (suffix.subids[0] != 0) )
|
|
1123 {
|
|
1124 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
1125 pdu->error_index = index;
|
|
1126 SSAOidZero(&suffix);
|
|
1127 return 1;
|
|
1128 }
|
|
1129
|
|
1130 /* check the access */
|
|
1131 if( !(object->access & WRITE_FLAG) )
|
|
1132 {
|
|
1133 pdu->error_status = SNMP_ERR_READONLY;
|
|
1134 pdu->error_index = index;
|
|
1135 SSAOidZero(&suffix);
|
|
1136 return 1;
|
|
1137 }
|
|
1138
|
|
1139 /* check the value length */
|
|
1140 switch(object->asn1_type)
|
|
1141 {
|
|
1142 case INTEGER:
|
|
1143 case COUNTER:
|
|
1144 case GAUGE:
|
|
1145 case TIMETICKS:
|
|
1146 case IPADDRESS:
|
|
1147 if(variable->val_len != 4)
|
|
1148 {
|
|
1149 (void)sprintf(error_label, "val_len is not 4 (%d) for node %s",
|
|
1150 variable->val_len, node->label);
|
|
1151 SSAOidZero(&suffix);
|
|
1152 return -1;
|
|
1153 }
|
|
1154
|
|
1155 if(variable->val.integer == NULL)
|
|
1156 {
|
|
1157 (void)sprintf(error_label, "val.integer is NULL for node %s",
|
|
1158 node->label);
|
|
1159 SSAOidZero(&suffix);
|
|
1160 return -1;
|
|
1161 }
|
|
1162
|
|
1163 break;
|
|
1164 }
|
|
1165
|
|
1166 /* in case of enumerated integer, check the value */
|
|
1167 if( (object->asn1_type == INTEGER)
|
|
1168 && (object->first_enum != NULL) )
|
|
1169 {
|
|
1170 Enum *enums;
|
|
1171
|
|
1172
|
|
1173 integer = *(variable->val.integer);
|
|
1174
|
|
1175 for(enums = object->first_enum; enums; enums = enums->next_enum)
|
|
1176 {
|
|
1177 if(enums->value == integer)
|
|
1178 {
|
|
1179 break;
|
|
1180 }
|
|
1181 }
|
|
1182
|
|
1183 if(enums == NULL)
|
|
1184 {
|
|
1185 pdu->error_status = SNMP_ERR_BADVALUE;
|
|
1186 pdu->error_index = index;
|
|
1187 SSAOidZero(&suffix);
|
|
1188 return 1;
|
|
1189 }
|
|
1190 }
|
|
1191
|
|
1192 switch(object->asn1_type)
|
|
1193 {
|
|
1194 case INTEGER:
|
|
1195 case COUNTER:
|
|
1196 case GAUGE:
|
|
1197 case TIMETICKS:
|
|
1198 integer = *(variable->val.integer);
|
|
1199
|
|
1200 snmp_error = (*(object->set))(pass, &integer);
|
|
1201 break;
|
|
1202
|
|
1203 case OBJID:
|
|
1204 if(SSAOidInit(&oid, variable->val.objid,
|
|
1205 variable->val_len / (int32_t)sizeof(Subid),
|
|
1206 error_label)) {
|
|
1207 SSAOidZero(&suffix);
|
|
1208 return -1;
|
|
1209 }
|
|
1210
|
|
1211 snmp_error = (*(object->set))(pass, &oid);
|
|
1212 SSAOidZero(&oid);
|
|
1213 break;
|
|
1214
|
|
1215 case STRING:
|
|
1216 case IPADDRESS:
|
|
1217 case OPAQUE:
|
|
1218 if(SSAStringInit(&string, variable->val.string,
|
|
1219 variable->val_len, error_label)) {
|
|
1220 SSAOidZero(&suffix);
|
|
1221 return -1;
|
|
1222 }
|
|
1223
|
|
1224 snmp_error = (*(object->set))(pass, &string);
|
|
1225 SSAStringZero(&string);
|
|
1226 break;
|
|
1227 }
|
|
1228
|
|
1229 if(snmp_error != SNMP_ERR_NOERROR)
|
|
1230 {
|
|
1231 if(snmp_error < 0)
|
|
1232 {
|
|
1233 error("the set(%s) method of %s returned %d",
|
|
1234 (pass == FIRST_PASS)? "FIRST_PASS": "SECOND_PASS",
|
|
1235 node->label, snmp_error);
|
|
1236 snmp_error = SNMP_ERR_GENERR;
|
|
1237 }
|
|
1238 pdu->error_status = snmp_error;
|
|
1239 pdu->error_index = index;
|
|
1240 SSAOidZero(&suffix);
|
|
1241 return 1;
|
|
1242 }
|
|
1243
|
|
1244 break;
|
|
1245
|
|
1246
|
|
1247 case COLUMN:
|
|
1248 column = node->data.column;
|
|
1249 entry = column->entry;
|
|
1250
|
|
1251 /* check the ASN.1 type */
|
|
1252 if(variable->type != column->asn1_type)
|
|
1253 {
|
|
1254 (void)sprintf(error_label, "wrong ASN.1 type (0x%x) for node %s",
|
|
1255 variable->type, node->label);
|
|
1256 SSAOidZero(&suffix);
|
|
1257 return -1;
|
|
1258 }
|
|
1259
|
|
1260 /* check the suffix */
|
|
1261 if (suffix.subids == NULL)
|
|
1262 {
|
|
1263 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
1264 pdu->error_index = index;
|
|
1265 SSAOidZero(&suffix);
|
|
1266 return 1;
|
|
1267 }
|
|
1268
|
|
1269 /* check the access */
|
|
1270 if( !(column->access & WRITE_FLAG) )
|
|
1271 {
|
|
1272 pdu->error_status = SNMP_ERR_READONLY;
|
|
1273 pdu->error_index = index;
|
|
1274 SSAOidZero(&suffix);
|
|
1275 return 1;
|
|
1276 }
|
|
1277
|
|
1278 /* check the value length */
|
|
1279 switch(column->asn1_type)
|
|
1280 {
|
|
1281 case INTEGER:
|
|
1282 case COUNTER:
|
|
1283 case GAUGE:
|
|
1284 case TIMETICKS:
|
|
1285 case IPADDRESS:
|
|
1286 if(variable->val_len != 4)
|
|
1287 {
|
|
1288 (void)sprintf(error_label, "val_len is not 4 (%d) for node %s",
|
|
1289 variable->val_len, node->label);
|
|
1290 SSAOidZero(&suffix);
|
|
1291 return -1;
|
|
1292 }
|
|
1293
|
|
1294 if(variable->val.integer == NULL)
|
|
1295 {
|
|
1296 (void)sprintf(error_label, "val.integer is NULL for node %s",
|
|
1297 node->label);
|
|
1298 SSAOidZero(&suffix);
|
|
1299 return -1;
|
|
1300 }
|
|
1301
|
|
1302 break;
|
|
1303 }
|
|
1304
|
|
1305 /* in case of enumerated integer, check the value */
|
|
1306 if( (column->asn1_type == INTEGER)
|
|
1307 && (column->first_enum != NULL) )
|
|
1308 {
|
|
1309 Enum *enums;
|
|
1310
|
|
1311
|
|
1312 integer = *(variable->val.integer);
|
|
1313
|
|
1314 for(enums = column->first_enum; enums; enums = enums->next_enum)
|
|
1315 {
|
|
1316 if(enums->value == integer)
|
|
1317 {
|
|
1318 break;
|
|
1319 }
|
|
1320 }
|
|
1321
|
|
1322 if(enums == NULL)
|
|
1323 {
|
|
1324 pdu->error_status = SNMP_ERR_BADVALUE;
|
|
1325 pdu->error_index = index;
|
|
1326 SSAOidZero(&suffix);
|
|
1327 return 1;
|
|
1328 }
|
|
1329 }
|
|
1330
|
|
1331 switch(column->asn1_type)
|
|
1332 {
|
|
1333 case INTEGER:
|
|
1334 case COUNTER:
|
|
1335 case GAUGE:
|
|
1336 case TIMETICKS:
|
|
1337 integer = *(variable->val.integer);
|
|
1338
|
|
1339 break;
|
|
1340
|
|
1341 case OBJID:
|
|
1342 if(SSAOidInit(&oid, variable->val.objid,
|
|
1343 variable->val_len / (int32_t)sizeof(Subid), error_label)) {
|
|
1344 SSAOidZero(&suffix);
|
|
1345 return -1;
|
|
1346 }
|
|
1347
|
|
1348 break;
|
|
1349
|
|
1350 case STRING:
|
|
1351 case IPADDRESS:
|
|
1352 case OPAQUE:
|
|
1353 if(SSAStringInit(&string, variable->val.string, variable->val_len, error_label))
|
|
1354 {
|
|
1355 SSAOidZero(&suffix);
|
|
1356 return -1;
|
|
1357 }
|
|
1358
|
|
1359 break;
|
|
1360 }
|
|
1361
|
|
1362 index_obj.len = suffix.len;
|
|
1363 for (i = 0; i < suffix.len; i++)
|
|
1364 {
|
|
1365 index_obj.value[i] = suffix.subids[i];
|
|
1366 }
|
|
1367
|
|
1368
|
|
1369 switch(column->asn1_type)
|
|
1370 {
|
|
1371 case INTEGER:
|
|
1372 case COUNTER:
|
|
1373 case GAUGE:
|
|
1374 case TIMETICKS:
|
|
1375 snmp_error = (*(column->set))(pass, index_obj, &integer);
|
|
1376 break;
|
|
1377
|
|
1378 case OBJID:
|
|
1379 snmp_error = (*(column->set))(pass, index_obj, &oid);
|
|
1380 break;
|
|
1381
|
|
1382 case STRING:
|
|
1383 case IPADDRESS:
|
|
1384 case OPAQUE:
|
|
1385 snmp_error = (*(column->set))(pass, index_obj, &string);
|
|
1386 break;
|
|
1387 }
|
|
1388
|
|
1389 switch(column->asn1_type)
|
|
1390 {
|
|
1391 case OBJID:
|
|
1392 SSAOidZero(&oid);
|
|
1393 break;
|
|
1394
|
|
1395 case STRING:
|
|
1396 case IPADDRESS:
|
|
1397 case OPAQUE:
|
|
1398 SSAStringZero(&string);
|
|
1399 break;
|
|
1400 }
|
|
1401
|
|
1402 if(snmp_error != SNMP_ERR_NOERROR)
|
|
1403 {
|
|
1404 if(snmp_error < 0)
|
|
1405 {
|
|
1406 error("the set(%s) method of %s returned %d",
|
|
1407 (pass == FIRST_PASS)? "FIRST_PASS": "SECOND_PASS",
|
|
1408 node->parent->label,
|
|
1409 snmp_error);
|
|
1410 snmp_error = SNMP_ERR_GENERR;
|
|
1411 }
|
|
1412
|
|
1413 pdu->error_status = snmp_error;
|
|
1414 pdu->error_index = index;
|
|
1415 SSAOidZero(&suffix);
|
|
1416 return 1;
|
|
1417 }
|
|
1418
|
|
1419 break;
|
|
1420
|
|
1421
|
|
1422 case NODE:
|
|
1423 pdu->error_status = SNMP_ERR_NOSUCHNAME;
|
|
1424 pdu->error_index = index;
|
|
1425 SSAOidZero(&suffix);
|
|
1426 return 1;
|
|
1427 }
|
|
1428
|
|
1429 SSAOidZero(&suffix);
|
|
1430
|
|
1431 index++;
|
|
1432 }
|
|
1433
|
|
1434 return 0;
|
|
1435 }
|
|
1436
|
|
1437
|
|
1438 /****************************************************************/
|
|
1439
|
|
1440 /* flag == 0 means turn off auto mem free */
|
|
1441 void SSAAutoMemFree(int flag)
|
|
1442 {
|
|
1443 ssa_mem_free = flag;
|
|
1444 }
|
|
1445
|
|
1446
|