1 /*
2 * SNMPStats Module
3 * Copyright (C) 2006 SOMA Networks, INC.
4 * Written by: Jeffrey Magder (jmagder@somanetworks.com)
5 *
6 * This file is part of Kamailio, a free SIP server.
7 *
8 * Kamailio is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
12 *
13 * Kamailio is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 * USA
22 *
23 * The file implements the kamailioSIPStatusCodesTable. For a full description
24 * of the table, please see the KAMAILIO-SIP-COMMON-MIB.
25 *
26 * This file is much larger and more complicated than the files for other
27 * tables. This is because the table is settable, bringing a lot of SNMP
28 * overhead. Most of the file consists of the original auto-generated
29 * code (aside from white space and comment changes).
30 *
31 * The functions that have been modified to implement this table are the
32 * following:
33 *
34 * 1) kamailioSIPStatusCodesTable_create_row()
35 *
36 * - The row structure has been modified from its default to store the
37 * number of messages that have been received and sent with a certain
38 * status code, at the time this row was created. This function
39 * populates that data.
40 *
41 * 2) kamailioSIPStatusCodesTable_extract_index()
42 *
43 * - Modified to fail if the index is invalid. The index is invalid if it
44 * does not match up with the global userLookupCounter.
45 *
46 * 3) kamailioSIPStatusCodesTable_can_[activate|deactivate|delete]()
47 *
48 * - Simplified to always allow activation/deactivation/deletion.
49 *
50 * 4) kamailioSIPStatusCodesTable_set_reserve1()
51 *
52 * - The reserve1 phase passes if the row is new, and the rowStatus column
53 * is being set to 'createAndGo'
54 *
55 * - The reserve1 phase passes if the row is not new, and the rowStatus
56 * column is being set to 'destroy'
57 *
58 * 5) kamailioSIPStatusCodesTable_get_value()
59 *
60 * - Instead of returning a variable binding to either
61 * kamailioSIPStatusCodeIns or kamailioSIPStatusCodeOuts, the function
62 * returns a variable binding equal to the current value as per the
63 * statistics framework, minus either kamailioSIPStatusCodeIns or
64 * kamailioSIPStatusCodeOuts
65 *
66 * You can safely ignore the other functions.
67 *
68 */
69
70 #include <net-snmp/net-snmp-config.h>
71 #include <net-snmp/net-snmp-includes.h>
72 #include <net-snmp/agent/net-snmp-agent-includes.h>
73
74 #include <net-snmp/library/snmp_assert.h>
75
76 #include "snmpSIPStatusCodesTable.h"
77 #include "snmpstats_globals.h"
78 #include "snmp_statistics.h"
79
80 static netsnmp_handler_registration *my_handler = NULL;
81 static netsnmp_table_array_callbacks cb;
82
83 oid kamailioSIPStatusCodesTable_oid[] = {kamailioSIPStatusCodesTable_TABLE_OID};
84
85 size_t kamailioSIPStatusCodesTable_oid_len =
86 OID_LENGTH(kamailioSIPStatusCodesTable_oid);
87
88
89 /*
90 * Initializes the kamailioSIPStatusCodesTable module. This step is easier
91 * than in the other tables because there is no table population. All table
92 * population takes place during run time.
93 */
init_kamailioSIPStatusCodesTable(void)94 void init_kamailioSIPStatusCodesTable(void)
95 {
96 initialize_table_kamailioSIPStatusCodesTable();
97 }
98
99
100 /* the *_row_copy routine */
kamailioSIPStatusCodesTable_row_copy(kamailioSIPStatusCodesTable_context * dst,kamailioSIPStatusCodesTable_context * src)101 static int kamailioSIPStatusCodesTable_row_copy(
102 kamailioSIPStatusCodesTable_context *dst,
103 kamailioSIPStatusCodesTable_context *src)
104 {
105 if(!dst || !src)
106 return 1;
107
108
109 /* copy index, if provided */
110 if(dst->index.oids) {
111 free(dst->index.oids);
112 }
113
114 if(snmp_clone_mem((void *)&dst->index.oids, src->index.oids,
115 src->index.len * sizeof(oid))) {
116 dst->index.oids = NULL;
117 return 1;
118 }
119
120 dst->index.len = src->index.len;
121
122
123 /* copy components into the context structure */
124 dst->kamailioSIPStatusCodeMethod = src->kamailioSIPStatusCodeMethod;
125 dst->kamailioSIPStatusCodeValue = src->kamailioSIPStatusCodeValue;
126 dst->kamailioSIPStatusCodeIns = src->kamailioSIPStatusCodeIns;
127 dst->kamailioSIPStatusCodeOuts = src->kamailioSIPStatusCodeOuts;
128 dst->kamailioSIPStatusCodeRowStatus = src->kamailioSIPStatusCodeRowStatus;
129
130 return 0;
131 }
132
133 /*
134 * the *_extract_index routine (Mostly auto-generated)
135 *
136 * This routine is called when a set request is received for an index that
137 * was not found in the table container. Here, we parse the oid in the
138 * individual index components and copy those indexes to the context. Then
139 * we make sure the indexes for the new row are valid.
140 *
141 * It has been modified from its original form in that the indexes aren't
142 * returned if they are invalid. An index is invalid if it is not between
143 * 100 and 699 (Inclusive).
144 */
kamailioSIPStatusCodesTable_extract_index(kamailioSIPStatusCodesTable_context * ctx,netsnmp_index * hdr)145 int kamailioSIPStatusCodesTable_extract_index(
146 kamailioSIPStatusCodesTable_context *ctx, netsnmp_index *hdr)
147 {
148
149 /*
150 * temporary local storage for extracting oid index
151 *
152 * extract index uses varbinds (netsnmp_variable_list) to parse
153 * the index OID into the individual components for each index part.
154 */
155 netsnmp_variable_list var_kamailioSIPStatusCodeMethod;
156 netsnmp_variable_list var_kamailioSIPStatusCodeValue;
157 int err;
158
159 /*
160 * copy index, if provided
161 */
162 if(hdr) {
163 netsnmp_assert(ctx->index.oids == NULL);
164 if((hdr->len > MAX_OID_LEN)
165 || snmp_clone_mem((void *)&ctx->index.oids, hdr->oids,
166 hdr->len * sizeof(oid))) {
167 return -1;
168 }
169
170 ctx->index.len = hdr->len;
171 }
172
173 /* Initialize the two variables responsible for holding our two indices.
174 */
175 memset(&var_kamailioSIPStatusCodeMethod, 0x00,
176 sizeof(var_kamailioSIPStatusCodeMethod));
177
178 memset(&var_kamailioSIPStatusCodeValue, 0x00,
179 sizeof(var_kamailioSIPStatusCodeValue));
180
181 var_kamailioSIPStatusCodeMethod.type = ASN_UNSIGNED;
182 var_kamailioSIPStatusCodeValue.type = ASN_UNSIGNED;
183
184 var_kamailioSIPStatusCodeMethod.next_variable =
185 &var_kamailioSIPStatusCodeValue;
186
187 var_kamailioSIPStatusCodeValue.next_variable = NULL;
188
189 if(hdr) {
190 /* parse the oid into the individual index components */
191 err = parse_oid_indexes(
192 hdr->oids, hdr->len, &var_kamailioSIPStatusCodeMethod);
193
194 if(err == SNMP_ERR_NOERROR) {
195
196 /* copy index components into the context structure */
197 ctx->kamailioSIPStatusCodeMethod =
198 *var_kamailioSIPStatusCodeMethod.val.integer;
199 ctx->kamailioSIPStatusCodeValue =
200 *var_kamailioSIPStatusCodeValue.val.integer;
201
202
203 if(*var_kamailioSIPStatusCodeMethod.val.integer < 1) {
204 err = -1;
205 }
206
207 if(*var_kamailioSIPStatusCodeValue.val.integer < 100
208 || *var_kamailioSIPStatusCodeValue.val.integer > 699) {
209 err = -1;
210 }
211 }
212
213 /* parsing may have allocated memory. free it. */
214 snmp_reset_var_buffers(&var_kamailioSIPStatusCodeMethod);
215
216 return err;
217 }
218
219 return -1;
220 }
221
222
223 /*
224 * This is an auto-generated function. In general the *_can_activate routine
225 * is called when a row is changed to determine if all the values set are
226 * consistent with the row's rules for a row status of ACTIVE. If not, then 0
227 * can be returned to prevent the row status from becomming final.
228 *
229 * For our purposes, we have no need for this check, so we always return 1.
230 */
kamailioSIPStatusCodesTable_can_activate(kamailioSIPStatusCodesTable_context * undo_ctx,kamailioSIPStatusCodesTable_context * row_ctx,netsnmp_request_group * rg)231 int kamailioSIPStatusCodesTable_can_activate(
232 kamailioSIPStatusCodesTable_context *undo_ctx,
233 kamailioSIPStatusCodesTable_context *row_ctx, netsnmp_request_group *rg)
234 {
235 return 1;
236 }
237
238
239 /*
240 * This is an auto-generated function. In general the *_can_deactivate routine
241 * is called when a row that is currently ACTIVE is set to a state other than
242 * ACTIVE. If there are conditions in which a row should not be allowed to
243 * transition out of the ACTIVE state (such as the row being referred to by
244 * another row or table), check for them here.
245 *
246 * Since this table has no reason why this shouldn't be allowed, we always
247 * return 1;
248 */
kamailioSIPStatusCodesTable_can_deactivate(kamailioSIPStatusCodesTable_context * undo_ctx,kamailioSIPStatusCodesTable_context * row_ctx,netsnmp_request_group * rg)249 int kamailioSIPStatusCodesTable_can_deactivate(
250 kamailioSIPStatusCodesTable_context *undo_ctx,
251 kamailioSIPStatusCodesTable_context *row_ctx, netsnmp_request_group *rg)
252 {
253 return 1;
254 }
255
256
257 /*
258 * This is an auto-generated function. In general the *_can_delete routine is
259 * called to determine if a row can be deleted. This usually involved checking
260 * if it can be deactivated, and if it can be, then checking for other
261 * conditions.
262 *
263 * Since this table ha no reason why row deletion shouldn't be allowed, we
264 * always return 1, unless we can't deactivate.
265 */
kamailioSIPStatusCodesTable_can_delete(kamailioSIPStatusCodesTable_context * undo_ctx,kamailioSIPStatusCodesTable_context * row_ctx,netsnmp_request_group * rg)266 int kamailioSIPStatusCodesTable_can_delete(
267 kamailioSIPStatusCodesTable_context *undo_ctx,
268 kamailioSIPStatusCodesTable_context *row_ctx, netsnmp_request_group *rg)
269 {
270 if(kamailioSIPStatusCodesTable_can_deactivate(undo_ctx, row_ctx, rg) != 1)
271 return 0;
272
273 return 1;
274 }
275
276 /*
277 * (Mostly auto-generated function)
278 *
279 * The *_create_row routine is called by the table handler to create a new row
280 * for a given index. This is the first stage of the row creation process. The
281 * *_set_reserve_* functions can be used to prevent the row from being inserted
282 * into the table even if the row passes any preliminary checks set here.
283 *
284 * Returns a newly allocated kamailioSIPRegUserLookupTable_context structure (a
285 * row in the table) if the indexes are legal. NULL will be returned otherwise.
286 *
287 * The function has been modified from its original form, in that it will store
288 * the number of messages 'in' to the system, and the number of messages 'out'
289 * of the system, that had a status code matching this rows status code, at the
290 * time this row was created.
291 *
292 * This value will be used in the future to calculate the delta between now and
293 * the time this row has been read.
294 * */
kamailioSIPStatusCodesTable_create_row(netsnmp_index * hdr)295 kamailioSIPStatusCodesTable_context *kamailioSIPStatusCodesTable_create_row(
296 netsnmp_index *hdr)
297 {
298 stat_var *in_status_code;
299 stat_var *out_status_code;
300
301 kamailioSIPStatusCodesTable_context *ctx =
302 SNMP_MALLOC_TYPEDEF(kamailioSIPStatusCodesTable_context);
303 if(!ctx)
304 return NULL;
305
306 /* The *_extract_index funtion already validates the indices, so we
307 * don't need to do any further evaluations here. */
308 if(kamailioSIPStatusCodesTable_extract_index(ctx, hdr)) {
309 if(NULL != ctx->index.oids)
310 free(ctx->index.oids);
311 free(ctx);
312 return NULL;
313 }
314
315
316 /* The indices were already set up in the extract_index function
317 * above. */
318 ctx->kamailioSIPStatusCodeIns = 0;
319 ctx->kamailioSIPStatusCodeOuts = 0;
320 ctx->kamailioSIPStatusCodeRowStatus = 0;
321
322 /* Retrieve the index for the status code, and then assign the starting
323 * values. The starting values will be used to calculate deltas during
324 * the next snmpget/snmpwalk/snmptable/etc. */
325 int codeIndex = ctx->kamailioSIPStatusCodeValue;
326
327 ctx->startingInStatusCodeValue = 0;
328 ctx->startingOutStatusCodeValue = 0;
329
330 in_status_code = get_stat_var_from_num_code(codeIndex, 0);
331 out_status_code = get_stat_var_from_num_code(codeIndex, 1);
332
333 if(in_status_code != NULL) {
334 ctx->startingInStatusCodeValue = get_stat_val(in_status_code);
335 }
336
337 if(out_status_code != NULL) {
338 ctx->startingOutStatusCodeValue = get_stat_val(out_status_code);
339 }
340
341 return ctx;
342 }
343
344
345 /*
346 * Auto-generated function. The *_duplicate row routine
347 */
kamailioSIPStatusCodesTable_duplicate_row(kamailioSIPStatusCodesTable_context * row_ctx)348 kamailioSIPStatusCodesTable_context *kamailioSIPStatusCodesTable_duplicate_row(
349 kamailioSIPStatusCodesTable_context *row_ctx)
350 {
351 kamailioSIPStatusCodesTable_context *dup;
352
353 if(!row_ctx)
354 return NULL;
355
356 dup = SNMP_MALLOC_TYPEDEF(kamailioSIPStatusCodesTable_context);
357 if(!dup)
358 return NULL;
359
360 if(kamailioSIPStatusCodesTable_row_copy(dup, row_ctx)) {
361 free(dup);
362 dup = NULL;
363 }
364
365 return dup;
366 }
367
368
369 /*
370 * The *_delete_row method is auto-generated, and is called to delete a row.
371 *
372 * This will not be called if earlier checks said that this row can't be
373 * deleted. However, in our implementation there is never a reason why this
374 * function can't be called.
375 */
kamailioSIPStatusCodesTable_delete_row(kamailioSIPStatusCodesTable_context * ctx)376 netsnmp_index *kamailioSIPStatusCodesTable_delete_row(
377 kamailioSIPStatusCodesTable_context *ctx)
378 {
379 if(ctx->index.oids)
380 free(ctx->index.oids);
381
382 free(ctx);
383
384 return NULL;
385 }
386
387
388 /*
389 * Large parts of this function have been auto-generated. The functions purpose
390 * is to check to make sure all SNMP set values for the given row, have been
391 * valid. If not, then the process is supposed to be aborted. Otherwise, we
392 * pass on to the *_reserve2 function.
393 *
394 * For our purposes, our only check is to make sure that either of the following
395 * conditions are true:
396 *
397 * 1) If this row already exists, then the SET request is setting the rowStatus
398 * column to 'destroy'.
399 *
400 * 2) If this row does not already exist, then the SET request is setting the
401 * rowStatus to 'createAndGo'.
402 *
403 * Since the MIB specified there are to be no other modifications to the row,
404 * any other condition is considered illegal, and will result in an SNMP error
405 * being returned.
406 */
kamailioSIPStatusCodesTable_set_reserve1(netsnmp_request_group * rg)407 void kamailioSIPStatusCodesTable_set_reserve1(netsnmp_request_group *rg)
408 {
409 kamailioSIPStatusCodesTable_context *row_ctx =
410 (kamailioSIPStatusCodesTable_context *)rg->existing_row;
411
412 netsnmp_variable_list *var;
413 netsnmp_request_group_item *current;
414
415 int rc;
416
417 /* Loop through the specified columns, and make sure that all values are
418 * valid. */
419 for(current = rg->list; current; current = current->next) {
420
421 var = current->ri->requestvb;
422 rc = SNMP_ERR_NOERROR;
423
424 switch(current->tri->colnum) {
425 case COLUMN_KAMAILIOSIPSTATUSCODEROWSTATUS:
426
427 /** RowStatus = ASN_INTEGER */
428 rc = netsnmp_check_vb_type_and_size(var, ASN_INTEGER,
429 sizeof(row_ctx->kamailioSIPStatusCodeRowStatus));
430
431 /* Want to make sure that if it already exists that it
432 * is setting it to 'destroy', or if it doesn't exist,
433 * that it is setting it to 'createAndGo' */
434 if(row_ctx->kamailioSIPStatusCodeRowStatus == 0
435 && *var->val.integer != TC_ROWSTATUS_CREATEANDGO) {
436 rc = SNMP_ERR_BADVALUE;
437 }
438
439 else if(row_ctx->kamailioSIPStatusCodeRowStatus
440 == TC_ROWSTATUS_ACTIVE
441 && *var->val.integer != TC_ROWSTATUS_DESTROY) {
442 rc = SNMP_ERR_BADVALUE;
443 }
444
445
446 break;
447
448 default: /** We shouldn't get here */
449 rc = SNMP_ERR_GENERR;
450 snmp_log(LOG_ERR, "unknown column in kamailioSIP"
451 "StatusCodesTable_set_reserve1\n");
452 }
453
454 if(rc) {
455 netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc);
456 }
457
458 rg->status = SNMP_MAX(rg->status, current->ri->status);
459 }
460 }
461
462 /*
463 * Auto-generated function. The function is supposed to check for any
464 * last-minute conditions not being met. However, we don't have any such
465 * conditions, so we leave the default function as is.
466 */
kamailioSIPStatusCodesTable_set_reserve2(netsnmp_request_group * rg)467 void kamailioSIPStatusCodesTable_set_reserve2(netsnmp_request_group *rg)
468 {
469 kamailioSIPStatusCodesTable_context *undo_ctx =
470 (kamailioSIPStatusCodesTable_context *)rg->undo_info;
471
472 netsnmp_request_group_item *current;
473
474 int rc;
475
476 rg->rg_void = rg->list->ri;
477
478 for(current = rg->list; current; current = current->next) {
479
480 rc = SNMP_ERR_NOERROR;
481
482 switch(current->tri->colnum) {
483
484 case COLUMN_KAMAILIOSIPSTATUSCODEROWSTATUS:
485 /** RowStatus = ASN_INTEGER */
486 rc = netsnmp_check_vb_rowstatus(current->ri->requestvb,
487 undo_ctx ? undo_ctx->kamailioSIPStatusCodeRowStatus
488 : 0);
489
490 rg->rg_void = current->ri;
491 break;
492
493 default: /** We shouldn't get here */
494 netsnmp_assert(0); /** why wasn't this caught in reserve1? */
495 }
496
497 if(rc) {
498 netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc);
499 }
500 }
501 }
502
503 /*
504 * This function is called only when all the *_reserve[1|2] functions were
505 * succeful. Its purpose is to make any changes to the row before it is
506 * inserted into the table.
507 *
508 * In our case, we don't require any changes. So we leave the original
509 * auto-generated code as is.
510 */
kamailioSIPStatusCodesTable_set_action(netsnmp_request_group * rg)511 void kamailioSIPStatusCodesTable_set_action(netsnmp_request_group *rg)
512 {
513 netsnmp_variable_list *var;
514
515 kamailioSIPStatusCodesTable_context *row_ctx =
516 (kamailioSIPStatusCodesTable_context *)rg->existing_row;
517
518 kamailioSIPStatusCodesTable_context *undo_ctx =
519 (kamailioSIPStatusCodesTable_context *)rg->undo_info;
520
521 netsnmp_request_group_item *current;
522
523 int row_err = 0;
524
525 /* Depending on what the snmpset was, set the row to be created or
526 * deleted. */
527 for(current = rg->list; current; current = current->next) {
528 var = current->ri->requestvb;
529
530 switch(current->tri->colnum) {
531 case COLUMN_KAMAILIOSIPSTATUSCODEROWSTATUS:
532
533 /** RowStatus = ASN_INTEGER */
534 row_ctx->kamailioSIPStatusCodeRowStatus = *var->val.integer;
535
536 if(*var->val.integer == TC_ROWSTATUS_CREATEANDGO) {
537 rg->row_created = 1;
538 } else if(*var->val.integer == TC_ROWSTATUS_DESTROY) {
539 rg->row_deleted = 1;
540 } else {
541 /* We should never be here, because the RESERVE
542 * functions should have taken care of all other
543 * values. */
544 LM_ERR("Invalid RowStatus in "
545 "kamailioSIPStatusCodesTable\n");
546 }
547
548 break;
549
550 default: /** We shouldn't get here */
551 netsnmp_assert(0); /** why wasn't this caught in reserve1? */
552 }
553 }
554
555 /*
556 * done with all the columns. Could check row related
557 * requirements here.
558 */
559 #ifndef kamailioSIPStatusCodesTable_CAN_MODIFY_ACTIVE_ROW
560 if(undo_ctx && RS_IS_ACTIVE(undo_ctx->kamailioSIPStatusCodeRowStatus)
561 && row_ctx
562 && RS_IS_ACTIVE(row_ctx->kamailioSIPStatusCodeRowStatus)) {
563 row_err = 1;
564 }
565 #endif
566
567 LM_DBG("stage row_err = %d\n", row_err);
568
569 /*
570 * check activation/deactivation
571 */
572 row_err = netsnmp_table_array_check_row_status(&cb, rg,
573 row_ctx ? &row_ctx->kamailioSIPStatusCodeRowStatus : NULL,
574 undo_ctx ? &undo_ctx->kamailioSIPStatusCodeRowStatus : NULL);
575 if(row_err) {
576 netsnmp_set_mode_request_error(
577 MODE_SET_BEGIN, (netsnmp_request_info *)rg->rg_void, row_err);
578 return;
579 }
580 }
581
582
583 /*
584 * The COMMIT phase is used to do any extra processing after the ACTION phase.
585 * In our table, there is nothing to do, so the function body is empty.
586 */
kamailioSIPStatusCodesTable_set_commit(netsnmp_request_group * rg)587 void kamailioSIPStatusCodesTable_set_commit(netsnmp_request_group *rg)
588 {
589 }
590
591
592 /*
593 * This function is called if the *_reserve[1|2] calls failed. Its supposed to
594 * free up any resources allocated earlier. However, we already take care of
595 * all these resources in earlier functions. So for our purposes, the function
596 * body is empty.
597 */
kamailioSIPStatusCodesTable_set_free(netsnmp_request_group * rg)598 void kamailioSIPStatusCodesTable_set_free(netsnmp_request_group *rg)
599 {
600 }
601
602
603 /*
604 * This function is called if an ACTION phase fails, to do extra clean-up work.
605 * We don't have anything complicated enough to warrant putting anything in this
606 * function. Therefore, its just left with an empty function body.
607 */
kamailioSIPStatusCodesTable_set_undo(netsnmp_request_group * rg)608 void kamailioSIPStatusCodesTable_set_undo(netsnmp_request_group *rg)
609 {
610 }
611
612
613 /*
614 * Initialize the kamailioSIPStatusCodesTable table by defining how it is
615 * structured.
616 *
617 * This function is mostly auto-generated.
618 */
initialize_table_kamailioSIPStatusCodesTable(void)619 void initialize_table_kamailioSIPStatusCodesTable(void)
620 {
621 netsnmp_table_registration_info *table_info;
622
623 if(my_handler) {
624 snmp_log(LOG_ERR, "initialize_table_kamailioSIPStatusCodes"
625 "Table_handler called again\n");
626 return;
627 }
628
629 memset(&cb, 0x00, sizeof(cb));
630
631 /** create the table structure itself */
632 table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
633 if(!table_info) {
634 snmp_log(LOG_ERR, "failed to allocate table_info\n");
635 return;
636 }
637
638 my_handler = netsnmp_create_handler_registration(
639 "kamailioSIPStatusCodesTable", netsnmp_table_array_helper_handler,
640 kamailioSIPStatusCodesTable_oid,
641 kamailioSIPStatusCodesTable_oid_len, HANDLER_CAN_RWRITE);
642
643 if(!my_handler) {
644 SNMP_FREE(table_info);
645 snmp_log(LOG_ERR, "malloc failed in initialize_table_kamailioSIP"
646 "StatusCodesTable_handler\n");
647 return; /** mallocs failed */
648 }
649
650 /** index: kamailioSIPStatusCodeMethod */
651 netsnmp_table_helper_add_index(table_info, ASN_UNSIGNED);
652 /** index: kamailioSIPStatusCodeValue */
653 netsnmp_table_helper_add_index(table_info, ASN_UNSIGNED);
654
655 table_info->min_column = kamailioSIPStatusCodesTable_COL_MIN;
656 table_info->max_column = kamailioSIPStatusCodesTable_COL_MAX;
657
658 /***************************************************
659 * registering the table with the master agent
660 */
661 cb.get_value = kamailioSIPStatusCodesTable_get_value;
662
663 cb.container = netsnmp_container_find("kamailioSIPStatusCodesTable_primary:"
664 "kamailioSIPStatusCodesTable:"
665 "table_container");
666
667 #ifdef kamailioSIPStatusCodesTable_CUSTOM_SORT
668 netsnmp_container_add_index(cb.container,
669 netsnmp_container_find("kamailioSIPStatusCodesTable_custom:"
670 "kamailioSIPStatusCodesTable:"
671 "table_container"));
672
673 cb.container->next->compare = kamailioSIPStatusCodesTable_cmp;
674 #endif
675 cb.can_set = 1;
676
677 cb.create_row = (UserRowMethod *)kamailioSIPStatusCodesTable_create_row;
678
679 cb.duplicate_row =
680 (UserRowMethod *)kamailioSIPStatusCodesTable_duplicate_row;
681
682 cb.delete_row = (UserRowMethod *)kamailioSIPStatusCodesTable_delete_row;
683
684 cb.row_copy =
685 (Netsnmp_User_Row_Operation *)kamailioSIPStatusCodesTable_row_copy;
686
687 cb.can_activate =
688 (Netsnmp_User_Row_Action *)kamailioSIPStatusCodesTable_can_activate;
689
690 cb.can_deactivate = (Netsnmp_User_Row_Action *)
691 kamailioSIPStatusCodesTable_can_deactivate;
692
693 cb.can_delete =
694 (Netsnmp_User_Row_Action *)kamailioSIPStatusCodesTable_can_delete;
695
696 cb.set_reserve1 = kamailioSIPStatusCodesTable_set_reserve1;
697 cb.set_reserve2 = kamailioSIPStatusCodesTable_set_reserve2;
698
699 cb.set_action = kamailioSIPStatusCodesTable_set_action;
700 cb.set_commit = kamailioSIPStatusCodesTable_set_commit;
701
702 cb.set_free = kamailioSIPStatusCodesTable_set_free;
703 cb.set_undo = kamailioSIPStatusCodesTable_set_undo;
704
705 DEBUGMSGTL(("initialize_table_kamailioSIPStatusCodesTable",
706 "Registering table kamailioSIPStatusCodesTable "
707 "as a table array\n"));
708
709 netsnmp_table_container_register(
710 my_handler, table_info, &cb, cb.container, 1);
711 }
712
713 /*
714 * This function is called to handle SNMP GET requests.
715 *
716 * The row which this function is called with, will store a message code. The
717 * function will retrieve the 'number of messages in' and 'number of messages
718 * out' statistic for this particular message code from the statistics
719 * framework.
720 *
721 * The function will then subtract from this value the value it was initialized
722 * with when the row was first created. In this sense, the row shows how many
723 * ins and how many outs have been received (With respect to the message code)
724 * since this row was created.
725 */
kamailioSIPStatusCodesTable_get_value(netsnmp_request_info * request,netsnmp_index * item,netsnmp_table_request_info * table_info)726 int kamailioSIPStatusCodesTable_get_value(netsnmp_request_info *request,
727 netsnmp_index *item, netsnmp_table_request_info *table_info)
728 {
729 stat_var *the_stat;
730
731 netsnmp_variable_list *var = request->requestvb;
732
733 kamailioSIPStatusCodesTable_context *context =
734 (kamailioSIPStatusCodesTable_context *)item;
735
736 /* Retrieve the statusCodeIdx so we can calculate deltas between current
737 * values and previous values. */
738 int statusCodeIdx = context->kamailioSIPStatusCodeValue;
739
740 switch(table_info->colnum) {
741 case COLUMN_KAMAILIOSIPSTATUSCODEINS:
742
743 context->kamailioSIPStatusCodeIns = 0;
744
745 the_stat = get_stat_var_from_num_code(statusCodeIdx, 0);
746
747 if(the_stat != NULL) {
748 /* Calculate the Delta */
749 context->kamailioSIPStatusCodeIns =
750 get_stat_val(the_stat)
751 - context->startingInStatusCodeValue;
752 }
753
754 snmp_set_var_typed_value(var, ASN_COUNTER,
755 (unsigned char *)&context->kamailioSIPStatusCodeIns,
756 sizeof(context->kamailioSIPStatusCodeIns));
757 break;
758
759 case COLUMN_KAMAILIOSIPSTATUSCODEOUTS:
760
761 context->kamailioSIPStatusCodeOuts = 0;
762
763 the_stat = get_stat_var_from_num_code(statusCodeIdx, 1);
764
765 if(the_stat != NULL) {
766 /* Calculate the Delta */
767 context->kamailioSIPStatusCodeOuts =
768 get_stat_val(the_stat)
769 - context->startingOutStatusCodeValue;
770 }
771 snmp_set_var_typed_value(var, ASN_COUNTER,
772 (unsigned char *)&context->kamailioSIPStatusCodeOuts,
773 sizeof(context->kamailioSIPStatusCodeOuts));
774 break;
775
776 case COLUMN_KAMAILIOSIPSTATUSCODEROWSTATUS:
777 /** RowStatus = ASN_INTEGER */
778 snmp_set_var_typed_value(var, ASN_INTEGER,
779 (unsigned char *)&context->kamailioSIPStatusCodeRowStatus,
780 sizeof(context->kamailioSIPStatusCodeRowStatus));
781 break;
782
783 default: /** We shouldn't get here */
784 snmp_log(LOG_ERR, "unknown column in "
785 "kamailioSIPStatusCodesTable_get_value\n");
786 return SNMP_ERR_GENERR;
787 }
788 return SNMP_ERR_NOERROR;
789 }
790
791 /*
792 * kamailioSIPRegUserLookupTable_get_by_idx
793 */
794 const kamailioSIPStatusCodesTable_context *
kamailioSIPStatusCodesTable_get_by_idx(netsnmp_index * hdr)795 kamailioSIPStatusCodesTable_get_by_idx(netsnmp_index *hdr)
796 {
797 return (const kamailioSIPStatusCodesTable_context *)CONTAINER_FIND(
798 cb.container, hdr);
799 }
800