comparison usr/src/cmd/agents/snmp/agent/agent.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
comparison
equal deleted inserted replaced
-1:000000000000 0:c9caec207d52
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