/usr/share/snmp/mib2c-data/mfd-access-unsorted-external-defines.m2i is in libsnmp-base 5.7.2.1+dfsg-1+deb8u1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 | ############################################################# -*- c -*-
## generic include for XXX. Do not use directly.
##
## $Id$
########################################################################
##
@eval $mfd_aue_wrap_param = "wrap_ctx"@
@eval $mfd_aue_wrap_param_type = "${context}_interface_ctx *"@
@eval $mfd_aue_wrap_param_decl = "$mfd_aue_wrap_param_type $mfd_aue_wrap_param"@
##
@eval $mfd_aue_param = "${context}_reg"@
@eval $mfd_aue_param_type = "${context}_registration *"@
@eval $mfd_aue_param_decl = "$mfd_aue_param_type $mfd_aue_param"@
@eval $mfd_aue_param_cmt = "$mfd_aue_param Pointer to a $mfd_aue_param_type"
##
@if $m2c_mark_boundary == 1@
/** START code generated by $RCSfile$ $Revision$ */
@end@
##//####################################################################
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@if $m2c_processing_type eq 'h'@
##
@if $m2c_include_examples == 1@
$example_start
/* *********************************************************************
* Since we have no idea how you really access your data, we'll go with
* a worst case example: a flat text file.
@ if $m2c_data_transient != 2@
@ print Example code is for fully transient data. Either turn off@
@ print m2c_include_examples or set m2c_data_transient to 2.@
@ exit@
@ end@
*/
#define MAX_LINE_SIZE 256
$example_end
@end@
/**
* loop context
*
* ToDo:
* define loop context structure
*
* Since the actual loop is in the MFD handler, a loop contex parameter
* is provided to help you keep track of where you are in between calls
* to functions that you wrote and the master MFD handler calls. The
* structure of this context is user defineable, and is defined in the
* file ${table}_data_access.h.
*
* E.G., if your data is stored in a linked list, the obvious thing you
* want to know from one function call to the next is your current
* position in the linked list. Thus the easiest context to use is a
* pointer within the linked list. For an array, the current index to
* that array would be easiest.
*
* The funtion calls are actually passed a reference to the loop
* context, to allow the loop context to be allocated memory. Here are
* some simple examples definitions for various data formats. These
* definitions are used in examples later on.
*
*/
typedef struct ${context}_loop_context_s {
/*
* temporary context used during iteration
*/
${context}_rowreq_ctx *rowreq_ctx;
@if $m2c_include_examples == 1@
/*
* this example code is based on a data source that is a
* text file to be read and parsed.
*/
FILE *filep;
char line[MAX_LINE_SIZE];
@end@
} ${context}_loop_context;
/*
* define a reference to the loop context
*
* NOTE: DO NOT ADD ITEMS TO THIS STRUCTURE!
*/
typedef struct ${context}_ref_loop_ctx_s {
${context}_loop_context *loop_ctx;
} ${context}_ref_loop_ctx;
int ${context}_loop_get_first( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_rowreq_ctx *rowreq_ctx_ref);
int ${context}_loop_get_next( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_rowreq_ctx *rowreq_ctx_ref);
int ${context}_loop_get_data( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_rowreq_ctx *rowreq_ctx_ref);
int ${context}_loop_save_position($mfd_aue_param_decl,
${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_loop_ctx *save_loop_ctx_ref, int reuse);
int ${context}_loop_cleanup_context( $mfd_aue_param_decl, ${context}_ref_loop_ctx *ref);
##
@end@ // m2c_processing_type eq 'h'
########################################################################
##//####################################################################
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@if $m2c_processing_type eq 'i'@
/**
* @internal
* wrapper around clean up a loop reference
*/
static int
_${context}_loop_cleanup_context( $mfd_aue_wrap_param_decl,
${context}_ref_loop_ctx *ref)
{
DEBUGMSGTL(("internal:${context}:_${context}_loop_cleanup_context","called\n"));
return ${context}_loop_cleanup_context($mfd_aue_wrap_param->user_ctx, ref);
} /* _${context}_loop_cleanup_context */
/**
* @internal
* wrapper around save position
*/
static int
_${context}_loop_save_position( $mfd_aue_wrap_param_decl, ${context}_ref_loop_ctx *ref,
${context}_ref_loop_ctx *ref_copy, int reuse)
{
DEBUGMSGTL(("internal:${context}:_${context}_loop_save_position","called\n"));
return ${context}_loop_save_position($mfd_aue_wrap_param->user_ctx, ref,
ref_copy, reuse);
} /* _${context}_loop_save_position */
/**
* @internal
* wrapper around user get_first to setup the index oid
*/
static int
_${context}_loop_get_first_wrapper($mfd_aue_wrap_param_decl,
${context}_ref_loop_ctx * loop_ctx_ref,
${context}_ref_rowreq_ctx * rowreq_ctx_ref)
{
int rc;
DEBUGMSGTL(("internal:${context}:_${context}_loop_get_first_wrapper","called\n"));
rc = ${context}_loop_get_first($mfd_aue_wrap_param->user_ctx, loop_ctx_ref,
rowreq_ctx_ref);
/*
* convert index to OID
*/
if(SNMPERR_SUCCESS == rc ) {
netsnmp_assert((NULL != rowreq_ctx_ref) &&
(rowreq_ctx_ref->rowreq_ctx->oid_idx.oids == rowreq_ctx_ref->rowreq_ctx->oid_tmp));
rowreq_ctx_ref->rowreq_ctx->oid_idx.len = sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp);
rc = ${context}_index_to_oid(&rowreq_ctx_ref->rowreq_ctx->oid_idx,
&rowreq_ctx_ref->rowreq_ctx->tbl_idx);
netsnmp_assert(rowreq_ctx_ref->rowreq_ctx->oid_idx.len !=
sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp));
}
return rc;
} /* _${context}_loop_get_first_wrapper */
/**
* @internal
* wrapper around user get_next to setup the index oid
*/
static int
_${context}_loop_get_next_wrapper($mfd_aue_wrap_param_decl,
${context}_ref_loop_ctx * loop_ctx_ref,
${context}_ref_rowreq_ctx * rowreq_ctx_ref)
{
int rc;
DEBUGMSGTL(("internal:${context}:_${context}_loop_get_next_wrapper","called\n"));
rc = ${context}_loop_get_next($mfd_aue_wrap_param->user_ctx, loop_ctx_ref,
rowreq_ctx_ref);
/*
* convert index to OID
*/
if(SNMPERR_SUCCESS == rc ) {
netsnmp_assert((NULL != rowreq_ctx_ref) &&
(rowreq_ctx_ref->rowreq_ctx->oid_idx.oids == rowreq_ctx_ref->rowreq_ctx->oid_tmp));
rowreq_ctx_ref->rowreq_ctx->oid_idx.len = sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp);
rc = ${context}_index_to_oid(&rowreq_ctx_ref->rowreq_ctx->oid_idx,
&rowreq_ctx_ref->rowreq_ctx->tbl_idx);
netsnmp_assert(rowreq_ctx_ref->rowreq_ctx->oid_idx.len !=
sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp));
}
return rc;
} /* _${context}_loop_get_next_wrapper */
@if $m2c_data_transient != 0@ #
/**
* @internal
* get data wrapper to allocate context for the user
*/
static int
_${context}_loop_get_data_wrapper($mfd_aue_wrap_param_decl,
${context}_ref_loop_ctx * loop_ctx_ref,
${context}_ref_rowreq_ctx * rowreq_ctx_ref)
{
// ${context}_rowreq_ctx *orig_ctx = rowreq_ctx_ref->rowreq_ctx;
DEBUGMSGTL(("internal:${context}:_${context}_loop_get_data_wrapper","called\n"));
return ${context}_loop_get_data($mfd_aue_wrap_param->user_ctx, loop_ctx_ref, rowreq_ctx_ref);
} /* _${context}_loop_get_data_wrapper */
@end@ // transient != 0
/**
* @internal
* initialize the iterator container with functions or wrappers
*/
void
_${context}_container_init(${context}_interface_ctx *if_ctx)
{
DEBUGMSGTL(("internal:${context}:_${context}_container_init","called\n"));
if_ctx->container = netsnmp_container_iterator_get(/** registration */
if_ctx,
/** compare */
NULL,
/** get_first */
(Netsnmp_Iterator_Loop_Key*)_${context}_loop_get_first_wrapper,
/** get_next */
(Netsnmp_Iterator_Loop_Key*)_${context}_loop_get_next_wrapper,
/** get_data */
@if $m2c_data_transient != 0@ #
(Netsnmp_Iterator_Loop_Data*)_${context}_loop_get_data_wrapper,
@else@
NULL,
@end@
/** save_pos */
(Netsnmp_Iterator_Ctx_Dup*)_${context}_loop_save_position,
/** init_context */
(Netsnmp_Iterator_Ctx*)NULL,
/** cleanup_context */
(Netsnmp_Iterator_Ctx*)_${context}_loop_cleanup_context,
/** free_user_ctx */
NULL,
/** sorted */
0);
} /* _${context}_container_init */
##
@end@ // m2c_processing_type eq 'i'
########################################################################
##//####################################################################
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@if $m2c_processing_type eq 'c'@
/**
* unsorted-external overview
*
* The unsorted external data access code works by calling a few simple
* functions to get the index value for each row. Once the agent determines
* which row is needed to process an incoming request, another function
* is called to retrieve the data for that row.
*
* A simplified version of the pseudo-code looks like this:
*
* ${context}_loop_get_first(loop,data)
* while( no_error ) {
* if( best_match(data, key)
* ${context}_loop_save_position(loop,pos);
* ${context}_loop_get_next(loop,data)
* }
* ${context}_loop_get_data(pos,data)
* ${context}_loop_cleanup_context(loop)
*/
/***********************************************************************
*
* ITERATION
*
***********************************************************************/
/**
* get the first data index
*
* Summary
* -------
* This function is called to initialize the iterator loop context for a
* new iteration loop and return the index(es) for the first
* ${context}_data in the data set.
*
* Note that during the loop, the only important thing is the indexes.
* If access to your data is cheap/fast (e.g. you have a pointer to a
* structure in memory), it would make sense to update the data here.
* If, however, the accessing the data invovles more work (e.g. parsing
* some other existing data, or peforming calculations to derive the data),
* then you should limit yourself to setting the indexes. Extracting the
* can be put off until the desired row is found. See the notes on
* ${context}_loop_get_data().
*
* Note that this function does not correspond to a SNMP GET pdu, and
* you should return data items in whatever order they are already in.
* (In fact, if your data is already ordered in the same order as the
* SNMP indexes, you shouldn't be using the unsorted-access code).
*
* This function should update the table index (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
* values for the raw data (rowreq_ctx_ref->rowreq_ctx->data).
*
* More Details
* ------------
* If there is currently no data available, return MFD_END_OF_DATA.
* Otherwise, you should set rowreq_ctx_ref->rowreq_ctx and its indexes.
*
* rowreq_ctx_ref->rowreq_ctx will be NULL. You should allocate a new context
* for this loop. [Alternatively, you could allocate one in
* ${context}_loop_init_context, save it in your
* ${context}_ref_loop_ctx, and use it here.]
*
* Once you have your context pointer, you should set the index (or indexes)
* in rowreq_ctx_ref->rowreq_ctx->tbl_idx to the appropriate value for this row. [If you
* use your loop_ctx_ref cleverly, you might be able to put this work in
* ${context}_loop_get_next, and simply call that function.]
*
* @param $mfd_aue_param_cmt
* @param loop_ctx_ref Pointer to your loop reference.
* @param rowreq_ctx_ref Pointer to a context reference.
*
* @retval MFD_SUCCESS : success.
* @retval MFD_END_OF_DATA : no data available
* @retval MFD_ERROR : error.
*/
int
${context}_loop_get_first( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_rowreq_ctx *rowreq_ctx_ref)
{
DEBUGMSGTL(("verbose:${context}:${context}_loop_get_first","called\n"));
netsnmp_assert(rowreq_ctx_ref);
netsnmp_assert(loop_ctx_ref);
/*
* allocate memory for new structure
*/
loop_ctx_ref->loop_ctx = SNMP_MALLOC_TYPEDEF(${context}_loop_context);
if(NULL == loop_ctx_ref->loop_ctx)
return MFD_ERROR;
/*
* allocate a temporary context to use during iteration
*/
@ eval $m2c_tmp = ""@
@ if ($m2c_data_allocate == 1) || ($m2c_data_init == 1)@
@ eval $m2c_tmp = "NULL"@
@ if ($m2c_data_allocate == 1) && ($m2c_data_init == 1)@
@ eval $m2c_tmp = "$m2c_tmp, NULL"@
@ @end@
@ end@
loop_ctx_ref->loop_ctx->rowreq_ctx = ${context}_allocate_rowreq_ctx($m2c_tmp);
if(NULL == loop_ctx_ref->loop_ctx->rowreq_ctx) {
SNMP_FREE(loop_ctx_ref->loop_ctx);
return MFD_RESOURCE_UNAVAILABLE;
}
/*
* ToDo:
* set up loop context
*/
@if $m2c_include_examples == 1@
$example_start
/*
* open our data file.
*/
loop_ctx_ref->loop_ctx->filep = fopen("/etc/dummy.conf", "r");
if(NULL == loop_ctx_ref->loop_ctx->filep) {
return MFD_RESOURCE_UNAVAILABLE;
}
$example_end
@end@
@ifconf ${table}_update_idx.m2i@
@ include ${table}_update_idx.m2i@
@else@
@ if $m2c_include_examples == 1@
$example_start
/*
* in this example, after opening the file, get next does the same thing
* as get first, we let's just call get next...
*/
return ${context}_loop_get_next($mfd_aue_param, loop_ctx_ref, rowreq_ctx_ref);
$example_end
@ else@
/*
* we just need the index for now. Reuse the one in the loop context's
* temporary row request context. (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
*/
rowreq_ctx_ref->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
/*
* ToDo:
* set local vars for index from loop_ctx_ref->loop_ctx
* this can be done in one of two ways:
*/
/*
* 1) individually
*/
@ foreach $node index@
@ include m2c_setup_node.m2i@
/*
* ToDo:
* set rowreq_ctx_ref->rowreq_ctx->tbl_idx->$node
@ if $m2c_node_needlength == 1@
* and rowreq_ctx_ref->tbl_idx->${node}_len
@ end@
*/
@ end@ #foreach
/*
* OR
*/
/*
* 2) by calling ${context}_indexes_set()
* ${context}_indexes_set(rowreq_ctx_ref->tbl_idx,
@ foreach $node index@
@ include m2c_setup_node.m2i@
@ if $m2c_node_needlength == 1@
* ${node}_ptr, ${node}_len
@ else@
* $node
@ end@
@ end@ # foreach index
* );
*/
@ end@ # example
@end@ #ifconf
return MFD_SUCCESS;
} /* ${context}_loop_get_first */
/**
* get the next data index
*
* Summary
* -------
* This function returns the next data item in the data set. The same
* caveat applies here as did above. The indexes are the important parts
* during loop processing.
*
* Note that this function does not correspond to a SNMP GET-NEXT pdu, and
* you should return data items in whatever order they are already in.
* (In fact, if your data is already ordered in the same order as the
* SNMP indexes, you shouldn't be using the unsorted-access code).
*
* More Details
* ------------
* rowreq_ctx_ref->rowreq_ctx will have been set in ${context}_loop_get_first.
*
* If there is currently no data available, return MFD_END_OF_DATA.
* Otherwise, you should set the indexes in rowreq_ctx_ref->rowreq_ctx->tbl_idx.
*
* You should set the index (or indexes) in rowreq_ctx_ref->rowreq_ctx->tbl_idx to the
* appropriate value for this row.
*
* @param $mfd_aue_param_cmt
* @param loop_ctx_ref Pointer to your loop reference.
* @param rowreq_ctx_ref Pointer to a context reference.
*
* @retval MFD_SUCCESS : success.
* @retval MFD_END_OF_DATA : no more data available
* @retval MFD_ERROR : error.
*/
int
${context}_loop_get_next( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_rowreq_ctx *rowreq_ctx_ref)
{
DEBUGMSGTL(("verbose:${context}:${context}_loop_get_next","called\n"));
netsnmp_assert(loop_ctx_ref && loop_ctx_ref->loop_ctx);
netsnmp_assert(rowreq_ctx_ref);
/*
* we just need the index for now. Reuse the one in the loop context's
* temporary row request context. (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
*/
rowreq_ctx_ref->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
@ if $m2c_include_examples == 1@
$example_start
/*
* get a line (skip blank lines)
*/
do {
if (!fgets(loop_ctx_ref->loop_ctx->line, sizeof(loop_ctx_ref->loop_ctx->line),
loop_ctx_ref->loop_ctx->filep)) {
/* we're done */
fclose(loop_ctx_ref->loop_ctx->filep);
loop_ctx_ref->loop_ctx->filep = NULL;
}
} while (loop_ctx_ref->loop_ctx->filep && (loop_ctx_ref->loop_ctx->line[0] == '\n'));
/*
* check for end of data
*/
if(NULL == loop_ctx_ref->loop_ctx->filep)
return MFD_END_OF_DATA;
/*
* ToDo:
* set local vars for index from loop_ctx_ref->loop_ctx
* this can be done in one of two ways:
*/
/*
* 1) individually
*/
@ foreach $node index@
@ include m2c_setup_node.m2i@
/*
* ToDo:
* set rowreq_ctx_ref->rowreq_ctx->tbl_idx->$node
@ if $m2c_node_needlength == 1@
* and rowreq_ctx_ref->tbl_idx->${node}_len
@ end@
*/
@ end@ #foreach
/*
* OR
*/
/*
* 2) by calling ${context}_indexes_set()
* ${context}_indexes_set(rowreq_ctx_ref->tbl_idx,
@ foreach $node index@
@ include m2c_setup_node.m2i@
@ if $m2c_node_needlength == 1@
* ${node}_ptr, ${node}_len
@ else@
* $node
@ end@
@ end@ # foreach index
* );
*/
$example_end
@ end@ # example
return MFD_SUCCESS;
} /* ${context}_loop_get_next */
/**
* duplicate the current loop reference
*
* Summary
* -------
* During loop iteration, the iterator keeps track of the row that
* is the current best match. This function is called when the
* current row is a better match than any previous row.
*
* You should save any information you need to be able to locate this row
* again from the current loop context to a new loop context.
*
* At the end of the loop, when the best match has been found, the saved
* loop context will be used to get the data for the row by calling
* ${context}_loop_get_data().
@if $m2c_data_transient != 0@ # persistent
*
* Since your data is transient, you need to make a copy of it before
* the iterator moves on to the next row.
@end@
*
@if $m2c_data_transient != 0@ # persistent
* More Details
* ------------
@ if $m2c_data_transient == 1@ # short term
* Since your data is semi-TRANSIENT data, you could just keep a pointer
* to the data in the loop reference. The data should then be copied in
* ${context}_loop_get_data().
@ else@ # $m2c_data_transient == 2@ # copy immediately
* One idea would be to copy it space allocated in the loop reference
* structure. Another would be to simply have a pointer in the loop
* reference structure, and allocate memory here.
*
@ end@
@end@
* @param $mfd_aue_param_cmt
* @param loop_ctx_ref Reference to current loop context.
* @param save_loop_ctx_ref Reference to a loop context for saving the current
* position. If reuse is not set or
* save_loop_ctx_ref->loop_ctx is NULL, allocate
* a new one. If reuse is set, you may reuse the existing
* loop_ctx.
* @param reuse Indicates if an existing save_loop_ctx_ref->loop_ctx
* may be reused.
*
* @retval MFD_SUCCESS : success.
* @retval MFD_ERROR : error.
*/
int
${context}_loop_save_position($mfd_aue_param_decl,
${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_loop_ctx *save_loop_ctx_ref,
int reuse)
{
DEBUGMSGTL(("verbose:${context}:${context}_loop_save_position","called\n"));
netsnmp_assert(loop_ctx_ref && save_loop_ctx_ref);
/*
* ToDo:
* 1) allocate new loop context, unless you can reuse a previous pointer.
* 2) save information for the position of loop_ctx_ref in save_loop_ctx_ref.
*/
if((0 == reuse) || (NULL == save_loop_ctx_ref->loop_ctx))
save_loop_ctx_ref->loop_ctx = SNMP_MALLOC_TYPEDEF(${context}_loop_context);
if(NULL == save_loop_ctx_ref->loop_ctx) {
snmp_log(LOG_ERR, "could not allocate memory\n");
return MFD_ERROR;
}
/*
* if you can reuse a previously saved contex, just swap
* it out with the loop iterator
*/
if(reuse && save_loop_ctx_ref->loop_ctx->rowreq_ctx) {
${context}_rowreq_ctx * tmp_rowreq_ctx = save_loop_ctx_ref->loop_ctx->rowreq_ctx;
save_loop_ctx_ref->loop_ctx->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
loop_ctx_ref->loop_ctx->rowreq_ctx = tmp_rowreq_ctx;
}
else {
/*
* take the current pointer
*/
save_loop_ctx_ref->loop_ctx->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
/*
* allocate a new context to replace the one you just took.
*/
@ eval $m2c_tmp = ""@
@ if ($m2c_data_allocate == 1) || ($m2c_data_init == 1)@
@ eval $m2c_tmp = "NULL"@
@ if ($m2c_data_allocate == 1) && ($m2c_data_init == 1)@
@ eval $m2c_tmp = "$m2c_tmp, NULL"@
@ @end@
@ end@
loop_ctx_ref->loop_ctx->rowreq_ctx = ${context}_allocate_rowreq_ctx($m2c_tmp);
if(NULL == loop_ctx_ref->loop_ctx->rowreq_ctx) {
SNMP_FREE(loop_ctx_ref->loop_ctx);
return MFD_ERROR;
}
}
@if $m2c_data_transient == 0@ # persistent
/** non-TRANSIENT data: no need to copy */
@elsif $m2c_data_transient == 1@ # short term
/** semi-TRANSIENT data: will copy data when index found */
/** only need to copy pertinent data from loop context */
@elsif $m2c_data_transient == 2@ # copy immediately
/*
* TRANSIENT data: copy all the data.
*/
@end@
@if $m2c_include_examples == 1@
$example_start
@ if $m2c_data_transient == 1@ # short term
/** save line to do that */
memcpy(save_loop_ctx_ref->loop_ctx->line, loop_ctx_ref->loop_ctx->line,
sizeof(loop_ctx_ref->loop_ctx->line));
@ elsif $m2c_data_transient == 2@ # copy immediately
@ foreach $node nonindex@
@ include m2c_setup_node.m2i@
/*
* ToDo:
* set rowreq_ctx_ref->${m2c_data_item}$node
* from the loop context
*/
@ end@
@ end@
$example_end
@end@ # example
return MFD_SUCCESS;
} /* ${context}_loop_save_position */
@if $m2c_data_transient != 0@ # semi-transient
/**
* set ${context}_data from a data context
*
* Summary
* -------
* At the end of the loop, when the best match has been found, the saved
* loop context will be used to get the data for the row by calling
* ${context}_loop_get_data().
*
* You should return a fully populated row request context in
* rowreq_ctx_ref->rowreq_ctx.
*
* More Details
* ------------
* @param $mfd_aue_param_cmt
* @param loop_ctx_ref pointer to your loop reference.
* @param rowreq_ctx_ref pointer to a context reference.
*/
int
${context}_loop_get_data( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
${context}_ref_rowreq_ctx *rowreq_ctx_ref)
{
DEBUGMSGTL(("verbose:${context}:${context}_loop_get_data","called\n"));
netsnmp_assert((NULL != loop_ctx_ref) && (NULL != loop_ctx_ref->loop_ctx));
netsnmp_assert(NULL != rowreq_ctx_ref);
netsnmp_assert(NULL != rowreq_ctx_ref->rowreq_ctx);
/*
* take temporary row request context from loop context
*/
rowreq_ctx_ref->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
loop_ctx_ref->loop_ctx->rowreq_ctx = NULL;
/*
* copy data to the data context (rowreq_ctx_ref->${m2c_data_item})
@ if $m2c_include_examples == 1@
* in loop_save_position, we saved line to do that
@ end@
*/
@ foreach $node nonindex@
@ include m2c_setup_node.m2i@
/*
* $m2c_node_summary
*/
@ eval $m2c_ctx_lh = "rowreq_ctx_ref->$m2c_ctx_rh"@
@ eval $m2c_ctx_lhs = "rowreq_ctx_ref->$m2c_ctx_rhs"@
@ eval $m2c_ctx_rh = "loop_ctx_ref->loop_ctx->$node"@
@ eval $m2c_ctx_rhs = "loop_ctx_ref->loop_ctx->${node}_len"@
@ include generic-value-map.m2i@
@ end@
return MFD_SUCCESS;
} /* ${context}_loop_get_data */
@end@ // if $m2c_data_transient != 0
/**
* clean up a loop reference
*
* Summary
* -------
* This function will be called once the loop iteration has completed
* to release any memory or resources allocated for the loop context.
*
* More Details
* ------------
* @param $mfd_aue_param_cmt
* @param loop_ctx_ref Pointer to your loop reference.
*
* @retval MFD_SUCCESS : success.
* @retval MFD_ERROR : error.
*/
int
${context}_loop_cleanup_context( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref)
{
DEBUGMSGTL(("verbose:${context}:${context}_loop_cleanup_context","called\n"));
netsnmp_assert(loop_ctx_ref);
if(!loop_ctx_ref->loop_ctx)
return MFD_ERROR;
/*
* release the row request context, if it wasn't taken
*/
if(loop_ctx_ref->loop_ctx->rowreq_ctx)
${context}_release_rowreq_ctx(loop_ctx_ref->loop_ctx->rowreq_ctx);
/*
* ToDo:
* release resources
*/
@if $m2c_include_examples == 1@
$example_start
/*
* close file
*/
if(loop_ctx_ref->loop_ctx->filep)
fclose(loop_ctx_ref->loop_ctx->filep);
$example_end
@end@
/*
* free loop context
*/
free(loop_ctx_ref->loop_ctx);
return MFD_SUCCESS;
} /* ${context}_loop_cleanup_context */
@end@ // m2c_processing_type eq 'c'
########################################################################
##//####################################################################
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@if $m2c_processing_type eq 'r'@
##
unsorted-external summary
-------------------------
The unsorted-external data access code is for cases when you data is
kept UNSORTED and EXTERNAL to the agent/sub-agent.
This code was generated based on the following assumptions or settings:
1) The raw data for this table is UNSORTED.
@if $mfd_readme_verbose != 0@
UNSORTED data is data that is not kept in the same order as the way
SNMP expects the index(es) for the table to be kept. [It could very
well be sorted in some other order, but for the purpose of SNMP, the
order is incorrect.] If you're not sure if your data is sorted
in an SNMP compliant way, its likely not.
Because the raw data is unsorted, to satisfy a particular request, the
entire data set must be examined to find the apropriate index. This
is done via a simple loop. The MFD handler will call your get_first
function and the call the get_next function repeatedly, until it
returns SNMPERR_NO_VARS.
@end@
2) The raw data for this table is EXTERNAL.
@if $mfd_readme_verbose != 0@
EXTERNAL data is data that is owned by some other process,
device, file or mechanism. The agent must use some interface to
read or modify the data. An external process may modify the data
without the agent's knowledge. For example, the Net-SNMP agent
implements the interface table (ifTable), which reports on
network interfaces. The host operating system owns this data, and
Net-SNMP must use system calls to report or manipulate the data.
Examples of external data include data stored in kernel space, in
files, in another non-memory shared process, and data stored in
devices.
@end@
3) The raw data for this table is TRANSIENT.
@if $mfd_readme_verbose != 0@
TRANSIENT data is data that may be overwritten by another funtion
or process. For example, many OS functions return data in a
static buffer that will be reused the next time the function is
called. Because of this, we will assume that you will copy the
raw data retrieved from these other sources to a generated
structure for use within the Net-SNMP agent. (Don't worry, we'll
help you)
@end@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
The unsorted external data access code works by calling a few simple
functions to get the index value for each row. Once the agent determines
which row is needed to process an incoming request, another function
is called to retrieve the data for that row.
A simplified version of the pseudo-code looks like this:
${context}_loop_init_context(loop)
${context}_loop_get_first(loop,data)
while( no_error ) {
if( best_match(data, key)
${context}_loop_save_position(loop,pos);
${context}_loop_get_next(loop,data)
}
${context}_loop_get_data(pos,data)
${context}_loop_cleanup_context(loop)
##
## end sync
##
We will talk about each individual step below.
########################################################################
Defining context for the loop
-----------------------------
ToDo : typedef ${context}_loop_context
WHERE: ${table}_data_access.h
@if $mfd_readme_verbose != 0@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
Since the actual loop is in the MFD handler, a loop contex parameter
is provided to help you keep track of where you are in between calls
to functions that you wrote and the master MFD handler calls. The
structure of this context is user defineable, and is defined in the
file ${table}_data_access.h.
E.G., if your data is stored in a linked list, the obvious thing you
want to know from one function call to the next is your current
position in the linked list. Thus the easiest context to use is a
pointer within the linked list. For an array, the current index to
that array would be easiest.
The funtion calls are actually passed a reference to the loop
context, to allow the loop context to be allocated memory. Here are
some simple examples definitions for various data formats. These
definitions are used in examples later on.
##
## end sync
##
Linked list
-----------
typedef list_node ${context}_loop_context;
Array
-----
typedef integer ${context}_loop_context;
File
----
typedef struct ${context}_loop_context_s {
char * file_name;
FILE * f;
char line[128];
} ${context}_loop_context;
@end@
########################################################################
Initialization
--------------
ToDo : Initialization
FUNC : ${context}_loop_init_data
WHERE: ${table}_data_access.c
@if $mfd_readme_verbose != 0@
The ${context}_loop_init_data function will be called during startup to
allow for any initialization needed for the data access routines.
@end@
########################################################################
Preparing for the loop
----------------------
ToDo : initialize loop context
FUNC : ${context}_loop_init_context
WHERE: ${table}_data_access.c
@if $mfd_readme_verbose != 0@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
This function will be called before the start of a new itertion over
the data. The loop context that is initialized here will be passed to
${context}_loop_get_first and ${context}_loop_get_next.
Set the loop context variable ref->loop_ctx so that the iteration
functions (get_first and get_next) can locate the apropriate data
context.
##
## end sync
##
The primary purpose of the loop_init_context call is to initialize
the loop context data (ref). Here are some simple examples, based on the
earlier example loop contexts.
Linked list
-----------
ref->loop_ctx = my_table_head_ptr;
Array
-----
/* instead of actually allocating memory, just use the pointer */
/* as an integer */
(integer)(ref->loop_ctx) = 0;
File
----
ref->loop_ctx = SNMP_MALLOC_TYPEDEF(${context}_loop_context);
/* error checking here */
ref->loop_ctx->file_name = (char*) reg->mfd_user_ctx;
ref->loop_ctx->f = fopen( ref->loop_ctx->file_name, "r+" );
@end@
########################################################################
The Loop
--------
ToDo : return raw data
FUNC : ${context}_loop_get_first
WHERE: ${table}_data_access.c
@if $mfd_readme_verbose != 0@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
This function is called to return set the index(es) for the first
${context}_data in the data set.
Note that during the loop, the only important thing is the indexes.
If access to your data is cheap/fast (e.g. you have a pointer to a
structure in memory), it would make sense to update the data here.
If, however, the accessing the data invovles more work (e.g. parsing
some other existing data, or peforming calculations to derive the data),
then you should limit yourslef to setting the indexes. Extracting the
can be put off until the desired row is found See the notes on
${context}_loop_get_data().
Note that this function does not correspond to a SNMP GET pdu, and
you should return data items in whatever order they are already in.
(In fact, if your data is already ordered in the same order as the
SNMP indexes, you shouldn't be using the unsorted-access code).
This function should update the table index (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
values for the raw data (rowreq_ctx_ref->rowreq_ctx->data).
##
## end sync
##
Linked list
-----------
rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx;
Array
-----
/* assuming registration has array of pointers */
rowreq_ctx_ref->rowreq_ctx->data = reg->mfd_user_ctx[(integer)(ref->loop_ctx)];
File
----
fgets(loop_ctx_ref->loop_ctx->line, sizeof(loop_ctx_ref->loop_ctx->line),
loop_ctx_ref->loop_ctx->f);
rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx->line;
@end@
ToDo : return raw data
FUNC : ${context}_loop_get_next
WHERE: ${table}_data_access.c
@if $mfd_readme_verbose != 0@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
This function returns the next data item in the data set. The same
caveat applies here as did above. The indexes are the important parts
during loop processing.
Note that this function does not correspond to a SNMP GET-NEXT pdu, and
you should return data items in whatever order they are already in.
(In fact, if your data is already ordered in the same order as the
SNMP indexes, you shouldn't be using the unsorted-access code).
##
## end sync
##
Linked list
-----------
loop_ctx_ref->loop_ctx = loop_ctx_ref->loop_ctx->next;
rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx;
Array
-----
++((integer)(ref->loop_ctx));
/* assuming registration has array of pointers */
rowreq_ctx_ref->rowreq_ctx->data = reg->mfd_user_ctx[(integer)(ref->loop_ctx)];
File
----
fgets(loop_ctx_ref->loop_ctx->line, sizeof(loop_ctx_ref->loop_ctx->line),
loop_ctx_ref->loop_ctx->f);
rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx->line;
@end@
########################################################################
Updating the Index
------------------
ToDo : update index for the raw data
FUNC : ${context}_indexes_set
WHERE: ${table}_data_access.c
This is a convenience function for setting the index context from
the native C data. Where necessary, value mapping should be done.
@if $mfd_readme_verbose == 1@
This function should update the table index values (found in
tbl_idx) for the given raw data.
@end@
########################################################################
Saving a position in the loop
-----------------------------
ToDo : Saving a position in the loop
FUNC : ${context}_loop_save_position
WHERE: ${table}_data_access.c
@if $mfd_readme_verbose != 0@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
During loop iteration, the iterator keeps track of the row that
is the current best match. This function is called when the
current row is a better match than any previous row.
You should save any information you need to be able to locate this row
again from the current loop context to a new loop context.
At the end of the loop, when the best match has been found, the saved
loop context will be used to get the data for the row by calling
${context}_loop_get_data().
@if $m2c_data_transient != 0@ # persistent
Since your data is transient, you need to make a copy of it before
the iterator moves on to the next row.
@end@
##
## end sync
##
@end@
########################################################################
Returning Data For an Index
---------------------------
ToDo : copy transient raw data to generated structure
FUNC : ${context}_loop_get_data
WHERE: ${table}_data_access.c
@if $mfd_readme_verbose != 0@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
At the end of the loop, when the best match has been found, the saved
loop context will be used to get the data for the row by calling
${context}_loop_get_data().
##
## end sync
##
@end@
########################################################################
Cleaning up after the loop
--------------------------
ToDo : release any allocated memory
FUNC : ${context}_loop_cleanup_context
WHERE: ${table}_data_access.c
@if $mfd_readme_verbose != 0@
##
## this should be syncronized with master version of comments in
## mfd-access-unsorted-external-body.m2i You should be able to copy
## the comments here and replace " * " with " ".
##
This function will be called once the loop iteration has completed
to release any memory allocated for loop reference.
##
## end sync
##
The purpose of the loop_cleanup_context call is to release any memory
allocated for the loop context data. Here are some simple examples, based
on the earlier example loop contexts.
Linked list
-----------
/* nothing to do */
Array
-----
/* nothing to do */
File
----
free(ref->loop_ctx);
@end@
##
@end@ // m2c_processing_type eq 'r
########################################################################
@if $m2c_mark_boundary == 1@
/** END code generated by $RCSfile$ $Revision$ */
@end@
|