# HG changeset patch # User jlarmour # Date 961779991 0 # Node ID 95f3e12a6327d122964398bcc3ceedde0de5a19e # Parent 6409b6d94dd7dbbe95f819fd6d86a72375ca45b0 Merge from eCos master repository on 2000-06-23-16:41:10-BST diff --git a/host/libcdl/ChangeLog b/host/libcdl/ChangeLog --- a/host/libcdl/ChangeLog +++ b/host/libcdl/ChangeLog @@ -1,3 +1,14 @@ +2000-06-22 Bart Veer + + * value.cxx, interface.cxx: + Allow the flavor property to be used on interfaces. booldata + interfaces allow the use of #ifdef to determine whether or not + a feature is available. Clean up some of the value stuff to match, + especially when it comes to savefiles. + + * build.cxx, cdlmisc.cxx, cdlcore.hxx: + Add version #define support. + 2000-06-15 John Dallaway * cdl.dsp: diff --git a/host/libcdl/TODO b/host/libcdl/TODO --- a/host/libcdl/TODO +++ b/host/libcdl/TODO @@ -95,6 +95,13 @@ 19) add diagnostic callback support to t 20) make version comparison completely case insensitive, to avoid problems on some file systems. +21) configure magic to cope with Debian TCL organization. + See http://sourceware.cygnus.com/ml/ecos-discuss/2000-06/msg00094.html + +22) add version number #define's to pkgconf/system.h, to allow + application code to adapt to different versions of a package. + http://sourceware.cygnus.com/ml/ecos-discuss/2000-06/msg00140.html + Intermediate ------------ diff --git a/host/libcdl/build.cxx b/host/libcdl/build.cxx --- a/host/libcdl/build.cxx +++ b/host/libcdl/build.cxx @@ -1114,6 +1114,143 @@ CdlBuildLoadableBody::update_all_build_i //}}} //}}} +//{{{ Version number #define's + +// ---------------------------------------------------------------------------- +// Given a package xxxPKG_A_B_C with a version V1_2_3, generate additional +// #define's of the form: +// +// #define xxxNUM_A_B_C_VERSION_MAJOR 1 +// #define xxxNUM_A_B_C_VERSION_MINOR 2 +// #define xxxNUM_A_B_C_VERSION_RELEASE 3 +// +// The goal here is to allow application code to cope with API +// changes (which of course should be a rare event but cannot be +// eliminated completely). C preprocessor #if statements are +// essentially limited to numerical values, so there is no easy +// way of coping with V1_2_3 at the preprocessor level. However it +// is possible to cope with VERSION_NUMBER #define's. +// +// Note that only application code and third party packages are +// affected. +// +// These #define's go into system.h, alongside the main definition of +// the package. There seems to be little point in putting them in the +// package's own configuration header. +// +// There are three problems. First, what should be done for packages +// which do not follow the naming conventions? Given a completely +// random package rather than something like xxxPKG_..., what symbol +// names should be used? Basically, if the package does not follow the +// naming convention then there is no safe way of generating new +// symbols. Any names that are chosen might clash. Of course even for +// packages that do follow the naming convention a clash is still +// possible, just a lot less likely. +// +// Conclusion: if a package does not follow the naming convention, do +// not generate version #define's for it. +// +// Second, what happens if a different version numbering scheme is +// used? For example the release number might be absent. Version +// numbering schemes might change between releases, but application +// code may still check the #define's. +// +// Third and related, what should happen for "current" and anoncvs? Do +// we want to look at what other versions are installed and bump one +// of the numbers? +// +// Conclusion: the version #define's always have to be generated, +// even if they are not present in the version string, to allow +// application code to test these symbols anyway. A safe default is +// necessary, and -1 is probably the best bet. For example, if +// the version is bumped from 1.3.287 to 1.4 then the release number +// for the latter is set to -1. Another possible default would be +// 0, but that could cause problems for packages that start counting +// from 0 (not a common practice, but...) +// +// This leaves the question of what to do about "current". Chances are +// that "current" comes from anoncvs and is always more recent than +// any official release, so when comparing versions "current" should +// always be greater than anything else. This can be achieved by using +// a sufficiently large number for the major version. In practice +// it is cleaner to have another #define to indicate the current +// version, and then define package versions to match, i.e.: +// +// #define CYGNUM_VERSION_CURRENT 0x7fffff00 +// ... +// #define xxxNUM_A_B_C_VERSION_MAJOR CYGNUM_VERSION_CURRENT +// #define xxxNUM_A_B_C_VERSION_MINOR -1 +// #define xxxNUM_A_B_C_VERSION_RELEASE -1 +// +// All comparisons should now work sensibly. Leaving a little bit +// of slack for VERSION_CURRENT seems like a good precaution. + +static void +system_h_add_version_header(Tcl_Channel system_h) +{ + CYG_REPORT_FUNCNAME("system_h_add_version_header"); + Tcl_Write(system_h, "#define CYGNUM_VERSION_CURRENT 0x7fffff00\n", -1); + CYG_REPORT_RETURN(); +} + +static void +system_h_add_package_versioning(Tcl_Channel system_h, std::string name, std::string value) +{ + CYG_REPORT_FUNCNAME("system_h_add_package_versioning"); + + char name_buf[256]; + char line_buf[512]; + + // The first thing to check is that the package name can be used + // as the basis for the version symbols. + bool ok = false; + unsigned int i; + for (i = 0; i < name.size(); i++) { + if ('_' == name[i]) { + if (3 < i) { + if ((name[i-3] == 'P') && (name[i-2] == 'K') && (name[i-1] == 'G')) { + ok = true; + } + } + break; + } + } + if (name.size() >= 256) { + ok = false; + } + if (!ok) { + CYG_REPORT_RETURN(); + return; + } + + strcpy(name_buf, name.c_str()); + + // Change from xxxPKG to xxxNUM + name_buf[i - 3] = 'N'; + name_buf[i - 2] = 'U'; + name_buf[i - 1] = 'M'; + + // Now determine the version strings. + std::string major = "-1"; + std::string minor = "-1"; + std::string release = "-1"; + if ("current" == value) { + major = "CYGNUM_VERSION_CURRENT"; + } else { + Cdl::split_version_string(value, major, minor, release); + } + + sprintf(line_buf, "#define %s_VERSION_MAJOR %s\n", name_buf, major.c_str()); + Tcl_Write(system_h, line_buf, -1); + sprintf(line_buf, "#define %s_VERSION_MINOR %s\n", name_buf, minor.c_str()); + Tcl_Write(system_h, line_buf, -1); + sprintf(line_buf, "#define %s_VERSION_RELEASE %s\n", name_buf, release.c_str()); + Tcl_Write(system_h, line_buf, -1); + + CYG_REPORT_RETURN(); +} + +//}}} //{{{ CdlDefinableBody //{{{ Basics @@ -1468,6 +1605,11 @@ CdlDefinableBody::generate_config_header tmp = "#define "+ tmp + "\n"; Tcl_Write(chan, const_cast(tmp.c_str()), -1); } + + // For loadables, add additional version information to system_h + if (dynamic_cast((CdlConstNode)this) == loadable) { + system_h_add_package_versioning(system_h, name, value); + } } } @@ -1956,11 +2098,14 @@ CdlToplevelBody::generate_config_headers sprintf(local_buf, banner_format, "SYSTEM_H", "SYSTEM_H", "system.h"); Tcl_Write(system_h, local_buf, -1); + // Add generic version information + system_h_add_version_header(system_h); + // The rest of system.h will be filled in by the following loop. // - // Next, walk down the previously constructed headers vector, - // create appropriate files, and let each DefineLoadable fill - // in the file for itself. + // Walk down the previously constructed headers vector, create + // appropriate files, and let each DefineLoadable fill in the + // file for itself. std::vector >::iterator outer_i; std::vector >::iterator inner_i; for (outer_i = headers.begin(); outer_i != headers.end(); outer_i++) { diff --git a/host/libcdl/cdlcore.hxx b/host/libcdl/cdlcore.hxx --- a/host/libcdl/cdlcore.hxx +++ b/host/libcdl/cdlcore.hxx @@ -985,6 +985,10 @@ class Cdl { } }; + // Split a version string into major, minor and release numbers. + static void split_version_string(const std::string&, std::string& /* major */, + std::string& /* minor */, std::string& /* release */); + // It is occasionally useful to take a full CDL name such as CYGPKG_KERNEL // and turn it into a short form, i.e. kernel. static std::string get_short_form(const std::string&); diff --git a/host/libcdl/cdlmisc.cxx b/host/libcdl/cdlmisc.cxx --- a/host/libcdl/cdlmisc.cxx +++ b/host/libcdl/cdlmisc.cxx @@ -846,7 +846,7 @@ Cdl::is_interactive(void) } //}}} -//{{{ Cdl::compare_versions() +//{{{ version support() // ---------------------------------------------------------------------------- // Packages may need to impose constraints on which versions of other @@ -1013,6 +1013,49 @@ Cdl::compare_versions(std::string arg1, // Not reachable. } +// ---------------------------------------------------------------------------- +// Given a version string, extract major, minor and release numbers. +// Some or all of these may be absent. Basically the code just +// iterates through the string looking for sequences of numbers. + +static void +version_extract_number(const std::string& version, unsigned int& index, std::string& result) +{ + CYG_REPORT_FUNCNAME("version_extract_number"); + + // The calling code is expected to supply a sensible default. + // Search for a digit + for ( ; index < version.size(); index++) { + if (isdigit(version[index])) { + break; + } + } + if (index != version.size()) { + result = ""; + if ((index > 0) && ('-' == version[index-1])) { + result = "-"; + } + do { + result += version[index++]; + } while ((index < version.size()) && isdigit(version[index])); + } + + CYG_REPORT_RETURN(); +} + +void +Cdl::split_version_string(const std::string& version, std::string& major, std::string& minor, std::string& release) +{ + CYG_REPORT_FUNCNAME("CdlMisc::split_version_string"); + + unsigned int index = 0; + version_extract_number(version, index, major); + version_extract_number(version, index, minor); + version_extract_number(version, index, release); + + CYG_REPORT_RETURN(); +} + //}}} //{{{ Cdl::get_short_form() diff --git a/host/libcdl/interface.cxx b/host/libcdl/interface.cxx --- a/host/libcdl/interface.cxx +++ b/host/libcdl/interface.cxx @@ -231,12 +231,17 @@ CdlInterfaceBody::parse_interface(CdlInt new_interface->CdlBuildableBody::check_properties(interp); new_interface->CdlDefinableBody::check_properties(interp); - // A few properties do not make sense for interfaces. - // Start with the value-related ones. Interfaces always - // have the flavor Data. + // The flavor "none" makes no sense for interfaces. + // The flavor "bool" makes very little sense, but may be useful + // in weird cases. Both booldata and data make sense. + // The default flavor is "data", because interfaces are + // essentially just counters. if (new_interface->has_property(CdlPropertyId_Flavor)) { - CdlParse::report_error(interp, "", "An interface should not have a `flavor' property."); + if (CdlValueFlavor_None == new_interface->get_flavor()) { + CdlParse::report_error(interp, "", "An interface should not have the `none' flavor."); + } } + // Interfaces cannot be modified directly by the user, so // there is no point in entry_proc, check_proc, dialog or // wizard @@ -342,17 +347,22 @@ CdlInterfaceBody::save(CdlInterpreter in if (!minimal) { const std::vector& referrers = this->get_referrers(); std::vector::const_iterator ref_i; + int real_referrers = 0; for (ref_i = referrers.begin(); ref_i != referrers.end(); ref_i++) { CdlNode node = ref_i->get_source(); CdlProperty prop = ref_i->get_source_property(); CdlValuable valuable = dynamic_cast(node); if ((0 != valuable) && (CdlPropertyId_Implements == prop->get_property_name())) { + real_referrers++; data += std::string(indentation, ' ') + " # Implemented by " + valuable->get_name() + ", " + (valuable->is_active() ? "active" : "inactive") + ", " + (valuable->is_enabled() ? "enabled" : "disabled") + '\n'; } } + if (0 == real_referrers) { + data += std::string(indentation, ' ') + " # No options implement this inferface\n"; + } } interp->write_data(chan, data); @@ -469,10 +479,43 @@ CdlInterfaceBody::recalculate(CdlTransac } } } - if (count != old_value.get_integer_value()) { - CdlValue new_value = old_value; - new_value.set_integer_value(count, CdlValueSource_Default); - transaction->set_whole_value(this, old_value, new_value); + + // What to do with the count depends on the flavor. + switch(this->get_flavor()) { + case CdlValueFlavor_Bool : + { + bool new_bool = (count > 0); + if (new_bool != old_value.is_enabled()) { + CdlValue new_value = old_value; + new_value.set_enabled(new_bool, CdlValueSource_Default); + transaction->set_whole_value(this, old_value, new_value); + } + break; + } + case CdlValueFlavor_BoolData: + { + // The only thing that actually needs checking is the count value. + // Iff that has changed then the boolean part may need changing as well. + if (count != old_value.get_integer_value()) { + CdlValue new_value = old_value; + new_value.set_enabled_and_value(count > 0, count, CdlValueSource_Default); + transaction->set_whole_value(this, old_value, new_value); + } + + break; + } + case CdlValueFlavor_Data: + { + if (count != old_value.get_integer_value()) { + CdlValue new_value = old_value; + new_value.set_integer_value(count, CdlValueSource_Default); + transaction->set_whole_value(this, old_value, new_value); + } + break; + } + + default: + break; } CYG_REPORT_RETURN(); diff --git a/host/libcdl/value.cxx b/host/libcdl/value.cxx --- a/host/libcdl/value.cxx +++ b/host/libcdl/value.cxx @@ -713,6 +713,8 @@ CdlValue::CdlValue(CdlValueFlavor flavor cdlvalue_cookie = CdlValue_Magic; CYGDBG_MEMLEAK_CONSTRUCTOR(); + + // This cannot happen until after the object is valid. set_flavor(flavor_arg); CYG_POSTCONDITION_THISC(); @@ -870,44 +872,65 @@ CdlValue::set_flavor(CdlValueFlavor flav flavor = flavor_arg; switch(flavor) { case CdlValueFlavor_None : - { - // All value sources are enabled, but "default" remains the only valid one. - enabled[CdlValueSource_Default] = true; - enabled[CdlValueSource_Inferred] = true; - enabled[CdlValueSource_Wizard] = true; - enabled[CdlValueSource_User] = true; - break; - } + { + // All value sources are enabled, but "default" remains + // the only valid one. All data parts are set to "1", + // although that should not really matter. + enabled[CdlValueSource_Default] = true; + enabled[CdlValueSource_Inferred] = true; + enabled[CdlValueSource_Wizard] = true; + enabled[CdlValueSource_User] = true; + + CdlSimpleValue simple_val((cdl_int) 1); + values[CdlValueSource_Default] = simple_val; + values[CdlValueSource_Inferred] = simple_val; + values[CdlValueSource_Wizard] = simple_val; + values[CdlValueSource_User] = simple_val; + break; + } case CdlValueFlavor_Bool : - { - // All value sources start out as disabled. - enabled[CdlValueSource_Default] = false; - enabled[CdlValueSource_Inferred] = false; - enabled[CdlValueSource_Wizard] = false; - enabled[CdlValueSource_User] = false; - break; - } + { + // All value sources start out as disabled, but with a + // constant data part of 1. Users can only control the + // boolean part. This is consistent with header file + // generation: no #define is generated for disabled + // options, but if the option is enabled then the data + // part will be used for the value. + enabled[CdlValueSource_Default] = false; + enabled[CdlValueSource_Inferred] = false; + enabled[CdlValueSource_Wizard] = false; + enabled[CdlValueSource_User] = false; + + CdlSimpleValue simple_val(cdl_int(1)); + values[CdlValueSource_Default] = simple_val; + values[CdlValueSource_Inferred] = simple_val; + values[CdlValueSource_Wizard] = simple_val; + values[CdlValueSource_User] = simple_val; + break; + } case CdlValueFlavor_BoolData : - { - // All value sources start out as disabled. - enabled[CdlValueSource_Default] = false; - enabled[CdlValueSource_Inferred] = false; - enabled[CdlValueSource_Wizard] = false; - enabled[CdlValueSource_User] = false; - break; - } + { + // All value sources start out as disabled, just like + // booleans. Nothing is known about the data part. + enabled[CdlValueSource_Default] = false; + enabled[CdlValueSource_Inferred] = false; + enabled[CdlValueSource_Wizard] = false; + enabled[CdlValueSource_User] = false; + break; + } case CdlValueFlavor_Data : - { - // All value sources start out as enabled. - enabled[CdlValueSource_Default] = true; - enabled[CdlValueSource_Inferred] = true; - enabled[CdlValueSource_Wizard] = true; - enabled[CdlValueSource_User] = true; - break; - } + { + // All value sources start out as enabled, and cannot be + // changed. Nothing is known about the data part. + enabled[CdlValueSource_Default] = true; + enabled[CdlValueSource_Inferred] = true; + enabled[CdlValueSource_Wizard] = true; + enabled[CdlValueSource_User] = true; + break; + } default : break; @@ -3751,58 +3774,57 @@ CdlValuableBody::save(CdlInterpreter int data += '\n'; } - // Only display the various values if the user actually has some - // control over them. Otherwise just display the current value in a comment. + if (CdlValueFlavor_None == this->get_flavor()) { + data += indent_string + "# There is no associated value.\n"; + } else if (this->has_property(CdlPropertyId_Calculated)) { + CdlProperty_Expression expr = this->get_calculated_expression(); + data += indent_string + "# Calculated value: " + + CdlInterpreterBody::extend_comment(expr->get_original_string(), indentation, 4) + '\n'; + data += CdlInterpreterBody::multiline_comment(follow_expr_references(expr, expr), indentation, 4); + } else { + data += indent_string + "# This value cannot be modified here.\n"; + } + + // Output the flavor. This clutters up the savefile a bit. + // However it is necessary so that the user can distinguish + // between bool, booldata and data items + switch(this->get_flavor()) { + case CdlValueFlavor_Bool: + data += indent_string + "# Flavor: bool\n"; + break; + case CdlValueFlavor_BoolData: + data += indent_string + "# Flavor: booldata\n"; + break; + case CdlValueFlavor_Data: + data += indent_string + "# Flavor: data\n"; + break; + default: + break; + } + + // If the value is not modifiable, just list the current value. + // This is not in a form that allows users to change it easily. if (!modifiable) { - - if (CdlValueFlavor_None == this->get_flavor()) { - data += indent_string + "# There is no associated value.\n"; - } else if (this->has_property(CdlPropertyId_Calculated)) { - CdlProperty_Expression expr = this->get_calculated_expression(); - data += indent_string + "# Calculated value: " + - CdlInterpreterBody::extend_comment(expr->get_original_string(), indentation, 4) + '\n'; - data += CdlInterpreterBody::multiline_comment(follow_expr_references(expr, expr), indentation, 4); - } else { - data += indent_string + "# This value cannot be modified here.\n"; - } - switch(this->get_flavor()) { - case CdlValueFlavor_None : + case CdlValueFlavor_None : break; - case CdlValueFlavor_Bool : + case CdlValueFlavor_Bool : data += indent_string + "# Current value: " + (this->is_enabled() ? one : zero) + '\n'; break; - case CdlValueFlavor_BoolData : + case CdlValueFlavor_BoolData : data += indent_string + "# Current value: " + (this->is_enabled() ? one : zero) + " " + CdlInterpreterBody::extend_comment(this->get_value(), indentation, 4) + '\n'; break; - case CdlValueFlavor_Data : + case CdlValueFlavor_Data : data += indent_string + "# Current_value: " + CdlInterpreterBody::extend_comment(this->get_value(), indentation, 4) + '\n'; break; - default: + default: break; } } else if (CdlValueFlavor_None != this->get_flavor()) { - // Output the flavor. This clutters up the savefile a bit. - // However it is necessary so that the user can distinguish - // between bool, booldata and data items - switch(this->get_flavor()) { - case CdlValueFlavor_Bool: - data += indent_string + "# Flavor: bool\n"; - break; - case CdlValueFlavor_BoolData: - data += indent_string + "# Flavor: booldata\n"; - break; - case CdlValueFlavor_Data: - data += indent_string + "# Flavor: data\n"; - break; - default: - break; - } - // If there is a user value, output it. Otherwise output // a comment that allows users to edit the user value conveniently. // It is assumed that the user will want a value similar to the diff --git a/host/tools/configtool/ChangeLog b/host/tools/configtool/ChangeLog --- a/host/tools/configtool/ChangeLog +++ b/host/tools/configtool/ChangeLog @@ -1,3 +1,51 @@ +2000-06-22 John Dallaway + + * standalone/common/cdl_exec.cxx: + + Modify cdl_list() to restore printf line which + mysteriously disappeared some time ago. + +2000-06-20 John Dallaway + + * common/common/build.cxx: + + Modify generate_toplevel_makefile() to make the generated + makefile fragment more generic. + +2000-06-19 John Dallaway + + * common/common/build.cxx: + + Modify generate_toplevel_makefile() to generate a rule + to export global flags and command prefix as a makefile + fragment for optional use by application developers. + +2000-06-19 John Dallaway + + * common/win32/CTCommon.rc: + + Replace OK/Cancel buttons with 'Close' button in the + Build Options dialog. + + * common/win32/CTCommonDoc.cpp: + + Modify OnFileImport() to specify a default file extension + for the File Import dialog box. + + * common/win32/memmap.cpp: + + Modify add_relative_sections_to_list() to skip sections + which have already been added and track whether sections + should be skipped. + + * standalone/common/ecosconfig.cxx: + + Modify main() to return error codes in a consistent manner. + + * standalone/win32/Configtool.rc: + + Update engineering team list. + 2000-06-15 John Dallaway * standalone/win32/ConfigToolDoc.cpp: @@ -5,7 +53,6 @@ 2000-06-15 John Dallaway makes [info_make_vector [make].make].priority < 100) { // if priority higher than default complilation fprintf (stream, "\t$(MAKE) -r -C %s %s\n", info_make_vector [make].loadable->directory.c_str (), resolve_tokens (info_make_vector [make].loadable->makes [info_make_vector [make].make].target).c_str ()); @@ -441,6 +441,11 @@ bool generate_toplevel_makefile (const C } fprintf (stream, "\t@echo $@ finished\n\n"); + fprintf (stream, "$(PREFIX)/include/pkgconf/ecos.mak: makefile\n"); + fprintf (stream, "\t@echo 'ECOS_GLOBAL_CFLAGS = %s' > $@\n", get_flags (config, NULL, "CFLAGS").c_str ()); + fprintf (stream, "\t@echo 'ECOS_GLOBAL_LDFLAGS = %s' >> $@\n", get_flags (config, NULL, "LDFLAGS").c_str ()); + fprintf (stream, "\t@echo 'ECOS_COMMAND_PREFIX = $(COMMAND_PREFIX)' >> $@\n\n"); + // close the makefile return (0 == fclose (stream)); } diff --git a/host/tools/configtool/common/win32/CTCommon.rc b/host/tools/configtool/common/win32/CTCommon.rc --- a/host/tools/configtool/common/win32/CTCommon.rc +++ b/host/tools/configtool/common/win32/CTCommon.rc @@ -396,8 +396,7 @@ BEGIN LISTBOX IDC_BUILD_OPTIONS_LIST,213,41,107,149, LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "OK",IDOK,213,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,270,7,50,14 + DEFPUSHBUTTON "Close",IDOK,270,7,50,14 END IDD_ADDREMOVE_DIALOG DIALOG DISCARDABLE 0, 0, 312, 189 diff --git a/host/tools/configtool/common/win32/CTCommonDoc.cpp b/host/tools/configtool/common/win32/CTCommonDoc.cpp --- a/host/tools/configtool/common/win32/CTCommonDoc.cpp +++ b/host/tools/configtool/common/win32/CTCommonDoc.cpp @@ -1709,7 +1709,7 @@ void CConfigToolDoc::OnFileExport() void CConfigToolDoc::OnFileImport() { - CFileDialog dlg (TRUE, NULL, NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configurations (*.ecm)|*.ecm||"), AfxGetMainWnd ()); + CFileDialog dlg (TRUE, _T("ecm"), NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configurations (*.ecm)|*.ecm||"), AfxGetMainWnd ()); TCHAR szBuffer [MAX_PATH * 16] = _T(""); dlg.m_ofn.lpstrFile = szBuffer; dlg.m_ofn.nMaxFile = MAX_PATH * 16; diff --git a/host/tools/configtool/common/win32/memmap.cpp b/host/tools/configtool/common/win32/memmap.cpp --- a/host/tools/configtool/common/win32/memmap.cpp +++ b/host/tools/configtool/common/win32/memmap.cpp @@ -838,6 +838,7 @@ bool mem_map::add_relative_sections_to_l mem_location * new_section_location = (location_type == initial_location ? new_section->initial_location : new_section->final_location); list ::iterator insertion_point = section_view; ++insertion_point; + bool no_relocation = true; while (new_section_location->following_section != NULL) { @@ -848,14 +849,18 @@ bool mem_map::add_relative_sections_to_l const bool section_relocates = new_section->relocates; new_section = new_section_view.section; new_section_view.section_location = (new_section->relocates ? location_type : fixed_location); - if ((new_section_view.section_location == fixed_location) && (location_type == final_location) && (! section_view->section->relocates) && (! section_relocates)) + if ((new_section_view.section_location == fixed_location) && (location_type == final_location) && (! section_view->section->relocates) && (! section_relocates) && no_relocation) { - // section already added to the view + // section already added to the view so add nothing but + // increment insertion point for following sections + TRACE (_T("Skipping section %s %s location (relative) preceding %s\n"), CString (new_section_location->following_section->name.c_str()), location_type == initial_location ? _T("initial") : _T("final"), ((insertion_point != region->section_view_list.end ()) && (insertion_point->section != NULL)) ? CString (insertion_point->section->name.c_str()) : _T("(null)")); + ++insertion_point; } else { - TRACE (_T("Inserting section %s %s location (relative) preceding %s\n"), CString (new_section_location->following_section->name.c_str()), location_type == initial_location ? _T("initial") : _T("final"), ((insertion_point != region->section_view_list.end ()) && (insertion_point->section != NULL)) ? CString (insertion_point->section->name.c_str()) : _T("(null)")); + TRACE (_T("Inserting section %s %s location (relative) preceding %s\n"), CString (new_section_location->following_section->name.c_str()), location_type == initial_location ? _T("initial") : _T("final"), ((insertion_point != region->section_view_list.end ()) && (insertion_point->section != NULL)) ? CString (insertion_point->section->name.c_str()) : _T("(null)")); region->section_view_list.insert (insertion_point, new_section_view); + no_relocation = no_relocation && ! new_section_view.section->relocates; } new_section_location = (location_type == initial_location ? new_section->initial_location : new_section->final_location); } diff --git a/host/tools/configtool/standalone/common/cdl_exec.cxx b/host/tools/configtool/standalone/common/cdl_exec.cxx --- a/host/tools/configtool/standalone/common/cdl_exec.cxx +++ b/host/tools/configtool/standalone/common/cdl_exec.cxx @@ -279,6 +279,7 @@ bool cdl_exec::cmd_list () { std::sort (packages.begin (), packages.end ()); for (unsigned int package = 0; package < packages.size (); package++) { const std::vector & aliases = pkgdata->get_package_aliases (packages [package]); + printf ("Package %s (%s):\n aliases:", packages [package].c_str (), aliases [0].c_str ()); for (unsigned int alias = 1; alias < aliases.size (); alias++) { printf (" %s", aliases [alias].c_str ()); } diff --git a/host/tools/configtool/standalone/common/ecosconfig.cxx b/host/tools/configtool/standalone/common/ecosconfig.cxx --- a/host/tools/configtool/standalone/common/ecosconfig.cxx +++ b/host/tools/configtool/standalone/common/ecosconfig.cxx @@ -218,8 +218,8 @@ int main (int argc, char * argv []) { if (command_index + 2 == argc) { status = exec.cmd_target (argv [command_index + 1]); } else { + status = false; usage_message (); - return -1; } } else if ("template" == command) { @@ -236,16 +236,16 @@ int main (int argc, char * argv []) { if (command_index + 2 == argc) { status = exec.cmd_export (argv [command_index + 1]); } else { + status = false; usage_message (); - return -1; } } else if ("import" == command) { if (command_index + 2 == argc) { status = exec.cmd_import (argv [command_index + 1]); } else { + status = false; usage_message (); - return -1; } } else { diff --git a/host/tools/configtool/standalone/win32/Configtool.rc b/host/tools/configtool/standalone/win32/Configtool.rc --- a/host/tools/configtool/standalone/win32/Configtool.rc +++ b/host/tools/configtool/standalone/win32/Configtool.rc @@ -188,18 +188,18 @@ END IDD_ABOUTBOX DIALOGEX 0, 0, 217, 190 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About ConfigTool" -FONT 8, "MS Sans Serif", 0, 0, 0x1 +CAPTION "About Configuration Tool" +FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",IDOK,178,7,32,14,WS_GROUP LTEXT "eCos Configuration Tool 1.3.net",IDC_STATIC,40,10,119,8, SS_NOPREFIX - ICON IDR_MAINFRAME,IDC_STATIC,11,17,21,20 + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 LTEXT "Date/Time info",IDC_STATIC_DATETIME,40,23,119,8 LTEXT "Copyright © 1998-2000 Red Hat, Inc.",IDC_STATIC,40,36, 170,8 LTEXT "The eCos engineering team is:",IDC_STATIC,7,50,109,8 - CTEXT "\r\nPaul Beskeen\r\nJohn Dallaway\r\nRobert Erskine\r\nSimon FitzMaurice\r\nNick Garnett\r\nJohn Lane\r\nJonathan Larmour\r\nAlex Schuilenburg\r\nJesper Skov\r\nGary Thomas\r\nHugo Tyson\r\nBart Veer", + CTEXT "\r\nPaul Beskeen\r\nJohn Dallaway\r\nRobert Erskine\r\nNick Garnett\r\nJonathan Larmour\r\nAlex Schuilenburg\r\nJesper Skov\r\nGary Thomas\r\nHugo Tyson\r\nBart Veer", IDC_STATIC_ABOUT,7,69,203,114,SS_SUNKEN,WS_EX_CLIENTEDGE END diff --git a/host/tools/ecostest/ChangeLog b/host/tools/ecostest/ChangeLog --- a/host/tools/ecostest/ChangeLog +++ b/host/tools/ecostest/ChangeLog @@ -1,3 +1,15 @@ +2000-06-19 John Dallaway + + * unix/Makefile: + + Link with -lposix4 under Solaris for sched_yield(). + +2000-06-16 Jonathan Larmour + + * common/eCosTestDownloadFilter.cpp: Remove RCS id tags + * common/eCosTestMonitorFilter.cpp: Ditto + * common/eCosTestSerialFilter.cpp: Ditto + 2000-06-15 John Dallaway * common/eCosTest.cpp: diff --git a/host/tools/ecostest/common/eCosTestDownloadFilter.cpp b/host/tools/ecostest/common/eCosTestDownloadFilter.cpp --- a/host/tools/ecostest/common/eCosTestDownloadFilter.cpp +++ b/host/tools/ecostest/common/eCosTestDownloadFilter.cpp @@ -53,7 +53,6 @@ #include "eCosStd.h" #include "eCosTrace.h" -#define DL_FILTER_VER "$Id: eCosTestDownloadFilter.cpp,v 1.14 2000/06/16 16:44:01 jlarmour Exp $" #include "eCosTestDownloadFilter.h" CeCosTestDownloadFilter::CeCosTestDownloadFilter(): diff --git a/host/tools/ecostest/common/eCosTestMonitorFilter.cpp b/host/tools/ecostest/common/eCosTestMonitorFilter.cpp --- a/host/tools/ecostest/common/eCosTestMonitorFilter.cpp +++ b/host/tools/ecostest/common/eCosTestMonitorFilter.cpp @@ -45,7 +45,6 @@ #include "eCosStd.h" -#define SER_FILTER_VER "$Id: eCosTestMonitorFilter.cpp,v 1.13 2000/06/16 16:44:01 jlarmour Exp $" #include "eCosTestMonitorFilter.h" CeCosTestMonitorFilter::CeCosTestMonitorFilter(): diff --git a/host/tools/ecostest/common/eCosTestSerialFilter.cpp b/host/tools/ecostest/common/eCosTestSerialFilter.cpp --- a/host/tools/ecostest/common/eCosTestSerialFilter.cpp +++ b/host/tools/ecostest/common/eCosTestSerialFilter.cpp @@ -51,7 +51,6 @@ #include "eCosStd.h" -#define SER_FILTER_VER "$Id: eCosTestSerialFilter.cpp,v 1.14 2000/06/16 16:44:01 jlarmour Exp $" #include "eCosTestSerialFilter.h" #include "eCosThreadUtils.h" diff --git a/host/tools/ecostest/unix/Makefile b/host/tools/ecostest/unix/Makefile --- a/host/tools/ecostest/unix/Makefile +++ b/host/tools/ecostest/unix/Makefile @@ -27,7 +27,7 @@ CXX=g++ ifeq ($(shell uname), SunOS) # SunOS -LIBS := -lpthread -lsocket -lxnet -lstdc++ +LIBS := -lpthread -lsocket -lxnet -lstdc++ -lposix4 else # Linux LIBS := -lpthread -efence -lstdc++ diff --git a/packages/ChangeLog b/packages/ChangeLog --- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,11 @@ +2000-06-22 Jesper Skov + + * ecos.db: Added io_wallclock alias. + + 2000-06-13 Hugo Tyson + + * ecos.db: Add CYGPKG_SNMPLIB and CYGPKG_SNMPAGENT. + 2000-06-05 John Dallaway * ecos.db: diff --git a/packages/NEWS b/packages/NEWS --- a/packages/NEWS +++ b/packages/NEWS @@ -1,3 +1,8 @@ +* CDL now supports type bool and booldata for interfaces +* CDL now exports extra macros in header files, to indicate package version + numbers +* A port of the University of California at Davis (UCD) SNMP stack has been + added, including SNMP clients * Hitachi SH7709A variant support added * NEC V85x architecture support added * NEC Cosmo CEB-V850/SA1 evaluation board platform HAL added diff --git a/packages/devs/eth/arm/edb7xxx/current/ChangeLog b/packages/devs/eth/arm/edb7xxx/current/ChangeLog --- a/packages/devs/eth/arm/edb7xxx/current/ChangeLog +++ b/packages/devs/eth/arm/edb7xxx/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-07 Hugo Tyson * ecos.db: Re-organize device packages. This is a massive change diff --git a/packages/devs/eth/arm/edb7xxx/current/cdl/edb7xxx_eth_drivers.cdl b/packages/devs/eth/arm/edb7xxx/current/cdl/edb7xxx_eth_drivers.cdl --- a/packages/devs/eth/arm/edb7xxx/current/cdl/edb7xxx_eth_drivers.cdl +++ b/packages/devs/eth/arm/edb7xxx/current/cdl/edb7xxx_eth_drivers.cdl @@ -51,7 +51,7 @@ cdl_package CYGPKG_DEVS_ETH_ARM_EDB7XXX implements CYGHWR_NET_DRIVERS implements CYGHWR_NET_DRIVER_ETH0 include_dir . -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description "Ethernet driver for Cirrus Logic EDB7xxx boards." compile -library=libextras.a if_edb7xxx.c diff --git a/packages/devs/eth/powerpc/quicc/current/ChangeLog b/packages/devs/eth/powerpc/quicc/current/ChangeLog --- a/packages/devs/eth/powerpc/quicc/current/ChangeLog +++ b/packages/devs/eth/powerpc/quicc/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-07 Hugo Tyson * ecos.db: Re-organize device packages. This is a massive change diff --git a/packages/devs/eth/powerpc/quicc/current/cdl/quicc_eth_drivers.cdl b/packages/devs/eth/powerpc/quicc/current/cdl/quicc_eth_drivers.cdl --- a/packages/devs/eth/powerpc/quicc/current/cdl/quicc_eth_drivers.cdl +++ b/packages/devs/eth/powerpc/quicc/current/cdl/quicc_eth_drivers.cdl @@ -51,7 +51,7 @@ cdl_package CYGPKG_DEVS_ETH_POWERPC_QUIC implements CYGHWR_NET_DRIVERS implements CYGHWR_NET_DRIVER_ETH0 include_dir . -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description "Ethernet driver for PowerPC MPC8xx boards." compile -library=libextras.a if_quicc.c diff --git a/packages/devs/serial/arm/aeb/current/ChangeLog b/packages/devs/serial/arm/aeb/current/ChangeLog --- a/packages/devs/serial/arm/aeb/current/ChangeLog +++ b/packages/devs/serial/arm/aeb/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_arm_aeb.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/arm/aeb/current/cdl/ser_arm_aeb.cdl b/packages/devs/serial/arm/aeb/current/cdl/ser_arm_aeb.cdl --- a/packages/devs/serial/arm/aeb/current/cdl/ser_arm_aeb.cdl +++ b/packages/devs/serial/arm/aeb/current/cdl/ser_arm_aeb.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_ARM_AEB { requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the ARM AEB-1." diff --git a/packages/devs/serial/arm/cma230/current/ChangeLog b/packages/devs/serial/arm/cma230/current/ChangeLog --- a/packages/devs/serial/arm/cma230/current/ChangeLog +++ b/packages/devs/serial/arm/cma230/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_arm_cma230.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/arm/cma230/current/cdl/ser_arm_cma230.cdl b/packages/devs/serial/arm/cma230/current/cdl/ser_arm_cma230.cdl --- a/packages/devs/serial/arm/cma230/current/cdl/ser_arm_cma230.cdl +++ b/packages/devs/serial/arm/cma230/current/cdl/ser_arm_cma230.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_ARM_CMA230 requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the Cogent ARM/CMA230." diff --git a/packages/devs/serial/arm/ebsa285/current/ChangeLog b/packages/devs/serial/arm/ebsa285/current/ChangeLog --- a/packages/devs/serial/arm/ebsa285/current/ChangeLog +++ b/packages/devs/serial/arm/ebsa285/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-12 Hugo Tyson * src/ebsa285_serial.c (ebsa285_serial_init): Fix silly debug diff --git a/packages/devs/serial/arm/ebsa285/current/cdl/ser_arm_ebsa285.cdl b/packages/devs/serial/arm/ebsa285/current/cdl/ser_arm_ebsa285.cdl --- a/packages/devs/serial/arm/ebsa285/current/cdl/ser_arm_ebsa285.cdl +++ b/packages/devs/serial/arm/ebsa285/current/cdl/ser_arm_ebsa285.cdl @@ -49,7 +49,7 @@ cdl_package CYGPKG_IO_SERIAL_ARM_EBSA285 requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the StrongARM/EBSA285." diff --git a/packages/devs/serial/arm/edb7xxx/current/ChangeLog b/packages/devs/serial/arm/edb7xxx/current/ChangeLog --- a/packages/devs/serial/arm/edb7xxx/current/ChangeLog +++ b/packages/devs/serial/arm/edb7xxx/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_arm_edb7xxx.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/arm/edb7xxx/current/cdl/ser_arm_edb7xxx.cdl b/packages/devs/serial/arm/edb7xxx/current/cdl/ser_arm_edb7xxx.cdl --- a/packages/devs/serial/arm/edb7xxx/current/cdl/ser_arm_edb7xxx.cdl +++ b/packages/devs/serial/arm/edb7xxx/current/cdl/ser_arm_edb7xxx.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_ARM_EDB7XXX requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the Cirrus Logic EDB7XXX." diff --git a/packages/devs/serial/arm/pid/current/ChangeLog b/packages/devs/serial/arm/pid/current/ChangeLog --- a/packages/devs/serial/arm/pid/current/ChangeLog +++ b/packages/devs/serial/arm/pid/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-06-09 Jesper Skov * src/pid_serial_with_ints.c: diff --git a/packages/devs/serial/arm/pid/current/cdl/ser_arm_pid.cdl b/packages/devs/serial/arm/pid/current/cdl/ser_arm_pid.cdl --- a/packages/devs/serial/arm/pid/current/cdl/ser_arm_pid.cdl +++ b/packages/devs/serial/arm/pid/current/cdl/ser_arm_pid.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_ARM_PID { requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the ARM PID." diff --git a/packages/devs/serial/i386/pc/current/ChangeLog b/packages/devs/serial/i386/pc/current/ChangeLog --- a/packages/devs/serial/i386/pc/current/ChangeLog +++ b/packages/devs/serial/i386/pc/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_i386_pc.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/i386/pc/current/cdl/ser_i386_pc.cdl b/packages/devs/serial/i386/pc/current/cdl/ser_i386_pc.cdl --- a/packages/devs/serial/i386/pc/current/cdl/ser_i386_pc.cdl +++ b/packages/devs/serial/i386/pc/current/cdl/ser_i386_pc.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_I386_PC { requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the PC." diff --git a/packages/devs/serial/mips/jmr3904/current/ChangeLog b/packages/devs/serial/mips/jmr3904/current/ChangeLog --- a/packages/devs/serial/mips/jmr3904/current/ChangeLog +++ b/packages/devs/serial/mips/jmr3904/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_mips_jmr3904.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/mips/jmr3904/current/cdl/ser_mips_jmr3904.cdl b/packages/devs/serial/mips/jmr3904/current/cdl/ser_mips_jmr3904.cdl --- a/packages/devs/serial/mips/jmr3904/current/cdl/ser_mips_jmr3904.cdl +++ b/packages/devs/serial/mips/jmr3904/current/cdl/ser_mips_jmr3904.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_TX39_JMR390 requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the TX39 JMR3904." diff --git a/packages/devs/serial/mips/vrc4373/current/ChangeLog b/packages/devs/serial/mips/vrc4373/current/ChangeLog --- a/packages/devs/serial/mips/vrc4373/current/ChangeLog +++ b/packages/devs/serial/mips/vrc4373/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_mips_vrc4373.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/mips/vrc4373/current/cdl/ser_mips_vrc4373.cdl b/packages/devs/serial/mips/vrc4373/current/cdl/ser_mips_vrc4373.cdl --- a/packages/devs/serial/mips/vrc4373/current/cdl/ser_mips_vrc4373.cdl +++ b/packages/devs/serial/mips/vrc4373/current/cdl/ser_mips_vrc4373.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_MIPS_VRC437 requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the VRC4373." diff --git a/packages/devs/serial/mn10300/mn10300/current/ChangeLog b/packages/devs/serial/mn10300/mn10300/current/ChangeLog --- a/packages/devs/serial/mn10300/mn10300/current/ChangeLog +++ b/packages/devs/serial/mn10300/mn10300/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_mn10300.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/mn10300/mn10300/current/cdl/ser_mn10300.cdl b/packages/devs/serial/mn10300/mn10300/current/cdl/ser_mn10300.cdl --- a/packages/devs/serial/mn10300/mn10300/current/cdl/ser_mn10300.cdl +++ b/packages/devs/serial/mn10300/mn10300/current/cdl/ser_mn10300.cdl @@ -53,7 +53,7 @@ cdl_package CYGPKG_IO_SERIAL_MN10300 { requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the MN10300." diff --git a/packages/devs/serial/powerpc/cogent/current/ChangeLog b/packages/devs/serial/powerpc/cogent/current/ChangeLog --- a/packages/devs/serial/powerpc/cogent/current/ChangeLog +++ b/packages/devs/serial/powerpc/cogent/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_powerpc_cogent.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/powerpc/cogent/current/cdl/ser_powerpc_cogent.cdl b/packages/devs/serial/powerpc/cogent/current/cdl/ser_powerpc_cogent.cdl --- a/packages/devs/serial/powerpc/cogent/current/cdl/ser_powerpc_cogent.cdl +++ b/packages/devs/serial/powerpc/cogent/current/cdl/ser_powerpc_cogent.cdl @@ -49,7 +49,7 @@ cdl_package CYGPKG_IO_SERIAL_POWERPC_COG requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the Cogent PowerPC." diff --git a/packages/devs/serial/powerpc/quicc/current/ChangeLog b/packages/devs/serial/powerpc/quicc/current/ChangeLog --- a/packages/devs/serial/powerpc/quicc/current/ChangeLog +++ b/packages/devs/serial/powerpc/quicc/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_quicc_smc.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl b/packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl --- a/packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl +++ b/packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl @@ -50,7 +50,7 @@ cdl_package CYGPKG_IO_SERIAL_POWERPC_QUI requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the PowerPC QUICC/SMC." diff --git a/packages/devs/serial/sh/edk7708/current/ChangeLog b/packages/devs/serial/sh/edk7708/current/ChangeLog --- a/packages/devs/serial/sh/edk7708/current/ChangeLog +++ b/packages/devs/serial/sh/edk7708/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_sh_edk7708.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/sh/edk7708/current/cdl/ser_sh_edk7708.cdl b/packages/devs/serial/sh/edk7708/current/cdl/ser_sh_edk7708.cdl --- a/packages/devs/serial/sh/edk7708/current/cdl/ser_sh_edk7708.cdl +++ b/packages/devs/serial/sh/edk7708/current/cdl/ser_sh_edk7708.cdl @@ -49,7 +49,7 @@ cdl_package CYGPKG_IO_SERIAL_SH_EDK7708 requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the Hitachi SH3 EDK7708 board." diff --git a/packages/devs/serial/sparclite/sleb/current/ChangeLog b/packages/devs/serial/sparclite/sleb/current/ChangeLog --- a/packages/devs/serial/sparclite/sleb/current/ChangeLog +++ b/packages/devs/serial/sparclite/sleb/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-04-11 Hugo Tyson * cdl/ser_sparclite_sleb.cdl: Change the parent from CYGPKG_IO_SERIAL diff --git a/packages/devs/serial/sparclite/sleb/current/cdl/ser_sparclite_sleb.cdl b/packages/devs/serial/sparclite/sleb/current/cdl/ser_sparclite_sleb.cdl --- a/packages/devs/serial/sparclite/sleb/current/cdl/ser_sparclite_sleb.cdl +++ b/packages/devs/serial/sparclite/sleb/current/cdl/ser_sparclite_sleb.cdl @@ -49,7 +49,7 @@ cdl_package CYGPKG_IO_SERIAL_SPARCLITE_S requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the SPARClite SLEB." diff --git a/packages/devs/serial/v85x/v850/current/ChangeLog b/packages/devs/serial/v85x/v850/current/ChangeLog --- a/packages/devs/serial/v85x/v850/current/ChangeLog +++ b/packages/devs/serial/v85x/v850/current/ChangeLog @@ -1,3 +1,9 @@ +2000-06-22 Hugo Tyson + + * cdl/.cdl: Remove the comment on the empty + include_files directive; the tools now support this correctly. + This keeps internal include files internal. + 2000-05-28 Gary Thomas * src/v85x_v850_serial.h: diff --git a/packages/devs/serial/v85x/v850/current/cdl/ser_v85x_v850.cdl b/packages/devs/serial/v85x/v850/current/cdl/ser_v85x_v850.cdl --- a/packages/devs/serial/v85x/v850/current/cdl/ser_v85x_v850.cdl +++ b/packages/devs/serial/v85x/v850/current/cdl/ser_v85x_v850.cdl @@ -49,7 +49,7 @@ cdl_package CYGPKG_IO_SERIAL_V85X_V850 { requires CYGPKG_ERROR include_dir cyg/io -# include_files ; # none _exported_ whatsoever + include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the NEC CEB/V850SA1." diff --git a/packages/ecos.db b/packages/ecos.db --- a/packages/ecos.db +++ b/packages/ecos.db @@ -233,6 +233,19 @@ package CYGPKG_NET_ETH_DRIVERS { description "Platform independent ethernet support." } +package CYGPKG_SNMPLIB { + alias { "SNMP library" snmplib } + directory net/snmp/lib + script snmplib.cdl + description "UCD SNMP library." +} + +package CYGPKG_SNMPAGENT { + alias { "SNMP agent" snmpagent } + directory net/snmp/agent + script snmpagent.cdl + description "UCD SNMP agent." +} package CYGPKG_DEVS_ETH_ARM_EDB7XXX { alias { "Cirrus Logic ethernet driver" edb7xxx_eth_driver } hardware @@ -268,7 +281,7 @@ package CYGPKG_IO_PCI { } package CYGPKG_IO_WALLCLOCK { - alias { "Wallclock device framework" wallclock devices_wallclock device_wallclock } + alias { "Wallclock device framework" wallclock io_wallclock devices_wallclock device_wallclock } directory io/wallclock script wallclock.cdl description " diff --git a/packages/ecosadmin.tcl b/packages/ecosadmin.tcl --- a/packages/ecosadmin.tcl +++ b/packages/ecosadmin.tcl @@ -1,9 +1,9 @@ #!/bin/sh # these lines restart using the tcl shell \ exec sh -c "if ( echo | tclsh ) 2>/dev/null ; then \ - exec tclsh "${0}" ${1+"${@}"} ; \ + exec tclsh \"${0}\" ${1+${*}} ; \ elif ( echo | cygtclsh80 ) 2>/dev/null ; then \ - exec cygtclsh80 "${0}" ${1+"${@}"} ; \ + exec cygtclsh80 \"${0}\" ${1+${*}} ; \ else \ echo Could not find TCL interpreter ; \ exit 1 ; \ diff --git a/packages/hal/arm/aeb/current/ChangeLog b/packages/hal/arm/aeb/current/ChangeLog --- a/packages/hal/arm/aeb/current/ChangeLog +++ b/packages/hal/arm/aeb/current/ChangeLog @@ -1,3 +1,19 @@ +2000-06-21 Jonathan Larmour + + * src/flash_cksum.tcl: Fix quoting when invoking TCL interpreter + +2000-06-18 Gary Thomas + + * include/pkgconf/mlt_arm_aebC_ram.ldi: + * include/pkgconf/mlt_arm_aebC_ram.mlt: + * include/pkgconf/mlt_arm_aebC_rom.ldi: + * include/pkgconf/mlt_arm_aebC_rom.mlt: + * include/pkgconf/mlt_arm_aeb_ram.ldi: + * include/pkgconf/mlt_arm_aeb_ram.mlt: + * include/pkgconf/mlt_arm_aeb_rom.ldi: + * include/pkgconf/mlt_arm_aeb_rom.mlt: + Incorporate new fixed vectors (used on all ARM platforms). + 2000-06-06 Jonathan Larmour * src/flash_cksum.tcl: Make sure it invokes the interpreter correctly diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.ldi b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.ldi --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.ldi +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.ldi @@ -10,10 +10,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved_vectors = 0; . = __reserved_vectors + 0x1000; - __reserved_not_mapped = ALIGN (0x1); . = __reserved_not_mapped + 0x7000; - __reserved_rom_usage = ALIGN (0x1); . = __reserved_rom_usage + 0x4000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0xC000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.mlt b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.mlt --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.mlt +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_ram.mlt @@ -1,9 +1,7 @@ version 0 region ram 0 48000 0 ! -section reserved_vectors 1000 1 0 0 1 1 1 1 0 0 reserved_not_mapped reserved_not_mapped ! -section reserved_not_mapped 7000 1 0 0 0 1 0 1 reserved_rom_usage reserved_rom_usage ! -section reserved_rom_usage 4000 1 0 0 0 1 0 1 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 C000 C000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.ldi b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.ldi --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.ldi +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.ldi @@ -18,9 +18,8 @@ SECTIONS SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) - __reserved_vectors = 0; . = __reserved_vectors + 0x1000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x8000, FOLLOWING (.gcc_except_table)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) - __reserved_not_mapped = ALIGN (0x4); . = __reserved_not_mapped + 0x7000; SECTIONS_END } diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.mlt b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.mlt --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.mlt +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aebC_rom.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 48000 0 ! region rom 4018000 8000 1 ! -section reserved_vectors 1000 1 0 0 1 1 1 1 0 0 reserved_not_mapped reserved_not_mapped ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 8000 bss ! section bss 0 4 0 1 0 0 0 0 ! section reserved_not_mapped 7000 4 0 0 0 1 0 0 data ! section rom_vectors 0 1 0 1 1 1 1 1 4018000 4018000 text text ! diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.ldi b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.ldi --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.ldi +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.ldi @@ -10,10 +10,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved_vectors = 0; . = __reserved_vectors + 0x1000; - __reserved_not_mapped = ALIGN (0x1); . = __reserved_not_mapped + 0x7000; - __reserved_for_rom = ALIGN (0x1); . = __reserved_for_rom + 0x4000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0xC000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.mlt b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.mlt --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.mlt +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_ram.mlt @@ -1,9 +1,7 @@ version 0 region ram 0 28000 0 ! -section reserved_vectors 1000 1 0 0 1 1 1 1 0 0 reserved_not_mapped reserved_not_mapped ! -section reserved_not_mapped 7000 1 0 0 0 1 0 1 reserved_for_rom reserved_for_rom ! -section reserved_for_rom 4000 1 0 0 0 1 0 1 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 C000 C000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.ldi b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.ldi --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.ldi +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.ldi @@ -18,9 +18,8 @@ SECTIONS SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) - __reserved_vectors = 0; . = __reserved_vectors + 0x1000; - __reserved_not_mapped = 0x1000; . = __reserved_not_mapped + 0x7000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x8000, FOLLOWING (.gcc_except_table)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTIONS_END } diff --git a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.mlt b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.mlt --- a/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.mlt +++ b/packages/hal/arm/aeb/current/include/pkgconf/mlt_arm_aeb_rom.mlt @@ -1,9 +1,8 @@ version 0 region ram 0 28000 0 ! region rom 4018000 8000 1 ! -section reserved_vectors 1000 1 0 0 1 0 1 0 0 0 ! -section reserved_not_mapped 7000 1 0 0 1 1 1 0 1000 1000 data ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 8000 bss ! section bss 0 4 0 1 0 0 0 0 ! section rom_vectors 0 1 0 1 1 1 1 1 4018000 4018000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! diff --git a/packages/hal/arm/aeb/current/src/flash_cksum.tcl b/packages/hal/arm/aeb/current/src/flash_cksum.tcl --- a/packages/hal/arm/aeb/current/src/flash_cksum.tcl +++ b/packages/hal/arm/aeb/current/src/flash_cksum.tcl @@ -1,9 +1,9 @@ #!/bin/sh -# the next line restarts using tclsh \ +# these lines restart using the tcl shell \ exec sh -c "if ( echo | tclsh ) 2>/dev/null ; then \ - exec tclsh "${0}" ${1+"${@}"} ; \ + exec tclsh \"${0}\" ${1+${*}} ; \ elif ( echo | cygtclsh80 ) 2>/dev/null ; then \ - exec cygtclsh80 "${0}" ${1+"${@}"} ; \ + exec cygtclsh80 \"${0}\" ${1+${*}} ; \ else \ echo Could not find TCL interpreter ; \ exit 1 ; \ diff --git a/packages/hal/arm/arch/current/ChangeLog b/packages/hal/arm/arch/current/ChangeLog --- a/packages/hal/arm/arch/current/ChangeLog +++ b/packages/hal/arm/arch/current/ChangeLog @@ -1,3 +1,18 @@ +2000-06-19 Gary Thomas + + * src/vectors.S: Changes for virtual vector support. + (hal_virtual_vector_table): Need to protect if virtual vector + stuff not defined. + + * src/hal_mk_defs.c: Add symbols for virtual vector table. + + * src/hal_misc.c (hal_arch_default_isr): New function. Used in + place of 'hal_default_isr' if virtual vector support is enabled. + + * include/hal_intr.h: "Fixed" items now exported in 'vectors.S' + + * src/vectors.S: Add notion of "fixed vectors" to all platforms. + 2000-06-08 Jesper Skov * include/hal_arch.h (CYGARC_HAL_SAVE_GP, CYGARC_HAL_RESTORE_GP): diff --git a/packages/hal/arm/arch/current/include/hal_intr.h b/packages/hal/arm/arch/current/include/hal_intr.h --- a/packages/hal/arm/arch/current/include/hal_intr.h +++ b/packages/hal/arm/arch/current/include/hal_intr.h @@ -94,26 +94,24 @@ // Static data used by HAL // ISR tables -externC volatile CYG_ADDRESS hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; -externC volatile CYG_ADDRWORD hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; -externC volatile CYG_ADDRESS hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; +externC CYG_ADDRESS hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; +externC CYG_ADDRWORD hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; +externC CYG_ADDRESS hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; // VSR table -//externC volatile CYG_ADDRESS hal_vsr_table[CYGNUM_HAL_VSR_COUNT]; - -// actually, it is immediately after the hardware vectors -#define hal_vsr_table ((volatile CYG_ADDRESS *)(0x20)) +externC CYG_ADDRESS hal_vsr_table[CYGNUM_HAL_VSR_COUNT]; -// and followed by a DRAM size variable used during bootup. This is in a -// fixed location so that it can be shared between an eCos Stub ROM and a -// RAM start eCos app. Ie. so that RAM startup code knows DRAM size. -// If this variable is zero, RAM size is unknown/is the default. -#define hal_dram_size (*(CYG_WORD *)(0x40)) +// Platform setup memory size (0 if unknown by hardware) +externC CYG_ADDRWORD hal_dram_size; //-------------------------------------------------------------------------- // Default ISR +// The #define is used to test whether this routine exists, and to allow +// code outside the HAL to call it. + +externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); -externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); +#define HAL_DEFAULT_ISR hal_default_isr //-------------------------------------------------------------------------- // Interrupt state storage diff --git a/packages/hal/arm/arch/current/src/hal_misc.c b/packages/hal/arm/arch/current/src/hal_misc.c --- a/packages/hal/arm/arch/current/src/hal_misc.c +++ b/packages/hal/arm/arch/current/src/hal_misc.c @@ -175,6 +175,18 @@ cyg_hal_invoke_constructors (void) /*------------------------------------------------------------------------*/ /* default ISR */ +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT +externC cyg_uint32 +hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + CYG_TRACE1(true, "Interrupt: %d", vector); + + diag_printf("Spurious Interrupt!!! - vector: %d, data: %x\n", vector, + data); + CYG_FAIL("Spurious Interrupt!!!"); + return 0; +} +#else externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { @@ -196,6 +208,7 @@ hal_default_isr(CYG_ADDRWORD vector, CYG CYG_FAIL("Spurious Interrupt!!!"); return 0; } +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT /*------------------------------------------------------------------------*/ /* Idle thread action */ diff --git a/packages/hal/arm/arch/current/src/hal_mk_defs.c b/packages/hal/arm/arch/current/src/hal_mk_defs.c --- a/packages/hal/arm/arch/current/src/hal_mk_defs.c +++ b/packages/hal/arm/arch/current/src/hal_mk_defs.c @@ -51,6 +51,7 @@ # include # include #endif +#include /* * This program is used to generate definitions needed by @@ -102,6 +103,9 @@ main(void) DEFINE(CPSR_MODE_BITS, CPSR_MODE_BITS); DEFINE(CPSR_INITIAL, CPSR_INITIAL); DEFINE(CPSR_THREAD_INITIAL, CPSR_THREAD_INITIAL); +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT) + DEFINE(CYGNUM_CALL_IF_TABLE_SIZE, CYGNUM_CALL_IF_TABLE_SIZE); +#endif } diff --git a/packages/hal/arm/arch/current/src/vectors.S b/packages/hal/arm/arch/current/src/vectors.S --- a/packages/hal/arm/arch/current/src/vectors.S +++ b/packages/hal/arm/arch/current/src/vectors.S @@ -169,7 +169,35 @@ PTR(FIQ) PTR(start) // This is copied to 0x28 for bootup // 0x40 // location 0x40 is used for storing DRAM size if known // for some platforms. + +// +// "Vectors" - fixed location data items +// This section contains any data which might be shared between +// an eCos application and any other environment, e.g. the debug +// ROM. +// + .section ".fixed_vectors" + // Interrupt/exception VSR pointers + .globl hal_vsr_table +hal_vsr_table: + .rept 8 + .long 0 + .endr + .globl hal_dram_size +hal_dram_size: + .long 0 + + .balign 16 +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away + // Vectors used to communicate between eCos and ROM environments + .globl hal_virtual_vector_table +hal_virtual_vector_table: + .rept CYGNUM_CALL_IF_TABLE_SIZE + .long 0 + .endr +#endif + .balign 32 // Other vectors - this may include "fixed" locations @@ -203,7 +231,8 @@ warm_reset: mov r0,#0 // move vectors // We cannot perform a store until after PLATFORM_SETUP1 #ifndef CYGPKG_HAL_ARM_EBSA285 // EBSA285 sets the DRAM size above - str r0, [r0,#0x40] // DRAM size to zero => unknown + ldr r1,=hal_dram_size + str r0, [r1] // DRAM size to zero => unknown #endif ldr r1,=__exception_handlers @@ -356,6 +385,14 @@ 2: ldr r2,[r1,#0x24] str r2,[r0,#0x24] #endif + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + .extern hal_ctrlc_isr_init + bl hal_ctrlc_isr_init +#endif +#endif LED 2 @@ -676,6 +713,20 @@ 10: ARM_MODE(r0,10) mov r0,v1 // vector # + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + // If we are supporting Ctrl-C interrupts from GDB, we must squirrel + // away a pointer to the save interrupt state here so that we can + // plant a breakpoint at some later time. + + .extern hal_saved_interrupt_state + ldr r2,=hal_saved_interrupt_state + str v6,[r2] +#endif +#endif + #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS cmp r0,#0 // ignore spurious interrupts beq spurious_IRQ diff --git a/packages/hal/arm/cma230/current/ChangeLog b/packages/hal/arm/cma230/current/ChangeLog --- a/packages/hal/arm/cma230/current/ChangeLog +++ b/packages/hal/arm/cma230/current/ChangeLog @@ -1,3 +1,19 @@ +2000-06-18 Gary Thomas + + * include/pkgconf/mlt_arm_cma222_ram.ldi: + * include/pkgconf/mlt_arm_cma222_ram.mlt: + * include/pkgconf/mlt_arm_cma222_rom.ldi: + * include/pkgconf/mlt_arm_cma222_rom.mlt: + * include/pkgconf/mlt_arm_cma230T_ram.ldi: + * include/pkgconf/mlt_arm_cma230T_ram.mlt: + * include/pkgconf/mlt_arm_cma230T_rom.ldi: + * include/pkgconf/mlt_arm_cma230T_rom.mlt: + * include/pkgconf/mlt_arm_cma230_ram.ldi: + * include/pkgconf/mlt_arm_cma230_ram.mlt: + * include/pkgconf/mlt_arm_cma230_rom.ldi: + * include/pkgconf/mlt_arm_cma230_rom.mlt: + Incorporate new fixed vectors (used on all ARM platforms). + 2000-02-29 Jonathan Larmour * include/pkgconf/mlt_arm_cma222_ram.h: diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.ldi b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.ldi --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.ldi +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.ldi @@ -10,8 +10,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved = 0; . = __reserved + 0x8000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0x8000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.mlt b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.mlt --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.mlt +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_ram.mlt @@ -1,7 +1,7 @@ version 0 region ram 0 200000 0 ! -section reserved 8000 1 0 0 1 1 1 1 0 0 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 8000 8000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.ldi b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.ldi --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.ldi +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.ldi @@ -18,8 +18,8 @@ SECTIONS SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) - __reserved = 0; . = __reserved + 0x1000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x1000, FOLLOWING (.gcc_except_table)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTIONS_END } diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.mlt b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.mlt --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.mlt +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma222_rom.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 200000 0 ! region rom e000000 40000 1 ! -section reserved 1000 1 0 0 1 1 1 0 0 0 data ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 1000 bss ! section bss 0 4 0 1 0 0 0 0 ! section rom_vectors 0 1 0 1 1 1 1 1 e000000 e000000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.ldi b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.ldi --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.ldi +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.ldi @@ -10,8 +10,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved = 0; . = __reserved + 0x8000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0x8000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.mlt b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.mlt --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.mlt +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_ram.mlt @@ -1,7 +1,7 @@ version 0 region ram 0 200000 0 ! -section reserved 8000 1 0 0 1 1 1 1 0 0 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 8000 8000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.ldi b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.ldi --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.ldi +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.ldi @@ -18,8 +18,8 @@ SECTIONS SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) - __reserved = 0; . = __reserved + 0x1000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x1000, FOLLOWING (.gcc_except_table)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTIONS_END } diff --git a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.mlt b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.mlt --- a/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.mlt +++ b/packages/hal/arm/cma230/current/include/pkgconf/mlt_arm_cma230_rom.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 200000 0 ! region rom e000000 40000 1 ! -section reserved 1000 1 0 0 1 1 1 0 0 0 data ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 1000 bss ! section bss 0 4 0 1 0 0 0 0 ! section rom_vectors 0 1 0 1 1 1 1 1 e000000 e000000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! diff --git a/packages/hal/arm/ebsa285/current/ChangeLog b/packages/hal/arm/ebsa285/current/ChangeLog --- a/packages/hal/arm/ebsa285/current/ChangeLog +++ b/packages/hal/arm/ebsa285/current/ChangeLog @@ -1,3 +1,17 @@ +2000-06-19 Gary Thomas + + * include/hal_platform_setup.h: + 'hal_dram_size' is now a properly defined variable (no more + fixed 0x40 stuff). + +2000-06-18 Gary Thomas + + * include/pkgconf/mlt_arm_ebsa285_ram.ldi: + * include/pkgconf/mlt_arm_ebsa285_ram.mlt: + * include/pkgconf/mlt_arm_ebsa285_rom.ldi: + * include/pkgconf/mlt_arm_ebsa285_rom.mlt: + Incorporate new fixed vectors (used on all ARM platforms). + 2000-02-29 Jonathan Larmour * include/pkgconf/mlt_arm_ebsa285_ram.h: diff --git a/packages/hal/arm/ebsa285/current/include/hal_platform_setup.h b/packages/hal/arm/ebsa285/current/include/hal_platform_setup.h --- a/packages/hal/arm/ebsa285/current/include/hal_platform_setup.h +++ b/packages/hal/arm/ebsa285/current/include/hal_platform_setup.h @@ -133,7 +133,7 @@ 778: #define CALL_MEMINIT_CODE \ mov r10, lr /* preserve lr */ ;\ bl __mem285_init ;\ - mov r1, #0x40 /* [see hal_intr.h] */ ;\ + ldr r1, =hal_dram_size /* [see hal_intr.h] */ ;\ str r0, [ r1 ] /* store the top of memory address */ ;\ mov lr, r10 /* in hal_dram_size for future use */ ;\ diff --git a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.ldi b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.ldi --- a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.ldi +++ b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.ldi @@ -10,8 +10,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved = 0; . = __reserved + 0x10000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0x10000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.mlt b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.mlt --- a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.mlt +++ b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_ram.mlt @@ -1,7 +1,7 @@ version 0 region ram 0 1000000 0 ! -section reserved 10000 1 0 0 1 1 1 1 0 0 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 10000 10000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.ldi b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.ldi --- a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.ldi +++ b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.ldi @@ -18,8 +18,8 @@ SECTIONS SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) - __reserved = 0; . = __reserved + 0x8000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x8000, FOLLOWING (.gcc_except_table)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTIONS_END } diff --git a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.mlt b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.mlt --- a/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.mlt +++ b/packages/hal/arm/ebsa285/current/include/pkgconf/mlt_arm_ebsa285_rom.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 1000000 0 ! region rom 41000000 400000 1 ! -section reserved 8000 1 0 0 1 1 1 0 0 0 data ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 8000 bss ! section bss 0 4 0 1 0 0 0 0 ! section rom_vectors 0 1 0 1 1 1 1 1 41000000 41000000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! diff --git a/packages/hal/arm/edb7xxx/current/ChangeLog b/packages/hal/arm/edb7xxx/current/ChangeLog --- a/packages/hal/arm/edb7xxx/current/ChangeLog +++ b/packages/hal/arm/edb7xxx/current/ChangeLog @@ -1,3 +1,21 @@ +2000-06-18 Gary Thomas + + * include/pkgconf/mlt_arm_cl7111_ram.ldi: + * include/pkgconf/mlt_arm_cl7111_ram.mlt: + * include/pkgconf/mlt_arm_cl7111_rom.ldi: + * include/pkgconf/mlt_arm_cl7111_rom.mlt: + * include/pkgconf/mlt_arm_edb7209_rom.ldi: + * include/pkgconf/mlt_arm_edb7209_rom.mlt: + * include/pkgconf/mlt_arm_edb7211_ram.ldi: + * include/pkgconf/mlt_arm_edb7211_ram.mlt: + * include/pkgconf/mlt_arm_edb7211_rom.ldi: + * include/pkgconf/mlt_arm_edb7211_rom.mlt: + * include/pkgconf/mlt_arm_edb7212_ram.ldi: + * include/pkgconf/mlt_arm_edb7212_ram.mlt: + * include/pkgconf/mlt_arm_edb7212_rom.ldi: + * include/pkgconf/mlt_arm_edb7212_rom.mlt: + Incorporate new fixed vectors (used on all ARM platforms). + 2000-04-07 Gary Thomas * cdl/hal_arm_edb7xxx.cdl: Fix build of i2s audio test. diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.ldi b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.ldi --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.ldi +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.ldi @@ -10,8 +10,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved = 0; . = __reserved + 0x8000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0x8000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.mlt b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.mlt --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.mlt +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_ram.mlt @@ -1,7 +1,7 @@ version 0 region ram 0 1c0000 0 ! -section reserved 8000 1 0 0 1 1 1 1 0 0 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 8000 8000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.ldi b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.ldi --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.ldi +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.ldi @@ -18,8 +18,8 @@ SECTIONS SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) - __reserved = 0; . = __reserved + 0x1000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x1000, FOLLOWING (.gcc_except_table)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTIONS_END } diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.mlt b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.mlt --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.mlt +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_cl7111_rom.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 1c0000 0 ! region rom e0000000 40000 1 ! -section reserved 1000 1 0 0 1 1 1 0 0 0 data ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 1000 bss ! section bss 0 4 0 1 0 0 0 0 ! section rom_vectors 0 1 0 1 1 1 1 1 e0000000 e0000000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.ldi b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.ldi --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.ldi +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.ldi @@ -19,8 +19,8 @@ SECTIONS SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_mmu_tables (rom, ALIGN (0x4000), LMA_EQ_VMA) - __reserved = 0; . = __reserved + 0x1000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.mmu_tables)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x1000, FOLLOWING (.mmu_tables)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTIONS_END } diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.mlt b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.mlt --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.mlt +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7209_rom.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 9c00 0 ! region rom e0000000 800000 1 !This is ROM bank 0, physical address 0x00000000.When running eCos, this space is remapped to 0xE0000000. -section reserved 1000 1 0 0 1 1 1 0 0 0 data ! -section data 0 1 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 1000 bss ! section bss 0 4 0 1 0 0 0 0 ! section rom_vectors 0 1 0 1 1 1 1 1 e0000000 e0000000 text text ! section text 0 1 0 1 0 1 0 1 fini fini ! diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.ldi b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.ldi --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.ldi +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.ldi @@ -10,7 +10,7 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved = 0; + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) SECTION_rom_vectors (ram, 0x8000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.mlt b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.mlt --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.mlt +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_ram.mlt @@ -1,6 +1,6 @@ version 0 region ram 0 fd9000 0 !DRAM -section reserved 0 1 0 0 1 0 1 0 0 0 ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! section rom_vectors 0 1 0 1 1 1 1 1 8000 8000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.ldi b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.ldi --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.ldi +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.ldi @@ -20,7 +20,7 @@ SECTIONS SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_mmu_tables (rom, ALIGN (0x4000), LMA_EQ_VMA) - __reserved = 0; + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) SECTION_data (ram, 0x1000, FOLLOWING (.mmu_tables)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) __sram = 0x60000000; diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.mlt b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.mlt --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.mlt +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7211_rom.mlt @@ -2,7 +2,7 @@ version 0 region ram 0 fd7000 0 ! region sram 60000000 9c00 0 ! region rom e0000000 800000 1 !This is ROM bank 0, physical address 0x00000000.When running eCos, this space is remapped to 0xE0000000. -section reserved 0 1 0 0 1 0 1 0 0 0 ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! section data 0 1 1 1 1 1 0 0 1000 bss ! section bss 0 4 0 1 0 0 0 0 ! section sram 0 1 0 0 1 0 1 0 60000000 60000000 ! diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.ldi b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.ldi --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.ldi +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.ldi @@ -11,8 +11,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved = 0; . = __reserved + 0x8000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0x8000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.mlt b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.mlt --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.mlt +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_ram.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 fd7000 0 ! region sram 60000000 9c00 0 ! -section reserved 8000 1 0 0 1 1 1 1 0 0 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 8000 8000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.ldi b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.ldi --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.ldi +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.ldi @@ -20,8 +20,8 @@ SECTIONS SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_mmu_tables (rom, ALIGN (0x4000), LMA_EQ_VMA) - __reserved = 0; . = __reserved + 0x1000; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.mmu_tables)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x1000, FOLLOWING (.mmu_tables)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_sram (sram, 0x60000000, LMA_EQ_VMA) SECTIONS_END diff --git a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.mlt b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.mlt --- a/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.mlt +++ b/packages/hal/arm/edb7xxx/current/include/pkgconf/mlt_arm_edb7212_rom.mlt @@ -2,8 +2,8 @@ version 0 region ram 0 fd7000 0 ! region sram 60000000 9c00 0 ! region rom e0000000 800000 1 !This is ROM bank 0, physical address 0x00000000.When running eCos, this space is remapped to 0xE0000000. -section reserved 1000 1 0 0 1 1 1 0 0 0 data ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 1000 bss ! section bss 0 4 0 1 0 0 0 0 ! section sram 0 1 0 1 1 0 1 0 60000000 60000000 ! section rom_vectors 0 1 0 1 1 1 1 1 e0000000 e0000000 text text ! diff --git a/packages/hal/arm/pid/current/ChangeLog b/packages/hal/arm/pid/current/ChangeLog --- a/packages/hal/arm/pid/current/ChangeLog +++ b/packages/hal/arm/pid/current/ChangeLog @@ -1,3 +1,27 @@ +2000-06-18 Gary Thomas + + * include/pkgconf/mlt_arm_pid9_ram.ldi: + * include/pkgconf/mlt_arm_pid9_ram.mlt: + * include/pkgconf/mlt_arm_pid9_rom.ldi: + * include/pkgconf/mlt_arm_pid9_rom.mlt: + * include/pkgconf/mlt_arm_pidBE_ram.ldi: + * include/pkgconf/mlt_arm_pidBE_ram.mlt: + * include/pkgconf/mlt_arm_pidBE_rom.ldi: + * include/pkgconf/mlt_arm_pidBE_rom.mlt: + * include/pkgconf/mlt_arm_pidTBE_ram.ldi: + * include/pkgconf/mlt_arm_pidTBE_ram.mlt: + * include/pkgconf/mlt_arm_pidTBE_rom.ldi: + * include/pkgconf/mlt_arm_pidTBE_rom.mlt: + * include/pkgconf/mlt_arm_pidT_ram.ldi: + * include/pkgconf/mlt_arm_pidT_ram.mlt: + * include/pkgconf/mlt_arm_pidT_rom.ldi: + * include/pkgconf/mlt_arm_pidT_rom.mlt: + * include/pkgconf/mlt_arm_pid_ram.ldi: + * include/pkgconf/mlt_arm_pid_ram.mlt: + * include/pkgconf/mlt_arm_pid_rom.ldi: + * include/pkgconf/mlt_arm_pid_rom.mlt: + Incorporate new fixed vectors (used on all ARM platforms). + 2000-03-24 Jesper Skov * src/hal_diag.c (hal_diag_write_char): Fix compiler warning. diff --git a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.ldi b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.ldi --- a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.ldi +++ b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.ldi @@ -10,8 +10,8 @@ MEMORY SECTIONS { SECTIONS_BEGIN - __reserved = 0; . = __reserved + 0x8000; - SECTION_rom_vectors (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0x8000, LMA_EQ_VMA) SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) diff --git a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.mlt b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.mlt --- a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.mlt +++ b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_ram.mlt @@ -1,7 +1,7 @@ version 0 region ram 0 80000 0 ! -section reserved 8000 1 0 0 1 1 1 1 0 0 rom_vectors rom_vectors ! -section rom_vectors 0 4 0 1 0 1 0 1 text text ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section rom_vectors 0 1 0 1 1 1 1 1 8000 8000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! section fini 0 4 0 1 0 1 0 1 rodata rodata ! section rodata 0 4 0 1 0 1 0 1 rodata1 rodata1 ! diff --git a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.ldi b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.ldi --- a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.ldi +++ b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.ldi @@ -18,8 +18,8 @@ SECTIONS SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) - __reserved = 0; . = __reserved + 0x800; - SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_fixed_vectors (ram, 0x20, LMA_EQ_VMA) + SECTION_data (ram, 0x800, FOLLOWING (.gcc_except_table)) SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) SECTIONS_END } diff --git a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.mlt b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.mlt --- a/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.mlt +++ b/packages/hal/arm/pid/current/include/pkgconf/mlt_arm_pid_rom.mlt @@ -1,8 +1,8 @@ version 0 region ram 0 80000 0 ! region rom 4000000 80000 1 ! -section reserved 800 1 0 0 1 1 1 0 0 0 data ! -section data 0 4 1 1 0 1 0 0 bss ! +section fixed_vectors 0 1 0 1 1 0 1 0 20 20 ! +section data 0 1 1 1 1 1 0 0 800 bss ! section bss 0 4 0 1 0 0 0 0 ! section rom_vectors 0 1 0 1 1 1 1 1 4000000 4000000 text text ! section text 0 4 0 1 0 1 0 1 fini fini ! diff --git a/packages/hal/common/current/ChangeLog b/packages/hal/common/current/ChangeLog --- a/packages/hal/common/current/ChangeLog +++ b/packages/hal/common/current/ChangeLog @@ -1,3 +1,40 @@ +2000-06-21 Jesper Skov + + * src/hal_stub.c: Fixed clients of vector procs tables to pass + in the correct arguments. Hook O-packetizer up on procs slot + reserved for IO mangler. Install mangler when necessary. + + * src/hal_if.c: Extended set procs functions to allow temporarily + switching console procs in a safe manner. Removed debug and + console wrappers - all IO happens via drivers hooked up in tables + rather than through hardwired macros. Proper initialization of + console proc entry. Fixed clients of vector procs tables to pass + in the correct arguments. Stub now does its own vector table + initialization. Added special procs slot for IO manglers. + + * include/hal_if.h: Define special IDs used by the set procs + functions. PROCS_HANDLED removed since the procs table will now + always service any port. + +2000-06-19 Gary Thomas + + * cdl/hal.cdl: Revert change below - GUARANTEED can exist + with STUBS defined. + +2000-06-18 Gary Thomas + + * cdl/hal.cdl: Use of virtual vector functions for diagnostic + output must be disabled when building with stubs. Note: this + lets stubs be built for platforms with guaranteed virtual + vector support. + +2000-06-16 Jesper Skov + + * include/hal_if.h: All vector-dependant features hidden when + config option not enabled. + + * src/hal_if.c (hal_if_init): Fix warning. + 2000-06-15 Jesper Skov * include/hal_if.h: Added console-include decision logic. diff --git a/packages/hal/common/current/include/hal_if.h b/packages/hal/common/current/include/hal_if.h --- a/packages/hal/common/current/include/hal_if.h +++ b/packages/hal/common/current/include/hal_if.h @@ -51,6 +51,7 @@ #include #include +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT //-------------------------------------------------------------------------- typedef int (*bsp_handler_t)(int __irq_nr, void *__regs); @@ -187,6 +188,20 @@ externC CYG_ADDRWORD hal_virtual_vector_ // (except INSTALL_BPT_FN since it's so high). #define CYGNUM_CALL_IF_TABLE_VERSION CYGNUM_CALL_IF_LAST_ENTRY + + +// These are special debug/console procs IDs +// QUERY_CURRENT will cause the ID of the currently selected proc ID to be +// returned. +// EMPTY this is the ID used for an empty procs table (i.e, NULL +// pointer) +// MANGLER selects the procs space reserved for the console mangler +// allowing the application to temporarily disable mangling +// or temporarily switch in different console procs. +#define CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT -1 +#define CYGNUM_CALL_IF_SET_COMM_ID_EMPTY -2 +#define CYGNUM_CALL_IF_SET_COMM_ID_MANGLER -3 + // The below is a (messy) attempt at adding some type safety to the // above array. At the same time, the accessors allow the // implementation to be easily changed in the future (both tag->data @@ -314,6 +329,13 @@ typedef void (*__call_if_install_bpt_fn_ #define CYGACC_CALL_IF_INSTALL_BPT_FN_SET(_x_) \ hal_virtual_vector_table[CYGNUM_CALL_IF_INSTALL_BPT_FN]=(CYG_ADDRWORD)(_x_) +//-------------------------------------------------------------------------- +// Diag wrappers. +externC void hal_if_diag_init(void); +externC void hal_if_diag_write_char(char c); +externC void hal_if_diag_read_char(char *c); + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT //-------------------------------------------------------------------------- // Functions provided by the HAL interface. @@ -321,23 +343,13 @@ externC void hal_if_init(void); //-------------------------------------------------------------------------- -// Diag wrappers. -externC void hal_if_diag_init(void); -externC void hal_if_diag_write_char(char c); -externC void hal_if_diag_read_char(char *c); - -//-------------------------------------------------------------------------- -// Determining if console code needs to be included, or if it will be -// provided by via the vector table: -// -// The console channel is already handled if (a) stubs are included and the -// console and debug channels are the same, or (b) the console channel is -// the same as the ROM monitor debug channel. -#if (defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) \ - && (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL)) \ - || (defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \ - && (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == CYGNUM_HAL_VIRTUAL_VECTOR_ROM_DEBUG_CHANNEL)) -# define CYGPRI_CONSOLE_PROCS_HANDLED +// Configuration control for the interface services. +// When this is set, code should initialize the vector table wherever +// appropriate. +#if defined(CYG_HAL_STARTUP_ROM) || \ + ( defined(CYG_HAL_STARTUP_RAM) && \ + !defined(CYGSEM_HAL_USE_ROM_MONITOR)) +# define CYGPRI_HAL_IMPLEMENTS_IF_SERVICES #endif //----------------------------------------------------------------------------- diff --git a/packages/hal/common/current/src/hal_if.c b/packages/hal/common/current/src/hal_if.c --- a/packages/hal/common/current/src/hal_if.c +++ b/packages/hal/common/current/src/hal_if.c @@ -62,18 +62,9 @@ externC void init_thread_syscall(void * externC CYG_ADDRWORD hal_interrupt_handlers[]; externC CYG_ADDRWORD hal_vsr_table[]; - -//-------------------------------------------------------------------------- -// Configuration control for the services in this feil. -#if defined(CYG_HAL_STARTUP_ROM) || \ - ( defined(CYG_HAL_STARTUP_RAM) && \ - !defined(CYGSEM_HAL_USE_ROM_MONITOR)) -# define CYGPRI_IMPLEMENTS_IF_SERVICES -#endif - //-------------------------------------------------------------------------- // Implementations and function wrappers for monitor services -#ifdef CYGPRI_IMPLEMENTS_IF_SERVICES +#ifdef CYGPRI_HAL_IMPLEMENTS_IF_SERVICES static void reset(void) @@ -117,20 +108,41 @@ nop_service(void) //---------------------------------- // Comm controls -static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS]; +static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+1]; + + static int set_debug_comm(int __comm_id) { - static int __selected_id; + static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY; - CYG_ASSERT(-1 == __comm_id - || __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, + CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER + && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, "Invalid channel"); - if (-1 == __comm_id) + switch (__comm_id) { + case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: + if (__selected_id > 0) + return __selected_id-1; + if (__selected_id == 0) + return CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; return __selected_id; + case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY: + CYGACC_CALL_IF_DEBUG_PROCS_SET(0); + __selected_id = __comm_id; + return 1; + + case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: + __comm_id = 0; + break; + + default: + __comm_id++; // skip mangler entry + break; + } + __selected_id = __comm_id; CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]); @@ -141,15 +153,34 @@ set_debug_comm(int __comm_id) static int set_console_comm(int __comm_id) { - static int __selected_id; + static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY; - CYG_ASSERT(-1 == __comm_id - || __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, + CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER + && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS, "Invalid channel"); - if (-1 == __comm_id) + switch (__comm_id) { + case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: + if (__selected_id > 0) + return __selected_id-1; + if (__selected_id == 0) + return CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; return __selected_id; + case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY: + CYGACC_CALL_IF_CONSOLE_PROCS_SET(0); + __selected_id = __comm_id; + return 1; + + case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: + __comm_id = 0; + break; + + default: + __comm_id++; // skip mangler entry + break; + } + __selected_id = __comm_id; CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]); @@ -157,63 +188,6 @@ set_console_comm(int __comm_id) return 1; } - -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -//---------------------------------- -// eCos debug procedure wrappers -static void -debug_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len) -{ - CYGARC_HAL_SAVE_GP(); - - while(__len-- > 0) - HAL_STUB_PLATFORM_PUT_CHAR(*__buf++); - - CYGARC_HAL_RESTORE_GP(); -} - -static void -debug_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) -{ - CYGARC_HAL_SAVE_GP(); - - while(__len-- > 0) - *__buf++ = HAL_STUB_PLATFORM_GET_CHAR(); - - CYGARC_HAL_RESTORE_GP(); -} - - -static void -debug_putc(void* __ch_data, cyg_uint8 __ch) -{ - CYGARC_HAL_SAVE_GP(); - - HAL_STUB_PLATFORM_PUT_CHAR(__ch); - - CYGARC_HAL_RESTORE_GP(); -} - -static cyg_uint8 -debug_getc(void* __ch_data) -{ - cyg_uint8 __ch; - CYGARC_HAL_SAVE_GP(); - - __ch = HAL_STUB_PLATFORM_GET_CHAR(); - - CYGARC_HAL_RESTORE_GP(); - return __ch; -} - -static int -debug_control(void *__ch_data, __comm_control_cmd_t __func, ...) -{ - // Do nothing (yet). - return 0; -} -#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - //---------------------------------- // Cache functions @@ -239,65 +213,6 @@ flush_dcache(void *__p, int __nbytes) #endif -#if !defined(CYGPRI_CONSOLE_PROCS_HANDLED) \ - && defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) -// -------------------- -// Console wrapper functions. These are used for pumping data to the device -// via low-level functions provided by the platform HAL. Mangling has -// happened (if applicable) by the time the stream hits this code. -static void -console_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len) -{ - CYGARC_HAL_SAVE_GP(); - - while(__len-- > 0) - HAL_PLF_DIAG_RAW_WRITE_CHAR(*__buf++); - - CYGARC_HAL_RESTORE_GP(); -} - -static void -console_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) -{ - CYGARC_HAL_SAVE_GP(); - - while(__len-- > 0) - HAL_PLF_DIAG_RAW_READ_CHAR(*__buf++); - - CYGARC_HAL_RESTORE_GP(); -} - - -static void -console_putc(void* __ch_data, cyg_uint8 __ch) -{ - CYGARC_HAL_SAVE_GP(); - - HAL_PLF_DIAG_RAW_WRITE_CHAR(__ch); - - CYGARC_HAL_RESTORE_GP(); -} - -static cyg_uint8 -console_getc(void* __ch_data) -{ - cyg_uint8 __ch; - CYGARC_HAL_SAVE_GP(); - - HAL_PLF_DIAG_RAW_READ_CHAR(__ch); - - CYGARC_HAL_RESTORE_GP(); - return __ch; -} - -static int -console_control(void *__ch_data, __comm_control_cmd_t __func, ...) -{ - // Do nothing (yet). - return 0; -} -#endif - #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) //----------------------------------------------------------------------------- // Console IO functions that adhere to the virtual vector table semantics in @@ -310,22 +225,17 @@ console_control(void *__ch_data, __comm_ void hal_if_diag_init(void) { -#ifndef CYGPRI_CONSOLE_PROCS_HANDLED - // Set up console procs for the channel and initialize it. - hal_virtual_comm_table_t* comm; - // Hook console wrappers up on the diag channel - CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL); - comm = CYGACC_CALL_IF_CONSOLE_PROCS(); +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + cyg_hal_plf_comms_init(); +#endif - CYGACC_COMM_IF_WRITE_SET(*comm, console_write); - CYGACC_COMM_IF_READ_SET(*comm, console_read); - CYGACC_COMM_IF_PUTC_SET(*comm, console_putc); - CYGACC_COMM_IF_GETC_SET(*comm, console_getc); - CYGACC_COMM_IF_CONTROL_SET(*comm, console_control); - - // Init device. - HAL_PLF_DIAG_RAW_INIT(); -#endif + // Set console channel. This should only be done when the console channel + // differs from the debug channel to prevent removing the debug agent's + // mangler procs. + if (CYGACC_CALL_IF_SET_DEBUG_COMM()(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT) + != CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL) + + CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL); } void @@ -334,10 +244,10 @@ hal_if_diag_write_char(char c) hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, c); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), c); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, c); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), c); } } @@ -347,10 +257,10 @@ hal_if_diag_read_char(char *c) hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) - *c = CYGACC_COMM_IF_GETC(*__chan)(*__chan); + *c = CYGACC_COMM_IF_GETC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan)); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); - *c = CYGACC_COMM_IF_GETC(*__chan)(*__chan); + *c = CYGACC_COMM_IF_GETC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan)); } } #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG @@ -364,9 +274,8 @@ void hal_if_init(void) { // Set up services provided by monitors -#ifdef CYGPRI_IMPLEMENTS_IF_SERVICES +#ifdef CYGPRI_HAL_IMPLEMENTS_IF_SERVICES { - hal_virtual_comm_table_t* comm; int i, j; // Initialize tables with the NOP service. // This should only be done for service routine entries - data @@ -374,7 +283,7 @@ hal_if_init(void) for (i = 0; i < CYGNUM_CALL_IF_TABLE_SIZE; i++) hal_virtual_vector_table[i] = (CYG_ADDRWORD) &nop_service; - for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS; j++) + for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+1; j++) for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++) comm_channels[j][i] = (CYG_ADDRWORD) &nop_service; @@ -401,23 +310,12 @@ hal_if_init(void) CYGACC_CALL_IF_FLUSH_ICACHE_SET(flush_icache); CYGACC_CALL_IF_FLUSH_DCACHE_SET(flush_dcache); - // Clear console procs entry. If platform has been to - // configured to use a separate console port, it will be set - // up later (hal_diag_init). Alternatively (if this is a stub) - // it will be initialized with the output mangler - // (O-packetizer for GDB) which uses the debug comms. - CYGACC_CALL_IF_CONSOLE_PROCS_SET(0); - -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - // Hook debug wrappers up on the debug channel - set_debug_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); - comm = CYGACC_CALL_IF_DEBUG_PROCS(); - CYGACC_COMM_IF_WRITE_SET(*comm, debug_write); - CYGACC_COMM_IF_READ_SET(*comm, debug_read); - CYGACC_COMM_IF_PUTC_SET(*comm, debug_putc); - CYGACC_COMM_IF_GETC_SET(*comm, debug_getc); - CYGACC_COMM_IF_CONTROL_SET(*comm, debug_control); -#endif + // Clear console procs entry. If platform has been configured + // to use a separate console port, it will be set up later + // (hal_diag_init). Alternatively (if this is a stub) it will + // be initialized with the output mangler (O-packetizer for + // GDB) which uses the debug comms. + set_console_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY); // Data entries not currently supported in eCos CYGACC_CALL_IF_CPU_DATA_SET(0); diff --git a/packages/hal/common/current/src/hal_stub.c b/packages/hal/common/current/src/hal_stub.c --- a/packages/hal/common/current/src/hal_stub.c +++ b/packages/hal/common/current/src/hal_stub.c @@ -107,7 +107,7 @@ putDebugChar (int c) { #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); - CYGACC_COMM_IF_PUTC(*__debug_procs)(__debug_procs, c); + CYGACC_COMM_IF_PUTC(*__debug_procs)(CYGACC_COMM_IF_CH_DATA(*__debug_procs), c); #elif defined(CYGPKG_CYGMON) ecos_bsp_console_putc(c); #else @@ -121,7 +121,7 @@ getDebugChar (void) { #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); - return CYGACC_COMM_IF_GETC(*__debug_procs)(__debug_procs); + return CYGACC_COMM_IF_GETC(*__debug_procs)(CYGACC_COMM_IF_CH_DATA(*__debug_procs)); #elif defined(CYGPKG_CYGMON) return ecos_bsp_console_getc(); #else @@ -135,7 +135,7 @@ void { #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); - CYGACC_COMM_IF_CONTROL(*__debug_procs)(__debug_procs, __COMMCTL_SETBAUD, baud); + CYGACC_COMM_IF_CONTROL(*__debug_procs)(CYGACC_COMM_IF_CH_DATA(*__debug_procs), __COMMCTL_SETBAUD, baud); #elif defined(CYGPKG_CYGMON) // FIXME! #else @@ -270,7 +270,7 @@ cyg_hal_gdb_diag_getc(void* __ch_data) hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGARC_HAL_SAVE_GP(); - __ch = CYGACC_COMM_IF_GETC(*__chan)(*__chan); + __ch = CYGACC_COMM_IF_GETC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan)); CYGARC_HAL_RESTORE_GP(); @@ -307,24 +307,24 @@ cyg_hal_gdb_diag_putc(void* __ch_data, c cyg_uint8 csum = 0, c1; int i; - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, '$'); - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, 'O'); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), '$'); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), 'O'); csum += 'O'; for( i = 0; i < pos; i++ ) { char ch = line[i]; char h = hex[(ch>>4)&0xF]; char l = hex[ch&0xF]; - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, h); - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, l); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), h); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), l); csum += h; csum += l; } - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, '#'); - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, hex[(csum>>4)&0xF]); - CYGACC_COMM_IF_PUTC(*__chan)(*__chan, hex[csum&0xF]); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), '#'); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), hex[(csum>>4)&0xF]); + CYGACC_COMM_IF_PUTC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan), hex[csum&0xF]); - c1 = CYGACC_COMM_IF_GETC(*__chan)(*__chan); + c1 = CYGACC_COMM_IF_GETC(*__chan)(CYGACC_COMM_IF_CH_DATA(*__chan)); if( c1 == '+' ) break; if( cyg_hal_is_break( &c1 , 1 ) ) { @@ -357,11 +357,10 @@ cyg_hal_gdb_diag_write(void* __ch_data, static void cyg_hal_gdb_diag_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) { - hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGARC_HAL_SAVE_GP(); while(__len-- > 0) - *__buf++ = CYGACC_COMM_IF_GETC(*__chan)(*__chan); + *__buf++ = cyg_hal_gdb_diag_getc(__ch_data); CYGARC_HAL_RESTORE_GP(); } @@ -372,15 +371,6 @@ cyg_hal_gdb_diag_control(void *__ch_data // Do nothing (yet). return 0; } - -hal_virtual_comm_table_t cyg_hal_gdb_console_procs = { - 0, - (CYG_ADDRWORD) &cyg_hal_gdb_diag_write, - (CYG_ADDRWORD) &cyg_hal_gdb_diag_read, - (CYG_ADDRWORD) &cyg_hal_gdb_diag_putc, - (CYG_ADDRWORD) &cyg_hal_gdb_diag_getc, - (CYG_ADDRWORD) &cyg_hal_gdb_diag_control}; - #endif @@ -479,8 +469,9 @@ initHardware (void) { static int initialized = 0; - if (initialized++) + if (initialized) return; + initialized = 1; #if !defined(CYGPKG_CYGMON) #ifdef HAL_STUB_PLATFORM_INIT @@ -492,13 +483,30 @@ initHardware (void) HAL_STUB_PLATFORM_INIT_SERIAL(); #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT - // This should really be done during handle_exception_init (at - // stub exit), but that makes it impossible a stub to be included - // in the application without breaking things. So do it here - // instead - stub initialization happens after - // constructors/hal_diag_init anyway. - if (NULL == CYGACC_CALL_IF_CONSOLE_PROCS()) - CYGACC_CALL_IF_CONSOLE_PROCS_SET(cyg_hal_gdb_console_procs); + { + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Initialize mangler procs + CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_gdb_diag_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_gdb_diag_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_gdb_diag_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_gdb_diag_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_gdb_diag_control); + + // Now either restore the previous console channel, or let the + // mangler stay in its place. The latter happens if the + // console channel was previously unspecified, or if the + // previous channel matches the used for GDB communication. + if (CYGNUM_CALL_IF_SET_COMM_ID_EMPTY != cur + && CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL != cur) + CYGACC_CALL_IF_SET_CONSOLE_COMM()(cur); + + // Set the debug channel. + CYGACC_CALL_IF_SET_DEBUG_COMM()(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); + } #endif #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT diff --git a/packages/hal/i386/pc/current/ChangeLog b/packages/hal/i386/pc/current/ChangeLog --- a/packages/hal/i386/pc/current/ChangeLog +++ b/packages/hal/i386/pc/current/ChangeLog @@ -1,3 +1,8 @@ +2000-06-20 Nick Garnett + + * include/var_intr.h: Added cast to _data_ argument in + HAL_INTERRUPT_ATTACH() to prevent compiler errors. + 2000-03-23 Nick Garnett * doc/RELEASENOTES.txt: Added this file to contain release notes. diff --git a/packages/hal/i386/pc/current/include/var_intr.h b/packages/hal/i386/pc/current/include/var_intr.h --- a/packages/hal/i386/pc/current/include/var_intr.h +++ b/packages/hal/i386/pc/current/include/var_intr.h @@ -118,7 +118,8 @@ externC void hal_pc_interrupt_attach(CYG_ADDRWORD vector, CYG_ADDRESS isr, CYG_ADDRWORD parameter, void * object) ; #define HAL_INTERRUPT_ATTACH(_vector_, _isr_, _data_, _object_) \ - hal_pc_interrupt_attach(_vector_, (CYG_ADDRESS)_isr_, _data_, _object_) + hal_pc_interrupt_attach(_vector_, (CYG_ADDRESS)_isr_, \ + (CYG_ADDRWORD)_data_, _object_) #define HAL_ENABLE_INTERRUPTS() \ CYG_MACRO_START \ diff --git a/packages/hal/powerpc/cogent/current/ChangeLog b/packages/hal/powerpc/cogent/current/ChangeLog --- a/packages/hal/powerpc/cogent/current/ChangeLog +++ b/packages/hal/powerpc/cogent/current/ChangeLog @@ -1,3 +1,49 @@ +2000-06-21 Jesper Skov + + * src/plf_stub.c: Provide plf stub init which prints build date + on LCD for ROM monitor configs. + + * src/cma_ser.inl: [deleted] + * src/hal_diag.c: + * include/plf_stub.h: + * include/hal_diag.h: + * cdl/hal_powerpc_cogent.cdl: + Added LCD as the 3rd comms channel. Cleanups to support full procs + table. + +2000-06-20 Jesper Skov + + * include/pkgconf/mlt_powerpc_cogent_ram.h: + * include/pkgconf/mlt_powerpc_cogent_ram.mlt: + * include/pkgconf/mlt_powerpc_cogent_ram.ldi: + * include/pkgconf/mlt_powerpc_cogent_rom.h: + * include/pkgconf/mlt_powerpc_cogent_rom.mlt: + * include/pkgconf/mlt_powerpc_cogent_rom.ldi: + Updated. + +2000-06-16 Jesper Skov + + * src/plf_stub.c: + * src/cma_ser.inl: Removed BREAK handling. + + * include/plf_stub.h: Changed to virtual vector style. + + * src/plf_misc.c: + * include/plf_intr.h: Added ctrlc handling. + + * src/hal_diag.c: + * include/hal_diag.h: virtual vector changes. + + * hal_aux.c renamed to plf_misc.c + + * cdl/hal_powerpc_cogent.cdl: Added virtual vector options. + + * include/pkgconf/mlt_powerpc_cogent_rom.ldi: + * include/pkgconf/mlt_powerpc_cogent_rom.mlt: + * include/pkgconf/mlt_powerpc_cogent_ram.ldi: + * include/pkgconf/mlt_powerpc_cogent_rom.mlt: + Added space for virtual table. + 2000-06-13 Jesper Skov * include/plf_intr.h: Added. diff --git a/packages/hal/powerpc/cogent/current/cdl/hal_powerpc_cogent.cdl b/packages/hal/powerpc/cogent/current/cdl/hal_powerpc_cogent.cdl --- a/packages/hal/powerpc/cogent/current/cdl/hal_powerpc_cogent.cdl +++ b/packages/hal/powerpc/cogent/current/cdl/hal_powerpc_cogent.cdl @@ -50,10 +50,11 @@ cdl_package CYGPKG_HAL_POWERPC_COGENT { The cogent HAL package provides the support needed to run eCos on a Cogent board equipped with a PowerPC processor." - compile hal_diag.c hal_aux.c cogent.S plf_stub.c + compile hal_diag.c plf_misc.c cogent.S plf_stub.c implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT define_proc { puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " @@ -78,30 +79,49 @@ cdl_package CYGPKG_HAL_POWERPC_COGENT { equivalent technology." } - cdl_option CYGHWR_HAL_POWERPC_COGENT_GDB_PORT { - display "GDB Serial Port" - flavor data - legal_values 1 0 + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 3 + description " + Channel 0: Serial A, Channel 1: Serial B, Channel 2: LCD" + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 default_value 1 description " - The Cogent board has two separate serial ports. This option - chooses which of these ports will be used by the GDB stub. - On the CMA101 board, 0 and 1 are the P11 and P12 - connectors respectively. On the CMA102 board, 0 and 1 are - the P2 and P3 connectors respectively." + The MBX board has only one serial port. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 1 + description " + The MBX board has only one serial port. This option + chooses which port will be used for diagnostic output." } - cdl_option CYGHWR_HAL_POWERPC_COGENT_DIAG_PORT { - display "Diag Serial Port" - flavor data - legal_values 1 0 + # This option is only used when USE_ROM_MONITOR is enabled - but + # it cannot be a sub-option to that option, since the code uses the + # definition in a preprocessor comparison. + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_ROM_DEBUG_CHANNEL { + display "Debug serial port used by ROM monitor" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 default_value 1 description " - The Cogent board has two separate serial ports. This option - chooses which of these ports will be used for diag output. - On the CMA101 board, 0 and 1 are the P11 and P12 - connectors respectively. On the CMA102 board, 0 and 1 are - the P2 and P3 connectors respectively." + The MBX board has only one serial port. This + option tells the code which port is in use by the ROM + monitor. It should only be necessary to change this + option if a non-standard configurated eCos GDB stub is + used." } cdl_option CYGHWR_HAL_POWERPC_BOARD_SPEED { @@ -187,8 +207,8 @@ cdl_package CYGPKG_HAL_POWERPC_COGENT { requires CYGSEM_HAL_ROM_MONITOR requires CYGBLD_BUILD_COMMON_GDB_STUBS requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM no_define diff --git a/packages/hal/powerpc/cogent/current/include/hal_diag.h b/packages/hal/powerpc/cogent/current/include/hal_diag.h --- a/packages/hal/powerpc/cogent/current/include/hal_diag.h +++ b/packages/hal/powerpc/cogent/current/include/hal_diag.h @@ -49,6 +49,16 @@ #include +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) + +#include + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +#else // everything by steam + //----------------------------------------------------------------------------- // functions implemented in hal_diag.c @@ -66,6 +76,8 @@ externC void hal_diag_read_char(char *c) #define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + //----------------------------------------------------------------------------- // end of hal_diag.h #endif // CYGONCE_HAL_HAL_DIAG_H diff --git a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.h b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.h --- a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.h +++ b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.h @@ -1,10 +1,22 @@ -// eCos memory layout - Wed Nov 24 15:29:29 1999 - -// This is a generated file - changes will be lost if ConfigTool(MLT) is run - -#include -#include - -#define CYGMEM_REGION_ram (0) -#define CYGMEM_REGION_ram_SIZE (0x800000) -#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +// eCos memory layout - Tue Jun 20 10:13:16 2000 + +// This is a generated file - do not edit + +#include +#include + +#define CYGMEM_REGION_ram (0) +#define CYGMEM_REGION_ram_SIZE (0x800000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +extern char CYG_LABEL_NAME (_reserved_vectors) []; +#define CYGMEM_SECTION_reserved_vectors (CYG_LABEL_NAME (_reserved_vectors)) +#define CYGMEM_SECTION_reserved_vectors_SIZE (0x3000) +extern char CYG_LABEL_NAME (_reserved_vsr_table) []; +#define CYGMEM_SECTION_reserved_vsr_table (CYG_LABEL_NAME (_reserved_vsr_table)) +#define CYGMEM_SECTION_reserved_vsr_table_SIZE (0x200) +extern char CYG_LABEL_NAME (_reserved_virtual_table) []; +#define CYGMEM_SECTION_reserved_virtual_table (CYG_LABEL_NAME (_reserved_virtual_table)) +#define CYGMEM_SECTION_reserved_virtual_table_SIZE (0x100) +extern char CYG_LABEL_NAME (_reserved_for_rom) []; +#define CYGMEM_SECTION_reserved_for_rom (CYG_LABEL_NAME (_reserved_for_rom)) +#define CYGMEM_SECTION_reserved_for_rom_SIZE (0xcd00) diff --git a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.ldi b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.ldi --- a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.ldi +++ b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.ldi @@ -1,53 +1,28 @@ -//=========================================================================== -// -// RAM start linker control script -// -//=========================================================================== -//####COPYRIGHTBEGIN#### -// -// ------------------------------------------- -// The contents of this file are subject to the Red Hat eCos Public License -// Version 1.1 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://www.redhat.com/ -// -// Software distributed under the License is distributed on an "AS IS" -// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -// License for the specific language governing rights and limitations under -// the License. -// -// The Original Code is eCos - Embedded Configurable Operating System, -// released September 30, 1998. -// -// The Initial Developer of the Original Code is Red Hat. -// Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. -// All Rights Reserved. -// ------------------------------------------- -// -//####COPYRIGHTEND#### -//=========================================================================== - -MEMORY -{ - ram : ORIGIN = 0x00000000, LENGTH = 0x800000 -} - -SECTIONS -{ - SECTIONS_BEGIN - __reserved_vectors = 0; . = __reserved_vectors + 0x3000; - __reserved_vsr_table = ALIGN (0x1); . = __reserved_vsr_table + 0x200; - __reserved_for_rom = ALIGN (0x1); . = __reserved_for_rom + 0xce00; - SECTION_vectors (ram, ALIGN(0x4), LMA_EQ_VMA) - SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) - SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) - SECTION_rodata1 (ram, ALIGN (0x8), LMA_EQ_VMA) - SECTION_rodata (ram, ALIGN (0x8), LMA_EQ_VMA) - SECTION_fixup (ram, ALIGN (0x4), LMA_EQ_VMA) - SECTION_gcc_except_table (ram, ALIGN (0x1), LMA_EQ_VMA) - SECTION_data (ram, ALIGN (0x8), LMA_EQ_VMA) - SECTION_sbss (ram, ALIGN (0x4), LMA_EQ_VMA) - SECTION_bss (ram, ALIGN (0x10), LMA_EQ_VMA) - SECTIONS_END -} +// eCos memory layout - Tue Jun 20 10:13:16 2000 + +// This is a generated file - do not edit + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 0x800000 +} + +SECTIONS +{ + SECTIONS_BEGIN + __reserved_vectors = 0; . = __reserved_vectors + 0x3000; + __reserved_vsr_table = ALIGN (0x10); . = __reserved_vsr_table + 0x200; + __reserved_virtual_table = ALIGN (0x10); . = __reserved_virtual_table + 0x100; + __reserved_for_rom = ALIGN (0x10); . = __reserved_for_rom + 0xcd00; + SECTION_vectors (ram, ALIGN (0x10), LMA_EQ_VMA) + SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (ram, ALIGN (0x8), LMA_EQ_VMA) + SECTION_rodata (ram, ALIGN (0x8), LMA_EQ_VMA) + SECTION_fixup (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x8), LMA_EQ_VMA) + SECTION_sbss (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x10), LMA_EQ_VMA) + SECTIONS_END +} diff --git a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.mlt b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.mlt --- a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.mlt +++ b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_ram.mlt @@ -1,15 +1,16 @@ -version 0 -region ram 0 800000 0 ! -section reserved_vectors 3000 1 0 0 1 1 1 1 0 0 reserved_vsr_table reserved_vsr_table ! -section reserved_vsr_table 200 1 0 0 0 1 0 1 reserved_for_rom reserved_for_rom ! -section reserved_for_rom ce00 1 0 0 0 1 0 1 vectors vectors ! -section vectors 0 4 0 1 0 1 0 1 text text ! -section text 0 4 0 1 0 1 0 1 fini fini ! -section fini 0 4 0 1 0 1 0 1 rodata1 rodata1 ! -section rodata1 0 8 0 1 0 1 0 1 rodata rodata ! -section rodata 0 8 0 1 0 1 0 1 fixup fixup ! -section fixup 0 4 0 1 0 1 0 1 gcc_except_table gcc_except_table ! -section gcc_except_table 0 1 0 1 0 1 0 1 data data ! -section data 0 8 0 1 0 1 0 1 sbss sbss ! -section sbss 0 4 0 1 0 1 0 1 bss bss ! -section bss 0 10 0 1 0 0 0 0 ! +version 0 +region ram 0 800000 0 ! +section reserved_vectors 3000 1 0 0 1 1 1 1 0 0 reserved_vsr_table reserved_vsr_table ! +section reserved_vsr_table 200 10 0 0 0 1 0 1 reserved_virtual_table reserved_virtual_table ! +section reserved_virtual_table 100 10 0 0 0 1 0 1 reserved_for_rom reserved_for_rom ! +section reserved_for_rom cd00 10 0 0 0 1 0 1 vectors vectors ! +section vectors 0 10 0 1 0 1 0 1 text text ! +section text 0 4 0 1 0 1 0 1 fini fini ! +section fini 0 4 0 1 0 1 0 1 rodata1 rodata1 ! +section rodata1 0 8 0 1 0 1 0 1 rodata rodata ! +section rodata 0 8 0 1 0 1 0 1 fixup fixup ! +section fixup 0 4 0 1 0 1 0 1 gcc_except_table gcc_except_table ! +section gcc_except_table 0 1 0 1 0 1 0 1 data data ! +section data 0 8 0 1 0 1 0 1 sbss sbss ! +section sbss 0 4 0 1 0 1 0 1 bss bss ! +section bss 0 10 0 1 0 0 0 0 ! diff --git a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.h b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.h --- a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.h +++ b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.h @@ -1,13 +1,22 @@ -// eCos memory layout - Wed Nov 24 11:39:14 1999 - -// This is a generated file - changes will be lost if ConfigTool(MLT) is run - -#include -#include - -#define CYGMEM_REGION_ram (0x0) -#define CYGMEM_REGION_ram_SIZE (0x800000) -#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) -#define CYGMEM_REGION_rom (0xfff00000) -#define CYGMEM_REGION_rom_SIZE (0x40000) -#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +// eCos memory layout - Tue Jun 20 10:15:36 2000 + +// This is a generated file - do not edit + +#include +#include + +#define CYGMEM_REGION_ram (0) +#define CYGMEM_REGION_ram_SIZE (0x800000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0xfff00000) +#define CYGMEM_REGION_rom_SIZE (0x40000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +extern char CYG_LABEL_NAME (_reserved_vectors) []; +#define CYGMEM_SECTION_reserved_vectors (CYG_LABEL_NAME (_reserved_vectors)) +#define CYGMEM_SECTION_reserved_vectors_SIZE (0x3000) +extern char CYG_LABEL_NAME (_reserved_vsr_table) []; +#define CYGMEM_SECTION_reserved_vsr_table (CYG_LABEL_NAME (_reserved_vsr_table)) +#define CYGMEM_SECTION_reserved_vsr_table_SIZE (0x200) +extern char CYG_LABEL_NAME (_reserved_virtual_table) []; +#define CYGMEM_SECTION_reserved_virtual_table (CYG_LABEL_NAME (_reserved_virtual_table)) +#define CYGMEM_SECTION_reserved_virtual_table_SIZE (0x100) diff --git a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.ldi b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.ldi --- a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.ldi +++ b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.ldi @@ -1,53 +1,28 @@ -//=========================================================================== -// -// ROM start linker control script -// -//=========================================================================== -//####COPYRIGHTBEGIN#### -// -// ------------------------------------------- -// The contents of this file are subject to the Red Hat eCos Public License -// Version 1.1 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://www.redhat.com/ -// -// Software distributed under the License is distributed on an "AS IS" -// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -// License for the specific language governing rights and limitations under -// the License. -// -// The Original Code is eCos - Embedded Configurable Operating System, -// released September 30, 1998. -// -// The Initial Developer of the Original Code is Red Hat. -// Portions created by Red Hat are -// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. -// All Rights Reserved. -// ------------------------------------------- -// -//####COPYRIGHTEND#### -//=========================================================================== - -MEMORY -{ - rom : ORIGIN = 0xfff00000, LENGTH = 0x40000 - ram : ORIGIN = 0x00000000, LENGTH = 0x800000 -} - -SECTIONS -{ - SECTIONS_BEGIN - SECTION_vectors (rom, 0xfff00000, LMA_EQ_VMA) - SECTION_text (rom, ALIGN (0x4), LMA_EQ_VMA) - SECTION_fini (rom, ALIGN (0x8), LMA_EQ_VMA) - SECTION_rodata1 (rom, ALIGN (0x8), LMA_EQ_VMA) - SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) - SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) - SECTION_gcc_except_table (rom, ALIGN (0x1), LMA_EQ_VMA) - __reserved_vectors = 0; . = __reserved_vectors + 0x3000; - __reserved_vsr_table = ALIGN (0x1); . = __reserved_vsr_table + 0x200; - SECTION_data (ram, ALIGN (0x10), FOLLOWING (.gcc_except_table)) - SECTION_sbss (ram, ALIGN (0x4), LMA_EQ_VMA) - SECTION_bss (ram, ALIGN (0x10), LMA_EQ_VMA) - SECTIONS_END -} +// eCos memory layout - Tue Jun 20 10:15:36 2000 + +// This is a generated file - do not edit + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 0x800000 + rom : ORIGIN = 0xfff00000, LENGTH = 0x40000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_vectors (rom, 0xfff00000, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x8), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x8), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x1), LMA_EQ_VMA) + __reserved_vectors = 0; . = __reserved_vectors + 0x3000; + __reserved_vsr_table = ALIGN (0x10); . = __reserved_vsr_table + 0x200; + __reserved_virtual_table = ALIGN (0x10); . = __reserved_virtual_table + 0x100; + SECTION_data (ram, ALIGN (0x10), FOLLOWING (.gcc_except_table)) + SECTION_sbss (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x10), LMA_EQ_VMA) + SECTIONS_END +} diff --git a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.mlt b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.mlt --- a/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.mlt +++ b/packages/hal/powerpc/cogent/current/include/pkgconf/mlt_powerpc_cogent_rom.mlt @@ -1,15 +1,16 @@ -version 0 -region ram 0 800000 0 ! -region rom fff00000 40000 1 ! -section reserved_vectors 3000 1 0 0 1 1 1 1 0 0 reserved_vsr_table reserved_vsr_table ! -section reserved_vsr_table 200 4 0 0 0 1 0 1 data data ! -section data 0 10 0 1 0 1 0 1 sbss sbss ! -section sbss 0 4 0 1 0 1 0 1 bss bss ! -section bss 0 10 0 1 0 0 0 0 ! -section vectors 0 1 0 1 1 1 1 1 fff00000 fff00000 text text ! -section text 0 4 0 1 0 1 0 1 fini fini ! -section fini 0 8 0 1 0 1 0 1 rodata1 rodata1 ! -section rodata1 0 8 0 1 0 1 0 1 rodata rodata ! -section rodata 0 4 0 1 0 1 0 1 fixup fixup ! -section fixup 0 4 0 1 0 1 0 1 gcc_except_table gcc_except_table ! -section gcc_except_table 0 1 0 1 0 0 0 1 data ! +version 0 +region ram 0 800000 0 ! +region rom fff00000 40000 1 ! +section reserved_vectors 3000 1 0 0 1 1 1 1 0 0 reserved_vsr_table reserved_vsr_table ! +section reserved_vsr_table 200 10 0 0 0 1 0 1 reserved_virtual_table reserved_virtual_table ! +section reserved_virtual_table 100 10 0 0 0 1 0 0 data ! +section data 0 10 1 1 0 1 0 0 sbss ! +section sbss 0 4 0 1 0 1 0 1 bss bss ! +section bss 0 10 0 1 0 0 0 0 ! +section vectors 0 1 0 1 1 1 1 1 fff00000 fff00000 text text ! +section text 0 4 0 1 0 1 0 1 fini fini ! +section fini 0 8 0 1 0 1 0 1 rodata1 rodata1 ! +section rodata1 0 8 0 1 0 1 0 1 rodata rodata ! +section rodata 0 4 0 1 0 1 0 1 fixup fixup ! +section fixup 0 4 0 1 0 1 0 1 gcc_except_table gcc_except_table ! +section gcc_except_table 0 1 0 1 0 0 0 1 data ! diff --git a/packages/hal/powerpc/cogent/current/include/plf_intr.h b/packages/hal/powerpc/cogent/current/include/plf_intr.h --- a/packages/hal/powerpc/cogent/current/include/plf_intr.h +++ b/packages/hal/powerpc/cogent/current/include/plf_intr.h @@ -48,7 +48,21 @@ // //========================================================================== -// Empty for now +//-------------------------------------------------------------------------- +// Control-C support. + +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + +// Serial interrupts are feed to IRQ1 (vector 0x08) on the Cogent +// board. +# define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_SIU_IRQ1 + +externC cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); + +# define HAL_CTRLC_ISR hal_ctrlc_isr + +#endif //-------------------------------------------------------------------------- #endif // ifndef CYGONCE_HAL_PLF_INTR_H diff --git a/packages/hal/powerpc/cogent/current/include/plf_stub.h b/packages/hal/powerpc/cogent/current/include/plf_stub.h --- a/packages/hal/powerpc/cogent/current/include/plf_stub.h +++ b/packages/hal/powerpc/cogent/current/include/plf_stub.h @@ -59,43 +59,34 @@ #include // architecture stub support //---------------------------------------------------------------------------- -// Define serial stuff. -externC void hal_cma_stub_init_serial( void ); -externC int hal_cma_stub_get_char( void ); -externC void hal_cma_stub_put_char( int c ); -externC int hal_cma_stub_interruptible( int state ); -externC void hal_cma_stub_init_break_irq( void ); +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. -// Only define init function if no serial driver is used on the same port. -#if ((CYGHWR_HAL_POWERPC_COGENT_GDB_PORT == 0 \ - && defined(CYGPKG_IO_SERIAL_POWERPC_COGENT_SERIAL_A)) || \ - (CYGHWR_HAL_POWERPC_COGENT_GDB_PORT == 1 \ - && defined(CYGPKG_IO_SERIAL_POWERPC_COGENT_SERIAL_B))) -#define HAL_STUB_PLATFORM_INIT_SERIAL() CYG_EMPTY_STATEMENT -#else -#define HAL_STUB_PLATFORM_INIT_SERIAL() hal_cma_stub_init_serial() -#endif +externC void cyg_hal_plf_comms_init(void); -#define HAL_STUB_PLATFORM_GET_CHAR() hal_cma_stub_get_char() -#define HAL_STUB_PLATFORM_PUT_CHAR(c) hal_cma_stub_put_char((c)) +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() + #define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) -#define HAL_STUB_PLATFORM_INTERRUPTIBLE (&hal_cma_stub_interruptible) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 #define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() hal_cma_stub_init_break_irq() //---------------------------------------------------------------------------- // Stub initializer. -#ifdef CYGSEM_HAL_ROM_MONITOR -extern void diag_init (void); -# define HAL_STUB_PLATFORM_INIT() diag_init() -#else -# define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT -#endif +//---------------------------------------------------------------------------- +// Stub initializer. +extern void hal_plf_stub_init( void ); +#define HAL_STUB_PLATFORM_INIT() hal_plf_stub_init(); + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS //---------------------------------------------------------------------------- // Reset. +// The Cogent does not have a watchdog (not one we can easily use for this +// purpose anyway). #define HAL_STUB_PLATFORM_RESET() CYG_EMPTY_STATEMENT -#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#define HAL_STUB_PLATFORM_RESET_ENTRY 0xfff00100 //----------------------------------------------------------------------------- #endif // CYGONCE_HAL_PLF_STUB_H diff --git a/packages/hal/powerpc/cogent/current/src/hal_diag.c b/packages/hal/powerpc/cogent/current/src/hal_diag.c --- a/packages/hal/powerpc/cogent/current/src/hal_diag.c +++ b/packages/hal/powerpc/cogent/current/src/hal_diag.c @@ -42,85 +42,560 @@ //============================================================================= #include -#include // CYGHWR_HAL_POWERPC_COGENT_DIAG_PORT #include // our header. #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) -#include // hal_output_gdb_string +#include // CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION #endif #include // base types, externC #include // IO macros #include // Interrupt macros -//----------------------------------------------------------------------------- -// Select default diag channel to use +#include // SAVE/RESTORE GP +#include // Calling-if API + + +static void cyg_hal_plf_serial_init(void); +static void cyg_hal_plf_lcd_init(void); -//#define CYG_KERNEL_DIAG_ROMART -//#define CYG_KERNEL_DIAG_LCD -//#define CYG_KERNEL_DIAG_SERIAL +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; -#if !defined(CYG_KERNEL_DIAG_SERIAL) && \ - !defined(CYG_KERNEL_DIAG_LCD) && \ - !defined(CYG_KERNEL_DIAG_ROMART) + initialized = 1; + + cyg_hal_plf_serial_init(); + cyg_hal_plf_lcd_init(); +} -#define CYG_KERNEL_DIAG_SERIAL - +#if 0 +#ifdef CYGSEM_HAL_ROM_MONITOR + // It's handy to have the LCD initialized at reset when using it + // for debugging output. + { + diag_write_string ("eCos ROM " __TIME__ "\n"); + diag_write_string (__DATE__ "\n"); + } +#endif #endif -// Always use LCD when building a GDB stub ROM. -#ifdef CYGSEM_HAL_ROM_MONITOR -#undef CYG_KERNEL_DIAG_SERIAL -#undef CYG_KERNEL_DIAG_ROMART +//============================================================================= +// Serial driver +//============================================================================= + +//----------------------------------------------------------------------------- +// There are two serial ports. +#define CYG_DEV_SERIAL_BASE_A 0xe900047 // port A +#define CYG_DEV_SERIAL_BASE_B 0xe900007 // port B + +//----------------------------------------------------------------------------- +// Default baud rate is 38400 +#define CYG_DEV_SERIAL_RS232_T1_VALUE_B38400 0x00 +#define CYG_DEV_SERIAL_RS232_T2_VALUE_B38400 0x06 + +//----------------------------------------------------------------------------- +// Define the serial registers. The Cogent board is equipped with a 16552 +// serial chip. +#define CYG_DEV_SERIAL_RBR 0x00 // receiver buffer register, read, dlab = 0 +#define CYG_DEV_SERIAL_THR 0x00 // transmitter holding register, write, dlab = 0 +#define CYG_DEV_SERIAL_DLL 0x00 // divisor latch (LS), read/write, dlab = 1 +#define CYG_DEV_SERIAL_IER 0x08 // interrupt enable register, read/write, dlab = 0 +#define CYG_DEV_SERIAL_DLM 0x08 // divisor latch (MS), read/write, dlab = 1 +#define CYG_DEV_SERIAL_IIR 0x10 // interrupt identification register, read, dlab = 0 +#define CYG_DEV_SERIAL_FCR 0x10 // fifo control register, write, dlab = 0 +#define CYG_DEV_SERIAL_AFR 0x10 // alternate function register, read/write, dlab = 1 +#define CYG_DEV_SERIAL_LCR 0x18 // line control register, read/write +#define CYG_DEV_SERIAL_MCR 0x20 +#define CYG_DEV_SERIAL_MCR_A 0x20 +#define CYG_DEV_SERIAL_MCR_B 0x20 +#define CYG_DEV_SERIAL_LSR 0x28 // line status register, read +#define CYG_DEV_SERIAL_MSR 0x30 // modem status register, read +#define CYG_DEV_SERIAL_SCR 0x38 // scratch pad register + +// The interrupt enable register bits. +#define SIO_IER_ERDAI 0x01 // enable received data available irq +#define SIO_IER_ETHREI 0x02 // enable THR empty interrupt +#define SIO_IER_ELSI 0x04 // enable receiver line status irq +#define SIO_IER_EMSI 0x08 // enable modem status interrupt + +// The interrupt identification register bits. +#define SIO_IIR_IP 0x01 // 0 if interrupt pending +#define SIO_IIR_ID_MASK 0x0e // mask for interrupt ID bits + +// The line status register bits. +#define SIO_LSR_DR 0x01 // data ready +#define SIO_LSR_OE 0x02 // overrun error +#define SIO_LSR_PE 0x04 // parity error +#define SIO_LSR_FE 0x08 // framing error +#define SIO_LSR_BI 0x10 // break interrupt +#define SIO_LSR_THRE 0x20 // transmitter holding register empty +#define SIO_LSR_TEMT 0x40 // transmitter register empty +#define SIO_LSR_ERR 0x80 // any error condition + +// The modem status register bits. +#define SIO_MSR_DCTS 0x01 // delta clear to send +#define SIO_MSR_DDSR 0x02 // delta data set ready +#define SIO_MSR_TERI 0x04 // trailing edge ring indicator +#define SIO_MSR_DDCD 0x08 // delta data carrier detect +#define SIO_MSR_CTS 0x10 // clear to send +#define SIO_MSR_DSR 0x20 // data set ready +#define SIO_MSR_RI 0x40 // ring indicator +#define SIO_MSR_DCD 0x80 // data carrier detect + +// The line control register bits. +#define SIO_LCR_WLS0 0x01 // word length select bit 0 +#define SIO_LCR_WLS1 0x02 // word length select bit 1 +#define SIO_LCR_STB 0x04 // number of stop bits +#define SIO_LCR_PEN 0x08 // parity enable +#define SIO_LCR_EPS 0x10 // even parity select +#define SIO_LCR_SP 0x20 // stick parity +#define SIO_LCR_SB 0x40 // set break +#define SIO_LCR_DLAB 0x80 // divisor latch access bit + +// The FIFO control register +#define SIO_FCR_FCR0 0x01 // enable xmit and rcvr fifos +#define SIO_FCR_FCR1 0x02 // clear RCVR FIFO +#define SIO_FCR_FCR2 0x04 // clear XMIT FIFO + + +static void +init_serial_channel( cyg_uint8* base ) +{ + cyg_uint8 lcr; + + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_IER, 0); + + // Disable and clear FIFOs (need to enable to clear). + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, + (SIO_FCR_FCR0 | SIO_FCR_FCR1 | SIO_FCR_FCR2)); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, 0); + + // 8-1-no parity. + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1); + + // Set speed to 38400. + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + lcr |= SIO_LCR_DLAB; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + + + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLL, + CYG_DEV_SERIAL_RS232_T2_VALUE_B38400); + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLM, + CYG_DEV_SERIAL_RS232_T1_VALUE_B38400); + lcr &= ~SIO_LCR_DLAB; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr); + + { + // Special initialization for ST16C552 on CMA102 + cyg_uint8 mcr; + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_MCR_A, mcr); + mcr |= 8; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_MCR_A, mcr); + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_MCR_B, mcr); + mcr |= 8; + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_MCR_B, mcr); + } + + // Enable FIFOs (and clear them). + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, + (SIO_FCR_FCR0 | SIO_FCR_FCR1 | SIO_FCR_FCR2)); +} + +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8* base = (cyg_uint8*)__ch_data; + cyg_uint8 c, lsr; + CYGARC_HAL_SAVE_GP(); + + do { + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + } while ((lsr & SIO_LSR_DR) == 0); + + HAL_READ_UINT8(base+CYG_DEV_SERIAL_RBR, c); + + CYGARC_HAL_RESTORE_GP(); + return c; +} + +void +cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 c) +{ + cyg_uint8* base = (cyg_uint8*)__ch_data; + cyg_uint8 lsr; + CYGARC_HAL_SAVE_GP(); + + do { + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + } while ((lsr & SIO_LSR_THRE) == 0); + + HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_THR, c); + + // Hang around until the character has been safely sent. + do { + HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr); + } while ((lsr & SIO_LSR_THRE) == 0); + + CYGARC_HAL_RESTORE_GP(); +} + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + // Do nothing (yet). + return 0; +} + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES + +static void +cyg_hal_plf_serial_init(void) +{ + // Disable interrupts. + HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_IRQ1); + + // Init channels + init_serial_channel((cyg_uint8*)CYG_DEV_SERIAL_BASE_A); + init_serial_channel((cyg_uint8*)CYG_DEV_SERIAL_BASE_B); + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + { + // Setup procs in the vector table + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM()(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, CYG_DEV_SERIAL_BASE_A); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); -#define CYG_KERNEL_DIAG_LCD + // Set channel 1 + CYGACC_CALL_IF_SET_CONSOLE_COMM()(1); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, CYG_DEV_SERIAL_BASE_B); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM()(cur); + } #endif +} + +//============================================================================= +// LCD driver +//============================================================================= +// FEMA 162B 16 character x 2 line LCD +// base addresses and register offsets * + +#define MBD_BASE 0 + +#define LCD_BASE (MBD_BASE + 0xEB00007) + +#define LCD_DATA 0x00 // read/write lcd data +#define LCD_STAT 0x08 // read lcd busy status +#define LCD_CMD 0x08 // write lcd command + +// status register bit definitions +#define LCD_STAT_BUSY 0x80 // 1 = display busy +#define LCD_STAT_ADD 0x7F // bits 0-6 return current display address + +// command register definitions +#define LCD_CMD_RST 0x01 // clear entire display and reset display address +#define LCD_CMD_HOME 0x02 // reset display address and reset any shifting +#define LCD_CMD_ECL 0x04 // move cursor left one position on next data write +#define LCD_CMD_ESL 0x05 // shift display left one position on next data write +#define LCD_CMD_ECR 0x06 // move cursor right one position on next data write +#define LCD_CMD_ESR 0x07 // shift display right one position on next data write +#define LCD_CMD_DOFF 0x08 // display off, cursor off, blinking off +#define LCD_CMD_BL 0x09 // blink character at current cursor position +#define LCD_CMD_CUR 0x0A // enable cursor on +#define LCD_CMD_DON 0x0C // turn display on +#define LCD_CMD_CL 0x10 // move cursor left one position +#define LCD_CMD_SL 0x14 // shift display left one position +#define LCD_CMD_CR 0x18 // move cursor right one position +#define LCD_CMD_SR 0x1C // shift display right one position +#define LCD_CMD_MODE 0x38 // sets 8 bits, 2 lines, 5x7 characters +#define LCD_CMD_ACG 0x40 // bits 0-5 sets the character generator address +#define LCD_CMD_ADD 0x80 // bits 0-6 sets the display data address to line 1 + + +// LCD status values +#define LCD_OK 0x00 +#define LCD_ERR 0x01 + +#define LCD_LINE0 0x00 +#define LCD_LINE1 0x40 + +#define LCD_LINE_LENGTH 16 + +static char lcd_line0[LCD_LINE_LENGTH+1]; +static char lcd_line1[LCD_LINE_LENGTH+1]; +static char *lcd_line[2] = { lcd_line0, lcd_line1 }; +static int lcd_curline = 0; +static int lcd_linepos = 0; + + +static void lcd_dis(int add, char *s, cyg_uint8* base); + +static void +init_lcd_channel(cyg_uint8* base) +{ + cyg_uint8 stat; + int i; + + // wait for not busy + // Note: It seems that the LCD isn't quite ready to process commands + // when it clears the BUSY flag. Reading the status address an extra + // time seems to give it enough breathing room. + do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + HAL_READ_UINT8(base+LCD_STAT, stat); + + // configure the lcd for 8 bits/char, 2 lines + // and 5x7 dot matrix + HAL_WRITE_UINT8(base+LCD_CMD, LCD_CMD_MODE); + + // wait for not busy + do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + HAL_READ_UINT8(base+LCD_STAT, stat); + + // turn the LCD display on + HAL_WRITE_UINT8(base+LCD_CMD, LCD_CMD_DON); + + lcd_curline = 0; + lcd_linepos = 0; + + for( i = 0; i < LCD_LINE_LENGTH; i++ ) + lcd_line[0][i] = lcd_line[1][i] = ' '; + + lcd_line[0][LCD_LINE_LENGTH] = lcd_line[1][LCD_LINE_LENGTH] = 0; + + lcd_dis(LCD_LINE0, lcd_line[0], base); + lcd_dis(LCD_LINE1, lcd_line[1], base); +} + +// this routine writes the string to the LCD +// display after setting the address to add +static void +lcd_dis(int add, char *s, cyg_uint8* base) +{ + cyg_uint8 stat; + int i; + + // wait for not busy (see Note in hal_diag_init above) + do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + HAL_READ_UINT8(base+LCD_STAT, stat); + + // write the address + HAL_WRITE_UINT8(base+LCD_CMD, (LCD_CMD_ADD + add)); + + // write the string out to the display stopping when we reach 0 + for (i = 0; *s != '\0'; i++) + { + // wait for not busy + do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + HAL_READ_UINT8(base+LCD_STAT, stat); + + // write the data + HAL_WRITE_UINT8(base+LCD_DATA, *s++); + } +} + +void +cyg_hal_plf_lcd_putc(void* __ch_data, cyg_uint8 c) +{ + cyg_uint8* base = (cyg_uint8*)__ch_data; + unsigned long __state; + int i; + CYGARC_HAL_SAVE_GP(); + + // ignore CR + if( c == '\r' ) return; + + HAL_DISABLE_INTERRUPTS(__state); + if( c == '\n' ) + { + lcd_dis(LCD_LINE0, &lcd_line[lcd_curline^1][0], base); + lcd_dis(LCD_LINE1, &lcd_line[lcd_curline][0], base); + + // Do a line feed + lcd_curline ^= 1; + lcd_linepos = 0; + + for( i = 0; i < LCD_LINE_LENGTH; i++ ) + lcd_line[lcd_curline][i] = ' '; + + HAL_RESTORE_INTERRUPTS(__state); + return; + } + + // Only allow to be output if there is room on the LCD line + if( lcd_linepos < LCD_LINE_LENGTH ) + lcd_line[lcd_curline][lcd_linepos++] = c; + + HAL_RESTORE_INTERRUPTS(__state); +} + +cyg_uint8 +cyg_hal_plf_lcd_getc(void* __ch_data) +{ + return 0; +} + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + +static void +cyg_hal_plf_lcd_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_lcd_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_lcd_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_lcd_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +static int +cyg_hal_plf_lcd_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + // Do nothing (yet). + return 0; +} + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES + +static void +cyg_hal_plf_lcd_init(void) +{ + // Init channel + init_lcd_channel((cyg_uint8*)LCD_BASE); + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + { + // Setup procs in the vector table + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Set channel 2 + CYGACC_CALL_IF_SET_CONSOLE_COMM()(2); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, LCD_BASE); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_lcd_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_lcd_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_lcd_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_lcd_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_lcd_control); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM()(cur); + } +#endif +} + +//============================================================================= +// Compatibility with older stubs +//============================================================================= + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + +//----------------------------------------------------------------------------- // Assumption: all diagnostic output must be GDB packetized unless // this is a configuration for a stand-alone ROM system. #if defined(CYG_HAL_STARTUP_ROM) && !defined(CYGSEM_HAL_ROM_MONITOR) # define HAL_DIAG_USES_HARDWARE #endif - -//----------------------------------------------------------------------------- -// Serial diag functions. -#ifdef CYG_KERNEL_DIAG_SERIAL - -// Include the serial driver. -#define CYG_CMA_PORT CYGHWR_HAL_POWERPC_COGENT_DIAG_PORT -#include +#if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0) +# define __BASE ((cyg_uint8*)CYG_DEV_SERIAL_BASE_A) +#elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 1) +# define __BASE ((cyg_uint8*)CYG_DEV_SERIAL_BASE_B) +#else +# error "Cannot use LCD" +#endif #ifdef HAL_DIAG_USES_HARDWARE void hal_diag_init(void) { - hal_cma_init_serial(); + cyg_hal_plf_comms_init(); } void hal_diag_write_char(char __c) { - hal_cma_put_char(__c); + cyg_hal_plf_serial_putc(__BASE, __c); } void hal_diag_read_char(char *c) { - *c = (char) hal_cma_get_char(); + *c = cyg_hal_plf_serial_getc(__BASE); } #else // ifdef HAL_DIAG_USES_HARDWARE // Initialize diag port -void hal_diag_init(void) +void +hal_diag_init(void) { -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - // assume GDB channel is already set up. - if (0) hal_cma_init_serial(); // avoids compiler warning -#else - hal_cma_init_serial(); -#endif - + // Init devices + cyg_hal_plf_comms_init(); } void @@ -128,14 +603,14 @@ hal_diag_write_char_serial( char c ) { unsigned long __state; HAL_DISABLE_INTERRUPTS(__state); - hal_cma_put_char(c); + cyg_hal_plf_serial_putc(__BASE, c); HAL_RESTORE_INTERRUPTS(__state); } void hal_diag_read_char(char *c) { - *c = (char) hal_cma_get_char(); + *c = cyg_hal_plf_serial_getc(__BASE); } void @@ -219,266 +694,11 @@ hal_diag_write_char(char c) } } -#endif // ifdef HAL_DIAG_USES_HARDWARE - -#endif // ifdef CYG_KERNEL_DIAG_SERIAL - -//----------------------------------------------------------------------------- -// Cogent board specific LCD code - -#if defined(CYG_KERNEL_DIAG_LCD) - -// FEMA 162B 16 character x 2 line LCD -// base addresses and register offsets * - -#define MBD_BASE 0 - -#define LCD_BASE (MBD_BASE + 0xEB00007) - -#define LCD_DATA (LCD_BASE + 0x00) // read/write lcd data -#define LCD_STAT (LCD_BASE + 0x08) // read lcd busy status -#define LCD_CMD (LCD_BASE + 0x08) // write lcd command - -// status register bit definitions -#define LCD_STAT_BUSY 0x80 // 1 = display busy -#define LCD_STAT_ADD 0x7F // bits 0-6 return current display address - -// command register definitions -#define LCD_CMD_RST 0x01 // clear entire display and reset display address -#define LCD_CMD_HOME 0x02 // reset display address and reset any shifting -#define LCD_CMD_ECL 0x04 // move cursor left one position on next data write -#define LCD_CMD_ESL 0x05 // shift display left one position on next data write -#define LCD_CMD_ECR 0x06 // move cursor right one position on next data write -#define LCD_CMD_ESR 0x07 // shift display right one position on next data write -#define LCD_CMD_DOFF 0x08 // display off, cursor off, blinking off -#define LCD_CMD_BL 0x09 // blink character at current cursor position -#define LCD_CMD_CUR 0x0A // enable cursor on -#define LCD_CMD_DON 0x0C // turn display on -#define LCD_CMD_CL 0x10 // move cursor left one position -#define LCD_CMD_SL 0x14 // shift display left one position -#define LCD_CMD_CR 0x18 // move cursor right one position -#define LCD_CMD_SR 0x1C // shift display right one position -#define LCD_CMD_MODE 0x38 // sets 8 bits, 2 lines, 5x7 characters -#define LCD_CMD_ACG 0x40 // bits 0-5 sets the character generator address -#define LCD_CMD_ADD 0x80 // bits 0-6 sets the display data address to line 1 + - -// LCD status values -#define LCD_OK 0x00 -#define LCD_ERR 0x01 - -#define LCD_LINE0 0x00 -#define LCD_LINE1 0x40 - -#define LCD_LINE_LENGTH 16 - -static char lcd_line0[LCD_LINE_LENGTH+1]; -static char lcd_line1[LCD_LINE_LENGTH+1]; -static char *lcd_line[2] = { lcd_line0, lcd_line1 }; -static int lcd_curline = 0; -static int lcd_linepos = 0; - - -static void lcd_dis(int add, char *string); - -externC void diag_write_string (const char*); - -void hal_diag_init() -{ - cyg_uint8 stat; - int i; - - // wait for not busy - // Note: It seems that the LCD isn't quite ready to process commands - // when it clears the BUSY flag. Reading the status address an extra - // time seems to give it enough breathing room. - do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); - HAL_READ_UINT8 (LCD_STAT, stat); - - // configure the lcd for 8 bits/char, 2 lines - // and 5x7 dot matrix - HAL_WRITE_UINT8 (LCD_CMD, LCD_CMD_MODE); - - // wait for not busy - do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); - HAL_READ_UINT8 (LCD_STAT, stat); - - // turn the LCD display on - HAL_WRITE_UINT8 (LCD_CMD, LCD_CMD_DON); - - lcd_curline = 0; - lcd_linepos = 0; - - for( i = 0; i < LCD_LINE_LENGTH; i++ ) - lcd_line[0][i] = lcd_line[1][i] = ' '; - - lcd_line[0][LCD_LINE_LENGTH] = lcd_line[1][LCD_LINE_LENGTH] = 0; - - lcd_dis( LCD_LINE0, lcd_line[0] ); - lcd_dis( LCD_LINE1, lcd_line[1] ); - - -#ifdef CYGSEM_HAL_ROM_MONITOR - // It's handy to have the LCD initialized at reset when using it - // for debugging output. - { - diag_write_string ("eCos ROM " __TIME__ "\n"); - diag_write_string (__DATE__ "\n"); - } -#endif -} - -// this routine writes the string to the LCD -// display after setting the address to add -static void lcd_dis(int add, char *string) -{ - cyg_uint8 stat; - int i; - - // wait for not busy (see Note in hal_diag_init above) - do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); - HAL_READ_UINT8 (LCD_STAT, stat); - - // write the address - HAL_WRITE_UINT8 (LCD_CMD, (LCD_CMD_ADD + add)); - - // write the string out to the display stopping when we reach 0 - for (i = 0; *string != '\0'; i++) - { - // wait for not busy - do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); - HAL_READ_UINT8 (LCD_STAT, stat); +#endif // ifdef HAL_DIAG_USES_HARDWARE - // write the data - HAL_WRITE_UINT8 (LCD_DATA, *string++); - } -} - -void hal_diag_write_char(char c) -{ - unsigned long __state; - int i; - - // ignore CR - if( c == '\r' ) return; - - HAL_DISABLE_INTERRUPTS(__state); - if( c == '\n' ) - { - lcd_dis( LCD_LINE0, &lcd_line[lcd_curline^1][0] ); - lcd_dis( LCD_LINE1, &lcd_line[lcd_curline][0] ); - - // Do a line feed - lcd_curline ^= 1; - lcd_linepos = 0; - - for( i = 0; i < LCD_LINE_LENGTH; i++ ) - lcd_line[lcd_curline][i] = ' '; - - HAL_RESTORE_INTERRUPTS(__state); - return; - } - - // Only allow to be output if there is room on the LCD line - if( lcd_linepos < LCD_LINE_LENGTH ) - lcd_line[lcd_curline][lcd_linepos++] = c; - - HAL_RESTORE_INTERRUPTS(__state); -} - -void hal_diag_read_char(char* c) {} - -#endif - - -//---------------------------------------------------------------------------*/ -// PromICE AI interface - - -#if defined(CYG_KERNEL_DIAG_ROMART) - -#ifdef CYGPKG_HAL_POWERPC_COGENT -#define PROMICE_AILOC 0xfff00020 -#endif - -// Add this to the LoadICE config file: ailoc 20 19200 -// Note: I couldn't get this to work. jskov - -#define PROMICE_BUS_SIZE 16 -#define PROMICE_BURST_SIZE 1 - -#if PROMICE_BUS_SIZE == 16 +#undef __BASE -typedef volatile struct -{ - volatile cyg_uint16 zero; -// cyg_uint16 pad1[PROMICE_BURST_SIZE]; - volatile cyg_uint16 one; -// cyg_uint16 pad2[PROMICE_BURST_SIZE]; - volatile cyg_uint16 data; -// cyg_uint16 pad3[PROMICE_BURST_SIZE]; - volatile cyg_uint16 status; - -} AISTRUCT; - -#endif - -AISTRUCT *AI = (AISTRUCT *)PROMICE_AILOC; - -#define PROMICE_STATUS_TDA 0x01 -#define PROMICE_STATUS_HDA 0x02 -#define PROMICE_STATUS_OVR 0x04 - -void hal_diag_init() -{ - volatile cyg_uint8 junk; - - while( AI->status == 0xCC ) - continue; - - junk = AI->data; -} - -static void ai_write_char(cyg_uint8 data) -{ - volatile cyg_uint8 junk; - int i; - unsigned long __state; - - HAL_DISABLE_INTERRUPTS(__state); - - // Wait for tda == 0 - while( (AI->status & PROMICE_STATUS_TDA) == PROMICE_STATUS_TDA ) - continue; - - // Send start bit - junk = AI->one; - - for( i = 0; i < 8; i++ ) - { - // send ls bit of data - if( (data & 1) == 1 ) - junk = AI->one; - else - junk = AI->zero; - - // shift down for next bit - data >>= 1; - } - - // Send stop bit - junk = AI->one; - - HAL_RESTORE_INTERRUPTS(__state); - - // all done -} - -void hal_diag_write_char(char c) -{ - ai_write_char((cyg_uint8)c); -} - -#endif +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG //----------------------------------------------------------------------------- // End of hal_diag.c diff --git a/packages/hal/powerpc/cogent/current/src/plf_misc.c b/packages/hal/powerpc/cogent/current/src/plf_misc.c new file mode 100644 --- /dev/null +++ b/packages/hal/powerpc/cogent/current/src/plf_misc.c @@ -0,0 +1,168 @@ +//============================================================================= +// +// plf_misc.c +// +// Platform miscellaneous code/data. +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors:hmt +// Date: 1999-06-08 +// Purpose: Platform specific code and data +// Description: Tables for per-platform initialization +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include // HAL memory definitions +#include // hal_if_init + +#include // IO macros +#include // interrupt vectors +#include // Helper functions +#include // HANDLED + +// The memory map is weakly defined, allowing the application to redefine +// it if necessary. The regions defined below are the minimum requirements. +CYGARC_MEMDESC_TABLE CYGBLD_ATTRIB_WEAK = { + // Mapping for the Cogent CMA101/102 boards. + CYGARC_MEMDESC_NOCACHE( 0xfff00000, 0x00100000 ), // ROM region + CYGARC_MEMDESC_NOCACHE( 0xff000000, 0x00100000 ), // MCP registers + CYGARC_MEMDESC_NOCACHE( 0x0e000000, 0x01000000 ), // IO registers + CYGARC_MEMDESC_CACHE( 0x00000000, 0x00800000 ), // Main memory + + CYGARC_MEMDESC_TABLE_END +}; + +void +hal_platform_init(void) +{ + hal_if_init(); +} + + +//-------------------------------------------------------------------------- +// Control C ISR support + +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + +#if (1 == CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) +#define CYG_DEVICE_SERIAL_RS232_16550_BASE CYG_DEVICE_SERIAL_RS232_16550_BASE_B +#else +#define CYG_DEVICE_SERIAL_RS232_16550_BASE CYG_DEVICE_SERIAL_RS232_16550_BASE_A +#endif + +//----------------------------------------------------------------------------- +// There are two serial ports. +#define CYG_DEVICE_SERIAL_RS232_16550_BASE_A 0xe900047 // port A +#define CYG_DEVICE_SERIAL_RS232_16550_BASE_B 0xe900007 // port B + +// receiver buffer register, read, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_RBR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x00) +// interrupt enable register, read/write, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_IER \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x08) +// interrupt identification register, read, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_IIR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x10) +// line status register, read +#define CYG_DEVICE_SERIAL_RS232_16550_LSR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x28) + + +// The interrupt enable register bits. +#define SIO_IER_ERDAI 0x01 // enable received data available irq +#define SIO_IER_ETHREI 0x02 // enable THR empty interrupt +#define SIO_IER_ELSI 0x04 // enable receiver line status irq +#define SIO_IER_EMSI 0x08 // enable modem status interrupt + +// The interrupt identification register bits. +#define SIO_IIR_IP 0x01 // 0 if interrupt pending +#define SIO_IIR_ID_MASK 0x0e // mask for interrupt ID bits +#define ISR_Tx 0x02 +#define ISR_Rx 0x04 + +// The line status register bits. +#define SIO_LSR_DR 0x01 // data ready +#define SIO_LSR_OE 0x02 // overrun error +#define SIO_LSR_PE 0x04 // parity error +#define SIO_LSR_FE 0x08 // framing error +#define SIO_LSR_BI 0x10 // break interrupt +#define SIO_LSR_THRE 0x20 // transmitter holding register empty +#define SIO_LSR_TEMT 0x40 // transmitter register empty +#define SIO_LSR_ERR 0x80 // any error condition + +struct Hal_SavedRegisters *hal_saved_interrupt_state; + +void hal_ctrlc_isr_init(void) +{ + // Enable serial receive interrupts. + HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_IER, SIO_IER_ERDAI); + + HAL_INTERRUPT_SET_LEVEL(CYGHWR_HAL_GDB_PORT_VECTOR, 1); + HAL_INTERRUPT_UNMASK(CYGHWR_HAL_GDB_PORT_VECTOR); +} + +cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + cyg_uint8 _iir; + + + HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_IIR, _iir); + _iir &= SIO_IIR_ID_MASK; + + if ( ISR_Rx == _iir ) { + + cyg_uint8 c, lsr; + + HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LSR, lsr); + if (lsr & SIO_LSR_DR) { + + HAL_READ_UINT8( CYG_DEVICE_SERIAL_RS232_16550_RBR, c ); + + if( cyg_hal_is_break( &c , 1 ) ) + cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); + } + + // Acknowledge the interrupt + HAL_INTERRUPT_ACKNOWLEDGE(CYGHWR_HAL_GDB_PORT_VECTOR); + + return CYG_ISR_HANDLED; + } + + return 0; +} + +#endif + +// EOF plf_misc.c diff --git a/packages/hal/powerpc/cogent/current/src/plf_stub.c b/packages/hal/powerpc/cogent/current/src/plf_stub.c --- a/packages/hal/powerpc/cogent/current/src/plf_stub.c +++ b/packages/hal/powerpc/cogent/current/src/plf_stub.c @@ -42,18 +42,29 @@ #include -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include +#include -#include +#define L1 "eCos ROM " __TIME__ "\n" +#define L2 __DATE__ "\n" -//---------------------------------------------------------------------------- -// Include the serial driver. -#define CYG_CMA_STUB -#define CYG_CMA_PUBLIC -#define CYG_CMA_PORT CYGHWR_HAL_POWERPC_COGENT_GDB_PORT -#define CYG_CMA_NAME_PREFIX hal_cma_stub_ -#include +void +hal_plf_stub_init(void) +{ +#if defined(CYGSEM_HAL_ROM_MONITOR) && defined(CYGSEM_HAL_VIRTUAL_VECTOR) + // Put stub build date on the LCD. + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); -#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + CYGACC_CALL_IF_SET_CONSOLE_COMM()(2); + + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_WRITE(*comm)(CYGACC_COMM_IF_CH_DATA(*comm), L1, strlen(L1)); + CYGACC_COMM_IF_WRITE(*comm)(CYGACC_COMM_IF_CH_DATA(*comm), L2, strlen(L2)); + + CYGACC_CALL_IF_SET_CONSOLE_COMM()(cur); +#endif +} + //----------------------------------------------------------------------------- // End of plf_stub.c diff --git a/packages/hal/powerpc/mbx/current/ChangeLog b/packages/hal/powerpc/mbx/current/ChangeLog --- a/packages/hal/powerpc/mbx/current/ChangeLog +++ b/packages/hal/powerpc/mbx/current/ChangeLog @@ -1,3 +1,18 @@ +2000-06-22 John Dallaway + + * include/pkgconf/mlt_powerpc_mbx_rom.mlt: + + Synchronize with mlt_powerpc_mbx_rom.ldi. + +2000-06-21 Jesper Skov + + * src/hal_diag.c: Provide comms_init function, initializing the + serial device. Changed quicc calls to provide eppc_base. + + * include/plf_stub.h: + * include/hal_diag.h: + Changed defines to match new procs table handling of IO. + 2000-06-15 Jesper Skov * include/pkgconf/mlt_powerpc_mbx_rom.h: diff --git a/packages/hal/powerpc/mbx/current/include/hal_diag.h b/packages/hal/powerpc/mbx/current/include/hal_diag.h --- a/packages/hal/powerpc/mbx/current/include/hal_diag.h +++ b/packages/hal/powerpc/mbx/current/include/hal_diag.h @@ -69,6 +69,10 @@ #include +externC void cyg_hal_plf_serial_init(void); +externC void cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 __ch); +externC cyg_uint8 cyg_hal_plf_serial_getc(void* __ch_data); + #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) #include @@ -77,12 +81,6 @@ #define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) #define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) -#ifndef CYGPRI_CONSOLE_PROCS_HANDLED -# define HAL_PLF_DIAG_RAW_INIT() cyg_quicc_init_smc1() -# define HAL_PLF_DIAG_RAW_WRITE_CHAR(_c_) cyg_quicc_smc1_uart_putchar(_c_) -# define HAL_PLF_DIAG_RAW_READ_CHAR(_c_) (_c_) = cyg_quicc_smc1_uart_rcvchar() -#endif - #else // everything by steam //----------------------------------------------------------------------------- diff --git a/packages/hal/powerpc/mbx/current/include/pkgconf/mlt_powerpc_mbx_rom.mlt b/packages/hal/powerpc/mbx/current/include/pkgconf/mlt_powerpc_mbx_rom.mlt --- a/packages/hal/powerpc/mbx/current/include/pkgconf/mlt_powerpc_mbx_rom.mlt +++ b/packages/hal/powerpc/mbx/current/include/pkgconf/mlt_powerpc_mbx_rom.mlt @@ -2,9 +2,9 @@ version 0 region ram 0 400000 0 ! region rom fe000000 800000 1 ! section reserved_vectors 3000 1 0 0 1 1 1 1 0 0 reserved_vsr_table reserved_vsr_table ! -section reserved_vsr_table 200 4 0 0 0 1 0 1 reserved_virtual_table reserved_virtual_table ! -section reserved_virtual_table 100 4 0 0 0 1 0 1 data data ! -section data 0 10 0 1 0 1 0 1 sbss sbss ! +section reserved_vsr_table 200 1 0 0 0 1 0 1 reserved_virtual_table reserved_virtual_table ! +section reserved_virtual_table 100 1 0 0 0 1 0 0 data ! +section data 0 10 1 1 0 1 0 0 sbss ! section sbss 0 4 0 1 0 1 0 1 bss bss ! section bss 0 10 0 1 0 0 0 0 ! section vectors 0 1 0 1 1 1 1 1 fe000000 fe000000 text text ! diff --git a/packages/hal/powerpc/mbx/current/include/plf_stub.h b/packages/hal/powerpc/mbx/current/include/plf_stub.h --- a/packages/hal/powerpc/mbx/current/include/plf_stub.h +++ b/packages/hal/powerpc/mbx/current/include/plf_stub.h @@ -54,13 +54,13 @@ #include // architecture stub support //---------------------------------------------------------------------------- -// Define serial stuff. All comes from the quicc_smc1.c file. - -#include +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. -#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_quicc_init_smc1() -#define HAL_STUB_PLATFORM_GET_CHAR() cyg_quicc_smc1_uart_rcvchar() -#define HAL_STUB_PLATFORM_PUT_CHAR(c) cyg_quicc_smc1_uart_putchar((c)) +externC void cyg_hal_plf_comms_init(void); + +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() #define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) #define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT diff --git a/packages/hal/powerpc/mbx/current/src/hal_diag.c b/packages/hal/powerpc/mbx/current/src/hal_diag.c --- a/packages/hal/powerpc/mbx/current/src/hal_diag.c +++ b/packages/hal/powerpc/mbx/current/src/hal_diag.c @@ -58,6 +58,20 @@ #include #include + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + initialized = 1; + + cyg_hal_plf_serial_init(); +} + + #if !defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) //----------------------------------------------------------------------------- @@ -108,17 +122,23 @@ dump_diag_buf(int start, int len) #if defined(CYG_KERNEL_DIAG_SERIAL) +EPPC *eppc; + void hal_diag_init(void) { static int init = 0; if (init) return; init++; + + // hardwired base + eppc = eppc_base(); + // init the actual serial port - cyg_quicc_init_smc1(); + cyg_hal_plf_serial_init(); #ifndef CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL #ifndef CYG_HAL_STARTUP_ROM // We are talking to GDB; ack the "go" packet! - cyg_quicc_smc1_uart_putchar('+'); + cyg_hal_plf_serial_putc(eppc, '+'); #endif #endif } @@ -127,7 +147,7 @@ void hal_diag_write_char_serial( char c { unsigned long __state; HAL_DISABLE_INTERRUPTS(__state); - cyg_quicc_smc1_uart_putchar(c); + cyg_hal_plf_serial_putc(eppc, c); HAL_RESTORE_INTERRUPTS(__state); } @@ -203,7 +223,7 @@ void hal_diag_write_char(char c) // Wait for the ACK character '+' from GDB here and handle // receiving a ^C instead. This is the reason for this clause // being a loop. - c = cyg_quicc_smc1_uart_rcvchar(); + c = cyg_hal_plf_serial_getc(eppc); if( c == '+' ) break; // a good acknowledge @@ -236,7 +256,7 @@ void hal_diag_write_char(char c) void hal_diag_read_char(char *c) { - *c = cyg_quicc_smc1_uart_rcvchar(); + *c = cyg_hal_plf_serial_getc(eppc); } #endif // CYG_KERNEL_DIAG_SERIAL diff --git a/packages/hal/powerpc/mpc8xx/current/ChangeLog b/packages/hal/powerpc/mpc8xx/current/ChangeLog --- a/packages/hal/powerpc/mpc8xx/current/ChangeLog +++ b/packages/hal/powerpc/mpc8xx/current/ChangeLog @@ -1,3 +1,14 @@ +2000-06-19 Jesper Skov + + * include/var_regs.h: + * include/variant.inc: + * src/var_misc.c: + Make caches default to off when the MMU is disabled. + +2000-06-16 Jesper Skov + + * src/var_intr.c (hal_call_isr): Use driver API definitions. + 2000-06-14 Jesper Skov * cdl/hal_powerpc_mpc8xx.cdl: Proper ROM_MONITOR hack. diff --git a/packages/hal/powerpc/mpc8xx/current/include/var_regs.h b/packages/hal/powerpc/mpc8xx/current/include/var_regs.h --- a/packages/hal/powerpc/mpc8xx/current/include/var_regs.h +++ b/packages/hal/powerpc/mpc8xx/current/include/var_regs.h @@ -167,8 +167,16 @@ #define MD_DRAM1 826 // data MMU RAM read 1 #define MD_RPN_CHANGED 0x00000100 // page changed + #endif // ifdef CYGARC_HAL_COMMON_EXPORT_CPU_MACROS +#define CYGARC_REG_MI_CTR 784 +#define CYGARC_REG_MI_CTR_CIDEF 0x20000000 + +#define CYGARC_REG_MD_CTR 792 +#define CYGARC_REG_MD_CTR_CIDEF 0x20000000 +#define CYGARC_REG_MD_CTR_WTDEF 0x10000000 + //-------------------------------------------------------------------------- // Internal Memory Map. #define CYGARC_REG_IMMR 638 // internal memory map base register diff --git a/packages/hal/powerpc/mpc8xx/current/include/variant.inc b/packages/hal/powerpc/mpc8xx/current/include/variant.inc --- a/packages/hal/powerpc/mpc8xx/current/include/variant.inc +++ b/packages/hal/powerpc/mpc8xx/current/include/variant.inc @@ -99,6 +99,14 @@ mtspr CYGARC_REG_IC_CST,r3 isync + # Default caching to off when MMU is disabled + mfspr r3,CYGARC_REG_MI_CTR + oris r3,r3,(CYGARC_REG_MI_CTR_CIDEF)@h + mtspr CYGARC_REG_MI_CTR,r3 + mfspr r3,CYGARC_REG_MD_CTR + oris r3,r3,(CYGARC_REG_MD_CTR_CIDEF)@h + mtspr CYGARC_REG_MD_CTR,r3 + # Set up MSR (disable MMU for now) lwi r3,(CYG_MSR & ~(MSR_IR | MSR_DR)) sync diff --git a/packages/hal/powerpc/mpc8xx/current/src/var_intr.c b/packages/hal/powerpc/mpc8xx/current/src/var_intr.c --- a/packages/hal/powerpc/mpc8xx/current/src/var_intr.c +++ b/packages/hal/powerpc/mpc8xx/current/src/var_intr.c @@ -46,11 +46,7 @@ #include #include // hal_interrupt_x tables - -// These are the Cyg_Interrupt::HANDLED/CALL_DSR values. -#define Cyg_InterruptHANDLED 1 -#define Cyg_InterruptCALL_DSR 2 - +#include // CYG_ISR_HANDLED typedef cyg_uint32 cyg_ISR(cyg_uint32 vector, CYG_ADDRWORD data); @@ -69,12 +65,12 @@ hal_call_isr (cyg_uint32 vector) isr_ret = (*isr) (vector, data); #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT - if (isr_ret & Cyg_InterruptCALL_DSR) { + if (isr_ret & CYG_ISR_CALL_DSR) { cyg_interrupt_post_dsr (hal_interrupt_objects[vector]); } #endif - return isr_ret & ~Cyg_InterruptCALL_DSR; + return isr_ret & ~CYG_ISR_CALL_DSR; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -107,8 +103,7 @@ hal_arbitration_isr_tb (CYG_ADDRWORD vec if (tbscr & CYGARC_REG_IMM_TBSCR_REFA) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_TB_A); - CYG_ASSERT (isr_ret & Cyg_InterruptHANDLED, - "Interrupt not handled"); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); #ifndef CYGSEM_HAL_COMMON_INTERRUPTS_CHECK_ALL_SOURCES return isr_ret; @@ -118,8 +113,7 @@ hal_arbitration_isr_tb (CYG_ADDRWORD vec if (tbscr & CYGARC_REG_IMM_TBSCR_REFB) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_TB_B); - CYG_ASSERT (isr_ret & Cyg_InterruptHANDLED, - "Interrupt not handled"); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); #ifndef CYGSEM_HAL_COMMON_INTERRUPTS_CHECK_ALL_SOURCES return isr_ret; @@ -143,8 +137,7 @@ hal_arbitration_isr_pit (CYG_ADDRWORD ve if (piscr & CYGARC_REG_IMM_PISCR_PS) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_PIT); - CYG_ASSERT (isr_ret & Cyg_InterruptHANDLED, - "Interrupt not handled"); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); #ifndef CYGSEM_HAL_COMMON_INTERRUPTS_CHECK_ALL_SOURCES return isr_ret; @@ -170,8 +163,7 @@ hal_arbitration_isr_rtc (CYG_ADDRWORD ve if (rtcsc & CYGARC_REG_IMM_RTCSC_SEC) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_RTC_SEC); - CYG_ASSERT (isr_ret & Cyg_InterruptHANDLED, - "Interrupt not handled"); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); #ifndef CYGSEM_HAL_COMMON_INTERRUPTS_CHECK_ALL_SOURCES return isr_ret; @@ -181,8 +173,7 @@ hal_arbitration_isr_rtc (CYG_ADDRWORD ve if (rtcsc & CYGARC_REG_IMM_RTCSC_ALR) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_RTC_ALR); - CYG_ASSERT (isr_ret & Cyg_InterruptHANDLED, - "Interrupt not handled"); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); #ifndef CYGSEM_HAL_COMMON_INTERRUPTS_CHECK_ALL_SOURCES return isr_ret; @@ -206,8 +197,7 @@ hal_arbitration_isr_cpm (CYG_ADDRWORD ve if (civr) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_CPM_LAST - civr); - CYG_ASSERT (isr_ret & Cyg_InterruptHANDLED, - "Interrupt not handled"); + CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled"); #ifndef CYGSEM_HAL_COMMON_INTERRUPTS_CHECK_ALL_SOURCES return isr_ret; diff --git a/packages/hal/powerpc/mpc8xx/current/src/var_misc.c b/packages/hal/powerpc/mpc8xx/current/src/var_misc.c --- a/packages/hal/powerpc/mpc8xx/current/src/var_misc.c +++ b/packages/hal/powerpc/mpc8xx/current/src/var_misc.c @@ -96,7 +96,7 @@ int cyg_hal_map_memory (int id,CYG_ADDRESS virt, CYG_ADDRESS phys, cyg_int32 size, cyg_uint8 flags) { - cyg_uint32 epn, rpn, ctr, twc; + cyg_uint32 epn, rpn, twc, ctr = 0; int max_tlbs; #if defined(CYGPKG_HAL_POWERPC_MPC860) @@ -148,6 +148,10 @@ cyg_hal_map_memory (int id,CYG_ADDRESS v id++; } + // Make caches default disabled when MMU is disabled. + CYGARC_MTSPR (MI_CTR, ctr | CYGARC_REG_MI_CTR_CIDEF); + CYGARC_MTSPR (MD_CTR, ctr | CYGARC_REG_MD_CTR_CIDEF); + return id; } @@ -158,7 +162,7 @@ cyg_hal_map_memory (int id,CYG_ADDRESS v void cyg_hal_clear_MMU (void) { - cyg_uint32 ctr; + cyg_uint32 ctr = 0; int id; int max_tlbs; @@ -174,7 +178,7 @@ cyg_hal_clear_MMU (void) for (id = 0; id < max_tlbs; id++) { ctr = id << MI_CTR_INDX_SHIFT; - + // Instruction TLBs. CYGARC_MTSPR (MI_TWC, 0); CYGARC_MTSPR (MI_CTR, ctr); @@ -186,6 +190,10 @@ cyg_hal_clear_MMU (void) CYGARC_MTSPR (MD_EPN, 0); CYGARC_MTSPR (MD_RPN, 0); } + + // Make caches default disabled when MMU is disabled. + CYGARC_MTSPR (MI_CTR, ctr | CYGARC_REG_MI_CTR_CIDEF); + CYGARC_MTSPR (MD_CTR, ctr | CYGARC_REG_MD_CTR_CIDEF); } //-------------------------------------------------------------------------- diff --git a/packages/hal/powerpc/quicc/current/ChangeLog b/packages/hal/powerpc/quicc/current/ChangeLog --- a/packages/hal/powerpc/quicc/current/ChangeLog +++ b/packages/hal/powerpc/quicc/current/ChangeLog @@ -1,3 +1,15 @@ +2000-06-21 Jesper Skov + + * src/quicc_smc1.c: + * include/quicc_smc1.h: + Allow callers to specify base. Added code to initialize vector + procs table. + +2000-06-16 Jesper Skov + + * src/quicc_smc1.c (hal_ctrlc_isr): Check that interrupt is + generated by serial controller. + 2000-06-13 Jesper Skov * src/quicc_smc1.c: diff --git a/packages/hal/powerpc/quicc/current/include/quicc_smc1.h b/packages/hal/powerpc/quicc/current/include/quicc_smc1.h --- a/packages/hal/powerpc/quicc/current/include/quicc_smc1.h +++ b/packages/hal/powerpc/quicc/current/include/quicc_smc1.h @@ -45,9 +45,12 @@ // //============================================================================= -extern void cyg_quicc_smc1_uart_putchar(char ch); -extern int cyg_quicc_smc1_uart_rcvchar(void); -extern void cyg_quicc_init_smc1(void); +#include +#include // FIXME: bad, but need eppc_base + +externC void cyg_hal_plf_serial_init(void); +externC void cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 __ch); +externC cyg_uint8 cyg_hal_plf_serial_getc(void* __ch_data); //-------------------------------------------------------------------------- // Control-C support. diff --git a/packages/hal/powerpc/quicc/current/src/quicc_smc1.c b/packages/hal/powerpc/quicc/current/src/quicc_smc1.c --- a/packages/hal/powerpc/quicc/current/src/quicc_smc1.c +++ b/packages/hal/powerpc/quicc/current/src/quicc_smc1.c @@ -38,7 +38,9 @@ // Description: Serial IO for MBX boards which connect their debug channel // to SMC1; or any QUICC user who wants to use SMC1. // Usage: -// +// Notes: The driver hooks itself up on procs channel 0. This should +// probably be made configurable, allowing the platform +// to specify location. // //####DESCRIPTIONEND#### // @@ -49,6 +51,8 @@ #include #include +#include + #ifdef CYGPKG_HAL_POWERPC_MPC860 // eCos headers decribing PowerQUICC: @@ -74,6 +78,12 @@ #define Rxbuf ((volatile char *)eppc + 0x2810) #define Txbuf ((volatile char *)eppc + 0x2820) +// SMC Events (interrupts) +#define QUICC_SMCE_BRK 0x10 // Break received +#define QUICC_SMCE_BSY 0x04 // Busy - receive buffer overrun +#define QUICC_SMCE_TX 0x02 // Tx interrupt +#define QUICC_SMCE_RX 0x01 // Rx interrupt + /* * Initialize SMC1 as a uart. @@ -207,13 +217,14 @@ init_smc1_uart(void) extern int enable_diag_uart; #endif // CYGDBG_DIAG_BUF -void -cyg_quicc_smc1_uart_putchar(char ch) +void +cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 ch) { volatile struct cp_bufdesc *bd, *first; - EPPC *eppc = eppc_base(); + EPPC *eppc = (EPPC*) __ch_data; volatile struct smc_uart_pram *uart_pram = &eppc->pram[2].scc.pothers.smc_modem.psmc.u; int timeout; + CYGARC_HAL_SAVE_GP(); /* tx buffer descriptor */ bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbptr); @@ -269,19 +280,21 @@ cyg_quicc_smc1_uart_putchar(char ch) while (bd->ctrl & QUICC_BD_CTL_Ready) ; // Wait until buffer free bd->length = 0; #ifdef CYGDBG_DIAG_BUF - enable_diag_uart = 1; + enable_diag_uart = 1; #endif // CYGDBG_DIAG_BUF + + CYGARC_HAL_RESTORE_GP(); } - -int -cyg_quicc_smc1_uart_rcvchar(void) +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) { volatile struct cp_bufdesc *bd; char ch; - EPPC *eppc = eppc_base(); + EPPC *eppc = (EPPC*) __ch_data; volatile struct smc_uart_pram *uart_pram = &eppc->pram[2].scc.pothers.smc_modem.psmc.u; int cache_state; + CYGARC_HAL_SAVE_GP(); /* rx buffer descriptor */ bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbptr); @@ -299,16 +312,47 @@ cyg_quicc_smc1_uart_rcvchar(void) HAL_DCACHE_INVALIDATE(bd->buffer, uart_pram->mrblr); // Make sure no stale data } + CYGARC_HAL_RESTORE_GP(); return ch; } +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + // Do nothing (yet). + return 0; +} + /* * Early initialization of comm channels. Must not rely * on interrupts, yet. Interrupt operation can be enabled * in _bsp_board_init(). */ void -cyg_quicc_init_smc1(void) +cyg_hal_plf_serial_init(void) { volatile EPPC *eppc = eppc_base(); int i; @@ -324,6 +368,28 @@ cyg_quicc_init_smc1(void) for (i = 0; i < 100000; i++); init_smc1_uart(); + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \ + || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES) + { + // Setup procs in the vector table + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM()(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM()(0);// Should be configurable! + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, eppc_base()); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM()(cur); + } +#endif } #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // the below should be removed @@ -385,6 +451,7 @@ hal_ctrlc_isr_init(void) HAL_INTERRUPT_UNMASK(CYGHWR_HAL_GDB_PORT_VECTOR); } + cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { @@ -392,30 +459,30 @@ hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_A struct cp_bufdesc *bd; char ch; - eppc->smc_regs[0].smc_smce = 0xff; + if (eppc->smc_regs[0].smc_smce & QUICC_SMCE_RX) { - /* rx buffer descriptors */ - bd = (struct cp_bufdesc *)((char *)eppc_base() + Rxbd); + eppc->smc_regs[0].smc_smce = QUICC_SMCE_RX; - if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) { + /* rx buffer descriptors */ + bd = (struct cp_bufdesc *)((char *)eppc_base() + Rxbd); - // then there be a character waiting - ch = bd->buffer[0]; - bd->length = 1; - bd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Wrap | QUICC_BD_CTL_Int; - - if( cyg_hal_is_break( &ch , 1 ) ) - cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); + if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) { + + // then there be a character waiting + ch = bd->buffer[0]; + bd->length = 1; + bd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Wrap | QUICC_BD_CTL_Int; + + if( cyg_hal_is_break( &ch , 1 ) ) + cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); + } // Interrupt handled. Acknowledge it. eppc->cpmi_cisr = 0x10; return CYG_ISR_HANDLED; } - eppc->cpmi_cisr = 0x10; // acknowledge the Rx event anyway - // in case it was left over from polled reception - - // Not a serial interrupt + // Not a serial interrupt. return 0; } #endif diff --git a/packages/hal/sh/edk/current/ChangeLog b/packages/hal/sh/edk/current/ChangeLog --- a/packages/hal/sh/edk/current/ChangeLog +++ b/packages/hal/sh/edk/current/ChangeLog @@ -1,3 +1,7 @@ +1999-06-19 John Dallaway + + * cdl/hal_sh_edk7708.cdl: Tidy display strings. + 2000-04-12 Jesper Skov * src/hal_diag.c: Output text raw if configuration requires it. diff --git a/packages/hal/sh/edk/current/cdl/hal_sh_edk7708.cdl b/packages/hal/sh/edk/current/cdl/hal_sh_edk7708.cdl --- a/packages/hal/sh/edk/current/cdl/hal_sh_edk7708.cdl +++ b/packages/hal/sh/edk/current/cdl/hal_sh_edk7708.cdl @@ -41,7 +41,7 @@ # ==================================================================== cdl_package CYGPKG_HAL_SH_EDK7708 { - display "Hitachi SH3 EDK7708 evaluation board" + display "Hitachi EDK/SH7708 board" parent CYGPKG_HAL_SH define_header hal_sh_edk7708.h include_dir cyg/hal diff --git a/packages/hal/v85x/arch/current/src/hal_mk_defs.c b/packages/hal/v85x/arch/current/src/hal_mk_defs.c --- a/packages/hal/v85x/arch/current/src/hal_mk_defs.c +++ b/packages/hal/v85x/arch/current/src/hal_mk_defs.c @@ -51,9 +51,7 @@ # include # include #endif -#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT) #include -#endif /* * This program is used to generate definitions needed by diff --git a/packages/hal/v85x/ceb_v850/current/ChangeLog b/packages/hal/v85x/ceb_v850/current/ChangeLog --- a/packages/hal/v85x/ceb_v850/current/ChangeLog +++ b/packages/hal/v85x/ceb_v850/current/ChangeLog @@ -1,3 +1,14 @@ +2000-06-17 Gary Thomas + + * include/plf_intr.h: + * include/plf_stub.h: + * include/hal_diag.h: + * include/plf_sections.h: + * src/hal_diag.c: + * src/plf_stub.c: + * src/plf_misc.c: + * cdl/hal_v85x_ceb_v850.cdl: Support new virtual vector ROM mode. + 2000-05-25 John Dallaway * cdl/hal_v85x_ceb_v850.cdl: Tidy display strings. diff --git a/packages/hal/v85x/ceb_v850/current/cdl/hal_v85x_ceb_v850.cdl b/packages/hal/v85x/ceb_v850/current/cdl/hal_v85x_ceb_v850.cdl --- a/packages/hal/v85x/ceb_v850/current/cdl/hal_v85x_ceb_v850.cdl +++ b/packages/hal/v85x/ceb_v850/current/cdl/hal_v85x_ceb_v850.cdl @@ -55,10 +55,16 @@ cdl_package CYGPKG_HAL_V85X_V850_CEB { implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK implements CYGINT_HAL_DIAG_DISABLE_GDB_PROTOCOL_SUPPORTED + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT_GUARANTEED define_proc { puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "#define CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS 1" + puts $::cdl_header "#define CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL 0" + puts $::cdl_header "#define CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL 0" + puts $::cdl_header "#define CYGNUM_HAL_VIRTUAL_VECTOR_ROM_DEBUG_CHANNEL 0" } cdl_component CYG_HAL_STARTUP { @@ -154,8 +160,9 @@ cdl_package CYGPKG_HAL_V85X_V850_CEB { requires CYGSEM_HAL_ROM_MONITOR requires CYGBLD_BUILD_COMMON_GDB_STUBS requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS - requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT - requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires ! CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM no_define diff --git a/packages/hal/v85x/ceb_v850/current/include/hal_diag.h b/packages/hal/v85x/ceb_v850/current/include/hal_diag.h --- a/packages/hal/v85x/ceb_v850/current/include/hal_diag.h +++ b/packages/hal/v85x/ceb_v850/current/include/hal_diag.h @@ -34,12 +34,12 @@ //============================================================================= //#####DESCRIPTIONBEGIN#### // -// Author(s): nickg -// Contributors: nickg -// Date: 1998-03-02 -// Purpose: HAL Support for Kernel Diagnostic Routines -// Description: Diagnostic routines for use during kernel development. -// Usage: #include +// Author(s): nickg +// Contributors: nickg, gthomas +// Date: 1998-03-02 +// Purpose: HAL Support for Kernel Diagnostic Routines +// Description: Diagnostic routines for use during kernel development. +// Usage: #include // //####DESCRIPTIONEND#### // @@ -52,19 +52,38 @@ /*---------------------------------------------------------------------------*/ /* functions implemented in hal_diag.c */ + externC void hal_diag_init(void); - externC void hal_diag_write_char(char c); - externC void hal_diag_read_char(char *c); /*---------------------------------------------------------------------------*/ -#define HAL_DIAG_INIT() hal_diag_init() +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) + +#include + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) +#ifndef CYGPRI_CONSOLE_PROCS_HANDLED +externC void hal_plf_init_serial(void); +externC void hal_plf_write_char(int); +externC int hal_plf_get_char(void); + +# define HAL_PLF_DIAG_RAW_INIT() hal_plf_init_serial() +# define HAL_PLF_DIAG_RAW_WRITE_CHAR(_c_) hal_plf_write_char(_c_) +# define HAL_PLF_DIAG_RAW_READ_CHAR(_c_) (_c_) = hal_plf_get_char() +#endif + +#else + +#define HAL_DIAG_INIT() hal_diag_init() #define HAL_DIAG_WRITE_CHAR(_c_) hal_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) -#define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) +#endif /*---------------------------------------------------------------------------*/ /* end of hal_diag.h */ diff --git a/packages/hal/v85x/ceb_v850/current/include/plf_intr.h b/packages/hal/v85x/ceb_v850/current/include/plf_intr.h --- a/packages/hal/v85x/ceb_v850/current/include/plf_intr.h +++ b/packages/hal/v85x/ceb_v850/current/include/plf_intr.h @@ -115,6 +115,9 @@ // The vector used by the Real time clock. #define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_VECTOR_INTTM10 +// Vector used to detect ^C +#define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_VECTOR_INTCSI1 + // Mapping from interrupt numbers to hardware registers #define CYG_HAL_V85X_INTERRUPT_CONTROL_REGISTERS \ (volatile unsigned char *)V850_REG_WDTIC, \ @@ -148,6 +151,15 @@ (volatile unsigned char *)V850_REG_DMAIC2, \ (volatile unsigned char *)V850_REG_WTIC +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) + +extern struct Hal_SavedRegisters *hal_saved_interrupt_state; +extern void hal_ctrlc_isr_init(void); +extern cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); +#define HAL_CTRLC_ISR(_v_,_d_) hal_ctrlc_isr(_v_, _d_) +#endif + //-------------------------------------------------------------------------- #endif // ifndef CYGONCE_HAL_PLF_INTR_H // End of plf_intr.h diff --git a/packages/hal/v85x/ceb_v850/current/include/plf_sections.h b/packages/hal/v85x/ceb_v850/current/include/plf_sections.h --- a/packages/hal/v85x/ceb_v850/current/include/plf_sections.h +++ b/packages/hal/v85x/ceb_v850/current/include/plf_sections.h @@ -42,4 +42,5 @@ //========================================================================== #define SECTIONS_END . = ALIGN(4); _end = .; PROVIDE (end = .); \ - PROVIDE(_hal_vsr_table = 0x00FC0260); + PROVIDE(_hal_vsr_table = 0x00FC0260); \ + PROVIDE(_hal_virtual_vector_table = 0x00FC0300); diff --git a/packages/hal/v85x/ceb_v850/current/include/plf_stub.h b/packages/hal/v85x/ceb_v850/current/include/plf_stub.h --- a/packages/hal/v85x/ceb_v850/current/include/plf_stub.h +++ b/packages/hal/v85x/ceb_v850/current/include/plf_stub.h @@ -73,12 +73,14 @@ extern void hal_plf_stub_init(void); #define HAL_STUB_PLATFORM_INIT() hal_plf_stub_init(); +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + //---------------------------------------------------------------------------- // Reset. +extern void hal_plf_reset_board(void); #define HAL_STUB_PLATFORM_RESET() hal_plf_reset_board() - -#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#define HAL_STUB_PLATFORM_RESET_ENTRY 0x00000000 //----------------------------------------------------------------------------- #endif // CYGONCE_HAL_PLF_STUB_H diff --git a/packages/hal/v85x/ceb_v850/current/src/hal_diag.c b/packages/hal/v85x/ceb_v850/current/src/hal_diag.c --- a/packages/hal/v85x/ceb_v850/current/src/hal_diag.c +++ b/packages/hal/v85x/ceb_v850/current/src/hal_diag.c @@ -53,10 +53,14 @@ #include // interrupt macros #include // IO macros #include -#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#include -#include // cyg_hal_gdb_interrupt -#define CYG_DEVICE_SERIAL_INT CYGNUM_HAL_VECTOR_INTCSI1 + +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) +#include // target_register_t +#include // HAL_INTERRUPT_UNMASK(...) +#include // Calling interface definitions +#include // Helper functions +#include // CYG_ISR_HANDLED #endif #include // hardware registers, etc. @@ -64,11 +68,6 @@ // Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e. // totally stand-alone) system. -#ifdef CYGSEM_HAL_ROM_MONITOR -#define CYG_HAL_STARTUP_ROM -#undef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS -#endif - #if defined(CYG_HAL_STARTUP_ROM) && !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) #define HAL_DIAG_USES_HARDWARE #else @@ -96,37 +95,6 @@ /*---------------------------------------------------------------------------*/ // CEB-v850 -void -FAIL(char *m) -{ - static char *fail_reason; - fail_reason = m; -#if 0 - while (1) { - show_led('~'); - show_hex4(m); - show_led('/'); - } -#else - diag_printf("FAIL: %s\n", m); -#endif -} - -void -ALERT(char *m) -{ - static char *alert_reason; - alert_reason = m; -#if 0 - show_led('~'); - show_led('~'); - show_hex4(m); - show_led('/'); -#else - diag_printf("ALERT: %s\n", m); -#endif -} - // Actually send character down the wire void hal_diag_write_char_serial(char c) @@ -155,8 +123,6 @@ hal_diag_read_serial(char *c) return true; } -#ifdef HAL_DIAG_USES_HARDWARE - void hal_diag_init(void) { static int init = 0; @@ -176,25 +142,13 @@ void hal_diag_init(void) *txstat = 0x47; } -#ifdef DEBUG_DIAG -#ifndef CYG_HAL_STARTUP_ROM -#define DIAG_BUFSIZE 2048 -static char diag_buffer[DIAG_BUFSIZE]; -static int diag_bp = 0; -#endif -#endif +#ifdef HAL_DIAG_USES_HARDWARE void hal_diag_write_char(char c) { CYG_INTERRUPT_STATE old; HAL_DISABLE_INTERRUPTS(old); hal_diag_init(); -#ifdef DEBUG_DIAG -#ifndef CYG_HAL_STARTUP_ROM - diag_buffer[diag_bp++] = c; - if (diag_bp == sizeof(diag_buffer)) diag_bp = 0; -#endif -#endif hal_diag_write_char_serial(c); HAL_RESTORE_INTERRUPTS(old); } @@ -206,16 +160,6 @@ void hal_diag_read_char(char *c) #else // HAL_DIAG relies on GDB -// Initialize diag port -void hal_diag_init(void) -{ - char *msg = "eCos 1.3.x - " __DATE__ "\n\r"; - static int init = 0; - if (init) return; - init++; - while (*msg) hal_diag_write_char(*msg++); -} - void hal_diag_read_char(char *c) { @@ -289,7 +233,7 @@ hal_diag_write_char(char c) #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) && \ defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) - cyg_drv_interrupt_acknowledge(CYG_DEVICE_SERIAL_INT); + cyg_drv_interrupt_acknowledge(CYGHWR_HAL_GDB_PORT_VECTOR); if( c1 == 3 ) { // Ctrl-C: breakpoint. #if 0 // FIXME - __builtin_return_address() doesn't work @@ -308,12 +252,37 @@ hal_diag_write_char(char c) // And re-enable interrupts #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old); - hal_diag_write_char_break(); // FIXME +#if 1 // FIXME - __builtin_return_address() doesn't work + hal_diag_write_char_break(); +#endif #else HAL_RESTORE_INTERRUPTS(old); #endif } } +#endif // USE HARDWARE + +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) + +struct Hal_SavedRegisters *hal_saved_interrupt_state; + +void +hal_ctrlc_isr_init(void) +{ + HAL_INTERRUPT_UNMASK(CYGHWR_HAL_GDB_PORT_VECTOR); +} + +cyg_uint32 +hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + volatile unsigned char *RxDATA = (volatile unsigned char *)V850_REG_RXS0; + unsigned char ch; + ch = (char)*RxDATA; + if( cyg_hal_is_break( &ch , 1 ) ) + cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); + return CYG_ISR_HANDLED; +} #endif /*---------------------------------------------------------------------------*/ diff --git a/packages/hal/v85x/ceb_v850/current/src/plf_misc.c b/packages/hal/v85x/ceb_v850/current/src/plf_misc.c --- a/packages/hal/v85x/ceb_v850/current/src/plf_misc.c +++ b/packages/hal/v85x/ceb_v850/current/src/plf_misc.c @@ -53,6 +53,8 @@ #include // Interrupt handling #include // Hardware definitions +#include // ROM monitor interfaces + extern void show_hex4(unsigned long val); extern void show_hex1(unsigned long val); extern void show_8bit_reg(void *addr); @@ -62,6 +64,7 @@ void cyg_hal_platform_hardware_init(void) { int i; + hal_if_init(); // Initialize GDB[ROM]/eCos interfaces show_led(' '); show_led(' '); } @@ -224,6 +227,37 @@ show_led(int p) } } +void +FAIL(char *m) +{ + static char *fail_reason; + fail_reason = m; +#if 0 + while (1) { + show_led('~'); + show_hex4(m); + show_led('/'); + } +#else + diag_printf("FAIL: %s\n", m); +#endif +} + +void +ALERT(char *m) +{ + static char *alert_reason; + alert_reason = m; +#if 0 + show_led('~'); + show_led('~'); + show_hex4(m); + show_led('/'); +#else + diag_printf("ALERT: %s\n", m); +#endif +} + // // Clock support, using 16 bit timer TM1 // diff --git a/packages/kernel/current/ChangeLog b/packages/kernel/current/ChangeLog --- a/packages/kernel/current/ChangeLog +++ b/packages/kernel/current/ChangeLog @@ -1,3 +1,13 @@ +2000-06-16 Gary Thomas + + * cdl/kernel.cdl: Remove exception tests for CMA230 - not supported + by hardware. + +2000-06-16 Jesper Skov + + * src/intr/intr.cxx (chain_isr): Only call default_isr if no isrs + in the chain reacted to the interrupt. + 2000-06-08 Jesper Skov * src/debug/dbg-thread-demux.c: Use generic HAL feature to allow diff --git a/packages/kernel/current/cdl/kernel.cdl b/packages/kernel/current/cdl/kernel.cdl --- a/packages/kernel/current/cdl/kernel.cdl +++ b/packages/kernel/current/cdl/kernel.cdl @@ -330,6 +330,7 @@ cdl_package CYGPKG_KERNEL { CYGPKG_HAL_ARM_AEB ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmemfix1 tests/kmemvar1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/kthread0 tests/kthread1 tests/mbox1 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone" : \ CYGPKG_HAL_ARM_EBSA285 ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmemfix1 tests/kmemvar1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/kthread0 tests/kthread1 tests/mbox1 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone tests/stress_threads tests/kcache1 tests/kcache2" : \ CYGPKG_HAL_ARM_EDB7XXX ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmemfix1 tests/kmemvar1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/kthread0 tests/kthread1 tests/mbox1 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone tests/stress_threads tests/kcache1 tests/kcache2" : \ + CYGPKG_HAL_ARM_CMA230 ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kintr0 tests/kmbox1 tests/kmemfix1 tests/kmemvar1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/kthread0 tests/kthread1 tests/mbox1 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone" : \ CYGPKG_HAL_ARM ? "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmemfix1 tests/kmemvar1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/kthread0 tests/kthread1 tests/mbox1 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone" : \ "tests/bin_sem0 tests/bin_sem1 tests/bin_sem2 tests/clock0 tests/clock1 tests/clockcnv tests/cnt_sem0 tests/cnt_sem1 tests/except1 tests/flag0 tests/flag1 tests/intr0 tests/kclock0 tests/kclock1 tests/kexcept1 tests/kintr0 tests/kmbox1 tests/kmemfix1 tests/kmemvar1 tests/kmutex0 tests/kmutex1 tests/ksched1 tests/ksem0 tests/ksem1 tests/kflag0 tests/kflag1 tests/kthread0 tests/kthread1 tests/mbox1 tests/memfix1 tests/memfix2 tests/memvar1 tests/memvar2 tests/mutex0 tests/mutex1 tests/mutex2 tests/mutex3 tests/sched1 tests/sync2 tests/sync3 tests/thread0 tests/thread1 tests/thread2 tests/release tests/kill tests/thread_gdb tests/tm_basic tests/dhrystone tests/stress_threads tests/kcache1 tests/kcache2" } diff --git a/packages/kernel/current/src/intr/intr.cxx b/packages/kernel/current/src/intr/intr.cxx --- a/packages/kernel/current/src/intr/intr.cxx +++ b/packages/kernel/current/src/intr/intr.cxx @@ -330,7 +330,8 @@ Cyg_Interrupt::chain_isr(cyg_vector vect { Cyg_Interrupt *p = *(Cyg_Interrupt **)data; register cyg_uint32 isr_ret = 0; - + register cyg_uint32 isr_chain_ret = 0; + CYG_INSTRUMENT_INTR(CHAIN_ISR, vector, 0); while( p != NULL ) @@ -339,6 +340,8 @@ Cyg_Interrupt::chain_isr(cyg_vector vect { isr_ret = p->isr(vector, p->data); + isr_chain_ret |= isr_ret; + if( isr_ret & Cyg_Interrupt::CALL_DSR ) p->post_dsr(); if( isr_ret & Cyg_Interrupt::HANDLED ) break; @@ -348,7 +351,7 @@ Cyg_Interrupt::chain_isr(cyg_vector vect } #ifdef HAL_DEFAULT_ISR - if( (isr_ret & Cyg_Interrupt::HANDLED) == 0 ) + if( (isr_chain_ret & (Cyg_Interrupt::HANDLED|Cyg_Interrupt::CALL_DSR)) == 0 ) { // If we finished the loop for some reason other than that an // ISR has handled the interrupt, call any default ISR to either diff --git a/packages/language/c/libc/current/ChangeLog b/packages/language/c/libc/current/ChangeLog --- a/packages/language/c/libc/current/ChangeLog +++ b/packages/language/c/libc/current/ChangeLog @@ -1,3 +1,14 @@ +2000-06-20 Jonathan Larmour + + * include/time.inl (__gmtime_r): Don't save leap year status when + calculating tm_wday + +2000-06-17 Jonathan Larmour + + * tests/time/gmtime.c (test): Add a couple more test cases + + * include/time.inl (__gmtime_r): Deal with boundary case correctly + 2000-05-25 Hugo Tyson * src/clibincl/stream.inl (set_error): If the error is EEOF, set diff --git a/packages/language/c/libc/current/include/time.inl b/packages/language/c/libc/current/include/time.inl --- a/packages/language/c/libc/current/include/time.inl +++ b/packages/language/c/libc/current/include/time.inl @@ -414,8 +414,7 @@ CYGPRI_LIBC_TIME_GMTIME_R_INLINE struct // Day of the year. We know _tim is +ve now CYG_ASSERT(_tim >= 0, "Number of seconds since start of year is negative!"); - // assign tm_mday as well for further below - __result->tm_mday = __result->tm_yday = _tim / CYGNUM_LIBC_TIME_SECSPERDAY; + __result->tm_yday = _tim / CYGNUM_LIBC_TIME_SECSPERDAY; // Day of the week. Normalize to be 0..6, and note that it might // be negative, so we have to deal with the modulus being @@ -425,7 +424,9 @@ CYGPRI_LIBC_TIME_GMTIME_R_INLINE struct // Month and Day of the month _months_p = cyg_libc_time_month_lengths[ - cyg_libc_time_year_is_leap(1900 + __result->tm_year)]; + cyg_libc_time_year_is_leap(1900 + __result->tm_year) ? 1 : 0 ]; + + __result->tm_mday = __result->tm_yday+1; for (__result->tm_mon = 0; __result->tm_mday > _months_p[__result->tm_mon]; @@ -435,10 +436,6 @@ CYGPRI_LIBC_TIME_GMTIME_R_INLINE struct } // for - // The month day is now in the range 0..30 - // We move it to 1..31 - ++__result->tm_mday; - _tim -= __result->tm_yday*CYGNUM_LIBC_TIME_SECSPERDAY; // hours, mins secs diff --git a/packages/language/c/libc/current/tests/time/gmtime.c b/packages/language/c/libc/current/tests/time/gmtime.c --- a/packages/language/c/libc/current/tests/time/gmtime.c +++ b/packages/language/c/libc/current/tests/time/gmtime.c @@ -153,6 +153,36 @@ test( CYG_ADDRWORD data ) tm2 = gmtime(&t); CYG_TEST_PASS_FAIL(!cmp_structtm(&tm1, tm2), "gmtime test #4"); + tm1.tm_sec = 59; + tm1.tm_min = 59; + tm1.tm_hour = 23; + tm1.tm_mday = 31; + tm1.tm_mon = 4; + tm1.tm_wday = 3; + tm1.tm_yday = 151; + tm1.tm_year = 100; + tm1.tm_isdst = 0; + + t = (time_t)959817599; + + tm2 = gmtime(&t); + CYG_TEST_PASS_FAIL(!cmp_structtm(&tm1, tm2), "gmtime test #5"); + + tm1.tm_sec = 0; + tm1.tm_min = 0; + tm1.tm_hour = 0; + tm1.tm_mday = 1; + tm1.tm_mon = 5; + tm1.tm_wday = 4; + tm1.tm_yday = 152; + tm1.tm_year = 100; + tm1.tm_isdst = 0; + + t = (time_t)959817600; + + tm2 = gmtime(&t); + CYG_TEST_PASS_FAIL(!cmp_structtm(&tm1, tm2), "gmtime test #6"); + CYG_TEST_FINISH("Finished tests from testcase " __FILE__ " for C library " "gmtime() function"); } // test() diff --git a/packages/net/drivers/eth/common/current/ChangeLog b/packages/net/drivers/eth/common/current/ChangeLog --- a/packages/net/drivers/eth/common/current/ChangeLog +++ b/packages/net/drivers/eth/common/current/ChangeLog @@ -1,3 +1,15 @@ +2000-06-23 Hugo Tyson + + * src/eth_drv.c (eth_drv_send): Do not consume an SG entry for + zero length data; tolerate overflow of the SG. Before this, pings + of 6000 bytes crashed the system! + + You can now set net_debug to 2 to get quieter output; 1 gives the + whole packet dump as before. + + * include/eth_drv.h (MAX_ETH_DRV_SG): Make this 16 so that an MTU + made of all mbufs will not overflow. + 2000-03-28 Gary Thomas * src/eth_drv.c (eth_drv_recv): Tolerate running out of MBUFs diff --git a/packages/net/drivers/eth/common/current/include/eth_drv.h b/packages/net/drivers/eth/common/current/include/eth_drv.h --- a/packages/net/drivers/eth/common/current/include/eth_drv.h +++ b/packages/net/drivers/eth/common/current/include/eth_drv.h @@ -79,7 +79,10 @@ struct eth_drv_sg { CYG_ADDRESS buf; CYG_ADDRWORD len; }; -#define MAX_ETH_DRV_SG 8 + +// This is 16 to ensure that an MTU made of mbufs (not clusters) will fit. +// 1600 is more that the MTU of 1500; it must be right. +#define MAX_ETH_DRV_SG 16 struct eth_drv_sc; diff --git a/packages/net/drivers/eth/common/current/src/eth_drv.c b/packages/net/drivers/eth/common/current/src/eth_drv.c --- a/packages/net/drivers/eth/common/current/src/eth_drv.c +++ b/packages/net/drivers/eth/common/current/src/eth_drv.c @@ -289,15 +289,23 @@ eth_drv_send(struct ifnet *ifp) total_len += len; sg_list[sg_len].buf = (CYG_ADDRESS)data; sg_list[sg_len].len = len; - sg_len++; + if ( len ) + sg_len++; if (net_debug) { - diag_printf("xmit %d bytes at %x\n", len, data); - diag_dump_buf(data, len); + diag_printf("xmit %d bytes at %x sg[%d]\n", len, data, sg_len); + if ( 1 & net_debug ) + diag_dump_buf(data, len); + } + if ( MAX_ETH_DRV_SG < sg_len ) { + diag_printf("too many mbufs to tx, %d > %d\n", sg_len, MAX_ETH_DRV_SG ); + sg_len = 0; + break; // drop it on the floor } } // Tell hardware to send this packet - (sc->funs->send)(sc, sg_list, sg_len, total_len, (unsigned long)m0); + if ( sg_len ) + (sc->funs->send)(sc, sg_list, sg_len, total_len, (unsigned long)m0); } cyg_scheduler_unlock(); // Allow DSRs to run @@ -402,7 +410,9 @@ eth_drv_recv(struct eth_drv_sc *sc, int if (net_debug) { for (i = 0; i < sg_len; i++) { if (sg_list[i].buf) { - diag_dump_buf((void *)sg_list[i].buf, sg_list[i].len); + diag_printf("rx %d bytes at %x sg[%d]\n", sg_list[i].len, sg_list[i].buf, i); + if ( 1 & net_debug ) + diag_dump_buf((void *)sg_list[i].buf, sg_list[i].len); } } } @@ -430,3 +440,4 @@ eth_drv_recv(struct eth_drv_sc *sc, int ether_input(ifp, eh, m); } +// EOF eth_drv.c diff --git a/packages/net/snmp/agent/current/ChangeLog b/packages/net/snmp/agent/current/ChangeLog new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/ChangeLog @@ -0,0 +1,269 @@ +2000-06-19 Hugo Tyson + + * src/mibgroup/mibII/dot3.c (var_dot3StatsTable): Don't trip over + loopback interface; it doesn't support the same enquiries as an + eth device. + + * src/mibgroup/mibII/interfaces.c (var_ifTable): Don't trip over + loopback interface; it doesn't support the same enquiries as an + eth device. + +2000-06-14 Hugo Tyson + + * cdl/snmpagent.cdl: Add options for the default values for system + MIB vals that describe the machine. + + * src/mibgroup/mibII/system_mib.c (init_system_mib): Pick up + values from configury (this goes via config.h in the library). + +2000-06-14 John Dallaway + + * cdl/snmpagent.cdl: Tidy display strings. + +2000-06-14 Hugo Tyson + + * cdl/snmpagent.cdl: Install all the header files below + include/ucd-snmp/ as is the normal host-side standard; this avoids + some rather terrible filenamespace pollution too. That location + is also added to the include path, using a mechanism that's rather + build-method-specific; it may need revisiting. + +2000-06-14 Hugo Tyson + + * cdl/snmpagent.cdl: parent this below CYGPKG_NET. + +2000-06-13 Hugo Tyson + + * cdl/snmpagent.cdl: Add mibgroup/mibII/dot3.c to compile list. + + * src/mibgroup/mibII/dot3.c (var_dot3StatsTable): Done that - and + it required changes to the EBSA ether device driver. Of course, + if those info-macros are not present, the SNMP agent module uses + zeros, so it should "work" half-heartedly with other platforms + too. + + * include/mibgroup/mibII/dot3.h: Completed handler function list. + + * src/mibgroup/mibII/interfaces.c (var_ifTable): This now makes + use of info-macros exported from the ethernet dd. + + * include/mib_module_inits.h: Call init_dot3() in the bootup. + + * src/mibgroup/mibII/system_mib.c (init_system_mib): Fill in + default system type description. + +2000-06-09 Hugo Tyson + + * src/mibgroup/mibII/tcp.c (var_tcpConnTable): Done that. + +2000-06-09 Hugo Tyson + + * src/mibgroup/mibII/udp.c (var_udpTable): Done that. + +2000-06-08 Hugo Tyson + + * src/mibgroup/mibII/icmp.c (var_icmp): Fleshed this out with a + copy from the UCD version - BSD stack nosing-in-kernel memory arm + of the code is the same, unsurprisingly. + +2000-06-08 Hugo Tyson + + * src/mibgroup/mibII/ip.c (var_ip): Flesh this out; it's mostly + there now. + + * src/mibgroup/mibII/interfaces.c (var_ifTable): Make this more + consistent, particularly the use of FIXMEs for the bits I have not + completed yet. + +2000-06-06 Hugo Tyson + + * src/mibgroup/mibII/interfaces.c (var_ifTable): Flesh this out + with lots of snooping into the ifnet structures and a little info + from the device driver. The info is there now. + + * src/mibgroup/mibII/tcp.c (var_tcpConnTable,var_ipv6TcpConnTable): + * src/mibgroup/mibII/udp.c (var_udpTable,var_ipv6UdpTable): + * src/mibgroup/mibII/ip.c (var_ipAddrTable,var_ipNetToMediaTable): + Fix these (by commenting out) parts for complex tables that made + the snmpwalk tool crash out; ie. it acts as if all such complex + tables are empty, rather than returning badly indexed entries. + +2000-06-02 Hugo Tyson + + * utils/mib2c/README-eCos: + * utils/mib2c/README.mib2c: + * utils/mib2c/mib2c: + * utils/mib2c/mib2c.conf: + * utils/mib2c/mib2c.conf-ORIG: + * utils/mib2c/mib2c.storage.conf: + * utils/mib2c/mib2c.vartypes.conf: + New files, just to keep my variant of mib2c.conf under source + controlled; it includes our copyright (and attribution to UCD et + al, of course) the different include paths as required by eCos' + package layout and a couple of other nits sorted out. + +2000-06-02 Hugo Tyson + + * cdl/snmpagent.cdl (compile): Omit the read-only file-system + part; the library will cheerfully use it, but it's not at all + necessary. Waste of time - unless someone is liable to use the + snmplib for tool rather than agent purposes. + + * include/mib_module_includes.h: Include the full set of includes + for the MIBs we will implement. Ie. + mibgroup/mibII/system_mib.h // { mib2 1 } + mibgroup/mibII/sysORTable.h // { mib2 1.9.1 } == { system 9.1 } + mibgroup/mibII/interfaces.h // { mib2 2 } + (NOT mibgroup/mibII/at.h) // #3 is deprecated + mibgroup/mibII/ip.h // { mib2 4 } + mibgroup/mibII/icmp.h // { mib2 5 } + mibgroup/mibII/tcp.h // { mib2 6 } + mibgroup/mibII/udp.h // { mib2 7 } + mibgroup/mibII/dot3.h // { mib2 10.7 } == { transmission 7 } + mibgroup/mibII/snmp_mib.h // { mib2 11 } + + * include/mib_module_inits.h: Same thing really; but dot3 is not + yet in there at all, it'll be added later. + init_system_mib(); // { mib2 1 } + init_sysORTable(); // { mib2 1.9.1 } == { system 9.1 } + init_interfaces(); // { mib2 2 } + //init_at(); // #3 is deprecated + init_ip(); // { mib2 4 } + init_icmp(); // { mib2 5 } + init_tcp(); // { mib2 6 } + init_udp(); // { mib2 7 } + //init_dot3(); // { mib2 10.7 } == { transmission 7 } FIXME + init_snmp_mib(); // { mib2 11 } + + * include/mibgroup/mibII/icmp.h: + * include/mibgroup/mibII/interfaces.h: + * include/mibgroup/mibII/ip.h: + * include/mibgroup/mibII/tcp.h: + * include/mibgroup/mibII/udp.h: + These files have all been replaced by versions direct from mib2c, + without any of the UNIX/LINUX/Win32-specific gubbins from the + original versions. + + * include/mibgroup/mibII/dot3.h: New file direct from mib2c. + + * include/mibgroup/mibII/route_write.h: DELETED + * include/mibgroup/mibII/at.h: DELETED + * include/mibgroup/mibII/var_route.h: DELETED + Removed, not necessary for the vanilla headers; they were there + before to satisfy include needs of the originals. + + * src/mibgroup/mibII/dot3.c: + * src/mibgroup/mibII/icmp.c: + * src/mibgroup/mibII/interfaces.c: + * src/mibgroup/mibII/ip.c: + * src/mibgroup/mibII/tcp.c: + * src/mibgroup/mibII/udp.c: + These are new files, direct from mib2c, again without all the + UNIX/LINUX/Win32-specific gubbins from the original versions. + + * src/rofs/EtherLike-MIB.c: DELETED + * src/rofs/IANAifType-MIB.c: DELETED + * src/rofs/IF-MIB.c: DELETED + * src/rofs/IP-MIB.c: DELETED + * src/rofs/RFC-1215.c: DELETED + * src/rofs/SNMPv2-CONF.c: DELETED + * src/rofs/SNMPv2-MIB.c: DELETED + * src/rofs/SNMPv2-SMI.c: DELETED + * src/rofs/SNMPv2-TC.c: DELETED + * src/rofs/SNMPv2-TM.c: DELETED + * src/rofs/TCP-MIB.c: DELETED + * src/rofs/UDP-MIB.c: DELETED + * src/rofs/snmprofs.c: DELETED + Turns out that I don't need a read-only FS with all the MIBs in in + the agent - reading them in (and complaining of their absence) is + part of the snmplib startup, but it's not needed by an agent. + This also means that if reinstated they should live in the lib + component rather than the agent one; oh well. + + +2000-05-31 Hugo Tyson + + * Initial commit of port of UCD-SNMP version 4.1.2 to eCos. + +//========================================================================== +// +// ./agent/current/ChangeLog +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ diff --git a/packages/net/snmp/agent/current/cdl/snmpagent.cdl b/packages/net/snmp/agent/current/cdl/snmpagent.cdl new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/cdl/snmpagent.cdl @@ -0,0 +1,287 @@ +# ==================================================================== +# +# snmpagent.cdl +# +# SNMP agent configuration data +# +# ==================================================================== +#####COPYRIGHTBEGIN#### +# +# ------------------------------------------- +# The contents of this file are subject to the Red Hat eCos Public License +# Version 1.1 (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://www.redhat.com/ +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +# License for the specific language governing rights and limitations under +# the License. +# +# The Original Code is eCos - Embedded Configurable Operating System, +# released September 30, 1998. +# +# The Initial Developer of the Original Code is Red Hat. +# Portions created by Red Hat are +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# All Rights Reserved. +# ------------------------------------------- +# +#####COPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): hmt +# Original data: hmt +# Contributors: gthomas +# Date: 2000-05-30 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_SNMPAGENT { + display "SNMP agent" + parent CYGPKG_NET +# doc doc/index.html + include_dir ucd-snmp + requires CYGPKG_IO + requires CYGPKG_LIBC + requires CYGPKG_ERROR + requires CYGPKG_NET + requires CYGPKG_SNMPLIB + description "SNMP agent based on the UCD-SNMP project." + + compile \ + agent_read_config.c \ + agent_registry.c \ + agent_trap.c \ + kernel.c \ + mib_modules.c \ + snmp_agent.c \ + snmp_vars.c \ + snmpd.c \ + snmptask.c \ + mibgroup/mibII/system_mib.c \ + mibgroup/mibII/sysORTable.c \ + mibgroup/mibII/snmp_mib.c \ + mibgroup/mibII/icmp.c \ + mibgroup/mibII/interfaces.c \ + mibgroup/mibII/ip.c \ + mibgroup/mibII/tcp.c \ + mibgroup/mibII/udp.c \ + mibgroup/util_funcs.c \ + mibgroup/mibII/dot3.c \ + + + +# Turns out the agent does not need to read the MIBs at all. +# It is all part of the library startup; I had been misled by +# debug/error messages. But that part of the lib is not used. +# +# rofs/EtherLike-MIB.c \ +# rofs/IANAifType-MIB.c \ +# rofs/IF-MIB.c \ +# rofs/IP-MIB.c \ +# rofs/RFC-1215.c \ +# rofs/SNMPv2-CONF.c \ +# rofs/SNMPv2-MIB.c \ +# rofs/SNMPv2-SMI.c \ +# rofs/SNMPv2-TC.c \ +# rofs/SNMPv2-TM.c \ +# rofs/TCP-MIB.c \ +# rofs/UDP-MIB.c + +# compile -library=libextras.a rofs/snmprofs.c + +# mibgroup/mibII/interfaces.c \ +# mibgroup/mibII/icmp.c \ +# mibgroup/mibII/ip.c \ +# mibgroup/mibII/snmp_mib.c \ +# mibgroup/mibII/sysORTable.c \ +# mibgroup/mibII/system_mib.c \ +# mibgroup/mibII/tcp.c \ +# mibgroup/mibII/udp.c \ +# mibgroup/util_funcs.c \ +# + +# these from MIBII that I think I might need later +# mibgroup/mibII/ipv6.c \ +# mibgroup/mibII/route_write.c \ +# mibgroup/mibII/var_route.c \ +# AT group is deprecated +# mibgroup/mibII/at.c \ +# SNMPv3 view access control +# mibgroup/mibII/vacm_vars.c \ + + +# here is the full list +# compile \ +# dlmods/dlmod_mib.c \ +# dlmods/example.c \ +# mibgroup/agentx/client.c \ +# mibgroup/agentx/master.c \ +# mibgroup/agentx/master_admin.c \ +# mibgroup/agentx/master_request.c \ +# mibgroup/agentx/protocol.c \ +# mibgroup/agentx/subagent.c \ +# mibgroup/examples/example.c \ +# mibgroup/examples/ucdDemoPublic.c \ +# mibgroup/examples/ucdDemoPublic.cmds \ +# mibgroup/examples/ucdDemoPublic.conf \ +# mibgroup/host/hr_device.c \ +# mibgroup/host/hr_disk.c \ +# mibgroup/host/hr_filesys.c \ +# mibgroup/host/hr_network.c \ +# mibgroup/host/hr_other.c \ +# mibgroup/host/hr_partition.c \ +# mibgroup/host/hr_print.c \ +# mibgroup/host/hr_proc.c \ +# mibgroup/host/hr_storage.c \ +# mibgroup/host/hr_swinst.c \ +# mibgroup/host/hr_swrun.c \ +# mibgroup/host/hr_system.c \ +# mibgroup/host/hr_utils.c \ +# mibgroup/mibII/interfaces.c \ +# mibgroup/mibII/at.c \ +# mibgroup/mibII/icmp.c \ +# mibgroup/mibII/ip.c \ +# mibgroup/mibII/ipv6.c \ +# mibgroup/mibII/route_write.c \ +# mibgroup/mibII/snmp_mib.c \ +# mibgroup/mibII/sysORTable.c \ +# mibgroup/mibII/system_mib.c \ +# mibgroup/mibII/tcp.c \ +# mibgroup/mibII/udp.c \ +# mibgroup/mibII/vacm_vars.c \ +# mibgroup/mibII/var_route.c \ +# mibgroup/misc/ipfwacc.c \ +# mibgroup/misc/dlmod.c \ +# mibgroup/smux/snmp_bgp.c \ +# mibgroup/smux/smux.c \ +# mibgroup/smux/snmp_ospf.c \ +# mibgroup/smux/snmp_rip2.c \ +# mibgroup/snmpv3/snmpEngine.c \ +# mibgroup/snmpv3/snmpMPDStats.c \ +# mibgroup/snmpv3/usmStats.c \ +# mibgroup/snmpv3/usmUser.c \ +# mibgroup/target/snmpTargetAddrEntry.c \ +# mibgroup/target/snmpTargetParamsEntry.c \ +# mibgroup/ucd-snmp/diskio.c \ +# mibgroup/ucd-snmp/disk.c \ +# mibgroup/ucd-snmp/errormib.c \ +# mibgroup/ucd-snmp/extensible.c \ +# mibgroup/ucd-snmp/file.c \ +# mibgroup/ucd-snmp/hpux.c \ +# mibgroup/ucd-snmp/loadave.c \ +# mibgroup/ucd-snmp/memory.c \ +# mibgroup/ucd-snmp/memory_freebsd2.c \ +# mibgroup/ucd-snmp/memory_netbsd1.c \ +# mibgroup/ucd-snmp/memory_solaris2.c \ +# mibgroup/ucd-snmp/pass.c \ +# mibgroup/ucd-snmp/pass_persist.c \ +# mibgroup/ucd-snmp/proc.c \ +# mibgroup/ucd-snmp/registry.c \ +# mibgroup/ucd-snmp/versioninfo.c \ +# mibgroup/ucd-snmp/vmstat.c \ +# mibgroup/ucd-snmp/vmstat_freebsd2.c \ +# mibgroup/ucd-snmp/vmstat_netbsd1.c \ +# mibgroup/ucd-snmp/vmstat_solaris2.c \ +# mibgroup/header_complex.c \ +# mibgroup/kernel_sunos5.c \ +# mibgroup/util_funcs.c \ + + + cdl_component CYGPKG_SNMPAGENT_SYSTEM_MIB { + display "System MIB defaults" + flavor none + no_define + description " + These options control the default values for items in the + system MIB. The symbols are used as initializers for C char + arrays; therefore you must include \"double-quotes\" in the + defined value to get the correct results." + + cdl_option CYGDAT_NET_SNMPAGENT_SYS_CONTACT { + display "Contact address" + flavor data + default_value { "\"nobody@nowhere.net\"" } + description " + This specifies the value returned for the sysContact field + of the System MIB (via the symbol SYS_CONTACT in the UCD + sources)." + } + + cdl_option CYGDAT_NET_SNMPAGENT_SYS_LOC { + display "System location" + flavor data + default_value { "\"\"" } + description " + This specifies the value returned for the sysLocation field + of the System MIB (via the symbol SYS_LOC in the UCD + sources)" + } + + cdl_option CYGDAT_NET_SNMPAGENT_VERS_DESC { + display "Version description" + flavor data + default_value { "\"ucd-snmp-4.1.2/Red Hat eCos\"" } + description " + This specifies the value returned for the sysDescr field + of the System MIB (via the symbol VERS_DESC in the UCD + sources)" + } + + cdl_option CYGDAT_NET_SNMPAGENT_SYS_NAME { + display "System name " + flavor data + default_value { "\"eCos\"" } + description " + This specifies the value returned for the sysName field + of the System MIB (via the symbol SYS_NAME in the UCD + sources)" + } + } + + cdl_component CYGPKG_SNMPAGENT_OPTIONS { + display "SNMP agent build options" + flavor none + no_define + + cdl_option CYGPKG_SNMPAGENT_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS -DIN_UCD_SNMP_SOURCE=1 -I$(PREFIX)/include/ucd-snmp" } + description " + This option modifies the set of compiler flags for + building the SNMP agent package. + These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_SNMPAGENT_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the SNMP agent package. These flags are removed from + the set of global flags if present." + } + + cdl_option CYGPKG_SNMPAGENT_TESTS { + display "SNMP agent tests" + flavor data + no_define + calculated { + "tests/snmpping" + } + description " + This option specifies the set of tests for the eCos SMNP agent." + } + } +} + +# EOF snmpagent.cdl diff --git a/packages/net/snmp/agent/current/include/agent_callbacks.h b/packages/net/snmp/agent/current/include/agent_callbacks.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/agent_callbacks.h @@ -0,0 +1,93 @@ +//========================================================================== +// +// ./agent/current/include/agent_callbacks.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef AGENT_CALLBACKS_H +#define AGENT_CALLBACKS_H + +#define SNMPD_CALLBACK_ACM_CHECK 0 +#define SNMPD_CALLBACK_REGISTER_OID 1 +#define SNMPD_CALLBACK_UNREGISTER_OID 2 +#define SNMPD_CALLBACK_REG_SYSOR 3 +#define SNMPD_CALLBACK_UNREG_SYSOR 4 +#define SNMPD_CALLBACK_ACM_CHECK_INITIAL 5 + +#endif /* AGENT_CALLBACKS_H */ diff --git a/packages/net/snmp/agent/current/include/agent_read_config.h b/packages/net/snmp/agent/current/include/agent_read_config.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/agent_read_config.h @@ -0,0 +1,99 @@ +//========================================================================== +// +// ./agent/current/include/agent_read_config.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * agent_read_config.h: reads configuration files for extensible sections. + * + */ +#ifndef _AGENT_READ_CONFIG_H +#define _AGENT_READ_CONFIG_H + +void init_agent_read_config (const char *); +void update_config (void); +void snmpd_register_config_handler (const char *, + void (*parser)(const char *, char *), + void (*releaser) (void), + const char *); +void snmpd_unregister_config_handler (const char *); +void snmpd_store_config (const char *); + +#endif /* _AGENT_READ_CONFIG_H */ diff --git a/packages/net/snmp/agent/current/include/agent_registry.h b/packages/net/snmp/agent/current/include/agent_registry.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/agent_registry.h @@ -0,0 +1,172 @@ +//========================================================================== +// +// ./agent/current/include/agent_registry.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef AGENT_REGISTRY_H +#define AGENT_REGISTRY_H + +/* the structure of parameters passed to registered ACM modules */ +struct view_parameters { + struct snmp_pdu *pdu; + oid *name; + size_t namelen; + int errorcode; /* do not change unless you're + specifying an error, + as it starts in a success state. */ +}; + +struct register_parameters { + oid *name; + size_t namelen; + int priority; + int range_subid; + oid range_ubound; +}; + +#define MIB_REGISTERED_OK 0 +#define MIB_DUPLICATE_REGISTRATION -1 +#define MIB_REGISTRATION_FAILED -2 + +#define MIB_UNREGISTERED_OK 0 +#define MIB_NO_SUCH_REGISTRATION -1 +#define MIB_UNREGISTRATION_FAILED -2 + +#define DEFAULT_MIB_PRIORITY 127 + +#define ALLOCATE_THIS_INDEX 0x0 +#define ALLOCATE_ANY_INDEX 0x1 +#define ALLOCATE_NEW_INDEX 0x3 + /* N.B: it's deliberate that NEW_INDEX & ANY_INDEX == ANY_INDEX */ + +#define ANY_INTEGER_INDEX -1 +#define ANY_STRING_INDEX NULL +#define ANY_OID_INDEX NULL + +#define INDEX_ERR_GENERR -1 +#define INDEX_ERR_WRONG_TYPE -2 +#define INDEX_ERR_NOT_ALLOCATED -3 +#define INDEX_ERR_WRONG_SESSION -4 + +char* register_string_index( oid *, size_t, char *); +int register_int_index( oid *, size_t, int); +struct variable_list* register_oid_index( oid *, size_t, oid *, size_t); +struct variable_list* register_index( struct variable_list *, int, struct snmp_session*); + +int release_index( struct variable_list *); +int remove_index( struct variable_list *, struct snmp_session*); +void unregister_index_by_session(struct snmp_session *); +int unregister_index(struct variable_list *, int, struct snmp_session *); + +void setup_tree (void); +struct subtree *find_subtree (oid *, size_t, struct subtree *); +struct subtree *find_subtree_next (oid *, size_t, struct subtree *); +struct subtree *find_subtree_previous (oid *, size_t, struct subtree *); +struct snmp_session *get_session_for_oid( oid *, size_t); + +int register_mib(const char *, struct variable *, size_t, size_t, oid *, size_t); +int register_mib_priority(const char *, struct variable *, size_t, size_t, oid *, size_t, int); +int register_mib_range(const char *, struct variable *, size_t , size_t , oid *, size_t, int, int, oid, struct snmp_session *); + +int unregister_mib (oid *, size_t); +int unregister_mib_priority (oid *, size_t, int); +int unregister_mib_range (oid *, size_t, int, int, oid); +void unregister_mibs_by_session (struct snmp_session *); + +struct subtree *free_subtree (struct subtree *); +int compare_tree (const oid *, size_t, const oid *, size_t); +int in_a_view(oid *, size_t *, struct snmp_pdu *, int); +int check_access(struct snmp_pdu *pdu); + +/* REGISTER_MIB(): This macro simply loads register_mib with less pain: + + descr: A short description of the mib group being loaded. + var: The variable structure to load. + vartype: The variable structure used to define it (variable2, variable4, ...) + theoid: A *initialized* *exact length* oid pointer. + (sizeof(theoid) *must* return the number of elements!) +*/ +#define REGISTER_MIB(descr, var, vartype, theoid) \ + if (register_mib(descr, (struct variable *) var, sizeof(struct vartype), \ + sizeof(var)/sizeof(struct vartype), \ + theoid, sizeof(theoid)/sizeof(oid)) != MIB_REGISTERED_OK ) \ + DEBUGMSGTL(("register_mib", "%s registration failed\n", descr)); + +#endif /* AGENT_REGISTRY_H */ diff --git a/packages/net/snmp/agent/current/include/agent_trap.h b/packages/net/snmp/agent/current/include/agent_trap.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/agent_trap.h @@ -0,0 +1,102 @@ +//========================================================================== +// +// ./agent/current/include/agent_trap.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef AGENT_TRAP_H +#define AGENT_TRAP_H + +void send_easy_trap (int, int); +void send_trap_pdu(struct snmp_pdu *); +void send_v2trap ( struct variable_list *); +void send_trap_vars (int, int, struct variable_list *); + +void snmpd_parse_config_authtrap (const char *, char *); +void snmpd_parse_config_trapsink (const char *, char *); +void snmpd_parse_config_trap2sink (const char *, char *); +void snmpd_parse_config_informsink (const char *, char *); +void snmpd_free_trapsinks (void); +void snmpd_parse_config_trapcommunity (const char *, char *); +void snmpd_free_trapcommunity (void); + +int create_trap_session (char *, u_short, char *, int, int); +int add_trap_session( struct snmp_session *, int, int); + +#endif /* AGENT_TRAP_H */ diff --git a/packages/net/snmp/agent/current/include/ds_agent.h b/packages/net/snmp/agent/current/include/ds_agent.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/ds_agent.h @@ -0,0 +1,99 @@ +//========================================================================== +// +// ./agent/current/include/ds_agent.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef DS_AGENT_H +#define DS_AGENT_H +/* defines agent's default store registrations */ + +/* booleans */ +#define DS_AGENT_VERBOSE 0 /* 1 if verbose output desired */ +#define DS_AGENT_ROLE 1 /* 0 if master, 1 if client */ +#define DS_AGENT_NO_ROOT_ACCESS 2 /* 1 if we can't get root access */ + +/* strings */ +#define DS_AGENT_PROGNAME 0 /* argv[0] */ +#define DS_AGENT_X_SOCKET 1 /* AF_UNIX or ip:port socket addr */ + +/* integers */ +#define DS_AGENT_FLAGS 0 /* session.flags */ + +#endif diff --git a/packages/net/snmp/agent/current/include/kernel.h b/packages/net/snmp/agent/current/include/kernel.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/kernel.h @@ -0,0 +1,92 @@ +//========================================================================== +// +// ./agent/current/include/kernel.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ + +#ifndef linux +extern void init_kmem (const char *); +extern int klookup (unsigned long, char *, int); +#endif + +#if HAVE_KVM_H +#include +extern kvm_t *kd; +#endif diff --git a/packages/net/snmp/agent/current/include/m2m.h b/packages/net/snmp/agent/current/include/m2m.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/m2m.h @@ -0,0 +1,131 @@ +//========================================================================== +// +// ./agent/current/include/m2m.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * m2m.h + */ + +struct get_req_state { + int type; + void *info; +}; + +/* values for type field in get_req_state */ +#define ALARM_GET_REQ 1 +#define EVENT_GET_REQ 2 + +/* the following define is used to document a routine or variable which +** is not static to a module. +*/ +#define Export + +/* values for EntryStatus */ +#define ENTRY_ACTIVE 1 +#define ENTRY_NOTINSERVICE 2 +#define ENTRY_NOTREADY 3 +#define ENTRY_CREATEANDGO 4 +#define ENTRY_CREATEANDWAIT 5 +#define ENTRY_DESTROY 6 + +/* maximum length for an OwnerString variable */ +#define MAX_OWNER_STR_LEN 128 + +/* maximum length for a description field */ +#define MAX_DESCRIPTION_LEN 128 + +/* defines for noting whether the incoming packet is unicast, broadcast, +** or multicast +*/ +#define PKT_UNICAST 0 +#define PKT_BROADCAST 1 +#define PKT_MULTICAST 2 + +/* macro to compare two ethernet addresses. addr1 is a pointer to a +** struct ether_addr; addr2 is just a struct ether_addr. +*/ +#define sameEtherAddr(addr1, addr2) \ + ((*((short *)((addr1)->ether_addr_octet)) == \ + *((short *)((addr2).ether_addr_octet))) &&\ + (*((short *)(((addr1)->ether_addr_octet) + 2)) == \ + *((short *)((((addr2).ether_addr_octet) + 2)))) &&\ + (*((short *)(((addr1)->ether_addr_octet) + 4)) == \ + *((short *)((((addr2).ether_addr_octet) + 4))))) diff --git a/packages/net/snmp/agent/current/include/mib_module_config.h b/packages/net/snmp/agent/current/include/mib_module_config.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mib_module_config.h @@ -0,0 +1,179 @@ +//========================================================================== +// +// ./agent/current/include/mib_module_config.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file is automatically generated by configure. Do not modify by hand. */ +/* Define if compiling with the mibII module files. */ +#define USING_MIBII_MODULE 1 + +/* Define if compiling with the ucd_snmp module files. */ +#define USING_UCD_SNMP_MODULE 1 + +/* Define if compiling with the snmpv3mibs module files. */ +//#define USING_SNMPV3MIBS_MODULE 1 + +/* Define if compiling with the mibII/system_mib module files. */ +#define USING_MIBII_SYSTEM_MIB_MODULE 1 + +/* Define if compiling with the mibII/sysORTable module files. */ +#define USING_MIBII_SYSORTABLE_MODULE 1 + +/* Define if compiling with the mibII/at module files. */ +//#define USING_MIBII_AT_MODULE 1 + +/* Define if compiling with the mibII/interfaces module files. */ +#define USING_MIBII_INTERFACES_MODULE 1 + +/* Define if compiling with the mibII/snmp_mib module files. */ +#define USING_MIBII_SNMP_MIB_MODULE 1 + +/* Define if compiling with the mibII/tcp module files. */ +#define USING_MIBII_TCP_MODULE 1 + +/* Define if compiling with the mibII/icmp module files. */ +#define USING_MIBII_ICMP_MODULE 1 + +/* Define if compiling with the mibII/ip module files. */ +#define USING_MIBII_IP_MODULE 1 + +/* Define if compiling with the mibII/udp module files. */ +#define USING_MIBII_UDP_MODULE 1 + +/* Define if compiling with the mibII/vacm_vars module files. */ +//#define USING_MIBII_VACM_VARS_MODULE 1 + +/* Define if compiling with the ucd-snmp/memory module files. */ +//#define USING_UCD_SNMP_MEMORY_MODULE 1 + +/* Define if compiling with the ucd-snmp/vmstat module files. */ +//#define USING_UCD_SNMP_VMSTAT_MODULE 1 + +/* Define if compiling with the ucd-snmp/proc module files. */ +//#define USING_UCD_SNMP_PROC_MODULE 1 + +/* Define if compiling with the ucd-snmp/versioninfo module files. */ +//#define USING_UCD_SNMP_VERSIONINFO_MODULE 1 + +/* Define if compiling with the ucd-snmp/pass module files. */ +//#define USING_UCD_SNMP_PASS_MODULE 1 + +/* Define if compiling with the ucd-snmp/pass_persist module files. */ +//#define USING_UCD_SNMP_PASS_PERSIST_MODULE 1 + +/* Define if compiling with the ucd-snmp/disk module files. */ +//#define USING_UCD_SNMP_DISK_MODULE 1 + +/* Define if compiling with the ucd-snmp/loadave module files. */ +//#define USING_UCD_SNMP_LOADAVE_MODULE 1 + +/* Define if compiling with the ucd-snmp/extensible module files. */ +//#define USING_UCD_SNMP_EXTENSIBLE_MODULE 1 + +/* Define if compiling with the ucd-snmp/errormib module files. */ +//#define USING_UCD_SNMP_ERRORMIB_MODULE 1 + +/* Define if compiling with the ucd-snmp/registry module files. */ +//#define USING_UCD_SNMP_REGISTRY_MODULE 1 + +/* Define if compiling with the ucd-snmp/file module files. */ +//#define USING_UCD_SNMP_FILE_MODULE 1 + +/* Define if compiling with the snmpv3/snmpEngine module files. */ +//#define USING_SNMPV3_SNMPENGINE_MODULE 1 + +/* Define if compiling with the snmpv3/snmpMPDStats module files. */ +//#define USING_SNMPV3_SNMPMPDSTATS_MODULE 1 + +/* Define if compiling with the snmpv3/usmStats module files. */ +//#define USING_SNMPV3_USMSTATS_MODULE 1 + +/* Define if compiling with the snmpv3/usmUser module files. */ +//#define USING_SNMPV3_USMUSER_MODULE 1 + +/* Define if compiling with the util_funcs module files. */ +#define USING_UTIL_FUNCS_MODULE 1 + +/* Define if compiling with the mibII/var_route module files. */ +//#define USING_MIBII_VAR_ROUTE_MODULE 1 + +/* Define if compiling with the mibII/route_write module files. */ +//#define USING_MIBII_ROUTE_WRITE_MODULE 1 + diff --git a/packages/net/snmp/agent/current/include/mib_module_dot_conf.h b/packages/net/snmp/agent/current/include/mib_module_dot_conf.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mib_module_dot_conf.h @@ -0,0 +1,83 @@ +//========================================================================== +// +// ./agent/current/include/mib_module_dot_conf.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file is automatically generated by configure. Do not modify by hand. */ diff --git a/packages/net/snmp/agent/current/include/mib_module_includes.h b/packages/net/snmp/agent/current/include/mib_module_includes.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mib_module_includes.h @@ -0,0 +1,116 @@ +//========================================================================== +// +// ./agent/current/include/mib_module_includes.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file is automatically generated by configure. Do not modify by hand. */ +//#include "mibgroup/mibII.h" // no content +//#include "mibgroup/ucd_snmp.h" +//#include "mibgroup/snmpv3mibs.h" +#include "mibgroup/mibII/system_mib.h" // { mib2 1 } +#include "mibgroup/mibII/sysORTable.h" // { mib2 1.9.1 } == { system 9.1 } +#include "mibgroup/mibII/interfaces.h" // { mib2 2 } +//#include "mibgroup/mibII/at.h" // #3 is deprecated +#include "mibgroup/mibII/ip.h" // { mib2 4 } +#include "mibgroup/mibII/icmp.h" // { mib2 5 } +#include "mibgroup/mibII/tcp.h" // { mib2 6 } +#include "mibgroup/mibII/udp.h" // { mib2 7 } +#include "mibgroup/mibII/dot3.h" // { mib2 10.7 } == { transmission 7 } +#include "mibgroup/mibII/snmp_mib.h" // { mib2 11 } +//#include "mibgroup/mibII/vacm_vars.h" +//#include "mibgroup/ucd-snmp/memory.h" +//#include "mibgroup/ucd-snmp/vmstat.h" +//#include "mibgroup/ucd-snmp/proc.h" +//#include "mibgroup/ucd-snmp/versioninfo.h" +//#include "mibgroup/ucd-snmp/pass.h" +//#include "mibgroup/ucd-snmp/pass_persist.h" +//#include "mibgroup/ucd-snmp/disk.h" +//#include "mibgroup/ucd-snmp/loadave.h" +//#include "mibgroup/ucd-snmp/extensible.h" +//#include "mibgroup/ucd-snmp/errormib.h" +//#include "mibgroup/ucd-snmp/registry.h" +//#include "mibgroup/ucd-snmp/file.h" +//#include "mibgroup/snmpv3/snmpEngine.h" +//#include "mibgroup/snmpv3/snmpMPDStats.h" +//#include "mibgroup/snmpv3/usmStats.h" +//#include "mibgroup/snmpv3/usmUser.h" +//#include "mibgroup/util_funcs.h" +//#include "mibgroup/mibII/var_route.h" +//#include "mibgroup/mibII/route_write.h" diff --git a/packages/net/snmp/agent/current/include/mib_module_inits.h b/packages/net/snmp/agent/current/include/mib_module_inits.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mib_module_inits.h @@ -0,0 +1,130 @@ +//========================================================================== +// +// ./agent/current/include/mib_module_inits.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file is automatically generated by configure. Do not modify by hand. */ + + +init_system_mib(); // { mib2 1 } +init_sysORTable(); // { mib2 1.9.1 } == { system 9.1 } +init_interfaces(); // { mib2 2 } +//init_at(); // #3 is deprecated +init_ip(); // { mib2 4 } +init_icmp(); // { mib2 5 } +init_tcp(); // { mib2 6 } +init_udp(); // { mib2 7 } +init_dot3(); // { mib2 10.7 } == { transmission 7 } +init_snmp_mib(); // { mib2 11 } + + + + + +// init_system_mib(); +// init_sysORTable(); +// init_interfaces(); +// init_snmp_mib(); +// init_tcp(); +// init_icmp(); +// init_ip(); +// init_udp(); + + +// init_at(); // #3 is deprecated + +// init_vacm_vars(); +// init_memory(); +// init_vmstat(); +// init_proc(); +// init_versioninfo(); +// init_pass(); +// init_pass_persist(); +// init_disk(); +// init_loadave(); +// init_extensible(); +// init_errormib(); +// init_registry(); +// init_file(); +// init_snmpEngine(); +// init_snmpMPDStats(); +// init_usmStats(); +// init_usmUser(); +// init_var_route(); diff --git a/packages/net/snmp/agent/current/include/mib_module_shutdown.h b/packages/net/snmp/agent/current/include/mib_module_shutdown.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mib_module_shutdown.h @@ -0,0 +1,83 @@ +//========================================================================== +// +// ./agent/current/include/mib_module_shutdown.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file is automatically generated by configure. Do not modify by hand. */ diff --git a/packages/net/snmp/agent/current/include/mib_modules.h b/packages/net/snmp/agent/current/include/mib_modules.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mib_modules.h @@ -0,0 +1,84 @@ +//========================================================================== +// +// ./agent/current/include/mib_modules.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +void init_mib_modules(void); + diff --git a/packages/net/snmp/agent/current/include/mibdefs.h b/packages/net/snmp/agent/current/include/mibdefs.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibdefs.h @@ -0,0 +1,94 @@ +//========================================================================== +// +// ./agent/current/include/mibdefs.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* 2 global mib defs: + ERRORFLAG: A binary flag to signal an error condition. + Also used as exit code. + ERRORMSG: A text message describing what caused the above condition, + Also used as the single line return message from programs */ + +#define MIBINDEX 1 +#define ERRORNAME 2 +#define ERRORFLAG 100 +#define ERRORMSG 101 +#define ERRORFIX 102 +#define ERRORFIXCMD 103 diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/dot3.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/dot3.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/dot3.h @@ -0,0 +1,114 @@ +//========================================================================== +// +// snmp/snmpagent/current/include/mibgroup/mibII/dot3.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +#ifndef _MIBGROUP_DOT3_H +#define _MIBGROUP_DOT3_H + + +/* we may use header_generic and header_simple_table from the util_funcs module */ + + +config_require(util_funcs) + + +/* function prototypes */ +void init_dot3(void); +FindVarMethod var_dot3; +FindVarMethod var_dot3PauseTable; +WriteMethod write_dot3PauseAdminMode; + +FindVarMethod var_dot3StatsTable; +FindVarMethod var_dot3StatsTable; + +FindVarMethod var_dot3ControlTable; +FindVarMethod var_dot3ControlTable; + +FindVarMethod var_dot3PauseTable; +FindVarMethod var_dot3PauseTable; + +WriteMethod write_dot3PauseAdminMode; + +#endif /* _MIBGROUP_DOT3_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/icmp.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/icmp.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/icmp.h @@ -0,0 +1,106 @@ +//========================================================================== +// +// snmp/snmpagent/current/include/mibgroup/mibII/icmp.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +#ifndef _MIBGROUP_ICMP_H +#define _MIBGROUP_ICMP_H + + +/* we may use header_generic and header_simple_table from the util_funcs module */ + + +config_require(util_funcs) + + +/* function prototypes */ + + +void init_icmp(void); +FindVarMethod var_icmp; + + + + +#endif /* _MIBGROUP_ICMP_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/interfaces.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/interfaces.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/interfaces.h @@ -0,0 +1,109 @@ +//========================================================================== +// +// snmp/snmpagent/current/include/mibgroup/mibII/interfaces.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +#ifndef _MIBGROUP_INTERFACES_H +#define _MIBGROUP_INTERFACES_H + + +/* we may use header_generic and header_simple_table from the util_funcs module */ + + +config_require(util_funcs) + + +/* function prototypes */ + + +void init_interfaces(void); +FindVarMethod var_interfaces; +FindVarMethod var_ifTable; + + +WriteMethod write_ifAdminStatus; + + + +#endif /* _MIBGROUP_INTERFACES_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/ip.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/ip.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/ip.h @@ -0,0 +1,126 @@ +//========================================================================== +// +// snmp/snmpagent/current/include/mibgroup/mibII/ip.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +#ifndef _MIBGROUP_IP_H +#define _MIBGROUP_IP_H + + +/* we may use header_generic and header_simple_table from the util_funcs module */ + + +config_require(util_funcs) + + +/* function prototypes */ + + +void init_ip(void); +FindVarMethod var_ip; +FindVarMethod var_ipAddrTable; +FindVarMethod var_ipNetToMediaTable; + + +WriteMethod write_ipForwarding; +WriteMethod write_ipDefaultTTL; +WriteMethod write_ipRouteDest; +WriteMethod write_ipRouteIfIndex; +WriteMethod write_ipRouteMetric1; +WriteMethod write_ipRouteMetric2; +WriteMethod write_ipRouteMetric3; +WriteMethod write_ipRouteMetric4; +WriteMethod write_ipRouteNextHop; +WriteMethod write_ipRouteType; +WriteMethod write_ipRouteAge; +WriteMethod write_ipRouteMask; +WriteMethod write_ipRouteMetric5; +WriteMethod write_ipNetToMediaIfIndex; +WriteMethod write_ipNetToMediaPhysAddress; +WriteMethod write_ipNetToMediaNetAddress; +WriteMethod write_ipNetToMediaType; + + + +#endif /* _MIBGROUP_IP_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/snmp_mib.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/snmp_mib.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/snmp_mib.h @@ -0,0 +1,165 @@ +//========================================================================== +// +// ./agent/current/include/mibgroup/mibII/snmp_mib.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * SNMP MIB group interface - snmp.h + * + */ +#ifndef _MIBGROUP_SNMP_H +#define _MIBGROUP_SNMP_H + +struct variable; + +extern FindVarMethod var_snmp; +extern WriteMethod write_snmp; + +void init_snmp_mib(void); + +extern int snmp_inpkts; /* 1 - current */ +extern int snmp_outpkts; /* 2 - obsolete */ +extern int snmp_inbadversions; /* 3 - current */ +extern int snmp_inbadcommunitynames; /* 4 - current */ +extern int snmp_inbadcommunityuses; /* 5 - current */ +extern int snmp_inasnparseerrors; /* 6 - current */ +extern int snmp_intoobigs; /* 8 - obsolete */ +extern int snmp_innosuchnames; /* 9 - obsolete */ +extern int snmp_inbadvalues; /* 10 - obsolete */ +extern int snmp_inreadonlys; /* 11 - obsolete */ +extern int snmp_ingenerrs; /* 12 - obsolete */ +extern int snmp_intotalreqvars; /* 13 - obsolete */ +extern int snmp_intotalsetvars; /* 14 - obsolete */ +extern int snmp_ingetrequests; /* 15 - obsolete */ +extern int snmp_ingetnexts; /* 16 - obsolete */ +extern int snmp_insetrequests; /* 17 - obsolete */ +extern int snmp_ingetresponses; /* 18 - obsolete */ +extern int snmp_intraps; /* 19 - obsolete */ +extern int snmp_outtoobigs; /* 20 - obsolete */ +extern int snmp_outnosuchnames; /* 21 - obsolete */ +extern int snmp_outbadvalues; /* 22 - obsolete */ +extern int snmp_outgenerrs; /* 24 - obsolete */ +extern int snmp_outgetrequests; /* 25 - obsolete */ +extern int snmp_outgetnexts; /* 26 - obsolete */ +extern int snmp_outsetrequests; /* 27 - obsolete */ +extern int snmp_outgetresponses; /* 28 - obsolete */ +extern int snmp_outtraps; /* 29 - obsolete */ +extern int snmp_enableauthentraps; /* 30 - current */ +extern int snmp_silentdrops; /* 31 - current */ +extern int snmp_proxydrops; /* 32 - current */ + +extern char *snmp_trapsink; +extern char *snmp_trapcommunity; + + +#define SNMPINPKTS 1 +#define SNMPOUTPKTS 2 +#define SNMPINBADVERSIONS 3 +#define SNMPINBADCOMMUNITYNAMES 4 +#define SNMPINBADCOMMUNITYUSES 5 +#define SNMPINASNPARSEERRORS 6 +#define SNMPINBADTYPES 7 +#define SNMPINTOOBIGS 8 +#define SNMPINNOSUCHNAMES 9 +#define SNMPINBADVALUES 10 +#define SNMPINREADONLYS 11 +#define SNMPINGENERRS 12 +#define SNMPINTOTALREQVARS 13 +#define SNMPINTOTALSETVARS 14 +#define SNMPINGETREQUESTS 15 +#define SNMPINGETNEXTS 16 +#define SNMPINSETREQUESTS 17 +#define SNMPINGETRESPONSES 18 +#define SNMPINTRAPS 19 +#define SNMPOUTTOOBIGS 20 +#define SNMPOUTNOSUCHNAMES 21 +#define SNMPOUTBADVALUES 22 +#define SNMPOUTREADONLYS 23 +#define SNMPOUTGENERRS 24 +#define SNMPOUTGETREQUESTS 25 +#define SNMPOUTGETNEXTS 26 +#define SNMPOUTSETREQUESTS 27 +#define SNMPOUTGETRESPONSES 28 +#define SNMPOUTTRAPS 29 +#define SNMPENABLEAUTHENTRAPS 30 +#define SNMPSILENTDROPS 31 +#define SNMPPROXYDROPS 32 + +#endif /* _MIBGROUP_SNMP_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/sysORTable.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/sysORTable.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/sysORTable.h @@ -0,0 +1,136 @@ +//========================================================================== +// +// ./agent/current/include/mibgroup/mibII/sysORTable.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * Template MIB group interface - sysORTable.h + * + */ +#ifndef _MIBGROUP_SYSORTABLE_H +#define _MIBGROUP_SYSORTABLE_H + +config_require(util_funcs) + +struct sysORTable { + char *OR_descr; + oid *OR_oid; + size_t OR_oidlen; + struct timeval OR_uptime; + struct snmp_session *OR_sess; + struct sysORTable *next; +}; + +struct register_sysOR_parameters { + oid *name; + int namelen; + const char *descr; +}; + +extern void init_sysORTable (void); +extern FindVarMethod var_sysORTable; +extern FindVarMethod var_sysORLastChange; +extern int register_sysORTable (oid *, size_t, const char *); +extern int unregister_sysORTable (oid *, size_t); +extern int register_sysORTable_sess (oid *, size_t, const char *, struct snmp_session *); +extern int unregister_sysORTable_sess (oid *, size_t, struct snmp_session *); +extern void unregister_sysORTable_by_session (struct snmp_session *); + +#define SYSORTABLEINDEX 1 +#define SYSORTABLEID 2 +#define SYSORTABLEDESCR 3 +#define SYSORTABLEUPTIME 4 + +#define SYS_ORTABLE_REGISTERED_OK 0 +#define SYS_ORTABLE_REGISTRATION_FAILED -1 +#define SYS_ORTABLE_UNREGISTERED_OK 0 +#define SYS_ORTABLE_NO_SUCH_REGISTRATION -1 + +#ifdef USING_MIBII_SYSORTABLE_MODULE +#define REGISTER_SYSOR_ENTRY(theoid, descr) \ + (void)register_sysORTable(theoid, sizeof(theoid)/sizeof(oid), descr); +#define REGISTER_SYSOR_TABLE(theoid, len, descr) \ + (void)register_sysORTable(theoid, len, descr); + +#else +#define REGISTER_SYSOR_ENTRY +#define REGISTER_SYSOR_TABLE +#endif /* USING_MIBII_SYSORTABLE_MODULE */ +#endif /* _MIBGROUP_SYSORTABLE_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/system_mib.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/system_mib.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/system_mib.h @@ -0,0 +1,110 @@ +//========================================================================== +// +// ./agent/current/include/mibgroup/mibII/system_mib.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * System MIB group interface - system.h + * + */ +#ifndef _MIBGROUP_SYSTEM_MIB_H +#define _MIBGROUP_SYSTEM_MIB_H + +config_require(util_funcs) + +extern char version_descr[]; + +void init_system_mib (void); +extern FindVarMethod var_system; + +/* config file parsing routines */ +void system_parse_config_sysloc (const char *, char *); +void system_parse_config_syscon (const char *, char *); + +#define VERSION_DESCR 1 +#define VERSIONID 2 +#define UPTIME 3 +#define SYSCONTACT 4 +#define SYSTEMNAME 5 +#define SYSLOCATION 6 +#define SYSSERVICES 7 +#define SYSORLASTCHANGE 8 + +#endif /* _MIBGROUP_SYSTEM_MIB_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/tcp.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/tcp.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/tcp.h @@ -0,0 +1,111 @@ +//========================================================================== +// +// snmp/snmpagent/current/include/mibgroup/mibII/tcp.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +#ifndef _MIBGROUP_TCP_H +#define _MIBGROUP_TCP_H + + +/* we may use header_generic and header_simple_table from the util_funcs module */ + + +config_require(util_funcs) + + +/* function prototypes */ + + +void init_tcp(void); +FindVarMethod var_tcp; +FindVarMethod var_tcpConnTable; +FindVarMethod var_ipv6TcpConnTable; + + +WriteMethod write_tcpConnState; +WriteMethod write_ipv6TcpConnState; + + + +#endif /* _MIBGROUP_TCP_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/mibII/udp.h b/packages/net/snmp/agent/current/include/mibgroup/mibII/udp.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/mibII/udp.h @@ -0,0 +1,109 @@ +//========================================================================== +// +// snmp/snmpagent/current/include/mibgroup/mibII/udp.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +#ifndef _MIBGROUP_UDP_H +#define _MIBGROUP_UDP_H + + +/* we may use header_generic and header_simple_table from the util_funcs module */ + + +config_require(util_funcs) + + +/* function prototypes */ + + +void init_udp(void); +FindVarMethod var_udp; +FindVarMethod var_udpTable; +FindVarMethod var_ipv6UdpTable; + + + + + +#endif /* _MIBGROUP_UDP_H */ diff --git a/packages/net/snmp/agent/current/include/mibgroup/struct.h b/packages/net/snmp/agent/current/include/mibgroup/struct.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/struct.h @@ -0,0 +1,126 @@ +//========================================================================== +// +// ./agent/current/include/mibgroup/struct.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef UCD_SNMP_STRUCT +#define UCD_SNMP_STRUCT + +#define STRMAX 1024 +#define SHPROC 1 +#define EXECPROC 2 +#define PASSTHRU 3 +#define PASSTHRU_PERSIST 4 +#define MIBMAX 30 + +struct extensible +{ + char name[STRMAX]; + char command[STRMAX]; + char fixcmd[STRMAX]; + int type; + int result; + char output[STRMAX]; + struct extensible *next; + unsigned long miboid[MIBMAX]; + size_t miblen; + int pid; +}; + +struct myproc +{ + char name[STRMAX]; + char fixcmd[STRMAX]; + int min; + int max; + struct myproc *next; +}; + +/* +struct mibinfo +{ + int numid; + unsigned long mibid[10]; + char *name; + void (*handle) (); +}; +*/ + +#endif diff --git a/packages/net/snmp/agent/current/include/mibgroup/util_funcs.h b/packages/net/snmp/agent/current/include/mibgroup/util_funcs.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibgroup/util_funcs.h @@ -0,0 +1,113 @@ +//========================================================================== +// +// ./agent/current/include/mibgroup/util_funcs.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * util_funcs.h: utilitiy functions for extensible groups. + */ +#ifndef _MIBGROUP_UTIL_FUNCS_H +#define _MIBGROUP_UTIL_FUNCS_H + +#ifdef IN_UCD_SNMP_SOURCE +#include "mibgroup/struct.h" +#else +#include +#endif + +void Exit (int); +int shell_command (struct extensible *); +int exec_command (struct extensible *); +int get_exec_output (struct extensible *); +int get_exec_pipes (char *cmd, int *fdIn, int *fdOut, int *pid); +WriteMethod clear_cache; +RETSIGTYPE restart_doit (int); +WriteMethod restart_hook; +void print_mib_oid (oid *, size_t); +void sprint_mib_oid (char *, oid *, size_t); +int header_simple_table (struct variable *, oid *, size_t *, int, size_t *, WriteMethod **write_method, int); +int header_generic (struct variable *,oid *, size_t *, int, size_t *, WriteMethod **); +int checkmib (struct variable *, oid *, size_t *, int, size_t *, WriteMethod **write_method, int); +char *find_field (char *, int); +int parse_miboid (const char *, oid *); +void string_append_int (char *, int); +void wait_on_exec (struct extensible *); + +#endif /* _MIBGROUP_UTIL_FUNCS_H */ diff --git a/packages/net/snmp/agent/current/include/mibincl.h b/packages/net/snmp/agent/current/include/mibincl.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/mibincl.h @@ -0,0 +1,138 @@ +//========================================================================== +// +// ./agent/current/include/mibincl.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * mibincl.h + */ + +#include +#include + +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_MALLOC_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include +#endif + +#include "mib_module_config.h" + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_impl.h" + +#include "snmp_vars.h" +#include "agent_read_config.h" +#include "var_struct.h" + +#include "snmp.h" +#include "mib.h" +#include "snmp_debug.h" +#include "snmp_logging.h" +#include "read_config.h" +#include "tools.h" +#include "agent_trap.h" +#include "callback.h" +#define u_char unsigned char +#define u_short unsigned short + + diff --git a/packages/net/snmp/agent/current/include/snmp_agent.h b/packages/net/snmp/agent/current/include/snmp_agent.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/snmp_agent.h @@ -0,0 +1,120 @@ +//========================================================================== +// +// ./agent/current/include/snmp_agent.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmp_agent.h + * + * External definitions for functions in snmp_agent.c. + */ + +#ifndef SNMP_AGENT_H +#define SNMP_AGENT_H + +#define SNMP_MAX_PDU_SIZE 64000 /* local constraint on PDU size sent by agent + (see also SNMP_MAX_MSG_SIZE in snmp_api.h) */ + +struct agent_snmp_session { + int mode; + struct variable_list *start, *end; + struct snmp_session *session; + struct snmp_pdu *pdu; + int rw; + int exact; + int status; + + struct request_list *outstanding_requests; + struct agent_snmp_session *next; +}; + +/* config file parsing routines */ +int handle_snmp_packet(int, struct snmp_session *, int, struct snmp_pdu *, void *); +int handle_next_pass( struct agent_snmp_session *); +int handle_var_list( struct agent_snmp_session *); +void snmp_agent_parse_config (char *, char *); +struct agent_snmp_session *init_agent_snmp_session( struct snmp_session *, struct snmp_pdu *); +int getNextSessID(void); +int init_master_agent(int dest_port, + int (*pre_parse) (struct snmp_session *, snmp_ipaddr), + int (*post_parse) (struct snmp_session *, struct snmp_pdu *,int)); +int agent_check_and_process(int block); + +#endif diff --git a/packages/net/snmp/agent/current/include/snmp_vars.h b/packages/net/snmp/agent/current/include/snmp_vars.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/snmp_vars.h @@ -0,0 +1,170 @@ +//========================================================================== +// +// ./agent/current/include/snmp_vars.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * Definitions for SNMP (RFC 1067) agent variable finder. + * + */ + +#ifndef _SNMP_VARS_H_ +#define _SNMP_VARS_H_ + +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + Copyright 1989 TGV, Incorporated + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and TGV not be used +in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. + +CMU AND TGV DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL CMU OR TGV BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +******************************************************************/ + +struct variable; + +/* Function pointer called by the master agent for writes. */ +typedef int (WriteMethod)(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t length); + +/* Function pointer called by the master agent for mib information retrieval */ +typedef u_char *(FindVarMethod)(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method); + +/* Function pointer called by the master agent for setting up subagent requests */ +struct agent_snmp_session; +typedef int (AddVarMethod)(struct agent_snmp_session *asp, + struct variable_list *vbp); + +struct nlist; + +extern long long_return; +extern u_char return_buf[]; + +extern oid nullOid[]; +extern int nullOidLen; + +#define INST 0xFFFFFFFF /* used to fill out the instance field of the variables table */ + +struct variable { + u_char magic; /* passed to function as a hint */ + char type; /* type of variable */ +/* See important comment in snmp_vars.c relating to acl */ + u_short acl; /* access control list for variable */ + FindVarMethod *findVar; /* function that finds variable */ + u_char namelen; /* length of above */ + oid name[MAX_OID_LEN]; /* object identifier of variable */ +}; + +void init_agent(const char *); +int subtree_old_size (void); +void sort_tree (void); + +#ifndef _AGENT_REGISTRY_H +#include "agent_registry.h" +#endif + +/* fail overloads non-negative integer value. it must be -1 ! */ +#define MATCH_FAILED (-1) +#define MATCH_SUCCEEDED 0 + +#endif /* _SNMP_VARS_H_ */ diff --git a/packages/net/snmp/agent/current/include/snmpd.h b/packages/net/snmp/agent/current/include/snmpd.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/snmpd.h @@ -0,0 +1,101 @@ +//========================================================================== +// +// ./agent/current/include/snmpd.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmpd.h + */ + +#define MASTER_AGENT 0 +#define SUB_AGENT 1 +extern int agent_role; + +extern int snmp_dump_packet; +extern int verbose; +extern int (*sd_handlers[])(int); +extern int smux_listen_sd; + +extern int snmp_read_packet (int); +extern u_char *getStatPtr (oid *, size_t *, u_char *, size_t *, + u_short *, int, WriteMethod **write_method, struct snmp_pdu *, int *); + +/* config file parsing routines */ +void agentBoots_conf (char *, char *); diff --git a/packages/net/snmp/agent/current/include/var_struct.h b/packages/net/snmp/agent/current/include/var_struct.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/var_struct.h @@ -0,0 +1,164 @@ +//========================================================================== +// +// ./agent/current/include/var_struct.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef VAR_STRUCT_H +#define VAR_STRUCT_H +/* + * The subtree structure contains a subtree prefix which applies to + * all variables in the associated variable list. + * + * By converting to a tree of subtree structures, entries can + * now be subtrees of another subtree in the structure. i.e: + * 1.2 + * 1.2.0 + */ +struct subtree { + oid name[16]; /* objid prefix of registered subtree */ + u_char namelen; /* number of subid's in name above */ + oid start[16]; /* objid of start of covered range */ + u_char start_len; /* number of subid's in start name */ + oid end[16]; /* objid of end of covered range */ + u_char end_len; /* number of subid's in end name */ + struct variable *variables; /* pointer to variables array */ + int variables_len; /* number of entries in above array */ + int variables_width; /* sizeof each variable entry */ + char label[256]; /* calling module's label */ + struct snmp_session *session; + u_char flags; + u_char priority; + struct subtree *next; /* List of 'sibling' subtrees */ + struct subtree *prev; /* Make siblings a doubly-linked list */ + struct subtree *children; /* List of 'child' subtrees */ +}; + +/* + * This is a new variable structure that doesn't have as much memory + * tied up in the object identifier. It's elements have also been re-arranged + * so that the name field can be variable length. Any number of these + * structures can be created with lengths tailor made to a particular + * application. The first 5 elements of the structure must remain constant. + */ +struct variable2 { + u_char magic; /* passed to function as a hint */ + u_char type; /* type of variable */ + u_short acl; /* access control list for variable */ + FindVarMethod *findVar; /* function that finds variable */ + u_char namelen; /* length of name below */ + oid name[2]; /* object identifier of variable */ +}; + +struct variable4 { + u_char magic; /* passed to function as a hint */ + u_char type; /* type of variable */ + u_short acl; /* access control list for variable */ + FindVarMethod *findVar; /* function that finds variable */ + u_char namelen; /* length of name below */ + oid name[4]; /* object identifier of variable */ +}; + +struct variable7 { + u_char magic; /* passed to function as a hint */ + u_char type; /* type of variable */ + u_short acl; /* access control list for variable */ + FindVarMethod *findVar; /* function that finds variable */ + u_char namelen; /* length of name below */ + oid name[7]; /* object identifier of variable */ +}; + +struct variable8 { + u_char magic; /* passed to function as a hint */ + u_char type; /* type of variable */ + u_short acl; /* access control list for variable */ + FindVarMethod *findVar; /* function that finds variable */ + u_char namelen; /* length of name below */ + oid name[8]; /* object identifier of variable */ +}; + +struct variable13 { + u_char magic; /* passed to function as a hint */ + u_char type; /* type of variable */ + u_short acl; /* access control list for variable */ + FindVarMethod *findVar; /* function that finds variable */ + u_char namelen; /* length of name below */ + oid name[13]; /* object identifier of variable */ +}; +#endif /* VAR_STRUCT_H */ diff --git a/packages/net/snmp/agent/current/include/version.h b/packages/net/snmp/agent/current/include/version.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/include/version.h @@ -0,0 +1,83 @@ +//========================================================================== +// +// ./agent/current/include/version.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +static const char *VersionInfo="4.1.2"; diff --git a/packages/net/snmp/agent/current/src/agent_read_config.c b/packages/net/snmp/agent/current/src/agent_read_config.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/agent_read_config.c @@ -0,0 +1,243 @@ +//========================================================================== +// +// ./agent/current/src/agent_read_config.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * agent_read_config.c + */ + +#include + +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#include +#include +#include + +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_NETINET_IN_SYSTM_H +#include +#endif +#if HAVE_NETINET_IP_H +#include +#endif +#ifdef INET6 +#if HAVE_NETINET_IP6_H +#include +#endif +#endif +#if HAVE_SYS_QUEUE_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include +#elif HAVE_WINSOCK_H +#include +#endif +#if HAVE_SYS_STREAM_H +#include +#endif +#if HAVE_NET_ROUTE_H +#include +#endif +#if HAVE_NETINET_IP_VAR_H +#include +#endif +#ifdef INET6 +#if HAVE_NETINET6_IP6_VAR_H +#include +#endif +#endif +#if HAVE_NETINET_IN_PCB_H +#include +#endif +#if HAVE_INET_MIB2_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "mibincl.h" +#include "snmpusm.h" + +#include "mibgroup/struct.h" +#include "read_config.h" +#include "agent_read_config.h" +#include "callback.h" +#include "snmp_agent.h" +#include "agent_trap.h" +#include "snmpd.h" +#include "system.h" +#include "snmp_debug.h" +#include "snmp_alarm.h" +#include "default_store.h" +#include "ds_agent.h" +#include "mib_module_includes.h" + +char dontReadConfigFiles; +char *optconfigfile; + +void init_agent_read_config (const char *app) +{ + if ( app != NULL ) + ds_set_string(DS_LIBRARY_ID, DS_LIB_APPTYPE, app); + + register_app_config_handler("authtrapenable", + snmpd_parse_config_authtrap, NULL, + "1 | 2\t\t(1 = enable, 2 = disable)"); + + if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == MASTER_AGENT ) { + register_app_config_handler("trapsink", + snmpd_parse_config_trapsink, snmpd_free_trapsinks, + "host [community]"); + register_app_config_handler("trap2sink", + snmpd_parse_config_trap2sink, NULL, + "host [community]"); + register_app_config_handler("informsink", + snmpd_parse_config_informsink, NULL, + "host [community]"); + } + register_app_config_handler("trapcommunity", + snmpd_parse_config_trapcommunity, + snmpd_free_trapcommunity, + "community-string"); +#include "mib_module_dot_conf.h" +#ifdef TESTING + print_config_handlers(); +#endif +} + +void update_config(void) +{ + free_config(); + read_configs(); +} + + +void +snmpd_register_config_handler(const char *token, + void (*parser) (const char *, char *), + void (*releaser) (void), + const char *help) +{ + DEBUGMSGTL(("snmpd_register_app_config_handler", + "registering .conf token for \"%s\"\n", token)); + register_app_config_handler(token, parser, releaser, help); +} + +void +snmpd_unregister_config_handler(const char *token) +{ + unregister_app_config_handler(token); +} + +/* this function is intended for use by mib-modules to store permenant + configuration information generated by sets or persistent counters */ +void +snmpd_store_config(const char *line) +{ + read_app_config_store(line); +} diff --git a/packages/net/snmp/agent/current/src/agent_registry.c b/packages/net/snmp/agent/current/src/agent_registry.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/agent_registry.c @@ -0,0 +1,1460 @@ +//========================================================================== +// +// ./agent/current/src/agent_registry.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * agent_registry.c + * + * Maintain a registry of MIB subtrees, together + * with related information regarding mibmodule, sessions, etc + */ + +#define IN_SNMP_VARS_C + +#include +#if HAVE_STRING_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#include +#include +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "mibincl.h" +#include "snmp_client.h" +#include "default_store.h" +#include "ds_agent.h" +#include "callback.h" +#include "agent_callbacks.h" +#include "agent_registry.h" +#include "snmp_alarm.h" + +#include "snmpd.h" +#include "mibgroup/struct.h" +#include "mib_module_includes.h" + +#ifdef USING_AGENTX_SUBAGENT_MODULE +#include "agentx/subagent.h" +#include "agentx/client.h" +#endif + + +struct snmp_index { + struct variable_list varbind; /* or pointer to var_list ? */ + struct snmp_session *session; /* NULL implies unused ? */ + struct snmp_index *next_oid; + struct snmp_index *prev_oid; + struct snmp_index *next_idx; +} *snmp_index_head = NULL; +struct subtree *subtrees; + +int tree_compare(const struct subtree *ap, const struct subtree *bp) +{ + return snmp_oid_compare(ap->name,ap->namelen,bp->name,bp->namelen); +} + + + + /* + * Split the subtree into two at the specified point, + * returning the new (second) subtree + */ +struct subtree * +split_subtree(struct subtree *current, oid name[], int name_len ) +{ + struct subtree *new_sub, *ptr; + int i; + char *cp; + + if ( snmp_oid_compare(name, name_len, + current->end, current->end_len) > 0 ) + return NULL; /* Split comes after the end of this subtree */ + + new_sub = (struct subtree *)malloc(sizeof(struct subtree)); + if ( new_sub == NULL ) + return NULL; + memcpy(new_sub, current, sizeof(struct subtree)); + + /* Set up the point of division */ + memcpy(current->end, name, name_len*sizeof(oid)); + memcpy(new_sub->start, name, name_len*sizeof(oid)); + current->end_len = name_len; + new_sub->start_len = name_len; + + /* + * Split the variables between the two new subtrees + */ + i = current->variables_len; + current->variables_len = 0; + + for ( ; i > 0 ; i-- ) { + /* Note that the variable "name" field omits + the prefix common to the whole registration, + hence the strange comparison here */ + if ( snmp_oid_compare( new_sub->variables[0].name, + new_sub->variables[0].namelen, + name + current->namelen, + name_len - current->namelen ) >= 0 ) + break; /* All following variables belong to the second subtree */ + + current->variables_len++; + new_sub->variables_len--; + cp = (char *)new_sub->variables; + new_sub->variables = (struct variable *)(cp + new_sub->variables_width); + } + + /* Delegated trees should retain their variables regardless */ + if ( current->variables_len > 0 && + IS_DELEGATED((u_char)current->variables[0].type)) { + new_sub->variables_len = 1; + new_sub->variables = current->variables; + } + + /* Propogate this split down through any children */ + if ( current->children ) + new_sub->children = split_subtree(current->children, name, name_len); + + /* Retain the correct linking of the list */ + for ( ptr = current ; ptr != NULL ; ptr=ptr->children ) + ptr->next = new_sub; + for ( ptr = new_sub ; ptr != NULL ; ptr=ptr->children ) + ptr->prev = current; + for ( ptr = new_sub->next ; ptr != NULL ; ptr=ptr->children ) + ptr->prev = new_sub; + + return new_sub; +} + +int +load_subtree( struct subtree *new_sub ) +{ + struct subtree *tree1, *tree2, *new2; + struct subtree *prev, *next; + int res; + + if ( new_sub == NULL ) + return MIB_REGISTERED_OK; /* Degenerate case */ + + /* + * Find the subtree that contains the start of + * the new subtree (if any)... + */ + tree1 = find_subtree( new_sub->start, new_sub->start_len, NULL ); + /* + * ...and the subtree that follows the new one + * (NULL implies this is the final region covered) + */ + if ( tree1 == NULL ) + tree2 = find_subtree_next( new_sub->start, new_sub->start_len, NULL ); + else + tree2 = tree1->next; + + + /* + * Handle new subtrees that start in virgin territory. + */ + if ( tree1 == NULL ) { + new2 = NULL; + /* Is there any overlap with later subtrees ? */ + if ( tree2 && snmp_oid_compare( new_sub->end, new_sub->end_len, + tree2->start, tree2->start_len ) > 0 ) + new2 = split_subtree( new_sub, tree2->start, tree2->start_len ); + + /* + * Link the new subtree (less any overlapping region) + * with the list of existing registrations + */ + if ( tree2 ) { + new_sub->prev = tree2->prev; + tree2->prev = new_sub; + } + else + new_sub->prev = find_subtree_previous( new_sub->start, new_sub->start_len, NULL ); + + if ( new_sub->prev ) + new_sub->prev->next = new_sub; + else + subtrees = new_sub; + + new_sub->next = tree2; + + /* + * If there was any overlap, + * recurse to merge in the overlapping region + * (including anything that may follow the overlap) + */ + if ( new2 ) + return load_subtree( new2 ); + } + + else { + /* + * If the new subtree starts *within* an existing registration + * (rather than at the same point as it), then split the + * existing subtree at this point. + */ + if ( snmp_oid_compare( new_sub->start, new_sub->start_len, + tree1->start, tree1->start_len) != 0 ) + tree1 = split_subtree( tree1, new_sub->start, new_sub->start_len); + if ( tree1 == NULL ) + return MIB_REGISTRATION_FAILED; + + /* Now consider the end of this existing subtree: + * If it matches the new subtree precisely, + * simply merge the new one into the list of children + * If it includes the whole of the new subtree, + * split it at the appropriate point, and merge again + * + * If the new subtree extends beyond this existing region, + * split it, and recurse to merge the two parts. + */ + + switch ( snmp_oid_compare( new_sub->end, new_sub->end_len, + tree1->end, tree1->end_len)) { + + case -1: /* Existing subtree contains new one */ + (void) split_subtree( tree1, + new_sub->end, new_sub->end_len); + /* Fall Through */ + + case 0: /* The two trees match precisely */ + /* + * Note: This is the only point where the original + * registration OID ("name") is used + */ + prev = NULL; + next = tree1; + while ( next && next->namelen > new_sub->namelen ) { + prev = next; + next = next->children; + } + while ( next && next->namelen == new_sub->namelen && + next->priority < new_sub->priority ) { + prev = next; + next = next->children; + } + if ( next && next->namelen == new_sub->namelen && + next->priority == new_sub->priority ) + return MIB_DUPLICATE_REGISTRATION; + + if ( prev ) { + new_sub->children = next; + prev->children = new_sub; + new_sub->prev = prev->prev; + new_sub->next = prev->next; + } + else { + new_sub->children = next; + new_sub->prev = next->prev; + new_sub->next = next->next; + + for ( next = new_sub->next ; + next != NULL ; + next = next->children ) + next->prev = new_sub; + + for ( prev = new_sub->prev ; + prev != NULL ; + prev = prev->children ) + prev->next = new_sub; + } + break; + + case 1: /* New subtree contains the existing one */ + new2 = split_subtree( new_sub, + tree1->end, tree1->end_len); + res = load_subtree( new_sub ); + if ( res != MIB_REGISTERED_OK ) + return res; + return load_subtree( new2 ); + + } + + } + return 0; +} + + +int +register_mib_range(const char *moduleName, + struct variable *var, + size_t varsize, + size_t numvars, + oid *mibloc, + size_t mibloclen, + int priority, + int range_subid, + oid range_ubound, + struct snmp_session *ss) +{ + struct subtree *subtree, *sub2; + int res, i; + struct register_parameters reg_parms; + + subtree = (struct subtree *) malloc(sizeof(struct subtree)); + if ( subtree == NULL ) + return MIB_REGISTRATION_FAILED; + memset(subtree, 0, sizeof(struct subtree)); + + DEBUGMSGTL(("register_mib", "registering \"%s\" at ", moduleName)); + DEBUGMSGOID(("register_mib", mibloc, mibloclen)); + DEBUGMSG(("register_mib","\n")); + + /* + * Create the new subtree node being registered + */ + memcpy(subtree->name, mibloc, mibloclen*sizeof(oid)); + subtree->namelen = (u_char) mibloclen; + memcpy(subtree->start, mibloc, mibloclen*sizeof(oid)); + subtree->start_len = (u_char) mibloclen; + memcpy(subtree->end, mibloc, mibloclen*sizeof(oid)); + subtree->end[ mibloclen-1 ]++; /* XXX - or use 'variables' info ? */ + subtree->end_len = (u_char) mibloclen; + memcpy(subtree->label, moduleName, strlen(moduleName)+1); + if ( var ) { + subtree->variables = (struct variable *) malloc(varsize*numvars); + memcpy(subtree->variables, var, numvars*varsize); + subtree->variables_len = numvars; + subtree->variables_width = varsize; + } + subtree->priority = priority; + subtree->session = ss; + res = load_subtree(subtree); + + /* + * If registering a range, + * use the first subtree as a template + * for the rest of the range + */ + if (( res == MIB_REGISTERED_OK ) && ( range_subid != 0 )) { + for ( i = mibloc[range_subid-1] +1 ; i < (int)range_ubound ; i++ ) { + sub2 = (struct subtree *) malloc(sizeof(struct subtree)); + if ( sub2 == NULL ) { + unregister_mib_range( mibloc, mibloclen, priority, + range_subid, range_ubound); + return MIB_REGISTRATION_FAILED; + } + memcpy( sub2, subtree, sizeof(struct subtree)); + sub2->start[range_subid-1] = i; + sub2->end[ range_subid-1] = i; /* XXX - ???? */ + res = load_subtree(sub2); + if ( res != MIB_REGISTERED_OK ) { + unregister_mib_range( mibloc, mibloclen, priority, + range_subid, range_ubound); + return MIB_REGISTRATION_FAILED; + } + } + } + + + reg_parms.name = mibloc; + reg_parms.namelen = mibloclen; + reg_parms.priority = priority; + reg_parms.range_subid = range_subid; + reg_parms.range_ubound = range_ubound; + snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_OID, + ®_parms); + + return res; +} + +int +register_mib_priority(const char *moduleName, + struct variable *var, + size_t varsize, + size_t numvars, + oid *mibloc, + size_t mibloclen, + int priority) +{ + return register_mib_range( moduleName, var, varsize, numvars, + mibloc, mibloclen, priority, 0, 0, NULL ); +} + +int +register_mib(const char *moduleName, + struct variable *var, + size_t varsize, + size_t numvars, + oid *mibloc, + size_t mibloclen) +{ + return register_mib_priority( moduleName, var, varsize, numvars, + mibloc, mibloclen, DEFAULT_MIB_PRIORITY ); +} + + +void +unload_subtree( struct subtree *sub, struct subtree *prev) +{ + struct subtree *ptr; + + if ( prev != NULL ) { /* non-leading entries are easy */ + prev->children = sub->children; + return; + } + /* otherwise, we need to amend our neighbours as well */ + + if ( sub->children == NULL) { /* just remove this node completely */ + for (ptr = sub->prev ; ptr ; ptr=ptr->children ) + ptr->next = sub->next; + for (ptr = sub->next ; ptr ; ptr=ptr->children ) + ptr->prev = sub->prev; + return; + } + else { + for (ptr = sub->prev ; ptr ; ptr=ptr->children ) + ptr->next = sub->children; + for (ptr = sub->next ; ptr ; ptr=ptr->children ) + ptr->prev = sub->children; + return; + } +} + +int +unregister_mib_range( oid *name, size_t len, int priority, + int range_subid, oid range_ubound) +{ + struct subtree *list, *myptr; + struct subtree *prev, *child; /* loop through children */ + struct register_parameters reg_parms; + + list = find_subtree( name, len, subtrees ); + if ( list == NULL ) + return MIB_NO_SUCH_REGISTRATION; + + for ( child=list, prev=NULL; child != NULL; + prev=child, child=child->children ) { + if (( snmp_oid_compare( child->name, child->namelen, name, len) == 0 ) + && ( child->priority == priority )) + break; /* found it */ + } + if ( child == NULL ) + return MIB_NO_SUCH_REGISTRATION; + + unload_subtree( child, prev ); + myptr = child; /* remember this for later */ + + /* + * Now handle any occurances in the following subtrees, + * as a result of splitting this range. Due to the + * nature of the way such splits work, the first + * subtree 'slice' that doesn't refer to the given + * name marks the end of the original region. + * + * This should also serve to register ranges. + */ + + for ( list = myptr->next ; list != NULL ; list=list->next ) { + for ( child=list, prev=NULL; child != NULL; + prev=child, child=child->children ) { + if (( snmp_oid_compare( child->name, child->namelen, + name, len) == 0 ) + && ( child->priority == priority )) { + + unload_subtree( child, prev ); + free_subtree( child ); + break; + } + } + if ( child == NULL ) /* Didn't find the given name */ + break; + } + free_subtree( myptr ); + + reg_parms.name = name; + reg_parms.namelen = len; + reg_parms.priority = priority; + reg_parms.range_subid = range_subid; + reg_parms.range_ubound = range_ubound; + snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREGISTER_OID, + ®_parms); + + return MIB_UNREGISTERED_OK; +} + +int +unregister_mib_priority(oid *name, size_t len, int priority) +{ + return unregister_mib_range( name, len, priority, 0, 0 ); +} + +int +unregister_mib(oid *name, + size_t len) +{ + return unregister_mib_priority( name, len, DEFAULT_MIB_PRIORITY ); +} + +void +unregister_mibs_by_session (struct snmp_session *ss) +{ + struct subtree *list, *list2; + struct subtree *child, *prev, *next_child; + + for( list = subtrees; list != NULL; list = list2) { + list2 = list->next; + for ( child=list, prev=NULL; child != NULL; child=next_child ) { + + next_child = child->children; + if (( (ss->flags & SNMP_FLAGS_SUBSESSION) && child->session == ss ) || + (!(ss->flags & SNMP_FLAGS_SUBSESSION) && + child->session->subsession == ss )) { + unload_subtree( child, prev ); + free_subtree( child ); + } + else + prev = child; + } + } +} + + +struct subtree * +free_subtree(struct subtree *st) +{ + struct subtree *ret = NULL; + if ((snmp_oid_compare(st->name, st->namelen, st->start, st->start_len) == 0) + && (st->variables != NULL)) + free(st->variables); + if (st->next != NULL) + ret = st->next; + free(st); + return ret; +} + +/* in_a_view: determines if a given snmp_pdu is allowed to see a + given name/namelen OID pointer + name IN - name of var, OUT - name matched + nameLen IN -number of sub-ids in name, OUT - subid-is in matched name + pi IN - relevant auth info re PDU + cvp IN - relevant auth info re mib module +*/ + +int +in_a_view(oid *name, /* IN - name of var, OUT - name matched */ + size_t *namelen, /* IN -number of sub-ids in name*/ + struct snmp_pdu *pdu, /* IN - relevant auth info re PDU */ + int type) /* IN - variable type being checked */ +{ + + struct view_parameters view_parms; + view_parms.pdu = pdu; + view_parms.name = name; + if (namelen) + view_parms.namelen = *namelen; + else + view_parms.namelen = 0; + view_parms.errorcode = 0; + + if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW) + return 0; /* Enable bypassing of view-based access control */ + + /* check for v1 and counter64s, since snmpv1 doesn't support it */ + if (pdu->version == SNMP_VERSION_1 && type == ASN_COUNTER64) + return 5; + switch (pdu->version) { + case SNMP_VERSION_1: + case SNMP_VERSION_2c: + case SNMP_VERSION_3: + snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK, + &view_parms); + return view_parms.errorcode; + } + return 1; +} + +/* in_a_view: determines if a given snmp_pdu is ever going to be allowed to do + anynthing or if it's not going to ever be authenticated. */ +int +check_access(struct snmp_pdu *pdu) /* IN - pdu being checked */ +{ + struct view_parameters view_parms; + view_parms.pdu = pdu; + view_parms.name = 0; + view_parms.namelen = 0; + view_parms.errorcode = 0; + + if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW) + return 0; /* Enable bypassing of view-based access control */ + + switch (pdu->version) { + case SNMP_VERSION_1: + case SNMP_VERSION_2c: + case SNMP_VERSION_3: + snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, + SNMPD_CALLBACK_ACM_CHECK_INITIAL, + &view_parms); + return view_parms.errorcode; + } + return 1; +} + +/* lexicographical compare two object identifiers. + * Returns -1 if name1 < name2, + * 0 if name1 = name2, or name1 matches name2 for length of name2 + * 1 if name1 > name2 + * + * Note: snmp_oid_compare checks len2 before last return. + */ +int +compare_tree(const oid *in_name1, + size_t len1, + const oid *in_name2, + size_t len2) +{ + register int len, res; + register const oid * name1 = in_name1; + register const oid * name2 = in_name2; + + /* len = minimum of len1 and len2 */ + if (len1 < len2) + len = len1; + else + len = len2; + /* find first non-matching OID */ + while(len-- > 0){ + res = *(name1++) - *(name2++); + if (res < 0) + return -1; + if (res > 0) + return 1; + } + /* both OIDs equal up to length of shorter OID */ + if (len1 < len2) + return -1; + + /* name1 matches name2 for length of name2, or they are equal */ + return 0; +} + +struct subtree *find_subtree_previous(oid *name, + size_t len, + struct subtree *subtree) +{ + struct subtree *myptr, *previous = NULL; + + if ( subtree ) + myptr = subtree; + else + myptr = subtrees; /* look through everything */ + + for( ; myptr != NULL; previous = myptr, myptr = myptr->next) { + if (snmp_oid_compare(name, len, myptr->start, myptr->start_len) < 0) + return previous; + } + return previous; +} + +struct subtree *find_subtree_next(oid *name, + size_t len, + struct subtree *subtree) +{ + struct subtree *myptr = NULL; + + myptr = find_subtree_previous(name, len, subtree); + if ( myptr != NULL ) { + myptr = myptr->next; + while ( myptr && (myptr->variables == NULL || myptr->variables_len == 0) ) + myptr = myptr->next; + return myptr; + } + else if (subtree && snmp_oid_compare(name, len, subtree->start, subtree->start_len) < 0) + return subtree; + else + return NULL; +} + +struct subtree *find_subtree(oid *name, + size_t len, + struct subtree *subtree) +{ + struct subtree *myptr; + + myptr = find_subtree_previous(name, len, subtree); + if (myptr && snmp_oid_compare(name, len, myptr->end, myptr->end_len) < 0) + return myptr; + + return NULL; +} + +struct snmp_session *get_session_for_oid( oid *name, size_t len) +{ + struct subtree *myptr; + + myptr = find_subtree_previous(name, len, subtrees); + while ( myptr && myptr->variables == NULL ) + myptr = myptr->next; + + if ( myptr == NULL ) + return NULL; + else + return myptr->session; +} + + + +static struct subtree root_subtrees[] = { + { { 0 }, 1 }, /* ccitt */ + { { 1 }, 1 }, /* iso */ + { { 2 }, 1 } /* joint-ccitt-iso */ +}; + + +void setup_tree (void) +{ +#ifdef USING_AGENTX_SUBAGENT_MODULE + int role; + + role = ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE); + ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, MASTER_AGENT); +#endif + + register_mib("", NULL, 0, 0, + root_subtrees[0].name, root_subtrees[0].namelen); + register_mib("", NULL, 0, 0, + root_subtrees[1].name, root_subtrees[1].namelen); + register_mib("", NULL, 0, 0, + root_subtrees[2].name, root_subtrees[2].namelen); + + /* Support for 'static' subtrees (subtrees_old) has now been dropped */ + + /* No longer necessary to sort the mib tree - this is inherent in + the construction of the subtree structure */ + +#ifdef USING_AGENTX_SUBAGENT_MODULE + ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, role); +#endif +} + + /* + * Initial support for index allocation + */ +extern struct snmp_session *main_session; + +char * +register_string_index( oid *name, size_t name_len, char *cp ) +{ + struct variable_list varbind, *res; + + memset( &varbind, 0, sizeof(struct variable_list)); + varbind.type = ASN_OCTET_STR; + snmp_set_var_objid( &varbind, name, name_len ); + if ( cp != ANY_STRING_INDEX ) { + snmp_set_var_value( &varbind, (u_char *)cp, strlen(cp) ); + res = register_index( &varbind, ALLOCATE_THIS_INDEX, main_session ); + } + else + res = register_index( &varbind, ALLOCATE_ANY_INDEX, main_session ); + + if ( res == NULL ) + return NULL; + else + return (char *)res->val.string; +} + +int +register_int_index( oid *name, size_t name_len, int val ) +{ + struct variable_list varbind, *res; + + memset( &varbind, 0, sizeof(struct variable_list)); + varbind.type = ASN_INTEGER; + snmp_set_var_objid( &varbind, name, name_len ); + varbind.val.string = varbind.buf; + if ( val != ANY_INTEGER_INDEX ) { + varbind.val_len = sizeof(long); + *varbind.val.integer = val; + res = register_index( &varbind, ALLOCATE_THIS_INDEX, main_session ); + } + else + res = register_index( &varbind, ALLOCATE_ANY_INDEX, main_session ); + + if ( res == NULL ) + return -1; + else + return *res->val.integer; +} + +struct variable_list * +register_oid_index( oid *name, size_t name_len, + oid *value, size_t value_len ) +{ + struct variable_list varbind; + + memset( &varbind, 0, sizeof(struct variable_list)); + varbind.type = ASN_OBJECT_ID; + snmp_set_var_objid( &varbind, name, name_len ); + if ( value != ANY_OID_INDEX ) { + snmp_set_var_value( &varbind, (u_char*)value, value_len*sizeof(oid) ); + return( register_index( &varbind, ALLOCATE_THIS_INDEX, main_session )); + } + else + return( register_index( &varbind, ALLOCATE_ANY_INDEX, main_session )); +} + +struct variable_list* +register_index(struct variable_list *varbind, int flags, struct snmp_session *ss ) +{ + struct snmp_index *new_index, *idxptr, *idxptr2; + struct snmp_index *prev_oid_ptr, *prev_idx_ptr; + int res, res2, i; + +#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING) + if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT ) + return( agentx_register_index( ss, varbind, flags )); +#endif + /* Look for the requested OID entry */ + prev_oid_ptr = NULL; + prev_idx_ptr = NULL; + res = 1; + res2 = 1; + for( idxptr = snmp_index_head ; idxptr != NULL; + prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) { + if ((res = snmp_oid_compare(varbind->name, varbind->name_length, + idxptr->varbind.name, + idxptr->varbind.name_length)) <= 0 ) + break; + } + + /* Found the OID - now look at the registered indices */ + if ( res == 0 && idxptr ) { + if ( varbind->type != idxptr->varbind.type ) + return NULL; /* wrong type */ + + /* + * If we've been asked for an arbitrary new value, + * then find the end of the list. + * If we've been asked for any arbitrary value, + * then look for an unused entry, and use that. + * If there aren't any, continue as for new. + * Otherwise, locate the given value in the (sorted) + * list of already allocated values + */ + if ( flags & ALLOCATE_ANY_INDEX ) { + for(idxptr2 = idxptr ; idxptr2 != NULL; + prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { + if ( flags == ALLOCATE_ANY_INDEX && idxptr2->session == NULL ) { + idxptr2->session = ss ; + return &idxptr2->varbind; + } + } + } + else { + for(idxptr2 = idxptr ; idxptr2 != NULL; + prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { + switch ( varbind->type ) { + case ASN_INTEGER: + res2 = (*varbind->val.integer - *idxptr2->varbind.val.integer); + break; + case ASN_OCTET_STR: + i = SNMP_MIN(varbind->val_len, idxptr2->varbind.val_len); + res2 = memcmp(varbind->val.string, idxptr2->varbind.val.string, i); + break; + case ASN_OBJECT_ID: + res2 = snmp_oid_compare(varbind->val.objid, varbind->val_len/sizeof(oid), + idxptr2->varbind.val.objid, + idxptr2->varbind.val_len/sizeof(oid)); + break; + default: + return NULL; /* wrong type */ + } + if ( res2 <= 0 ) + break; + } + if ( res2 == 0 ) + return NULL; /* duplicate value */ + } + } + + /* + * OK - we've now located where the new entry needs to + * be fitted into the index registry tree + * To recap: + * 'prev_oid_ptr' points to the head of the OID index + * list prior to this one. If this is null, then + * it means that this is the first OID in the list. + * 'idxptr' points either to the head of this OID list, + * or the next OID (if this is a new OID request) + * These can be distinguished by the value of 'res'. + * + * 'prev_idx_ptr' points to the index entry that sorts + * immediately prior to the requested value (if any). + * If an arbitrary value is required, then this will + * point to the last allocated index. + * If this pointer is null, then either this is a new + * OID request, or the requested value is the first + * in the list. + * 'idxptr2' points to the next sorted index (if any) + * but is not actually needed any more. + * + * Clear? Good! + * I hope you've been paying attention. + * There'll be a test later :-) + */ + + /* + * We proceed by creating the new entry + * (by copying the entry provided) + */ + new_index = (struct snmp_index *)malloc( sizeof( struct snmp_index )); + if (new_index == NULL) + return NULL; + if (snmp_clone_var( varbind, &new_index->varbind ) != 0 ) { + free( new_index ); + return NULL; + } + new_index->session = ss; + + if ( varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX ) + new_index->varbind.val.string[new_index->varbind.val_len] = 0; + + /* + * If we've been given a value, then we can use that, but + * otherwise, we need to create a new value for this entry. + * Note that ANY_INDEX and NEW_INDEX are both covered by this + * test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?) + */ + if ( flags & ALLOCATE_ANY_INDEX ) { + if ( prev_idx_ptr ) { + if ( snmp_clone_var( &prev_idx_ptr->varbind, &new_index->varbind ) != 0 ) { + free( new_index ); + return NULL; + } + } + else + new_index->varbind.val.string = new_index->varbind.buf; + + switch ( varbind->type ) { + case ASN_INTEGER: + if ( prev_idx_ptr ) { + (*new_index->varbind.val.integer)++; + } + else + *(new_index->varbind.val.integer) = 1; + new_index->varbind.val_len = sizeof(long); + break; + case ASN_OCTET_STR: + if ( prev_idx_ptr ) { + i = new_index->varbind.val_len-1; + while ( new_index->varbind.buf[ i ] == 'z' ) { + new_index->varbind.buf[ i ] = 'a'; + i--; + if ( i < 0 ) { + i = new_index->varbind.val_len; + new_index->varbind.buf[ i ] = 'a'; + new_index->varbind.buf[ i+1 ] = 0; + } + } + new_index->varbind.buf[ i ]++; + } + else + strcpy((char *)new_index->varbind.buf, "aaaa"); + new_index->varbind.val_len = strlen((char *)new_index->varbind.buf); + break; + case ASN_OBJECT_ID: + if ( prev_idx_ptr ) { + i = prev_idx_ptr->varbind.val_len/sizeof(oid) -1; + while ( new_index->varbind.val.objid[ i ] == 255 ) { + new_index->varbind.val.objid[ i ] = 1; + i--; + if ( i == 0 && new_index->varbind.val.objid[0] == 2 ) { + new_index->varbind.val.objid[ 0 ] = 1; + i = new_index->varbind.val_len/sizeof(oid); + new_index->varbind.val.objid[ i ] = 0; + new_index->varbind.val_len += sizeof(oid); + } + } + new_index->varbind.val.objid[ i ]++; + } + else { + /* If the requested OID name is small enough, + * append another OID (1) and use this as the + * default starting value for new indexes. + */ + if ( (varbind->name_length+1) * sizeof(oid) <= 40 ) { + for ( i = 0 ; i < (int)varbind->name_length ; i++ ) + new_index->varbind.val.objid[i] = varbind->name[i]; + new_index->varbind.val.objid[varbind->name_length] = 1; + new_index->varbind.val_len = + (varbind->name_length+1) * sizeof(oid); + } + else { + /* Otherwise use '.1.1.1.1...' */ + i = 40/sizeof(oid); + if ( i > 4 ) + i = 4; + new_index->varbind.val_len = i * (sizeof(oid)); + for (i-- ; i>=0 ; i-- ) + new_index->varbind.val.objid[i] = 1; + } + } + break; + default: + free( new_index ); + return NULL; /* Index type not supported */ + } + } + + /* + * Right - we've set up the new entry. + * All that remains is to link it into the tree. + * There are a number of possible cases here, + * so watch carefully. + */ + if ( prev_idx_ptr ) { + new_index->next_idx = prev_idx_ptr->next_idx; + new_index->next_oid = prev_idx_ptr->next_oid; + prev_idx_ptr->next_idx = new_index; + } + else { + if ( res == 0 && idxptr ) { + new_index->next_idx = idxptr; + new_index->next_oid = idxptr->next_oid; + } + else { + new_index->next_idx = NULL; + new_index->next_oid = idxptr; + } + + if ( prev_oid_ptr ) { + while ( prev_oid_ptr ) { + prev_oid_ptr->next_oid = new_index; + prev_oid_ptr = prev_oid_ptr->next_idx; + } + } + else + snmp_index_head = new_index; + } + return &new_index->varbind; +} + + /* + * Release an allocated index, + * to allow it to be used elsewhere + */ +int +release_index(struct variable_list *varbind) +{ + return( unregister_index( varbind, TRUE, NULL )); +} + + /* + * Completely remove an allocated index, + * due to errors in the registration process. + */ +int +remove_index(struct variable_list *varbind, struct snmp_session *ss) +{ + return( unregister_index( varbind, FALSE, ss )); +} + +void +unregister_index_by_session(struct snmp_session *ss) +{ + struct snmp_index *idxptr, *idxptr2; + for(idxptr = snmp_index_head ; idxptr != NULL; idxptr = idxptr->next_oid) + for(idxptr2 = idxptr ; idxptr2 != NULL; idxptr2 = idxptr2->next_idx) + if ( idxptr2->session == ss ) + idxptr2->session = NULL; +} + + +int +unregister_index(struct variable_list *varbind, int remember, struct snmp_session *ss) +{ + struct snmp_index *idxptr, *idxptr2; + struct snmp_index *prev_oid_ptr, *prev_idx_ptr; + int res, res2, i; + +#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING) + if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT ) + return( agentx_unregister_index( ss, varbind )); +#endif + /* Look for the requested OID entry */ + prev_oid_ptr = NULL; + prev_idx_ptr = NULL; + res = 1; + res2 = 1; + for( idxptr = snmp_index_head ; idxptr != NULL; + prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) { + if ((res = snmp_oid_compare(varbind->name, varbind->name_length, + idxptr->varbind.name, + idxptr->varbind.name_length)) <= 0 ) + break; + } + + if ( res != 0 ) + return INDEX_ERR_NOT_ALLOCATED; + if ( varbind->type != idxptr->varbind.type ) + return INDEX_ERR_WRONG_TYPE; + + for(idxptr2 = idxptr ; idxptr2 != NULL; + prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) { + i = SNMP_MIN(varbind->val_len, idxptr2->varbind.val_len); + res2 = memcmp(varbind->val.string, idxptr2->varbind.val.string, i); + if ( res2 <= 0 ) + break; + } + if ( res2 != 0 ) + return INDEX_ERR_NOT_ALLOCATED; + if ( ss != idxptr2->session ) + return INDEX_ERR_WRONG_SESSION; + + /* + * If this is a "normal" index unregistration, + * mark the index entry as unused, but leave + * it in situ. This allows differentiation + * between ANY_INDEX and NEW_INDEX + */ + if ( remember ) { + idxptr2->session = NULL; /* Unused index */ + return SNMP_ERR_NOERROR; + } + /* + * If this is a failed attempt to register a + * number of indexes, the successful ones + * must be removed completely. + */ + if ( prev_idx_ptr ) { + prev_idx_ptr->next_idx = idxptr2->next_idx; + } + else if ( prev_oid_ptr ) { + if ( idxptr2->next_idx ) /* Use p_idx_ptr as a temp variable */ + prev_idx_ptr = idxptr2->next_idx; + else + prev_idx_ptr = idxptr2->next_oid; + while ( prev_oid_ptr ) { + prev_oid_ptr->next_oid = prev_idx_ptr; + prev_oid_ptr = prev_oid_ptr->next_idx; + } + } + else { + if ( idxptr2->next_idx ) + snmp_index_head = idxptr2->next_idx; + else + snmp_index_head = idxptr2->next_oid; + } + snmp_free_var( (struct variable_list *)idxptr2 ); + return SNMP_ERR_NOERROR; +} + + +void dump_registry( void ) +{ + struct subtree *myptr, *myptr2; + struct snmp_index *idxptr, *idxptr2; + char start_oid[SPRINT_MAX_LEN]; + char end_oid[SPRINT_MAX_LEN]; + + for( myptr = subtrees ; myptr != NULL; myptr = myptr->next) { + sprint_objid(start_oid, myptr->start, myptr->start_len); + sprint_objid(end_oid, myptr->end, myptr->end_len); + printf("%c %s - %s %c\n", + ( myptr->variables ? ' ' : '(' ), + start_oid, end_oid, + ( myptr->variables ? ' ' : ')' )); + for( myptr2 = myptr ; myptr2 != NULL; myptr2 = myptr2->children) { + if ( myptr2->label && myptr2->label[0] ) + printf("\t%s\n", myptr2->label); + } + } + + if ( snmp_index_head ) + printf("\nIndex Allocations:\n"); + for( idxptr = snmp_index_head ; idxptr != NULL; idxptr = idxptr->next_oid) { + sprint_objid(start_oid, idxptr->varbind.name, idxptr->varbind.name_length); + printf("%s indexes:\n", start_oid); + for( idxptr2 = idxptr ; idxptr2 != NULL; idxptr2 = idxptr2->next_idx) { + switch( idxptr2->varbind.type ) { + case ASN_INTEGER: + printf(" %c %ld %c\n", + ( idxptr2->session ? ' ' : '(' ), + *idxptr2->varbind.val.integer, + ( idxptr2->session ? ' ' : ')' )); + break; + case ASN_OCTET_STR: + printf(" %c %s %c\n", + ( idxptr2->session ? ' ' : '(' ), + idxptr2->varbind.val.string, + ( idxptr2->session ? ' ' : ')' )); + break; + case ASN_OBJECT_ID: + sprint_objid(end_oid, idxptr2->varbind.val.objid, + idxptr2->varbind.val_len/sizeof(oid)); + printf(" %c %s %c\n", + ( idxptr2->session ? ' ' : '(' ), + end_oid, + ( idxptr2->session ? ' ' : ')' )); + break; + default: + printf("unsupported type (%d)\n", + idxptr2->varbind.type); + } + } + } +} + +#ifdef TESTING +struct variable_list varbind; +struct snmp_session main_sess, *main_session=&main_sess; + +void +test_string_register( int n, char *cp ) +{ + varbind.name[4] = n; + if (register_string_index(varbind.name, varbind.name_length, cp) == NULL) + printf("allocating %s failed\n", cp); +} + +void +test_int_register( int n, int val ) +{ + varbind.name[4] = n; + if (register_int_index( varbind.name, varbind.name_length, val ) == -1 ) + printf("allocating %d/%d failed\n", n, val); +} + +void +test_oid_register( int n, int subid ) +{ + struct variable_list *res; + + varbind.name[4] = n; + if ( subid != -1 ) { + varbind.val.objid[5] = subid; + res = register_oid_index(varbind.name, varbind.name_length, + varbind.val.objid, + varbind.val_len/sizeof(oid) ); + } + else + res = register_oid_index(varbind.name, varbind.name_length, NULL, 0); + + if (res == NULL ) + printf("allocating %d/%d failed\n", n, subid); +} + +void +main( int argc, char argv[] ) +{ + oid name[] = { 1, 2, 3, 4, 0 }; + int i; + + memset( &varbind, 0, sizeof(struct variable_list)); + snmp_set_var_objid( &varbind, name, 5 ); + varbind.type = ASN_OCTET_STR; + /* + * Test index structure linking: + * a) sorted by OID + */ + test_string_register( 20, "empty OID" ); + test_string_register( 10, "first OID" ); + test_string_register( 40, "last OID" ); + test_string_register( 30, "middle OID" ); + + /* + * b) sorted by index value + */ + test_string_register( 25, "eee: empty IDX" ); + test_string_register( 25, "aaa: first IDX" ); + test_string_register( 25, "zzz: last IDX" ); + test_string_register( 25, "mmm: middle IDX" ); + printf("This next one should fail....\n"); + test_string_register( 25, "eee: empty IDX" ); /* duplicate */ + printf("done\n"); + + /* + * c) test initial index linking + */ + test_string_register( 5, "eee: empty initial IDX" ); + test_string_register( 5, "aaa: replace initial IDX" ); + + /* + * Did it all work? + */ + dump_registry(); + unregister_index_by_session( main_session ); + /* + * Now test index allocation + * a) integer values + */ + test_int_register( 110, -1 ); /* empty */ + test_int_register( 110, -1 ); /* append */ + test_int_register( 110, 10 ); /* append exact */ + printf("This next one should fail....\n"); + test_int_register( 110, 10 ); /* exact duplicate */ + printf("done\n"); + test_int_register( 110, -1 ); /* append */ + test_int_register( 110, 5 ); /* insert exact */ + + /* + * b) string values + */ + test_string_register( 120, NULL ); /* empty */ + test_string_register( 120, NULL ); /* append */ + test_string_register( 120, "aaaz" ); + test_string_register( 120, NULL ); /* minor rollover */ + test_string_register( 120, "zzzz" ); + test_string_register( 120, NULL ); /* major rollover */ + + /* + * c) OID values + */ + + test_oid_register( 130, -1 ); /* empty */ + test_oid_register( 130, -1 ); /* append */ + + varbind.val_len = varbind.name_length*sizeof(oid); + memcpy( varbind.buf, varbind.name, varbind.val_len); + varbind.val.objid = (oid*) varbind.buf; + varbind.val_len += sizeof(oid); + + test_oid_register( 130, 255 ); /* append exact */ + test_oid_register( 130, -1 ); /* minor rollover */ + test_oid_register( 130, 100 ); /* insert exact */ + printf("This next one should fail....\n"); + test_oid_register( 130, 100 ); /* exact duplicate */ + printf("done\n"); + + varbind.val.objid = (oid*)varbind.buf; + for ( i=0; i<6; i++ ) + varbind.val.objid[i]=255; + varbind.val.objid[0]=1; + test_oid_register( 130, 255 ); /* set up rollover */ + test_oid_register( 130, -1 ); /* medium rollover */ + + for ( i=0; i<6; i++ ) + varbind.val.objid[i]=255; + varbind.val.objid[0]=2; + test_oid_register( 130, 255 ); /* set up rollover */ + test_oid_register( 130, -1 ); /* major rollover */ + + /* + * Did it all work? + */ + dump_registry(); + + /* + * Test the various "invalid" requests + * (unsupported types, mis-matched types, etc) + */ + printf("The rest of these should fail....\n"); + test_oid_register( 110, -1 ); + test_oid_register( 110, 100 ); + test_oid_register( 120, -1 ); + test_oid_register( 120, 100 ); + test_string_register( 110, NULL ); + test_string_register( 110, "aaaa" ); + test_string_register( 130, NULL ); + test_string_register( 130, "aaaa" ); + test_int_register( 120, -1 ); + test_int_register( 120, 1 ); + test_int_register( 130, -1 ); + test_int_register( 130, 1 ); + printf("done - this dump should be the same as before\n"); + dump_registry(); +} +#endif diff --git a/packages/net/snmp/agent/current/src/agent_trap.c b/packages/net/snmp/agent/current/src/agent_trap.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/agent_trap.c @@ -0,0 +1,607 @@ +//========================================================================== +// +// ./agent/current/src/agent_trap.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* agent_trap.c: define trap generation routines for mib modules, etc, + to use */ + +#include + +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_SYS_SOCKET_H +#include +#elif HAVE_WINSOCK_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "snmp_client.h" +#include "snmp.h" +#include "system.h" +#include "read_config.h" +#include "snmp_debug.h" + +struct trap_sink { + struct snmp_session *sesp; + struct trap_sink *next; + int pdutype; + int version; +}; + +struct trap_sink *sinks = NULL; + +extern struct timeval starttime; + +#define OID_LENGTH(x) (sizeof(x)/sizeof(x[0])) + +oid objid_enterprisetrap[] = { EXTENSIBLEMIB, 251 }; +oid version_id[] = { EXTENSIBLEMIB, AGENTID, OSTYPE }; +int enterprisetrap_len = OID_LENGTH( objid_enterprisetrap ); +int version_id_len = OID_LENGTH( version_id ); + +#define SNMPV2_TRAPS_PREFIX SNMP_OID_SNMPMODULES,1,1,5 +oid cold_start_oid[] = { SNMPV2_TRAPS_PREFIX, 1 }; /* SNMPv2-MIB */ +oid warm_start_oid[] = { SNMPV2_TRAPS_PREFIX, 2 }; /* SNMPv2-MIB */ +oid link_down_oid[] = { SNMPV2_TRAPS_PREFIX, 3 }; /* IF-MIB */ +oid link_up_oid[] = { SNMPV2_TRAPS_PREFIX, 4 }; /* IF-MIB */ +oid auth_fail_oid[] = { SNMPV2_TRAPS_PREFIX, 5 }; /* SNMPv2-MIB */ +oid egp_xxx_oid[] = { SNMPV2_TRAPS_PREFIX, 99 }; /* ??? */ + +#define SNMPV2_TRAP_OBJS_PREFIX SNMP_OID_SNMPMODULES,1,1,4 +oid snmptrap_oid[] = { SNMPV2_TRAP_OBJS_PREFIX, 1, 0 }; +oid snmptrapenterprise_oid[] = { SNMPV2_TRAP_OBJS_PREFIX, 3, 0 }; +oid sysuptime_oid[] = { SNMP_OID_MIB2,1,3,0 }; +int snmptrap_oid_len = OID_LENGTH(snmptrap_oid); +int snmptrapenterprise_oid_len = OID_LENGTH(snmptrapenterprise_oid); +int sysuptime_oid_len = OID_LENGTH(sysuptime_oid); + + +#define SNMP_AUTHENTICATED_TRAPS_ENABLED 1 +#define SNMP_AUTHENTICATED_TRAPS_DISABLED 2 + +int snmp_enableauthentraps = SNMP_AUTHENTICATED_TRAPS_DISABLED; +char *snmp_trapcommunity = NULL; + +/* Prototypes */ + /* +static int create_v1_trap_session (const char *, u_short, const char *); +static int create_v2_trap_session (const char *, u_short, const char *); +static int create_v2_inform_session (const char *, u_short, const char *); +static void free_trap_session (struct trap_sink *sp); +static void send_v1_trap (struct snmp_session *, int, int); +static void send_v2_trap (struct snmp_session *, int, int, int); + */ + + + /******************* + * + * Trap session handling + * + *******************/ +int add_trap_session( struct snmp_session *ss, int pdutype, int version ) +{ + struct trap_sink *new_sink = + (struct trap_sink *) malloc (sizeof (*new_sink)); + if ( new_sink == NULL ) + return 0; + + new_sink->sesp = ss; + new_sink->pdutype = pdutype; + new_sink->version = version; + new_sink->next = sinks; + sinks = new_sink; + return 1; +} + +int create_trap_session (char *sink, u_short sinkport, + char *com, + int version, int pdutype) +{ + struct snmp_session session, *sesp; + + memset (&session, 0, sizeof (struct snmp_session)); + session.peername = sink; + session.version = version; + if (com) { + session.community = (u_char *)com; + session.community_len = strlen (com); + } + session.remote_port = sinkport; + sesp = snmp_open (&session); + + if (sesp) { + return( add_trap_session( sesp, pdutype, version )); + } + + /* diagnose snmp_open errors with the input struct snmp_session pointer */ + snmp_sess_perror("snmpd: create_trap_session", &session); + return 0; +} + +static int create_v1_trap_session (char *sink, u_short sinkport, + char *com) +{ + return create_trap_session( sink, sinkport, com, + SNMP_VERSION_1, SNMP_MSG_TRAP ); +} + +static int create_v2_trap_session (char *sink, u_short sinkport, + char *com) +{ + return create_trap_session( sink, sinkport, com, + SNMP_VERSION_2c, SNMP_MSG_TRAP2 ); +} + +static int create_v2_inform_session (char *sink, u_short sinkport, + char *com) +{ + return create_trap_session( sink, sinkport, com, + SNMP_VERSION_2c, SNMP_MSG_INFORM ); +} + + +static void free_trap_session (struct trap_sink *sp) +{ + snmp_close(sp->sesp); + free (sp); +} + + +void snmpd_free_trapsinks (void) +{ + struct trap_sink *sp = sinks; + while (sp) { + sinks = sinks->next; + free_trap_session(sp); + sp = sinks; + } +} + + /******************* + * + * Trap handling + * + *******************/ + +void send_enterprise_trap_vars (int trap, + int specific, + oid *enterprise, int enterprise_length, + struct variable_list *vars) +{ + struct variable_list uptime_var, snmptrap_var, enterprise_var; + struct variable_list *v2_vars, *last_var=NULL; + struct snmp_pdu *template_pdu, *pdu; + struct timeval now; + long uptime; + struct sockaddr_in *pduIp; + struct trap_sink *sink; + oid temp_oid[MAX_OID_LEN]; + + /* + * Initialise SNMPv2 required variables + */ + gettimeofday(&now, NULL); + uptime = calculate_time_diff(&now, &starttime); + memset (&uptime_var, 0, sizeof (struct variable_list)); + snmp_set_var_objid( &uptime_var, sysuptime_oid, OID_LENGTH(sysuptime_oid)); + snmp_set_var_value( &uptime_var, (u_char *)&uptime, sizeof(uptime) ); + uptime_var.type = ASN_TIMETICKS; + uptime_var.next_variable = &snmptrap_var; + + memset (&snmptrap_var, 0, sizeof (struct variable_list)); + snmp_set_var_objid( &snmptrap_var, snmptrap_oid, OID_LENGTH(snmptrap_oid)); + /* value set later .... */ + snmptrap_var.type = ASN_OBJECT_ID; + if ( vars ) + snmptrap_var.next_variable = vars; + else + snmptrap_var.next_variable = &enterprise_var; + + /* find end of provided varbind list, + ready to append the enterprise info if necessary */ + last_var = vars; + while ( last_var && last_var->next_variable ) + last_var = last_var->next_variable; + + memset (&enterprise_var, 0, sizeof (struct variable_list)); + snmp_set_var_objid( &enterprise_var, + snmptrapenterprise_oid, OID_LENGTH(snmptrapenterprise_oid)); + snmp_set_var_value( &enterprise_var, (u_char *)enterprise, enterprise_length*sizeof(oid)); + enterprise_var.type = ASN_OBJECT_ID; + enterprise_var.next_variable = NULL; + + v2_vars = &uptime_var; + + /* + * Create a template PDU, ready for sending + */ + template_pdu = snmp_pdu_create( SNMP_MSG_TRAP ); + if ( template_pdu == NULL ) + return; + template_pdu->trap_type = trap; + template_pdu->specific_type = specific; + if ( snmp_clone_mem((void **)&template_pdu->enterprise, + enterprise, enterprise_length*sizeof(oid))) { + snmp_free_pdu( template_pdu ); + return; + } + template_pdu->enterprise_length = enterprise_length; + template_pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; + pduIp = (struct sockaddr_in *)&template_pdu->agent_addr; + pduIp->sin_family = AF_INET; + pduIp->sin_addr.s_addr = get_myaddr(); + template_pdu->time = uptime; + + /* + * Now use the parameters to determine + * which v2 variables are needed, + * and what values they should take. + */ + switch ( trap ) { + case -1: /* + * SNMPv2 only + * Check to see whether the variables provided + * are sufficient for SNMPv2 notifications + */ + if (vars && snmp_oid_compare(vars->name, vars->name_length, + sysuptime_oid, OID_LENGTH(sysuptime_oid)) == 0 ) + v2_vars = vars; + else + if (vars && snmp_oid_compare(vars->name, vars->name_length, + snmptrap_oid, OID_LENGTH(snmptrap_oid)) == 0 ) + uptime_var.next_variable = vars; + else { + /* Hmmm... we don't seem to have a value - oops! */ + snmptrap_var.next_variable = vars; + } + last_var = NULL; /* Don't need enterprise info */ + break; + + /* "Standard" SNMPv1 traps */ + + case SNMP_TRAP_COLDSTART: + snmp_set_var_value( &snmptrap_var, + (u_char *)cold_start_oid, + sizeof(cold_start_oid)); + break; + case SNMP_TRAP_WARMSTART: + snmp_set_var_value( &snmptrap_var, + (u_char *)warm_start_oid, + sizeof(warm_start_oid)); + break; + case SNMP_TRAP_LINKDOWN: + snmp_set_var_value( &snmptrap_var, + (u_char *)link_down_oid, + sizeof(link_down_oid)); + break; + case SNMP_TRAP_LINKUP: + snmp_set_var_value( &snmptrap_var, + (u_char *)link_up_oid, + sizeof(link_up_oid)); + break; + case SNMP_TRAP_AUTHFAIL: + if (snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) + return; + snmp_set_var_value( &snmptrap_var, + (u_char *)auth_fail_oid, + sizeof(auth_fail_oid)); + break; + case SNMP_TRAP_EGPNEIGHBORLOSS: + snmp_set_var_value( &snmptrap_var, + (u_char *)egp_xxx_oid, + sizeof(egp_xxx_oid)); + break; + + case SNMP_TRAP_ENTERPRISESPECIFIC: + memcpy( &temp_oid, + (char *)enterprise, + (enterprise_length)*sizeof(oid)); + temp_oid[ enterprise_length ] = 0; + temp_oid[ enterprise_length+1 ] = specific; + snmp_set_var_value( &snmptrap_var, + (u_char *)&temp_oid, + (enterprise_length+2)*sizeof(oid)); + snmptrap_var.next_variable = vars; + last_var = NULL; /* Don't need version info */ + break; + } + + + /* + * Now loop through the list of trap sinks, + * sending an appropriately formatted PDU to each + */ + for ( sink = sinks ; sink ; sink=sink->next ) { + if ( sink->version == SNMP_VERSION_1 && trap == -1 ) + continue; /* Skip v1 sinks for v2 only traps */ + template_pdu->version = sink->version; + template_pdu->command = sink->pdutype; + if ( sink->version != SNMP_VERSION_1 ) { + template_pdu->variables = v2_vars; + if ( last_var ) + last_var->next_variable = &enterprise_var; + } + else + template_pdu->variables = vars; + + pdu = snmp_clone_pdu( template_pdu ); + pdu->sessid = sink->sesp->sessid; /* AgentX only ? */ + if ( snmp_send( sink->sesp, pdu) == 0 ) { + snmp_sess_perror ("snmpd: send_trap", sink->sesp); + snmp_free_pdu( pdu ); + } + else { + snmp_increment_statistic(STAT_SNMPOUTTRAPS); + snmp_increment_statistic(STAT_SNMPOUTPKTS); + } + + if ( sink->version != SNMP_VERSION_1 && last_var ) + last_var->next_variable = NULL; + } + + /* Ensure we don't free anything we shouldn't */ + if ( last_var ) + last_var->next_variable = NULL; + template_pdu->variables = NULL; + snmp_free_pdu( template_pdu ); +} + +void send_trap_vars (int trap, + int specific, + struct variable_list *vars) +{ + if ( trap == SNMP_TRAP_ENTERPRISESPECIFIC ) + send_enterprise_trap_vars( trap, specific, objid_enterprisetrap, + OID_LENGTH(objid_enterprisetrap), vars ); + else + send_enterprise_trap_vars( trap, specific, version_id, + OID_LENGTH(version_id), vars ); +} + +void send_easy_trap (int trap, + int specific) +{ + send_trap_vars( trap, specific, NULL ); +} + +void send_v2trap ( struct variable_list *vars) +{ + send_trap_vars( -1, -1, vars ); +} + +void +send_trap_pdu(struct snmp_pdu *pdu) +{ + send_trap_vars( -1, -1, pdu->variables ); +} + + + + /******************* + * + * Config file handling + * + *******************/ + +void snmpd_parse_config_authtrap(const char *token, + char *cptr) +{ + int i; + + i = atoi(cptr); + if ( i == 0 ) { + if ( !strcmp( cptr, "enable" )) + i = SNMP_AUTHENTICATED_TRAPS_ENABLED; + else if ( !strcmp( cptr, "disable" )) + i = SNMP_AUTHENTICATED_TRAPS_DISABLED; + } + if (i < 1 || i > 2) + config_perror("authtrapenable must be 1 or 2"); + else + snmp_enableauthentraps = i; +} + +void snmpd_parse_config_trapsink(const char *token, + char *cptr) +{ + char tmpbuf[1024]; + char *sp, *cp, *pp = NULL; + u_short sinkport; + + if (!snmp_trapcommunity) snmp_trapcommunity = strdup("public"); + sp = strtok(cptr, " \t\n"); + cp = strtok(NULL, " \t\n"); + if (cp) pp = strtok(NULL, " \t\n"); + if (cp && pp) { + sinkport = atoi(pp); + if ((sinkport < 1) || (sinkport > 0xffff)) { + config_perror("trapsink port out of range"); + sinkport = SNMP_TRAP_PORT; + } + } else { + sinkport = SNMP_TRAP_PORT; + } + if (create_v1_trap_session(sp, sinkport, + cp ? cp : snmp_trapcommunity) == 0) { + sprintf(tmpbuf,"cannot create trapsink: %s", cptr); + config_perror(tmpbuf); + } +} + + +void +snmpd_parse_config_trap2sink(const char *word, char *cptr) +{ + char tmpbuf[1024]; + char *sp, *cp, *pp = NULL; + u_short sinkport; + + if (!snmp_trapcommunity) snmp_trapcommunity = strdup("public"); + sp = strtok(cptr, " \t\n"); + cp = strtok(NULL, " \t\n"); + if (cp) pp = strtok(NULL, " \t\n"); + if (cp && pp) { + sinkport = atoi(pp); + if ((sinkport < 1) || (sinkport > 0xffff)) { + config_perror("trapsink port out of range"); + sinkport = SNMP_TRAP_PORT; + } + } else { + sinkport = SNMP_TRAP_PORT; + } + if (create_v2_trap_session(sp, sinkport, + cp ? cp : snmp_trapcommunity) == 0) { + sprintf(tmpbuf,"cannot create trap2sink: %s", cptr); + config_perror(tmpbuf); + } +} + +void +snmpd_parse_config_informsink(const char *word, char *cptr) +{ + char tmpbuf[1024]; + char *sp, *cp, *pp = NULL; + u_short sinkport; + + if (!snmp_trapcommunity) snmp_trapcommunity = strdup("public"); + sp = strtok(cptr, " \t\n"); + cp = strtok(NULL, " \t\n"); + if (cp) pp = strtok(NULL, " \t\n"); + if (cp && pp) { + sinkport = atoi(pp); + if ((sinkport < 1) || (sinkport > 0xffff)) { + config_perror("trapsink port out of range"); + sinkport = SNMP_TRAP_PORT; + } + } else { + sinkport = SNMP_TRAP_PORT; + } + if (create_v2_inform_session(sp, sinkport, + cp ? cp : snmp_trapcommunity) == 0) { + sprintf(tmpbuf,"cannot create informsink: %s", cptr); + config_perror(tmpbuf); + } +} + +void +snmpd_parse_config_trapcommunity(const char *word, char *cptr) +{ + if (snmp_trapcommunity) free(snmp_trapcommunity); + snmp_trapcommunity = malloc (strlen(cptr)+1); + copy_word(cptr, snmp_trapcommunity); +} + +void snmpd_free_trapcommunity (void) +{ + if (snmp_trapcommunity) { + free(snmp_trapcommunity); + snmp_trapcommunity = NULL; + } +} diff --git a/packages/net/snmp/agent/current/src/kernel.c b/packages/net/snmp/agent/current/src/kernel.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/kernel.c @@ -0,0 +1,279 @@ +//========================================================================== +// +// ./agent/current/src/kernel.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ + +/* + * 13 Jun 91 wsak (wk0x@andrew) added mips support + */ + +#include + +#ifdef CAN_USE_NLIST + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_STRING_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_KVM_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "snmp_logging.h" +#include "default_store.h" + +#include "kernel.h" +#include "ds_agent.h" + +#ifndef NULL +#define NULL 0 +#endif + + +#if HAVE_KVM_H +kvm_t *kd; + +void +init_kmem(const char *file) +{ +#if HAVE_KVM_OPENFILES + char err[4096]; + kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, err); + if (kd == NULL && !ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) { + snmp_log(LOG_CRIT, "init_kmem: kvm_openfiles failed: %s\n", err); + exit(1); + } +#else + kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); + if (!kd && !ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) { + snmp_log(LOG_CRIT, "init_kmem: kvm_open failed: %s\n", strerror(errno)); + exit(1); + } +#endif /* HAVE_KVM_OPENFILES */ +} + + +/* + * klookup: + * + * It seeks to the location off in kmem + * It does a read into target of siz bytes. + * + * Return 0 on failure and 1 on sucess. + * + */ + + +int +klookup(unsigned long off, + char *target, + int siz) +{ + int result; + if (kd == NULL) return 0; + result = kvm_read(kd, off, target, siz); + if (result != siz) { +#if HAVE_KVM_OPENFILES + snmp_log(LOG_ERR,"kvm_read(*, %lx, %p, %d) = %d: %s\n", off, target, siz, + result, kvm_geterr(kd)); +#else + snmp_log(LOG_ERR,"kvm_read(*, %lx, %p, %d) = %d: ", off, target, siz, + result); + snmp_log_perror("klookup"); +#endif + return 0; + } + return 1; +} + +#else /* HAVE_KVM_H */ + +static off_t klseek (off_t); +static int klread (char *, int); +int swap, mem, kmem; + +void +init_kmem(const char *file) +{ + kmem = open(file, O_RDONLY); + if (kmem < 0 && !ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)){ + snmp_log_perror(file); + exit(1); + } + fcntl(kmem,F_SETFD,1); + mem = open("/dev/mem",O_RDONLY); + if (mem < 0 && !ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)){ + snmp_log_perror("/dev/mem"); + exit(1); + } + fcntl(mem,F_SETFD,1); +#ifdef DMEM_LOC + swap = open(DMEM_LOC,O_RDONLY); + if (swap < 0 && !ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)){ + snmp_log_perror(DMEM_LOC); + exit(1); + } + fcntl(swap,F_SETFD,1); +#endif +} + + +/* + * Seek into the kernel for a value. + */ +static off_t +klseek(off_t base) +{ + return (lseek(kmem, (off_t)base, SEEK_SET)); +} + + +/* + * Read from the kernel + */ +static int +klread(char *buf, + int buflen) +{ + return (read(kmem, buf, buflen)); +} + + +/* + * klookup: + * + * It seeks to the location off in kmem + * It does a read into target of siz bytes. + * + * Return 0 on failure and 1 on sucess. + * + */ + + +int +klookup(unsigned long off, + char *target, + int siz) +{ + long retsiz; + + if (kmem < 0) return 0; + + if ((retsiz = klseek((off_t) off)) != off) { + snmp_log(LOG_ERR, "klookup(%lx, %p, %d): ", off, target, siz); + snmp_log_perror("klseek"); +#ifdef EXIT_ON_BAD_KLREAD + exit(1); +#endif + return (0); + } + if ((retsiz = klread(target, siz)) != siz ) { + if (snmp_get_do_debugging()) { + /* these happen too often on too many architectures to print them + unless we're in debugging mode. People get very full log files. */ + snmp_log(LOG_ERR, "klookup(%lx, %p, %d): ", off, target, siz); + snmp_log_perror("klread"); + } +#ifdef EXIT_ON_BAD_KLREAD + exit(1); +#endif + return(0); + } + return (1); +} + +#endif /* HAVE_KVM_H */ + +#endif /* CAN_USE_NLIST */ diff --git a/packages/net/snmp/agent/current/src/mib_modules.c b/packages/net/snmp/agent/current/src/mib_modules.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mib_modules.c @@ -0,0 +1,131 @@ +//========================================================================== +// +// ./agent/current/src/mib_modules.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* wrapper to call all the mib module initialization functions */ + +#include "mib_module_config.h" +#include +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "system.h" +#include "read_config.h" +#include "snmp.h" +#include "mib.h" +#include "m2m.h" +#include "snmp_vars.h" +#include "agent_read_config.h" +#include "snmpv3.h" +#include "callback.h" +#include "snmp_alarm.h" +#include "default_store.h" +#include "tools.h" + +#include "mibgroup/struct.h" +#include "mib_modules.h" +#include "mib_module_includes.h" +#ifdef USING_AGENTX_SUBAGENT_MODULE +#include "mibgroup/agentx/subagent.h" +#endif + +void +init_mib_modules(void) { +# include "mib_module_inits.h" +} diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/dot3.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/dot3.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/dot3.c @@ -0,0 +1,541 @@ +//========================================================================== +// +// snmp/snmpagent/current/src/mibgroup/mibII/dot3.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +/* This should always be included first before anything else */ +#include + + +/* minimal include directives */ +#include "mibincl.h" +#include "mibgroup/util_funcs.h" +#include "mibgroup/mibII/dot3.h" + +#include + +// Get info about the device +#include + +#include + +#ifdef CYGBLD_DEVS_ETH_DEVICE_H +#include CYGBLD_DEVS_ETH_DEVICE_H +#endif + +#ifdef CYGBLD_DEVS_ETH_INFO_H +#include CYGBLD_DEVS_ETH_INFO_H +#endif + +/* + * dot3_variables_oid: + * this is the top level oid that we want to register under. This + * is essentially a prefix, with the suffix appearing in the + * variable below. + */ + +oid dot3_variables_oid[] = { 1,3,6,1,2,1,10,7 }; + + +extern struct ifnet_head ifnet; + + +/* + * variable4 dot3_variables: + * this variable defines function callbacks and type return information + * for the dot3 mib section + */ +struct variable4 dot3_variables[] = { +/* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +#define DOT3STATSINDEX 3 + { DOT3STATSINDEX , ASN_INTEGER , RONLY , var_dot3StatsTable, 3, { 2,1,1 } }, +#define DOT3STATSALIGNMENTERRORS 4 + { DOT3STATSALIGNMENTERRORS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,2 } }, +#define DOT3STATSFCSERRORS 5 + { DOT3STATSFCSERRORS , ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,3 } }, +#define DOT3STATSSINGLECOLLISIONFRAMES 6 + { DOT3STATSSINGLECOLLISIONFRAMES, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,4 } }, +#define DOT3STATSMULTIPLECOLLISIONFRAMES 7 + { DOT3STATSMULTIPLECOLLISIONFRAMES, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,5 } }, +#define DOT3STATSSQETESTERRORS 8 + { DOT3STATSSQETESTERRORS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,6 } }, +#define DOT3STATSDEFERREDTRANSMISSIONS 9 + { DOT3STATSDEFERREDTRANSMISSIONS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,7 } }, +#define DOT3STATSLATECOLLISIONS 10 + { DOT3STATSLATECOLLISIONS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,8 } }, +#define DOT3STATSEXCESSIVECOLLISIONS 11 + { DOT3STATSEXCESSIVECOLLISIONS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,9 } }, +#define DOT3STATSINTERNALMACTRANSMITERRORS 12 + { DOT3STATSINTERNALMACTRANSMITERRORS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,10 } }, +#define DOT3STATSCARRIERSENSEERRORS 13 + { DOT3STATSCARRIERSENSEERRORS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,11 } }, +#define DOT3STATSFRAMETOOLONGS 14 + { DOT3STATSFRAMETOOLONGS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,13 } }, +#define DOT3STATSINTERNALMACRECEIVEERRORS 15 + { DOT3STATSINTERNALMACRECEIVEERRORS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,16 } }, +#define DOT3STATSETHERCHIPSET 16 + { DOT3STATSETHERCHIPSET, ASN_OBJECT_ID , RONLY , var_dot3StatsTable, 3, { 2,1,17 } }, +#define DOT3STATSSYMBOLERRORS 17 + { DOT3STATSSYMBOLERRORS, ASN_COUNTER , RONLY , var_dot3StatsTable, 3, { 2,1,18 } }, +#define DOT3STATSDUPLEXSTATUS 18 + { DOT3STATSDUPLEXSTATUS, ASN_INTEGER , RONLY , var_dot3StatsTable, 3, { 2,1,19 } }, + +// We do not have this histogram available: +//#define DOT3COLLFREQUENCIES 22 +// { DOT3COLLFREQUENCIES , ASN_COUNTER , RONLY , var_dot3CollTable, 3, { 5,1,3 } }, + +//UNSUPPORTED: currently we do not get these statistics out +//#define DOT3CONTROLFUNCTIONSSUPPORTED 25 +// { DOT3CONTROLFUNCTIONSSUPPORTED, ASN_BIT_STR , RONLY , var_dot3ControlTable, 3, { 9,1,1 } }, +//#define DOT3CONTROLINUNKNOWNOPCODES 26 +// { DOT3CONTROLINUNKNOWNOPCODES, ASN_COUNTER , RONLY , var_dot3ControlTable, 3, { 9,1,2 } }, + + +//UNSUPPORTED: currently we do not get these statistics out +//#define DOT3PAUSEADMINMODE 29 +// { DOT3PAUSEADMINMODE , ASN_INTEGER , RWRITE, var_dot3PauseTable, 3, { 10,1,1 } }, +//#define DOT3PAUSEOPERMODE 30 +// { DOT3PAUSEOPERMODE , ASN_INTEGER , RONLY , var_dot3PauseTable, 3, { 10,1,2 } }, +//#define DOT3INPAUSEFRAMES 31 +// { DOT3INPAUSEFRAMES , ASN_COUNTER , RONLY , var_dot3PauseTable, 3, { 10,1,3 } }, +//#define DOT3OUTPAUSEFRAMES 32 +// { DOT3OUTPAUSEFRAMES , ASN_COUNTER , RONLY , var_dot3PauseTable, 3, { 10,1,4 } }, + +}; +/* (L = length of the oidsuffix) */ + + +/* + * init_dot3(): + * Initialization routine. This is called when the agent starts up. + * At a minimum, registration of your variables should take place here. + */ +void init_dot3(void) +{ + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("dot3", dot3_variables, variable4, + dot3_variables_oid); + + /* place any other initialization junk you need here */ +} + + +/* + * var_dot3StatsTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_dot3StatsTable above. + */ +unsigned char * +var_dot3StatsTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + static long long_ret; + struct eth_drv_sc *sc; +#ifdef ETH_DEV_DOT3STATSETHERCHIPSET + static oid etherobjid[] = { ETH_DEV_DOT3STATSETHERCHIPSET }; +#endif + static oid nullobjid[] = { 0,0 }; + + register struct ifnet *ifp; + int interface_count = 0; + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + interface_count++; + + if ( header_simple_table( vp,name,length,exact,var_len,write_method, + interface_count) + == MATCH_FAILED ) + return NULL; + + for ( interface_count = name[ (*length)-1 ], ifp = ifnet.tqh_first; + interface_count > 1 && ifp != 0; + interface_count-- ) + ifp = ifp->if_list.tqe_next; + + if ( ! ifp ) + return NULL; + + if ( IFT_LOOP == ifp->if_type ) { + switch(vp->magic) { + case DOT3STATSETHERCHIPSET: + *var_len = sizeof(nullobjid); + return (unsigned char *) nullobjid; + + case DOT3STATSDUPLEXSTATUS: + long_ret = 1; + return (unsigned char *) &long_ret; + + default: + long_ret = 0; // a dummy value for most of them + return (unsigned char *) &long_ret; + } + } + + sc = ifp->if_softc; + // Otherwise, assume it is ethernet... + { +#ifdef ETH_STATS_INIT + ETH_STATS_INIT( sc ); +#endif + + switch(vp->magic) { + case DOT3STATSINDEX: + long_ret = name[(*length)-1]; + return (unsigned char *) &long_ret; + + case DOT3STATSALIGNMENTERRORS: +#ifdef ETH_DEV_STATSALIGNMENTERRORS + long_ret = ETH_DEV_STATSALIGNMENTERRORS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSFCSERRORS: +#ifdef ETH_DEV_STATSFCSERRORS + long_ret = ETH_DEV_STATSFCSERRORS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSSINGLECOLLISIONFRAMES: +#ifdef ETH_DEV_STATSSINGLECOLLISIONFRAMES + long_ret = ETH_DEV_STATSSINGLECOLLISIONFRAMES( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSMULTIPLECOLLISIONFRAMES: +#ifdef ETH_DEV_STATSMULTIPLECOLLISIONFRAMES + long_ret = ETH_DEV_STATSMULTIPLECOLLISIONFRAMES( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSSQETESTERRORS: +#ifdef ETH_DEV_STATSSQETESTERRORS + long_ret = ETH_DEV_STATSSQETESTERRORS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSDEFERREDTRANSMISSIONS: +#ifdef ETH_DEV_STATSDEFERREDTRANSMISSIONS + long_ret = ETH_DEV_STATSDEFERREDTRANSMISSIONS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSLATECOLLISIONS: +#ifdef ETH_DEV_STATSLATECOLLISIONS + long_ret = ETH_DEV_STATSLATECOLLISIONS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSEXCESSIVECOLLISIONS: +#ifdef ETH_DEV_STATSEXCESSIVECOLLISIONS + long_ret = ETH_DEV_STATSEXCESSIVECOLLISIONS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSINTERNALMACTRANSMITERRORS: +#ifdef ETH_DEV_STATSINTERNALMACTRANSMITERRORS + long_ret = ETH_DEV_STATSINTERNALMACTRANSMITERRORS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSCARRIERSENSEERRORS: +#ifdef ETH_DEV_STATSCARRIERSENSEERRORS + long_ret = ETH_DEV_STATSCARRIERSENSEERRORS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSFRAMETOOLONGS: +#ifdef ETH_DEV_STATSFRAMETOOLONGS + long_ret = ETH_DEV_STATSFRAMETOOLONGS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSINTERNALMACRECEIVEERRORS: +#ifdef ETH_DEV_STATSINTERNALMACRECEIVEERRORS + long_ret = ETH_DEV_STATSINTERNALMACRECEIVEERRORS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSETHERCHIPSET: +#ifdef ETH_DEV_DOT3STATSETHERCHIPSET + *var_len = sizeof(etherobjid); + return (unsigned char *) etherobjid; +#else + *var_len = sizeof(nullobjid); + return (unsigned char *) nullobjid; +#endif + + case DOT3STATSSYMBOLERRORS: +#ifdef ETH_DEV_STATSSYMBOLERRORS + long_ret = ETH_DEV_STATSSYMBOLERRORS( sc ); +#else + long_ret = 0; +#endif + return (unsigned char *) &long_ret; + + case DOT3STATSDUPLEXSTATUS: +#ifdef ETH_DEV_FULLDUPLEX + if ( ETH_DEV_FULLDUPLEX( sc ) ) + long_ret = 3; // fullDuplex + else + long_ret = 2; // halfDuplex +#else + long_ret = 1; // Unknown +#endif + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + } + return NULL; +} + + +#if 0 // UNSUPPORTED: we do not have the information for these tables. +/* + * var_dot3ControlTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_dot3ControlTable above. + */ +unsigned char * +var_dot3ControlTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + /* variables we may use later */ + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + static oid objid[MAX_OID_LEN]; + static struct counter64 c64; + if (header_simple_table(vp,name,length,exact,var_len,write_method, TABLE_SIZE) + == MATCH_FAILED ) + return NULL; + + switch(vp->magic) { + case DOT3CONTROLFUNCTIONSSUPPORTED: + long_ret = 1; + return &long_ret; + + case DOT3CONTROLINUNKNOWNOPCODES: + long_ret = 0; + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + +/* + * var_dot3PauseTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_dot3PauseTable above. + */ +unsigned char * +var_dot3PauseTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + /* variables we may use later */ + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + static oid objid[MAX_OID_LEN]; + static struct counter64 c64; + + if (header_simple_table(vp,name,length,exact,var_len,write_method, TABLE_SIZE) + == MATCH_FAILED ) + return NULL; + + switch(vp->magic) { + case DOT3PAUSEADMINMODE: + *write_method = write_dot3PauseAdminMode; + long_ret = 0; + return (unsigned char *) &long_ret; + + case DOT3PAUSEOPERMODE: + long_ret = 0; + return (unsigned char *) &long_ret; + + case DOT3INPAUSEFRAMES: + long_ret = 0; + return (unsigned char *) &long_ret; + + case DOT3OUTPAUSEFRAMES: + long_ret = 0; + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + + +int +write_dot3PauseAdminMode(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long *long_ret; + int size; + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to dot3PauseAdminMode not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)){ + fprintf(stderr,"write to dot3PauseAdminMode: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + case RESERVE2: + size = var_val_len; + long_ret = (long *) var_val; + break; + + case FREE: + /* Release any resources that have been allocated */ + break; + + case ACTION: + /* The variable has been stored in long_ret for + you to use, and you have just been asked to do something with + it. Note that anything done here must be reversable in the UNDO case */ + break; + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} +#endif // UNSUPPORTED + +// EOF dot3.c diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/icmp.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/icmp.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/icmp.c @@ -0,0 +1,315 @@ +//========================================================================== +// +// snmp/snmpagent/current/src/mibgroup/mibII/icmp.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +/* This should always be included first before anything else */ +#include + + +/* minimal include directives */ +#include "mibincl.h" +#include "mibgroup/util_funcs.h" +#include "mibgroup/mibII/icmp.h" + + +#define _KERNEL +#include +#include + +/* + * icmp_variables_oid: + * this is the top level oid that we want to register under. This + * is essentially a prefix, with the suffix appearing in the + * variable below. + */ + + +oid icmp_variables_oid[] = { 1,3,6,1,2,1,5 }; + + +/* + * variable2 icmp_variables: + * this variable defines function callbacks and type return information + * for the icmp mib section + */ + + +struct variable2 icmp_variables[] = { +/* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +#define ICMPINMSGS 1 + { ICMPINMSGS , ASN_COUNTER , RONLY , var_icmp, 1, { 1 } }, +#define ICMPINERRORS 2 + { ICMPINERRORS , ASN_COUNTER , RONLY , var_icmp, 1, { 2 } }, +#define ICMPINDESTUNREACHS 3 + { ICMPINDESTUNREACHS , ASN_COUNTER , RONLY , var_icmp, 1, { 3 } }, +#define ICMPINTIMEEXCDS 4 + { ICMPINTIMEEXCDS , ASN_COUNTER , RONLY , var_icmp, 1, { 4 } }, +#define ICMPINPARMPROBS 5 + { ICMPINPARMPROBS , ASN_COUNTER , RONLY , var_icmp, 1, { 5 } }, +#define ICMPINSRCQUENCHS 6 + { ICMPINSRCQUENCHS , ASN_COUNTER , RONLY , var_icmp, 1, { 6 } }, +#define ICMPINREDIRECTS 7 + { ICMPINREDIRECTS , ASN_COUNTER , RONLY , var_icmp, 1, { 7 } }, +#define ICMPINECHOS 8 + { ICMPINECHOS , ASN_COUNTER , RONLY , var_icmp, 1, { 8 } }, +#define ICMPINECHOREPS 9 + { ICMPINECHOREPS , ASN_COUNTER , RONLY , var_icmp, 1, { 9 } }, +#define ICMPINTIMESTAMPS 10 + { ICMPINTIMESTAMPS , ASN_COUNTER , RONLY , var_icmp, 1, { 10 } }, +#define ICMPINTIMESTAMPREPS 11 + { ICMPINTIMESTAMPREPS , ASN_COUNTER , RONLY , var_icmp, 1, { 11 } }, +#define ICMPINADDRMASKS 12 + { ICMPINADDRMASKS , ASN_COUNTER , RONLY , var_icmp, 1, { 12 } }, +#define ICMPINADDRMASKREPS 13 + { ICMPINADDRMASKREPS , ASN_COUNTER , RONLY , var_icmp, 1, { 13 } }, +#define ICMPOUTMSGS 14 + { ICMPOUTMSGS , ASN_COUNTER , RONLY , var_icmp, 1, { 14 } }, +#define ICMPOUTERRORS 15 + { ICMPOUTERRORS , ASN_COUNTER , RONLY , var_icmp, 1, { 15 } }, +#define ICMPOUTDESTUNREACHS 16 + { ICMPOUTDESTUNREACHS , ASN_COUNTER , RONLY , var_icmp, 1, { 16 } }, +#define ICMPOUTTIMEEXCDS 17 + { ICMPOUTTIMEEXCDS , ASN_COUNTER , RONLY , var_icmp, 1, { 17 } }, +#define ICMPOUTPARMPROBS 18 + { ICMPOUTPARMPROBS , ASN_COUNTER , RONLY , var_icmp, 1, { 18 } }, +#define ICMPOUTSRCQUENCHS 19 + { ICMPOUTSRCQUENCHS , ASN_COUNTER , RONLY , var_icmp, 1, { 19 } }, +#define ICMPOUTREDIRECTS 20 + { ICMPOUTREDIRECTS , ASN_COUNTER , RONLY , var_icmp, 1, { 20 } }, +#define ICMPOUTECHOS 21 + { ICMPOUTECHOS , ASN_COUNTER , RONLY , var_icmp, 1, { 21 } }, +#define ICMPOUTECHOREPS 22 + { ICMPOUTECHOREPS , ASN_COUNTER , RONLY , var_icmp, 1, { 22 } }, +#define ICMPOUTTIMESTAMPS 23 + { ICMPOUTTIMESTAMPS , ASN_COUNTER , RONLY , var_icmp, 1, { 23 } }, +#define ICMPOUTTIMESTAMPREPS 24 + { ICMPOUTTIMESTAMPREPS, ASN_COUNTER , RONLY , var_icmp, 1, { 24 } }, +#define ICMPOUTADDRMASKS 25 + { ICMPOUTADDRMASKS , ASN_COUNTER , RONLY , var_icmp, 1, { 25 } }, +#define ICMPOUTADDRMASKREPS 26 + { ICMPOUTADDRMASKREPS , ASN_COUNTER , RONLY , var_icmp, 1, { 26 } }, + +}; +/* (L = length of the oidsuffix) */ + + +/* + * init_icmp(): + * Initialization routine. This is called when the agent starts up. + * At a minimum, registration of your variables should take place here. + */ +void init_icmp(void) { + + + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("icmp", icmp_variables, variable2, + icmp_variables_oid); + + + /* place any other initialization junk you need here */ +} + + +/* + * var_icmp(): + * This function is called every time the agent gets a request for + * a scalar variable that might be found within your mib section + * registered above. It is up to you to do the right thing and + * return the correct value. + * You should also correct the value of "var_len" if necessary. + * + * Please see the documentation for more information about writing + * module extensions, and check out the examples in the examples + * and mibII directories. + */ +unsigned char * +var_icmp(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + /* variables we may use later */ + static long long_ret; + int i; + + if (header_generic(vp,name,length,exact,var_len,write_method) + == MATCH_FAILED ) + return NULL; + + switch (vp->magic){ + case ICMPINMSGS: + long_ret = icmpstat.icps_badcode + icmpstat.icps_tooshort + + icmpstat.icps_checksum + icmpstat.icps_badlen; + for (i=0; i <= ICMP_MAXTYPE; i++) + long_ret += icmpstat.icps_inhist[i]; + return (u_char *)&long_ret; + case ICMPINERRORS: + long_ret = icmpstat.icps_badcode + icmpstat.icps_tooshort + + icmpstat.icps_checksum + icmpstat.icps_badlen; + return (u_char *)&long_ret; + case ICMPINDESTUNREACHS: + long_ret = icmpstat.icps_inhist[ICMP_UNREACH]; + return (u_char *) &long_ret; + case ICMPINTIMEEXCDS: + long_ret = icmpstat.icps_inhist[ICMP_TIMXCEED]; + return (u_char *) &long_ret; + case ICMPINPARMPROBS: + long_ret = icmpstat.icps_inhist[ICMP_PARAMPROB]; + return (u_char *) &long_ret; + case ICMPINSRCQUENCHS: + long_ret = icmpstat.icps_inhist[ICMP_SOURCEQUENCH]; + return (u_char *) &long_ret; + case ICMPINREDIRECTS: + long_ret = icmpstat.icps_inhist[ICMP_REDIRECT]; + return (u_char *) &long_ret; + case ICMPINECHOS: + long_ret = icmpstat.icps_inhist[ICMP_ECHO]; + return (u_char *) &long_ret; + case ICMPINECHOREPS: + long_ret = icmpstat.icps_inhist[ICMP_ECHOREPLY]; + return (u_char *) &long_ret; + case ICMPINTIMESTAMPS: + long_ret = icmpstat.icps_inhist[ICMP_TSTAMP]; + return (u_char *) &long_ret; + case ICMPINTIMESTAMPREPS: + long_ret = icmpstat.icps_inhist[ICMP_TSTAMPREPLY]; + return (u_char *) &long_ret; + case ICMPINADDRMASKS: + long_ret = icmpstat.icps_inhist[ICMP_MASKREQ]; + return (u_char *) &long_ret; + case ICMPINADDRMASKREPS: + long_ret = icmpstat.icps_inhist[ICMP_MASKREPLY]; + return (u_char *) &long_ret; + case ICMPOUTMSGS: + long_ret = icmpstat.icps_oldshort + icmpstat.icps_oldicmp; + for (i=0; i <= ICMP_MAXTYPE; i++) + long_ret += icmpstat.icps_outhist[i]; + return (u_char *)&long_ret; + case ICMPOUTERRORS: + long_ret = icmpstat.icps_oldshort + icmpstat.icps_oldicmp; + return (u_char *)&long_ret; + case ICMPOUTDESTUNREACHS: + long_ret = icmpstat.icps_outhist[ICMP_UNREACH]; + return (u_char *) &long_ret; + case ICMPOUTTIMEEXCDS: + long_ret = icmpstat.icps_outhist[ICMP_TIMXCEED]; + return (u_char *) &long_ret; + case ICMPOUTPARMPROBS: + long_ret = icmpstat.icps_outhist[ICMP_PARAMPROB]; + return (u_char *) &long_ret; + case ICMPOUTSRCQUENCHS: + long_ret = icmpstat.icps_outhist[ICMP_SOURCEQUENCH]; + return (u_char *) &long_ret; + case ICMPOUTREDIRECTS: + long_ret = icmpstat.icps_outhist[ICMP_REDIRECT]; + return (u_char *) &long_ret; + case ICMPOUTECHOS: + long_ret = icmpstat.icps_outhist[ICMP_ECHO]; + return (u_char *) &long_ret; + case ICMPOUTECHOREPS: + long_ret = icmpstat.icps_outhist[ICMP_ECHOREPLY]; + return (u_char *) &long_ret; + case ICMPOUTTIMESTAMPS: + long_ret = icmpstat.icps_outhist[ICMP_TSTAMP]; + return (u_char *) &long_ret; + case ICMPOUTTIMESTAMPREPS: + long_ret = icmpstat.icps_outhist[ICMP_TSTAMPREPLY]; + return (u_char *) &long_ret; + case ICMPOUTADDRMASKS: + long_ret = icmpstat.icps_outhist[ICMP_MASKREQ]; + return (u_char *) &long_ret; + case ICMPOUTADDRMASKREPS: + long_ret = icmpstat.icps_outhist[ICMP_MASKREPLY]; + return (u_char *) &long_ret; + default: + DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_icmp\n", vp->magic)); + } + + return NULL; +} + +// EOF icmp.c diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/interfaces.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/interfaces.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/interfaces.c @@ -0,0 +1,511 @@ +//========================================================================== +// +// snmp/snmpagent/current/src/mibgroup/mibII/interfaces.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +/* This should always be included first before anything else */ +#include + + +/* minimal include directives */ +#include "mibincl.h" +#include "mibgroup/util_funcs.h" +#include "mibgroup/mibII/interfaces.h" + +#include + +// Get info about the device +#include + +#include + +#ifdef CYGBLD_DEVS_ETH_DEVICE_H +#include CYGBLD_DEVS_ETH_DEVICE_H +#endif + +#ifdef CYGBLD_DEVS_ETH_INFO_H +#include CYGBLD_DEVS_ETH_INFO_H +#endif + +/* + * interfaces_variables_oid: + * this is the top level oid that we want to register under. This + * is essentially a prefix, with the suffix appearing in the + * variable below. + */ +oid interfaces_variables_oid[] = { 1,3,6,1,2,1,2 }; + + +extern struct ifnet_head ifnet; + + + +/* + * variable4 interfaces_variables: + * this variable defines function callbacks and type return information + * for the interfaces mib section + */ + + +struct variable4 interfaces_variables[] = { +/* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +#define IFNUMBER 1 + { IFNUMBER , ASN_INTEGER , RONLY , var_interfaces, 1, { 1 } }, +#define IFINDEX 4 + { IFINDEX , ASN_INTEGER , RONLY , var_ifTable, 3, { 2,1,1 } }, +#define IFDESCR 5 + { IFDESCR , ASN_OCTET_STR , RONLY , var_ifTable, 3, { 2,1,2 } }, +#define IFTYPE 6 + { IFTYPE , ASN_INTEGER , RONLY , var_ifTable, 3, { 2,1,3 } }, +#define IFMTU 7 + { IFMTU , ASN_INTEGER , RONLY , var_ifTable, 3, { 2,1,4 } }, +#define IFSPEED 8 + { IFSPEED , ASN_GAUGE , RONLY , var_ifTable, 3, { 2,1,5 } }, +#define IFPHYSADDRESS 9 + { IFPHYSADDRESS , ASN_OCTET_STR , RONLY , var_ifTable, 3, { 2,1,6 } }, +#define IFADMINSTATUS 10 + { IFADMINSTATUS , ASN_INTEGER , RWRITE, var_ifTable, 3, { 2,1,7 } }, +#define IFOPERSTATUS 11 + { IFOPERSTATUS , ASN_INTEGER , RONLY , var_ifTable, 3, { 2,1,8 } }, +#define IFLASTCHANGE 12 + { IFLASTCHANGE , ASN_TIMETICKS , RONLY , var_ifTable, 3, { 2,1,9 } }, +#define IFINOCTETS 13 + { IFINOCTETS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,10 } }, +#define IFINUCASTPKTS 14 + { IFINUCASTPKTS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,11 } }, +#define IFINNUCASTPKTS 15 + { IFINNUCASTPKTS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,12 } }, +#define IFINDISCARDS 16 + { IFINDISCARDS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,13 } }, +#define IFINERRORS 17 + { IFINERRORS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,14 } }, +#define IFINUNKNOWNPROTOS 18 + { IFINUNKNOWNPROTOS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,15 } }, +#define IFOUTOCTETS 19 + { IFOUTOCTETS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,16 } }, +#define IFOUTUCASTPKTS 20 + { IFOUTUCASTPKTS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,17 } }, +#define IFOUTNUCASTPKTS 21 + { IFOUTNUCASTPKTS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,18 } }, +#define IFOUTDISCARDS 22 + { IFOUTDISCARDS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,19 } }, +#define IFOUTERRORS 23 + { IFOUTERRORS , ASN_COUNTER , RONLY , var_ifTable, 3, { 2,1,20 } }, +#define IFOUTQLEN 24 + { IFOUTQLEN , ASN_GAUGE , RONLY , var_ifTable, 3, { 2,1,21 } }, +#define IFSPECIFIC 25 + { IFSPECIFIC , ASN_OBJECT_ID , RONLY , var_ifTable, 3, { 2,1,22 } }, + +}; +/* (L = length of the oidsuffix) */ + + +/* + * init_interfaces(): + * Initialization routine. This is called when the agent starts up. + * At a minimum, registration of your variables should take place here. + */ +void init_interfaces(void) { + + + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("interfaces", interfaces_variables, variable4, + interfaces_variables_oid); + + + /* place any other initialization junk you need here */ +} + + +/* + * var_interfaces(): + * This function is called every time the agent gets a request for + * a scalar variable that might be found within your mib section + * registered above. It is up to you to do the right thing and + * return the correct value. + * You should also correct the value of "var_len" if necessary. + * + * Please see the documentation for more information about writing + * module extensions, and check out the examples in the examples + * and mibII directories. + */ +unsigned char * +var_interfaces(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + + + /* variables we may use later */ + static long long_ret; +// static unsigned char string[SPRINT_MAX_LEN]; +// static oid objid[MAX_OID_LEN]; +// static struct counter64 c64; + + + if ( MATCH_FAILED == + header_generic(vp,name,length,exact,var_len,write_method) ) + return NULL; + + /* + * this is where we do the value assignments for the mib results. + */ + switch(vp->magic) { + case IFNUMBER: { + register struct ifnet *ifp; + long_ret = 0; + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + long_ret++; + + return (unsigned char *) &long_ret; + } + + default: + ERROR_MSG(""); + } + return NULL; +} + + +/* + * var_ifTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_interfaces above. + */ +unsigned char * +var_ifTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + + + /* variables we may use later */ + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + static oid objid[MAX_OID_LEN]; +// static struct counter64 c64; + + register struct ifnet *ifp; + int interface_count = 0; + + for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) + interface_count++; + + /* + * This assumes that the table is a 'simple' table. + * See the implementation documentation for the meaning of this. + * You will need to provide the correct value for the TABLE_SIZE parameter + * + * If this table does not meet the requirements for a simple table, + * you will need to provide the replacement code yourself. + * Mib2c is not smart enough to write this for you. + * Again, see the implementation documentation for what is required. + */ + if ( header_simple_table( vp,name,length,exact,var_len,write_method, + interface_count) + == MATCH_FAILED ) + return NULL; + + for ( interface_count = name[ (*length)-1 ], ifp = ifnet.tqh_first; + interface_count > 1 && ifp != 0; + interface_count-- ) + ifp = ifp->if_list.tqe_next; + + if ( ! ifp ) + return NULL; + + switch(vp->magic) { + + case IFINDEX: + long_ret = name[(*length)-1]; + return (unsigned char *) &long_ret; + + case IFDESCR: + if ( IFT_LOOP == ifp->if_type ) + strcpy( string, "(Loopback device)" ); + else { +#ifdef CYGDAT_DEVS_ETH_DESCRIPTION + strcpy( string, CYGDAT_DEVS_ETH_DESCRIPTION ); +#else + strcpy( string, "Some shy Ethernet adaptor" ); +#endif + } + *var_len = strlen(string); + return (unsigned char *) string; + + case IFTYPE: + long_ret = ifp->if_type; + return (unsigned char *) &long_ret; + + case IFMTU: + long_ret = ifp->if_mtu; + return (unsigned char *) &long_ret; + + case IFSPEED: + if ( IFT_LOOP == ifp->if_type ) + long_ret = 0; + else { +#ifdef ETH_DEV_IFSPEED + struct eth_drv_sc *sc = ifp->if_softc; +#ifdef ETH_STATS_INIT + ETH_STATS_INIT( sc ); +#endif + long_ret = ETH_DEV_IFSPEED( sc ); +#else + long_ret = ifp->if_baudrate; +#endif + } + return (unsigned char *) &long_ret; + + case IFPHYSADDRESS: { + if ( IFT_LOOP == ifp->if_type ) + bzero( string, ETHER_ADDR_LEN ); + else { + struct eth_drv_sc *sc = ifp->if_softc; + bcopy(&sc->sc_arpcom.ac_enaddr, string, ETHER_ADDR_LEN); + } + *var_len = ETHER_ADDR_LEN; + return (unsigned char *) string; + } + case IFADMINSTATUS: + //NOTSUPPORTED: *write_method = write_ifAdminStatus; + long_ret = (ifp->if_flags & IFF_RUNNING) ? 1 : 2; + return (unsigned char *) &long_ret; + + case IFOPERSTATUS: + long_ret = (ifp->if_flags & IFF_UP) ? 1 : 2; + return (unsigned char *) &long_ret; + + case IFLASTCHANGE: + long_ret = 0; //FIXME: ifp->if_lastchange; + return (unsigned char *) &long_ret; + + case IFINOCTETS: + long_ret = ifp->if_ibytes; + return (unsigned char *) &long_ret; + + case IFINUCASTPKTS: + long_ret = ifp->if_ipackets - ifp->if_imcasts; + return (unsigned char *) &long_ret; + + case IFINNUCASTPKTS: + long_ret = ifp->if_imcasts; + return (unsigned char *) &long_ret; + + case IFINDISCARDS: + long_ret = ifp->if_iqdrops; + return (unsigned char *) &long_ret; + + case IFINERRORS: + long_ret = ifp->if_ierrors; + return (unsigned char *) &long_ret; + + case IFINUNKNOWNPROTOS: + long_ret = ifp->if_noproto; + return (unsigned char *) &long_ret; + + case IFOUTOCTETS: + long_ret = ifp->if_obytes; + return (unsigned char *) &long_ret; + + case IFOUTUCASTPKTS: + long_ret = ifp->if_opackets - ifp->if_omcasts; + return (unsigned char *) &long_ret; + + case IFOUTNUCASTPKTS: + long_ret = ifp->if_omcasts; + return (unsigned char *) &long_ret; + + case IFOUTDISCARDS: + if ( IFT_LOOP == ifp->if_type ) + long_ret = 0; + else { +#ifdef ETH_DEV_IFOUTDISCARDS + long_ret = ETH_DEV_IFOUTDISCARDS( (struct eth_drv_sc *)(ifp->if_softc) ); +#else + long_ret = 0; +#endif + } + return (unsigned char *) &long_ret; + + case IFOUTERRORS: + long_ret = ifp->if_oerrors; + return (unsigned char *) &long_ret; + + case IFOUTQLEN: + if ( IFT_LOOP == ifp->if_type ) + long_ret = 0; + else { +#ifdef ETH_DEV_IFOUTQLEN + long_ret = ETH_DEV_IFOUTQLEN( (struct eth_drv_sc *)(ifp->if_softc) ); +#else + long_ret = 0; +#endif + } + return (unsigned char *) &long_ret; + + case IFSPECIFIC: + objid[0] = 0; + objid[1] = 0; + *var_len = 2*sizeof(oid); + return (unsigned char *) objid; + + default: + ERROR_MSG(""); + } + return NULL; +} + + + +//NOTSUPPORTED: +#if 0 +int +write_ifAdminStatus(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long *long_ret; + int size; + + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to ifAdminStatus not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)){ + fprintf(stderr,"write to ifAdminStatus: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + + case RESERVE2: + size = var_val_len; + long_ret = (long *) var_val; + + + break; + + + case FREE: + /* Release any resources that have been allocated */ + break; + + + case ACTION: + /* The variable has been stored in long_ret for you to use, + and you have just been asked to do something with it. Note + that anything done here must be reversable in the UNDO case */ + break; + + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} + +#endif + +// EOF interfaces.c diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/ip.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/ip.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/ip.c @@ -0,0 +1,936 @@ +//========================================================================== +// +// snmp/snmpagent/current/src/mibgroup/mibII/ip.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +/* This should always be included first before anything else */ +#include + + +/* minimal include directives */ +#include "mibincl.h" +#include "mibgroup/util_funcs.h" +#include "mibgroup/mibII/ip.h" + +#define _KERNEL 1 + +#include +#include + +extern struct in_ifaddrhead in_ifaddr; + +#include + +/* + * ip_variables_oid: + * this is the top level oid that we want to register under. This + * is essentially a prefix, with the suffix appearing in the + * variable below. + */ + + +oid ip_variables_oid[] = { 1,3,6,1,2,1,4 }; + + +/* + * variable4 ip_variables: + * this variable defines function callbacks and type return information + * for the ip mib section + */ + +struct variable4 ip_variables[] = { +/* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +#define IPFORWARDING 1 + { IPFORWARDING , ASN_INTEGER , RWRITE, var_ip, 1, { 1 } }, +#define IPDEFAULTTTL 2 + { IPDEFAULTTTL , ASN_INTEGER , RWRITE, var_ip, 1, { 2 } }, +#define IPINRECEIVES 3 + { IPINRECEIVES , ASN_COUNTER , RONLY , var_ip, 1, { 3 } }, +#define IPINHDRERRORS 4 + { IPINHDRERRORS , ASN_COUNTER , RONLY , var_ip, 1, { 4 } }, +#define IPINADDRERRORS 5 + { IPINADDRERRORS , ASN_COUNTER , RONLY , var_ip, 1, { 5 } }, +#define IPFORWDATAGRAMS 6 + { IPFORWDATAGRAMS , ASN_COUNTER , RONLY , var_ip, 1, { 6 } }, +#define IPINUNKNOWNPROTOS 7 + { IPINUNKNOWNPROTOS , ASN_COUNTER , RONLY , var_ip, 1, { 7 } }, +#define IPINDISCARDS 8 + { IPINDISCARDS , ASN_COUNTER , RONLY , var_ip, 1, { 8 } }, +#define IPINDELIVERS 9 + { IPINDELIVERS , ASN_COUNTER , RONLY , var_ip, 1, { 9 } }, +#define IPOUTREQUESTS 10 + { IPOUTREQUESTS , ASN_COUNTER , RONLY , var_ip, 1, { 10 } }, +#define IPOUTDISCARDS 11 + { IPOUTDISCARDS , ASN_COUNTER , RONLY , var_ip, 1, { 11 } }, +#define IPOUTNOROUTES 12 + { IPOUTNOROUTES , ASN_COUNTER , RONLY , var_ip, 1, { 12 } }, +#define IPREASMTIMEOUT 13 + { IPREASMTIMEOUT , ASN_INTEGER , RONLY , var_ip, 1, { 13 } }, +#define IPREASMREQDS 14 + { IPREASMREQDS , ASN_COUNTER , RONLY , var_ip, 1, { 14 } }, +#define IPREASMOKS 15 + { IPREASMOKS , ASN_COUNTER , RONLY , var_ip, 1, { 15 } }, +#define IPREASMFAILS 16 + { IPREASMFAILS , ASN_COUNTER , RONLY , var_ip, 1, { 16 } }, +#define IPFRAGOKS 17 + { IPFRAGOKS , ASN_COUNTER , RONLY , var_ip, 1, { 17 } }, +#define IPFRAGFAILS 18 + { IPFRAGFAILS , ASN_COUNTER , RONLY , var_ip, 1, { 18 } }, +#define IPFRAGCREATES 19 + { IPFRAGCREATES , ASN_COUNTER , RONLY , var_ip, 1, { 19 } }, + + +#define IPADENTADDR 22 + { IPADENTADDR , ASN_IPADDRESS , RONLY , var_ipAddrTable, 3, { 20,1,1 } }, +#define IPADENTIFINDEX 23 + { IPADENTIFINDEX , ASN_INTEGER , RONLY , var_ipAddrTable, 3, { 20,1,2 } }, +#define IPADENTNETMASK 24 + { IPADENTNETMASK , ASN_IPADDRESS , RONLY , var_ipAddrTable, 3, { 20,1,3 } }, +#define IPADENTBCASTADDR 25 + { IPADENTBCASTADDR , ASN_INTEGER , RONLY , var_ipAddrTable, 3, { 20,1,4 } }, +#define IPADENTREASMMAXSIZE 26 + { IPADENTREASMMAXSIZE , ASN_INTEGER , RONLY , var_ipAddrTable, 3, { 20,1,5 } }, + +// ROUTE TABLE is OBSOLETE according to my book +//#define IPROUTEDEST 29 +// { IPROUTEDEST , ASN_IPADDRESS , RWRITE, var_ipRouteTable, 3, { 21,1,1 } }, +//#define IPROUTEIFINDEX 30 +// { IPROUTEIFINDEX , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,2 } }, +//#define IPROUTEMETRIC1 31 +// { IPROUTEMETRIC1 , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,3 } }, +//#define IPROUTEMETRIC2 32 +// { IPROUTEMETRIC2 , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,4 } }, +//#define IPROUTEMETRIC3 33 +// { IPROUTEMETRIC3 , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,5 } }, +//#define IPROUTEMETRIC4 34 +// { IPROUTEMETRIC4 , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,6 } }, +//#define IPROUTENEXTHOP 35 +// { IPROUTENEXTHOP , ASN_IPADDRESS , RWRITE, var_ipRouteTable, 3, { 21,1,7 } }, +//#define IPROUTETYPE 36 +// { IPROUTETYPE , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,8 } }, +//#define IPROUTEPROTO 37 +// { IPROUTEPROTO , ASN_INTEGER , RONLY , var_ipRouteTable, 3, { 21,1,9 } }, +//#define IPROUTEAGE 38 +// { IPROUTEAGE , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,10 } }, +//#define IPROUTEMASK 39 +// { IPROUTEMASK , ASN_IPADDRESS , RWRITE, var_ipRouteTable, 3, { 21,1,11 } }, +//#define IPROUTEMETRIC5 40 +// { IPROUTEMETRIC5 , ASN_INTEGER , RWRITE, var_ipRouteTable, 3, { 21,1,12 } }, +//#define IPROUTEINFO 41 +// { IPROUTEINFO , ASN_OBJECT_ID , RONLY , var_ipRouteTable, 3, { 21,1,13 } }, + +#define IPNETTOMEDIAIFINDEX 44 + { IPNETTOMEDIAIFINDEX , ASN_INTEGER , RWRITE, var_ipNetToMediaTable, 3, { 22,1,1 } }, +#define IPNETTOMEDIAPHYSADDRESS 45 + { IPNETTOMEDIAPHYSADDRESS, ASN_OCTET_STR, RWRITE, var_ipNetToMediaTable, 3, { 22,1,2 } }, +#define IPNETTOMEDIANETADDRESS 46 + { IPNETTOMEDIANETADDRESS, ASN_IPADDRESS , RWRITE, var_ipNetToMediaTable, 3, { 22,1,3 } }, +#define IPNETTOMEDIATYPE 47 + { IPNETTOMEDIATYPE , ASN_INTEGER , RWRITE, var_ipNetToMediaTable, 3, { 22,1,4 } }, + +#define IPROUTINGDISCARDS 48 + { IPROUTINGDISCARDS , ASN_COUNTER , RONLY , var_ip, 1, { 23 } }, + +}; +/* (L = length of the oidsuffix) */ + + +/* + * init_ip(): + * Initialization routine. This is called when the agent starts up. + * At a minimum, registration of your variables should take place here. + */ +void init_ip(void) { + + + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("ip", ip_variables, variable4, + ip_variables_oid); + + + /* place any other initialization junk you need here */ +} + + +/* + * var_ip(): + * This function is called every time the agent gets a request for + * a scalar variable that might be found within your mib section + * registered above. It is up to you to do the right thing and + * return the correct value. + * You should also correct the value of "var_len" if necessary. + * + * Please see the documentation for more information about writing + * module extensions, and check out the examples in the examples + * and mibII directories. + */ +unsigned char * +var_ip(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + + + /* variables we may use later */ + static long long_ret; + + if (header_generic(vp,name,length,exact,var_len,write_method) + == MATCH_FAILED ) + return NULL; + + switch(vp->magic) { + + case IPFORWARDING: + *write_method = write_ipForwarding; + long_ret = ipforwarding ? 1 : 2; + return (unsigned char *) &long_ret; + + case IPDEFAULTTTL: + *write_method = write_ipDefaultTTL; + long_ret = ip_defttl; + return (unsigned char *) &long_ret; + + case IPINRECEIVES: + long_ret = ipstat.ips_total; + return (unsigned char *) &long_ret; + + case IPINHDRERRORS: + long_ret = ipstat.ips_badsum + + ipstat.ips_badhlen + + ipstat.ips_badlen + + ipstat.ips_badoptions + + ipstat.ips_badvers + + ipstat.ips_badfrags + + ipstat.ips_toolong + ; + return (unsigned char *) &long_ret; + + case IPINADDRERRORS: + long_ret = ipstat.ips_cantforward; + return (unsigned char *) &long_ret; + + case IPFORWDATAGRAMS: + long_ret = ipstat.ips_forward; + return (unsigned char *) &long_ret; + + case IPINUNKNOWNPROTOS: + long_ret = ipstat.ips_noproto; + return (unsigned char *) &long_ret; + + case IPINDISCARDS: + long_ret = ipstat.ips_total - ipstat.ips_delivered - + ( + ipstat.ips_badsum + + ipstat.ips_badhlen + + ipstat.ips_badlen + + ipstat.ips_badoptions + + ipstat.ips_badvers + + ipstat.ips_badfrags + + ipstat.ips_toolong + ) - + ipstat.ips_cantforward; + if ( 0 > long_ret ) + long_ret = 0; + return (unsigned char *) &long_ret; + + case IPINDELIVERS: + long_ret = ipstat.ips_delivered; + return (unsigned char *) &long_ret; + + case IPOUTREQUESTS: + long_ret = ipstat.ips_localout; + return (unsigned char *) &long_ret; + + case IPOUTDISCARDS: + long_ret = ipstat.ips_odropped; + return (unsigned char *) &long_ret; + + case IPOUTNOROUTES: + long_ret = ipstat.ips_noroute; + return (unsigned char *) &long_ret; + + case IPREASMTIMEOUT: + long_ret = 0; //FIXME + return (unsigned char *) &long_ret; + + case IPREASMREQDS: + long_ret = ipstat.ips_fragments; + return (unsigned char *) &long_ret; + + case IPREASMOKS: + long_ret = ipstat.ips_reassembled; + return (unsigned char *) &long_ret; + + case IPREASMFAILS: + long_ret = ipstat.ips_fragments - + (ipstat.ips_fragdropped + ipstat.ips_fragtimeout); + return (unsigned char *) &long_ret; + + case IPFRAGOKS: + long_ret = ipstat.ips_fragmented; + return (unsigned char *) &long_ret; + + case IPFRAGFAILS: + long_ret = ipstat.ips_cantfrag; + return (unsigned char *) &long_ret; + + case IPFRAGCREATES: + long_ret = ipstat.ips_ofragments; + return (unsigned char *) &long_ret; + + case IPROUTINGDISCARDS: + long_ret = ipstat.ips_noroute; + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + + +/* + * var_ipAddrTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_ipAddrTable above. + */ +unsigned char * +var_ipAddrTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + /* + * object identifier is of form: + * 1.3.6.1.2.1.4.20.1.?.A.B.C.D, where A.B.C.D is IP address. + * IPADDR starts at offset 10. + */ + oid lowest[14]; + oid current[14], *op; + u_char *cp; + + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + + register struct in_ifaddr *ia; + register struct in_ifaddr *low_ia = NULL; + + /* fill in object part of name for current (less sizeof instance part) */ + memcpy( (char *)current,(char *)vp->name, (int)vp->namelen * sizeof(oid)); + + for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { + cp = (u_char *)&(ia->ia_addr.sin_addr.s_addr); + + op = current + 10; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + if (exact){ + if (snmp_oid_compare(current, 14, name, *length) == 0) { + memcpy( (char *)lowest,(char *)current, 14 * sizeof(oid)); + low_ia = ia; + break; /* no need to search further */ + } + } else { + if ((snmp_oid_compare(current, 14, name, *length) > 0) && + (!low_ia || (snmp_oid_compare(current, 14, lowest, 14) < 0))) { + /* + * if new one is greater than input and closer to input than + * previous lowest, save this one as the "next" one. + */ + memcpy( (char *)lowest,(char *)current, 14 * sizeof(oid)); + low_ia = ia; + } + } + } + + if ( ! low_ia ) + return NULL; + + memcpy( (char *)name,(char *)lowest, 14 * sizeof(oid)); + *length = 14; + *write_method = 0; + *var_len = sizeof(long_return); + + /* + * this is where we do the value assignments for the mib results. + */ + switch(vp->magic) { + + case IPADENTADDR: + cp = (u_char *)&(low_ia->ia_addr.sin_addr.s_addr); + string[0] = *cp++; + string[1] = *cp++; + string[2] = *cp++; + string[3] = *cp++; + *var_len = 4; + return (unsigned char *) string; + + case IPADENTIFINDEX: + long_ret = low_ia->ia_ifa.ifa_ifp->if_index; + return (unsigned char *) &long_ret; + + case IPADENTNETMASK: + cp = (u_char *)&(low_ia->ia_subnetmask); + string[0] = *cp++; + string[1] = *cp++; + string[2] = *cp++; + string[3] = *cp++; + *var_len = 4; + return (unsigned char *) string; + + case IPADENTBCASTADDR: + long_ret = 1; + return (unsigned char *) &long_ret; + + case IPADENTREASMMAXSIZE: + long_ret = IP_MAXPACKET; + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + + + + +/* + * var_ipNetToMediaTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_ip above. + */ + +// According to sections 6.1.5 (ip) and 6.1.4 (at) pp.130-138 of the book +// by William Stallings, this lists *our* interfaces only, not the ARP +// table. The MIBs are rather ambiguous, as is Mark A. Miller's book also. +// +// Specifically, the indexing by interface Id suggests there should only be +// one entry per interface. + +unsigned char * +var_ipNetToMediaTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + /* + * IP Net to Media table object identifier is of form: + * 1.3.6.1.2.1.4.22.1.?.interface.A.B.C.D, where A.B.C.D is IP address. + * Interface is at offset 10, + * IPADDR starts at offset 11. + */ + u_char *cp; + oid *op; + oid lowest[16]; + oid current[16]; + + register struct in_ifaddr *ia; + register struct in_ifaddr *low_ia = NULL; + + /* fill in object part of name for current (less sizeof instance part) */ + memcpy((char *)current, (char *)vp->name, (int)vp->namelen * sizeof(oid)); + + for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { + // interface number + current[10] = ia->ia_ifa.ifa_ifp->if_index; + // IP address + cp = (u_char *)&(ia->ia_addr.sin_addr.s_addr); + op = current + 11; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + + if (exact){ + if (snmp_oid_compare(current, 15, name, *length) == 0){ + memcpy( (char *)lowest,(char *)current, 15 * sizeof(oid)); + low_ia = ia; + break; /* no need to search further */ + } + } else { + if ((snmp_oid_compare(current, 15, name, *length) > 0) && + ((!low_ia) || (snmp_oid_compare(current, 15, lowest, 15) < 0))) { + /* + * if new one is greater than input and closer to input than + * previous lowest, save this one as the "next" one. + */ + memcpy( (char *)lowest,(char *)current, 15 * sizeof(oid)); + low_ia = ia; + } + } + } + if ( ! low_ia ) + return(NULL); + + memcpy( (char *)name,(char *)lowest, 15 * sizeof(oid)); + *length = 15; + *write_method = 0; + *var_len = sizeof(long_return); + + /* + * this is where we do the value assignments for the mib results. + */ + switch(vp->magic) { + case IPNETTOMEDIAIFINDEX: + //NOTSUPPORTED: *write_method = write_ipNetToMediaIfIndex; + long_ret = low_ia->ia_ifa.ifa_ifp->if_index; + return (unsigned char *) &long_ret; + + case IPNETTOMEDIAPHYSADDRESS: { + struct eth_drv_sc *sc = low_ia->ia_ifa.ifa_ifp->if_softc; + bcopy(&sc->sc_arpcom.ac_enaddr, string, ETHER_ADDR_LEN); + *var_len = ETHER_ADDR_LEN; + //NOTSUPPORTED: *write_method = write_ipNetToMediaPhysAddress; + return (unsigned char *) string; + } + case IPNETTOMEDIANETADDRESS: + //NOTSUPPORTED: *write_method = write_ipNetToMediaNetAddress; + cp = (u_char *)&(low_ia->ia_addr.sin_addr.s_addr); + string[0] = *cp++; + string[1] = *cp++; + string[2] = *cp++; + string[3] = *cp++; + *var_len = 4; + return (unsigned char *) string; + + case IPNETTOMEDIATYPE: + //NOTSUPPORTED: *write_method = write_ipNetToMediaType; + long_ret = 4; // Static mapping + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + + + + +int +write_ipForwarding(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long setval; + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to ipForwarding not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(setval)){ + fprintf(stderr,"write to ipForwarding: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + setval = *(long *)var_val; + if ( 1 != setval && 2 != setval ) + return SNMP_ERR_WRONGVALUE; + break; + + case RESERVE2: + case FREE: + case ACTION: + case UNDO: + break; + + case COMMIT: + ipforwarding = (setval == 1); + break; + } + return SNMP_ERR_NOERROR; +} + + + + +int +write_ipDefaultTTL(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long setval; + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to ipDefaultTTL not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(setval)){ + fprintf(stderr,"write to ipDefaultTTL: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + setval = *(long *)var_val; + break; + + case RESERVE2: + case FREE: + case ACTION: + case UNDO: + break; + + case COMMIT: + ip_defttl = setval; + break; + } + return SNMP_ERR_NOERROR; +} + + +// --------------------------------------------------------------------------- +// writing these is not supported. The templates from mib2c are retained. +// +//NOTSUPPORTED: +#if 0 +int +write_ipNetToMediaIfIndex(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long *long_ret; + int size; + + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to ipNetToMediaIfIndex not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)){ + fprintf(stderr,"write to ipNetToMediaIfIndex: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + + case RESERVE2: + size = var_val_len; + long_ret = (long *) var_val; + + + break; + + + case FREE: + /* Release any resources that have been allocated */ + break; + + + case ACTION: + /* The variable has been stored in long_ret for + you to use, and you have just been asked to do something with + it. Note that anything done here must be reversable in the UNDO case */ + break; + + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} + + + + +int +write_ipNetToMediaPhysAddress(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static unsigned char string[SPRINT_MAX_LEN]; + int size; + + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_OCTET_STR){ + fprintf(stderr, "write to ipNetToMediaPhysAddress not ASN_OCTET_STR\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(string)){ + fprintf(stderr,"write to ipNetToMediaPhysAddress: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + + case RESERVE2: + size = var_val_len; + //string = (char *) var_val; + + + break; + + + case FREE: + /* Release any resources that have been allocated */ + break; + + + case ACTION: + /* The variable has been stored in string for + you to use, and you have just been asked to do something with + it. Note that anything done here must be reversable in the UNDO case */ + break; + + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} + + + + +int +write_ipNetToMediaNetAddress(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static unsigned char string[SPRINT_MAX_LEN]; + int size; + + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_IPADDRESS){ + fprintf(stderr, "write to ipNetToMediaNetAddress not ASN_IPADDRESS\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(string)){ + fprintf(stderr,"write to ipNetToMediaNetAddress: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + + case RESERVE2: + size = var_val_len; + //string = (char *) var_val; + + + break; + + + case FREE: + /* Release any resources that have been allocated */ + break; + + + case ACTION: + /* The variable has been stored in string for + you to use, and you have just been asked to do something with + it. Note that anything done here must be reversable in the UNDO case */ + break; + + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} + + + + +int +write_ipNetToMediaType(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long *long_ret; + int size; + + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to ipNetToMediaType not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)){ + fprintf(stderr,"write to ipNetToMediaType: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + + case RESERVE2: + size = var_val_len; + long_ret = (long *) var_val; + + + break; + + + case FREE: + /* Release any resources that have been allocated */ + break; + + + case ACTION: + /* The variable has been stored in long_ret for + you to use, and you have just been asked to do something with + it. Note that anything done here must be reversable in the UNDO case */ + break; + + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} + +#endif +// --------------------------------------------------------------------------- + +// EOF ip.c diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/snmp_mib.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/snmp_mib.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/snmp_mib.c @@ -0,0 +1,293 @@ +//========================================================================== +// +// ./agent/current/src/mibgroup/mibII/snmp_mib.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * SNMPv1 MIB group implementation - snmp.c + * + */ + +#include +#include +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#if HAVE_WINSOCK_H +#include +#endif + +#include "mibincl.h" +#include "system.h" +#include "mibgroup/util_funcs.h" + +#include "mibgroup/mibII/snmp_mib.h" +#include "mibgroup/mibII/sysORTable.h" + + + /********************* + * + * Kernel & interface information, + * and internal forward declarations + * + *********************/ + +extern int snmp_enableauthentraps; + int old_snmp_enableauthentraps; + +/********************* + * + * Initialisation & common implementation functions + * + *********************/ + +/* define the structure we're going to ask the agent to register our + information at */ +struct variable2 snmp_variables[] = { + {SNMPINPKTS, ASN_COUNTER, RONLY, var_snmp, 1, {1}}, + {SNMPOUTPKTS, ASN_COUNTER, RONLY, var_snmp, 1, {2}}, + {SNMPINBADVERSIONS, ASN_COUNTER, RONLY, var_snmp, 1, {3}}, + {SNMPINBADCOMMUNITYNAMES, ASN_COUNTER, RONLY, var_snmp, 1, {4}}, + {SNMPINBADCOMMUNITYUSES, ASN_COUNTER, RONLY, var_snmp, 1, {5}}, + {SNMPINASNPARSEERRORS, ASN_COUNTER, RONLY, var_snmp, 1, {6}}, + {SNMPINTOOBIGS, ASN_COUNTER, RONLY, var_snmp, 1, {8}}, + {SNMPINNOSUCHNAMES, ASN_COUNTER, RONLY, var_snmp, 1, {9}}, + {SNMPINBADVALUES, ASN_COUNTER, RONLY, var_snmp, 1, {10}}, + {SNMPINREADONLYS, ASN_COUNTER, RONLY, var_snmp, 1, {11}}, + {SNMPINGENERRS, ASN_COUNTER, RONLY, var_snmp, 1, {12}}, + {SNMPINTOTALREQVARS, ASN_COUNTER, RONLY, var_snmp, 1, {13}}, + {SNMPINTOTALSETVARS, ASN_COUNTER, RONLY, var_snmp, 1, {14}}, + {SNMPINGETREQUESTS, ASN_COUNTER, RONLY, var_snmp, 1, {15}}, + {SNMPINGETNEXTS, ASN_COUNTER, RONLY, var_snmp, 1, {16}}, + {SNMPINSETREQUESTS, ASN_COUNTER, RONLY, var_snmp, 1, {17}}, + {SNMPINGETRESPONSES, ASN_COUNTER, RONLY, var_snmp, 1, {18}}, + {SNMPINTRAPS, ASN_COUNTER, RONLY, var_snmp, 1, {19}}, + {SNMPOUTTOOBIGS, ASN_COUNTER, RONLY, var_snmp, 1, {20}}, + {SNMPOUTNOSUCHNAMES, ASN_COUNTER, RONLY, var_snmp, 1, {21}}, + {SNMPOUTBADVALUES, ASN_COUNTER, RONLY, var_snmp, 1, {22}}, + {SNMPOUTGENERRS, ASN_COUNTER, RONLY, var_snmp, 1, {24}}, + {SNMPOUTGETREQUESTS, ASN_COUNTER, RONLY, var_snmp, 1, {25}}, + {SNMPOUTGETNEXTS, ASN_COUNTER, RONLY, var_snmp, 1, {26}}, + {SNMPOUTSETREQUESTS, ASN_COUNTER, RONLY, var_snmp, 1, {27}}, + {SNMPOUTGETRESPONSES, ASN_COUNTER, RONLY, var_snmp, 1, {28}}, + {SNMPOUTTRAPS, ASN_COUNTER, RONLY, var_snmp, 1, {29}}, + {SNMPENABLEAUTHENTRAPS, ASN_INTEGER, RWRITE, var_snmp, 1, {30}}, + {SNMPSILENTDROPS, ASN_COUNTER, RONLY, var_snmp, 1, {31}}, + {SNMPPROXYDROPS, ASN_COUNTER, RONLY, var_snmp, 1, {32}} +}; + +/* Define the OID pointer to the top of the mib tree that we're + registering underneath */ +oid snmp_variables_oid[] = { SNMP_OID_MIB2,11 }; +#ifdef USING_MIBII_SYSTEM_MIB_MODULE +extern oid system_module_oid[]; +extern int system_module_oid_len; +extern int system_module_count; +#endif + +void +init_snmp_mib(void) { + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("mibII/snmp", snmp_variables, variable2, snmp_variables_oid); + +#ifdef USING_MIBII_SYSTEM_MIB_MODULE + if ( ++system_module_count == 3 ) + REGISTER_SYSOR_TABLE( system_module_oid, system_module_oid_len, + "The MIB module for SNMPv2 entities"); +#endif +} + +/* + header_snmp(... + Arguments: + vp IN - pointer to variable entry that points here + name IN/OUT - IN/name requested, OUT/name found + length IN/OUT - length of IN/OUT oid's + exact IN - TRUE if an exact match was requested + var_len OUT - length of variable or 0 if function returned + write_method + +*/ + + /********************* + * + * System specific implementation functions + * (actually common!) + * + *********************/ + + +u_char * +var_snmp(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + static long long_ret; + + *write_method = 0; /* assume it isnt writable for the time being */ + *var_len = sizeof(long_ret); /* assume an integer and change later if not */ + + if (header_generic(vp, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* this is where we do the value assignments for the mib results. */ + if (vp->magic == SNMPENABLEAUTHENTRAPS) { + *write_method = write_snmp; + long_return = snmp_enableauthentraps; + return (u_char *) &long_return; + } else if ( (vp->magic >= 1) + && (vp->magic <= (STAT_SNMP_STATS_END - STAT_SNMP_STATS_START + 1)) ) { + long_ret = snmp_get_statistic(vp->magic + STAT_SNMP_STATS_START - 1); + return (unsigned char *) &long_ret; + } + return NULL; +} + +/* + * only for snmpEnableAuthenTraps: + */ + +int +write_snmp (int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + long intval = *((long *) var_val); + + switch ( action ) { + case RESERVE1: /* Check values for acceptability */ + if (var_val_type != ASN_INTEGER){ + DEBUGMSGTL(("mibII/snmp_mib", "%x not integer type", var_val_type)); + return SNMP_ERR_WRONGTYPE; + } + + if (intval != 1 && intval != 2) { + DEBUGMSGTL(("mibII/snmp_mib", "not valid %x\n", intval)); + return SNMP_ERR_WRONGVALUE; + } + break; + + case RESERVE2: /* Allocate memory and similar resources */ + + /* Using static variables, so nothing needs to be done */ + break; + + case ACTION: /* Perform the SET action (if reversible) */ + + /* Save the old value, in case of UNDO */ + old_snmp_enableauthentraps = snmp_enableauthentraps; + snmp_enableauthentraps = intval; + break; + + case UNDO: /* Reverse the SET action and free resources */ + + snmp_enableauthentraps = old_snmp_enableauthentraps; + break; + + case COMMIT: /* Confirm the SET, performing any irreversible actions, + and free resources */ + /* save_into_conffile ("authentraps:", intval == 1 ? "yes" : "no"); */ + break; + + case FREE: /* Free any resources allocated */ + break; + } + return SNMP_ERR_NOERROR; +} + +/********************* + * + * Internal implementation functions + * + *********************/ diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/sysORTable.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/sysORTable.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/sysORTable.c @@ -0,0 +1,373 @@ +//========================================================================== +// +// ./agent/current/src/mibgroup/mibII/sysORTable.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * Template MIB group implementation - sysORTable.c + * + */ +#include +#if HAVE_STDLIB_H +#include +#endif +#include +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif + +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "mibincl.h" +#include "system.h" +#include "mibgroup/struct.h" +#include "mibgroup/util_funcs.h" +#include "mibgroup/mibII/sysORTable.h" +#include "snmpd.h" +#include "default_store.h" +#include "ds_agent.h" +#include "callback.h" +#include "agent_callbacks.h" + +#ifdef USING_AGENTX_SUBAGENT_MODULE +#include "agentx/subagent.h" +#include "agentx/client.h" +#endif + +extern struct timeval starttime; + +struct timeval sysOR_lastchange; +static struct sysORTable *table=NULL; +static int numEntries=0; + +/* define the structure we're going to ask the agent to register our + information at */ +struct variable2 sysORTable_variables[] = { + { SYSORTABLEID, ASN_OBJECT_ID, RONLY, var_sysORTable, 1, {2}}, + { SYSORTABLEDESCR, ASN_OCTET_STR, RONLY, var_sysORTable, 1, {3}}, + { SYSORTABLEUPTIME, ASN_TIMETICKS, RONLY, var_sysORTable, 1, {4}} +}; + +/* Define the OID pointer to the top of the mib tree that we're + registering underneath */ +oid sysORTable_variables_oid[] = { SNMP_OID_MIB2,1,9,1 }; +#ifdef USING_MIBII_SYSTEM_MIB_MODULE +extern oid system_module_oid[]; +extern int system_module_oid_len; +extern int system_module_count; +#endif + +void +init_sysORTable(void) { + /* register ourselves with the agent to handle our mib tree */ + +#ifdef USING_AGENTX_SUBAGENT_MODULE + if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == MASTER_AGENT ) + (void)register_mib_priority("mibII/sysORTable", + (struct variable *) sysORTable_variables, + sizeof(struct variable2), + sizeof(sysORTable_variables)/sizeof(struct variable2), + sysORTable_variables_oid, + sizeof(sysORTable_variables_oid)/sizeof(oid), 1); + else +#endif + REGISTER_MIB("mibII/sysORTable", sysORTable_variables, variable2, sysORTable_variables_oid); + +#ifdef USING_MIBII_SYSTEM_MIB_MODULE + if ( ++system_module_count == 3 ) + REGISTER_SYSOR_TABLE( system_module_oid, system_module_oid_len, + "The MIB module for SNMPv2 entities"); +#endif + + gettimeofday(&sysOR_lastchange, NULL); +} + + /********************* + * + * System specific implementation functions + * + *********************/ + +u_char * +var_sysORTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + struct timeval diff; + int i; + struct sysORTable *ptr; + + if (header_simple_table(vp, name, length, exact, var_len, write_method, numEntries)) + return NULL; + + DEBUGMSGTL(("mibII/sysORTable", "sysORTable -- ")); + for(i = 1, ptr=table; ptr != NULL && i < (int)name[*length-1]; + ptr = ptr->next, i++) { + DEBUGMSGTL(("mibII/sysORTable", "sysORTable -- %d != %d\n",i,name[*length-1])); + } + if (ptr == NULL) { + DEBUGMSGTL(("mibII/sysORTable", "sysORTable -- no match: %d\n",i)); + return NULL; + } + DEBUGMSGTL(("mibII/sysORTable", "sysORTable -- match: %d\n",i)); + + switch (vp->magic){ + case SYSORTABLEID: + *var_len = ptr->OR_oidlen*sizeof(ptr->OR_oid[0]); + return (u_char *) ptr->OR_oid; + + case SYSORTABLEDESCR: + *var_len = strlen(ptr->OR_descr); + return (u_char *) ptr->OR_descr; + + case SYSORTABLEUPTIME: + ptr->OR_uptime.tv_sec--; + ptr->OR_uptime.tv_usec += 1000000L; + diff.tv_sec = ptr->OR_uptime.tv_sec - 1 - starttime.tv_sec; + diff.tv_usec = ptr->OR_uptime.tv_usec + 1000000L - starttime.tv_usec; + if (diff.tv_usec > 1000000L){ + diff.tv_usec -= 1000000L; + diff.tv_sec++; + } + if ((diff.tv_sec * 100) + (diff.tv_usec / 10000) < 0) + long_return = 0; + else + long_return = ((diff.tv_sec * 100) + (diff.tv_usec / 10000)); + return ((u_char *) &long_return); + + default: + DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_sysORTable\n", vp->magic)); + } + return NULL; +} + + +int register_sysORTable_sess(oid *oidin, + size_t oidlen, + const char *descr, + struct snmp_session *ss) +{ + struct sysORTable **ptr=&table; + struct register_sysOR_parameters reg_sysOR_parms; + + DEBUGMSGTL(("mibII/sysORTable", "sysORTable registering: ")); + DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen)); + DEBUGMSG(("mibII/sysORTable","\n")); + + while(*ptr != NULL) + ptr = &((*ptr)->next); + *ptr = (struct sysORTable *) malloc(sizeof(struct sysORTable)); + if ( *ptr == NULL ) { + return SYS_ORTABLE_REGISTRATION_FAILED; + } + (*ptr)->OR_descr = (char *) malloc(strlen(descr)+1); + if ( (*ptr)->OR_descr == NULL ) { + free( *ptr ); + return SYS_ORTABLE_REGISTRATION_FAILED; + } + strcpy((*ptr)->OR_descr, descr); + (*ptr)->OR_oidlen = oidlen; + (*ptr)->OR_oid = (oid *) malloc(sizeof(oid)*oidlen); + if ( (*ptr)->OR_oid == NULL ) { + free( *ptr ); + free( (*ptr)->OR_descr ); + return SYS_ORTABLE_REGISTRATION_FAILED; + } + memcpy((*ptr)->OR_oid, oidin, sizeof(oid)*oidlen); + gettimeofday(&((*ptr)->OR_uptime), NULL); + (*ptr)->OR_sess = ss; + (*ptr)->next = NULL; + numEntries++; + + reg_sysOR_parms.name = oidin; + reg_sysOR_parms.namelen = oidlen; + reg_sysOR_parms.descr = descr; + snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REG_SYSOR, + ®_sysOR_parms); + + return SYS_ORTABLE_REGISTERED_OK; +} + +int register_sysORTable(oid *oidin, + size_t oidlen, + const char *descr) +{ + return register_sysORTable_sess( oidin, oidlen, descr, NULL ); +} + + + +int unregister_sysORTable_sess(oid *oidin, + size_t oidlen, + struct snmp_session *ss) +{ + struct sysORTable **ptr=&table, *prev=NULL; + int found = SYS_ORTABLE_NO_SUCH_REGISTRATION; + struct register_sysOR_parameters reg_sysOR_parms; + + DEBUGMSGTL(("mibII/sysORTable", "sysORTable unregistering: ")); + DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen)); + DEBUGMSG(("mibII/sysORTable","\n")); + + while(*ptr != NULL) { + if ( snmp_oid_compare( oidin, oidlen, (*ptr)->OR_oid, (*ptr)->OR_oidlen) == 0 ) { + if ( (*ptr)->OR_sess != ss ) + continue; /* different session */ + if ( prev == NULL ) + table = (*ptr)->next; + else + prev->next = (*ptr)->next; + + free( (*ptr)->OR_descr ); + free( (*ptr)->OR_oid ); + free( (*ptr) ); + numEntries--; + found = SYS_ORTABLE_UNREGISTERED_OK; + break; + } + prev = *ptr; + ptr = &((*ptr)->next); + } + + reg_sysOR_parms.name = oidin; + reg_sysOR_parms.namelen = oidlen; + snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREG_SYSOR, + ®_sysOR_parms); + + return found; +} + + +int unregister_sysORTable(oid *oidin, + size_t oidlen) +{ + return unregister_sysORTable_sess( oidin, oidlen, NULL ); +} + +void unregister_sysORTable_by_session(struct snmp_session *ss) +{ + struct sysORTable *ptr=table, *prev=NULL, *next; + + while ( ptr != NULL ) { + next = ptr->next; + if (( (ss->flags & SNMP_FLAGS_SUBSESSION) && ptr->OR_sess == ss ) || + (!(ss->flags & SNMP_FLAGS_SUBSESSION) && + ptr->OR_sess->subsession == ss )) { + if ( prev == NULL ) + table = next; + else + prev->next = next; + free( ptr->OR_descr ); + free( ptr->OR_oid ); + free( ptr ); + numEntries--; + + } + else + prev = ptr; + ptr = next; + } +} + diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/system_mib.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/system_mib.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/system_mib.c @@ -0,0 +1,508 @@ +//========================================================================== +// +// ./agent/current/src/mibgroup/mibII/system_mib.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * System MIB group implementation - system.c + * + */ + +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_SYS_TIME_H +#include +#endif + +#include +#if HAVE_UTSNAME_H +#include +#else +#if HAVE_SYS_UTSNAME_H +#include +#endif +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "mibincl.h" +#include "mibgroup/mibII/system_mib.h" +#include "mibgroup/struct.h" +#include "mibgroup/util_funcs.h" +#include "read_config.h" +#include "agent_read_config.h" +#include "system.h" +#include "mibgroup/mibII/sysORTable.h" + + + /********************* + * + * Kernel & interface information, + * and internal forward declarations + * + *********************/ + +#define SYS_STRING_LEN 256 +char version_descr[ SYS_STRING_LEN ] = VERS_DESC; +char sysContact[ SYS_STRING_LEN ] = SYS_CONTACT; +char sysName[ SYS_STRING_LEN ] = SYS_NAME; +char sysLocation[ SYS_STRING_LEN ] = SYS_LOC; + +char oldversion_descr[ SYS_STRING_LEN ]; +char oldsysContact[ SYS_STRING_LEN ]; +char oldsysName[ SYS_STRING_LEN ]; +char oldsysLocation[ SYS_STRING_LEN ]; + +int sysServices=72; +int sysServicesConfiged=0; + +extern oid version_id[]; +extern int version_id_len; + +extern struct timeval starttime; + +WriteMethod writeSystem; +int header_system(struct variable *,oid *, size_t *, int, size_t *, WriteMethod **); + +/* snmpd.conf config parsing */ + +void system_parse_config_sysloc(const char *token, + char *cptr) +{ + char tmpbuf[1024]; + + if (strlen(cptr) < sizeof(sysLocation)) { + strcpy(sysLocation,cptr); + } else { + sprintf(tmpbuf, "syslocation token too long (must be < %d):\n\t%s", + sizeof(sysLocation), cptr); + config_perror(tmpbuf); + } +} + +void system_parse_config_sysServices(const char *token, char *cptr) +{ + sysServices = atoi(cptr); + sysServicesConfiged = 1; +} + +void system_parse_config_syscon(const char *token, + char *cptr) +{ + char tmpbuf[1024]; + + if (strlen(cptr) < sizeof(sysContact)) { + strcpy(sysContact,cptr); + } else { + sprintf(tmpbuf, "syscontact token too long (must be < %d):\n\t%s", + sizeof(sysContact), cptr); + config_perror(tmpbuf); + } +} + + + /********************* + * + * Initialisation & common implementation functions + * + *********************/ + +/* define the structure we're going to ask the agent to register our + information at */ +struct variable2 system_variables[] = { + {VERSION_DESCR, ASN_OCTET_STR, RONLY, var_system, 1, {1}}, + {VERSIONID, ASN_OBJECT_ID, RONLY, var_system, 1, {2}}, + {UPTIME, ASN_TIMETICKS, RONLY, var_system, 1, {3}}, + {SYSCONTACT, ASN_OCTET_STR, RWRITE, var_system, 1, {4}}, + {SYSTEMNAME, ASN_OCTET_STR, RWRITE, var_system, 1, {5}}, + {SYSLOCATION, ASN_OCTET_STR, RWRITE, var_system, 1, {6}}, + {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}}, + {SYSORLASTCHANGE, ASN_TIMETICKS, RONLY, var_system, 1, {8}} +}; +/* Define the OID pointer to the top of the mib tree that we're + registering underneath */ +oid system_variables_oid[] = { SNMP_OID_MIB2,1 }; +oid system_module_oid[] = { SNMP_OID_SNMPMODULES,1 }; +int system_module_oid_len = sizeof( system_module_oid ) / sizeof( oid ); +int system_module_count = 0; + +void init_system_mib(void) +{ + +#ifdef HAVE_UNAME + struct utsname utsName; + + uname(&utsName); + sprintf(version_descr, "%s %s %s %s %s", utsName.sysname, utsName.nodename, + utsName.release, utsName.version, utsName.machine); +#else +#if HAVE_EXECV + struct extensible extmp; + + /* set default values of system stuff */ + sprintf(extmp.command,"%s -a",UNAMEPROG); + /* setup defaults */ + extmp.type = EXECPROC; + extmp.next = NULL; + exec_command(&extmp); + strncpy(version_descr,extmp.output, sizeof(version_descr)); + version_descr[strlen(version_descr)-1] = 0; /* chomp new line */ +#else +#ifdef __ECOS + sysServicesConfiged = 1; // May as well return the dummy value +#else +#endif // !__ECOS +#endif // !HAVE_EXECV +#endif // !HAVE_UNAME + +#ifdef HAVE_GETHOSTNAME + gethostname(sysName,sizeof(sysName)); +#else +#ifdef HAVE_UNAME + strncpy(sysName,utsName.nodename,sizeof(sysName)); +#else +#if HAVE_EXECV + sprintf(extmp.command,"%s -n",UNAMEPROG); + /* setup defaults */ + extmp.type = EXECPROC; + extmp.next = NULL; + exec_command(&extmp); + strncpy(sysName,extmp.output, sizeof(sysName)); + sysName[strlen(sysName)-1] = 0; /* chomp new line */ +#endif /* HAVE_EXECV */ +#endif /* HAVE_UNAME */ +#endif /* HAVE_GETHOSTNAME */ + + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("mibII/system", system_variables, variable2, \ + system_variables_oid); + + if ( ++system_module_count == 3 ) + REGISTER_SYSOR_ENTRY( system_module_oid, + "The MIB module for SNMPv2 entities"); + + /* register our config handlers */ + snmpd_register_config_handler("syslocation", system_parse_config_sysloc, + NULL, "location"); + snmpd_register_config_handler("syscontact", system_parse_config_syscon, + NULL,"contact-name"); + snmpd_register_config_handler("sysservices", system_parse_config_sysServices, + NULL,"NUMBER"); + +} + +/* + header_system(... + Arguments: + vp IN - pointer to variable entry that points here + name IN/OUT - IN/name requested, OUT/name found + length IN/OUT - length of IN/OUT oid's + exact IN - TRUE if an exact match was requested + var_len OUT - length of variable or 0 if function returned + write_method + +*/ + +int +header_system(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ +#define SYSTEM_NAME_LENGTH 8 + oid newname[MAX_OID_LEN]; + int result; + + DEBUGMSGTL(("mibII/system", "var_system: ")); + DEBUGMSGOID(("mibII/system", name, *length)); + DEBUGMSG(("mibII/system"," %d\n", exact)); + + memcpy((char *)newname, (char *)vp->name, vp->namelen * sizeof(oid)); + newname[SYSTEM_NAME_LENGTH] = 0; + result = snmp_oid_compare(name, *length, newname, vp->namelen + 1); + if ((exact && (result != 0)) || (!exact && (result >= 0))) + return(MATCH_FAILED); + memcpy( (char *)name,(char *)newname, (vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + + *write_method = 0; + *var_len = sizeof(long); /* default to 'long' results */ + return(MATCH_SUCCEEDED); +} + + /********************* + * + * System specific implementation functions + * (actually common!) + * + *********************/ + +#ifdef USING_MIBII_SYSORTABLE_MODULE +extern struct timeval sysOR_lastchange; +#endif + +u_char * +var_system(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + + struct timeval now, diff; + + if (header_system(vp, name, length, exact, var_len, write_method) == MATCH_FAILED ) + return NULL; + + switch (vp->magic){ + case VERSION_DESCR: + *var_len = strlen(version_descr); + *write_method = writeSystem; + return (u_char *)version_descr; + case VERSIONID: + *var_len = version_id_len*sizeof(version_id[0]); + return (u_char *)version_id; + case UPTIME: + gettimeofday(&now, NULL); + now.tv_sec--; + now.tv_usec += 1000000L; + diff.tv_sec = now.tv_sec - starttime.tv_sec; + diff.tv_usec = now.tv_usec - starttime.tv_usec; + if (diff.tv_usec > 1000000L){ + diff.tv_usec -= 1000000L; + diff.tv_sec++; + } + long_return = ((diff.tv_sec * 100) + (diff.tv_usec / 10000)); + return ((u_char *) &long_return); + case SYSCONTACT: + *var_len = strlen(sysContact); + *write_method = writeSystem; + return (u_char *)sysContact; + case SYSTEMNAME: + *var_len = strlen(sysName); + *write_method = writeSystem; + return (u_char *)sysName; + case SYSLOCATION: + *var_len = strlen(sysLocation); + *write_method = writeSystem; + return (u_char *)sysLocation; + case SYSSERVICES: +#if NO_DUMMY_VALUES + if (!sysServicesConfiged) + return NULL; +#endif + long_return = sysServices; + return (u_char *)&long_return; + +#ifdef USING_MIBII_SYSORTABLE_MODULE + case SYSORLASTCHANGE: + diff.tv_sec = sysOR_lastchange.tv_sec - 1 - starttime.tv_sec; + diff.tv_usec = + sysOR_lastchange.tv_usec + 1000000L - starttime.tv_usec; + if (diff.tv_usec > 1000000L){ + diff.tv_usec -= 1000000L; + diff.tv_sec++; + } + if ((diff.tv_sec * 100) + (diff.tv_usec / 10000) < 0) + long_return = 0; + else + long_return = ((diff.tv_sec * 100) + (diff.tv_usec / 10000)); + return ((u_char *) &long_return); +#endif + + default: + DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_system\n", vp->magic)); + } + return NULL; +} + + + +int +writeSystem(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + u_char *cp; + char *buf = NULL, *oldbuf = NULL; + int count; + + switch((char)name[7]){ + case VERSION_DESCR: + buf = version_descr; + oldbuf = oldversion_descr; + break; + case SYSCONTACT: + buf = sysContact; + oldbuf = oldsysContact; + break; + case SYSTEMNAME: + buf = sysName; + oldbuf = oldsysName; + break; + case SYSLOCATION: + buf = sysLocation; + oldbuf = oldsysLocation; + break; + default: + return SNMP_ERR_GENERR; /* ??? */ + } + + switch ( action ) { + case RESERVE1: /* Check values for acceptability */ + if (var_val_type != ASN_OCTET_STR){ + snmp_log(LOG_ERR, "not string\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(version_descr)-1){ + snmp_log(LOG_ERR, "bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + + for(cp = var_val, count = 0; count < (int)var_val_len; count++, cp++){ + if (!isprint(*cp)){ + snmp_log(LOG_ERR, "not print %x\n", *cp); + return SNMP_ERR_WRONGVALUE; + } + } + break; + + case RESERVE2: /* Allocate memory and similar resources */ + + /* Using static strings, so nothing needs to be done */ + break; + + case ACTION: /* Perform the SET action (if reversible) */ + + /* Save the old value, in case of UNDO */ + strcpy( oldbuf, buf); + memcpy( buf, var_val, var_val_len); + buf[var_val_len] = 0; + break; + + case UNDO: /* Reverse the SET action and free resources */ + + strcpy( buf, oldbuf); + oldbuf[0] = 0; + break; + + case COMMIT: /* Confirm the SET, performing any irreversible actions, + and free resources */ + case FREE: /* Free any resources allocated */ + + /* No resources have been allocated, but "empty" the 'oldbuf' */ + oldbuf[0] = 0; + break; + } + return SNMP_ERR_NOERROR; +} /* end of writeSystem */ + + /********************* + * + * Internal implementation functions - None + * + *********************/ + diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/tcp.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/tcp.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/tcp.c @@ -0,0 +1,646 @@ +//========================================================================== +// +// snmp/snmpagent/current/src/mibgroup/mibII/tcp.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +/* This should always be included first before anything else */ +#include + + +/* minimal include directives */ +#include "mibincl.h" +#include "mibgroup/util_funcs.h" +#include "mibgroup/mibII/tcp.h" + +#include + +#define _KERNEL +#include +#include +#include +#include +#include +#include +//#define TCPOUTFLAGS +#include +#include +#include +#include +#include +#include + +/* + * tcp_variables_oid: + * this is the top level oid that we want to register under. This + * is essentially a prefix, with the suffix appearing in the + * variable below. + */ + + +oid tcp_variables_oid[] = { 1,3,6,1,2,1,6 }; + + +/* + * variable4 tcp_variables: + * this variable defines function callbacks and type return information + * for the tcp mib section + */ + + +struct variable4 tcp_variables[] = { +/* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +#define TCPRTOALGORITHM 1 + { TCPRTOALGORITHM , ASN_INTEGER , RONLY , var_tcp, 1, { 1 } }, +#define TCPRTOMIN 2 + { TCPRTOMIN , ASN_INTEGER , RONLY , var_tcp, 1, { 2 } }, +#define TCPRTOMAX 3 + { TCPRTOMAX , ASN_INTEGER , RONLY , var_tcp, 1, { 3 } }, +#define TCPMAXCONN 4 + { TCPMAXCONN , ASN_INTEGER , RONLY , var_tcp, 1, { 4 } }, +#define TCPACTIVEOPENS 5 + { TCPACTIVEOPENS , ASN_COUNTER , RONLY , var_tcp, 1, { 5 } }, +#define TCPPASSIVEOPENS 6 + { TCPPASSIVEOPENS , ASN_COUNTER , RONLY , var_tcp, 1, { 6 } }, +#define TCPATTEMPTFAILS 7 + { TCPATTEMPTFAILS , ASN_COUNTER , RONLY , var_tcp, 1, { 7 } }, +#define TCPESTABRESETS 8 + { TCPESTABRESETS , ASN_COUNTER , RONLY , var_tcp, 1, { 8 } }, +#define TCPCURRESTAB 9 + { TCPCURRESTAB , ASN_GAUGE , RONLY , var_tcp, 1, { 9 } }, +#define TCPINSEGS 10 + { TCPINSEGS , ASN_COUNTER , RONLY , var_tcp, 1, { 10 } }, +#define TCPOUTSEGS 11 + { TCPOUTSEGS , ASN_COUNTER , RONLY , var_tcp, 1, { 11 } }, +#define TCPRETRANSSEGS 12 + { TCPRETRANSSEGS , ASN_COUNTER , RONLY , var_tcp, 1, { 12 } }, +#define TCPCONNSTATE 15 + { TCPCONNSTATE , ASN_INTEGER , RWRITE, var_tcpConnTable, 3, { 13,1,1 } }, +#define TCPCONNLOCALADDRESS 16 + { TCPCONNLOCALADDRESS , ASN_IPADDRESS , RONLY , var_tcpConnTable, 3, { 13,1,2 } }, +#define TCPCONNLOCALPORT 17 + { TCPCONNLOCALPORT , ASN_INTEGER , RONLY , var_tcpConnTable, 3, { 13,1,3 } }, +#define TCPCONNREMADDRESS 18 + { TCPCONNREMADDRESS , ASN_IPADDRESS , RONLY , var_tcpConnTable, 3, { 13,1,4 } }, +#define TCPCONNREMPORT 19 + { TCPCONNREMPORT , ASN_INTEGER , RONLY , var_tcpConnTable, 3, { 13,1,5 } }, +#define TCPINERRS 20 + { TCPINERRS , ASN_COUNTER , RONLY , var_tcp, 1, { 14 } }, +#define TCPOUTRSTS 21 + { TCPOUTRSTS , ASN_COUNTER , RONLY , var_tcp, 1, { 15 } }, +//#define IPV6TCPCONNSTATE 29 +// { IPV6TCPCONNSTATE , ASN_INTEGER , RWRITE, var_ipv6TcpConnTable, 3, { 16,1,6 } }, + +}; +/* (L = length of the oidsuffix) */ + + +/* + * init_tcp(): + * Initialization routine. This is called when the agent starts up. + * At a minimum, registration of your variables should take place here. + */ +void init_tcp(void) { + + + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("tcp", tcp_variables, variable4, + tcp_variables_oid); + + + /* place any other initialization junk you need here */ +} + + +/* + * var_tcp(): + * This function is called every time the agent gets a request for + * a scalar variable that might be found within your mib section + * registered above. It is up to you to do the right thing and + * return the correct value. + * You should also correct the value of "var_len" if necessary. + * + * Please see the documentation for more information about writing + * module extensions, and check out the examples in the examples + * and mibII directories. + */ +unsigned char * +var_tcp(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + static long long_ret; + + if (header_generic(vp,name,length,exact,var_len,write_method) + == MATCH_FAILED ) + return NULL; + + switch(vp->magic) { + + case TCPRTOALGORITHM: + long_ret = 1; // meaning "other" + return (unsigned char *) &long_ret; + + case TCPRTOMIN: + long_ret = TCPTV_MIN / PR_SLOWHZ * 1000;; + return (unsigned char *) &long_ret; + + case TCPRTOMAX: + long_ret = TCPTV_REXMTMAX / PR_SLOWHZ * 1000;; + return (unsigned char *) &long_ret; + + case TCPMAXCONN: + long_ret = -1; // It is dynamic. + return (unsigned char *) &long_ret; + + case TCPACTIVEOPENS: + long_ret = tcpstat.tcps_connattempt; + return (unsigned char *) &long_ret; + + case TCPPASSIVEOPENS: + long_ret = tcpstat.tcps_accepts; + return (unsigned char *) &long_ret; + + case TCPATTEMPTFAILS: + long_ret = tcpstat.tcps_conndrops; + return (unsigned char *) &long_ret; + + case TCPESTABRESETS: + long_ret = tcpstat.tcps_drops; + return (unsigned char *) &long_ret; + + case TCPCURRESTAB: { + struct inpcb *inp; + long_ret = 0; + for (inp = tcbtable.inpt_queue.cqh_first; + inp != (struct inpcb *)&tcbtable.inpt_queue; + inp = inp->inp_queue.cqe_next) { + struct tcpcb *tp = intotcpcb( inp ); + if ( tp && (TCPS_ESTABLISHED == tp->t_state || + TCPS_CLOSE_WAIT == tp->t_state) ) + long_ret++; + } + return (unsigned char *) &long_ret; + } + + case TCPINSEGS: + long_ret = tcpstat.tcps_rcvtotal; + return (unsigned char *) &long_ret; + + case TCPOUTSEGS: + long_ret = tcpstat.tcps_sndtotal - tcpstat.tcps_sndrexmitpack; + if ( long_ret < 0 ) + long_ret = 0; + return (unsigned char *) &long_ret; + + case TCPRETRANSSEGS: + long_ret = tcpstat.tcps_sndrexmitpack; + return (unsigned char *) &long_ret; + + case TCPINERRS: + long_ret = tcpstat.tcps_rcvbadsum + + tcpstat.tcps_rcvbadoff + + tcpstat.tcps_rcvshort + + tcpstat.tcps_rcvmemdrop; // Is that last one an input error? + return (unsigned char *) &long_ret; + + case TCPOUTRSTS: + long_ret = tcpstat.tcps_sndctrl - tcpstat.tcps_closed; + if ( long_ret < 0 ) + long_ret = 0; + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + + + + +/* + * var_tcpConnTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_tcpConnTable above. + */ +unsigned char * +var_tcpConnTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + register struct inpcb *inp; + register struct inpcb *low_inp = NULL; + oid lowest[24]; + oid newname[24]; + u_char *cp; + oid *op; + struct tcpcb *tp; + + // This is indexed by local-address, local-port, remote-address, remport + // at 1,3,6,1,2,1,6,13,1 + // so we get 1,3,6,1,2,1,6,13,1,?,A,B,C,D,lport,P,Q,R,S,rport + // initial length is 10, out-length is 20, + // Local address is offsets 10-13, port is offset 14. + // Remote address is offsets 15-18, port is offset 19. + + // starting from udbtable, look in + // low_pcb->inp_laddr.s_addr + // and low_pcb->inp_lport + // /_l/_f/ for foreign port,address. + + /* fill in object part of name for current (less sizeof instance part) */ + memcpy((char *)newname, (char *)vp->name, (int)vp->namelen * sizeof(oid)); + + for (inp = tcbtable.inpt_queue.cqh_first; + inp != (struct inpcb *)&tcbtable.inpt_queue; + inp = inp->inp_queue.cqe_next) { + + cp = (u_char *)&inp->inp_laddr.s_addr; + op = newname + 10; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + + newname[14] = ntohs(inp->inp_lport); + + cp = (u_char *)&inp->inp_faddr.s_addr; + op = newname + 15; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + + newname[19] = ntohs(inp->inp_fport); + + if (exact){ + if (snmp_oid_compare(newname, 20, name, *length) == 0){ + memcpy( (char *)lowest,(char *)newname, 20 * sizeof(oid)); + low_inp = inp; + break; /* no need to search further */ + } + } else { + if ((snmp_oid_compare(newname, 20, name, *length) > 0) && + (!low_inp || (snmp_oid_compare(newname, 20, lowest, 20) < 0))){ + /* + * if new one is greater than input and closer to input than + * previous lowest, save this one as the "next" one. + */ + memcpy( (char *)lowest,(char *)newname, 20 * sizeof(oid)); + low_inp = inp; + } + } + } + + if ( ! low_inp ) + return NULL; + + tp = intotcpcb( low_inp ); + if ( ! tp ) + return NULL; // Shouldn't happen + + memcpy( (char *)name,(char *)lowest, 20 * sizeof(oid)); + *length = 20; + *var_len = sizeof( long_ret ); + *write_method = 0; + + switch(vp->magic) { + case TCPCONNSTATE: + // NOTSUPPORTED: *write_method = write_tcpConnState; + switch ( tp->t_state ) { + case TCPS_CLOSED : // 0 /* closed */ + long_ret = 1; break; + case TCPS_LISTEN : // 1 /* listening for connection */ + long_ret = 2; break; + case TCPS_SYN_SENT : // 2 /* active, have sent syn */ + long_ret = 3; break; + case TCPS_SYN_RECEIVED : // 3 /* have sent and received syn */ + long_ret = 4; break; + case TCPS_ESTABLISHED : // 4 /* established */ + long_ret = 5; break; + case TCPS_CLOSE_WAIT : // 5 /* rcvd fin, waiting for close */ + long_ret = 8; break; + case TCPS_FIN_WAIT_1 : // 6 /* have closed, sent fin */ + long_ret = 6; break; + case TCPS_CLOSING : // 7 /* closed xchd FIN; await ACK */ + long_ret = 10; break; + case TCPS_LAST_ACK : // 8 /* had fin and close; await FIN ACK */ + long_ret = 9; break; + case TCPS_FIN_WAIT_2 : // 9 /* have closed, fin is acked */ + long_ret = 7; break; + case TCPS_TIME_WAIT : // 10 /* in 2*msl quiet wait after close */ + long_ret = 11; break; + default: + long_ret = 1; + } + return (unsigned char *) &long_ret; + + case TCPCONNLOCALADDRESS: + cp = (u_char *)&low_inp->inp_laddr.s_addr; + string[0] = *cp++; + string[1] = *cp++; + string[2] = *cp++; + string[3] = *cp++; + *var_len = 4; + return (unsigned char *) string; + + case TCPCONNLOCALPORT: + long_ret = (long)ntohs(low_inp->inp_lport); + return (unsigned char *) &long_ret; + + case TCPCONNREMADDRESS: + cp = (u_char *)&low_inp->inp_faddr.s_addr; + string[0] = *cp++; + string[1] = *cp++; + string[2] = *cp++; + string[3] = *cp++; + *var_len = 4; + return (unsigned char *) string; + + case TCPCONNREMPORT: + long_ret = (long)ntohs(low_inp->inp_fport); + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + + +#if 0 // NOTSUPPORTED: +int +write_tcpConnState(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long *long_ret; + int size; + + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to tcpConnState not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)){ + fprintf(stderr,"write to tcpConnState: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + + case RESERVE2: + size = var_val_len; + long_ret = (long *) var_val; + + + break; + + + case FREE: + /* Release any resources that have been allocated */ + break; + + + case ACTION: + /* The variable has been stored in long_ret for + you to use, and you have just been asked to do something with + it. Note that anything done here must be reversable in the UNDO case */ + break; + + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} + +#endif + + + + +#if 0 // NOTSUPPORTED: +/* + * var_ipv6TcpConnTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_tcp above. + */ +unsigned char * +var_ipv6TcpConnTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + + + /* variables we may use later */ + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + static oid objid[MAX_OID_LEN]; + static struct counter64 c64; + + + /* + * This assumes that the table is a 'simple' table. + * See the implementation documentation for the meaning of this. + * You will need to provide the correct value for the TABLE_SIZE parameter + * + * If this table does not meet the requirements for a simple table, + * you will need to provide the replacement code yourself. + * Mib2c is not smart enough to write this for you. + * Again, see the implementation documentation for what is required. + */ +// if (header_simple_table(vp,name,length,exact,var_len,write_method, +// IPV6TCPCONNTABLE_TABLE_SIZE) +// == MATCH_FAILED ) + return NULL; + + + /* + * this is where we do the value assignments for the mib results. + */ + switch(vp->magic) { + + + case IPV6TCPCONNSTATE: + *write_method = write_ipv6TcpConnState; + long_ret = 0; + return (unsigned char *) &long_ret; + + + default: + ERROR_MSG(""); + } + return NULL; +} + + + + +int +write_ipv6TcpConnState(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + static long *long_ret; + int size; + + + switch ( action ) { + case RESERVE1: + if (var_val_type != ASN_INTEGER){ + fprintf(stderr, "write to tcpConnState not ASN_INTEGER\n"); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)){ + fprintf(stderr,"write to tcpConnState: bad length\n"); + return SNMP_ERR_WRONGLENGTH; + } + break; + + + case RESERVE2: + size = var_val_len; + long_ret = (long *) var_val; + + + break; + + + case FREE: + /* Release any resources that have been allocated */ + break; + + + case ACTION: + /* The variable has been stored in long_ret for + you to use, and you have just been asked to do something with + it. Note that anything done here must be reversable in the UNDO case */ + break; + + + case UNDO: + /* Back out any changes made in the ACTION case */ + break; + + + case COMMIT: + /* Things are working well, so it's now safe to make the change + permanently. Make sure that anything done here can't fail! */ + break; + } + return SNMP_ERR_NOERROR; +} + +#endif // NOTSUPPORTED: ipv6 + +// EOF tcp.c diff --git a/packages/net/snmp/agent/current/src/mibgroup/mibII/udp.c b/packages/net/snmp/agent/current/src/mibgroup/mibII/udp.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/mibII/udp.c @@ -0,0 +1,312 @@ +//========================================================================== +// +// snmp/snmpagent/current/src/mibgroup/mibII/udp.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* This file was generated by mib2c and is intended for use as a mib module + for the ucd-snmp snmpd agent. */ + + +/* This should always be included first before anything else */ +#include + + +/* minimal include directives */ +#include "mibincl.h" +#include "mibgroup/util_funcs.h" +#include "mibgroup/mibII/udp.h" + + + +#define _KERNEL + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * udp_variables_oid: + * this is the top level oid that we want to register under. This + * is essentially a prefix, with the suffix appearing in the + * variable below. + */ + + +oid udp_variables_oid[] = { 1,3,6,1,2,1,7 }; + + +/* + * variable4 udp_variables: + * this variable defines function callbacks and type return information + * for the udp mib section + */ + + +struct variable4 udp_variables[] = { +/* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +#define UDPINDATAGRAMS 1 + { UDPINDATAGRAMS , ASN_COUNTER , RONLY , var_udp, 1, { 1 } }, +#define UDPNOPORTS 2 + { UDPNOPORTS , ASN_COUNTER , RONLY , var_udp, 1, { 2 } }, +#define UDPINERRORS 3 + { UDPINERRORS , ASN_COUNTER , RONLY , var_udp, 1, { 3 } }, +#define UDPOUTDATAGRAMS 4 + { UDPOUTDATAGRAMS , ASN_COUNTER , RONLY , var_udp, 1, { 4 } }, +#define UDPLOCALADDRESS 7 + { UDPLOCALADDRESS , ASN_IPADDRESS , RONLY , var_udpTable, 3, { 5,1,1 } }, +#define UDPLOCALPORT 8 + { UDPLOCALPORT , ASN_INTEGER , RONLY , var_udpTable, 3, { 5,1,2 } }, + +//#define IPV6UDPIFINDEX 13 +// { IPV6UDPIFINDEX , ASN_INTEGER , RONLY , var_ipv6UdpTable, 3, { 6,1,3 } }, + +}; +/* (L = length of the oidsuffix) */ + + +/* + * init_udp(): + * Initialization routine. This is called when the agent starts up. + * At a minimum, registration of your variables should take place here. + */ +void init_udp(void) { + + + /* register ourselves with the agent to handle our mib tree */ + REGISTER_MIB("udp", udp_variables, variable4, + udp_variables_oid); + + + /* place any other initialization junk you need here */ +} + + +/* + * var_udp(): + * This function is called every time the agent gets a request for + * a scalar variable that might be found within your mib section + * registered above. It is up to you to do the right thing and + * return the correct value. + * You should also correct the value of "var_len" if necessary. + * + * Please see the documentation for more information about writing + * module extensions, and check out the examples in the examples + * and mibII directories. + */ +unsigned char * +var_udp(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + static long long_ret; + + if (header_generic(vp,name,length,exact,var_len,write_method) + == MATCH_FAILED ) + return NULL; + + switch(vp->magic) { + case UDPINDATAGRAMS: + long_ret = udpstat.udps_ipackets; + return (u_char *) &long_ret; + case UDPNOPORTS: + long_ret = udpstat.udps_noport; + return (u_char *) &long_ret; + case UDPOUTDATAGRAMS: + long_ret = udpstat.udps_opackets; + return (u_char *) &long_ret; + case UDPINERRORS: + long_ret = udpstat.udps_hdrops + udpstat.udps_badsum + + udpstat.udps_badlen; + return (u_char *) &long_ret; + default: + ERROR_MSG(""); + } + return NULL; +} + + +/* + * var_udpTable(): + * Handle this table separately from the scalar value case. + * The workings of this are basically the same as for var_udpTable above. + */ +unsigned char * +var_udpTable(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + static long long_ret; + static unsigned char string[SPRINT_MAX_LEN]; + register struct inpcb *inp; + register struct inpcb *low_inp = NULL; + oid lowest[16]; + oid newname[16]; + u_char *cp; + oid *op; + + // This is indexed by local-address, local-port, at 1,3,6,1,2,1,7,5,1,1, + // so we get 1,3,6,1,2,1,7,5,1,?,A,B,C,D,port + // initial length is 10, out-length is 15, + // Address is offsets 10-13, port is offset 14. + + // starting from udbtable, look in + // low_pcb->inp_laddr.s_addr + // and low_pcb->inp_lport + + /* fill in object part of name for current (less sizeof instance part) */ + memcpy((char *)newname, (char *)vp->name, (int)vp->namelen * sizeof(oid)); + + for (inp = udbtable.inpt_queue.cqh_first; + inp != (struct inpcb *)&udbtable.inpt_queue; + inp = inp->inp_queue.cqe_next) { + cp = (u_char *)&inp->inp_laddr.s_addr; + op = newname + 10; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + *op++ = *cp++; + + newname[14] = ntohs(inp->inp_lport); + + if (exact){ + if (snmp_oid_compare(newname, 15, name, *length) == 0){ + memcpy( (char *)lowest,(char *)newname, 15 * sizeof(oid)); + low_inp = inp; + break; /* no need to search further */ + } + } else { + if ((snmp_oid_compare(newname, 15, name, *length) > 0) && + (!low_inp || (snmp_oid_compare(newname, 15, lowest, 15) < 0))){ + /* + * if new one is greater than input and closer to input than + * previous lowest, save this one as the "next" one. + */ + memcpy( (char *)lowest,(char *)newname, 15 * sizeof(oid)); + low_inp = inp; + } + } + } + + if ( ! low_inp ) + return NULL; + + memcpy( (char *)name,(char *)lowest, 15 * sizeof(oid)); + *length = 15; + *var_len = sizeof( long_ret ); + *write_method = 0; + + switch(vp->magic) { + + case UDPLOCALADDRESS: + cp = (u_char *)&low_inp->inp_laddr.s_addr; + string[0] = *cp++; + string[1] = *cp++; + string[2] = *cp++; + string[3] = *cp++; + *var_len = 4; + return (unsigned char *) string; + + case UDPLOCALPORT: + long_ret = (long)ntohs(low_inp->inp_lport); + return (unsigned char *) &long_ret; + + default: + ERROR_MSG(""); + } + return NULL; +} + + +// EOF udp.c diff --git a/packages/net/snmp/agent/current/src/mibgroup/util_funcs.c b/packages/net/snmp/agent/current/src/mibgroup/util_funcs.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/mibgroup/util_funcs.c @@ -0,0 +1,777 @@ +//========================================================================== +// +// ./agent/current/src/mibgroup/util_funcs.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * util_funcs.c + */ + +#include + +#if HAVE_IO_H +#include +#endif +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_MALLOC_H +#include +#endif +#include +#ifdef __alpha +#ifndef _BSD +#define _BSD +#define _myBSD +#endif +#endif +#if HAVE_SYS_WAIT_H +# include +#endif +#ifdef __alpha +#ifdef _myBSD +#undef _BSD +#undef _myBSD +#endif +#endif +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#include +#include +#if HAVE_STRING_H +#include +#else +#include +#endif +#include +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_BASETSD_H +#include +#define ssize_t SSIZE_T +#endif +#if HAVE_RAISE +#define alarm raise +#endif +#include "mibincl.h" +#include "mibgroup/struct.h" +#include "mibgroup/util_funcs.h" +#include "system.h" +#if HAVE_LIMITS_H +#include "limits.h" +#endif +#ifdef USING_UCD_SNMP_ERRORMIB_MODULE +#include "ucd-snmp/errormib.h" +#else +#define setPerrorstatus(x) snmp_log_perror(x) +#endif +#include "read_config.h" + +#ifdef EXCACHETIME +static long cachetime; +#endif + +extern int numprocs, numextens; + +void +Exit(int var) +{ + snmp_log(LOG_ERR, "Server Exiting with code %d\n",var); + exit(var); +} + +int shell_command(struct extensible *ex) +{ +#if HAVE_SYSTEM + char shellline[STRMAX]; + FILE *shellout; + + sprintf(shellline,"%s > /tmp/shoutput",ex->command); + ex->result = system(shellline); + ex->result = WEXITSTATUS(ex->result); + shellout = fopen("/tmp/shoutput","r"); + if((shellout = fopen("/tmp/shoutput","r")) != NULL) { + if (fgets(ex->output,STRMAX,shellout) == NULL) { + ex->output[0] = 0; + } + fclose(shellout); + } + unlink("/tmp/shoutput"); +#else + ex->output[0] = 0; + ex->result = 0; +#endif + return(ex->result); +} + +#define MAXOUTPUT 300 + +int exec_command(struct extensible *ex) +{ +#if HAVE_EXECV + int fd; + FILE *file; + + if ((fd = get_exec_output(ex))) { + file = fdopen(fd,"r"); + if (fgets(ex->output,STRMAX,file) == NULL) { + ex->output[0] = 0; + } + fclose(file); + wait_on_exec(ex); + } else +#endif + { + ex->output[0] = 0; + ex->result = 0; + } + return(ex->result); +} + +void wait_on_exec(struct extensible *ex) +{ +#ifndef EXCACHETIME + if (ex->pid && waitpid(ex->pid,&ex->result,0) < 0) { + setPerrorstatus("waitpid"); + } + ex->pid = 0; +#endif +} + +#define MAXARGS 30 + +int get_exec_output(struct extensible *ex) +{ +#if HAVE_EXECV + int fd[2],i, cnt; + char ctmp[STRMAX], *cptr1, *cptr2, argvs[STRMAX], **argv, **aptr; +#ifdef EXCACHETIME + char cache[MAXCACHESIZE]; + ssize_t cachebytes; + long curtime; + static char lastcmd[STRMAX]; + int cfd; + static int lastresult; + int readcount; +#endif + +#ifdef EXCACHETIME + curtime = time(NULL); + if (curtime > (cachetime + EXCACHETIME) || + strcmp(ex->command, lastcmd) != 0) { + strcpy(lastcmd,ex->command); + cachetime = curtime; +#endif + if (pipe(fd)) + { + setPerrorstatus("pipe"); +#ifdef EXCACHETIME + cachetime = 0; +#endif + return 0; + } + if ((ex->pid = fork()) == 0) + { + close(1); + if (dup(fd[1]) != 1) + { + setPerrorstatus("dup"); + return 0; + } + close(fd[1]); + close(fd[0]); + for(cnt=1,cptr1 = ex->command, cptr2 = argvs; *cptr1 != 0; + cptr2++, cptr1++) { + *cptr2 = *cptr1; + if (*cptr1 == ' ') { + *(cptr2++) = 0; + cptr1 = skip_white(cptr1); + *cptr2 = *cptr1; + if (*cptr1 != 0) cnt++; + } + } + *cptr2 = 0; + *(cptr2+1) = 0; + argv = (char **) malloc((cnt+2) * sizeof(char *)); + if (argv == NULL) + return 0; /* memory alloc error */ + aptr = argv; + *(aptr++) = argvs; + for (cptr2 = argvs, i=1; i != cnt; cptr2++) + if (*cptr2 == 0) { + *(aptr++) = cptr2 + 1; + i++; + } + while (*cptr2 != 0) cptr2++; + *(aptr++) = NULL; + copy_word(ex->command,ctmp); + execv(ctmp,argv); + snmp_log_perror(ctmp); + exit(1); + } + else + { + close(fd[1]); + if (ex->pid < 0) { + close(fd[0]); + setPerrorstatus("fork"); +#ifdef EXCACHETIME + cachetime = 0; +#endif + return 0; + } +#ifdef EXCACHETIME + unlink(CACHEFILE); + /* XXX Use SNMP_FILEMODE_CLOSED instead of 644? */ + if ((cfd = open(CACHEFILE,O_WRONLY|O_TRUNC|O_CREAT,0644)) < 0) { + setPerrorstatus("open"); + cachetime = 0; + return 0; + } + fcntl(fd[0],F_SETFL,O_NONBLOCK); /* don't block on reads */ +#ifdef HAVE_USLEEP + for (readcount = 0; readcount <= MAXREADCOUNT*100 && + (cachebytes = read(fd[0],(void *)cache,MAXCACHESIZE)); + readcount++) { +#else + for (readcount = 0; readcount <= MAXREADCOUNT && + (cachebytes = read(fd[0],(void *)cache,MAXCACHESIZE)); + readcount++) { +#endif + if (cachebytes > 0) + write(cfd,(void *) cache, cachebytes); + else if (cachebytes == -1 && errno != EAGAIN) { + setPerrorstatus("read"); + break; + } + else +#ifdef HAVE_USLEEP + usleep (10000); /* sleeps for 0.01 sec */ +#else + sleep (1); +#endif + } + close(cfd); + close(fd[0]); + /* wait for the child to finish */ + if (ex->pid > 0 && waitpid(ex->pid,&ex->result,0) < 0) { + setPerrorstatus("waitpid()"); + cachetime = 0; + return 0; + } + ex->pid = 0; + ex->result = WEXITSTATUS(ex->result); + lastresult = ex->result; +#else /* !EXCACHETIME */ + return(fd[0]); +#endif + } +#ifdef EXCACHETIME + } + else { + ex->result = lastresult; + } + if ((cfd = open(CACHEFILE,O_RDONLY)) < 0) { + setPerrorstatus("open"); + return 0; + } + return(cfd); +#endif + +#else /* !HAVE_EXECV */ + return 0; +#endif +} + +int get_exec_pipes(char *cmd, + int *fdIn, + int *fdOut, + int *pid) + +{ +#if HAVE_EXECV + int fd[2][2],i, cnt; + char ctmp[STRMAX], *cptr1, *cptr2, argvs[STRMAX], **argv, **aptr; + /* Setup our pipes */ + if (pipe(fd[0]) || pipe(fd[1])) + { + setPerrorstatus("pipe"); + return 0; + } + if ((*pid = fork()) == 0) /* First handle for the child */ + { + close(0); + if (dup(fd[0][0]) != 0) + { + setPerrorstatus("dup"); + return 0; + } + close(1); + if (dup(fd[1][1]) != 1) + { + setPerrorstatus("dup"); + return 0; + } + close(fd[0][0]); + close(fd[0][1]); + close(fd[1][0]); + close(fd[1][1]); + for(cnt=1,cptr1 = cmd, cptr2 = argvs; *cptr1 != 0; + cptr2++, cptr1++) { + *cptr2 = *cptr1; + if (*cptr1 == ' ') { + *(cptr2++) = 0; + cptr1 = skip_white(cptr1); + *cptr2 = *cptr1; + if (*cptr1 != 0) cnt++; + } + } + *cptr2 = 0; + *(cptr2+1) = 0; + argv = (char **) malloc((cnt+2) * sizeof(char *)); + if (argv == NULL) + return 0; /* memory alloc error */ + aptr = argv; + *(aptr++) = argvs; + for (cptr2 = argvs, i=1; i != cnt; cptr2++) + if (*cptr2 == 0) { + *(aptr++) = cptr2 + 1; + i++; + } + while (*cptr2 != 0) cptr2++; + *(aptr++) = NULL; + copy_word(cmd,ctmp); + execv(ctmp,argv); + snmp_log_perror("execv"); + exit(1); + } + else + { + close(fd[0][0]); + close(fd[1][1]); + if (*pid < 0) { + close(fd[0][1]); + close(fd[1][0]); + setPerrorstatus("fork"); + return 0; + } + *fdIn = fd[1][0]; + *fdOut = fd[0][1]; + return(1); /* We are returning 0 for error... */ + } +#endif /* !HAVE_EXECV */ + return 0; +} + +int clear_cache(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + + long tmp=0; + + if (var_val_type != ASN_INTEGER) { + snmp_log(LOG_NOTICE, "Wrong type != int\n"); + return SNMP_ERR_WRONGTYPE; + } + tmp = *((long *) var_val); + if (tmp == 1 && action == COMMIT) { +#ifdef EXCACHETIME + cachetime = 0; /* reset the cache next read */ +#endif + } + return SNMP_ERR_NOERROR; +} + +char **argvrestartp, *argvrestartname, *argvrestart; + +RETSIGTYPE restart_doit(int a) +{ + int i; + + /* close everything open */ + for (i=0; i<= 2; i++) + close(i); + + /* do the exec */ +#if HAVE_EXECV + execv(argvrestartname,argvrestartp); + setPerrorstatus("execv"); +#endif +} + +int +restart_hook(int action, + u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + oid *name, + size_t name_len) +{ + + long tmp=0; + + if (var_val_type != ASN_INTEGER) { + snmp_log(LOG_NOTICE, "Wrong type != int\n"); + return SNMP_ERR_WRONGTYPE; + } + tmp = *((long *) var_val); + if (tmp == 1 && action == COMMIT) { +#ifdef SIGALRM + signal(SIGALRM,restart_doit); +#endif + alarm(RESTARTSLEEP); + } + return SNMP_ERR_NOERROR; +} + +void +print_mib_oid(oid name[], + size_t len) +{ + char *buffer; + buffer=malloc(11*len); /* maximum digit lengths for int32 + a '.' */ + if (!buffer) { + snmp_log(LOG_ERR, "Malloc failed - out of memory?"); + return; + } + sprint_mib_oid(buffer, name, len); + snmp_log(LOG_NOTICE, "Mib: %s\n", buffer); + free(buffer); +} + +void +sprint_mib_oid(char *buf, + oid name[], + size_t len) +{ + int i; + for(i=0; i < (int)len; i++) { + sprintf(buf,".%d",(int) name[i]); + while (*buf != 0) + buf++; + } +} + +/*******************************************************************-o-****** + * header_simple_table + * + * Parameters: + * *vp Variable data. + * *name Fully instantiated OID name. + * *length Length of name. + * exact TRUE if an exact match is desired. + * *var_len Hook for size of returned data type. + * (**write_method) Hook for write method (UNUSED). + * max + * + * Returns: + * 0 If name matches vp->name (accounting for 'exact') and is + * not greater in length than 'max'. + * 1 Otherwise. + * + * + * Compare 'name' to vp->name for the best match or an exact match (if + * requested). Also check that 'name' is not longer than 'max' if + * max is greater-than/equal 0. + * Store a successful match in 'name', and increment the OID instance if + * the match was not exact. + * + * 'name' and 'length' are undefined upon failure. + * + */ +int header_simple_table(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method, int max) +{ + int i, + rtest; /* Set to: -1 If name < vp->name, + * 1 If name > vp->name, + * 0 Otherwise. + */ + oid newname[MAX_OID_LEN]; + + for(i=0,rtest=0; i < (int) vp->namelen && i < (int)(*length) && !rtest; i++) { + if (name[i] != vp->name[i]) { + if (name[i] < vp->name[i]) + rtest = -1; + else + rtest = 1; + } + } + if (rtest > 0 || + (rtest == 0 && !exact && (int)(vp->namelen+1) < (int) *length) || + (exact == 1 && (rtest || (int)*length != (int)(vp->namelen+1)))) { + if (var_len) + *var_len = 0; + return MATCH_FAILED; + } + + memset(newname, 0, sizeof(newname)); + + if (((int) *length) <= (int) vp->namelen || rtest == -1) { + memmove(newname, vp->name, (int)vp->namelen * sizeof (oid)); + newname[vp->namelen] = 1; + *length = vp->namelen+1; + } + else { + *length = vp->namelen+1; + memmove(newname, name, (*length) * sizeof(oid)); + if (!exact) + newname[*length-1] = name[*length-1] + 1; + else + newname[*length-1] = name[*length-1]; + } + if (max >= 0 && ((int)newname[*length-1] > max)) { + if(var_len) + *var_len = 0; + return MATCH_FAILED; + } + + memmove(name, newname, (*length) * sizeof(oid)); + if (write_method) + *write_method = 0; + if (var_len) + *var_len = sizeof(long); /* default */ + return(MATCH_SUCCEEDED); +} + +/* + header_generic(... + Arguments: + vp IN - pointer to variable entry that points here + name IN/OUT - IN/name requested, OUT/name found + length IN/OUT - length of IN/OUT oid's + exact IN - TRUE if an exact match was requested + var_len OUT - length of variable or 0 if function returned + write_method + +*/ + +/*******************************************************************-o-****** + * generic_header + * + * Parameters: + * *vp (I) Pointer to variable entry that points here. + * *name (I/O) Input name requested, output name found. + * *length (I/O) Length of input and output oid's. + * exact (I) TRUE if an exact match was requested. + * *var_len (O) Length of variable or 0 if function returned. + * (**write_method) Hook to name a write method (UNUSED). + * + * Returns: + * MATCH_SUCCEEDED If vp->name matches name (accounting for exact bit). + * MATCH_FAILED Otherwise, + * + * + * Check whether variable (vp) matches name. + */ +int +header_generic(struct variable *vp, + oid *name, + size_t *length, + int exact, + size_t *var_len, + WriteMethod **write_method) +{ + oid newname[MAX_OID_LEN]; + int result; + + DEBUGMSGTL(("util_funcs", "header_generic: ")); + DEBUGMSGOID(("util_funcs", name, *length)); + DEBUGMSG(("util_funcs"," exact=%d\n", exact)); + + memcpy((char *)newname, (char *)vp->name, (int)vp->namelen * sizeof(oid)); + newname[vp->namelen] = 0; + result = snmp_oid_compare(name, *length, newname, vp->namelen + 1); + DEBUGMSGTL(("util_funcs", " result: %d\n", result)); + if ((exact && (result != 0)) || (!exact && (result >= 0))) + return(MATCH_FAILED); + memcpy( (char *)name,(char *)newname, ((int)vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + + *write_method = 0; + *var_len = sizeof(long); /* default to 'long' results */ + return(MATCH_SUCCEEDED); +} + +/* checkmib(): provided for backwards compatibility, do not use: */ +int checkmib(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method, int max) { + /* checkmib used to be header_simple_table, with reveresed boolean + return output. header_simple_table() was created to match + header_generic(). */ + return (!header_simple_table(vp, name, length, exact, var_len, + write_method, max)); +} + +char *find_field(char *ptr, + int field) +{ + int i; + char *init=ptr; + + if (field == LASTFIELD) { + /* skip to end */ + while (*ptr++); + ptr = ptr - 2; + /* rewind a field length */ + while (*ptr != 0 && isspace(*ptr) && init <= ptr) ptr--; + while (*ptr != 0 && !isspace(*ptr) && init <= ptr) ptr--; + if (isspace(*ptr)) ptr++; /* past space */ + if (ptr < init) ptr = init; + if (!isspace(*ptr) && *ptr != 0) return(ptr); + } else { + if ((ptr = skip_white(ptr)) == NULL) return(NULL); + for (i=1; *ptr != 0 && i != field; i++) + { + if ((ptr = skip_not_white(ptr)) == NULL) return (NULL); + if ((ptr = skip_white(ptr)) == NULL) return (NULL); + } + if (*ptr != 0 && i == field) return(ptr); + return (NULL); + } + return(NULL); +} + +int parse_miboid(const char *buf, + oid *oidout) +{ + int i; + + if (!buf) + return 0; + if (*buf == '.') buf++; + for(i=0;isdigit(*buf);i++) { + oidout[i] = atoi(buf); + while(isdigit(*buf++)); + if (*buf == '.') buf++; + } + /* oidout[i] = -1; hmmm */ + return i; +} + +void +string_append_int (char *s, + int val) +{ + char textVal[16]; + + if (val < 10) { + *s++ = '0' + val; + *s = '\0'; + return; + } + sprintf (textVal, "%d", val); + strcpy(s, textVal); + return; +} diff --git a/packages/net/snmp/agent/current/src/snmp_agent.c b/packages/net/snmp/agent/current/src/snmp_agent.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/snmp_agent.c @@ -0,0 +1,873 @@ +//========================================================================== +// +// ./agent/current/src/snmp_agent.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmp_agent.c + * + * Simple Network Management Protocol (RFC 1067). + */ +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#include + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#include +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#define SNMP_NEED_REQUEST_LIST +#include "snmp_api.h" +#include "snmp_impl.h" +#include "snmp.h" +#include "mib.h" +#include "snmp_client.h" + +#include "snmp_vars.h" +#include "snmpd.h" +#include "mibgroup/struct.h" +#include "mibgroup/util_funcs.h" +#include "var_struct.h" +#include "read_config.h" +#include "snmp_logging.h" +#include "snmp_debug.h" +#include "mib_module_config.h" + +#include "default_store.h" +#include "ds_agent.h" +#include "snmp_agent.h" +#include "agent_trap.h" + +static int snmp_vars_inc; + +static struct agent_snmp_session *agent_session_list = NULL; + + +static void dump_var(oid *, size_t, int, void *, size_t); +static int goodValue(u_char, size_t, u_char, size_t); +static void setVariable(u_char *, u_char, size_t, u_char *, size_t); + +static void dump_var ( + oid *var_name, + size_t var_name_len, + int statType, + void *statP, + size_t statLen) +{ + char buf [SPRINT_MAX_LEN]; + struct variable_list temp_var; + + temp_var.type = statType; + temp_var.val.string = (u_char *)statP; + temp_var.val_len = statLen; + sprint_variable (buf, var_name, var_name_len, &temp_var); + snmp_log(LOG_INFO, " >> %s\n", buf); +} + + +int getNextSessID() +{ + static int SessionID = 0; + + return ++SessionID; +} + +int +agent_check_and_process(int block) { + int numfds; + fd_set fdset; + struct timeval timeout, *tvp = &timeout; + int count; + int fakeblock=0; + + tvp = &timeout; + tvp->tv_sec = 0; + tvp->tv_usec = 0; + + numfds = 0; + FD_ZERO(&fdset); + snmp_select_info(&numfds, &fdset, tvp, &fakeblock); + if (block == 1 && fakeblock == 1) + tvp = NULL; /* block without timeout */ + else if (block == 0) { + tvp->tv_sec = 0; + tvp->tv_usec = 0; + } + + count = select(numfds, &fdset, 0, 0, tvp); + + if (count > 0){ + /* packets found, process them */ + snmp_read(&fdset); + } else switch(count){ + case 0: + snmp_timeout(); + break; + case -1: + if (errno == EINTR){ + return -1; + } else { + snmp_log_perror("select"); + } + return -1; + default: + snmp_log(LOG_ERR, "select returned %d\n", count); + return -1; + } /* endif -- count>0 */ + return count; +} + + +/* + * The session is created using the "traditional API" routine snmp_open() + * so is linked into the global library Sessions list. It also opens a + * socket that listens for incoming requests. + * + * The agent runs in an infinite loop (in the 'receive()' routine), + * which calls snmp_read() when such a request is received on this socket. + * This routine then traverses the library 'Sessions' list to identify the + * relevant session and eventually invokes '_sess_read'. + * This then processes the incoming packet, calling the pre_parse, parse, + * post_parse and callback routines in turn. + */ + + /* Global access to the primary session structure for this agent. + for Index Allocation use initially. */ +struct snmp_session *main_session; + +int +init_master_agent(int dest_port, + int (*pre_parse) (struct snmp_session *, snmp_ipaddr), + int (*post_parse) (struct snmp_session *, struct snmp_pdu *,int)) +{ + struct snmp_session sess, *session; + + if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != MASTER_AGENT ) + return 0; /* no error if ! MASTER_AGENT */ + + DEBUGMSGTL(("snmpd","installing master agent on port %d\n", dest_port)); + + snmp_sess_init( &sess ); + + sess.version = SNMP_DEFAULT_VERSION; + sess.peername = SNMP_DEFAULT_PEERNAME; + sess.community_len = SNMP_DEFAULT_COMMUNITY_LEN; + + sess.local_port = dest_port; + sess.callback = handle_snmp_packet; + sess.authenticator = NULL; + sess.flags = ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS); + session = snmp_open_ex( &sess, pre_parse, 0, post_parse, 0, 0 ); + + if ( session == NULL ) { + /* diagnose snmp_open errors with the input struct snmp_session pointer */ + snmp_sess_perror("init_master_agent", &sess); + return 1; + } + main_session = session; + return 0; +} + +struct agent_snmp_session * +init_agent_snmp_session( struct snmp_session *session, struct snmp_pdu *pdu ) +{ + struct agent_snmp_session *asp; + + asp = malloc( sizeof( struct agent_snmp_session )); + if ( asp == NULL ) + return NULL; + asp->start = pdu->variables; + asp->end = pdu->variables; + if ( asp->end != NULL ) + while ( asp->end->next_variable != NULL ) + asp->end = asp->end->next_variable; + asp->session = session; + asp->pdu = pdu; + asp->rw = READ; + asp->exact = TRUE; + asp->outstanding_requests = NULL; + asp->next = NULL; + asp->mode = RESERVE1; + asp->status = SNMP_ERR_NOERROR; + + return asp; +} + +int +count_varbinds( struct snmp_pdu *pdu ) +{ + int count = 0; + struct variable_list *var_ptr; + + for ( var_ptr = pdu->variables ; var_ptr != NULL ; + var_ptr = var_ptr->next_variable ) + count++; + + return count; +} + +int +handle_snmp_packet(int operation, struct snmp_session *session, int reqid, + struct snmp_pdu *pdu, void *magic) +{ + struct agent_snmp_session *asp; + int status, allDone, i; + struct variable_list *var_ptr, *var_ptr2; + + if ( magic == NULL ) { + asp = init_agent_snmp_session( session, snmp_clone_pdu(pdu) ); + status = SNMP_ERR_NOERROR; + } + else { + asp = (struct agent_snmp_session *)magic; + status = asp->status; + } + + if (asp->outstanding_requests != NULL) + return 1; + + if ( check_access(pdu) != 0) { + /* access control setup is incorrect */ + send_easy_trap(SNMP_TRAP_AUTHFAIL, 0); + if (asp->pdu->version != SNMP_VERSION_1 && asp->pdu->version != SNMP_VERSION_2c) { + asp->pdu->errstat = SNMP_ERR_AUTHORIZATIONERROR; + asp->pdu->command = SNMP_MSG_RESPONSE; + snmp_increment_statistic(STAT_SNMPOUTPKTS); + snmp_send( asp->session, asp->pdu ); + return 1; + } else { + /* drop the request */ + free( asp ); + return 0; + } + } + + switch (pdu->command) { + case SNMP_MSG_GET: + if ( asp->mode != RESERVE1 ) + break; /* Single pass */ + snmp_increment_statistic(STAT_SNMPINGETREQUESTS); + status = handle_next_pass( asp ); + asp->mode = RESERVE2; + break; + + case SNMP_MSG_GETNEXT: + if ( asp->mode != RESERVE1 ) + break; /* Single pass */ + snmp_increment_statistic(STAT_SNMPINGETNEXTS); + asp->exact = FALSE; + status = handle_next_pass( asp ); + asp->mode = RESERVE2; + break; + + case SNMP_MSG_GETBULK: + /* + * GETBULKS require multiple passes. The first pass handles the + * explicitly requested varbinds, and subsequent passes append + * to the existing var_op_list. Each pass (after the first) + * uses the results of the preceeding pass as the input list + * (delimited by the start & end pointers. + * Processing is terminated if all entries in a pass are + * EndOfMib, or the maximum number of repetitions are made. + */ + if ( asp->mode == RESERVE1 ) { + snmp_increment_statistic(STAT_SNMPINGETREQUESTS); + asp->exact = FALSE; + /* + * Limit max repetitions to something reasonable + * XXX: We should figure out what will fit somehow... + */ + if ( asp->pdu->errindex > 100 ) + asp->pdu->errindex = 100; + + status = handle_next_pass( asp ); /* First pass */ + asp->mode = RESERVE2; + if ( status != SNMP_ERR_NOERROR ) + break; + + while ( asp->pdu->errstat-- > 0 ) /* Skip non-repeaters */ + asp->start = asp->start->next_variable; + asp->pdu->errindex--; /* Handled first repetition */ + + if ( asp->outstanding_requests != NULL ) + return 1; + } + + while ( asp->pdu->errindex-- > 0 ) { /* Process repeaters */ + /* + * Add new variable structures for the + * repeating elements, ready for the next pass. + * Also check that these are not all EndOfMib + */ + allDone = TRUE; /* Check for some content */ + for ( var_ptr = asp->start; + var_ptr != asp->end->next_variable; + var_ptr = var_ptr->next_variable ) { + /* XXX: we don't know the size of the next + OID, so assume the maximum length */ + if ( var_ptr->type != SNMP_ENDOFMIBVIEW ) + { + var_ptr2 = snmp_add_null_var(asp->pdu, var_ptr->name, MAX_OID_LEN); + for ( i=var_ptr->name_length ; iname[i] = 0; + var_ptr2->name_length = var_ptr->name_length; + + allDone = FALSE; + } + } + if ( allDone ) + break; + + asp->start = asp->end->next_variable; + while ( asp->end->next_variable != NULL ) + asp->end = asp->end->next_variable; + + status = handle_next_pass( asp ); + if ( status != SNMP_ERR_NOERROR ) + break; + if ( asp->outstanding_requests != NULL ) + return 1; + } + break; + + case SNMP_MSG_SET: + /* + * SETS require 3-4 passes through the var_op_list. The first two + * passes verify that all types, lengths, and values are valid + * and may reserve resources and the third does the set and a + * fourth executes any actions. Then the identical GET RESPONSE + * packet is returned. + * If either of the first two passes returns an error, another + * pass is made so that any reserved resources can be freed. + * If the third pass returns an error, another pass is made so that + * any changes can be reversed. + * If the fourth pass (or any of the error handling passes) + * return an error, we'd rather not know about it! + */ + if ( asp->mode == RESERVE1 ) { + snmp_increment_statistic(STAT_SNMPINSETREQUESTS); + asp->rw = WRITE; + + status = handle_next_pass( asp ); + + if ( status != SNMP_ERR_NOERROR ) + asp->mode = FREE; + else + asp->mode = RESERVE2; + + if ( asp->outstanding_requests != NULL ) + return 1; + } + + if ( asp->mode == RESERVE2 ) { + status = handle_next_pass( asp ); + + if ( status != SNMP_ERR_NOERROR ) + asp->mode = FREE; + else + asp->mode = ACTION; + + if ( asp->outstanding_requests != NULL ) + return 1; + } + + if ( asp->mode == ACTION ) { + status = handle_next_pass( asp ); + + if ( status != SNMP_ERR_NOERROR ) + asp->mode = UNDO; + else + asp->mode = COMMIT; + + if ( asp->outstanding_requests != NULL ) + return 1; + } + + if ( asp->mode == COMMIT ) { + status = handle_next_pass( asp ); + + if ( status != SNMP_ERR_NOERROR ) { + status = SNMP_ERR_COMMITFAILED; + asp->mode = FINISHED_FAILURE; + } + else + asp->mode = FINISHED_SUCCESS; + + if ( asp->outstanding_requests != NULL ) + return 1; + } + + if ( asp->mode == UNDO ) { + if (handle_next_pass( asp ) != SNMP_ERR_NOERROR ) + status = SNMP_ERR_UNDOFAILED; + + asp->mode = FINISHED_FAILURE; + break; + } + + if ( asp->mode == FREE ) { + (void) handle_next_pass( asp ); + break; + } + + break; + + case SNMP_MSG_RESPONSE: + snmp_increment_statistic(STAT_SNMPINGETRESPONSES); + free( asp ); + return 0; + case SNMP_MSG_TRAP: + case SNMP_MSG_TRAP2: + snmp_increment_statistic(STAT_SNMPINTRAPS); + free( asp ); + return 0; + default: + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + free( asp ); + return 0; + } + + if ( asp->outstanding_requests != NULL ) { + asp->status = status; + asp->next = agent_session_list; + agent_session_list = asp; + } + else { + /* + * May need to "dumb down" a SET error status for a + * v1 query. See RFC2576 - section 4.3 + */ + if (( asp->pdu->command == SNMP_MSG_SET ) && + ( asp->pdu->version == SNMP_VERSION_1 )) { + switch ( status ) { + case SNMP_ERR_WRONGVALUE: + case SNMP_ERR_WRONGENCODING: + case SNMP_ERR_WRONGTYPE: + case SNMP_ERR_WRONGLENGTH: + case SNMP_ERR_INCONSISTENTVALUE: + status = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_NOACCESS: + case SNMP_ERR_NOTWRITABLE: + case SNMP_ERR_NOCREATION: + case SNMP_ERR_INCONSISTENTNAME: + case SNMP_ERR_AUTHORIZATIONERROR: + status = SNMP_ERR_NOSUCHNAME; + break; + case SNMP_ERR_RESOURCEUNAVAILABLE: + case SNMP_ERR_COMMITFAILED: + case SNMP_ERR_UNDOFAILED: + status = SNMP_ERR_GENERR; + break; + } + } + /* + * Similarly we may need to "dumb down" v2 exception + * types to throw an error for a v1 query. + * See RFC2576 - section 4.1.2.3 + */ + if (( asp->pdu->command != SNMP_MSG_SET ) && + ( asp->pdu->version == SNMP_VERSION_1 )) { + for ( var_ptr = asp->pdu->variables, i=0 ; + var_ptr != NULL ; + var_ptr = var_ptr->next_variable, i++ ) { + switch ( var_ptr->type ) { + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_COUNTER64: + status = SNMP_ERR_NOSUCHNAME; + asp->pdu->errindex=i; + break; + } + } + } + if ( status == SNMP_ERR_NOERROR ) { + snmp_increment_statistic_by( + (asp->pdu->command == SNMP_MSG_SET ? + STAT_SNMPINTOTALSETVARS : STAT_SNMPINTOTALREQVARS ), + count_varbinds( asp->pdu )); + } + else { + /* + * Use a copy of the original request + * to report failures. + */ + i = asp->pdu->errindex; + snmp_free_pdu( asp->pdu ); + asp->pdu = snmp_clone_pdu( pdu ); + asp->pdu->errindex = i; + } + asp->pdu->command = SNMP_MSG_RESPONSE; + asp->pdu->errstat = status; + snmp_send( asp->session, asp->pdu ); + snmp_increment_statistic(STAT_SNMPOUTPKTS); + snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES); + free( asp ); + } + + return 1; +} + + +int +handle_next_pass(struct agent_snmp_session *asp) +{ + int status; + struct snmp_pdu *pdu = asp->pdu; + struct request_list *req_p, *next_req; + + + if ( asp->outstanding_requests != NULL ) + return SNMP_ERR_NOERROR; + status = handle_var_list( asp ); + if ( asp->outstanding_requests != NULL ) { + if ( status == SNMP_ERR_NOERROR ) { + /* Send out any subagent requests */ + for ( req_p = asp->outstanding_requests ; + req_p != NULL ; req_p = req_p->next_request ) { + + snmp_async_send( req_p->session, req_p->pdu, + req_p->callback, req_p->cb_data ); + } + asp->pdu = snmp_clone_pdu( pdu ); + asp->pdu->variables = pdu->variables; + pdu->variables = NULL; + } + else { + /* discard outstanding requests */ + for ( req_p = asp->outstanding_requests ; + req_p != NULL ; req_p = next_req ) { + + next_req = req_p->next_request; + free( req_p ); + } + asp->outstanding_requests = NULL; + } + } + return status; +} + + +int +handle_var_list(struct agent_snmp_session *asp) +{ + struct variable_list *varbind_ptr; + u_char statType; + u_char *statP; + size_t statLen; + u_short acl; + WriteMethod *write_method; + AddVarMethod *add_method; + int noSuchObject = TRUE; + int count, view; + + count = 0; + varbind_ptr = asp->start; + if ( !varbind_ptr ) { + return SNMP_ERR_NOERROR; + } + + while (1) { + + count++; +statp_loop: + statP = getStatPtr( varbind_ptr->name, + &varbind_ptr->name_length, + &statType, &statLen, &acl, + asp->exact, &write_method, asp->pdu, &noSuchObject); + + if (statP == NULL && (asp->rw != WRITE || write_method == NULL)) { + varbind_ptr->val.integer = NULL; + varbind_ptr->val_len = 0; + if ( asp->exact ) { + if ( noSuchObject == TRUE ){ + statType = SNMP_NOSUCHOBJECT; + } else { + statType = SNMP_NOSUCHINSTANCE; + } + } else { + statType = SNMP_ENDOFMIBVIEW; + } + if (asp->pdu->version == SNMP_VERSION_1) { + asp->pdu->errstat = SNMP_ERR_NOSUCHNAME; + asp->pdu->errindex = count; + return SNMP_ERR_NOSUCHNAME; + } + else if (asp->rw == WRITE) { + asp->pdu->errstat = + ( noSuchObject ? SNMP_ERR_NOTWRITABLE + : SNMP_ERR_NOCREATION ); + asp->pdu->errindex = count; + return asp->pdu->errstat; + } + else + varbind_ptr->type = statType; + } + /* Delegated variables should be added to the + relevant outgoing request */ + else if ( IS_DELEGATED(statType)) { + add_method = (AddVarMethod*)statP; + statType = (*add_method)( asp, varbind_ptr ); + } + /* GETNEXT/GETBULK should just skip inaccessible entries */ + else if ((view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length, + asp->pdu, varbind_ptr->type)) + && !asp->exact) { + if (view != 5) send_easy_trap(SNMP_TRAP_AUTHFAIL, 0); + goto statp_loop; + } + /* Other access problems are permanent */ + else if (( asp->rw == WRITE && !(acl & 2)) || view) { + if (asp->pdu->version == SNMP_VERSION_1 || asp->rw != WRITE) { + if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)) + DEBUGMSGTL(("snmp_agent", " >> noSuchName (read-only)\n")); + ERROR_MSG("read-only"); + statType = SNMP_ERR_NOSUCHNAME; + } + else { + if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)) + DEBUGMSGTL(("snmp_agent", " >> notWritable\n")); + ERROR_MSG("Not Writable"); + statType = SNMP_ERR_NOTWRITABLE; + } + asp->pdu->errstat = statType; + asp->pdu->errindex = count; + send_easy_trap(SNMP_TRAP_AUTHFAIL, 0); + return statType; + } + else { + /* dump verbose info */ + if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) && statP) + dump_var(varbind_ptr->name, varbind_ptr->name_length, + statType, statP, statLen); + + /* FINALLY we can act on SET requests ....*/ + if ( asp->rw == WRITE ) { + if ( write_method != NULL ) { + statType = (*write_method)(asp->mode, + varbind_ptr->val.string, + varbind_ptr->type, + varbind_ptr->val_len, statP, + varbind_ptr->name, + varbind_ptr->name_length); + if (statType != SNMP_ERR_NOERROR) { + asp->pdu->errstat = statType; + asp->pdu->errindex = count; + return statType; + } + } + else { + if (!goodValue(varbind_ptr->type, varbind_ptr->val_len, + statType, statLen)){ + if (asp->pdu->version == SNMP_VERSION_1) + statType = SNMP_ERR_BADVALUE; + else + statType = SNMP_ERR_WRONGTYPE; /* poor approximation */ + asp->pdu->errstat = statType; + asp->pdu->errindex = count; + return statType; + } + /* actually do the set if necessary */ + if (asp->mode == COMMIT) + setVariable(varbind_ptr->val.string, varbind_ptr->type, + varbind_ptr->val_len, statP, statLen); + } + } + /* ... or save the results from assorted GETs */ + else { + snmp_set_var_value(varbind_ptr, statP, statLen); + varbind_ptr->type = statType; + } + } + + if ( varbind_ptr == asp->end ) + return SNMP_ERR_NOERROR; + varbind_ptr = varbind_ptr->next_variable; + if ( asp->mode == RESERVE1 ) + snmp_vars_inc++; + } +} + + + +static int +goodValue(u_char inType, + size_t inLen, + u_char actualType, + size_t actualLen) +{ + if (inLen > actualLen) + return FALSE; + return (inType == actualType); +} + +static void +setVariable(u_char *var_val, + u_char var_val_type, + size_t var_val_len, + u_char *statP, + size_t statLen) +{ + size_t buffersize = 1000; + + switch(var_val_type){ + case ASN_INTEGER: + asn_parse_int(var_val, &buffersize, &var_val_type, (long *)statP, statLen); + break; + case ASN_COUNTER: + case ASN_GAUGE: + case ASN_TIMETICKS: + asn_parse_unsigned_int(var_val, &buffersize, &var_val_type, (u_long *)statP, statLen); + break; + case ASN_COUNTER64: + asn_parse_unsigned_int64(var_val, &buffersize, &var_val_type, + (struct counter64 *)statP, statLen); + break; + case ASN_OCTET_STR: + case ASN_IPADDRESS: + case ASN_OPAQUE: + case ASN_NSAP: + asn_parse_string(var_val, &buffersize, &var_val_type, statP, &statLen); + break; + case ASN_OBJECT_ID: + asn_parse_objid(var_val, &buffersize, &var_val_type, (oid *)statP, &statLen); + break; + case ASN_BIT_STR: + asn_parse_bitstring(var_val, &buffersize, &var_val_type, statP, &statLen); + break; + } +} diff --git a/packages/net/snmp/agent/current/src/snmp_vars.c b/packages/net/snmp/agent/current/src/snmp_vars.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/snmp_vars.c @@ -0,0 +1,552 @@ +//========================================================================== +// +// ./agent/current/src/snmp_vars.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmp_vars.c - return a pointer to the named variable. + * + * + */ +/*********************************************************** + Copyright 1988, 1989, 1990 by Carnegie Mellon University + Copyright 1989 TGV, Incorporated + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and TGV not be used +in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. + +CMU AND TGV DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL CMU OR TGV BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +******************************************************************/ +/* + * additions, fixes and enhancements for Linux by Erik Schoenfelder + * (schoenfr@ibr.cs.tu-bs.de) 1994/1995. + * Linux additions taken from CMU to UCD stack by Jennifer Bray of Origin + * (jbray@origin-at.co.uk) 1997 + */ + + +#include +#if HAVE_STRING_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#include +#include +#if HAVE_FCNTL_H +#include +#endif + +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_SYS_SOCKET_H +#include +#elif HAVE_WINSOCK_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_NETINET_IN_SYSTM_H +#include +#endif +#if HAVE_NETINET_IP_H +#include +#endif +#ifdef INET6 +#if HAVE_NETINET_IP6_H +#include +#endif +#endif +#if HAVE_SYS_QUEUE_H +#include +#endif +#if HAVE_SYS_STREAM_H +#include +#endif +#if HAVE_NET_ROUTE_H +#include +#endif +#if HAVE_NETINET_IP_VAR_H +#include +#endif +#ifdef INET6 +#if HAVE_NETINET6_IP6_VAR_H +#include +#endif +#endif +#if HAVE_NETINET_IN_PCB_H +#include +#endif +#if HAVE_INET_MIB2_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "mibincl.h" +#include "snmpv3.h" +#include "snmpusm.h" +#include "system.h" +#include "kernel.h" +#include "snmp_vars.h" +#include "default_store.h" +#include "ds_agent.h" + +#include "mibgroup/struct.h" +#include "read_config.h" +#include "snmp_vars.h" +#include "agent_read_config.h" +#include "agent_registry.h" +#include "transform_oids.h" +#include "callback.h" +#include "snmp_alarm.h" +#include "snmpd.h" +#include "mib_module_includes.h" + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/* mib clients are passed a pointer to a oid buffer. Some mib clients + * (namely, those first noticed in mibII/vacm.c) modify this oid buffer + * before they determine if they really need to send results back out + * using it. If the master agent determined that the client was not the + * right one to talk with, it will use the same oid buffer to pass to the + * rest of the clients, which may not longer be valid. This should be + * fixed in all clients rather than the master. However, its not a + * particularily easy bug to track down so this saves debugging time at + * the expense of a few memcpy's. + */ +#define MIB_CLIENTS_ARE_EVIL 1 + +extern struct subtree *subtrees; +int subtree_size; +int subtree_malloc_size; + +/* + * Each variable name is placed in the variable table, without the + * terminating substring that determines the instance of the variable. When + * a string is found that is lexicographicly preceded by the input string, + * the function for that entry is called to find the method of access of the + * instance of the named variable. If that variable is not found, NULL is + * returned, and the search through the table continues (it will probably + * stop at the next entry). If it is found, the function returns a character + * pointer and a length or a function pointer. The former is the address + * of the operand, the latter is a write routine for the variable. + * + * u_char * + * findVar(name, length, exact, var_len, write_method) + * oid *name; IN/OUT - input name requested, output name found + * int length; IN/OUT - number of sub-ids in the in and out oid's + * int exact; IN - TRUE if an exact match was requested. + * int len; OUT - length of variable or 0 if function returned. + * int write_method; OUT - pointer to function to set variable, + * otherwise 0 + * + * The writeVar function is returned to handle row addition or complex + * writes that require boundary checking or executing an action. + * This routine will be called three times for each varbind in the packet. + * The first time for each varbind, action is set to RESERVE1. The type + * and value should be checked during this pass. If any other variables + * in the MIB depend on this variable, this variable will be stored away + * (but *not* committed!) in a place where it can be found by a call to + * writeVar for a dependent variable, even in the same PDU. During + * the second pass, action is set to RESERVE2. If this variable is dependent + * on any other variables, it will check them now. It must check to see + * if any non-committed values have been stored for variables in the same + * PDU that it depends on. Sometimes resources will need to be reserved + * in the first two passes to guarantee that the operation can proceed + * during the third pass. During the third pass, if there were no errors + * in the first two passes, writeVar is called for every varbind with action + * set to COMMIT. It is now that the values should be written. If there + * were errors during the first two passes, writeVar is called in the third + * pass once for each varbind, with the action set to FREE. An opportunity + * is thus provided to free those resources reserved in the first two passes. + * + * writeVar(action, var_val, var_val_type, var_val_len, statP, name, name_len) + * int action; IN - RESERVE1, RESERVE2, COMMIT, or FREE + * u_char *var_val; IN - input or output buffer space + * u_char var_val_type; IN - type of input buffer + * int var_val_len; IN - input and output buffer len + * u_char *statP; IN - pointer to local statistic + * oid *name IN - pointer to name requested + * int name_len IN - number of sub-ids in the name + */ + +long long_return; +#ifndef ibm032 +u_char return_buf[258]; +#else +u_char return_buf[256]; /* nee 64 */ +#endif + +struct timeval starttime; + +void +init_agent (const char *app) +{ + /* get current time (ie, the time the agent started) */ + gettimeofday(&starttime, NULL); + starttime.tv_sec--; + starttime.tv_usec += 1000000L; + + /* we handle alarm signals ourselves in the select loop */ + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG, 1); + + usm_set_reportErrorOnUnknownID(1); + +#ifdef CAN_USE_NLIST + init_kmem("/dev/kmem"); +#endif + + setup_tree(); + + init_agent_read_config(app); + +#ifdef TESTING + auto_nlist_print_tree(-2, 0); +#endif + + /* initialize agentx subagent if necessary. */ +#ifdef USING_AGENTX_SUBAGENT_MODULE + if(ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT) + subagent_pre_init(); +#endif + +} /* end init_agent() */ + + + +oid nullOid[] = {0,0}; +int nullOidLen = sizeof(nullOid)/sizeof(oid); + +/* + * getStatPtr - return a pointer to the named variable, as well as it's + * type, length, and access control list. + * Now uses 'search_subtree' (recursively) and 'search_subtree_vars' + * to do most of the work + * + * If an exact match for the variable name exists, it is returned. If not, + * and exact is false, the next variable lexicographically after the + * requested one is returned. + * + * If no appropriate variable can be found, NULL is returned. + */ +static int found; + +static u_char * +search_subtree_vars(struct subtree *tp, + oid *name, /* IN - name of var, OUT - name matched */ + size_t *namelen, /* IN -number of sub-ids in name, + OUT - subid-is in matched name */ + u_char *type, /* OUT - type of matched variable */ + size_t *len, /* OUT - length of matched variable */ + u_short *acl, /* OUT - access control list */ + int exact, /* IN - TRUE if exact match wanted */ + WriteMethod **write_method, + struct snmp_pdu *pdu, /* IN - relevant auth info re PDU */ + int *noSuchObject) +{ + register struct variable *vp; + struct variable compat_var, *cvp = &compat_var; + register int x; + u_char *access = NULL; + int result; + oid *suffix; + size_t suffixlen; +#if MIB_CLIENTS_ARE_EVIL + oid save[MAX_OID_LEN]; + size_t savelen = 0; +#endif + + if ( tp->variables == NULL ) + return NULL; + + result = compare_tree(name, *namelen, tp->name, tp->namelen); + suffixlen = *namelen - tp->namelen; + suffix = name + tp->namelen; + /* the following is part of the setup for the compatability + structure below that has been moved out of the main loop. + */ + memcpy(cvp->name, tp->name, tp->namelen * sizeof(oid)); + + *noSuchObject = TRUE; /* In case of null variables_len */ + for(x = 0, vp = tp->variables; x < tp->variables_len; + vp =(struct variable *)((char *)vp +tp->variables_width), x++){ + /* if exact and ALWAYS + if next and result >= 0 */ + /* and if vp->namelen != 0 -- Wes */ + if (vp->namelen && (exact || result >= 0)){ + result = compare_tree(suffix, suffixlen, vp->name, + vp->namelen); + } + /* if exact and result == 0 + if next and result <= 0 */ + /* or if vp->namelen == 0 -- Wes */ + if ((!exact && (result <= 0)) || (exact && (result == 0)) || + vp->namelen == 0) { + /* builds an old (long) style variable structure to retain + compatability with var_* functions written previously. + */ + if (vp->namelen) + memcpy((cvp->name + tp->namelen), + vp->name, vp->namelen * sizeof(oid)); + cvp->namelen = tp->namelen + vp->namelen; + cvp->type = vp->type; + cvp->magic = vp->magic; + cvp->acl = vp->acl; + cvp->findVar = vp->findVar; + *write_method = NULL; +#if MIB_CLIENTS_ARE_EVIL + memcpy(save, name, *namelen*sizeof(oid)); + savelen = *namelen; +#endif + DEBUGMSGTL(("snmp_vars", "Trying variable: ")); + DEBUGMSGOID(("snmp_vars", cvp->name, cvp->namelen)); + DEBUGMSG(("snmp_vars"," ...\n")); + + gaga: + access = (*(vp->findVar))(cvp, name, namelen, exact, + len, write_method); + DEBUGMSGTL(("snmp_vars", "Returned %s\n", + (access==NULL) ? "(null)" : "something" )); + + /* + * Check that the answer is acceptable. + * i.e. lies within the current subtree chunk + * + * It might be worth saving this answer just in + * case it turns out to be valid, but for now + * we'll simply discard it. + */ + if ( access && snmp_oid_compare(name, *namelen, + tp->end, tp->end_len) > 0) { + memcpy(name, tp->end, tp->end_len); + access = 0; + } +#if MIB_CLIENTS_ARE_EVIL + if (access == NULL) { + if (snmp_oid_compare(name, *namelen, save, savelen) != 0) { + DEBUGMSGTL(("snmp_vars", "evil_client: ")); + DEBUGMSGOID(("snmp_vars", save, savelen)); + DEBUGMSG(("snmp_vars"," =>")); + DEBUGMSGOID(("snmp_vars", name, *namelen)); + DEBUGMSG(("snmp_vars","\n")); + memcpy(name, save, savelen*sizeof(oid)); + *namelen = savelen; + } + } +#endif + if (*write_method) + *acl = cvp->acl; + /* check for permission to view this part of the OID tree */ + if ((access != NULL || (*write_method != NULL && exact)) && + in_a_view(name, namelen, pdu, cvp->type)) { + if ( access && !exact ) { + /* + * We've got an answer, but shouldn't use it. + * But we *might* be able to use a later + * instance of the same object, so we can't + * legitimately move on to the next variable + * in the variable structure just yet. + * Let's try re-calling the findVar routine + * with the returned name, and see whether + * the next answer is acceptable + */ + *write_method = NULL; + goto gaga; + } + access = NULL; + *write_method = NULL; + } else if (exact){ + found = TRUE; + } + if (access != NULL || (*write_method != NULL && exact)) + break; + } + /* if exact and result <= 0 */ + if (exact && (result <= 0)){ + *type = cvp->type; + *acl = cvp->acl; + if (found) + *noSuchObject = FALSE; + else + *noSuchObject = TRUE; + return NULL; + } + } + if (access != NULL || (exact && *write_method != NULL)) { + *type = cvp->type; + *acl = cvp->acl; + return access; + } + return NULL; +} + +u_char * +getStatPtr( + oid *name, /* IN - name of var, OUT - name matched */ + size_t *namelen, /* IN -number of sub-ids in name, + OUT - subid-is in matched name */ + u_char *type, /* OUT - type of matched variable */ + size_t *len, /* OUT - length of matched variable */ + u_short *acl, /* OUT - access control list */ + int exact, /* IN - TRUE if exact match wanted */ + WriteMethod **write_method, + struct snmp_pdu *pdu, /* IN - relevant auth info re PDU */ + int *noSuchObject) +{ + struct subtree *tp; + oid save[MAX_OID_LEN]; + size_t savelen = 0; + u_char result_type; + u_short result_acl; + u_char *search_return=NULL; + + found = FALSE; + + if (!exact){ + memcpy(save, name, *namelen * sizeof(oid)); + savelen = *namelen; + } + *write_method = NULL; + + DEBUGMSGTL(("snmp_vars", "Looking for: ")); + DEBUGMSGOID(("snmp_vars", name, *namelen)); + DEBUGMSG(("snmp_vars"," ...\n")); + + tp = find_subtree(name, *namelen, NULL); + + while ( search_return == NULL && tp != NULL ) { + DEBUGMSGTL(("snmp_vars", "Trying tree: ")); + DEBUGMSGOID(("snmp_vars", tp->name, tp->namelen)); + DEBUGMSG(("snmp_vars"," ...\n")); + search_return = search_subtree_vars( tp, name, namelen, &result_type, + len, &result_acl, exact, write_method, + pdu, noSuchObject); + if ( search_return != NULL || exact ) + break; + tp = tp->next; + } + if ( tp == NULL ) { + if (!search_return && !exact){ + memcpy(name, save, savelen * sizeof(oid)); + *namelen = savelen; + } + if (found) + *noSuchObject = FALSE; + else + *noSuchObject = TRUE; + return NULL; + } + *type = result_type; + *acl = result_acl; + return search_return; +} + diff --git a/packages/net/snmp/agent/current/src/snmpd.c b/packages/net/snmp/agent/current/src/snmpd.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/snmpd.c @@ -0,0 +1,1017 @@ +//========================================================================== +// +// ./agent/current/src/snmpd.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmpd.c - rrespond to SNMP queries from management stations + * + */ +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +#include + +#include +#include +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include +#elif HAVE_WINSOCK_H +#include +#endif +#if HAVE_NET_IF_H +#include +#endif +#if HAVE_INET_MIB2_H +#include +#endif +#if HAVE_SYS_IOCTL_H +#include +#endif +#if HAVE_SYS_FILE_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include +#endif +#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifndef FD_SET +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) memset((p), 0, sizeof(*(p))) +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "system.h" +#include "read_config.h" +#include "snmp.h" +#include "mib.h" +#include "m2m.h" +#include "snmp_vars.h" +#include "agent_read_config.h" +#include "snmpv3.h" +#include "callback.h" +#include "snmp_alarm.h" +#include "default_store.h" +#include "mib_module_config.h" + +#include "snmp_client.h" +#include "snmpd.h" +#include "var_struct.h" +#include "mibgroup/struct.h" +#include "mibgroup/util_funcs.h" +#include "snmp_debug.h" +#include "mib_modules.h" + +#include "snmpusm.h" +#include "tools.h" +#include "lcd_time.h" + +#include "transform_oids.h" + +#include "snmp_agent.h" +#include "agent_trap.h" +#include "ds_agent.h" +#include "agent_read_config.h" +#include "snmp_logging.h" + +#include "version.h" + +#include "mib_module_includes.h" + +/* + * Globals. + */ +#ifdef USE_LIBWRAP +#include + +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING; +#endif /* USE_LIBWRAP */ + +#define TIMETICK 500000L +#define ONE_SEC 1000000L + +int log_addresses = 0; +int snmp_dump_packet; +int running = 1; +int reconfig = 0; + +struct addrCache { + in_addr_t addr; + int status; +#define UNUSED 0 +#define USED 1 +#define OLD 2 +}; + +#define ADDRCACHE 10 + +static struct addrCache addrCache[ADDRCACHE]; +static int lastAddrAge = 0; + +extern char **argvrestartp; +extern char *argvrestart; +extern char *argvrestartname; + +#define NUM_SOCKETS 32 + +#ifdef USING_SMUX_MODULE +static int sdlist[NUM_SOCKETS], sdlen = 0; +int smux_listen_sd; +#endif /* USING_SMUX_MODULE */ + +/* + * Prototypes. + */ +int snmp_read_packet (int); +int snmp_input (int, struct snmp_session *, int, struct snmp_pdu *, void *); +static void usage (char *); +int main (int, char **); +static void SnmpTrapNodeDown (void); +static int receive(void); +int snmp_check_packet(struct snmp_session*, snmp_ipaddr); +int snmp_check_parse(struct snmp_session*, struct snmp_pdu*, int); + +static void usage(char *prog) +{ + printf("\nUsage: %s [-h] [-v] [-f] [-a] [-d] [-V] [-P PIDFILE] [-q] [-D] [-p NUM] [-L] [-l LOGFILE] [-r]",prog); +#if HAVE_UNISTD_H + printf(" [-u uid] [-g gid]"); +#endif + printf("\n"); + printf("\n\tVersion: %s\n",VersionInfo); + printf("\tAuthor: Wes Hardaker\n"); + printf("\tEmail: ucd-snmp-coders@ucd-snmp.ucdavis.edu\n"); + printf("\n-h\t\tThis usage message.\n"); + printf("-H\t\tDisplay configuration file directives understood.\n"); + printf("-v\t\tVersion information.\n"); + printf("-f\t\tDon't fork from the shell.\n"); + printf("-a\t\tLog addresses.\n"); + printf("-d\t\tDump sent and received UDP SNMP packets\n"); + printf("-V\t\tVerbose display\n"); + printf("-P PIDFILE\tUse PIDFILE to store process id\n"); + printf("-q\t\tPrint information in a more parsable format (quick-print)\n"); + printf("-D\t\tTurn on debugging output\n"); + printf("-p NUM\t\tRun on port NUM instead of the default: 161\n"); + printf("-x SOCKADDR\tBind AgentX to this address\n"); + printf("-c CONFFILE\tRead CONFFILE as a configuration file.\n"); + printf("-C\t\tDon't read the default configuration files.\n"); + printf("-L\t\tPrint warnings/messages to stdout/err\n"); + printf("-s\t\tLog warnings/messages to syslog\n"); + printf("-A\t\tAppend to the logfile rather than truncating it.\n"); + printf("-r Don't exit if root only accessible files can't be opened\n"); + printf("-l LOGFILE\tPrint warnings/messages to LOGFILE\n"); + printf("\t\t(By default LOGFILE=%s)\n", +#ifdef LOGFILE + LOGFILE +#else + "none" +#endif + ); +#if HAVE_UNISTD_H + printf("-g \t\tChange to this gid after opening port\n"); + printf("-u \t\tChange to this uid after opening port\n"); +#endif + printf("\n"); + exit(1); +} + + RETSIGTYPE +SnmpdShutDown(int a) +{ + running = 0; +} + +#ifdef SIGHUP + RETSIGTYPE +SnmpdReconfig(int a) +{ + reconfig = 1; + signal(SIGHUP, SnmpdReconfig); +} +#endif + +#ifdef SIGUSR1 +extern void dump_registry( void ); + RETSIGTYPE +SnmpdDump(int a) +{ + dump_registry(); + signal(SIGUSR1, SnmpdDump); +} +#endif + + + static void +SnmpTrapNodeDown(void) +{ + send_easy_trap (SNMP_TRAP_ENTERPRISESPECIFIC, 2); + /* XXX 2 - Node Down #define it as NODE_DOWN_TRAP */ +} + +/*******************************************************************-o-****** + * main + * + * Parameters: + * argc + * *argv[] + * + * Returns: + * 0 Always succeeds. (?) + * + * + * Setup and start the agent daemon. + * + * Also successfully EXITs with zero for some options. + */ +#if !defined(__ECOS) + + int +main(int argc, char *argv[]) +{ + int arg, i; + int ret; + u_short dest_port = SNMP_PORT; + int dont_fork = 0; + char logfile[SNMP_MAXBUF_SMALL]; + char *cptr, **argvptr; + char *pid_file = NULL; +#if HAVE_GETPID + FILE *PID; +#endif + int dont_zero_log = 0; + int stderr_log=0, syslog_log=0; + int uid=0, gid=0; + + logfile[0] = 0; + +#ifdef LOGFILE + strcpy(logfile, LOGFILE); +#endif + + + /* + * usage: snmpd + */ + for (arg = 1; arg < argc; arg++) + { + if (argv[arg][0] == '-') { + switch (argv[arg][1]) { + + case 'c': + if (++arg == argc) + usage(argv[0]); + ds_set_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG, + argv[arg]); + break; + + case 'C': + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS, 1); + break; + + case 'd': + snmp_set_dump_packet(++snmp_dump_packet); + ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1); + break; + + case 'q': + snmp_set_quick_print(1); + break; + + case 'T': + if (argv[arg][2] != '\0') + cptr = &argv[arg][2]; + else if (++arg>argc) { + fprintf(stderr,"Need UDP or TCP after -T flag.\n"); + usage(argv[0]); + exit(1); + } else { + cptr = argv[arg]; + } + if (strcasecmp(cptr,"TCP") == 0) { + ds_set_int(DS_APPLICATION_ID, DS_AGENT_FLAGS, + ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS) + | SNMP_FLAGS_STREAM_SOCKET); + } else if (strcasecmp(cptr,"UDP") == 0) { + /* default, do nothing */ + } else { + fprintf(stderr, + "Unknown transport \"%s\" after -T flag.\n", + cptr); + usage(argv[0]); + exit(1); + } + break; + + case 'D': + debug_register_tokens(&argv[arg][2]); + snmp_set_do_debugging(1); + break; + + case 'p': + if (++arg == argc) + usage(argv[0]); + dest_port = atoi(argv[arg]); + if (dest_port <= 0) + usage(argv[0]); + break; + + case 'x': + if (++arg == argc) + usage(argv[0]); + ds_set_string(DS_APPLICATION_ID, DS_AGENT_X_SOCKET, argv[arg]); + break; + + case 'r': + ds_set_boolean(DS_APPLICATION_ID, + DS_AGENT_NO_ROOT_ACCESS, 1); + break; + + case 'P': + if (++arg == argc) + usage(argv[0]); + pid_file = argv[arg]; + + case 'a': + log_addresses++; + break; + + case 'V': + ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1); + break; + + case 'f': + dont_fork = 1; + break; + + case 'l': + if (++arg == argc) + usage(argv[0]); + strcpy(logfile, argv[arg]); + break; + + case 'L': + stderr_log=1; + break; + + case 's': + syslog_log=1; + break; + + case 'A': + dont_zero_log = 1; + break; +#if HAVE_UNISTD_H + case 'u': + if (++arg == argc) usage(argv[0]); + uid = atoi(argv[arg]); + break; + case 'g': + if (++arg == argc) usage(argv[0]); + gid = atoi(argv[arg]); + break; +#endif + case 'h': + usage(argv[0]); + break; + case 'H': + init_agent("snmpd"); /* register our .conf handlers */ + init_mib_modules(); + init_snmp("snmpd"); + fprintf(stderr, "Configuration directives understood:\n"); + read_config_print_usage(" "); + exit(0); + case 'v': + printf("\nUCD-snmp version: %s\n",VersionInfo); + printf("Author: Wes Hardaker\n"); + printf("Email: ucd-snmp-coders@ucd-snmp.ucdavis.edu\n\n"); + exit (0); + case '-': + switch(argv[arg][2]){ + case 'v': + printf("\nUCD-snmp version: %s\n",VersionInfo); + printf("Author: Wes Hardaker\n"); + printf("Email: ucd-snmp-coders@ucd-snmp.ucdavis.edu\n\n"); + exit (0); + case 'h': + usage(argv[0]); + exit(0); + } + + default: + printf("invalid option: %s\n", argv[arg]); + usage(argv[0]); + break; + } + continue; + } + } /* end-for */ + + /* + * Initialize a argv set to the current for restarting the agent. + */ + argvrestartp = (char **) malloc((argc + 2) * sizeof(char *)); + argvptr = argvrestartp; + for (i = 0, ret = 1; i < argc; i++) { + ret += strlen(argv[i]) + 1; + } + argvrestart = (char *) malloc(ret); + argvrestartname = (char *) malloc(strlen(argv[0]) + 1); + strcpy(argvrestartname, argv[0]); + if ( strstr(argvrestartname, "agentxd") != NULL) + ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, SUB_AGENT); + else + ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, MASTER_AGENT); + for (cptr = argvrestart, i = 0; i < argc; i++) { + strcpy(cptr, argv[i]); + *(argvptr++) = cptr; + cptr += strlen(argv[i]) + 1; + } + *cptr = 0; + *argvptr = NULL; + + + /* + * Open the logfile if necessary. + */ + + /* Should open logfile and/or syslog based on arguments */ + if (logfile[0]) + snmp_enable_filelog(logfile, dont_zero_log); + if (syslog_log) + snmp_enable_syslog(); +#ifdef BUFSIZ + setvbuf(stdout, NULL, _IOLBF, BUFSIZ); +#endif + /* + * Initialize the world. Detach from the shell. + * Create initial user. + */ +#if HAVE_FORK + if (!dont_fork && fork() != 0) { + exit(0); + } +#endif + +#if HAVE_GETPID + if (pid_file != NULL) { + if ((PID = fopen(pid_file, "w")) == NULL) { + snmp_log_perror("fopen"); + if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) + exit(1); + } + else { + fprintf(PID, "%d\n", (int)getpid()); + fclose(PID); + } + } +#endif + +#else /* __ECOS environment: */ +void snmpd( void ) { + int arg, i; + int ret; + u_short dest_port = SNMP_PORT; +#define stderr_log 1 +#endif + + extern void init_all_network_interfaces(void); + + init_all_network_interfaces(); + + SOCK_STARTUP; + init_agent("snmpd"); /* do what we need to do first. */ + init_mib_modules(); + + + /* start library */ + init_snmp("snmpd"); + + ret = init_master_agent( dest_port, + snmp_check_packet, + snmp_check_parse ); + if( ret != 0 ) + Exit(1); /* Exit logs exit val for us */ + +#ifdef SIGTERM + signal(SIGTERM, SnmpdShutDown); +#endif +#ifdef SIGINT + signal(SIGINT, SnmpdShutDown); +#endif +#ifdef SIGHUP + signal(SIGHUP, SnmpdReconfig); +#endif +#ifdef SIGUSR1 + signal(SIGUSR1, SnmpdDump); +#endif + + /* send coldstart trap via snmptrap(1) if possible */ + send_easy_trap (0, 0); + +#if HAVE_UNISTD_H + if (gid) { + DEBUGMSGTL(("snmpd", "Changing gid to %d.\n", gid)); + if (setgid(gid)==-1) { + snmp_log_perror("setgid failed"); + if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) + exit(1); + } + } + if (uid) { + DEBUGMSGTL(("snmpd", "Changing uid to %d.\n", uid)); + if(setuid(uid)==-1) { + snmp_log_perror("setuid failed"); + if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) + exit(1); + } + } +#endif + + /* honor selection of standard error output */ + if (!stderr_log) + snmp_disable_stderrlog(); + + /* we're up, log our version number */ + snmp_log(LOG_INFO, "UCD-SNMP version %s\n", VersionInfo); + + memset(addrCache, 0, sizeof(addrCache)); + /* + * Forever monitor the dest_port for incoming PDUs. + */ + DEBUGMSGTL(("snmpd", "We're up. Starting to process data.\n")); + receive(); +#include "mib_module_shutdown.h" + DEBUGMSGTL(("snmpd", "sending shutdown trap\n")); + SnmpTrapNodeDown(); + DEBUGMSGTL(("snmpd", "Bye...\n")); + snmp_shutdown("snmpd"); + return 0; + +} /* End main() -- snmpd */ + +/*******************************************************************-o-****** + * receive + * + * Parameters: + * + * Returns: + * 0 On success. + * -1 System error. + * + * Infinite while-loop which monitors incoming messges for the agent. + * Invoke the established message handlers for incoming messages on a per + * port basis. Handle timeouts. + */ + static int +receive(void) +{ + int numfds; + fd_set fdset; + struct timeval timeout, *tvp = &timeout; + struct timeval sched, *svp = &sched, + now, *nvp = &now; + int count, block; +#ifdef USING_SMUX_MODULE + int i, sd; +#endif /* USING_SMUX_MODULE */ + + + /* + * Set the 'sched'uled timeout to the current time + one TIMETICK. + */ + gettimeofday(nvp, (struct timezone *) NULL); + svp->tv_usec = nvp->tv_usec + TIMETICK; + svp->tv_sec = nvp->tv_sec; + + while (svp->tv_usec >= ONE_SEC){ + svp->tv_usec -= ONE_SEC; + svp->tv_sec++; + } + + /* + * Loop-forever: execute message handlers for sockets with data, + * reset the 'sched'uler. + */ + while (running) { + if (reconfig) { + reconfig = 0; + snmp_log(LOG_INFO, "Reconfiguring daemon\n"); + update_config(); + } + tvp = &timeout; + tvp->tv_sec = 0; + tvp->tv_usec = TIMETICK; + + numfds = 0; + FD_ZERO(&fdset); + block = 0; + snmp_select_info(&numfds, &fdset, tvp, &block); + if (block == 1) + tvp = NULL; /* block without timeout */ + +#ifdef USING_SMUX_MODULE + if (smux_listen_sd >= 0) { + FD_SET(smux_listen_sd, &fdset); + numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; + for (i = 0; i < sdlen; i++) { + FD_SET(sdlist[i], &fdset); + numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds; + } + } +#endif /* USING_SMUX_MODULE */ + + count = select(numfds, &fdset, 0, 0, tvp); + + if (count > 0){ + snmp_read(&fdset); + } else switch(count){ + case 0: + snmp_timeout(); + break; + case -1: + if (errno == EINTR){ + continue; + } else { + snmp_log_perror("select"); + } + return -1; + default: + snmp_log(LOG_ERR, "select returned %d\n", count); + return -1; + } /* endif -- count>0 */ + +#ifdef USING_SMUX_MODULE + /* handle the SMUX sd's */ + if (smux_listen_sd >= 0) { + for (i = 0; i < sdlen; i++) { + if (FD_ISSET(sdlist[i], &fdset)) { + if (smux_process(sdlist[i]) < 0) { + for (; i < (sdlen - 1); i++) { + sdlist[i] = sdlist[i+1]; + } + sdlen--; + } + } + } + /* new connection */ + if (FD_ISSET(smux_listen_sd, &fdset)) { + if ((sd = smux_accept(smux_listen_sd)) >= 0) { + sdlist[sdlen++] = sd; + } + } + } +#endif /* USING_SMUX_MODULE */ + + + + /* + * If the time 'now' is greater than the 'sched'uled time, then: + * + * Check alarm and event timers. + * Reset the 'sched'uled time to current time + one TIMETICK. + * Age the cache network addresses (from whom messges have + * been received). + */ + gettimeofday(nvp, (struct timezone *) NULL); + + if (nvp->tv_sec > svp->tv_sec + || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){ + svp->tv_usec = nvp->tv_usec + TIMETICK; + svp->tv_sec = nvp->tv_sec; + + while (svp->tv_usec >= ONE_SEC){ + svp->tv_usec -= ONE_SEC; + svp->tv_sec++; + } + if (log_addresses && lastAddrAge++ > 600){ + + lastAddrAge = 0; + for(count = 0; count < ADDRCACHE; count++){ + if (addrCache[count].status == OLD) + addrCache[count].status = UNUSED; + if (addrCache[count].status == USED) + addrCache[count].status = OLD; + } + } + } /* endif -- now>sched */ + + /* run requested alarms */ + run_alarms(); + + } /* endwhile */ + + snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); + return 0; + +} /* end receive() */ + + + + +/*******************************************************************-o-****** + * snmp_check_packet + * + * Parameters: + * session, from + * + * Returns: + * 1 On success. + * 0 On error. + * + * Handler for all incoming messages (a.k.a. packets) for the agent. If using + * the libwrap utility, log the connection and deny/allow the access. Print + * output when appropriate, and increment the incoming counter. + * + */ +int +snmp_check_packet(struct snmp_session *session, + snmp_ipaddr from) +{ + struct sockaddr_in *fromIp = (struct sockaddr_in *)&from; + +#ifdef USE_LIBWRAP + const char *addr_string; + /* + * Log the message and/or dump the message. + * Optionally cache the network address of the sender. + */ + addr_string = inet_ntoa(fromIp->sin_addr); + + if(!addr_string) { + addr_string = STRING_UNKNOWN; + } + if(hosts_ctl("snmpd", addr_string, addr_string, STRING_UNKNOWN)) { + snmp_log(allow_severity, "Connection from %s\n", addr_string); + } else { + snmp_log(deny_severity, "Connection from %s REFUSED\n", addr_string); + return(0); + } +#endif /* USE_LIBWRAP */ + + snmp_increment_statistic(STAT_SNMPINPKTS); + + if (log_addresses || ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)){ + int count; + + for(count = 0; count < ADDRCACHE; count++){ + if (addrCache[count].status > UNUSED /* used or old */ + && fromIp->sin_addr.s_addr == addrCache[count].addr) + break; + } + + if (count >= ADDRCACHE || + ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)){ + snmp_log(LOG_INFO, "Received SNMP packet(s) from %s\n", + inet_ntoa(fromIp->sin_addr)); + for(count = 0; count < ADDRCACHE; count++){ + if (addrCache[count].status == UNUSED){ + addrCache[count].addr = fromIp->sin_addr.s_addr; + addrCache[count].status = USED; + break; + } + } + } else { + addrCache[count].status = USED; + } + } + + return ( 1 ); +} + + +int +snmp_check_parse( struct snmp_session *session, + struct snmp_pdu *pdu, + int result) +{ + if ( result == 0 ) { + if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) && + snmp_get_do_logging() ) { + char c_oid [SPRINT_MAX_LEN]; + struct variable_list *var_ptr; + + switch (pdu->command) { + case SNMP_MSG_GET: + snmp_log(LOG_DEBUG, " GET message\n"); break; + case SNMP_MSG_GETNEXT: + snmp_log(LOG_DEBUG, " GETNEXT message\n"); break; + case SNMP_MSG_RESPONSE: + snmp_log(LOG_DEBUG, " RESPONSE message\n"); break; + case SNMP_MSG_SET: + snmp_log(LOG_DEBUG, " SET message\n"); break; + case SNMP_MSG_TRAP: + snmp_log(LOG_DEBUG, " TRAP message\n"); break; + case SNMP_MSG_GETBULK: + snmp_log(LOG_DEBUG, " GETBULK message, non-rep=%d, max_rep=%d\n", + pdu->errstat, pdu->errindex); break; + case SNMP_MSG_INFORM: + snmp_log(LOG_DEBUG, " INFORM message\n"); break; + case SNMP_MSG_TRAP2: + snmp_log(LOG_DEBUG, " TRAP2 message\n"); break; + case SNMP_MSG_REPORT: + snmp_log(LOG_DEBUG, " REPORT message\n"); break; + } + + for ( var_ptr = pdu->variables ; + var_ptr != NULL ; var_ptr=var_ptr->next_variable ) + { + sprint_objid (c_oid, var_ptr->name, var_ptr->name_length); + snmp_log(LOG_DEBUG, " -- %s\n", c_oid); + } + } + return 1; + } + return 0; /* XXX: does it matter what the return value is? */ +} + +/*******************************************************************-o-****** + * snmp_input + * + * Parameters: + * op + * *session + * requid + * *pdu + * *magic + * + * Returns: + * 1 On success -OR- + * Passes through Return from alarmGetResponse() when + * USING_V2PARTY_ALARM_MODULE is defined. + * + * Call-back function to manage responses to traps (informs) and alarms. + * Not used by the agent to process other Response PDUs. + */ +int +snmp_input(int op, + struct snmp_session *session, + int reqid, + struct snmp_pdu *pdu, + void *magic) +{ + struct get_req_state *state = (struct get_req_state *)magic; + + if (op == RECEIVED_MESSAGE) { + if (pdu->command == SNMP_MSG_GET) { + if (state->type == EVENT_GET_REQ) { + /* this is just the ack to our inform pdu */ + return 1; + } + } + } + else if (op == TIMED_OUT) { + if (state->type == ALARM_GET_REQ) { + /* Need a mechanism to replace obsolete SNMPv2p alarm */ + } + } + return 1; + +} /* end snmp_input() */ diff --git a/packages/net/snmp/agent/current/src/snmptask.c b/packages/net/snmp/agent/current/src/snmptask.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/src/snmptask.c @@ -0,0 +1,191 @@ +//========================================================================== +// +// ./agent/current/src/snmptask.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +//========================================================================== +// +// snmptask.c +// +// eCos wrapper for the SNMP daemon +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// Support routines, etc., used by network code + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + + + + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL + 102400 +static char netsnmp_stack[STACK_SIZE]; +static cyg_thread netsnmp_thread_data; +static cyg_handle_t netsnmp_thread_handle; + + + + + + +externC void snmpd( void ); + +// Network initialization +// This function is called during system initialization to setup the whole +// networking environment. +// + +void +cyg_net_snmp_init(void) +{ + + // Create network background thread + cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY-2, // Priority + snmpd, // entry + 0, // entry parameter + "snmpd", // Name + &netsnmp_stack[0], // Stack + STACK_SIZE, // Size + &netsnmp_thread_handle, // Handle + &netsnmp_thread_data // Thread data structure + ); + cyg_thread_resume(netsnmp_thread_handle); // Start it + // Done + +} diff --git a/packages/net/snmp/agent/current/tests/snmpping.c b/packages/net/snmp/agent/current/tests/snmpping.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/tests/snmpping.c @@ -0,0 +1,356 @@ +//========================================================================== +// +// ./agent/current/tests/snmpping.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +//========================================================================== +// +// tests/snmpping.c +// +// Simple test of PING (ICMP) and networking support +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// PING test code + +#include + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +static char stack[STACK_SIZE]; +static cyg_thread thread_data; +static cyg_handle_t thread_handle; + +#define NUM_PINGS 16 +#define MAX_PACKET 4096 +static unsigned char pkt1[MAX_PACKET], pkt2[MAX_PACKET]; + +#define UNIQUEID 0x1234 + +extern void +cyg_test_exit(void); + +void +pexit(char *s) +{ + perror(s); + cyg_test_exit(); +} + +// Compute INET checksum +int +inet_cksum(u_short *addr, int len) +{ + register int nleft = len; + register u_short *w = addr; + register u_short answer; + register u_int sum = 0; + u_short odd_byte = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), + * we add sequential 16 bit words to it, and at the end, fold + * back all the carry bits from the top 16 bits into the lower + * 16 bits. + */ + while( nleft > 1 ) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if( nleft == 1 ) { + *(u_char *)(&odd_byte) = *(u_char *)w; + sum += odd_byte; + } + + /* + * add back carry outs from top 16 bits to low 16 bits + */ + sum = (sum >> 16) + (sum & 0x0000ffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} + +static int +show_icmp(unsigned char *pkt, int len, + struct sockaddr_in *from, struct sockaddr_in *to) +{ + cyg_tick_count_t *tp, tv; + struct ip *ip; + struct icmp *icmp; + tv = cyg_current_time(); + ip = (struct ip *)pkt; + if ((len < sizeof(*ip)) || ip->ip_v != IPVERSION) { + diag_printf("%s: Short packet or not IP! - Len: %d, Version: %d\n", + inet_ntoa(from->sin_addr), len, ip->ip_v); + return 0; + } + icmp = (struct icmp *)(pkt + sizeof(*ip)); + len -= (sizeof(*ip) + 8); + tp = (cyg_tick_count_t *)&icmp->icmp_data; + if (icmp->icmp_type != ICMP_ECHOREPLY) { + diag_printf("%s: Invalid ICMP - type: %d\n", + inet_ntoa(from->sin_addr), icmp->icmp_type); + return 0; + } + if (icmp->icmp_id != UNIQUEID) { + diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n", + inet_ntoa(from->sin_addr), UNIQUEID, icmp->icmp_id); + } + diag_printf("%d bytes from %s: ", len, inet_ntoa(from->sin_addr)); + diag_printf("icmp_seq=%d", icmp->icmp_seq); + diag_printf(", time=%dms\n", (int)(tv - *tp)*10); + return (from->sin_addr.s_addr == to->sin_addr.s_addr); +} + +static void +ping_host(int s, struct sockaddr_in *host) +{ + struct icmp *icmp = (struct icmp *)pkt1; + int icmp_len = 64; + int seq, ok_recv, bogus_recv; + cyg_tick_count_t *tp; + long *dp; + struct sockaddr_in from; + int i, len, fromlen; + + ok_recv = 0; + bogus_recv = 0; + diag_printf("PING server %s\n", inet_ntoa(host->sin_addr)); + for (seq = 0; seq < NUM_PINGS; seq++) { + // Build ICMP packet + icmp->icmp_type = ICMP_ECHO; + icmp->icmp_code = 0; + icmp->icmp_cksum = 0; + icmp->icmp_seq = seq; + icmp->icmp_id = 0x1234; + // Set up ping data + tp = (cyg_tick_count_t *)&icmp->icmp_data; + *tp++ = cyg_current_time(); + dp = (long *)tp; + for (i = sizeof(*tp); i < icmp_len; i += sizeof(*dp)) { + *dp++ = i; + } + // Add checksum + icmp->icmp_cksum = inet_cksum( (u_short *)icmp, icmp_len+8); + // Send it off + if (sendto(s, icmp, icmp_len+8, 0, (struct sockaddr *)host, sizeof(*host)) < 0) { + perror("sendto"); + continue; + } + // Wait for a response + fromlen = sizeof(from); + len = recvfrom(s, pkt2, sizeof(pkt2), 0, (struct sockaddr *)&from, &fromlen); + if (len < 0) { + perror("recvfrom"); + } else { + if (show_icmp(pkt2, len, &from, host)) { + ok_recv++; + } else { + bogus_recv++; + } + } + } + diag_printf("Sent %d packets, received %d OK, %d bad\n", NUM_PINGS, ok_recv, bogus_recv); +} + +static void +ping_test(struct bootp *bp) +{ + struct protoent *p; + struct timeval tv; + struct sockaddr_in host; + int s; + + if ((p = getprotobyname("icmp")) == (struct protoent *)0) { + perror("getprotobyname"); + return; + } + s = socket(AF_INET, SOCK_RAW, p->p_proto); + if (s < 0) { + perror("socket"); + return; + } + tv.tv_sec = 1; + tv.tv_usec = 0; + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + // Set up host address + host.sin_family = AF_INET; + host.sin_addr = bp->bp_siaddr; + host.sin_port = 0; + ping_host(s, &host); + // Now try a bogus host + host.sin_addr.s_addr = htonl(ntohl(host.sin_addr.s_addr) + 32); + ping_host(s, &host); + close(s); +} + +void +net_test(cyg_addrword_t p) +{ + int i = 4; + diag_printf("Start PING test\n"); + init_all_network_interfaces(); +#ifdef CYGPKG_SNMPAGENT + { + extern void cyg_net_snmp_init(void); + cyg_net_snmp_init(); + } +#endif + do { +#ifdef CYGHWR_NET_DRIVER_ETH0 + if (eth0_up) { + ping_test(ð0_bootp_data); + } + cyg_thread_delay(500); +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if (eth1_up) { + ping_test(ð1_bootp_data); + } + cyg_thread_delay(500); +#endif + } while ( i-- > 0 ); + cyg_test_exit(); +} + +void +cyg_start(void) +{ + // Create a main thread, so we can run the scheduler and have time 'pass' + cyg_thread_create(10, // Priority - just a number + net_test, // entry + 0, // entry parameter + "Network test", // Name + &stack[0], // Stack + STACK_SIZE, // Size + &thread_handle, // Handle + &thread_data // Thread data structure + ); + cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); +} diff --git a/packages/net/snmp/agent/current/utils/mib2c/README-eCos b/packages/net/snmp/agent/current/utils/mib2c/README-eCos new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/utils/mib2c/README-eCos @@ -0,0 +1,9 @@ + +perl -I~/perl.pl/nsPerl5.005_03/lib/site/i686-linux mib2c interfaces + +to get the SNMP module on-path. + +setenv MIBS ALL + +and place mibs in /usr/local/share/snmp/mibs/ + diff --git a/packages/net/snmp/agent/current/utils/mib2c/README.mib2c b/packages/net/snmp/agent/current/utils/mib2c/README.mib2c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/utils/mib2c/README.mib2c @@ -0,0 +1,224 @@ +This README describes the ./local/mib2c script. + +Author: Derek Simkowiak + dereks@kd-dev.com + http://www.kd-dev.com + (please mail questions to ucd-snmp-coders@ucd-snmp.ucdavis.edu, + not to the author directly. Thanks!) + +Date: Wed Jan 20 02:51:06 PST 1999 +----------------------------------------------------------------------- +mib2c + +OVERVIEW + + mib2c is a Perl script that takes a MIB (such as those files found +in ./mibs/ ) and converts it into C code. That C code can then be used as a +"template" to implement your MIB. Then, when you are done editing the C +code and recompiling, the UCD-SNMP agent (snmpd) will support your MIB. +mib2c takes the place of "MIB Compilers" that come with commercial SNMP +agents. + + +REQUIREMENTS/INSTALLATION + + mib2c requires the SNMP.pm Perl module. As of this writing the +latest version of the SNMP.pm module is 1.8. + + The SNMP.pm module can be downloaded from CPAN at + +http://www.cpan.org/modules/by-module/SNMP/ + + ...the file that you want is probably SNMP-1.8b5.tar.gz . +If you didn't know that already, most every Perl module can be downloaded +from CPAN (www.cpan.org). Follow the installation instructions for the +module. + + NOTE: If you are running Redhat Linux 5.2 (and perhaps other +versions), you might get the following errors during the "make test" phase +of the installation of the SNMP.pm module: + +[root@olly SNMP-1.8b5]# make test # This is the command... +PERL_DL_NONLAZY=1 /usr/bin/perl -I./blib/arch -I./blib/lib +-I/usr/lib/perl5/i386-linux/5.00404 -I/usr/lib/perl5 -e 'use Test::Harness +qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t +t/mib...............ok +t/session...........FAILED tests 7-8 + Failed 2/14 tests, 85.71% okay +t/translate.........ok +Failed Test Status Wstat Total Fail Failed List of failed +------------------------------------------------------------------------------- +t/session.t 14 2 14.29% 7-8 +Failed 1/3 test scripts, 66.67% okay. 2/24 subtests failed, 91.67% okay. +make: *** [test_dynamic] Error 9 + + + If the "make" went okay, then you can ignore these test failures. +These indicate you don't have write access to the portions of the mib +tree that the test script is trying to use. Please don't email the +UCD-SNMP list with other errors regarding the SNMP.pm module. +comp.lang.perl.modules is probably the most appropriate spot to +discuss problems with the SNMP.pm perl module itself. Interelated +problems between ucd-snmp and SNMP could be discussed on the ucd-snmp +mailing lists though. + + +USAGE + + mib2c takes one argument: an OID. It then traces down that OID +and generates the template C code. Here is the documentation, from the +top of the script: + +# This program, given an OID reference as an argument, creates some +# template mib module files to be used with the ucd-snmp agent. It is +# far from perfect and will not generate working modules, but it +# significantly shortens development time by outlining the basic +# structure. +# +# Its up to you to verify what it does and change the default values +# it returns. +# +# You *must* correct the beginning of the var_XXX() function to +# correctly determine mib ownership of the incoming request. + + +FINDING YOUR MIB + + Before you can specify the OID for your enterprise/MIB on the +command line, the script needs to be able to find your MIB so that it can +read it in and generate template code. Joe Marzot (gmarzot@nortelnetworks.com) +tells us: +-------------------------------------- +you should read (man mib_api). The defaultm behaviour for mib loading +from within the perl interface uses the environment variables described +there. You can also override these and explicitly define mibdirs and +load modules through the perl/SNMP api. + +the easiest thing to do is toss the mibs in /usr/local/share/snmp/mibs +and set the env. var., MIBS, to 'ALL'. +-------------------------------------- + + I recommend following the last two lines of advice. I simply did + +# cp /home/dereks/MY-MIB-FILE.txt /usr/local/share/snmp/mibs/ +# export MIBS=ALL + + ...on my Redhat system (with a BASH shell) and it was able to find +my MIB just fine. + + +EXAMPLES + + Here are some examples from Wes Hardaker (wjhardaker@ucdavis.edu). +He's using a C shell. Wes writes: +-------------------------------------- +Ok, in order to run the thing, you actually need to do something like +this: + +setenv MIBS MY-ITEM-MIB # assumes csh +mib2c itemNode + +Where, "itemNode" should be a node in the mib tree that you want to +generate C code for. Note, pick small pieces not large ones. Yes, it +will generate code for the entire mibII tree if you ask it to, in one +very large mib file. + +Examples: + +% mib2c interfaces +outputing to interfaces.c and interfaces.h ... + depth: 3 + Number of Lines Created: +178 interfaces.c +84 interfaces.h +262 total +Done. + +% mib2c mib-2 # Don't ever do this. +outputing to mib-2.c and mib-2.h ... + depth: 5 + Number of Lines Created: +2783 mib-2.c +617 mib-2.h +3400 total +Done. + +It may have some sorting problems with multiple level mib tree +branches being generated into one piece of code (reorder the .h file +structure to be in OID lexical order if needed). +-------------------------------------- + +WHAT TO DO WITH THE CODE THAT GETS GENERATED + + You will need to edit your generated code to work with your +hardware. For instance, if your MIB is for a refridgerator, you will need +to write the code that talks to the refridgerator (through the serial +port, maybe?) in Fridge Protocol. + + See the files in ./agent/mibgroup/examples/ and +./agent/mibgroup/dummy/ for heavily-commented example code. Don't ask me +questions about this stuff--I'm just now figuring it out myself... + + [NOTE: If anyone out there has tips about necessary options to +./configure, or re-compiling snmpd with custom MIB support, please add +them here...] + +WARNING + + As of this writing, the mib2c compiler is a bit outdated and needs +some work. Wes writes: +-------------------------------------- +It already needs changing, because the architecture has changed in the +3.6 line (though its backwards compatible, I'd prefer to generate +code from newer models than older ones). +-------------------------------------- + When I asked him to elaborate on the new 3.6 archictecture, all I +got was: +-------------------------------------- +It hopefully will be in the new documentation about mib module api +that Dave Shield is putting together (which is also currently wrong, +for that matter)... +-------------------------------------- + ...so I don't know what the hell he's talking about. + + +SOME ERRORS AND THEIR MEANING + + If you get a large number of errors that look like: + +[...] +unknown type: INTEGER for prIndex +unknown type: OCTETSTR for prNames +unknown type: INTEGER for prMin +[...] + + ...then you are trying to use an old version of the mib2c script +that does not support the SNMP.pm module version 1.8. Get the latest +version of the script. + + If you get the error + +Couldn't find mib reference: myEnterpriseOID + + ...when you know that it should be finding your MIB file(s), then +you forgot to put the word "END" at the very end of your MIB. (Uh...I'm +not speaking from experience here. Really.) + +ACKNOWLEGMENTS + + Many thanks to the people on the UCD-SNMP mailing list +(ucd-snmp@ucd-snmp.ucdavis.edu). In particular, many thanks to + +Wes Hardaker +Ken McNamara +Joe Marzot + + ...since about half this document is just cut'n'pasted from emails +they sent me. + + Good luck with your project. + +Derek Simkowiak +dereks@kd-dev.com +http://www.kd-dev.com + diff --git a/packages/net/snmp/agent/current/utils/mib2c/mib2c b/packages/net/snmp/agent/current/utils/mib2c/mib2c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/utils/mib2c/mib2c @@ -0,0 +1,310 @@ +#!/usr/bin/perl +#!/usr/bin/perl -w + +# +# Description: +# +# This program, given an OID reference as an argument, creates some +# template mib module files to be used with the ucd-snmp agent. It is +# far from perfect and will not generate working modules, but it +# significantly shortens development time by outlining the basic +# structure. +# +# Its up to you to verify what it does and change the default values +# it returns. +# + +use SNMP; +use FileHandle; + +#use strict 'vars'; +$SNMP::save_descriptions=1; +$SNMP::use_long_names=1; +$SNMP::use_enums=1; +SNMP::initMib(); + +$configfile="mib2c.conf"; +$debug=0; +$nostats = 0; + +sub usage { + print "$0 [-h] [-c configfile] [-f prefix] mibNode\n\n"; + print " -h\t\tThis message.\n\n"; + print " -c configfile\tSpecifies the configuration file to use\n\t\tthat dictates what the output of mib2c will look like.\n\n"; + print " -f prefix\tSpecifies the output prefix to use. All code\n\t\twill be put into prefix.c and prefix.h\n\n"; + print " mibNode\tThe name of the top level mib node you want to\n\t\tgenerate code for. By default, the code will be stored in\n\t\tmibNode.c and mibNode.h (use the -f flag to change this)\n\n"; + print " -d\t\tdebugging output (dont do it. trust me.)\n\n"; + print " -s\t\tDon't display statistics at the end\n\n"; + 1; +} + +while($#ARGV >= 0) { + $_ = shift; + $configfile = shift if (/-c/); + $debug = 1 if (/-d/); + $nostats = 1 if (/-s/); + usage && exit(1) if (/-h/); + $outputName = shift if (/-f/); + $oid = $_ if (/^[^-]/); +} + +read_config($configfile); +# +# internal conversion tables +# + +%accessToUCD = qw(ReadOnly RONLY ReadWrite RWRITE + WriteOnly RWRITE Create RWRITE); + +# The lengths of the defined 'variableN' structures +@varLengths = (2,4,7,8,13); + +if (!defined($oid)) { + print STDERR "You didn\'t specify a mib oid to convert!\n"; + usage(); + exit(1); +} + +$mib = $SNMP::MIB{$oid}; +$_ = $commaoid = $fulloid = $mib->{'objectID'}; +if (!defined ($fulloid)) { + print STDERR "Couldn\'t find mib reference: $oid\n"; + exit(1); +} +s/[^.]//g; +$commaoid =~ s/\./,/g; +$commaoid =~ s/^,//g; + +$outputName = $mib->{'label'} if (!defined($outputName)); +$OUTPUTNAME = uc($outputName); +$vroutine="$outputName"; +print "outputting to $outputName.c and $outputName.h ...\n"; + +#============================================ +# +# Walk the MIB tree, and construct strings +# holding the various fragments of code needed. +# +# 'loadMib' returns the length of the longest OID suffix +# encountered. +# +# The variables constructed and used are: +# +# (in the header file) +# functionInfo : A list of definitions for the table-handling functions, +# and routines for SETtable variables. +# (The main scalar handling routine is handled implicitly) +# +# (in the code file) +# structinfo : The contents of the variableN structure listing +# the variables handled, including type, access level, +# OID suffix and 'magic number' +# +# caseStatements: A hash array (indexed by variable routine name) +# containing the body of the switch statement +# used for returning the appropriate values. +# At a minimum, this consists of the various 'case' labels +# If full type information is available (from mib2c.conf) +# then this will also include a default initialiser, +# and setting of a 'write_method' (if appropriate). +# +# writeFuncs: A list of function skeletons for setting variables +# (for variables with suitable access levels). +# Note that this list will not include functions +# for variables which don't provide type information +# in the mib2c.conf file (even if such variables are +# defined as writeable in the variableN structure). +# +#============================================ +$count = 0; +$depth = loadMib($mib,0)-1; + +# Determine which 'variableN' structure is needed +for($varlen = 0; $varlen <= $#varLengths; $varlen++) { + last if ($depth <= $varLengths[$varlen]); +} +$varlen = $varLengths[$varlen]; + +#============================================ +# +# Table-handling routines. +# +#============================================ +foreach $vtable (@table_list) { + foreach $ptable (@processtable) { + $variables{$ptable}{'processed'} = + (eval "\"$variables{$ptable}{'code'}\"") . "\n\n"; + } + $var_routines .= + (eval "\"$variables{'code-var_table'}{'code'}\"") . "\n\n"; +} + +#============================================ +# +# Output the header file +# +#============================================ +open(DOTH,">$outputName.h"); +print DOTH (eval "\"$variables{'code-dot-h'}{'code'}\"") . "\n"; +close(DOTH); + +#============================================ +# +# Output the code file: +# Initialisation and main variable routine. +# +#============================================ + +open(DOTC,">$outputName.c"); +print DOTC (eval "\"$variables{'code-main-part'}{'code'}\"") . "\n\n";; +close(DOTC); + +#============================================ +# +# Everyone loves statistics. +# +#============================================ +print " depth: $depth\n"; +print " Number of Lines Created:\n"; +system("wc -l $outputName.c $outputName.h"); +print "Done.\n"; + +#============================================ +# +# loadMib: +# Recursive routine to walk the mib, +# and construct the various code fragment strings. +# +#============================================ +sub loadMib { + my $mib = shift; + my $i; + my $depth = shift; + $depth = $depth + 1; + my $name = $mib->{'label'}; + my $NAME = uc($name); + print "doing $mib->{label} : $mib->{objectID}\n" if $debug; + if (defined($mib->{'access'}) && + $mib->{'access'} =~ /ReadOnly|ReadWrite|WriteOnly|Create|NoAccess/) { + $count = $count + 1; + $subid = $mib->{'objectID'}; + $subid =~ s/$fulloid\.//; + $subid =~ s/\./,/g; + if (!defined($variables{$mib->{'type'}}) && !defined($mib->{'indexes'})) { + print STDERR "unknown type: $mib->{type} for $mib->{label} $mib->{'access'}\n"; + print STDERR "unknown type: no information generated for $mib->{label}\n"; + } else { + foreach $i (@process) { + next if (defined($variables{$i}{'skipif'}) && + eval $variables{$i}{'skipif'}); + my $result = (eval "\"$variables{$i}{'code'}\""); + $variables{$i}{'processed'} .= "$result\n"; + $variables{$vroutine}{$i}{'processed'} .= "$result\n"; + } + } + if (defined($mib->{'indexes'})) { + print "indexes: ", join(", ",@{$mib->{'indexes'}}),"\n" if ($debug); + $variables{$vroutine}{'indexes'} = $mib->{'indexes'}; + foreach $i (@{$mib->{'indexes'}}) { + $variables{$vroutine}{$i}{'isanindex'} = 1; + } + } + } + my $children = $$mib{'children'}; + my $i; + my $newdepth = $depth; + foreach $i (@{$children}) { + if ( $name =~ /Table$/ ) { + $vroutine="$name"; + push @table_list, $name; + $newdepth = max(loadMib($i, $depth), $newdepth); + $vroutine="$outputName"; + } + else { + $newdepth = max(loadMib($i, $depth), $newdepth); + } + } + return $newdepth; +} + +sub max { + my $x = shift; + my $y = shift; + return ($x > $y) ? $x : $y; +} + + +sub read_config() { + my $configfile = shift; + my ($type, $lasttoken); + my $fh = new FileHandle; + if ( $fh->open("<$configfile") ) { + while(<$fh>) { + next if (/^\s*\#/ || /^\s*$/); + if (/^\s*type:\s*(.*)/) { + if (defined($type) && defined($lasttoken) && + defined ($variables{$type}{$lasttoken})) { + chomp($variables{$type}{$lasttoken}); + } + $type = $1; + chomp($type); + } elsif (/include:\s*(.*)/) { + read_config($1); + } elsif (/process:\s*(.*)/) { + push (@process, $1); + } elsif (/processtable:\s*(.*)/) { + push (@processtable, $1); + } elsif (/delete:\s*(.*)/) { + delete($variables{$type}{$1}); + } elsif (/copy:\s*(.*)/) { + my $item; + chomp($1); + foreach $item (keys(%{$variables{$1}})) { + $variables{$type}{$item} = $variables{$1}{$item}; + } + } else { + if (/\s*([^:]*):(\s*.*)/) { + if (!defined($variables{$type}{$1})) { + if (defined($type) && defined($lasttoken) && + defined ($variables{$type}{$lasttoken})) { + chomp($variables{$type}{$lasttoken}); + } + $variables{$type}{$1} = $2; + $lasttoken = $1; + $variables{$type}{$1} =~ s/^\t+//; + } else { + # duplicate entry: tack it on. + my ($x, $y) = ($1, $2); + $y =~ s/^\t+//; + $variables{$type}{$x} .= "\n" . $y; + } + } else { + # continuation line, it started with spaces or a + + s/^\s*//; + s/^\+//; + $variables{$type}{$lasttoken} .= "\n" . $_; + chomp($variables{$type}{$lasttoken}); + } + } + } + $fh->close(); + } else { + warn "Config file ($configfile) not found.\n"; + } +} + +sub evalstr { + my $str = shift; +# if ($str !~ /^\"/) { + $str = "\"$str\""; # surround by quotes. +# } + eval ($str); # should return a string, with variables expanded +} + +sub evalrstr { + my $rstr = shift; +# if ($str !~ /^\"/) { +# $$rstr = "\"" . $$rstr . "\""; # surround by quotes. +# } + eval ("\"$$rstr\""); # should return a string, with variables expanded +} diff --git a/packages/net/snmp/agent/current/utils/mib2c/mib2c.conf b/packages/net/snmp/agent/current/utils/mib2c/mib2c.conf new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/utils/mib2c/mib2c.conf @@ -0,0 +1,451 @@ +# +# Define types of data by mib type, and translate into needed C code. +# + +############################################################################ +# source variable typing information: +include: mib2c.vartypes.conf + +# Begin code template section +############################################################################ +# variable statemnts used in a couple of places below +############################################################################ +type: code-varInits +code: /* variables we may use later */ +code: static long long_ret; +code: static unsigned char string[SPRINT_MAX_LEN]; +code: static oid objid[MAX_OID_LEN]; +code: static struct counter64 c64; + + +############################################################################ +# The .h file +############################################################################ +type: code-dot-h +code: //========================================================================== +code: // +code: // snmp/snmpagent/current/include/mibgroup/mibII/$outputName.h +code: // +code: // +code: //========================================================================== +code: //####COPYRIGHTBEGIN#### +code: // +code: // ------------------------------------------- +code: // The contents of this file are subject to the Red Hat eCos Public License +code: // Version 1.1 (the \"License\"); you may not use this file except in +code: // compliance with the License. You may obtain a copy of the License at +code: // http://www.redhat.com/ +code: // +code: // Software distributed under the License is distributed on an \"AS IS\" +code: // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +code: // License for the specific language governing rights and limitations under +code: // the License. +code: // +code: // The Original Code is eCos - Embedded Configurable Operating System, +code: // released September 30, 1998. +code: // +code: // The Initial Developer of the Original Code is Red Hat. +code: // Portions created by Red Hat are +code: // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +code: // All Rights Reserved. +code: // ------------------------------------------- +code: // +code: //####COPYRIGHTEND#### +code: //####UCDSNMPCOPYRIGHTBEGIN#### +code: // +code: // ------------------------------------------- +code: // +code: // Portions of this software may have been derived from the UCD-SNMP +code: // project, from the University of +code: // California at Davis, which was originally based on the Carnegie Mellon +code: // University SNMP implementation. Portions of this software are therefore +code: // covered by the appropriate copyright disclaimers included herein. +code: // +code: // The release used was version 4.1.2 of May 2000. \"ucd-snmp-4.1.2\" +code: // ------------------------------------------- +code: // +code: //####UCDSNMPCOPYRIGHTEND#### +code: //========================================================================== +code: //#####DESCRIPTIONBEGIN#### +code: // +code: // Author(s): hmt +code: // Contributors: hmt +code: // Date: 2000-05-30 +code: // Purpose: Port of UCD-SNMP distribution to eCos. +code: // Description: +code: // +code: // +code: //####DESCRIPTIONEND#### +code: // +code: //========================================================================== +code: /******************************************************************** +code: Copyright 1989, 1991, 1992 by Carnegie Mellon University +code: \ +code: Derivative Work - +code: Copyright 1996, 1998, 1999, 2000 The Regents of the University of California +code: \ +code: All Rights Reserved +code: \ +code: Permission to use, copy, modify and distribute this software and its +code: documentation for any purpose and without fee is hereby granted, +code: provided that the above copyright notice appears in all copies and +code: that both that copyright notice and this permission notice appear in +code: supporting documentation, and that the name of CMU and The Regents of +code: the University of California not be used in advertising or publicity +code: pertaining to distribution of the software without specific written +code: permission. +code: \ +code: CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +code: WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +code: WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +code: THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +code: INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +code: FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +code: CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +code: CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +code: *********************************************************************/ +code: /* This file was generated by mib2c and is intended for use as a mib module +code: for the ucd-snmp snmpd agent. */ +code: +code: #ifndef _MIBGROUP_${OUTPUTNAME}_H +code: #define _MIBGROUP_${OUTPUTNAME}_H +code: +code: /* we may use header_generic and header_simple_table from the util_funcs module */ +code: +code: config_require(util_funcs) +code: +code: /* function prototypes */ +code: +code: void init_$outputName(void); +code: FindVarMethod var_$outputName; +code: $variables{'code-var_table-decl'}{'processed'} +code: $variables{'code-write-func-decl'}{'processed'} +code: +code: #endif /* _MIBGROUP_${OUTPUTNAME}_H */ + +############################################################################ +# The .c file, top +############################################################################ +type: code-main-part +code: //========================================================================== +code: // +code: // snmp/snmpagent/current/src/mibgroup/mibII/$outputName.c +code: // +code: // +code: //========================================================================== +code: //####COPYRIGHTBEGIN#### +code: // +code: // ------------------------------------------- +code: // The contents of this file are subject to the Red Hat eCos Public License +code: // Version 1.1 (the \"License\"); you may not use this file except in +code: // compliance with the License. You may obtain a copy of the License at +code: // http://www.redhat.com/ +code: // +code: // Software distributed under the License is distributed on an \"AS IS\" +code: // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +code: // License for the specific language governing rights and limitations under +code: // the License. +code: // +code: // The Original Code is eCos - Embedded Configurable Operating System, +code: // released September 30, 1998. +code: // +code: // The Initial Developer of the Original Code is Red Hat. +code: // Portions created by Red Hat are +code: // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +code: // All Rights Reserved. +code: // ------------------------------------------- +code: // +code: //####COPYRIGHTEND#### +code: //####UCDSNMPCOPYRIGHTBEGIN#### +code: // +code: // ------------------------------------------- +code: // +code: // Portions of this software may have been derived from the UCD-SNMP +code: // project, from the University of +code: // California at Davis, which was originally based on the Carnegie Mellon +code: // University SNMP implementation. Portions of this software are therefore +code: // covered by the appropriate copyright disclaimers included herein. +code: // +code: // The release used was version 4.1.2 of May 2000. \"ucd-snmp-4.1.2\" +code: // ------------------------------------------- +code: // +code: //####UCDSNMPCOPYRIGHTEND#### +code: //========================================================================== +code: //#####DESCRIPTIONBEGIN#### +code: // +code: // Author(s): hmt +code: // Contributors: hmt +code: // Date: 2000-05-30 +code: // Purpose: Port of UCD-SNMP distribution to eCos. +code: // Description: +code: // +code: // +code: //####DESCRIPTIONEND#### +code: // +code: //========================================================================== +code: /******************************************************************** +code: Copyright 1989, 1991, 1992 by Carnegie Mellon University +code: \ +code: Derivative Work - +code: Copyright 1996, 1998, 1999, 2000 The Regents of the University of California +code: \ +code: All Rights Reserved +code: \ +code: Permission to use, copy, modify and distribute this software and its +code: documentation for any purpose and without fee is hereby granted, +code: provided that the above copyright notice appears in all copies and +code: that both that copyright notice and this permission notice appear in +code: supporting documentation, and that the name of CMU and The Regents of +code: the University of California not be used in advertising or publicity +code: pertaining to distribution of the software without specific written +code: permission. +code: \ +code: CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +code: WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +code: WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +code: THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +code: INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +code: FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +code: CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +code: CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +code: *********************************************************************/ +code: /* This file was generated by mib2c and is intended for use as a mib module +code: for the ucd-snmp snmpd agent. */ +code: +code: /* This should always be included first before anything else */ +code: #include +code: +code: /* minimal include directives */ +code: #include \"mibincl.h\" +code: #include \"mibgroup/util_funcs.h\" +code: #include \"mibgroup/mibII/$outputName.h\" +code: +code: /* +code: * ${outputName}_variables_oid: +code: * this is the top level oid that we want to register under. This +code: * is essentially a prefix, with the suffix appearing in the +code: * variable below. +code: */ +code: +code: oid ${outputName}_variables_oid[] = { $commaoid }; +code: +code: /* +code: * variable$varlen ${outputName}_variables: +code: * this variable defines function callbacks and type return information +code: * for the $outputName mib section +code: */ +code: +code: struct variable$varlen ${outputName}_variables[] = { +code: /* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +code: $variables{'variable-structure-info'}{'processed'} +code: }; +code: /* (L = length of the oidsuffix) */ +code: +code: /* +code: * init_$outputName(): +code: * Initialization routine. This is called when the agent starts up. +code: * At a minimum, registration of your variables should take place here. +code: */ +code: void init_$outputName(void) { +code: +code: /* register ourselves with the agent to handle our mib tree */ +code: REGISTER_MIB(\"$outputName\", ${outputName}_variables, variable$varlen,\ +code: ${outputName}_variables_oid); +code: +code: /* place any other initialization junk you need here */ +code: } +code: +code: /* +code: * var_$outputName(): +code: * This function is called every time the agent gets a request for +code: * a scalar variable that might be found within your mib section +code: * registered above. It is up to you to do the right thing and +code: * return the correct value. +code: * You should also correct the value of \"var_len\" if necessary. +code: * +code: * Please see the documentation for more information about writing +code: * module extensions, and check out the examples in the examples +code: * and mibII directories. +code: */ +code: unsigned char * +code: var_$outputName(struct variable *vp, +code: oid *name, +code: size_t *length, +code: int exact, +code: size_t *var_len, +code: WriteMethod **write_method) +code: { +code: +code: $variables{'code-varInits'}{'code'} +code: +code: if (header_generic(vp,name,length,exact,var_len,write_method) +code: == MATCH_FAILED ) +code: return NULL; +code: +code: /* +code: * this is where we do the value assignments for the mib results. +code: */ +code: switch(vp->magic) {\n\n +code: $variables{$outputName}{'code-case-statements'}{'processed'} +code: default: +code: ERROR_MSG(\"\"); +code: } +code: return NULL; +code: } +code: +code: $variables{'code-var_table'}{'processed'} +code: +code: $variables{'code-write-func'}{'processed'} + +############################################################################ +# var_ function for tables, which is handled specially and used above +# +# Note: $vtable is set to the table name in the processtable loop. +############################################################################ + +# +# header file defs first +# +type: code-var_table-decl +processtable: code-var_table-decl + +code: FindVarMethod var_$vtable; + +# +# Code code per table +# +type: code-var_table +processtable: code-var_table + +code: /* +code: * var_$vtable(): +code: * Handle this table separately from the scalar value case. +code: * The workings of this are basically the same as for var_$outputName above. +code: */ +code: unsigned char * +code: var_$vtable(struct variable *vp, +code: oid *name, +code: size_t *length, +code: int exact, +code: size_t *var_len, +code: WriteMethod **write_method) +code: { +code: +code: $variables{'code-varInits'}{'code'} +code: +code: /* +code: * This assumes that the table is a \'simple\' table. +code: * See the implementation documentation for the meaning of this. +code: * You will need to provide the correct value for the TABLE_SIZE parameter +code: * +code: * If this table does not meet the requirements for a simple table, +code: * you will need to provide the replacement code yourself. +code: * Mib2c is not smart enough to write this for you. +code: * Again, see the implementation documentation for what is required. +code: */ +code: if (header_simple_table(vp,name,length,exact,var_len,write_method, TABLE_SIZE) +code: == MATCH_FAILED ) +code: return NULL; +code: +code: /* +code: * this is where we do the value assignments for the mib results. +code: */ +code: switch(vp->magic) {\n\n +code: $variables{$vtable}{'code-case-statements'}{'processed'} +code: default: +code: ERROR_MSG(\"\"); +code: } +code: return NULL; +code: } + + +############################################################################ +# case statement sections +############################################################################ +type: code-case-statements +process: code-case-statements +skipif: $mib->{'access'} =~ /NoAccess/ + +code: case $NAME: +code: " . (($mib->{'access'} =~ /ReadWrite|WriteOnly|Create/) ? "*write_method = write_$mib->{label};" : "") . " +code: $variables{$mib->{'type'}}{'case'} +code: + +############################################################################ +# storage structure information +############################################################################ +type: variable-structure-info +process: variable-structure-info +skipif: $mib->{'access'} =~ /NoAccess/ +code: " . sprintf("#define %-20s $count", $NAME) . " +code: " . sprintf(" { %-20s, %-14s, %-6.6s, %s, %d, { %s } },", $NAME, $variables{$mib->{'type'}}{'asnType'}, $accessToUCD{$mib->{'access'}}, "var_$vroutine", $depth-1, $subid) . " + +############################################################################ +# write function defitition, also appended to the end of the .c file. +############################################################################ +# +# Header info: declair write functions for set processing +# +process: code-write-func-decl +type: code-write-func-decl +skipif: $mib->{'access'} !~ /Write|Create/ +code: WriteMethod write_$name; +# +# C code +# +type: code-write-func +process: code-write-func +skipif: $mib->{'access'} !~ /Write|Create/ +code: int +code: write_$name(int action, +code: u_char *var_val, +code: u_char var_val_type, +code: size_t var_val_len, +code: u_char *statP, +code: oid *name, +code: size_t name_len) +code: { +code: $variables{$mib->{'type'}}{writeInit} +code: int size; +code: +code: switch ( action ) { +code: case RESERVE1: +code: if (var_val_type != $variables{$mib->{'type'}}{asnType}){ +code: fprintf(stderr, \"write to $name not $variables{$mib->{'type'}}{asnType}\\n\"); +code: return SNMP_ERR_WRONGTYPE; +code: } +code: if (var_val_len > sizeof($variables{$mib->{'type'}}{variable})){ +code: fprintf(stderr,\"write to $name: bad length\\n\"); +code: return SNMP_ERR_WRONGLENGTH; +code: } +code: break; +code: +code: case RESERVE2: +code: size = var_val_len; +code: $variables{$mib->{'type'}}{variable} = ($variables{$mib->{'type'}}{cast}) var_val; +code: +code: break; +code: +code: case FREE: +code: /* Release any resources that have been allocated */ +code: break; +code: +code: case ACTION: +code: /* The variable has been stored in $variables{$mib->{'type'}}{variable} for +code: you to use, and you have just been asked to do something with +code: it. Note that anything done here must be reversable in the UNDO case */ +code: break; +code: +code: case UNDO: +code: /* Back out any changes made in the ACTION case */ +code: break; +code: +code: case COMMIT: +code: /* Things are working well, so it's now safe to make the change +code: permanently. Make sure that anything done here can't fail! */ +code: break; +code: } +code: return SNMP_ERR_NOERROR; +code: } +code: +code: diff --git a/packages/net/snmp/agent/current/utils/mib2c/mib2c.conf-ORIG b/packages/net/snmp/agent/current/utils/mib2c/mib2c.conf-ORIG new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/utils/mib2c/mib2c.conf-ORIG @@ -0,0 +1,299 @@ +# +# Define types of data by mib type, and translate into needed C code. +# + +############################################################################ +# source variable typing information: +include: mib2c.vartypes.conf + +# Begin code template section +############################################################################ +# variable statemnts used in a couple of places below +############################################################################ +type: code-varInits +code: /* variables we may use later */ +code: static long long_ret; +code: static unsigned char string[SPRINT_MAX_LEN]; +code: static oid objid[MAX_OID_LEN]; +code: static struct counter64 c64; + + +############################################################################ +# The .h file +############################################################################ +type: code-dot-h +code: /* This file was generated by mib2c and is intended for use as a mib module +code: for the ucd-snmp snmpd agent. */ +code: +code: #ifndef _MIBGROUP_${OUTPUTNAME}_H +code: #define _MIBGROUP_${OUTPUTNAME}_H +code: +code: /* we may use header_generic and header_simple_table from the util_funcs module */ +code: +code: config_require(util_funcs) +code: +code: /* function prototypes */ +code: +code: void init_$outputName(void); +code: FindVarMethod var_$outputName; +code: $variables{'code-var_table-decl'}{'processed'} +code: $variables{'code-write-func-decl'}{'processed'} +code: +code: #endif /* _MIBGROUP_${OUTPUTNAME}_H */ + +############################################################################ +# The .c file, top +############################################################################ +type: code-main-part +code: /* This file was generated by mib2c and is intended for use as a mib module +code: for the ucd-snmp snmpd agent. */ +code: +code: #ifdef IN_UCD_SNMP_SOURCE +code: /* If we're compiling this file inside the ucd-snmp source tree */ +code: +code: /* This should always be included first before anything else */ +code: #include +code: +code: /* minimal include directives */ +code: #include \"mibincl.h\" +code: #include \"util_funcs.h\" +code: +code: #else /* !IN_UCD_SNMP_SOURCE */ +code: +code: #include +code: #include +code: #include +code: +code: #endif /* !IN_UCD_SNMP_SOURCE */ +code: +code: #include \"$outputName.h\" +code: +code: /* +code: * ${outputName}_variables_oid: +code: * this is the top level oid that we want to register under. This +code: * is essentially a prefix, with the suffix appearing in the +code: * variable below. +code: */ +code: +code: oid ${outputName}_variables_oid[] = { $commaoid }; +code: +code: /* +code: * variable$varlen ${outputName}_variables: +code: * this variable defines function callbacks and type return information +code: * for the $outputName mib section +code: */ +code: +code: struct variable$varlen ${outputName}_variables[] = { +code: /* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +code: $variables{'variable-structure-info'}{'processed'} +code: }; +code: /* (L = length of the oidsuffix) */ +code: +code: /* +code: * init_$outputName(): +code: * Initialization routine. This is called when the agent starts up. +code: * At a minimum, registration of your variables should take place here. +code: */ +code: void init_$outputName(void) { +code: +code: /* register ourselves with the agent to handle our mib tree */ +code: REGISTER_MIB(\"$outputName\", ${outputName}_variables, variable$varlen,\ +code: ${outputName}_variables_oid); +code: +code: /* place any other initialization junk you need here */ +code: } +code: +code: /* +code: * var_$outputName(): +code: * This function is called every time the agent gets a request for +code: * a scalar variable that might be found within your mib section +code: * registered above. It is up to you to do the right thing and +code: * return the correct value. +code: * You should also correct the value of \"var_len\" if necessary. +code: * +code: * Please see the documentation for more information about writing +code: * module extensions, and check out the examples in the examples +code: * and mibII directories. +code: */ +code: unsigned char * +code: var_$outputName(struct variable *vp, +code: oid *name, +code: size_t *length, +code: int exact, +code: size_t *var_len, +code: WriteMethod **write_method) +code: { +code: +code: $variables{'code-varInits'}{'code'} +code: +code: if (header_generic(vp,name,length,exact,var_len,write_method) +code: == MATCH_FAILED ) +code: return NULL; +code: +code: /* +code: * this is where we do the value assignments for the mib results. +code: */ +code: switch(vp->magic) {\n\n +code: $variables{$outputName}{'code-case-statements'}{'processed'} +code: default: +code: ERROR_MSG(\"\"); +code: } +code: return NULL; +code: } +code: +code: $variables{'code-var_table'}{'processed'} +code: +code: $variables{'code-write-func'}{'processed'} + +############################################################################ +# var_ function for tables, which is handled specially and used above +# +# Note: $vtable is set to the table name in the processtable loop. +############################################################################ + +# +# header file defs first +# +type: code-var_table-decl +processtable: code-var_table-decl + +code: FindVarMethod var_$vtable; + +# +# Code code per table +# +type: code-var_table +processtable: code-var_table + +code: /* +code: * var_$vtable(): +code: * Handle this table separately from the scalar value case. +code: * The workings of this are basically the same as for var_$outputName above. +code: */ +code: unsigned char * +code: var_$vtable(struct variable *vp, +code: oid *name, +code: size_t *length, +code: int exact, +code: size_t *var_len, +code: WriteMethod **write_method) +code: { +code: +code: $variables{'code-varInits'}{'code'} +code: +code: /* +code: * This assumes that the table is a \'simple\' table. +code: * See the implementation documentation for the meaning of this. +code: * You will need to provide the correct value for the TABLE_SIZE parameter +code: * +code: * If this table does not meet the requirements for a simple table, +code: * you will need to provide the replacement code yourself. +code: * Mib2c is not smart enough to write this for you. +code: * Again, see the implementation documentation for what is required. +code: */ +code: if (header_simple_table(vp,name,length,exact,var_len,write_method, TABLE_SIZE) +code: == MATCH_FAILED ) +code: return NULL; +code: +code: /* +code: * this is where we do the value assignments for the mib results. +code: */ +code: switch(vp->magic) {\n\n +code: $variables{$vtable}{'code-case-statements'}{'processed'} +code: default: +code: ERROR_MSG(\"\"); +code: } +code: return NULL; +code: } + + +############################################################################ +# case statement sections +############################################################################ +type: code-case-statements +process: code-case-statements +skipif: $mib->{'access'} =~ /NoAccess/ + +code: case $NAME: +code: " . (($mib->{'access'} =~ /ReadWrite|WriteOnly|Create/) ? "*write_method = write_$mib->{label};" : "") . " +code: $variables{$mib->{'type'}}{'case'} +code: + +############################################################################ +# storage structure information +############################################################################ +type: variable-structure-info +process: variable-structure-info +skipif: $mib->{'access'} =~ /NoAccess/ +code: " . sprintf("#define %-20s $count", $NAME) . " +code: " . sprintf(" { %-20s, %-14s, %-6.6s, %s, %d, { %s } },", $NAME, $variables{$mib->{'type'}}{'asnType'}, $accessToUCD{$mib->{'access'}}, "var_$vroutine", $depth-1, $subid) . " + +############################################################################ +# write function defitition, also appended to the end of the .c file. +############################################################################ +# +# Header info: declair write functions for set processing +# +process: code-write-func-decl +type: code-write-func-decl +skipif: $mib->{'access'} !~ /Write|Create/ +code: WriteMethod write_$name; +# +# C code +# +type: code-write-func +process: code-write-func +skipif: $mib->{'access'} !~ /Write|Create/ +code: int +code: write_$name(int action, +code: u_char *var_val, +code: u_char var_val_type, +code: size_t var_val_len, +code: u_char *statP, +code: oid *name, +code: size_t name_len) +code: { +code: $variables{$mib->{'type'}}{writeInit} +code: int size; +code: +code: switch ( action ) { +code: case RESERVE1: +code: if (var_val_type != $variables{$mib->{'type'}}{asnType}){ +code: fprintf(stderr, \"write to $name not $variables{$mib->{'type'}}{asnType}\\n\"); +code: return SNMP_ERR_WRONGTYPE; +code: } +code: if (var_val_len > sizeof($variables{$mib->{'type'}}{variable})){ +code: fprintf(stderr,\"write to $name: bad length\\n\"); +code: return SNMP_ERR_WRONGLENGTH; +code: } +code: break; +code: +code: case RESERVE2: +code: size = var_val_len; +code: $variables{$mib->{'type'}}{variable} = ($variables{$mib->{'type'}}{cast}) var_val; +code: +code: break; +code: +code: case FREE: +code: /* Release any resources that have been allocated */ +code: break; +code: +code: case ACTION: +code: /* The variable has been stored in $variables{$mib->{'type'}}{variable} for +code: you to use, and you have just been asked to do something with +code: it. Note that anything done here must be reversable in the UNDO case */ +code: break; +code: +code: case UNDO: +code: /* Back out any changes made in the ACTION case */ +code: break; +code: +code: case COMMIT: +code: /* Things are working well, so it's now safe to make the change +code: permanently. Make sure that anything done here can't fail! */ +code: break; +code: } +code: return SNMP_ERR_NOERROR; +code: } +code: +code: diff --git a/packages/net/snmp/agent/current/utils/mib2c/mib2c.storage.conf b/packages/net/snmp/agent/current/utils/mib2c/mib2c.storage.conf new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/utils/mib2c/mib2c.storage.conf @@ -0,0 +1,681 @@ +# mib2c.storage.conf: +# +# This is a special mib2c.conf file that assumes that you want to do +# all storage of information locally rather than pulling the +# information from another source outside the agent (EG, the +# kernel). To accomplish this, it defines a structure for the +# storage of tables and assumes you want to use the header_complex +# functions for retrieving and storing that data in a local data +# store. It even writes a .conf file parser for you and sets you up +# for being able to do persistant storage fairly simply. +# +# In short: it trys to do almost all of the work for you... Almost... + +# +# Define types of data by mib type, and translate into needed C code. +# + +# We need to get some extra stuff into the variable declarations +# before sourcing the main mib2c.vartypes.conf file below. +type: OCTETSTR +storage: char *${name}; +storage: size_t ${name}Len; +varlenname: StorageTmp->${name}Len +vartest: if (StorageTmp->${name} == NULL) { +vartest: config_perror(\"invalid specification for ${name}\"); +vartest: return; +vartest: } +vartest: +action: tmpvar = StorageTmp->$name; +action: tmplen = StorageTmp->${name}Len; +action: memdup((u_char **) &StorageTmp->$name, var_val, var_val_len); +action: StorageTmp->${name}Len = var_val_len; +undo: SNMP_FREE(StorageTmp->${name}); +undo: StorageTmp->${name} = tmpvar; +undo: StorageTmp->${name}Len = tmplen; +commit: SNMP_FREE(tmpvar); +sizeofstart: +sizeofend: Len +tmpvar: char * +casttmp: strdup((char *) tmpvar); +# +type: INTEGER +storage: long $name; +storageret: & +varlenname: tmpint +sizeofstart: sizeof( +sizeofend: ) +tmpvar: int +action: tmpvar = StorageTmp->$name; +action: StorageTmp->${name} = *((long *) var_val); +undo: StorageTmp->${name} = tmpvar; +casttmp: tmpvar; +# +type: OBJECTID +storage: oid *$name; +storage: size_t ${name}Len +varlenname: StorageTmp->${name}Len +vartest: if (StorageTmp->${name} == NULL) { +vartest: config_perror(\"invalid specification for ${name}\"); +vartest: return; +vartest: } +vartest: +action: tmpvar = StorageTmp->$name; +action: tmplen = StorageTmp->${name}Len; +action: memdup((u_char **) &StorageTmp->$name, var_val, var_val_len); +action: StorageTmp->${name}Len = var_val_len/sizeof(oid); +undo: SNMP_FREE(StorageTmp->${name}); +undo: StorageTmp->${name} = tmpvar; +undo: StorageTmp->${name}Len = tmplen; +commit: SNMP_FREE(tmpvar); +sizeofstart: +sizeofend: Len +tmpvar: oid * +casttmp: (oid *) tmpvar; +freetmp: SNMP_FREE(tmpvar); +# +type: COUNTER64 +storage: struct counter64 $name; +varlenname: tmpint +sizeofstart: sizeof( +sizeofend: ) +tmpvar: struct counter64 * +casttmp: (struct counter64 *) tmpvar; + +############################################################################ +# source variable typing information: +include: mib2c.vartypes.conf + +############################################################################ +# The .h file +############################################################################ +type: code-dot-h +code: /* This file was generated by mib2c and is intended for use as a mib module +code: for the ucd-snmp snmpd agent. */ +code: +code: #ifndef _MIBGROUP_${OUTPUTNAME}_H +code: #define _MIBGROUP_${OUTPUTNAME}_H +code: +code: /* we may use header_complex from the header_complex module */ +code: +code: config_require(header_complex) +code: +code: /* our storage structure(s) */ +code: $variables{'code-structure-per-table'}{'processed'} +code: +code: /* enum definitions from the covered mib sections */ +code: +code: $variables{'code-enums'}{'processed'} +code: +code: /* function prototypes */ +code: +code: void init_$outputName(void); +code: $variables{'code-var-table-decl'}{'processed'} +code: $variables{'code-write-func-decl'}{'processed'} +code: $variables{'code-write-rowstatus-decl'}{'processed'} +code: +code: #endif /* _MIBGROUP_${OUTPUTNAME}_H */ + +# +# Structure definition, one per table +# +type: code-structure-per-table +processtable: code-structure-per-table + +code: struct ${vtable}_data { +code: $variables{$vtable}{'code-structure'}{'processed'} +code: }; + +# +# Structure storage arrays, one per table +# +type: code-structure-storage +processtable: code-structure-storage + +code: static struct header_complex_index *${vtable}Storage = NULL; + +# +# Structure definition line. +# +type: code-structure +process: code-structure + +code: " . eval ("\"$variables{$mib->{'type'}}{'storage'}\"") . " +#$variables{$i}{'code'}\""evalstr( +# +# ENUM definitions +# +type: code-enums +process: code-enums +skipif: $mib->{'textualConvention'} eq "RowStatus" || $mib->{'textualConvention'} eq "StorageType" + +code: " . eval{ my ($i, $x); foreach $i (sort {$mib->{'enums'}{$a} <=> $mib->{'enums'}{$b}} keys(%{$mib->{'enums'}})) { $x .= sprintf("#define %-40s %d\n","${NAME}_" . uc($i),$mib->{'enums'}{$i}); } $x; } . " + +############################################################################ +# The .c file, top +############################################################################ +type: code-main-part +code: /* This file was generated by mib2c and is intended for use as +code: a mib module for the ucd-snmp snmpd agent. */ +code: +code: /* This should always be included first before anything else */ +code: #include +code: #if HAVE_STDLIB_H +code: #include +code: #endif +code: #if HAVE_STRING_H +code: #include +code: #else +code: #include +code: #endif +code: +code: /* minimal include directives */ +code: #include \"mibincl.h\" +code: #include \"header_complex.h\" +code: #include \"$outputName.h\" +code: #include \"snmp-tc.h\" +code: +code: /* +code: * ${outputName}_variables_oid: +code: * this is the top level oid that we want to register under. This +code: * is essentially a prefix, with the suffix appearing in the +code: * variable below. +code: */ +code: +code: oid ${outputName}_variables_oid[] = { $commaoid }; +code: +code: /* +code: * variable$varlen ${outputName}_variables: +code: * this variable defines function callbacks and type return information +code: * for the $outputName mib section +code: */ +code: +code: struct variable$varlen ${outputName}_variables[] = { +code: /* magic number , variable type , ro/rw , callback fn , L, oidsuffix */ +code: $variables{'variable-structure-info'}{'processed'} +code: }; +code: /* (L = length of the oidsuffix) */ +code: +code: /* global storage of our data, saved in and configured by header_complex() */ +code: $variables{'code-structure-storage'}{'processed'} +code: +code: /* +code: * init_$outputName(): +code: * Initialization routine. This is called when the agent starts up. +code: * At a minimum, registration of your variables should take place here. +code: */ +code: void init_$outputName(void) { +code: DEBUGMSGTL((\"$outputName\", \"initializing... \")); +code: +code: /* register ourselves with the agent to handle our mib tree */ +code: REGISTER_MIB(\"$outputName\", ${outputName}_variables, variable$varlen,\ +code: ${outputName}_variables_oid); +code: +code: /* register our config handler(s) to deal with registrations */ +code: $variables{'code-parser-registration'}{'processed'} +code: +code: /* place any other initialization junk you need here */ +code: +code: DEBUGMSGTL((\"$outputName\", \"done.\\n\")); +code: } +code: +code: $variables{'code-parser'}{'processed'} +code: +code: $variables{'code-var_table'}{'processed'} +code: +code: $variables{'code-write-func'}{'processed'} +code: +code: $variables{'code-write-rowstatus'}{'processed'} + +############################################################################ +# var_ function for tables, which is handled specially and used above +# +# Note: $vtable is set to the table name in the processtable loop. +############################################################################ + +# +# header file defs first +# +type: code-var-table-decl +processtable: code-var-table-decl + +code: FindVarMethod var_$vtable; +code: void parse_$vtable(char *, char *); + +# +# .conf Parser Code per table +# +type: code-parser-registration +processtable: code-parser-registration +code: snmpd_register_config_handler(\"$vtable\", parse_$vtable, NULL, +code: \"HELP STRING\"); + +type: code-varlist-add +process: code-varlist-add +skipif: $variables{$vroutine}{$name}{'isanindex'} != 1 +code: snmp_varlist_add_variable(&vars, NULL, 0, $variables{$mib->{type}}{asnType}, ($variables{$mib->{type}}{'cast'}) thedata->$name, $variables{$mib->{type}}{'sizeofstart'}thedata->$name$variables{$mib->{type}}{'sizeofend'}); /* $name */ + +type: code-parser +processtable: code-parser + +code: /* +code: * ${vtable}_add(): adds a structure node to our data set +code: */ +code: int +code: ${vtable}_add(struct ${vtable}_data *thedata) { +code: struct variable_list *vars = NULL; +code: +code: DEBUGMSGTL((\"$outputName\", \"adding data... \")); +code: /* add the index variables to the varbind list, which is +code: used by header_complex to index the data */ +code: +code: $variables{$vtable}{'code-varlist-add'}{'processed'} +code: +code: header_complex_add_data(&${vtable}Storage, vars, thedata); +code: DEBUGMSGTL((\"$vtable\",\"registered an entry\\n\")); +code: +code: DEBUGMSGTL((\"$outputName\", \"done.\\n\")); +code: return SNMPERR_SUCCESS; +code: } +code: +code: /* +code: * parse_$vtable(): +code: * parses .conf file entries needed to configure the mib. +code: */ +code: void +code: parse_$vtable(char *token, char *line) { +code: size_t tmpint; +code: struct ${vtable}_data *StorageTmp = SNMP_MALLOC_STRUCT(${vtable}_data); +code: struct variable_list *vars = NULL; +code: +code: DEBUGMSGTL((\"$outputName\", \"parsing config... \")); +code: +code: if (StorageTmp == NULL) { +code: config_perror(\"malloc failure\"); +code: return; +code: } +code: +code: $variables{$vtable}{'code-parser-sections'}{'processed'} +code: +code: ${vtable}_add(StorageTmp); +code: +code: DEBUGMSGTL((\"$outputName\", \"done.\\n\")); +code: } +code: +code: +code: /* +code: * store_$vtable(): +code: * stores .conf file entries needed to configure the mib. +code: */ +code: void +code: store_$vtable(void) { +code: char line[SNMP_MAXBUF]; +code: char *cptr; +code: size_t tmpint; +code: struct ${vtable}_data *StorageTmp; +code: struct header_complex_index *hcindex; +code: +code: DEBUGMSGTL((\"$outputName\", \"storing data... \")); +code: +code: memset(line,0,sizeof(line)); +code: +code: strcat(line, \"$vtable\"); +code: cptr = line + strlen(line); +code: +code: for(hcindex=${vtable}Storage; hcindex != NULL; +code: hcindex = hcindex->next) { +code: StorageTmp = (struct ${vtable}_data *) hcindex->data; +code: +code: $variables{$vtable}{'code-persistent-sections'}{'processed'} +code: +code: snmpd_store_config(line); +code: } +code: DEBUGMSGTL((\"$outputName\", \"done.\\n\")); +code: } + +# individual sections for the parser +type: code-parser-sections +process: code-parser-sections +skipif: $mib->{'access'} =~ /NoAccess/ + +code: line = read_config_read_data($variables{$mib->{type}}{asnType}, line, &StorageTmp->$name, &" . eval ("\"$variables{$mib->{type}}{varlenname}\"") . "); +code: " . eval ("\"$variables{$mib->{type}}{vartest}\"") . " + +# +# .conf persistent save Code per table +# +type: code-persistent-sections +process: code-persistent-sections +skipif: $mib->{'access'} =~ /NoAccess/ +code: cptr = read_config_store_data($variables{$mib->{type}}{asnType}, cptr, &StorageTmp->$name, &" . eval ("\"$variables{$mib->{type}}{varlenname}\"") . "); + +# +# Code code per table +# +type: code-var_table +processtable: code-var_table + +code: /* +code: * var_$vtable(): +code: * Handle this table separately from the scalar value case. +code: * The workings of this are basically the same as for var_$outputName above. +code: */ +code: unsigned char * +code: var_$vtable(struct variable *vp, +code: oid *name, +code: size_t *length, +code: int exact, +code: size_t *var_len, +code: WriteMethod **write_method) +code: { +code: +code: struct ${vtable}_data *StorageTmp = NULL; +code: +code: DEBUGMSGTL((\"$outputName\", \"var_$vtable: Entering... \\n\")); +code: /* +code: * this assumes you have registered all your data properly +cdoe: * with header_complex_add() somewhere before this +code: */ +code: if ((StorageTmp = +code: header_complex(${vtable}Storage, vp,name,length,exact, +code: var_len,write_method)) == NULL) +code: return NULL; +code: +code: /* +code: * this is where we do the value assignments for the mib results. +code: */ +code: switch(vp->magic) {\n\n +code: $variables{$vtable}{'code-case-statements'}{'processed'} +code: default: +code: ERROR_MSG(\"\"); +code: } +code: return NULL; +code: } + + +############################################################################ +# case statement sections +############################################################################ +type: code-case-statements +process: code-case-statements +skipif: $mib->{'access'} =~ /NoAccess/ + +code: case $NAME: +code: " . (($mib->{'access'} =~ /ReadWrite|WriteOnly|Create/) ? "*write_method = write_$mib->{label};" : "") . " +code: *var_len = $variables{$mib->{'type'}}{'sizeofstart'}StorageTmp->$mib->{label}$variables{$mib->{'type'}}{'sizeofend'}; +code: return (u_char *) $variables{$mib->{'type'}}{'storageret'}StorageTmp->$mib->{label}; +code: + +############################################################################ +# storage structure information +############################################################################ +type: variable-structure-info +process: variable-structure-info +skipif: $mib->{'access'} =~ /NoAccess/ +code: " . sprintf("#define %-20s $count", $NAME) . " +code: " . sprintf(" { %-20s, %-14s, %-6.6s, %s, %d, { %s } },", $NAME, $variables{$mib->{'type'}}{'asnType'}, $accessToUCD{$mib->{'access'}}, "var_$vroutine", $depth-1, $subid) . " + +############################################################################ +# write function definition, also appended to the end of the .c file. +############################################################################ +# +# Header info: declair write functions for set processing +# +process: code-write-func-decl +type: code-write-func-decl +skipif: $mib->{'access'} !~ /Write|Create/ +code: WriteMethod write_$name; +# +# C code +# +type: code-write-func +process: code-write-func +skipif: $mib->{'textualConvention'} eq "RowStatus" || $mib->{'access'} !~ /Write|Create/ +code: int +code: write_$name(int action, +code: u_char *var_val, +code: u_char var_val_type, +code: size_t var_val_len, +code: u_char *statP, +code: oid *name, +code: size_t name_len) +code: { +code: static $variables{$mib->{'type'}}{tmpvar} tmpvar; +code: struct ${vroutine}_data *StorageTmp = NULL; +code: static size_t tmplen; +code: size_t newlen=name_len - (sizeof(${outputName}_variables_oid)/sizeof(oid) + $depth - 1); +code: +code: DEBUGMSGTL((\"$outputName\", \"write_$name entering action=%d... \\n\", action)); +code: if ((StorageTmp = +code: header_complex(${vroutine}Storage, NULL, +code: &name[sizeof(${outputName}_variables_oid)/sizeof(oid) + $depth - 1], +code: &newlen, 1, NULL, NULL)) == NULL) +code: return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */ +code: +code: switch ( action ) { +code: case RESERVE1: +code: if (var_val_type != $variables{$mib->{'type'}}{asnType}){ +code: fprintf(stderr, \"write to $name not $variables{$mib->{'type'}}{asnType}\\n\"); +code: return SNMP_ERR_WRONGTYPE; +code: } +code: break; +code: +code: case RESERVE2: +code: /* memory reseveration, final preparation... */ +code: break; +code: +code: case FREE: +code: /* Release any resources that have been allocated */ +code: break; +code: +code: case ACTION: +code: /* The variable has been stored in $variables{$mib->{'type'}}{variable} for +code: you to use, and you have just been asked to do something with +code: it. Note that anything done here must be reversable in the UNDO case */ +code: ".eval ("\"$variables{$mib->{type}}{action}\"")." +code: break; +code: +code: case UNDO: +code: /* Back out any changes made in the ACTION case */ +code: ".eval ("\"$variables{$mib->{type}}{undo}\"")." +code: break; +code: +code: case COMMIT: +code: /* Things are working well, so it's now safe to make the change +code: permanently. Make sure that anything done here can't fail! */ +code: ".eval ("\"$variables{$mib->{'type'}}{'commit'}\"")." +code: break; +code: } +code: return SNMP_ERR_NOERROR; +code: } +code: +code: +############################################################################ +# copy memory from varlist +############################################################################ +type: code-varlist-copy +process: code-varlist-copy +skipif: $variables{$vroutine}{$name}{'isanindex'} != 1 +code: memdup((u_char **) &(StorageNew->$name), +code: vp->val.$variables{$mib->{'type'}}{variable}, +code: vp->val_len); +code: StorageNew->${name}Len = vp->val_len; +code: vp = vp->next_variable; +############################################################################ +# add null pointers to a varlist; value to be parsed later +############################################################################ +type: code-varlist-add-null +process: code-varlist-add-null +skipif: $variables{$vroutine}{$name}{'isanindex'} != 1 +code: snmp_varlist_add_variable(&vars, NULL, 0, $variables{$mib->{'type'}}{asnType}, NULL, 0); /* $name */ +############################################################################ +# write function definition for a RowStatus object, +# - allows for creation/deletion. +############################################################################ +# +# Header info: declair write functions for set processing +# +process: code-write-rowstatus-decl +type: code-write-rowstatus-decl +skipif: $mib->{'textualConvention'} ne "RowStatus" +code: WriteMethod write_$name; +# +# code +# +type: code-write-rowstatus +process: code-write-rowstatus +skipif: $mib->{'textualConvention'} ne "RowStatus" +code: int +code: write_$name(int action, +code: u_char *var_val, +code: u_char var_val_type, +code: size_t var_val_len, +code: u_char *statP, +code: oid *name, +code: size_t name_len) +code: { +code: struct ${vroutine}_data *StorageTmp = NULL; +code: static struct ${vroutine}_data *StorageNew, *StorageDel; +code: size_t newlen=name_len - (sizeof(${vroutine}_variables_oid)/sizeof(oid) + 3 - 1); +code: static int old_value; +code: int set_value; +code: static struct variable_list *vars, *vp; +code: struct header_complex_index *hciptr; +code: char who[MAX_OID_LEN], flagName[MAX_OID_LEN]; +code: +code: StorageTmp = +code: header_complex(${vroutine}Storage, NULL, +code: &name[sizeof(${vroutine}_variables_oid)/sizeof(oid) + 3 - 1], +code: &newlen, 1, NULL, NULL); +code: +code: +code: if (var_val_type != ASN_INTEGER || var_val == NULL){ +code: fprintf(stderr, \"write to $name not ASN_INTEGER\\n\"); +code: return SNMP_ERR_WRONGTYPE; +code: } +code: set_value = *((long *) var_val); +code: +code: /* check legal range, and notReady is reserved for us, not a user */ +code: if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY) +code: return SNMP_ERR_INCONSISTENTVALUE; +code: +code: switch ( action ) { +code: case RESERVE1: +code: /* stage one: test validity */ +code: if (StorageTmp == NULL) { +code: /* create the row now? */ +code: +code: /* ditch illegal values now */ +code: if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) +code: return SNMP_ERR_INCONSISTENTVALUE; +code: +code: /* destroying a non-existent row is actually legal */ +code: if (set_value == RS_DESTROY) { +code: return SNMP_ERR_NOERROR; +code: } +code: +code: /* illegal creation values */ +code: if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) { +code: return SNMP_ERR_INCONSISTENTVALUE; +code: } +code: } else { +code: /* row exists. Check for a valid state change */ +code: if (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT) { +code: /* can't create a row that exists */ +code: return SNMP_ERR_INCONSISTENTVALUE; +code: } +code: /* XXX: interaction with row storage type needed */ +code: } +code: break; +code: +code: +code: case RESERVE2: +code: /* memory reseveration, final preparation... */ +code: if (StorageTmp == NULL) { +code: /* creation */ +code: vars = NULL; +code: +code: $variables{'code-varlist-add-null'}{'processed'} +code: +code: if (header_complex_parse_oid(&(name[sizeof(${vroutine}_variables_oid)/sizeof(oid)+2]), newlen, +code: vars) != SNMPERR_SUCCESS) { +code: /* XXX: free, zero vars */ +code: return SNMP_ERR_INCONSISTENTNAME; +code: } +code: vp = vars; +code: +code: StorageNew = SNMP_MALLOC_STRUCT(${vroutine}_data); +code: $variables{'code-varlist-copy'}{'processed'} +code: +code: StorageNew->$name = set_value; +code: /* XXX: free, zero vars, no longer needed? */ +code: } +code: +code: break; +code: +code: +code: case FREE: +code: /* XXX: free, zero vars */ +code: /* Release any resources that have been allocated */ +code: break; +code: +code: +code: case ACTION: +code: /* The variable has been stored in set_value for you to +code: use, and you have just been asked to do something with +code: it. Note that anything done here must be reversable in +code: the UNDO case */ +code: +code: if (StorageTmp == NULL) { +code: /* row creation, so add it */ +code: if (StorageNew != NULL) +code: ${vroutine}_add(StorageNew); +code: /* XXX: ack, and if it is NULL? */ +code: } else if (set_value != RS_DESTROY) { +code: /* set the flag? */ +code: old_value = StorageTmp->$name; +code: StorageTmp->$name = *((long *) var_val); +code: } else { +code: /* destroy... extract it for now */ +code: hciptr = +code: header_complex_find_entry(${vroutine}Storage, +code: StorageTmp); +code: StorageDel = +code: header_complex_extract_entry(&${vroutine}Storage, +code: hciptr); +code: } +code: break; +code: +code: +code: case UNDO: +code: /* Back out any changes made in the ACTION case */ +code: if (StorageTmp == NULL) { +code: /* row creation, so remove it again */ +code: hciptr = +code: header_complex_find_entry(${vroutine}Storage, +code: StorageTmp); +code: StorageDel = +code: header_complex_extract_entry(&${vroutine}Storage, +code: hciptr); +code: /* XXX: free it */ +code: } else if (StorageDel != NULL) { +code: /* row deletion, so add it again */ +code: ${vroutine}_add(StorageDel); +code: } else { +code: StorageTmp->$name = old_value; +code: } +code: break; +code: +code: +code: case COMMIT: +code: /* Things are working well, so it's now safe to make the change +code: permanently. Make sure that anything done here can't fail! */ +code: if (StorageDel != NULL) { +code: StorageDel == 0; +code: /* XXX: free it, its dead */ +code: } +code: break; +code: } +code: return SNMP_ERR_NOERROR; +code: } +code: diff --git a/packages/net/snmp/agent/current/utils/mib2c/mib2c.vartypes.conf b/packages/net/snmp/agent/current/utils/mib2c/mib2c.vartypes.conf new file mode 100644 --- /dev/null +++ b/packages/net/snmp/agent/current/utils/mib2c/mib2c.vartypes.conf @@ -0,0 +1,89 @@ +# +# Define types of data by mib type, and translate into needed C code. +# +# type: the label in question extracted from the mib. +# asnType: the internal type #define we should use for this type. +# variable: the name of the variable we're going to use. +# variablePtr: How to get a pointer to the variable above (may be +# the same, if variable is also a pointer) +# cast: how to cast from a void * or a char * to a pointer of +# your type. +# writeInit: variable declaration +# case: initialization of the variable to a bogus value. +# +# copy: copies the previous definition into the current one, +# if most of it (or all of it) is the same. +############################################################################ +type: OCTETSTR +asnType: ASN_OCTET_STR +variable: string +variablePtr: string +cast: char * +writeInit: static unsigned char string[SPRINT_MAX_LEN]; +case: *string = 0; +case: *var_len = strlen(string); +case: return (unsigned char *) string; +############################################################################ +type: INTEGER +asnType: ASN_INTEGER +variable: long_ret +variablePtr: &long_ret +cast: long * +writeInit: static long *long_ret; +case: long_ret = 0; +case: return (unsigned char *) &long_ret; +############################################################################ +type: OBJECTID +asnType: ASN_OBJECT_ID +variable: objid +variablePtr: objid +cast: oid * +writeInit: static oid *objid; +case: objid[0] = 0; +case: objid[1] = 0; +case: *var_len = 2*sizeof(oid); +case: return (unsigned char *) objid; +############################################################################ +type: COUNTER64 +asnType: ASN_COUNTER64 +variable: c64 +variablePtr: &c64 +cast: struct counter64 * +writeInit: struct counter64 *c64; +case: c64.high = 0; +case: c64.low = 0; +case: *var_len = sizeof(c64); +case: return (unsigned char *) &c64; +############################################################################ +type: COUNTER +copy: INTEGER +delete: asnType +asnType: ASN_COUNTER +############################################################################ +type: NETADDR +copy: ASN_OBJECT_ID +############################################################################ +type: UINTEGER +copy: INTEGER +delete: asnType +asnType: ASN_UINTEGER +############################################################################ +type: IPADDR +copy: OCTETSTR +delete: asnType +asnType: ASN_IPADDRESS +############################################################################ +type: GAUGE +copy: INTEGER +delete: asnType +asnType: ASN_GAUGE +############################################################################ +type: OPAQUE +copy: OCTETSTR +delete: asnType +asnType: ASN_OPAQUE +############################################################################ +type: TICKS +copy: INTEGER +delete: asnType +asnType: ASN_TIMETICKS diff --git a/packages/net/snmp/lib/current/ChangeLog b/packages/net/snmp/lib/current/ChangeLog new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/ChangeLog @@ -0,0 +1,139 @@ +2000-06-21 Hugo Tyson + + * src/snmp_logging.c: + * src/parse.c: Catch unprotected includes of sys/stat.h, + accidentally acquired from the stdinc/newlib world. Now prevented + by the might of #ifndef __ECOS. + +2000-06-14 Hugo Tyson + + * cdl/snmplib.cdl: Add option CYGDBG_NET_SNMPLIB_DEBUG to control + the standard UCD debugging. + + * include/config.h: React to the above, and remove deal with + default definitions from the agent configury for system MIB + values. + +2000-06-14 John Dallaway + + * cdl/snmplib.cdl: Tidy display strings. + +2000-06-14 Hugo Tyson + + * cdl/snmplib.cdl: Install all the header files below + include/ucd-snmp/ as is the normal host-side standard; this avoids + some rather terrible filenamespace pollution too. That location + is also added to the include path, using a mechanism that's rather + build-method-specific; it may need revisiting. + +2000-06-14 Hugo Tyson + + * cdl/snmplib.cdl: parent this below CYGPKG_NET. + +2000-06-12 Hugo Tyson + + * src/system.c (gettimeofday): Simulate this using libc's time() + function which will call through to a wallclock of one is present, + or just count up from start time. + +2000-06-02 Hugo Tyson + + * src/parse.c (add_mibdir): Return no mibs here, oh no; they're + not needed for agent use of the library. Waste of time - unless + someone is liable to use the snmplib for tool rather than agent + purposes. + + This goes along with the change to the agent to remove the ROFS + which contained all the MIBs - I had thought that the library + *needed* them to function, but it's not so - reading them in + (and complaining of their absence) is part of the snmplib startup, + but it's not needed by an agent. This also means that if + reinstated they should live here in the lib component rather than + over there in the agent one; oh well. + +2000-05-31 Hugo Tyson + + * Initial commit of port of UCD-SNMP version 4.1.2 to eCos. + +//========================================================================== +// +// ./lib/current/ChangeLog +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ diff --git a/packages/net/snmp/lib/current/cdl/snmplib.cdl b/packages/net/snmp/lib/current/cdl/snmplib.cdl new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/cdl/snmplib.cdl @@ -0,0 +1,122 @@ +# ==================================================================== +# +# snmplib.cdl +# +# SNMP library configuration data +# +# ==================================================================== +#####COPYRIGHTBEGIN#### +# +# ------------------------------------------- +# The contents of this file are subject to the Red Hat eCos Public License +# Version 1.1 (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://www.redhat.com/ +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +# License for the specific language governing rights and limitations under +# the License. +# +# The Original Code is eCos - Embedded Configurable Operating System, +# released September 30, 1998. +# +# The Initial Developer of the Original Code is Red Hat. +# Portions created by Red Hat are +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# All Rights Reserved. +# ------------------------------------------- +# +#####COPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): hmt +# Original data: hmt +# Contributors: gthomas +# Date: 2000-05-30 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_SNMPLIB { + display "SNMP library" + parent CYGPKG_NET +# doc doc/index.html + include_dir ucd-snmp + requires CYGPKG_IO + requires CYGPKG_LIBC + requires CYGPKG_ERROR + requires CYGPKG_NET + description "SNMP protocol support library based on the UCD-SNMP project." + + compile \ + asn1.c \ + callback.c \ + default_store.c \ + int64.c \ + keytools.c \ + lcd_time.c \ + md5.c \ + mib.c \ + mt_support.c \ + parse.c \ + read_config.c \ + scapi.c \ + snmp.c \ + snmp_alarm.c \ + snmp_api.c \ + snmp_auth.c \ + snmp_client.c \ + snmp_debug.c \ + snmp_logging.c \ + snmpusm.c \ + snmpv3.c \ + system.c \ + tools.c \ + vacm.c + + + cdl_option CYGDBG_NET_SNMPLIB_DEBUG { + display "Enable SNMP debug printout" + flavor bool + default_value 0 + description " + This option enables the debugging printout facilities of the + UCD SNMP module, controlled by the global variable 'dodebug'. + Setting this variable produces lots of printout for SNMP agent + activity, often enough to make your SNMP client time out." + } + + cdl_component CYGPKG_SNMPLIB_OPTIONS { + display "SNMP library build options" + flavor none + no_define + + cdl_option CYGPKG_SNMPLIB_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS -I$(PREFIX)/include/ucd-snmp" } + description " + This option modifies the set of compiler flags for + building the SNMP library package. + These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_SNMPLIB_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the SNMP library package. These flags are removed from + the set of global flags if present." + } + } +} + +# EOF snmplib.cdl diff --git a/packages/net/snmp/lib/current/include/asn1.h b/packages/net/snmp/lib/current/include/asn1.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/asn1.h @@ -0,0 +1,272 @@ +//========================================================================== +// +// ./lib/current/include/asn1.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef ASN1_H +#define ASN1_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define PARSE_PACKET 0 +#define DUMP_PACKET 1 + +/* + * Definitions for Abstract Syntax Notation One, ASN.1 + * As defined in ISO/IS 8824 and ISO/IS 8825 + * + * + */ +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#ifndef EIGHTBIT_SUBIDS +typedef u_long oid; +#define MAX_SUBID 0xFFFFFFFF +#else +typedef u_char oid; +#define MAX_SUBID 0xFF +#endif + +#define MIN_OID_LEN 2 +#define MAX_OID_LEN 128 /* max subid's in an oid */ +#ifndef MAX_NAME_LEN /* conflicts with some libraries */ +#define MAX_NAME_LEN MAX_OID_LEN /* obsolete. use MAX_OID_LEN */ +#endif + +#define ASN_BOOLEAN ((u_char)0x01) +#define ASN_INTEGER ((u_char)0x02) +#define ASN_BIT_STR ((u_char)0x03) +#define ASN_OCTET_STR ((u_char)0x04) +#define ASN_NULL ((u_char)0x05) +#define ASN_OBJECT_ID ((u_char)0x06) +#define ASN_SEQUENCE ((u_char)0x10) +#define ASN_SET ((u_char)0x11) + +#define ASN_UNIVERSAL ((u_char)0x00) +#define ASN_APPLICATION ((u_char)0x40) +#define ASN_CONTEXT ((u_char)0x80) +#define ASN_PRIVATE ((u_char)0xC0) + +#define ASN_PRIMITIVE ((u_char)0x00) +#define ASN_CONSTRUCTOR ((u_char)0x20) + +#define ASN_LONG_LEN (0x80) +#define ASN_EXTENSION_ID (0x1F) +#define ASN_BIT8 (0x80) + +#define IS_CONSTRUCTOR(byte) ((byte) & ASN_CONSTRUCTOR) +#define IS_EXTENSION_ID(byte) (((byte) & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) + +struct counter64 { + u_long high; + u_long low; +}; + +#ifdef OPAQUE_SPECIAL_TYPES +typedef struct counter64 integer64; +typedef struct counter64 unsigned64; + +/* The BER inside an OPAQUE is an context specific with a value of 48 (0x30) + plus the "normal" tag. For a Counter64, the tag is 0x46 (i.e., an + applications specific tag with value 6). So the value for a 64 bit + counter is 0x46 + 0x30, or 0x76 (118 base 10). However, values + greater than 30 can not be encoded in one octet. So the first octet + has the class, in this case context specific (ASN_CONTEXT), and + the special value (i.e., 31) to indicate that the real value follows + in one or more octets. The high order bit of each following octet + indicates if the value is encoded in additional octets. A high order + bit of zero, indicates the last. For this "hack", only one octet + will be used for the value. */ + + /* first octet of the tag */ +#define ASN_OPAQUE_TAG1 (ASN_CONTEXT | ASN_EXTENSION_ID) +/* base value for the second octet of the tag - the + second octet was the value for the tag */ +#define ASN_OPAQUE_TAG2 ((u_char)0x30) + +#define ASN_OPAQUE_TAG2U ((u_char)0x2f) /* second octet of tag for union */ + +/* All the ASN.1 types for SNMP "should have been" defined in this file, + but they were not. (They are defined in snmp_impl.h) Thus, the tag for + Opaque and Counter64 is defined, again, here with a different names. */ +#define ASN_APP_OPAQUE (ASN_APPLICATION | 4) +#define ASN_APP_COUNTER64 (ASN_APPLICATION | 6) +#define ASN_APP_FLOAT (ASN_APPLICATION | 8) +#define ASN_APP_DOUBLE (ASN_APPLICATION | 9) +#define ASN_APP_I64 (ASN_APPLICATION | 10) +#define ASN_APP_U64 (ASN_APPLICATION | 11) +#define ASN_APP_UNION (ASN_PRIVATE | 1) /* or ASN_PRIV_UNION ? */ + +/* value for Counter64 */ +#define ASN_OPAQUE_COUNTER64 (ASN_OPAQUE_TAG2 + ASN_APP_COUNTER64) +/* max size of BER encoding of Counter64 */ +#define ASN_OPAQUE_COUNTER64_MX_BER_LEN 12 + +/* value for Float */ +#define ASN_OPAQUE_FLOAT (ASN_OPAQUE_TAG2 + ASN_APP_FLOAT) +/* size of BER encoding of Float */ +#define ASN_OPAQUE_FLOAT_BER_LEN 7 + +/* value for Double */ +#define ASN_OPAQUE_DOUBLE (ASN_OPAQUE_TAG2 + ASN_APP_DOUBLE) +/* size of BER encoding of Double */ +#define ASN_OPAQUE_DOUBLE_BER_LEN 11 + +/* value for Integer64 */ +#define ASN_OPAQUE_I64 (ASN_OPAQUE_TAG2 + ASN_APP_I64) +/* max size of BER encoding of Integer64 */ +#define ASN_OPAQUE_I64_MX_BER_LEN 11 + +/* value for Unsigned64 */ +#define ASN_OPAQUE_U64 (ASN_OPAQUE_TAG2 + ASN_APP_U64) +/* max size of BER encoding of Unsigned64 */ +#define ASN_OPAQUE_U64_MX_BER_LEN 12 + +#endif /* OPAQUE_SPECIAL_TYPES */ + + +#define ASN_PRIV_INCL_RANGE (ASN_PRIVATE | 2) +#define ASN_PRIV_EXCL_RANGE (ASN_PRIVATE | 3) +#define ASN_PRIV_DELEGATED (ASN_PRIVATE | 4) +#define IS_DELEGATED(x) ((x) == ASN_PRIV_DELEGATED) + + +int asn_check_packet (u_char *, size_t); +u_char *asn_parse_int (u_char *, size_t *, u_char *, long *, size_t); +u_char *asn_build_int (u_char *, size_t *, u_char, long *, size_t); +u_char *asn_parse_unsigned_int (u_char *, size_t *, u_char *, u_long *, size_t); +u_char *asn_build_unsigned_int (u_char *, size_t *, u_char, u_long *, size_t); +u_char *asn_parse_string (u_char *, size_t *, u_char *, u_char *, size_t *); +u_char *asn_build_string (u_char *, size_t *, u_char, const u_char *, size_t); +u_char *asn_parse_header (u_char *, size_t *, u_char *); +u_char *asn_parse_sequence(u_char *, size_t *, u_char *, + u_char expected_type, /* must be this type */ + const char *estr); /* error message prefix */ +u_char *asn_build_header (u_char *, size_t *, u_char, size_t); +u_char *asn_build_sequence (u_char *, size_t *, u_char, size_t); +u_char *asn_parse_length (u_char *, u_long *); +u_char *asn_build_length (u_char *, size_t *, size_t); +u_char *asn_parse_objid (u_char *, size_t *, u_char *, oid *, size_t *); +u_char *asn_build_objid (u_char *, size_t *, u_char, oid *, size_t); +u_char *asn_parse_null (u_char *, size_t *, u_char *); +u_char *asn_build_null (u_char *, size_t *, u_char); +u_char *asn_parse_bitstring (u_char *, size_t *, u_char *, u_char *, size_t *); +u_char *asn_build_bitstring (u_char *, size_t *, u_char, u_char *, size_t); +u_char *asn_parse_unsigned_int64 (u_char *, size_t *, u_char *, + struct counter64 *, size_t); +u_char *asn_build_unsigned_int64 (u_char *, size_t *, u_char, + struct counter64 *, size_t); +u_char *asn_parse_signed_int64 (u_char *, size_t *, u_char *, + struct counter64 *, size_t); +u_char *asn_build_signed_int64 (u_char *, size_t *, u_char, + struct counter64 *, size_t); +u_char *asn_build_float (u_char *, size_t *, u_char, float *, + size_t); +u_char *asn_parse_float (u_char *, size_t *, u_char *, float *, size_t); +u_char *asn_build_double (u_char *, size_t *, u_char, double *, + size_t); +u_char *asn_parse_double (u_char *, size_t *, u_char *, double *, size_t); + +#ifdef __cplusplus +} +#endif +#endif /* ASN1_H */ diff --git a/packages/net/snmp/lib/current/include/callback.h b/packages/net/snmp/lib/current/include/callback.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/callback.h @@ -0,0 +1,125 @@ +//========================================================================== +// +// ./lib/current/include/callback.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* callback.c: A generic callback mechanism */ + +#ifndef CALLBACK_H +#define CALLBACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_CALLBACK_IDS 2 +#define MAX_CALLBACK_SUBIDS 8 + +/* Callback Major Types */ +#define SNMP_CALLBACK_LIBRARY 0 +#define SNMP_CALLBACK_APPLICATION 1 + +/* SNMP_CALLBACK_LIBRARY minor types */ +#define SNMP_CALLBACK_POST_READ_CONFIG 0 +#define SNMP_CALLBACK_STORE_DATA 1 +#define SNMP_CALLBACK_SHUTDOWN 2 +#define SNMP_CALLBACK_POST_PREMIB_READ_CONFIG 3 +#define SNMP_CALLBACK_LOGGING 4 + +typedef int (SNMPCallback)(int majorID, int minorID, void *serverarg, + void *clientarg); + +struct snmp_gen_callback { + SNMPCallback *sc_callback; + void *sc_client_arg; + struct snmp_gen_callback *next; +}; + +/* function prototypes */ +void init_callbacks(void); +int snmp_register_callback(int major, int minor, SNMPCallback *new_callback, + void *arg); +int snmp_call_callbacks(int major, int minor, void *caller_arg); + +#ifdef __cplusplus +} +#endif + +#endif /* CALLBACK_H */ diff --git a/packages/net/snmp/lib/current/include/config.h b/packages/net/snmp/lib/current/include/config.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/config.h @@ -0,0 +1,1229 @@ +//========================================================================== +// +// ./lib/current/include/config.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ +/* config.h: a general config file */ + + +#include +#include +#include + +/* Define IN_UCD_SNMP_SOURCE if compiling inside the ucd-snmp source tree */ +#define IN_UCD_SNMP_SOURCE 1 + +/* Our assigned enterprise number */ +#define ENTERPRISE_NUMBER 2021 + +/* don't change these values! */ +#define SNMPV1 0xAAAA /* readable by anyone */ +#define SNMPV2ANY 0xA000 /* V2 Any type (includes NoAuth) */ +#define SNMPV2AUTH 0x8000 /* V2 Authenticated requests only */ + +/* default list of mibs to load */ + +//#define DEFAULT_MIBS "IP-MIB:IF-MIB:TCP-MIB:UDP-MIB:SNMPv2-MIB:RFC1213-MIB:UCD-SNMP-MIB:UCD-DEMO-MIB:SNMP-VIEW-BASED-ACM-MIB:SNMP-COMMUNITY-MIB:SNMP-FRAMEWORK-MIB:SNMP-MPD-MIB:SNMP-USER-BASED-SM-MIB" + +//#define DEFAULT_MIBS "SNMPv2-MIB:RFC1213-MIB:UCD-SNMP-MIB" +#define DEFAULT_MIBS "all" + + +/* default location to look for mibs to load using the above tokens + and/or those in the MIBS envrionment variable*/ + +#define DEFAULT_MIBDIRS "MIBS/" + +/* default mib files to load, specified by path. */ + +/* #undef DEFAULT_MIBFILES */ + +/* should we compile to use special opaque types: float, double, + counter64, i64, ui64, union? */ +#define OPAQUE_SPECIAL_TYPES 1 + +/* comment the next line if you are compiling with libsnmp.h + and are not using the UC-Davis SNMP library. */ +#define UCD_SNMP_LIBRARY 1 + +/* define if you want to compile support for both authentication and + privacy support. */ +#define SCAPI_AUTHPRIV 1 + +/* define if you are using the MD5 code ...*/ +#define USE_INTERNAL_MD5 1 + +/* ... or define this if you're using openssl support */ +/* #undef USE_OPENSSL */ + +/* add in recent CMU library extensions (not complete) */ +/* #undef CMU_COMPATIBLE */ + +/* add in recent resource lock functions (not complete) */ +/* #undef _REENTRANT */ + +/* should "--" comments in mibs be a comment till the end of the line + or also until another "--", the latter being the technically + correct. */ +/* #undef MIB_COMMENT_IS_EOL_TERMINATED */ + +/* debugging stuff */ +#ifdef CYGDBG_NET_SNMPLIB_DEBUG +// #undef SNMP_NO_DEBUGGING +#else +#define SNMP_NO_DEBUGGING 1 /* if defined, we optimize the code + to exclude all debugging calls. */ +#endif + +#define SNMP_ALWAYS_DEBUG 0 /* Always print debugging information and + ignore the -D flag passed to the cmds */ + +/* PERSISTENT_DIRECTORY: If defined, the library is capabile of saving + persisant information to this directory in the form of configuration + lines: PERSISTENT_DIRECTORY/NAME.persistent.conf */ +//#define PERSISTENT_DIRECTORY "/var/ucd-snmp" + +/* PERSISTENT_MASK: the umask permissions to set up the persistent files with */ +//#define PERSISTENT_MASK 077 + +/* AGENT_DIRECTORY_MODE: the mode the agents should use to create + directories with. Since the data stored here is probably sensitive, it + probably should be read-only by root/administrator. */ +#define AGENT_DIRECTORY_MODE 0700 + +/* MAX_PERSISTENT_BACKUPS: + * The maximum number of persistent backups the library will try to + * read from the persistent cache directory. If an application fails to + * close down successfully more than this number of times, data will be lost. + */ +#define MAX_PERSISTENT_BACKUPS 10 + + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* #undef _ALL_SOURCE */ +#endif + +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 0 + +/* Define if you have and it should be used (not on Ultrix). */ +#define HAVE_ALLOCA_H 0 + +/* Define if you have the getmntent function. */ +#define HAVE_GETMNTENT 0 + +/* Define if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 0 + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +/* #undef STACK_DIRECTION */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* define the system type include file here */ +//#define SYSTEM_INCLUDE_FILE "s/linux.h" + +/* define the machine (cpu) type include file here */ +//#define MACHINE_INCLUDE_FILE "m/generic.h" + +#define SNMPLIBPATH "/lib/snmp" +#define SNMPSHAREPATH "/share/snmp" +#define SNMPCONFPATH "/etc/snmp" + +/* LOGFILE: If defined it closes stdout/err/in and opens this in out/err's + place. (stdin is closed so that sh scripts won't wait for it) */ + +//#define LOGFILE "/var/log/snmpd.log" + +/* default system contact */ +#ifdef CYGDAT_NET_SNMPAGENT_SYS_CONTACT +#define SYS_CONTACT CYGDAT_NET_SNMPAGENT_SYS_CONTACT +#else +#define SYS_CONTACT "nobody@dev.null" +#endif + +/* system location */ +#ifdef CYGDAT_NET_SNMPAGENT_SYS_LOC +#define SYS_LOC CYGDAT_NET_SNMPAGENT_SYS_LOC +#else +#define SYS_LOC "" +#endif + +/* Use libwrap to handle allow/deny hosts? */ +/* #undef USE_LIBWRAP */ + +/* Use dmalloc to do malloc debugging? */ +/* #undef HAVE_DMALLOC_H */ + +/* location of UNIX kernel */ +#define KERNEL_LOC "unknown" + +/* location of mount table list */ +#define ETC_MNTTAB "/etc/mtab" + +/* location of swap device (ok if not found) */ +/* #undef DMEM_LOC */ + +//#define PSCMD "/bin/ps -e" + +/* Where is the uname command */ +//#define UNAMEPROG "/bin/uname" + +/* testing code sections. */ +/* #undef SNMP_TESTING_CODE */ + +/* If you don't want the agent to report on variables it doesn't have data for */ +#define NO_DUMMY_VALUES 1 + +/* Define if statfs takes 2 args and the second argument has + type struct fs_data. [Ultrix] */ +/* #undef STAT_STATFS_FS_DATA */ + +/* Define if the TCP timer constants in + depend on the integer variable `hz'. [FreeBSD 4.x] */ +/* #undef TCPTV_NEEDS_HZ */ + +/* Define if you have the bcopy function. */ +#define HAVE_BCOPY 1 + +/* Define if you have the execv function. */ +//#define HAVE_EXECV 1 + +/* Define if you have the fork function. */ +//#define HAVE_FORK 1 + +/* Define if you have the getdtablesize function. */ +//#define HAVE_GETDTABLESIZE 1 + +/* Define if you have the getfsstat function. */ +/* #undef HAVE_GETFSSTAT */ + +/* Define if you have the gethostname function. */ +//#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getloadavg function. */ +/* #undef HAVE_GETLOADAVG */ + +/* Define if you have the getpagesize function. */ +//#define HAVE_GETPAGESIZE 1 + +/* Define if you have the getpid function. */ +//#define HAVE_GETPID 1 + +/* Define if you have the gettimeofday function. */ +//#define HAVE_GETTIMEOFDAY 1 + +/* Define if you have the if_freenameindex function. */ +//#define HAVE_IF_FREENAMEINDEX 1 + +/* Define if you have the if_nameindex function. */ +//#define HAVE_IF_NAMEINDEX 1 + +/* Define if you have the index function. */ +//#define HAVE_INDEX 1 + +/* Define if you have the knlist function. */ +/* #undef HAVE_KNLIST */ + +/* Define if you have the kvm_getprocs function. */ +/* #undef HAVE_KVM_GETPROCS */ + +/* Define if you have the kvm_openfiles function. */ +/* #undef HAVE_KVM_OPENFILES */ + +/* Define if you have the lrand48 function. */ +//#define HAVE_LRAND48 1 + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE 1 + +/* Define if you have the nlist function. */ +//#define HAVE_NLIST 1 + +/* Define if you have the rand function. */ +#define HAVE_RAND 1 + +/* Define if you have the random function. */ +//#define HAVE_RANDOM 1 + +/* Define if you have the regcomp function. */ +//#define HAVE_REGCOMP 1 + +/* Define if you have the rpmGetPath function. */ +/* #undef HAVE_RPMGETPATH */ + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setenv function. */ +#define HAVE_SETENV 1 + +/* Define if you have the setlocale function. */ +//#define HAVE_SETLOCALE 1 + +/* Define if you have the setmntent function. */ +//#define HAVE_SETMNTENT 1 + +/* Define if you have the sigalrm function. */ +#define HAVE_SIGALRM 1 + +/* Define if you have the sigblock function. */ +//#define HAVE_SIGBLOCK 1 + +/* Define if you have the sighold function. */ +//#define HAVE_SIGHOLD 1 + +/* Define if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define if you have the sigset function. */ +#define HAVE_SIGSET 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the statfs function. */ +//#define HAVE_STATFS 1 + +/* Define if you have the statvfs function. */ +//#define HAVE_STATVFS 1 + +/* Define if you have the strcasestr function. */ +//#define HAVE_STRCASESTR 1 + +/* Define if you have the strchr function. */ +#define HAVE_STRCHR 1 + +/* Define if you have the strdup function. */ +//#define HAVE_STRDUP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strncasecmp function. */ +//#define HAVE_STRNCASECMP 1 + +/* Define if you have the strtol function. */ +#define HAVE_STRTOL 1 + +/* Define if you have the system function. */ +//#define HAVE_SYSTEM 1 + +/* Define if you have the tcgetattr function. */ +//#define HAVE_TCGETATTR 1 + +/* Define if you have the uname function. */ +//#define HAVE_UNAME 1 + +/* Define if you have the usleep function. */ +//#define HAVE_USLEEP 1 + +/* Define if you have the vsnprintf function. */ +#define HAVE_VSNPRINTF 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define if you have the header file. */ +//#define HAVE_ASM_PAGE_H 1 + +/* Define if you have the header file. */ +//#define HAVE_DIRENT_H 1 + +/* Define if you have the header file. */ +#define HAVE_ERR_H 1 + +/* Define if you have the header file. */ +//#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +//#define HAVE_FSTAB_H 1 + +/* Define if you have the header file. */ +//#define HAVE_GETOPT_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_INET_MIB2_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_IOCTLS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_KSTAT_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_KVM_H */ + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +//#define HAVE_LINUX_HDREG_H 1 + +/* Define if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_MACHINE_PARAM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_MACHINE_PTE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_MACHINE_TYPES_H */ + +/* Define if you have the header file. */ +//#define HAVE_MALLOC_H 1 + +/* Define if you have the header file. */ +//#define HAVE_MNTENT_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_MTAB_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NDIR_H */ + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_DL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NET_IF_MIB_H */ + +/* Define if you have the header file. */ +#define HAVE_NET_IF_TYPES_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NET_IF_VAR_H */ + +/* Define if you have the header file. */ +#define HAVE_NET_ROUTE_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_ICMP_VAR_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IF_ETHER_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_PCB_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_VAR_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP6_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IP_VAR_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_FSM_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_TIMER_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_VAR_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCPIP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_UDP_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_UDP_VAR_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_IN6_PCB_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_IN6_VAR_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_IP6_VAR_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_ND6_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_TCP6_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_TCP6_FSM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_TCP6_TIMER_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NETINET6_TCP6_VAR_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_NLIST_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_OPENSSL_EVP_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_OPENSSL_HMAC_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_OSRELDATE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_PKGLOCS_H */ + +/* Define if you have the header file. */ +//#define HAVE_PTHREAD_H 1 + +/* Define if you have the header file. */ +//#define HAVE_REGEX_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SGTTY_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_CDEFS_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_CONF_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_DISKIO_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_DISKLABEL_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_DKIO_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_DMAP_H */ + +/* Define if you have the header file. */ +//#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_FIXPOINT_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_HASHING_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_LOADAVG_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_MBUF_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_MNTENT_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_MNTTAB_H */ + +/* Define if you have the header file. */ +//#define HAVE_SYS_MOUNT_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_POOL_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_PROC_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_PROTOSW_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_PSTAT_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_QUEUE_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKETVAR_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_STATFS_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_STATVFS_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_STREAM_H */ + +/* Define if you have the header file. */ +//#define HAVE_SYS_SWAP_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_SYSCTL_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_SYSMP_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_TCPIPSTATS_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_UN_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_USER_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_UTSNAME_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_VFS_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_VM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_VMMAC_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_VMMETER_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_VMPARAM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_VMSYSTM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_VNODE_H */ + +/* Define if you have the header file. */ +//#define HAVE_SYSLOG_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_UFS_FFS_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_UFS_FS_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_UFS_UFS_DINODE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_UFS_UFS_INODE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_UFS_UFS_QUOTA_H */ + +/* Define if you have the header file. */ +//#define HAVE_UNISTD_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_UTSNAME_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_VM_SWAP_PAGER_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_VM_VM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_XTI_H */ + +/* Define if you have the crypto library (-lcrypto). */ +/* #undef HAVE_LIBCRYPTO */ + +/* Define if you have the efence library (-lefence). */ +/* #undef HAVE_LIBEFENCE */ + +/* Define if you have the elf library (-lelf). */ +//#define HAVE_LIBELF 1 + +/* Define if you have the kstat library (-lkstat). */ +/* #undef HAVE_LIBKSTAT */ + +/* Define if you have the kvm library (-lkvm). */ +/* #undef HAVE_LIBKVM */ + +/* Define if you have the m library (-lm). */ +#define HAVE_LIBM 1 + +/* Define if you have the mld library (-lmld). */ +/* #undef HAVE_LIBMLD */ + +/* Define if you have the nsl library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define if you have the z library (-lz). */ +//#define HAVE_LIBZ 1 + +/* define if you are using linux and /proc/net/dev has the compressed + field, which exists in linux kernels 2.2 and greater. */ +/* #undef PROC_NET_DEV_HAS_COMPRESSED */ + +/* define rtentry to ortentry on SYSV machines (alphas) */ +//#define RTENTRY struct rtentry + +/* Use BSD 4.4 routing table entries? */ +/* #undef RTENTRY_4_4 */ + +/* Does struct sigaction have a sa_sigaction field? */ +#define STRUCT_SIGACTION_HAS_SA_SIGACTION 1 + +/* Does struct sockaddr have a sa_len field? */ +/* #undef STRUCT_SOCKADDR_HAS_SA_LEN */ + +/* Does struct sockaddr have a sa_family2 field? */ +/* #undef STRUCT_SOCKADDR_HAS_SA_UNION_SA_GENERIC_SA_FAMILY2 */ + +/* rtentry structure tests */ +/* #undef RTENTRY_RT_NEXT */ +//#define STRUCT_RTENTRY_HAS_RT_DST 1 +/* #undef STRUCT_RTENTRY_HAS_RT_UNIT */ +/* #undef STRUCT_RTENTRY_HAS_RT_USE */ +/* #undef STRUCT_RTENTRY_HAS_RT_REFCNT */ +/* #undef STRUCT_RTENTRY_HAS_RT_HASH */ + +/* ifnet structure tests */ +/* #undef STRUCT_IFNET_HAS_IF_BAUDRATE */ +#define STRUCT_IFNET_HAS_IF_SPEED 1 +#define STRUCT_IFNET_HAS_IF_TYPE 1 +/* #undef STRUCT_IFNET_HAS_IF_IMCASTS */ +/* #undef STRUCT_IFNET_HAS_IF_IQDROPS */ +/* #undef STRUCT_IFNET_HAS_IF_LASTCHANGE_TV_SEC */ +/* #undef STRUCT_IFNET_HAS_IF_NOPROTO */ +/* #undef STRUCT_IFNET_HAS_IF_OMCASTS */ +/* #undef STRUCT_IFNET_HAS_IF_XNAME */ +#define STRUCT_IFNET_HAS_IF_OBYTES 1 +#define STRUCT_IFNET_HAS_IF_IBYTES 1 +/* #undef STRUCT_IFNET_HAS_IF_ADDRLIST */ + +/* tcpstat.tcps_rcvmemdrop */ +/* #undef STRUCT_TCPSTAT_HAS_TCPS_RCVMEMDROP */ + +/* udpstat.udps_discard */ +/* #undef STRUCT_UDPSTAT_HAS_UDPS_DISCARD */ + +/* arphd.at_next */ +/* #undef STRUCT_ARPHD_HAS_AT_NEXT */ + +/* ifaddr.ifa_next */ +#define STRUCT_IFADDR_HAS_IFA_NEXT 1 + +/* ifnet.if_mtu */ +/* #undef STRUCT_IFNET_HAS_IF_MTU */ + +/* swdevt.sw_nblksenabled */ +/* #undef STRUCT_SWDEVT_HAS_SW_NBLKSENABLED */ + +/* nlist.n_value */ +/* #undef STRUCT_NLIST_HAS_N_VALUE */ + +/* vfsstat.f_frsize */ +//#define STRUCT_STATVFS_HAS_F_FRSIZE 1 + +/* vfsstat.f_files */ +//#define STRUCT_STATVFS_HAS_F_FILES 1 + +/* ifnet needs to have _KERNEL defined */ +/* #undef IFNET_NEEDS_KERNEL */ + +/* sysctl works to get boottime, etc... */ +/* #undef CAN_USE_SYSCTL */ + +/* type check for in_addr_t */ +//#define in_addr_t u_int + +/* define if SIOCGIFADDR exists in sys/ioctl.h */ +#define SYS_IOCTL_H_HAS_SIOCGIFADDR 1 + +/* define if your compiler (processor) defines __FUNCTION__ for you */ +#define HAVE_CPP_UNDERBAR_FUNCTION_DEFINED 1 + +/* mib pointer to the top of the extensible tree. This has been + assigned to UCDavis by the iana group. Optionally, point this to the + location in the tree your company/organization has been allocated. */ + +/* location of the extensible mib tree */ +#define EXTENSIBLEMIB 1,3,6,1,4,1,2021 +/* location of the extensible mib tree */ +#define EXTENSIBLEDOTMIB 1.3.6.1.4.1.2021 +/* count the above numbers */ +#define EXTENSIBLENUM 7 + +/* Mib-2 tree Info */ +/* These are the system information variables. */ + +#ifdef CYGDAT_NET_SNMPAGENT_VERS_DESC +#define VERS_DESC CYGDAT_NET_SNMPAGENT_VERS_DESC +#else +#define VERS_DESC "unknown" /* overridden at run time */ +#endif + +#ifdef CYGDAT_NET_SNMPAGENT_SYS_NAME +#define SYS_NAME CYGDAT_NET_SNMPAGENT_SYS_NAME +#else +#define SYS_NAME "unknown" /* overridden at run time */ +#endif + +/* comment out the second define to turn off functionality for any of + these: (See README for details) */ + +/* proc PROCESSNAME [MAX] [MIN] */ +//#define PROCMIBNUM 2 + +/* exec/shell NAME COMMAND */ +//#define SHELLMIBNUM 8 + +/* swap MIN */ +//#define MEMMIBNUM 4 + +/* disk DISK MINSIZE */ +//#define DISKMIBNUM 9 + +/* load 1 5 15 */ +//#define LOADAVEMIBNUM 10 + +/* which version are you using? This mibloc will tell you */ +#define VERSIONMIBNUM 100 + +/* Reports errors the agent runs into */ +/* (typically its "can't fork, no mem" problems) */ +#define ERRORMIBNUM 101 + +/* The sub id of EXENSIBLEMIB returned to queries of + .iso.org.dod.internet.mgmt.mib-2.system.sysObjectID.0 */ +#define AGENTID 250 + +/* This ID is returned after the AGENTID above. IE, the resulting + value returned by a query to sysObjectID is + EXTENSIBLEMIB.AGENTID.???, where ??? is defined below by OSTYPE */ + +#define HPUX9ID 1 +#define SUNOS4ID 2 +#define SOLARISID 3 +#define OSFID 4 +#define ULTRIXID 5 +#define HPUX10ID 6 +#define NETBSD1ID 7 +#define FREEBSDID 8 +#define IRIXID 9 +#define LINUXID 10 +#define BSDIID 11 +#define OPENBSDID 12 +#define UNKNOWNID 255 + +#ifdef hpux9 +#define OSTYPE HPUX9ID +#endif +#ifdef hpux10 +#define OSTYPE HPUX10ID +#endif +#ifdef sunos4 +#define OSTYPE SUNOS4ID +#endif +#ifdef solaris2 +#define OSTYPE SOLARISID +#endif +#if defined(osf3) || defined(osf4) +#define OSTYPE OSFID +#endif +#ifdef ultrix4 +#define OSTYPE ULTRIXID +#endif +#ifdef netbsd1 +#define OSTYPE NETBSD1ID +#endif +#ifdef freebsd2 +#define OSTYPE FREEBSDID +#endif +#if defined(irix6) || defined(irix5) +#define OSTYPE IRIXID +#endif +#ifdef linux +#define OSTYPE LINUXID +#endif +#if defined(bsdi2) || defined(bsdi3) +#define OSTYPE BSDIID +#endif +#ifdef openbsd2 +#define OSTYPE OPENBSDID +#endif +/* unknown */ +#ifndef OSTYPE +#define OSTYPE UNKNOWNID +#endif + +/* how long to wait (seconds) for error querys before reseting the error trap.*/ +#define ERRORTIMELENGTH 600 + +/* Exec command to fix PROC problems */ +/* %s will be replaced by the process name in error */ + +/* #define PROCFIXCMD "/usr/bin/perl /local/scripts/fixproc %s" */ + +/* Exec command to fix EXEC problems */ +/* %s will be replaced by the exec/script name in error */ + +/* #define EXECFIXCMD "/usr/bin/perl /local/scripts/fixproc %s" */ + +/* Should exec output Cashing be used (speeds up things greatly), and + if so, After how many seconds should the cache re-newed? Note: + Don't define CASHETIME to disable cashing completely */ + +//#define EXCACHETIME 30 +#define CACHEFILE "/tmp/.snmp-exec-cache" +#define MAXCACHESIZE (200*80) /* roughly 200 lines max */ + +#define MAXDISKS 50 /* can't scan more than this number */ + +/* misc defaults */ + +/* default of 100 meg minimum if the minimum size is not specified in + the config file */ +#define DEFDISKMINIMUMSPACE 100000 + +#define DEFMAXLOADAVE 12.0 /* default maximum load average before error */ + +#define MAXREADCOUNT 100 /* max times to loop reading output from + execs. Because of sleep(1)s, this will also + be time to wait (in seconds) for exec to finish */ + +#define SNMPBLOCK 1 /* Set to 1 if you want snmpgets to block and never + timeout. Original CMU code had this + hardcoded into the code as = 1 */ + +#define RESTARTSLEEP 5 /* How long to wait after a snmpset to + EXTENSIBLEMIB.VERSIONMIBNUM.VERRESTARTAGENT + before restarting the agent. This is + necessary to finish the snmpset reply + before restarting. */ + +/* Number of community strings to store */ +#define NUM_COMMUNITIES 5 + +/* UNdefine to allow specifying zero-length community string */ +/* #define NO_ZEROLENGTH_COMMUNITY 1 */ + +/* #define EXIT_ON_BAD_KLREAD */ +/* define to exit the agent on a bad kernel read */ + +#define LASTFIELD -1 /* internal define */ + +/* configure options specified */ +#define CONFIGURE_OPTIONS "" + +#ifndef HAVE_STRCHR +#ifdef HAVE_INDEX +# define strchr index +# define strrchr rindex +#endif +#endif + +#ifndef HAVE_INDEX +#ifdef HAVE_STRCHR +# define index strchr +# define rindex strrchr +#endif +#endif + +#ifndef HAVE_MEMCPY +#ifdef HAVE_BCOPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# define memcmp bcmp +#endif +#endif + +#ifndef HAVE_MEMMOVE +#ifdef HAVE_MEMCPY +# define memmove memcpy +#endif +#endif + +#ifndef HAVE_BCOPY +#ifdef HAVE_MEMCPY +# define bcopy(s, d, n) memcpy ((d), (s), (n)) +# define bzero(p,n) memset((p),(0),(n)) +# define bcmp memcmp +#endif +#endif + + +/* define random functions */ + +#ifndef HAVE_RANDOM +#ifdef HAVE_LRAND48 +#define random lrand48 +#define srandom(s) srand48(s) +#else +#ifdef HAVE_RAND +#define random rand +#define srandom(s) srand(s) +#endif +#endif +#endif + +/* define signal if DNE */ + +#ifndef HAVE_SIGNAL +#ifdef HAVE_SIGSET +#define signal(a,b) sigset(a,b) +#endif +#endif + +/* define if you have librpm and libdb */ +#define HAVE_LIBDB 1 +#define HAVE_LIBRPM 1 + +/* define if you have gethostbyname */ +#define HAVE_GETHOSTBYNAME 1 + +/* define if you have getservbyname */ +#define HAVE_GETSERVBYNAME 1 + +/* Not-to-be-compiled macros for use by configure only */ +#define config_require(x) +#define config_arch_require(x,y) +#define config_parse_dot_conf(w,x,y,z) +#define config_add_mib(x) + +#ifdef WIN32 +#define ENV_SEPARATOR ";" +#define ENV_SEPARATOR_CHAR ';' +#else +#define ENV_SEPARATOR ":" +#define ENV_SEPARATOR_CHAR ':' +#endif + +//#include SYSTEM_INCLUDE_FILE +//#include MACHINE_INCLUDE_FILE + +#if defined(HAVE_NLIST) && defined(STRUCT_NLIST_HAS_N_VALUE) && !defined(DONT_USE_NLIST) +#define CAN_USE_NLIST +#endif + +/* #undef INET6 */ + +// Be rid of lots of warning because of use of #if instead of #ifdef: +#define HAVE_SYSLOG_H 0 +#define HAVE_WINSOCK_H 0 +#define HAVE_DMALLOC_H 0 +#define SNMP_TESTING_CODE 0 +#define HAVE_DIRENT_H 0 +#define HAVE_SYS_NDIR_H 0 +#define HAVE_SYS_DIR_H 0 +#define HAVE_NDIR_H 0 +#define HAVE_UNISTD_H 0 +#define HAVE_FCNTL_H 0 +#define HAVE_MALLOC_H 0 +#define HAVE_SYS_FILE_H 0 +#define HAVE_KSTAT_H 0 +#define HAVE_SYS_UN_H 0 +#define SOCK_MAXADDRLEN 0 +#define HAVE_SYS_STREAM_H 0 +#define HAVE_INET_MIB2_H 0 +#define HAVE_GETPID 0 +#define HAVE_FORK 0 + + + +#define ECOSFIXME_NEEDFILESYSTEM 1 + + + +#define __time_t_defined + +#include +#include +#include + + +#include + +#include + + + + diff --git a/packages/net/snmp/lib/current/include/default_store.h b/packages/net/snmp/lib/current/include/default_store.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/default_store.h @@ -0,0 +1,166 @@ +//========================================================================== +// +// ./lib/current/include/default_store.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* default_store.h: storage space for defaults */ +#ifndef DEFAULT_STORE_H +#define DEFAULT_STORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define DS_MAX_IDS 3 +#define DS_MAX_SUBIDS 32 /* needs to be a multiple of 8 */ + +/* begin storage definitions */ +/* These definitions correspond with the "storid" argument to the API */ +#define DS_LIBRARY_ID 0 +#define DS_APPLICATION_ID 1 +#define DS_TOKEN_ID 2 + +/* These definitions correspond with the "which" argument to the API, + when the storeid argument is DS_LIBRARY_ID */ +/* library booleans */ +#define DS_LIB_MIB_ERRORS 0 +#define DS_LIB_SAVE_MIB_DESCRS 1 +#define DS_LIB_MIB_COMMENT_TERM 2 +#define DS_LIB_MIB_PARSE_LABEL 3 +#define DS_LIB_DUMP_PACKET 4 +#define DS_LIB_LOG_TIMESTAMP 5 +#define DS_LIB_DONT_READ_CONFIGS 6 +#define DS_LIB_MIB_REPLACE 7 /* replace objects from latest module */ +#define DS_LIB_PRINT_NUMERIC_ENUM 8 /* print only numeric enum values */ +#define DS_LIB_PRINT_NUMERIC_OIDS 9 /* print only numeric enum values */ +#define DS_LIB_DONT_BREAKDOWN_OIDS 10 /* dont print oid indexes specially */ +#define DS_LIB_ALARM_DONT_USE_SIG 11 /* don't use the alarm() signal */ +#define DS_LIB_PRINT_FULL_OID 12 /* print fully qualified oids */ +#define DS_LIB_QUICK_PRINT 13 /* print very brief output for parsing */ +#define DS_LIB_RANDOM_ACCESS 14 /* random access to oid labels */ +#define DS_LIB_REGEX_ACCESS 15 /* regex matching to oid labels */ +#define DS_LIB_DONT_CHECK_RANGE 16 /* don't check values for ranges on send*/ +#define DS_LIB_NO_TOKEN_WARNINGS 17 /* no warn about unknown config tokens */ + +/* library integers */ +#define DS_LIB_MIB_WARNINGS 0 +#define DS_LIB_SECLEVEL 1 +#define DS_LIB_SNMPVERSION 2 +#define DS_LIB_DEFAULT_PORT 3 +#define DS_LIB_PRINT_SUFFIX_ONLY 4 /* print out only a single oid node == 1. + like #1 but supply mib module too == 2. */ + +/* library strings */ +#define DS_LIB_SECNAME 0 +#define DS_LIB_CONTEXT 1 +#define DS_LIB_PASSPHRASE 2 +#define DS_LIB_AUTHPASSPHRASE 3 +#define DS_LIB_PRIVPASSPHRASE 4 +#define DS_LIB_OPTIONALCONFIG 5 +#define DS_LIB_APPTYPE 6 +#define DS_LIB_COMMUNITY 7 + +/* end storage definitions */ + +struct ds_read_config { + u_char type; + char *token; + int storeid; + int which; + struct ds_read_config *next; +}; + +int ds_set_boolean(int storeid, int which, int value); +int ds_get_boolean(int storeid, int which); +int ds_toggle_boolean(int storeid, int which); +int ds_set_int(int storeid, int which, int value); +int ds_get_int(int storeid, int which); +int ds_set_string(int storeid, int which, const char *value); +char *ds_get_string(int storeid, int which); +int ds_register_config(u_char type, const char *ftype, const char *token, + int storeid, int which); +int ds_register_premib(u_char type, const char *ftype, const char *token, + int storeid, int which); + +#ifdef __cplusplus +} +#endif + +#endif /* DEFAULT_STORE_H */ diff --git a/packages/net/snmp/lib/current/include/int64.h b/packages/net/snmp/lib/current/include/int64.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/int64.h @@ -0,0 +1,109 @@ +//========================================================================== +// +// ./lib/current/include/int64.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef INT64_INCLUDED +#define INT64_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct counter64 U64; + +#define I64CHARSZ 21 + +void divBy10 (U64, U64 *, unsigned int *); +void multBy10 (U64, U64 *); +void incrByU16 (U64 *, unsigned int); +void incrByU32 (U64 *, unsigned int); +void zeroU64 (U64 *); +int isZeroU64 (U64 *); +void printU64 (char *, U64 *); +void printI64 (char *, U64 *); +int read64 (U64 *, const char *); +void u64Subtract(U64 *pu64one, U64 *pu64two, U64 *pu64out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packages/net/snmp/lib/current/include/keytools.h b/packages/net/snmp/lib/current/include/keytools.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/keytools.h @@ -0,0 +1,141 @@ +//========================================================================== +// +// ./lib/current/include/keytools.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * keytools.h + */ + +#ifndef _KEYTOOLS_H +#define _KEYTOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define USM_LENGTH_EXPANDED_PASSPHRASE (1024 * 1024) /* 1Meg. */ + +#define USM_LENGTH_KU_HASHBLOCK 64 /* In bytes. */ + +#define USM_LENGTH_P_MIN 8 /* In characters. */ + /* Recommended practice given in , + * Section 11.2 "Defining Users". Move into cmdline app argument + * parsing, and out of the internal routine? XXX + */ + +/* + * Prototypes.h + */ +int generate_Ku ( oid *hashtype, u_int hashtype_len, + u_char *P, size_t pplen, + u_char *Ku, size_t *kulen); + +int generate_kul ( oid *hashtype, u_int hashtype_len, + u_char *engineID, size_t engineID_len, + u_char *Ku, size_t ku_len, + u_char *Kul, size_t *kul_len); + +int encode_keychange ( oid *hashtype, u_int hashtype_len, + u_char *oldkey, size_t oldkey_len, + u_char *newkey, size_t newkey_len, + u_char *kcstring, size_t *kcstring_len); + +int decode_keychange ( oid *hashtype, u_int hashtype_len, + u_char *oldkey, size_t oldkey_len, + u_char *kcstring, size_t kcstring_len, + u_char *newkey, size_t *newkey_len); + + +/* + * All functions devolve to the following block if we can't do cryptography + */ +#define _KEYTOOLS_NOT_AVAILABLE \ +{ \ + return SNMPERR_KT_NOT_AVAILABLE; \ +} + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYTOOLS_H */ + diff --git a/packages/net/snmp/lib/current/include/lcd_time.h b/packages/net/snmp/lib/current/include/lcd_time.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/lcd_time.h @@ -0,0 +1,206 @@ +//========================================================================== +// +// ./lib/current/include/lcd_time.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * lcd_time.h + */ + +#ifndef _LCD_TIME_H +#define _LCD_TIME_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* undefine to enable time synchronization only on authenticated packets */ +#define LCD_TIME_SYNC_OPT 1 + +/* + * Macros and definitions. + */ +#define ETIMELIST_SIZE 23 + + + +typedef struct enginetime_struct { + u_char *engineID; + u_int engineID_len; + + u_int engineTime; + u_int engineBoot; + /* Time & boots values received from last authenticated + * message within the previous time window. + */ + + time_t lastReceivedEngineTime; + /* Timestamp made when engineTime/engineBoots was last + * updated. Measured in seconds. + */ + +#ifdef LCD_TIME_SYNC_OPT + u_int authenticatedFlag; +#endif + struct enginetime_struct *next; +} enginetime, *Enginetime; + + + + +/* + * Macros for streamlined engineID existence checks -- + * + * e is char *engineID, + * e_l is u_int engineID_len. + * + * + * ISENGINEKNOWN(e, e_l) + * Returns: + * TRUE If engineID is recoreded in the EngineID List; + * FALSE Otherwise. + * + * ENSURE_ENGINE_RECORD(e, e_l) + * Adds the given engineID to the EngineID List if it does not exist + * already. engineID is added with a + * tuple of <0,0>. ALWAYS succeeds -- except in case of a + * fatal internal error. + * Returns: + * SNMPERR_SUCCESS On success; + * SNMPERR_GENERR Otherwise. + * + * MAKENEW_ENGINE_RECORD(e, e_l) + * Returns: + * SNMPERR_SUCCESS If engineID already exists in the EngineID List; + * SNMPERR_GENERR Otherwise -and- invokes ENSURE_ENGINE_RECORD() + * to add an entry to the EngineID List. + * + * XXX Requres the following declaration in modules calling ISENGINEKNOWN(): + * static u_int dummy_etime, dummy_eboot; + */ +#define ISENGINEKNOWN(e, e_l) \ + ( (get_enginetime(e, e_l, \ + &dummy_eboot, &dummy_etime, TRUE) == SNMPERR_SUCCESS) \ + ? TRUE \ + : FALSE ) + +#define ENSURE_ENGINE_RECORD(e, e_l) \ + ( (set_enginetime(e, e_l, 0, 0, FALSE) == SNMPERR_SUCCESS) \ + ? SNMPERR_SUCCESS \ + : SNMPERR_GENERR ) + +#define MAKENEW_ENGINE_RECORD(e, e_l) \ + ( (ISENGINEKNOWN(e, e_l) == TRUE) \ + ? SNMPERR_SUCCESS \ + : (ENSURE_ENGINE_RECORD(e, e_l), SNMPERR_GENERR) ) + + + +/* + * Prototypes. + */ +int get_enginetime (u_char *engineID, u_int engineID_len, + u_int *engine_boot, u_int *engine_time, + u_int authenticated); + +int get_enginetime_ex (u_char *engineID, u_int engineID_len, + u_int *engine_boot, u_int *engine_time, + u_int *last_engine_time, + u_int authenticated); + +int set_enginetime (u_char *engineID, u_int engineID_len, + u_int engine_boot, u_int engine_time, + u_int authenticated); + +Enginetime + search_enginetime_list ( u_char *engineID, + u_int engineID_len); + +int hash_engineID (u_char *engineID, u_int engineID_len); + +void dump_etimelist_entry (Enginetime e, int count); +void dump_etimelist (void); + +#ifdef __cplusplus +} +#endif + +#endif /* _LCD_TIME_H */ diff --git a/packages/net/snmp/lib/current/include/md5.h b/packages/net/snmp/lib/current/include/md5.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/md5.h @@ -0,0 +1,148 @@ +//========================================================================== +// +// ./lib/current/include/md5.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* +** ************************************************************************** +** md5.h -- Header file for implementation of MD5 Message Digest Algorithm ** +** Updated: 2/13/90 by Ronald L. Rivest ** +** (C) 1990 RSA Data Security, Inc. ** +** ************************************************************************** +*/ + +#ifndef MD5_H +#define MD5_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* MDstruct is the data structure for a message digest computation. +*/ +typedef struct { + unsigned int buffer[4]; /* Holds 4-word result of MD computation */ + unsigned char count[8]; /* Number of bits processed so far */ + unsigned int done; /* Nonzero means MD computation finished */ +} MDstruct, *MDptr; + +/* MDbegin(MD) +** Input: MD -- an MDptr +** Initialize the MDstruct prepatory to doing a message digest computation. +*/ +extern void MDbegin (MDptr); + +/* MDupdate(MD,X,count) +** Input: MD -- an MDptr +** X -- a pointer to an array of unsigned characters. +** count -- the number of bits of X to use (an unsigned int). +** Updates MD using the first ``count'' bits of X. +** The array pointed to by X is not modified. +** If count is not a multiple of 8, MDupdate uses high bits of last byte. +** This is the basic input routine for a user. +** The routine terminates the MD computation when count < 512, so +** every MD computation should end with one call to MDupdate with a +** count less than 512. Zero is OK for a count. +*/ +extern int MDupdate (MDptr, unsigned char *, unsigned int); + +/* MDprint(MD) +** Input: MD -- an MDptr +** Prints message digest buffer MD as 32 hexadecimal digits. +** Order is from low-order byte of buffer[0] to high-order byte of buffer[3]. +** Each byte is printed with high-order hexadecimal digit first. +*/ +extern void MDprint (MDptr); + +int MDchecksum(u_char *data, size_t len, u_char *mac, size_t maclen); +int MDsign(u_char *data, size_t len, u_char *mac, size_t maclen, + u_char *secret, size_t secretlen); +void MDget(MDstruct *MD, u_char *buf, size_t buflen); + +/* +** End of md5.h +****************************(cut)*****************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* MD5_H */ + diff --git a/packages/net/snmp/lib/current/include/mib.h b/packages/net/snmp/lib/current/include/mib.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/mib.h @@ -0,0 +1,396 @@ +//========================================================================== +// +// ./lib/current/include/mib.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef MIB_H +#define MIB_H + +#ifdef __cplusplus +extern "C" { +#endif +/* + * mib.h - Definitions for the variables as defined in the MIB + * + * Update: 1998-07-17 + * Added prototypes for print_oid_report* functions. + */ +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#ifdef CMU_COMPATIBLE + +struct mib_system { + char sysDescr[32]; /* textual description */ + u_char sysObjectID[16];/* OBJECT IDENTIFIER of system */ + u_char ObjIDLen; /* length of sysObjectID */ + u_int sysUpTime; /* Uptime in 100/s of a second */ +}; + +struct mib_interface { + int ifNumber; /* number of interfaces */ +}; + +struct mib_ifEntry { + int ifIndex; /* index of this interface */ + char ifDescr[32]; /* english description of interface */ + int ifType; /* network type of device */ + int ifMtu; /* size of largest packet in bytes */ + u_int ifSpeed; /* bandwidth in bits/sec */ + u_char ifPhysAddress[11]; /* interface's address */ + u_char PhysAddrLen; /* length of physAddr */ + int ifAdminStatus; /* desired state of interface */ + int ifOperStatus; /* current operational status */ + u_int ifLastChange; /* value of sysUpTime when current state entered */ + u_int ifInOctets; /* number of octets received on interface */ + u_int ifInUcastPkts; /* number of unicast packets delivered */ + u_int ifInNUcastPkts; /* number of broadcasts or multicasts */ + u_int ifInDiscards; /* number of packets discarded with no error */ + u_int ifInErrors; /* number of packets containing errors */ + u_int ifInUnknownProtos; /* number of packets with unknown protocol */ + u_int ifOutOctets; /* number of octets transmitted */ + u_int ifOutUcastPkts; /* number of unicast packets sent */ + u_int ifOutNUcastPkts;/* number of broadcast or multicast pkts */ + u_int ifOutDiscards; /* number of packets discarded with no error */ + u_int ifOutErrors; /* number of pkts discarded with an error */ + u_int ifOutQLen; /* number of packets in output queue */ +}; + +struct mib_atEntry { + int atIfIndex; /* interface on which this entry maps */ + u_char atPhysAddress[11]; /* physical address of destination */ + u_char PhysAddressLen; /* length of atPhysAddress */ + u_int atNetAddress; /* IP address of physical address */ +}; + +struct mib_ip { + int ipForwarding; /* 1 if gateway, 2 if host */ + int ipDefaultTTL; /* default TTL for pkts originating here */ + u_int ipInReceives; /* no. of IP packets received from interfaces */ + u_int ipInHdrErrors; /* number of pkts discarded due to header errors */ + u_int ipInAddrErrors; /* no. of pkts discarded due to bad address */ + u_int ipForwDatagrams;/* number pf pkts forwarded through this entity */ + u_int ipInUnknownProtos;/* no. of local-addressed pkts w/unknown proto */ + u_int ipInDiscards; /* number of error-free packets discarded */ + u_int ipInDelivers; /* number of datagrams delivered to upper level */ + u_int ipOutRequests; /* number of IP datagrams originating locally */ + u_int ipOutDiscards; /* number of error-free output IP pkts discarded */ + u_int ipOutNoRoutes; /* number of IP pkts discarded due to no route */ + int ipReasmTimeout; /* seconds fragment is held awaiting reassembly */ + u_int ipReasmReqds; /* no. of fragments needing reassembly (here) */ + u_int ipReasmOKs; /* number of fragments reassembled */ + u_int ipReasmFails; /* number of failures in IP reassembly */ + u_int ipFragOKs; /* number of datagrams fragmented here */ + u_int ipFragFails; /* no. pkts unable to be fragmented here */ + u_int ipFragCreates; /* number of IP fragments created here */ +}; + +struct mib_ipAddrEntry { + u_int ipAdEntAddr; /* IP address of this entry */ + int ipAdEntIfIndex; /* IF for this entry */ + u_int ipAdEntNetMask; /* subnet mask of this entry */ + int ipAdEntBcastAddr;/* read the MIB for this one */ +}; + +struct mib_ipRouteEntry { + u_int ipRouteDest; /* destination IP addr for this route */ + int ipRouteIfIndex; /* index of local IF for this route */ + int ipRouteMetric1; /* Primary routing metric */ + int ipRouteMetric2; /* Alternate routing metric */ + int ipRouteMetric3; /* Alternate routing metric */ + int ipRouteMetric4; /* Alternate routing metric */ + u_int ipRouteNextHop; /* IP addr of next hop */ + int ipRouteType; /* Type of this route */ + int ipRouteProto; /* How this route was learned */ + int ipRouteAge; /* No. of seconds since updating this route */ +}; + +struct mib_icmp { + u_int icmpInMsgs; /* Total of ICMP msgs received */ + u_int icmpInErrors; /* Total of ICMP msgs received with errors */ + u_int icmpInDestUnreachs; + u_int icmpInTimeExcds; + u_int icmpInParmProbs; + u_int icmpInSrcQuenchs; + u_int icmpInRedirects; + u_int icmpInEchos; + u_int icmpInEchoReps; + u_int icmpInTimestamps; + u_int icmpInTimestampReps; + u_int icmpInAddrMasks; + u_int icmpInAddrMaskReps; + u_int icmpOutMsgs; + u_int icmpOutErrors; + u_int icmpOutDestUnreachs; + u_int icmpOutTimeExcds; + u_int icmpOutParmProbs; + u_int icmpOutSrcQuenchs; + u_int icmpOutRedirects; + u_int icmpOutEchos; + u_int icmpOutEchoReps; + u_int icmpOutTimestamps; + u_int icmpOutTimestampReps; + u_int icmpOutAddrMasks; + u_int icmpOutAddrMaskReps; +}; + +struct mib_tcp { + int tcpRtoAlgorithm; /* retransmission timeout algorithm */ + int tcpRtoMin; /* minimum retransmission timeout (mS) */ + int tcpRtoMax; /* maximum retransmission timeout (mS) */ + int tcpMaxConn; /* maximum tcp connections possible */ + u_int tcpActiveOpens; /* number of SYN-SENT -> CLOSED transitions */ + u_int tcpPassiveOpens; /* number of SYN-RCVD -> LISTEN transitions */ + u_int tcpAttemptFails;/*(SYN-SENT,SYN-RCVD)->CLOSED or SYN-RCVD->LISTEN*/ + u_int tcpEstabResets; /* (ESTABLISHED,CLOSE-WAIT) -> CLOSED */ + u_int tcpCurrEstab; /* number in ESTABLISHED or CLOSE-WAIT state */ + u_int tcpInSegs; /* number of segments received */ + u_int tcpOutSegs; /* number of segments sent */ + u_int tcpRetransSegs; /* number of retransmitted segments */ +}; + +struct mib_tcpConnEntry { + int tcpConnState; /* State of this connection */ + u_int tcpConnLocalAddress;/* local IP address for this connection */ + int tcpConnLocalPort; /* local port for this connection */ + u_int tcpConnRemAddress; /* remote IP address for this connection */ + int tcpConnRemPort; /* remote port for this connection */ +}; + +struct mib_udp { + u_int udpInDatagrams; /* No. of UDP datagrams delivered to users */ + u_int udpNoPorts; /* No. of UDP datagrams to port with no listener */ + u_int udpInErrors; /* No. of UDP datagrams unable to be delivered */ + u_int udpOutDatagrams;/* No. of UDP datagrams sent from this entity */ +}; + +struct mib_egp { + u_int egpInMsgs; /* No. of EGP msgs received without error */ + u_int egpInErrors;/* No. of EGP msgs received with error */ + u_int egpOutMsgs; /* No. of EGP msgs sent */ + u_int egpOutErrors;/* No. of (outgoing) EGP msgs dropped due to error */ +}; + +struct mib_egpNeighEntry { + int egpNeighState; /* local EGP state with this entry's neighbor */ + u_int egpNeighAddr; /* IP address of this entry's neighbor */ +}; + +#endif /* CMU_COMPATIBLE */ + +#define MIB 1, 3, 6, 1, 2, 1 + +#define MIB_IFTYPE_OTHER 1 +#define MIB_IFTYPE_REGULAR1822 2 +#define MIB_IFTYPE_HDH1822 3 +#define MIB_IFTYPE_DDNX25 4 +#define MIB_IFTYPE_RFC877X25 5 +#define MIB_IFTYPE_ETHERNETCSMACD 6 +#define MIB_IFTYPE_ISO88023CSMACD 7 +#define MIB_IFTYPE_ISO88024TOKENBUS 8 +#define MIB_IFTYPE_ISO88025TOKENRING 9 +#define MIB_IFTYPE_ISO88026MAN 10 +#define MIB_IFTYPE_STARLAN 11 +#define MIB_IFTYPE_PROTEON10MBIT 12 +#define MIB_IFTYPE_PROTEON80MBIT 13 +#define MIB_IFTYPE_HYPERCHANNEL 14 +#define MIB_IFTYPE_FDDI 15 +#define MIB_IFTYPE_LAPB 16 +#define MIB_IFTYPE_SDLC 17 +#define MIB_IFTYPE_T1CARRIER 18 +#define MIB_IFTYPE_CEPT 19 +#define MIB_IFTYPE_BASICISDN 20 +#define MIB_IFTYPE_PRIMARYISDN 21 +#define MIB_IFTYPE_PROPPOINTTOPOINTSERIAL 22 + +#define MIB_IFSTATUS_UP 1 +#define MIB_IFSTATUS_DOWN 2 +#define MIB_IFSTATUS_TESTING 3 + +#define MIB_FORWARD_GATEWAY 1 +#define MIB_FORWARD_HOST 2 + +#define MIB_IPROUTETYPE_OTHER 1 +#define MIB_IPROUTETYPE_INVALID 2 +#define MIB_IPROUTETYPE_DIRECT 3 +#define MIB_IPROUTETYPE_REMOTE 4 + +#define MIB_IPROUTEPROTO_OTHER 1 +#define MIB_IPROUTEPROTO_LOCAL 2 +#define MIB_IPROUTEPROTO_NETMGMT 3 +#define MIB_IPROUTEPROTO_ICMP 4 +#define MIB_IPROUTEPROTO_EGP 5 +#define MIB_IPROUTEPROTO_GGP 6 +#define MIB_IPROUTEPROTO_HELLO 7 +#define MIB_IPROUTEPROTO_RIP 8 +#define MIB_IPROUTEPROTO_ISIS 9 +#define MIB_IPROUTEPROTO_ESIS 10 +#define MIB_IPROUTEPROTO_CISCOIGRP 11 +#define MIB_IPROUTEPROTO_BBNSPFIGP 12 +#define MIB_IPROUTEPROTO_OIGP 13 + +#define MIB_TCPRTOALG_OTHER 1 +#define MIB_TCPRTOALG_CONSTANT 2 +#define MIB_TCPRTOALG_RSRE 3 +#define MIB_TCPRTOALG_VANJ 4 + +#define MIB_TCPCONNSTATE_CLOSED 1 +#define MIB_TCPCONNSTATE_LISTEN 2 +#define MIB_TCPCONNSTATE_SYNSENT 3 +#define MIB_TCPCONNSTATE_SYNRECEIVED 4 +#define MIB_TCPCONNSTATE_ESTABLISHED 5 +#define MIB_TCPCONNSTATE_FINWAIT1 6 +#define MIB_TCPCONNSTATE_FINWAIT2 7 +#define MIB_TCPCONNSTATE_CLOSEWAIT 8 +#define MIB_TCPCONNSTATE_LASTACK 9 +#define MIB_TCPCONNSTATE_CLOSING 10 +#define MIB_TCPCONNSTATE_TIMEWAIT 11 + +#define MIB_EGPNEIGHSTATE_IDLE 1 +#define MIB_EGPNEIGHSTATE_AQUISITION 2 +#define MIB_EGPNEIGHSTATE_DOWN 3 +#define MIB_EGPNEIGHSTATE_UP 4 +#define MIB_EGPNEIGHSTATE_CEASE 5 + +struct variable_list; + +void print_mib (FILE *); +void print_ascii_dump (FILE *); +int read_objid (const char *, oid *, size_t *); +void register_mib_handlers (void); +void init_mib (void); +void print_variable (oid *, size_t, struct variable_list *); +void fprint_variable (FILE *, oid *, size_t, struct variable_list *); +void sprint_variable (char *, oid *, size_t, struct variable_list *); +void print_value (oid *, size_t, struct variable_list *); +void fprint_value (FILE *, oid *, size_t, struct variable_list *); +void sprint_value (char *, oid *, size_t, struct variable_list *); +void print_objid (oid *, size_t); +void fprint_objid (FILE *, oid *, size_t); +char *sprint_objid (char *, oid *, size_t); +void print_description (oid *, size_t); +void fprint_description (FILE *, oid *, size_t); +int get_module_node (const char *, const char *, oid *, size_t *); +int get_wild_node(const char *, oid *, size_t *); +int get_node (const char *, oid *, size_t *); +struct tree *get_symbol (oid *, size_t, struct tree *, char *); +struct tree *get_tree (oid *, size_t, struct tree *); +struct tree *get_tree_head (void); +void set_function (struct tree *); +void sprint_hexstring (char *, const u_char *, size_t); +void sprint_asciistring(char *buf, u_char *cp, size_t len); + +void print_oid_report (FILE *); +void print_oid_report_enable_labeledoid (void); +void print_oid_report_enable_oid (void); +void print_oid_report_enable_suffix (void); +void print_oid_report_enable_symbolic (void); + +void clear_tree_flags(register struct tree *tp); + +char *snmp_out_toggle_options(char *); +void snmp_out_toggle_options_usage(const char *, FILE *); +char *snmp_in_toggle_options(char *); +void snmp_in_toggle_options_usage(const char *, FILE *); + +#ifdef __cplusplus +} +#endif + +#endif /* MIB_H */ diff --git a/packages/net/snmp/lib/current/include/mt_support.h b/packages/net/snmp/lib/current/include/mt_support.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/mt_support.h @@ -0,0 +1,162 @@ +//========================================================================== +// +// ./lib/current/include/mt_support.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ + +/* mt_support.h - multi-thread resource locking support declarations */ +/* + * Author: Markku Laukkanen + * Created: 6-Sep-1999 + * History: + * 8-Sep-1999 M. Slifcak method names changed; + * use array of resource locking structures. + */ + +#ifndef MT_SUPPORT_H +#define MT_SUPPORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Lock group identifiers */ + +#define MT_LIBRARY_ID 0 +#define MT_APPLICATION_ID 1 +#define MT_TOKEN_ID 2 + +#define MT_MAX_IDS 3 /* one greater than last from above */ +#define MT_MAX_SUBIDS 10 + + +/* Lock resource identifiers for library resources */ + +#define MT_LIB_NONE 0 +#define MT_LIB_SESSION 1 +#define MT_LIB_REQUESTID 2 +#define MT_LIB_MESSAGEID 3 +#define MT_LIB_SESSIONID 4 +#define MT_LIB_TRANSID 5 + +#define MT_LIB_MAXIMUM 6 /* must be one greater than the last one */ + + +#ifdef _REENTRANT + +#if HAVE_PTHREAD_H + +#include +typedef pthread_mutex_t mutex_type; +#ifdef pthread_mutexattr_default + #define MT_MUTEX_INIT_DEFAULT pthread_mutexattr_default +#else + #define MT_MUTEX_INIT_DEFAULT 0 +#endif + +#elif defined(WIN32) || defined(cygwin) + +#include +typedef CRITICAL_SECTION mutex_type; + +#else + error "There is no re-entrant support as defined." +#endif + +int snmp_res_init(void); +int snmp_res_lock(int groupID, int resourceID); +int snmp_res_unlock(int groupID, int resourceID); +int snmp_res_destroy_mutex(int groupID, int resourceID); + +#else /* !_REENTRANT */ + +#define snmp_res_init() do {} while (0) +#define snmp_res_lock(x,y) do {} while (0) +#define snmp_res_unlock(x,y) do {} while (0) +#define snmp_res_destroy_mutex(x,y) do {} while (0) + +#endif /* !_REENTRANT */ + +#ifdef __cplusplus +} +#endif + +#endif /* MT_SUPPORT_H */ + diff --git a/packages/net/snmp/lib/current/include/parse.h b/packages/net/snmp/lib/current/include/parse.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/parse.h @@ -0,0 +1,306 @@ +//========================================================================== +// +// ./lib/current/include/parse.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef PARSE_H +#define PARSE_H + +#ifdef __cplusplus +extern "C" { +#endif +/* + * parse.h + */ +/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#define MAXLABEL 64 /* maximum characters in a label */ +#define MAXTOKEN 128 /* maximum characters in a token */ +#define MAXQUOTESTR 4096 /* maximum characters in a quoted string */ + +struct variable_list; + +/* + * A linked list of tag-value pairs for enumerated integers. + */ +struct enum_list { + struct enum_list *next; + int value; + char *label; +}; + +/* + * A linked list of ranges + */ +struct range_list { + struct range_list *next; + int low, high; +}; + +/* + * A linked list of indexes + */ +struct index_list { + struct index_list *next; + char *ilabel; + char isimplied; +}; + +/* + * A linked list of nodes. + */ +struct node { + struct node *next; + char *label; /* This node's (unique) textual name */ + u_long subid; /* This node's integer subidentifier */ + int modid; /* The module containing this node */ + char *parent; /* The parent's textual name */ + int tc_index; /* index into tclist (-1 if NA) */ + int type; /* The type of object this represents */ + int access; + int status; + struct enum_list *enums; /* (optional) list of enumerated integers */ + struct range_list *ranges; + struct index_list *indexes; + char *hint; + char *units; + char *description; /* description (a quoted string) */ +}; + +/* + * A tree in the format of the tree structure of the MIB. + */ +struct tree { + struct tree *child_list; /* list of children of this node */ + struct tree *next_peer; /* Next node in list of peers */ + struct tree *next; /* Next node in hashed list of names */ + struct tree *parent; + char *label; /* This node's textual name */ + u_long subid; /* This node's integer subidentifier */ + int modid; /* The module containing this node */ + int number_modules; + int *module_list; /* To handle multiple modules */ + int tc_index; /* index into tclist (-1 if NA) */ + int type; /* This node's object type */ + int access; /* This nodes access */ + int status; /* This nodes status */ + struct enum_list *enums; /* (optional) list of enumerated integers */ + struct range_list *ranges; + struct index_list *indexes; + char *hint; + char *units; + void (*printer) (char *, struct variable_list *, struct enum_list *, + const char *, const char *); /* Value printing function */ + char *description; /* description (a quoted string) */ + int reported; /* 1=report started in print_subtree... */ +}; + +/* + * Information held about each MIB module + */ +struct module_import { + char *label; /* The descriptor being imported */ + int modid; /* The module imported from */ +}; + +struct module { + char *name; /* This module's name */ + char *file; /* The file containing the module */ + struct module_import *imports; /* List of descriptors being imported */ + int no_imports; /* The number of such import descriptors */ + /* -1 implies the module hasn't been read in yet */ + int modid; /* The index number of this module */ + struct module *next; /* Linked list pointer */ +}; + +struct module_compatability { + const char *old_module; + const char *new_module; + const char *tag; /* NULL implies unconditional replacement, + otherwise node identifier or prefix */ + size_t tag_len; /* 0 implies exact match (or unconditional) */ + struct module_compatability *next; /* linked list */ +}; + + +/* non-aggregate types for tree end nodes */ +#define TYPE_OTHER 0 +#define TYPE_OBJID 1 +#define TYPE_OCTETSTR 2 +#define TYPE_INTEGER 3 +#define TYPE_NETADDR 4 +#define TYPE_IPADDR 5 +#define TYPE_COUNTER 6 +#define TYPE_GAUGE 7 +#define TYPE_TIMETICKS 8 +#define TYPE_OPAQUE 9 +#define TYPE_NULL 10 +#define TYPE_COUNTER64 11 +#define TYPE_BITSTRING 12 +#define TYPE_NSAPADDRESS 13 +#define TYPE_UINTEGER 14 + +#define MIB_ACCESS_READONLY 18 +#define MIB_ACCESS_READWRITE 19 +#define MIB_ACCESS_WRITEONLY 20 +#define MIB_ACCESS_NOACCESS 21 +#define MIB_ACCESS_NOTIFY 67 +#define MIB_ACCESS_CREATE 48 + +#define MIB_STATUS_MANDATORY 23 +#define MIB_STATUS_OPTIONAL 24 +#define MIB_STATUS_OBSOLETE 25 +#define MIB_STATUS_DEPRECATED 39 +#define MIB_STATUS_CURRENT 57 + +#ifdef CMU_COMPATIBLE +#define ACCESS_READONLY MIB_ACCESS_READONLY +#define ACCESS_READWRITE MIB_ACCESS_READWRITE +#define ACCESS_WRITEONLY MIB_ACCESS_WRITEONLY +#define ACCESS_NOACCESS MIB_ACCESS_NOACCESS +#define ACCESS_NOTIFY MIB_ACCESS_NOTIFY +#define ACCESS_CREATE MIB_ACCESS_CREATE +#define STATUS_MANDATORY MIB_STATUS_MANDATORY +#define STATUS_OPTIONAL MIB_STATUS_OPTIONAL +#define STATUS_OBSOLETE MIB_STATUS_OBSOLETE +#define STATUS_DEPRECATED MIB_STATUS_DEPRECATED +#define STATUS_CURRENT MIB_STATUS_CURRENT +#endif /* CMU_COMPATIBLE */ + +#define ANON "anonymous#" +#define ANON_LEN strlen(ANON) + +struct tree *read_module (const char *); +struct tree *read_mib (const char *); +struct tree *read_all_mibs (void); +int unload_module(const char *name); +void init_mib_internals (void); +int add_mibdir (const char *); +void add_module_replacement (const char *, const char *, const char *, int); +int which_module (const char *); +char *module_name (int, char *); +void print_subtree (FILE *, struct tree *, int); +void print_ascii_dump_tree (FILE *, struct tree *, int); +struct tree *find_tree_node (const char *, int); +const char *get_tc_descriptor (int); +struct tree *find_best_tree_node(const char *, struct tree *, u_int *); + /* backwards compatability */ +struct tree *find_node (const char *, struct tree*); +struct module *find_module (int); +void adopt_orphans (void); +void snmp_set_mib_warnings (int); +void snmp_set_mib_errors (int); +void snmp_set_save_descriptions (int); +void snmp_set_mib_comment_term (int); +void snmp_set_mib_parse_label (int); +char *snmp_mib_toggle_options(char *options); +void snmp_mib_toggle_options_usage(const char *lead, FILE *outf); +void print_mib(FILE *); +void print_mib_tree(FILE *, struct tree *, int); +int get_mib_parse_error_count(void); +int snmp_get_token(FILE *fp, char *token, int maxtlen); +struct tree * +find_best_tree_node(const char *name, struct tree *tree_top, u_int *match); + +#ifdef __cplusplus +} +#endif + +#endif /* PARSE_H */ diff --git a/packages/net/snmp/lib/current/include/read_config.h b/packages/net/snmp/lib/current/include/read_config.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/read_config.h @@ -0,0 +1,168 @@ +//========================================================================== +// +// ./lib/current/include/read_config.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * read_config.h: reads configuration files for extensible sections. + * + */ +#ifndef READ_CONFIG_H +#define READ_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define STRINGMAX 1024 + +#define NORMAL_CONFIG 0 +#define PREMIB_CONFIG 1 +#define EITHER_CONFIG 2 + + + +/* + * Defines a set of file types and the parse and free functions + * which process the syntax following a given token in a given file. + */ +struct config_files { + char *fileHeader; /* Label for entire file. */ + struct config_line *start; + struct config_files *next; +}; + +struct config_line { + char *config_token; /* Label for each line parser + in the given file. */ + void (*parse_line) (const char *, char *); + void (*free_func) (void); + struct config_line *next; + char config_time; /* {NORMAL,PREMIB,EITHER}_CONFIG */ + char *help; +}; + +void read_config (const char *, struct config_line *, int); +void read_configs (void); +void read_premib_configs (void); +void read_config_files (int); +void free_config (void); +void config_perror (const char *); +void config_pwarn (const char *); +char *skip_white (char *); +char *skip_not_white (char *); +char *skip_token(char *); +char *copy_word (char *, char *); +void read_config_with_type (const char *, const char *); +struct config_line *register_config_handler (const char *, const char *, + void (*parser)(const char *, char *), + void (*releaser) (void), + const char *); +struct config_line *register_app_config_handler (const char *, + void (*parser)(const char *, char *), + void (*releaser) (void), + const char *); +struct config_line *register_premib_handler (const char *, const char *, + void (*parser)(const char *, char *), + void (*releaser) (void), + const char *); +struct config_line *register_app_premib_handler (const char *, + void (*parser)(const char *, char *), + void (*releaser) (void), + const char *); +void unregister_config_handler (const char *, const char *); +void unregister_app_config_handler (const char *); +void read_config_print_usage(const char *lead); +char *read_config_save_octet_string(char *saveto, u_char *str, size_t len); +char *read_config_read_octet_string(char *readfrom, u_char **str, size_t *len); +char *read_config_read_objid(char *readfrom, oid **objid, size_t *len); +char *read_config_save_objid(char *saveto, oid *objid, size_t len); +char *read_config_read_data(int type, char *readfrom, void *dataptr, size_t *len); +char *read_config_store_data(int type, char *storeto, void *dataptr, size_t *len); +void read_config_store(const char *type, const char *line); +void read_app_config_store(const char *line); +void snmp_save_persistent(const char *type); +void snmp_clean_persistent(const char *type); + +#ifdef __cplusplus +} +#endif + +#endif /* READ_CONFIG_H */ diff --git a/packages/net/snmp/lib/current/include/scapi.h b/packages/net/snmp/lib/current/include/scapi.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/scapi.h @@ -0,0 +1,170 @@ +//========================================================================== +// +// ./lib/current/include/scapi.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * scapi.h + */ + +#ifndef _SCAPI_H +#define _SCAPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Authentication/privacy transform bitlengths. + */ +#define SNMP_TRANS_AUTHLEN_HMACMD5 128 +#define SNMP_TRANS_AUTHLEN_HMACSHA1 160 + +#define SNMP_TRANS_AUTHLEN_HMAC96 96 + +#define SNMP_TRANS_PRIVLEN_1DES 64 +#define SNMP_TRANS_PRIVLEN_1DES_IV 64 + + + +/* + * Prototypes. + */ +int sc_get_properlength(oid *hashtype, u_int hashtype_len); + +int sc_init (void); +int sc_shutdown (int majorID, int minorID, void *serverarg, + void *clientarg); + +int sc_random ( u_char *buf, size_t *buflen); + +int sc_generate_keyed_hash ( + oid *authtype, size_t authtypelen, + u_char *key, u_int keylen, + u_char *message, u_int msglen, + u_char *MAC, size_t *maclen); + +int sc_check_keyed_hash ( + oid *authtype, size_t authtypelen, + u_char *key, u_int keylen, + u_char *message, u_int msglen, + u_char *MAC, u_int maclen); + +int sc_encrypt ( oid *privtype, size_t privtypelen, + u_char *key, u_int keylen, + u_char *iv, u_int ivlen, + u_char *plaintext, u_int ptlen, + u_char *ciphertext, size_t *ctlen); + +int sc_decrypt ( oid *privtype, size_t privtypelen, + u_char *key, u_int keylen, + u_char *iv, u_int ivlen, + u_char *ciphertext, u_int ctlen, + u_char *plaintext, size_t *ptlen); + +int sc_hash(oid *hashtype, size_t hashtypelen, u_char *buf, size_t buf_len, + u_char *MAC, size_t *MAC_len); + +int sc_get_transform_type(oid *hashtype, u_int hashtype_len, + int (**hash_fn)( + const int mode, void **context, + const u_char *data, const int data_len, + u_char **digest, size_t *digest_len)); + + +/* + * All functions devolve to the following block if we can't do cryptography + */ +#define _SCAPI_NOT_CONFIGURED \ +{ \ + DEBUGPL(("SCAPI not configured"); \ + return SNMPERR_SC_NOT_CONFIGURED; \ +} + +/* define a transform type if we're using the internal md5 support */ +#ifdef USE_INTERNAL_MD5 +#define INTERNAL_MD5 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _SCAPI_H */ diff --git a/packages/net/snmp/lib/current/include/snmp-tc.h b/packages/net/snmp/lib/current/include/snmp-tc.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp-tc.h @@ -0,0 +1,115 @@ +//========================================================================== +// +// ./lib/current/include/snmp-tc.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_TC_H +#define SNMP_TC_H + +#ifdef __cplusplus +extern "C" { +#endif +/* snmp-tc.h: Provide some standard #defines for Textual Convention + related value information */ + +/* TrueValue */ +#define TV_TRUE 1 +#define TV_FALSE 2 + +/* RowStatus */ +#define RS_ACTIVE 1 +#define RS_NOTINSERVICE 2 +#define RS_NOTREADY 3 +#define RS_CREATEANDGO 4 +#define RS_CREATEANDWAIT 5 +#define RS_DESTROY 6 + +/* StorageType */ +#define ST_OTHER 1 +#define ST_VOLATILE 2 +#define ST_NONVOLATILE 3 +#define ST_PERMANENT 4 +#define ST_READONLY 5 + +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_TC_H */ diff --git a/packages/net/snmp/lib/current/include/snmp.h b/packages/net/snmp/lib/current/include/snmp.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp.h @@ -0,0 +1,377 @@ +//========================================================================== +// +// ./lib/current/include/snmp.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_H +#define SNMP_H + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Definitions for the Simple Network Management Protocol (RFC 1067). + * + * + */ +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + + +#define SNMP_PORT 161 /* standard UDP port for SNMP agents + to receive requests messages */ +#define SNMP_TRAP_PORT 162 /* standard UDP port for SNMP + managers to receive notificaion + (trap and inform) messages */ + +#define SNMP_MAX_LEN 1500 /* typical maximum message size */ +#define SNMP_MIN_MAX_LEN 484 /* minimum maximum message size */ + +/* SNMP versions */ +/* There currently exists the following SNMP versions. + * (Note that only SNMPv1 is in widespread usage, and this code supports + * only SNMPv1, SNMPv2c, and SNMPv3. + * + * SNMPv1 - (full) the original version, defined by RFC 1157 + * SNMPsec - (historic) the first attempt to add strong security + * to SNMPv1, defined by RFCs 1351, 1352, and 1353. + * SNMPv2p - (historic) party-based SNMP, which was another + * attempt to add strong security to SNMP, defined + * by RFCs 1441, 1445, 1446, 1448, and 1449. + * SNMPv2c - (experimental) community string-based SNMPv2, + * which was an attempt to combine the protocol + * operations of SNMPv2 with the security of + * SNMPv1, defined by RFCs 1901, 1905, and 1906. + * SNMPv2u - (experimental) user-based SNMPv2, which provided + * security based on user names and protocol + * operations of SNMPv2, defined by RFCs 1905, + * 1909, and 1910. + * SNMPv2* (or SNMPv2star) - (experimental) an attempt to add the + * best features of SNMPv2p and SNMPv2u, defined + * by unpublished documents found at WEB site + * owned by SNMP Research (a leading SNMP vendor) + * SNMPv3 - the current attempt by the IETF working group to merge + * the SNMPv2u and SNMPv2* proposals into a more widly + * accepted SNMPv3. It is defined by not yet published + * documents of the IETF SNMPv3 WG. + * + * SNMPv1, SNMPv2c, SNMPv2u, and SNMPv3 messages have a common + * form, which is an ASN.1 sequence containing a message version + * field, followed by version dependent fields. + * SNMPsec, SNMPv2p, and SNMPv2* messages have a common form, + * which is a tagged ASN.1 context specific sequence containing + * message dependent fields. + * + * In the #defines for the message versions below, the value + * for SNMPv1, SNMPv2c, SNMPv2u, and SNMPv3 messages is the + * value of the message version field. Since SNMPsec, SNMPv2p, + * and SNMPv2* messages do not have a message version field, + * the value in the defines for them is choosen to be a large + * arbitrary number. + * + * Note that many of the version ID's are defined below purely for + * documentational purposes. At this point the only protocol planned + * for future implementations is SNMP3, as the other v2 protocols will + * not be supported by the IETF (ie, v2u, v2sec, v2star) or used by + * the snmp community at large (at the time of this writing). */ + +/* versions based on version field */ +#define SNMP_VERSION_1 0 +#define SNMP_VERSION_2c 1 +#define SNMP_VERSION_2u 2 /* not (will never be) supported by this code */ +#define SNMP_VERSION_3 3 + +/* versions not based on a version field */ +#define SNMP_VERSION_sec 128 /* not (will never be) supported by this code */ +#define SNMP_VERSION_2p 129 +#define SNMP_VERSION_2star 130 /* not (will never be) supported by this code */ + +/* PDU types in SNMPv1, SNMPsec, SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 */ +#define SNMP_MSG_GET (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x0) +#define SNMP_MSG_GETNEXT (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x1) +#define SNMP_MSG_RESPONSE (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x2) +#define SNMP_MSG_SET (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x3) + +/* PDU types in SNMPv1 and SNMPsec */ +#define SNMP_MSG_TRAP (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x4) + +/* PDU types in SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 */ +#define SNMP_MSG_GETBULK (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x5) +#define SNMP_MSG_INFORM (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x6) +#define SNMP_MSG_TRAP2 (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x7) + +/* PDU types in SNMPv2u, SNMPv2*, and SNMPv3 */ +#define SNMP_MSG_REPORT (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x8) + +/* test for member of Confirmed Class i.e., reportable */ +#define SNMP_CMD_CONFIRMED(c) (c == SNMP_MSG_INFORM || c == SNMP_MSG_GETBULK ||\ + c == SNMP_MSG_GETNEXT || c == SNMP_MSG_GET || \ + c == SNMP_MSG_SET) + +/* Exception values for SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 */ +#define SNMP_NOSUCHOBJECT (ASN_CONTEXT | ASN_PRIMITIVE | 0x0) +#define SNMP_NOSUCHINSTANCE (ASN_CONTEXT | ASN_PRIMITIVE | 0x1) +#define SNMP_ENDOFMIBVIEW (ASN_CONTEXT | ASN_PRIMITIVE | 0x2) + +/* Error codes (the value of the field error-status in PDUs) */ + +/* in SNMPv1, SNMPsec, SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 PDUs */ +#define SNMP_ERR_NOERROR (0) /* XXX Used only for PDUs? */ +#define SNMP_ERR_TOOBIG (1) +#define SNMP_ERR_NOSUCHNAME (2) +#define SNMP_ERR_BADVALUE (3) +#define SNMP_ERR_READONLY (4) +#define SNMP_ERR_GENERR (5) + +/* in SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 PDUs */ +#define SNMP_ERR_NOACCESS (6) +#define SNMP_ERR_WRONGTYPE (7) +#define SNMP_ERR_WRONGLENGTH (8) +#define SNMP_ERR_WRONGENCODING (9) +#define SNMP_ERR_WRONGVALUE (10) +#define SNMP_ERR_NOCREATION (11) +#define SNMP_ERR_INCONSISTENTVALUE (12) +#define SNMP_ERR_RESOURCEUNAVAILABLE (13) +#define SNMP_ERR_COMMITFAILED (14) +#define SNMP_ERR_UNDOFAILED (15) +#define SNMP_ERR_AUTHORIZATIONERROR (16) +#define SNMP_ERR_NOTWRITABLE (17) + +/* in SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 PDUs */ +#define SNMP_ERR_INCONSISTENTNAME (18) + +#define MAX_SNMP_ERR 18 + + +/* values of the generic-trap field in trap PDUs */ +#define SNMP_TRAP_COLDSTART (0) +#define SNMP_TRAP_WARMSTART (1) +#define SNMP_TRAP_LINKDOWN (2) +#define SNMP_TRAP_LINKUP (3) +#define SNMP_TRAP_AUTHFAIL (4) +#define SNMP_TRAP_EGPNEIGHBORLOSS (5) +#define SNMP_TRAP_ENTERPRISESPECIFIC (6) + +/* row status values */ +#define SNMP_ROW_NONEXISTENT 0 +#define SNMP_ROW_ACTIVE 1 +#define SNMP_ROW_NOTINSERVICE 2 +#define SNMP_ROW_NOTREADY 3 +#define SNMP_ROW_CREATEANDGO 4 +#define SNMP_ROW_CREATEANDWAIT 5 +#define SNMP_ROW_DESTROY 6 + +/* row storage values */ +#define SNMP_STORAGE_OTHER 1 +#define SNMP_STORAGE_VOLATILE 2 +#define SNMP_STORAGE_NONVOLATILE 3 +#define SNMP_STORAGE_PERMANENT 4 +#define SNMP_STORAGE_READONLY 5 + +/* message processing models */ +#define SNMP_MP_MODEL_SNMPv1 0 +#define SNMP_MP_MODEL_SNMPv2c 1 +#define SNMP_MP_MODEL_SNMPv2u 2 +#define SNMP_MP_MODEL_SNMPv3 3 +#define SNMP_MP_MODEL_SNMPv2p 256 + +/* security values */ +#define SNMP_SEC_MODEL_ANY 0 +#define SNMP_SEC_MODEL_SNMPv1 1 +#define SNMP_SEC_MODEL_SNMPv2c 2 +#define SNMP_SEC_MODEL_USM 3 +#define SNMP_SEC_MODEL_SNMPv2p 256 + +#define SNMP_SEC_LEVEL_NOAUTH 1 +#define SNMP_SEC_LEVEL_AUTHNOPRIV 2 +#define SNMP_SEC_LEVEL_AUTHPRIV 3 + +#define SNMP_MSG_FLAG_AUTH_BIT 0x01 +#define SNMP_MSG_FLAG_PRIV_BIT 0x02 +#define SNMP_MSG_FLAG_RPRT_BIT 0x04 + + /* control PDU handling characteristics */ +#define UCD_MSG_FLAG_RESPONSE_PDU 0x100 +#define UCD_MSG_FLAG_EXPECT_RESPONSE 0x200 +#define UCD_MSG_FLAG_FORCE_PDU_COPY 0x400 +#define UCD_MSG_FLAG_ALWAYS_IN_VIEW 0x800 + +/* view status */ +#define SNMP_VIEW_INCLUDED 1 +#define SNMP_VIEW_EXCLUDED 2 + +/* basic oid values */ +#define SNMP_OID_INTERNET 1, 3, 6, 1 +#define SNMP_OID_ENTERPRISES SNMP_OID_INTERNET, 4, 1 +#define SNMP_OID_MIB2 SNMP_OID_INTERNET, 2, 1 +#define SNMP_OID_SNMPV2 SNMP_OID_INTERNET, 6 +#define SNMP_OID_SNMPMODULES SNMP_OID_SNMPV2, 3 + +/* lengths as defined by TCs */ +#define SNMPADMINLENGTH 255 + + +#ifdef CMU_COMPATIBLE +/* PDU types in SNMPv1, SNMPsec, SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 */ +#define GET_REQ_MSG SNMP_MSG_GET +#define GETNEXT_REQ_MSG SNMP_MSG_GETNEXT +#define GET_RSP_MSG SNMP_MSG_RESPONSE +#define SET_REQ_MSG SNMP_MSG_SET + +/* PDU types in SNMPv1 and SNMPsec */ +#define TRP_REQ_MSG SNMP_MSG_TRAP + +/* PDU types in SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 */ +#define BULK_REQ_MSG SNMP_MSG_GETBULK +#define INFORM_REQ_MSG SNMP_MSG_INFORM +#define TRP2_REQ_MSG SNMP_MSG_TRAP2 + +/* PDU types in SNMPv2u, SNMPv2*, and SNMPv3 */ +#define REPORT_RSP_MSG SNMP_MSG_REPORT + +/* since CMU V1.5 */ + +#define SNMP_PDU_GET SNMP_MSG_GET +#define SNMP_PDU_GETNEXT SNMP_MSG_GETNEXT +#define SNMP_PDU_RESPONSE SNMP_MSG_RESPONSE +#define SNMP_PDU_SET SNMP_MSG_SET +#define SNMP_PDU_GETBULK SNMP_MSG_GETBULK +#define SNMP_PDU_INFORM SNMP_MSG_INFORM +#define SNMP_PDU_V2TRAP SNMP_MSG_TRAP2 +#define SNMP_PDU_REPORT SNMP_MSG_REPORT + +#define SNMP_TRAP_AUTHENTICATIONFAILURE SNMP_TRAP_AUTHFAIL + +#define SMI_INTEGER ASN_INTEGER +#define SMI_STRING ASN_OCTET_STR +#define SMI_OBJID ASN_OBJECT_ID +#define SMI_NULLOBJ ASN_NULL +#define SMI_IPADDRESS ASN_IPADDRESS +#define SMI_COUNTER32 ASN_COUNTER +#define SMI_GAUGE32 ASN_GAUGE +#define SMI_UNSIGNED32 SMI_GAUGE32 +#define SMI_TIMETICKS ASN_TIMETICKS +#define SMI_OPAQUE ASN_OPAQUE +#define SMI_COUNTER64 ASN_COUNTER64 + +int mib_TxtToOid (char *, oid **, size_t *); +int mib_OidToTxt (oid *, size_t , char *, size_t ); + +struct snmp_pdu; +char *snmp_pdu_type (struct snmp_pdu *); + +struct snmp_session; +u_char * cmu_snmp_parse (struct snmp_session *session, + struct snmp_pdu *pdu, + u_char *data, + size_t length); + +#endif /* CMU_COMPATIBLE */ + +char *uptime_string (u_long, char *); +void xdump (const u_char *, size_t, const char *); +u_char *snmp_parse_var_op (u_char *, oid *, size_t *, u_char *, size_t *, + u_char **, size_t *); +u_char *snmp_build_var_op (u_char *, oid *, size_t *, u_char, size_t, u_char *, + size_t *); +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_H */ diff --git a/packages/net/snmp/lib/current/include/snmp_alarm.h b/packages/net/snmp/lib/current/include/snmp_alarm.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp_alarm.h @@ -0,0 +1,127 @@ +//========================================================================== +// +// ./lib/current/include/snmp_alarm.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_ALARM_H +#define SNMP_ALARM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (SNMPAlarmCallback)(unsigned int clientreg, void *clientarg); + +/* alarm flags */ +#define SA_REPEAT 0x01 /* keep repeating every X seconds */ + +struct snmp_alarm { + unsigned int seconds; + unsigned int flags; + unsigned int clientreg; + time_t lastcall; + time_t nextcall; + void *clientarg; + SNMPAlarmCallback *thecallback; + struct snmp_alarm *next; +}; + +/* the ones you should need */ +void snmp_alarm_unregister(unsigned int clientreg); +unsigned int snmp_alarm_register(unsigned int when, unsigned int flags, + SNMPAlarmCallback *thecallback, + void *clientarg); + +/* the ones you shouldn't */ +void init_snmp_alarm(void); +int init_alarm_post_config(int majorid, int minorid, void *serverarg, + void *clientarg); +void sa_update_entry(struct snmp_alarm *alrm); +struct snmp_alarm *sa_find_next(void); +void run_alarms(void); +RETSIGTYPE alarm_handler(int a); +void set_an_alarm(void); +int get_next_alarm_delay_time(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_ALARM_H */ diff --git a/packages/net/snmp/lib/current/include/snmp_api.h b/packages/net/snmp/lib/current/include/snmp_api.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp_api.h @@ -0,0 +1,847 @@ +//========================================================================== +// +// ./lib/current/include/snmp_api.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_API_H +#define SNMP_API_H + +/* + * snmp_api.h - API for access to snmp. + * + * Caution: when using this library in a multi-threaded application, + * the values of global variables "snmp_errno" and "snmp_detail" + * cannot be reliably determined. Suggest using snmp_error() + * to obtain the library error codes. + */ + +#ifndef DONT_SHARE_ERROR_WITH_OTHER_THREADS +#define SET_SNMP_ERROR(x) snmp_errno=(x) +#else +#define SET_SNMP_ERROR(x) +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + + +struct variable_list; +struct timeval; + + + /* + * Mimic size and alignment of 'struct sockaddr_storage' (see RFC 2553) + * But retain field names of traditional 'struct sockaddr' + */ + +#define _UCD_SS_MAXSIZE 92 /* <= sizeof( sockaddr_un ) */ +#define _UCD_SS_ALIGNSIZE (sizeof (long)) + +#define _UCD_SS_PAD1SIZE (_UCD_SS_ALIGNSIZE - sizeof( unsigned short )) +#define _UCD_SS_PAD2SIZE (_UCD_SS_MAXSIZE - \ + (sizeof( unsigned short ) + _UCD_SS_PAD1SIZE + _UCD_SS_ALIGNSIZE )) + +typedef struct { + +#ifdef STRUCT_SOCKADDR_HAS_SA_UNION_SA_GENERIC_SA_FAMILY2 + /* + * Certain systems (notably Irix 6.x) have a non-traditional + * socket structure, and #define the traditional field names. + * This local definition should reproduce this structure, and still + * be large enough to handle any necessary Unix domain addresses. + */ + union { + struct { +#ifdef _HAVE_SA_LEN + unsigned char sa_len2; + unsigned char sa_family2; +#else + unsigned short sa_family2; +#endif + char sa_data2[ _UCD_SS_PAD1SIZE ]; + } sa_generic; + long sa_align; + char sa_pad2[ _UCD_SS_PAD2SIZE ]; + } sa_union; + +#else + +#ifdef STRUCT_SOCKADDR_HAS_SA_LEN + unsigned char sa_len; + unsigned char sa_family; +#else + unsigned short sa_family; +#endif + char sa_data[ _UCD_SS_PAD1SIZE ]; + long sa_align; + char sa_pad2[ _UCD_SS_PAD2SIZE ]; +#endif + +} snmp_ipaddr; + +#define USM_AUTH_KU_LEN 32 +#define USM_PRIV_KU_LEN 32 + +struct snmp_pdu { + + /* + * Protocol-version independent fields + */ + long version; + int command; /* Type of this PDU */ + long reqid; /* Request id - note: not incremented on retries */ + long msgid; /* Message id for V3 messages + * note: incremented for each retry */ + long transid; /* Unique ID for incoming transactions */ + long sessid; /* Session id for AgentX messages */ + long errstat; /* Error status (non_repeaters in GetBulk) */ + long errindex; /* Error index (max_repetitions in GetBulk) */ + u_long time; /* Uptime */ + u_long flags; + + int securityModel; + int securityLevel; /* noAuthNoPriv, authNoPriv, authPriv */ + int msgParseModel; + + snmp_ipaddr address; /* Address of peer or trap destination */ + + struct variable_list *variables; + + + /* + * SNMPv1 & SNMPv2c fields + */ + u_char *community; /* community for outgoing requests. */ + size_t community_len; /* Length of community name. */ + + /* + * Trap information + */ + oid *enterprise; /* System OID */ + size_t enterprise_length; + long trap_type; /* trap type */ + long specific_type; /* specific type */ + snmp_ipaddr agent_addr; + + /* + * SNMPv3 fields + */ + u_char *contextEngineID; /* context snmpEngineID */ + size_t contextEngineIDLen; /* Length of contextEngineID */ + char *contextName; /* authoritative contextName */ + size_t contextNameLen; /* Length of contextName */ + u_char *securityEngineID; /* authoritative snmpEngineID for security */ + size_t securityEngineIDLen;/* Length of securityEngineID */ + char *securityName; /* on behalf of this principal */ + size_t securityNameLen; /* Length of securityName. */ + + /* + * AgentX fields + * (also uses SNMPv1 community field) + */ + int priority; + int range_subid; + + void * securityStateRef; +}; + +struct snmp_session; +typedef int (*snmp_callback) (int, struct snmp_session *, int, struct snmp_pdu *, void *); + +struct snmp_session { + /* + * Protocol-version independent fields + */ + long version; + int retries; /* Number of retries before timeout. */ + long timeout; /* Number of uS until first timeout, then exponential backoff */ + u_long flags; + struct snmp_session *subsession; + struct snmp_session *next; + + char *peername; /* Domain name or dotted IP address of default peer */ + u_short remote_port;/* UDP port number of peer. */ + u_short local_port; /* My UDP port number, 0 for default, picked randomly */ + /* Authentication function or NULL if null authentication is used */ + u_char *(*authenticator) (u_char *, size_t *, u_char *, size_t); + snmp_callback callback; /* Function to interpret incoming data */ + /* Pointer to data that the callback function may consider important */ + void *callback_magic; + + int s_errno; /* copy of system errno */ + int s_snmp_errno; /* copy of library errno */ + long sessid; /* Session id - AgentX only */ + + /* + * SNMPv1 & SNMPv2c fields + */ + u_char *community; /* community for outgoing requests. */ + size_t community_len; /* Length of community name. */ + + /* + * SNMPv3 fields + */ + u_char *contextEngineID; /* authoritative snmpEngineID */ + size_t contextEngineIDLen; /* Length of contextEngineID */ + u_int engineBoots; /* initial engineBoots for remote engine */ + u_int engineTime; /* initial engineTime for remote engine */ + char *contextName; /* authoritative contextName */ + size_t contextNameLen; /* Length of contextName */ + u_char *securityEngineID; /* authoritative snmpEngineID */ + size_t securityEngineIDLen; /* Length of contextEngineID */ + char *securityName; /* on behalf of this principal */ + size_t securityNameLen; /* Length of securityName. */ + oid *securityAuthProto; /* auth protocol oid */ + size_t securityAuthProtoLen; /* Length of auth protocol oid */ + u_char securityAuthKey[USM_AUTH_KU_LEN]; /* Ku for auth protocol XXX */ + size_t securityAuthKeyLen; /* Length of Ku for auth protocol */ + oid *securityPrivProto; /* priv protocol oid */ + size_t securityPrivProtoLen; /* Length of priv protocol oid */ + u_char securityPrivKey[USM_PRIV_KU_LEN]; /* Ku for privacy protocol XXX */ + size_t securityPrivKeyLen; /* Length of Ku for priv protocol */ + int securityModel; + int securityLevel; /* noAuthNoPriv, authNoPriv, authPriv */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +#ifdef SNMP_NEED_REQUEST_LIST +struct request_list { + struct request_list *next_request; + long request_id; /* request id */ + long message_id; /* message id */ + snmp_callback callback; /* user callback per request (NULL if unused) */ + void *cb_data; /* user callback data per request (NULL if unused) */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_session *session; + struct snmp_pdu *pdu; /* The pdu for this request + (saved so it can be retransmitted */ +}; +#endif /* SNMP_NEED_REQUEST_LIST */ + +/* + * Set fields in session and pdu to the following to get a default or unconfigured value. + */ +#define SNMP_DEFAULT_COMMUNITY_LEN 0 /* to get a default community name */ +#define SNMP_DEFAULT_RETRIES -1 +#define SNMP_DEFAULT_TIMEOUT -1 +#define SNMP_DEFAULT_REMPORT 0 +#define SNMP_DEFAULT_REQID -1 +#define SNMP_DEFAULT_MSGID -1 +#define SNMP_DEFAULT_ERRSTAT -1 +#define SNMP_DEFAULT_ERRINDEX -1 +#define SNMP_DEFAULT_ADDRESS 0 +#define SNMP_DEFAULT_PEERNAME NULL +#define SNMP_DEFAULT_ENTERPRISE_LENGTH 0 +#define SNMP_DEFAULT_TIME 0 +#define SNMP_DEFAULT_VERSION -1 +#define SNMP_DEFAULT_CONTEXT "" +#define SNMP_DEFAULT_AUTH_PROTO usmHMACMD5AuthProtocol +#define SNMP_DEFAULT_AUTH_PROTOLEN USM_LENGTH_OID_TRANSFORM +#define SNMP_DEFAULT_PRIV_PROTO usmDESPrivProtocol +#define SNMP_DEFAULT_PRIV_PROTOLEN USM_LENGTH_OID_TRANSFORM + +extern const char *snmp_api_errstring (int); +extern void snmp_perror (const char *); +extern void snmp_set_detail (const char *); + +#define SNMP_MAX_MSG_SIZE 1472 /* ethernet MTU minus IP/UDP header */ +#define SNMP_MAX_ENG_SIZE 32 +#define SNMP_MAX_SEC_NAME_SIZE 256 +#define SNMP_MAX_SEC_NAME_SIZE 256 +#define SNMP_MAX_CONTEXT_SIZE 256 +#define SNMP_SEC_PARAM_BUF_SIZE 256 + +/* set to one to ignore unauthenticated Reports */ +#define SNMPV3_IGNORE_UNAUTH_REPORTS 0 +/* to determine type of Report from varbind_list */ +#define REPORT_STATS_LEN 9 +#define REPORT_snmpUnknownSecurityModels_NUM 1 +#define REPORT_snmpInvalidMsgs_NUM 2 +#define REPORT_usmStatsUnsupportedSecLevels_NUM 1 +#define REPORT_usmStatsNotInTimeWindows_NUM 2 +#define REPORT_usmStatsUnknownUserNames_NUM 3 +#define REPORT_usmStatsUnknownEngineIDs_NUM 4 +#define REPORT_usmStatsWrongDigests_NUM 5 +#define REPORT_usmStatsDecryptionErrors_NUM 6 + +#define SNMP_DETAIL_SIZE 512 + +#define SNMP_FLAGS_DONT_PROBE 0x100 /* don't probe for an engineID */ +#define SNMP_FLAGS_STREAM_SOCKET 0x80 +#define SNMP_FLAGS_LISTENING 0x40 /* Server stream sockets only */ +#define SNMP_FLAGS_SUBSESSION 0x20 + +/* + * Error return values. + * + * SNMPERR_SUCCESS is the non-PDU "success" code. + * + * XXX These should be merged with SNMP_ERR_* defines and confined + * to values < 0. ??? + */ +#define SNMPERR_SUCCESS (0) /* XXX Non-PDU "success" code. */ +#define SNMPERR_GENERR (-1) +#define SNMPERR_BAD_LOCPORT (-2) +#define SNMPERR_BAD_ADDRESS (-3) +#define SNMPERR_BAD_SESSION (-4) +#define SNMPERR_TOO_LONG (-5) +#define SNMPERR_NO_SOCKET (-6) +#define SNMPERR_V2_IN_V1 (-7) +#define SNMPERR_V1_IN_V2 (-8) +#define SNMPERR_BAD_REPEATERS (-9) +#define SNMPERR_BAD_REPETITIONS (-10) +#define SNMPERR_BAD_ASN1_BUILD (-11) +#define SNMPERR_BAD_SENDTO (-12) +#define SNMPERR_BAD_PARSE (-13) +#define SNMPERR_BAD_VERSION (-14) +#define SNMPERR_BAD_SRC_PARTY (-15) +#define SNMPERR_BAD_DST_PARTY (-16) +#define SNMPERR_BAD_CONTEXT (-17) +#define SNMPERR_BAD_COMMUNITY (-18) +#define SNMPERR_NOAUTH_DESPRIV (-19) +#define SNMPERR_BAD_ACL (-20) +#define SNMPERR_BAD_PARTY (-21) +#define SNMPERR_ABORT (-22) +#define SNMPERR_UNKNOWN_PDU (-23) +#define SNMPERR_TIMEOUT (-24) +#define SNMPERR_BAD_RECVFROM (-25) +#define SNMPERR_BAD_ENG_ID (-26) +#define SNMPERR_BAD_SEC_NAME (-27) +#define SNMPERR_BAD_SEC_LEVEL (-28) +#define SNMPERR_ASN_PARSE_ERR (-29) +#define SNMPERR_UNKNOWN_SEC_MODEL (-30) +#define SNMPERR_INVALID_MSG (-31) +#define SNMPERR_UNKNOWN_ENG_ID (-32) +#define SNMPERR_UNKNOWN_USER_NAME (-33) +#define SNMPERR_UNSUPPORTED_SEC_LEVEL (-34) +#define SNMPERR_AUTHENTICATION_FAILURE (-35) +#define SNMPERR_NOT_IN_TIME_WINDOW (-36) +#define SNMPERR_DECRYPTION_ERR (-37) +#define SNMPERR_SC_GENERAL_FAILURE (-38) +#define SNMPERR_SC_NOT_CONFIGURED (-39) +#define SNMPERR_KT_NOT_AVAILABLE (-40) +#define SNMPERR_UNKNOWN_REPORT (-41) +#define SNMPERR_USM_GENERICERROR (-42) +#define SNMPERR_USM_UNKNOWNSECURITYNAME (-43) +#define SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL (-44) +#define SNMPERR_USM_ENCRYPTIONERROR (-45) +#define SNMPERR_USM_AUTHENTICATIONFAILURE (-46) +#define SNMPERR_USM_PARSEERROR (-47) +#define SNMPERR_USM_UNKNOWNENGINEID (-48) +#define SNMPERR_USM_NOTINTIMEWINDOW (-49) +#define SNMPERR_USM_DECRYPTIONERROR (-50) +#define SNMPERR_NOMIB (-51) +#define SNMPERR_RANGE (-52) +#define SNMPERR_MAX_SUBID (-53) +#define SNMPERR_BAD_SUBID (-54) +#define SNMPERR_LONG_OID (-55) +#define SNMPERR_BAD_NAME (-56) +#define SNMPERR_VALUE (-57) +#define SNMPERR_UNKNOWN_OBJID (-58) +#define SNMPERR_NULL_PDU (-59) +#define SNMPERR_NO_VARS (-60) +#define SNMPERR_VAR_TYPE (-61) +#define SNMPERR_MALLOC (-62) + +#define SNMPERR_MAX (-62) + +#define non_repeaters errstat +#define max_repetitions errindex + + +struct variable_list { + struct variable_list *next_variable; /* NULL for last variable */ + oid *name; /* Object identifier of variable */ + size_t name_length; /* number of subid's in name */ + u_char type; /* ASN type of variable */ + union { /* value of variable */ + long *integer; + u_char *string; + oid *objid; + u_char *bitstring; + struct counter64 *counter64; +#ifdef OPAQUE_SPECIAL_TYPES + float *floatVal; + double *doubleVal; +/* t_union *unionVal; */ +#endif /* OPAQUE_SPECIAL_TYPES */ + } val; + size_t val_len; + oid name_loc[MAX_OID_LEN]; /* 90 percentile < 24. */ + u_char buf[40]; /* 90 percentile < 40. */ +}; + + + +/* + * struct snmp_session *snmp_open(session) + * struct snmp_session *session; + * + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session *snmp_open (struct snmp_session *); + +/* + * int snmp_close(session) + * struct snmp_session *session; + * + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + * + * snmp_close_sessions() does the same thing for all open sessions + */ +int snmp_close (struct snmp_session *); +int snmp_close_sessions (void); + + +/* + * int snmp_send(session, pdu) + * struct snmp_session *session; + * struct snmp_pdu *pdu; + * + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int snmp_send (struct snmp_session *, struct snmp_pdu *); + +/* + * int snmp_async_send(session, pdu, callback, cb_data) + * struct snmp_session *session; + * struct snmp_pdu *pdu; + * snmp_callback callback; + * void *cb_data; + * + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session and store callback and data, + * then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int snmp_async_send (struct snmp_session *, struct snmp_pdu *, + snmp_callback, void *); + + +/* + * void snmp_read(fdset) + * fd_set *fdset; + * + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void snmp_read (fd_set *); + + + +/* + * void + * snmp_free_pdu(pdu) + * struct snmp_pdu *pdu; + * + * Frees the pdu and any malloc'd data associated with it. + */ +void snmp_free_pdu (struct snmp_pdu *); + +void snmp_free_var (struct variable_list *); + +void snmp_free_varbind(struct variable_list *var); + +/* + * int snmp_select_info(numfds, fdset, timeout, block) + * int *numfds; + * fd_set *fdset; + * struct timeval *timeout; + * int *block; + * + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set. + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather than + * time out. If block is input as 1, the timeout value will be treated as + * undefined, but it must be available for setting in snmp_select_info. On + * return, if block is true, the value of timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The number + * of sessions open) + */ +int snmp_select_info (int *, fd_set *, struct timeval *, int *); + + + +/* + * void snmp_timeout(); + * + * snmp_timeout should be called whenever the timeout from snmp_select_info + * expires, but it is idempotent, so snmp_timeout can be polled (probably a + * cpu expensive proposition). snmp_timeout checks to see if any of the + * sessions have an outstanding request that has timed out. If it finds one + * (or more), and that pdu has more retries available, a new packet is formed + * from the pdu and is resent. If there are no more retries available, the + * callback for the session is used to alert the user of the timeout. + */ + +void snmp_timeout (void); + + +/* + * This routine must be supplied by the application: + * + * u_char *authenticator(pdu, length, community, community_len) + * u_char *pdu; The rest of the PDU to be authenticated + * int *length; The length of the PDU (updated by the authenticator) + * u_char *community; The community name to authenticate under. + * int community_len The length of the community name. + * + * Returns the authenticated pdu, or NULL if authentication failed. + * If null authentication is used, the authenticator in snmp_session can be + * set to NULL(0). + */ + + + +/* + * This routine must be supplied by the application: + * + * int callback(operation, session, reqid, pdu, magic) + * int operation; + * struct snmp_session *session; The session authenticated under. + * int reqid; The request id of this pdu (0 for TRAP) + * struct snmp_pdu *pdu; The pdu information. + * void *magic A link to the data for this routine. + * + * Returns 1 if request was successful, 0 if it should be kept pending. + * Any data in the pdu must be copied because it will be freed elsewhere. + * Operations are defined below: + */ + +#define RECEIVED_MESSAGE 1 +#define TIMED_OUT 2 + +long snmp_get_next_msgid(void); +long snmp_get_next_reqid(void); +long snmp_get_next_sessid(void); +long snmp_get_next_transid(void); +/* provide for backwards compatibility */ +void snmp_set_dump_packet(int); +int snmp_get_dump_packet(void); +void snmp_set_quick_print(int); +int snmp_get_quick_print(void); +void snmp_set_suffix_only(int); +int snmp_get_suffix_only(void); +void snmp_set_full_objid(int); +int snmp_get_full_objid(void); +void snmp_set_random_access(int); +int snmp_get_random_access(void); + +int snmp_oid_compare (const oid *, size_t, const oid *, size_t); +void init_snmp (const char *); +u_char *snmp_pdu_build (struct snmp_pdu *, u_char *, size_t *); +int snmpv3_parse(struct snmp_pdu *, u_char *, size_t *, u_char **); +int snmpv3_dparse(struct snmp_pdu *, u_char *, size_t *, u_char **, int); +int snmpv3_packet_build(struct snmp_pdu *pdu, u_char *packet, size_t *out_length, u_char *pdu_data, size_t pdu_data_len); +int snmpv3_make_report(struct snmp_pdu *pdu, int error); +int snmpv3_get_report_type(struct snmp_pdu *pdu); +int snmp_pdu_parse(struct snmp_pdu *pdu, u_char *data, size_t *length); +int snmp_pdu_dparse(struct snmp_pdu *pdu, u_char *data, size_t *length, int); +u_char* snmpv3_scopedPDU_parse(struct snmp_pdu *pdu, u_char *cp, size_t *length); +u_char* snmpv3_scopedPDU_dparse(struct snmp_pdu *pdu, u_char *cp, size_t *length, int); +void snmp_shutdown(const char *type); +struct variable_list *snmp_pdu_add_variable (struct snmp_pdu *, oid *, size_t, u_char, u_char *, size_t); +struct variable_list *snmp_varlist_add_variable(struct variable_list **varlist, + oid *name, size_t name_length, u_char type, u_char *value, size_t len); +int hex_to_binary (const char *, u_char *); +int ascii_to_binary (const char *, u_char *); +int snmp_add_var (struct snmp_pdu *, oid*, size_t, char, const char *); +oid *snmp_duplicate_objid(oid *objToCopy, size_t); +u_int snmp_increment_statistic(int which); +u_int snmp_increment_statistic_by(int which, int count); +u_int snmp_get_statistic(int which); +void snmp_init_statistics(void); +int create_user_from_session(struct snmp_session *session); + +/* extended open */ +struct snmp_session *snmp_open_ex (struct snmp_session *, + int (*fpre_parse) (struct snmp_session *, snmp_ipaddr), + int (*fparse) (struct snmp_session *, struct snmp_pdu *, u_char *, size_t), + int (*fpost_parse) (struct snmp_session *, struct snmp_pdu *, int), + int (*fbuild) (struct snmp_session *, struct snmp_pdu *, u_char *, size_t *), + int (*fcheck) (u_char *, size_t) +); + +/* provided for backwards compatability. Don't use these functions. + See snmp_debug.h and snmp_debug.c instead. +*/ +#if HAVE_STDARG_H +void DEBUGP (const char *, ...); +#else +void DEBUGP (va_alist); +#endif +void DEBUGPOID(oid *, size_t); +void snmp_set_do_debugging (int); +int snmp_get_do_debugging (void); + +#ifdef CMU_COMPATIBLE +extern int snmp_dump_packet; +extern int quick_print; +#endif + +size_t snmp_socket_length (int family); + +/* + * snmp_error - return error data + * Inputs : address of errno, address of snmp_errno, address of string + * Caller must free the string returned after use. + */ +void snmp_error (struct snmp_session *, int *, int *, char **); +/* + * single session API. + * + * These functions perform similar actions as snmp_XX functions, + * but operate on a single session only. + * + * Synopsis: + + void * sessp; + struct snmp_session session, *ss; + struct snmp_pdu *pdu, *response; + + snmp_sess_init(&session); + session.retries = ... + session.remote_port = ... + sessp = snmp_sess_open(&session); + ss = snmp_sess_session(sessp); + if (ss == NULL) + exit(1); + ... + if (ss->community) free(ss->community); + ss->community = strdup(gateway); + ss->community_len = strlen(gateway); + ... + snmp_sess_synch_response(sessp, pdu, &response); + ... + snmp_sess_close(sessp); + + * See also: + * snmp_sess_synch_response, in snmp_client.h. + + * Notes: + * 1. Invoke snmp_sess_session after snmp_sess_open. + * 2. snmp_sess_session return value is an opaque pointer. + * 3. Do NOT free memory returned by snmp_sess_session. + * 4. Replace snmp_send(ss,pdu) with snmp_sess_send(sessp,pdu) + */ + +void snmp_sess_init (struct snmp_session *); +void * snmp_sess_open (struct snmp_session *); +struct snmp_session * snmp_sess_session (void *); + +/* use return value from snmp_sess_open as void * parameter */ + +int snmp_sess_send (void *, struct snmp_pdu *); +int snmp_sess_async_send (void *, struct snmp_pdu *, + snmp_callback, void *); +int snmp_sess_select_info (void *, int *, fd_set *, + struct timeval *, int *); +int snmp_sess_read (void *, fd_set *); +void snmp_sess_timeout (void *); +int snmp_sess_close (void *); + +void snmp_sess_error (void *, int *, int *, char **); +void snmp_sess_perror (const char *prog_string, struct snmp_session *ss); + +/* end single session API */ + +/* generic statistic counters */ + +/* snmpv3 statistics */ + +/* mpd stats */ +#define STAT_SNMPUNKNOWNSECURITYMODELS 0 +#define STAT_SNMPINVALIDMSGS 1 +#define STAT_SNMPUNKNOWNPDUHANDLERS 2 +#define STAT_MPD_STATS_START STAT_SNMPUNKNOWNSECURITYMODELS +#define STAT_MPD_STATS_END STAT_SNMPUNKNOWNPDUHANDLERS + +/* usm stats */ +#define STAT_USMSTATSUNSUPPORTEDSECLEVELS 3 +#define STAT_USMSTATSNOTINTIMEWINDOWS 4 +#define STAT_USMSTATSUNKNOWNUSERNAMES 5 +#define STAT_USMSTATSUNKNOWNENGINEIDS 6 +#define STAT_USMSTATSWRONGDIGESTS 7 +#define STAT_USMSTATSDECRYPTIONERRORS 8 +#define STAT_USM_STATS_START STAT_USMSTATSUNSUPPORTEDSECLEVELS +#define STAT_USM_STATS_END STAT_USMSTATSDECRYPTIONERRORS + +/* snmp counters */ +#define STAT_SNMPINPKTS 9 +#define STAT_SNMPOUTPKTS 10 +#define STAT_SNMPINBADVERSIONS 11 +#define STAT_SNMPINBADCOMMUNITYNAMES 12 +#define STAT_SNMPINBADCOMMUNITYUSES 13 +#define STAT_SNMPINASNPARSEERRS 14 +/* #define STAT_SNMPINBADTYPES 15 */ +#define STAT_SNMPINTOOBIGS 16 +#define STAT_SNMPINNOSUCHNAMES 17 +#define STAT_SNMPINBADVALUES 18 +#define STAT_SNMPINREADONLYS 19 +#define STAT_SNMPINGENERRS 20 +#define STAT_SNMPINTOTALREQVARS 21 +#define STAT_SNMPINTOTALSETVARS 22 +#define STAT_SNMPINGETREQUESTS 23 +#define STAT_SNMPINGETNEXTS 24 +#define STAT_SNMPINSETREQUESTS 25 +#define STAT_SNMPINGETRESPONSES 26 +#define STAT_SNMPINTRAPS 27 +#define STAT_SNMPOUTTOOBIGS 28 +#define STAT_SNMPOUTNOSUCHNAMES 29 +#define STAT_SNMPOUTBADVALUES 30 +/* #define STAT_SNMPOUTREADONLYS 31 */ +#define STAT_SNMPOUTGENERRS 32 +#define STAT_SNMPOUTGETREQUESTS 33 +#define STAT_SNMPOUTGETNEXTS 34 +#define STAT_SNMPOUTSETREQUESTS 35 +#define STAT_SNMPOUTGETRESPONSES 36 +#define STAT_SNMPOUTTRAPS 37 +/* AUTHTRAPENABLE 38 */ +#define STAT_SNMPSILENTDROPS 39 +#define STAT_SNMPPROXYDROPS 40 +#define STAT_SNMP_STATS_START STAT_SNMPINPKTS +#define STAT_SNMP_STATS_END STAT_SNMPOUTTRAPS + +#define MAX_STATS 41 + +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_API_H */ diff --git a/packages/net/snmp/lib/current/include/snmp_client.h b/packages/net/snmp/lib/current/include/snmp_client.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp_client.h @@ -0,0 +1,155 @@ +//========================================================================== +// +// ./lib/current/include/snmp_client.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmp_client.h + */ +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#ifndef SNMP_CLIENT_H +#define SNMP_CLIENT_H + +#ifdef __cplusplus +extern "C" { +#endif + + +struct snmp_pdu; +struct snmp_session; +struct variable_list; + +struct synch_state { + int waiting; + int status; +/* status codes */ +#define STAT_SUCCESS 0 +#define STAT_ERROR 1 +#define STAT_TIMEOUT 2 + int reqid; + struct snmp_pdu *pdu; +}; + +int snmp_set_var_value(struct variable_list *, u_char *, size_t); +int snmp_set_var_objid (struct variable_list *vp, + const oid *objid, size_t name_length); +struct variable_list* snmp_add_null_var (struct snmp_pdu *, oid *, size_t); +struct snmp_pdu *snmp_pdu_create (int); +struct snmp_pdu *snmp_fix_pdu (struct snmp_pdu *, int); +struct snmp_pdu *snmp_clone_pdu (struct snmp_pdu *); +struct snmp_pdu *snmp_split_pdu (struct snmp_pdu *, int skipCount, + int copyCount); + +unsigned long snmp_varbind_len(struct snmp_pdu * pdu); +int snmp_clone_var(struct variable_list *, struct variable_list *); +const char *snmp_errstring (int); +int snmp_synch_response (struct snmp_session *, struct snmp_pdu *, struct snmp_pdu **); +int snmp_synch_response_cb (struct snmp_session *, struct snmp_pdu *, struct snmp_pdu **, snmp_callback); +int snmp_clone_mem(void **, void *, unsigned); + +/* single session API - see snmp_api.h for full details */ +int snmp_sess_synch_response (void *, struct snmp_pdu *, struct snmp_pdu **); + +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_CLIENT_H */ diff --git a/packages/net/snmp/lib/current/include/snmp_debug.h b/packages/net/snmp/lib/current/include/snmp_debug.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp_debug.h @@ -0,0 +1,291 @@ +//========================================================================== +// +// ./lib/current/include/snmp_debug.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_DEBUG_H +#define SNMP_DEBUG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* snmp_debug.h: + + - prototypes for snmp debugging routines. + - easy to use macros to wrap around the functions. This also provides + the ability to reove debugging code easily from the applications at + compile time. +*/ + + +/* These functions should not be used, if at all possible. Instead, use + the macros below. */ +#if HAVE_STDARG_H +void debugmsg(const char *token, const char *format, ...); +void debugmsgtoken(const char *token, const char *format, ...); +#else +void debugmsg(va_alist); +void debugmsgtoken(va_alist); +#endif +void debugmsg_oid(const char *token, oid *theoid, size_t len); +void debugmsg_hex(const char *token, u_char *thedata, size_t len); +void debugmsg_hextli(const char *token, u_char *thedata, size_t len); +void debug_indent_add(int amount); +char *debug_indent(void); + +/* Use these macros instead of the functions above to allow them to be + re-defined at compile time to NOP for speed optimization. + + They need to be called enclosing all the arguments in a single set of ()s. + Example: + DEBUGMSGTL(("token", "debugging of something %s related\n", "snmp")); + +Usage: + All of the functions take a "token" argument that helps determine when + the output in question should be printed. See the snmpcmd.1 manual page + on the -D flag to turn on/off output for a given token on the command line. + + DEBUGMSG((token, format, ...)): equivelent to printf(format, ...) + (if "token" debugging output + is requested by the user) + + DEBUGMSGT((token, format, ...)): equivelent to DEBUGMSG, but prints + "token: " at the beginning of the + line for you. + + DEBUGTRACE Insert this token anywhere you want + tracing output displayed when the + "trace" debugging token is selected. + + DEBUGMSGL((token, format, ...)): equivelent to DEBUGMSG, but includes + DEBUGTRACE debugging line just before + yours. + + DEBUGMSGTL((token, format, ...)): Same as DEBUGMSGL and DEBUGMSGT + combined. + +Important: + It is considered best if you use DEBUGMSGTL() everywhere possible, as it + gives the nicest format output and provides tracing support just before + every debugging statement output. + +To print multiple pieces to a single line in one call, use: + + DEBUGMSGTL(("token", "line part 1")); + DEBUGMSG (("token", " and part 2\n")); + + to get: + + token: line part 1 and part 2 + + as debugging output. +*/ + +#ifndef SNMP_NO_DEBUGGING /* make sure we're wanted */ + +/* + * define two macros : one macro with, one without, + * a test if debugging is enabled. + * + * Generally, use the macro with _DBG_IF_ + */ + +/******************* Start private macros ************************/ +#define _DBG_IF_ snmp_get_do_debugging() +#define DEBUGIF(x) if (_DBG_IF_ && debug_is_token_registered(x) == SNMPERR_SUCCESS) + +#define __DBGMSGT(x) debugmsgtoken x, debugmsg x + +#ifdef HAVE_CPP_UNDERBAR_FUNCTION_DEFINED +#define __DBGTRACE __DBGMSGT(("trace","%s(): %s, %d\n",__FUNCTION__,\ + __FILE__,__LINE__)) +#else +#define __DBGTRACE __DBGMSGT(("trace"," %s, %d\n", __FILE__,__LINE__)) +#endif + +#define __DBGMSGL(x) __DBGTRACE, debugmsg x +#define __DBGMSGTL(x) __DBGTRACE, debugmsgtoken x, debugmsg x +#define __DBGMSGOID(x) debugmsg_oid x +#define __DBGMSGHEX(x) debugmsg_hex x +#define __DBGMSGHEXTLI(x) debugmsg_hextli x +#define __DBGINDENT() debug_indent() +#define __DBGINDENTADD(x) debug_indent_add(x) +#define __DBGINDENTMORE() debug_indent_add(2) +#define __DBGINDENTLESS() debug_indent_add(-2) +#define __DBGPRINTINDENT(token) __DBGMSGTL((token, "%s", __DBGINDENT())) + +#define __DBGDUMPHEADER(token,x) \ + __DBGPRINTINDENT(token), \ + debugmsg(token,x), \ + __DBGINDENTMORE() + +#define __DBGDUMPSETUP(token,buf,len) \ + __DBGTRACE, \ + __DBGMSGHEXTLI((token,buf,len)), \ + debugmsg(token,"\n"), \ + __DBGPRINTINDENT(token) + +/******************* End private macros ************************/ +/*****************************************************************/ + +/*****************************************************************/ +/********************Start public macros ************************/ + +#define DEBUGMSG(x) do {if (_DBG_IF_) {debugmsg x;} }while(0) +#define DEBUGMSGT(x) do {if (_DBG_IF_) {__DBGMSGT(x);} }while(0) +#define DEBUGTRACE do {if (_DBG_IF_) {__DBGTRACE;} }while(0) +#define DEBUGMSGL(x) do {if (_DBG_IF_) {__DBGMSGL(x);} }while(0) +#define DEBUGMSGTL(x) do {if (_DBG_IF_) {__DBGMSGTL(x);} }while(0) +#define DEBUGMSGOID(x) do {if (_DBG_IF_) {__DBGMSGOID(x);} }while(0) +#define DEBUGMSGHEX(x) do {if (_DBG_IF_) {__DBGMSGHEX(x);} }while(0) +#define DEBUGMSGHEXTLI(x) do {if (_DBG_IF_) {__DBGMSGHEXTLI(x);} }while(0) +#define DEBUGINDENT() do {if (_DBG_IF_) {__DBGINDENT();} }while(0) +#define DEBUGINDENTADD(x) do {if (_DBG_IF_) {__DBGINDENTADD(x);} }while(0) +#define DEBUGINDENTMORE() do {if (_DBG_IF_) {__DBGINDENTMORE();} }while(0) +#define DEBUGINDENTLESS() do {if (_DBG_IF_) {__DBGINDENTLESS();} }while(0) +#define DEBUGPRINTINDENT(token) \ + do {if (_DBG_IF_) {__DBGPRINTINDENT(token);} }while(0) + + +#define DEBUGDUMPHEADER(token,x) \ + do {if (_DBG_IF_) {__DBGDUMPHEADER(token,x);} }while(0) + +#define DEBUGDUMPSETUP(token,buf,len) \ + do {if (_DBG_IF_) {__DBGDUMPSETUP(token,buf,len);} }while(0) + +#else /* SNMP_NO_DEBUGGING := enable streamlining of the code */ + +#define DEBUGMSG(x) +#define DEBUGMSGT(x) +#define DEBUGTRACE +#define DEBUGMSGL(x) +#define DEBUGMSGTL(x) +#define DEBUGMSGOID(x) +#define DEBUGMSGHEX(x) +#define DEBUGIF(x) if(0) +#define DEBUGDUMP(t,b,l,p) +#define DEBUGINDENT() +#define DEBUGINDENTMORE() +#define DEBUGINDENTLESS() +#define DEBUGINDENTADD(x) +#define DEBUGMSGHEXTLI(x) +#define DEBUGPRINTINDENT(token) +#define DEBUGDUMPHEADER(token,x) +#define DEBUGDUMPSETUP(token, buf, len) + +#endif + +#define MAX_DEBUG_TOKENS 256 +#define MAX_DEBUG_TOKEN_LEN 128 +#define DEBUG_TOKEN_DELIMITER "," +#define DEBUG_ALWAYS_TOKEN "all" + +/* + setup routines: + + debug_register_tokens(char *): registers a list of tokens to + print debugging output for. + + debug_is_token_registered(char *): returns SNMPERR_SUCCESS or SNMPERR_GENERR + if a token has been registered or + not (and debugging output is "on"). + snmp_debug_init(void): registers .conf handlers. +*/ +void debug_register_tokens(char *tokens); +int debug_is_token_registered(const char *token); +void snmp_debug_init(void); + +/* provided for backwards compatability. Don't use these functions. */ +#if HAVE_STDARG_H +void DEBUGP (const char *, ...); +#else +void DEBUGP (va_alist); +#endif +void DEBUGPOID(oid *, size_t); +void snmp_set_do_debugging (int); +int snmp_get_do_debugging (void); +int debug_is_token_registered(const char *token); + +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_DEBUG_H */ diff --git a/packages/net/snmp/lib/current/include/snmp_impl.h b/packages/net/snmp/lib/current/include/snmp_impl.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp_impl.h @@ -0,0 +1,223 @@ +//========================================================================== +// +// ./lib/current/include/snmp_impl.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_IMPL_H +#define SNMP_IMPL_H + +#ifdef __cplusplus +extern "C" { +#endif +/* +* file: snmp_impl.h +*/ + +/* + * Definitions for SNMP implementation. + * + * + */ +/*********************************************************** + Copyright 1988, 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#include + +#define COMMUNITY_MAX_LEN 256 + +/* Space for character representation of an object identifier */ +#define SPRINT_MAX_LEN 2560 + + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define READ 1 +#define WRITE 0 + +#define RESERVE1 0 +#define RESERVE2 1 +#define ACTION 2 +#define COMMIT 3 +#define FREE 4 +#define UNDO 5 +#define FINISHED_SUCCESS 9 +#define FINISHED_FAILURE 10 + +/* Access control statements for the agent */ +#define RONLY 0x1 /* read access only */ +#define RWRITE 0x2 /* read and write access (must have 0x2 bit set) */ + +#define NOACCESS 0x0000 /* no access for anybody */ + +/* defined types (from the SMI, RFC 1157) */ +#define ASN_IPADDRESS (ASN_APPLICATION | 0) +#define ASN_COUNTER (ASN_APPLICATION | 1) +#define ASN_GAUGE (ASN_APPLICATION | 2) +#define ASN_UNSIGNED (ASN_APPLICATION | 2) /* RFC 1902 - same as GAUGE */ +#define ASN_TIMETICKS (ASN_APPLICATION | 3) +#define ASN_OPAQUE (ASN_APPLICATION | 4) /* changed so no conflict with other includes */ + +/* defined types (from the SMI, RFC 1442) */ +#define ASN_NSAP (ASN_APPLICATION | 5) /* historic - don't use */ +#define ASN_COUNTER64 (ASN_APPLICATION | 6) +#define ASN_UINTEGER (ASN_APPLICATION | 7) /* historic - don't use */ + +#ifdef OPAQUE_SPECIAL_TYPES +/* defined types from draft-perkins-opaque-01.txt */ +#define ASN_FLOAT (ASN_APPLICATION | 8) +#define ASN_DOUBLE (ASN_APPLICATION | 9) +#define ASN_INTEGER64 (ASN_APPLICATION | 10) +#define ASN_UNSIGNED64 (ASN_APPLICATION | 11) +#endif /* OPAQUE_SPECIAL_TYPES */ + +/* #define CMU_COMPATIBLE */ +#ifdef CMU_COMPATIBLE +#define INTEGER ASN_INTEGER +#define STRING ASN_OCTET_STR +#define OBJID ASN_OBJECT_ID +#define NULLOBJ ASN_NULL +#define BITSTRING ASN_BIT_STR /* HISTORIC - don't use */ +#define IPADDRESS ASN_IPADDRESS +#define COUNTER ASN_COUNTER +#define GAUGE ASN_GAUGE +#define UNSIGNED ASN_UNSIGNED +#define TIMETICKS ASN_TIMETICKS +#define ASNT_OPAQUE ASN_OPAQUE +#define NSAP ASN_NSAP +#define COUNTER64 ASN_COUNTER64 +#define UINTEGER ASN_UINTEGER +#endif /* CMU_COMPATIBLE */ + +/* changed to ERROR_MSG to eliminate conflict with other includes */ +#define ERROR_MSG(string) snmp_set_detail(string) + +/* from snmp.c */ +extern u_char sid[]; /* size SID_MAX_LEN */ +extern int snmp_errno; + + +/* + * For calling secauth_build, FIRST_PASS is an indication that a new nonce + * and lastTimeStamp should be recorded. LAST_PASS is an indication that + * the packet should be checksummed and encrypted if applicable, in + * preparation for transmission. + * 0 means do neither, FIRST_PASS | LAST_PASS means do both. + * For secauth_parse, FIRST_PASS means decrypt the packet, otherwise leave it + * alone. LAST_PASS is ignored. + */ +#define FIRST_PASS 1 +#define LAST_PASS 2 +u_char *snmp_comstr_parse(u_char *, size_t *, u_char *, size_t *, long *); +u_char *snmp_comstr_build (u_char *, size_t *, u_char *, size_t *, long *, size_t); + +int has_access (u_char, int, int, int); +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_IMPL_H */ diff --git a/packages/net/snmp/lib/current/include/snmp_logging.h b/packages/net/snmp/lib/current/include/snmp_logging.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmp_logging.h @@ -0,0 +1,146 @@ +//========================================================================== +// +// ./lib/current/include/snmp_logging.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_LOGGING_H +#define SNMP_LOGGING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if HAVE_SYSLOG_H +#include +#endif +#if HAVE_STDARG_H +#include +#else +#include +#endif + +#ifndef LOG_ERR +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#endif + +typedef void (*snmp_log_callback)(int level, const char* text); +struct snmp_log_message { + int priority; + const char *msg; +}; + +void init_snmp_logging(void); +int snmp_get_do_logging(void); +void snmp_disable_syslog(void); +void snmp_disable_filelog(void); +void snmp_disable_stderrlog(void); +void snmp_disable_calllog(void); +void snmp_disable_log(void); +void snmp_enable_syslog(void); +void snmp_enable_filelog(const char *logfilename, int dont_zero_log); +void snmp_enable_stderrlog(void); +void snmp_enable_calllog(void); + +#if HAVE_STDARG_H +int snmp_log(int priority, const char *format, ...); +#else +int snmp_log (va_alist); +#endif +int snmp_vlog(int priority, const char *format, va_list ap); + /* 0 - successful message formatting */ + /* -1 - Could not format log-string */ + /* -2 - Could not allocate memory for log-message */ + /* -3 - Log-message too long! */ + +void snmp_log_perror(const char *s); + +#ifdef __cplusplus +} +#endif + +#endif /* SNMP_LOGGING_H */ diff --git a/packages/net/snmp/lib/current/include/snmpusm.h b/packages/net/snmp/lib/current/include/snmpusm.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmpusm.h @@ -0,0 +1,284 @@ +//========================================================================== +// +// ./lib/current/include/snmpusm.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmpusm.h + * + * Header file for USM support. + */ + +#ifndef SNMPUSM_H +#define SNMPUSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define WILDCARDSTRING "*" + +/* + * General. + */ +#define USM_MAX_ID_LENGTH 1024 /* In bytes. */ +#define USM_MAX_SALT_LENGTH 64 /* In BITS. */ +#define USM_MAX_KEYEDHASH_LENGTH 128 /* In BITS. */ + +#define USM_TIME_WINDOW 150 + + +/* + * Structures. + */ +struct usmStateReference { + char *usr_name; + size_t usr_name_length; + u_char *usr_engine_id; + size_t usr_engine_id_length; + oid *usr_auth_protocol; + size_t usr_auth_protocol_length; + u_char *usr_auth_key; + size_t usr_auth_key_length; + oid *usr_priv_protocol; + size_t usr_priv_protocol_length; + u_char *usr_priv_key; + size_t usr_priv_key_length; + u_int usr_sec_level; +}; + + +/* struct usmUser: a structure to represent a given user in a list */ +/* Note: Any changes made to this structure need to be reflected in + the following functions: */ + +struct usmUser; +struct usmUser { + u_char *engineID; + size_t engineIDLen; + char *name; + char *secName; + oid *cloneFrom; + size_t cloneFromLen; + oid *authProtocol; + size_t authProtocolLen; + u_char *authKey; + size_t authKeyLen; + oid *privProtocol; + size_t privProtocolLen; + u_char *privKey; + size_t privKeyLen; + u_char *userPublicString; + int userStatus; + int userStorageType; + struct usmUser *next; + struct usmUser *prev; +}; + + + +/* + * Prototypes. + */ +void usm_set_reportErrorOnUnknownID (int value); + +struct usmStateReference * + usm_malloc_usmStateReference (void); + +void usm_free_usmStateReference (void *old); + +int usm_set_usmStateReference_name ( + struct usmStateReference *ref, + char *name, + size_t name_len); + +int usm_set_usmStateReference_engine_id ( + struct usmStateReference *ref, + u_char *engine_id, + size_t engine_id_len); + +int usm_set_usmStateReference_auth_protocol ( + struct usmStateReference *ref, + oid *auth_protocol, + size_t auth_protocol_len); + +int usm_set_usmStateReference_auth_key ( + struct usmStateReference *ref, + u_char *auth_key, + size_t auth_key_len); + +int usm_set_usmStateReference_priv_protocol ( + struct usmStateReference *ref, + oid *priv_protocol, + size_t priv_protocol_len); + +int usm_set_usmStateReference_priv_key ( + struct usmStateReference *ref, + u_char *priv_key, + size_t priv_key_len); + +int usm_set_usmStateReference_sec_level ( + struct usmStateReference *ref, + int sec_level); + +#ifdef SNMP_TESTING_CODE +void emergency_print (u_char *field, u_int length); +#endif + +int asn_predict_int_length (int type, long number, size_t len); + +int asn_predict_length (int type, u_char *ptr, size_t u_char_len); + +int usm_set_salt ( + u_char *iv, + size_t *iv_length, + u_char *priv_salt, + size_t priv_salt_length, + u_char *msgSalt ); + +int usm_parse_security_parameters ( + u_char *secParams, + size_t remaining, + u_char *secEngineID, + size_t *secEngineIDLen, + u_int *boots_uint, + u_int *time_uint, + char *secName, + size_t *secNameLen, + u_char *signature, + size_t *signature_length, + u_char *salt, + size_t *salt_length, + u_char **data_ptr); + +int usm_check_and_update_timeliness ( + u_char *secEngineID, + size_t secEngineIDLen, + u_int boots_uint, + u_int time_uint, + int *error); + +int usm_generate_out_msg (int, u_char *, size_t, int, int, u_char *, size_t, + char *, size_t, int, u_char *, size_t, void *, + u_char *, size_t *, u_char **, size_t *); + +int usm_process_in_msg (int, size_t, u_char *, int, int, u_char *, size_t, + u_char *, size_t *, char *, size_t *, u_char **, size_t *, + size_t *, void **); + +int usm_check_secLevel(int level, struct usmUser *user); +struct usmUser *usm_get_userList(void); +struct usmUser *usm_get_user(u_char *engineID, size_t engineIDLen, char *name); +struct usmUser *usm_get_user_from_list(u_char *engineID, size_t engineIDLen, + char *name, struct usmUser *userList, + int use_default); +struct usmUser *usm_add_user(struct usmUser *user); +struct usmUser *usm_add_user_to_list(struct usmUser *user, + struct usmUser *userList); +struct usmUser *usm_free_user(struct usmUser *user); +struct usmUser *usm_create_user(void); +struct usmUser *usm_create_initial_user(const char *name, + oid *authProtocol, size_t authProtocolLen, + oid *privProtocol, size_t privProtocolLen); +struct usmUser *usm_cloneFrom_user(struct usmUser *from, struct usmUser *to); +struct usmUser *usm_remove_user(struct usmUser *user); +struct usmUser *usm_remove_user_from_list(struct usmUser *user, + struct usmUser **userList); +char *get_objid(char *line, oid **optr, size_t *len); +void usm_save_users(const char *token, const char *type); +void usm_save_users_from_list(struct usmUser *user, const char *token, + const char *type); +void usm_save_user(struct usmUser *user, const char *token, const char *type); +SNMPCallback usm_store_users; +struct usmUser *usm_read_user(char *line); +void usm_parse_config_usmUser(const char *token, char *line); + +void usm_set_password(const char *token, char *line); +void usm_set_user_password(struct usmUser *user, const char *token, + char *line); +void init_usm(void); +int init_usm_post_config(int majorid, int minorid, void *serverarg, + void *clientarg); + +#ifdef __cplusplus +} +#endif + +#endif /* SNMPUSM_H */ diff --git a/packages/net/snmp/lib/current/include/snmpv3.h b/packages/net/snmp/lib/current/include/snmpv3.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/snmpv3.h @@ -0,0 +1,122 @@ +//========================================================================== +// +// ./lib/current/include/snmpv3.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmpv3.h + */ + +#ifndef SNMPV3_H +#define SNMPV3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_ENGINEID_LENGTH 128 + +int setup_engineID(u_char **eidp, const char *text); +void engineID_conf(const char *word, char *cptr); +void engineBoots_conf(const char *, char *); +void snmpv3_authtype_conf(const char *word, char *cptr); +void snmpv3_privtype_conf(const char *word, char *cptr); +void usm_parse_create_usmUser(const char *token, char *line); +void init_snmpv3(const char *); +int init_snmpv3_post_config(int majorid, int minorid, void *serverarg, + void *clientarg); +void shutdown_snmpv3(const char *type); +int snmpv3_store(int majorID, int minorID, void *serverarg, + void *clientarg); +u_long snmpv3_local_snmpEngineBoots(void); +int snmpv3_clone_engineID(u_char **, size_t* , u_char*, size_t); +int snmpv3_get_engineID(u_char *buf, size_t buflen); +u_char *snmpv3_generate_engineID(int *); +u_long snmpv3_local_snmpEngineTime(void); +int get_default_secLevel(void); +oid *get_default_authtype(size_t *); +oid *get_default_privtype(size_t *); +void snmpv3_set_engineBootsAndTime(int boots, int ttime); + +#ifdef __cplusplus +} +#endif + +#endif /* SNMPV3_H */ diff --git a/packages/net/snmp/lib/current/include/system.h b/packages/net/snmp/lib/current/include/system.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/system.h @@ -0,0 +1,220 @@ +//========================================================================== +// +// ./lib/current/include/system.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#ifndef SNMP_SYSTEM_H +#define SNMP_SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************** + Copyright 1993 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * Definitions for the system dependent library file + */ +#ifdef WIN32 +#include +#include +/* structure of a directory entry */ +typedef struct direct +{ + long d_ino; /* inode number (not used by MS-DOS) */ + int d_namlen; /* Name length */ + char d_name[257];/* file name */ +} _DIRECT; + +/* structure for dir operations */ +typedef struct _dir_struc +{ + char *start; /* Starting position */ + char *curr; /* Current position */ + long size; /* Size of string table */ + long nfiles; /* number if filenames in table */ + struct direct dirstr; /* Directory structure to return */ +} DIR; + +DIR *opendir (const char *filename); +struct direct *readdir (DIR *dirp); +int closedir (DIR *dirp); + +#ifndef HAVE_GETTIMEOFDAY +int gettimeofday (struct timeval *, struct timezone *tz); +#endif +#ifndef HAVE_STRCASECMP +int strcasecmp(const char *s1, const char *s2); +#endif +#ifndef HAVE_STRNCASECMP +int strncasecmp(const char *s1, const char *s2, size_t n); +#endif + +char * winsock_startup (void); +void winsock_cleanup (void); + +#define SOCK_STARTUP winsock_startup() +#define SOCK_CLEANUP winsock_cleanup() +#else +#define SOCK_STARTUP +#define SOCK_CLEANUP +#endif + +in_addr_t get_myaddr (void); +long get_uptime (void); + +#if HAVE_STDARG_H +void DEBUGP (const char *, ...); +#else +void DEBUGP (va_alist); +#endif + +#ifdef HAVE_CPP_UNDERBAR_FUNCTION_DEFINED +#define DEBUGPL(x) \ + DEBUGP("%s():%s,%d: ",__FUNCTION__,__FILE__,__LINE__); DEBUGP x ; +#else +#define DEBUGPL(x) \ + DEBUGP("():%s,%d: ",__FILE__,__LINE__); DEBUGP x ; +#endif + +#ifndef HAVE_STRDUP +char *strdup (const char *); +#endif +#ifndef HAVE_SETENV +int setenv (const char *, const char *, int); +#endif + +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +int calculate_time_diff(struct timeval *, struct timeval *); + +#ifndef HAVE_STRCASESTR +char *strcasestr(const char *, const char *); +#endif + +int mkdirhier(const char *pathname, mode_t mode, int skiplast); + +#ifdef __cplusplus +} +#endif + +#ifndef HAVE_GETTIMEOFDAY +int gettimeofday (struct timeval *, struct timezone *tz); +#endif +#ifndef HAVE_STRCASECMP +int strcasecmp(const char *s1, const char *s2); +#endif +#ifndef HAVE_STRNCASECMP +int strncasecmp(const char *s1, const char *s2, size_t n); +#endif + +#endif /* SNMP_SYSTEM_H */ diff --git a/packages/net/snmp/lib/current/include/tools.h b/packages/net/snmp/lib/current/include/tools.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/tools.h @@ -0,0 +1,225 @@ +//========================================================================== +// +// ./lib/current/include/tools.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * tools.h + */ + +#ifndef _TOOLS_H +#define _TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* + * General acros and constants. + */ +#ifdef WIN32 +# define SNMP_MAXPATH MAX_PATH +#else +# ifdef PATH_MAX +# define SNMP_MAXPATH PATH_MAX +# else +# define SNMP_MAXPATH MAXPATHLEN +# endif +#endif + +#define SNMP_MAXBUF (1024 * 4) +#define SNMP_MAXBUF_MEDIUM 1024 +#define SNMP_MAXBUF_SMALL 512 + +#define SNMP_MAXBUF_MESSAGE 1500 + +#define SNMP_MAXOID 64 + +#define SNMP_FILEMODE_CLOSED 0600 +#define SNMP_FILEMODE_OPEN 0644 + +#define BYTESIZE(bitsize) ((bitsize + 7) >> 3) +#define ROUNDUP8(x) ( ( (x+7) >> 3 ) * 8 ) + + + +#define SNMP_FREE(s) if (s) { free((void *)s); s=NULL; } + + /* XXX Not optimal everywhere. */ +#define SNMP_MALLOC_STRUCT(s) (struct s *) calloc(1, sizeof(struct s)) +#define SNMP_ZERO(s,l) if (s) memset(s, 0, l); + + +#define TOUPPER(c) (c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c) +#define TOLOWER(c) (c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c) + +#define HEX2VAL(s) \ + ((isalpha(s) ? (TOLOWER(s)-'a'+10) : (TOLOWER(s)-'0')) & 0xf) +#define VAL2HEX(s) ( (s) + (((s) >= 10) ? ('a'-10) : '0') ) + + +#define SNMP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define SNMP_MIN(a,b) ((a) > (b) ? (b) : (a)) + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +/* + * QUIT the FUNction: + * e Error code variable + * l Label to goto to cleanup and get out of the function. + * + * XXX It would be nice if the label could be constructed by the + * preprocessor in context. Limited to a single error return value. + * Temporary hack at best. + */ +#define QUITFUN(e, l) \ + if ( (e) != SNMPERR_SUCCESS) { \ + rval = SNMPERR_GENERR; \ + goto l ; \ + } + +/* + * DIFFTIMEVAL + * Set to the difference between (current) and (past). + * + * ASSUMES that all inputs are (struct timeval)'s. + * Cf. system.c:calculate_time_diff(). + */ +#define DIFFTIMEVAL(now, then, diff) \ +{ \ + now.tv_sec--; \ + now.tv_usec += 1000000L; \ + diff.tv_sec = now.tv_sec - then.tv_sec; \ + diff.tv_usec = now.tv_usec - then.tv_usec; \ + if (diff.tv_usec > 1000000L){ \ + diff.tv_usec -= 1000000L; \ + diff.tv_sec++; \ + } \ +} + + +/* + * ISTRANSFORM + * ASSUMES the minimum length for ttype and toid. + */ +#define USM_LENGTH_OID_TRANSFORM 10 + +#define ISTRANSFORM(ttype, toid) \ + !snmp_oid_compare(ttype, USM_LENGTH_OID_TRANSFORM, \ + usm ## toid ## Protocol, USM_LENGTH_OID_TRANSFORM) + +#define ENGINETIME_MAX 2147483647 /* ((2^31)-1) */ +#define ENGINEBOOT_MAX 2147483647 /* ((2^31)-1) */ + + + + +/* + * Prototypes. + */ +void free_zero (void *buf, size_t size); + +u_char *malloc_random (size_t *size); +u_char *malloc_zero (size_t size); +int memdup (u_char **to, const u_char *from, size_t size); + +u_int binary_to_hex (const u_char *input, size_t len, char **output); +int hex_to_binary2 (const u_char *input, size_t len, char **output); + +void dump_chunk (const char *debugtoken, const char *title, const u_char *buf, int size); +char *dump_snmpEngineID (const u_char *buf, size_t *buflen); + +typedef void * marker_t; +marker_t atime_newMarker(void); +void atime_setMarker(marker_t pm); +int atime_ready( marker_t pm, int deltaT); + +#ifdef __cplusplus +} +#endif + +#endif /* _TOOLS_H */ diff --git a/packages/net/snmp/lib/current/include/transform_oids.h b/packages/net/snmp/lib/current/include/transform_oids.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/transform_oids.h @@ -0,0 +1,97 @@ +//========================================================================== +// +// ./lib/current/include/transform_oids.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * transform_oids.h + * + * Numeric MIB names for auth and priv transforms. + */ + + +static oid usmNoAuthProtocol[] = { 1,3,6,1,6,3,10,1,1,1 }; +static oid usmHMACMD5AuthProtocol[] = { 1,3,6,1,6,3,10,1,1,2 }; +static oid usmHMACSHA1AuthProtocol[] = { 1,3,6,1,6,3,10,1,1,3 }; + +static oid usmNoPrivProtocol[] = { 1,3,6,1,6,3,10,1,2,1 }; +static oid usmDESPrivProtocol[] = { 1,3,6,1,6,3,10,1,2,2 }; + + diff --git a/packages/net/snmp/lib/current/include/vacm.h b/packages/net/snmp/lib/current/include/vacm.h new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/include/vacm.h @@ -0,0 +1,239 @@ +//========================================================================== +// +// ./lib/current/include/vacm.h +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * vacm.h + * + * SNMPv3 View-based Access Control Model + */ + +#ifndef VACM_H +#define VACM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SECURITYMODEL 1 +#define SECURITYNAME 2 +#define SECURITYGROUP 3 +#define SECURITYSTORAGE 4 +#define SECURITYSTATUS 5 + +#define ACCESSPREFIX 1 +#define ACCESSMODEL 2 +#define ACCESSLEVEL 3 +#define ACCESSMATCH 4 +#define ACCESSREAD 5 +#define ACCESSWRITE 6 +#define ACCESSNOTIFY 7 +#define ACCESSSTORAGE 8 +#define ACCESSSTATUS 9 + +#define VIEWNAME 1 +#define VIEWSUBTREE 2 +#define VIEWMASK 3 +#define VIEWTYPE 4 +#define VIEWSTORAGE 5 +#define VIEWSTATUS 6 + +#define VACM_MAX_STRING 32 +#define VACMSTRINGLEN 34 /* VACM_MAX_STRING + 2 */ + +struct vacm_securityEntry { + char securityName[VACMSTRINGLEN]; + snmp_ipaddr sourceIp; + snmp_ipaddr sourceMask; + char community[VACMSTRINGLEN]; + struct vacm_securityEntry *next; +}; + +struct vacm_groupEntry { + int securityModel; + char securityName[VACMSTRINGLEN]; + char groupName[VACMSTRINGLEN]; + int storageType; + int status; + + u_long bitMask; + struct vacm_groupEntry *reserved; + struct vacm_groupEntry *next; +}; + +struct vacm_accessEntry { + char groupName[VACMSTRINGLEN]; + char contextPrefix[VACMSTRINGLEN]; + int securityModel; + int securityLevel; + int contextMatch; + char readView[VACMSTRINGLEN]; + char writeView[VACMSTRINGLEN]; + char notifyView[VACMSTRINGLEN]; + int storageType; + int status; + + u_long bitMask; + struct vacm_accessEntry *reserved; + struct vacm_accessEntry *next; +}; + +struct vacm_viewEntry { + char viewName[VACMSTRINGLEN]; + oid viewSubtree[MAX_OID_LEN]; + size_t viewSubtreeLen; + u_char viewMask[VACMSTRINGLEN]; + size_t viewMaskLen; + int viewType; + int viewStorageType; + int viewStatus; + + u_long bitMask; + + struct vacm_viewEntry *reserved; + struct vacm_viewEntry *next; +}; + +void vacm_destroyViewEntry (const char *, oid *, size_t); +void vacm_destroyAllViewEntries (void); + +struct vacm_viewEntry * +vacm_getViewEntry (const char *, oid *, size_t); +/* + * Returns a pointer to the viewEntry with the + * same viewName and viewSubtree + * Returns NULL if that entry does not exist. + */ + +void +vacm_scanViewInit (void); +/* + * Initialized the scan routines so that they will begin at the + * beginning of the list of viewEntries. + * + */ + + +struct vacm_viewEntry * +vacm_scanViewNext (void); +/* + * Returns a pointer to the next viewEntry. + * These entries are returned in no particular order, + * but if N entries exist, N calls to view_scanNext() will + * return all N entries once. + * Returns NULL if all entries have been returned. + * view_scanInit() starts the scan over. + */ + +struct vacm_viewEntry * +vacm_createViewEntry (const char *, oid *, size_t); +/* + * Creates a viewEntry with the given index + * and returns a pointer to it. + * The status of this entry is created as invalid. + */ + +void vacm_destroyGroupEntry (int, const char *); +void vacm_destroyAllGroupEntries (void); +struct vacm_groupEntry *vacm_createGroupEntry (int, const char *); +struct vacm_groupEntry *vacm_getGroupEntry (int, const char *); +void vacm_scanGroupInit (void); +struct vacm_groupEntry *vacm_scanGroupNext (void); + +void vacm_destroyAccessEntry (const char *, const char *, int, int); +void vacm_destroyAllAccessEntries (void); +struct vacm_accessEntry *vacm_createAccessEntry (const char *, const char *, int, int); +struct vacm_accessEntry *vacm_getAccessEntry (const char *, const char *, int, int); +void vacm_scanAccessInit (void); +struct vacm_accessEntry *vacm_scanAccessNext (void); + +void vacm_destroySecurityEntry (const char *); +struct vacm_securityEntry *vacm_createSecurityEntry (const char *); +struct vacm_securityEntry *vacm_getSecurityEntry (const char *); +void vacm_scanSecurityInit (void); +struct vacm_securityEntry *vacm_scanSecurityEntry (void); +int vacm_is_configured(void); + +#ifdef __cplusplus +} +#endif + +#endif /* VACM_H */ diff --git a/packages/net/snmp/lib/current/src/asn1.c b/packages/net/snmp/lib/current/src/asn1.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/asn1.c @@ -0,0 +1,1952 @@ +//========================================================================== +// +// ./lib/current/src/asn1.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * Abstract Syntax Notation One, ASN.1 + * As defined in ISO/IS 8824 and ISO/IS 8825 + * This implements a subset of the above International Standards that + * is sufficient to implement SNMP. + * + * Encodes abstract data types into a machine independent stream of bytes. + * + */ +/********************************************************************** + Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +#include + +#ifdef KINETICS +#include "gw.h" +#endif + +#if HAVE_STRING_H +#include +#else +#include +#endif + +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#ifdef vms +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "int64.h" +#include "snmp_debug.h" +#include "mib.h" + +#ifndef NULL +#define NULL 0 +#endif + +#include "snmp_api.h" +#include "snmp_impl.h" /* to define ERROR_MSG */ + +static +void _asn_size_err(const char *str, size_t wrongsize, size_t rightsize) +{ + char ebuf[128]; + + sprintf(ebuf,"%s size %d: s/b %d",str, wrongsize, rightsize); + ERROR_MSG(ebuf); +} + +static +void _asn_length_err(const char *str, size_t wrongsize, size_t rightsize) +{ + char ebuf[128]; + + sprintf(ebuf,"%s length %d too large: exceeds %d",str, wrongsize, rightsize); + ERROR_MSG(ebuf); +} + +/* + * call after asn_parse_length to verify result. + */ +static +int _asn_parse_length_check(const char *str, + u_char *bufp, u_char *data, + u_long plen, size_t dlen) +{ + char ebuf[128]; + size_t header_len; + + if (bufp == NULL){ + /* error message is set */ + return 1; + } + header_len = bufp - data; + if (((size_t)plen + header_len) > dlen){ + sprintf(ebuf, "%s: message overflow: %d len + %d delta > %d len", + str, (int)plen, (int)header_len, (int)dlen); + ERROR_MSG(ebuf); + return 1; + } + return 0; +} + +/* + * call after asn_build_header to verify result. + */ +static +int _asn_build_header_check(const char *str, u_char *data, + size_t datalen, size_t typedlen) +{ + char ebuf[128]; + + if (data == NULL){ + /* error message is set */ + return 1; + } + if (datalen < typedlen){ + sprintf(ebuf, "%s: bad header, length too short: %d < %d", str, datalen, typedlen); + ERROR_MSG(ebuf); + return 1; + } + return 0; +} + +/* checks the incoming packet for validity and returns its size or 0 */ +int +asn_check_packet (u_char *pkt, size_t len) +{ + u_long asn_length; + + if (len < 2) + return 0; /* always too short */ + + if (*pkt != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; /* wrong type */ + + if (*(pkt+1) & 0x80) { + /* long length */ + if ((int)len < (int)(*(pkt+1) & ~0x80)+2) + return 0; /* still to short, incomplete length */ + asn_parse_length(pkt+1, &asn_length); + return (asn_length + 2 + (*(pkt+1) & ~0x80)); + } else { + /* short length */ + return (*(pkt+1) + 2); + } +} + +static +int _asn_bitstring_check(const char * str, u_long asn_length, u_char datum) +{ + char ebuf[128]; + + if (asn_length < 1){ + sprintf(ebuf,"%s: length %d too small", str, (int)asn_length); + ERROR_MSG(ebuf); + return 1; + } + if (datum > 7){ + sprintf(ebuf,"%s: datum %d >7: too large", str, (int)(datum)); + ERROR_MSG(ebuf); + return 1; + } + return 0; +} + +/* + * asn_parse_int - pulls a long out of an ASN int type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_parse_int( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + long *intp IN/OUT - pointer to start of output buffer + int intsize IN - size of output buffer +*/ + +u_char * +asn_parse_int(u_char *data, + size_t *datalength, + u_char *type, + long *intp, + size_t intsize) +{ +/* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + static const char *errpre = "parse int"; + register u_char *bufp = data; + u_long asn_length; + register long value = 0; + + if (intsize != sizeof (long)){ + _asn_size_err(errpre, intsize, sizeof(long)); + return NULL; + } + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) + return NULL; + + if ((size_t)asn_length > intsize){ + _asn_length_err(errpre, (size_t)asn_length, intsize); + return NULL; + } + + *datalength -= (int)asn_length + (bufp - data); + if (*bufp & 0x80) + value = -1; /* integer is negative */ + + DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length); + + while(asn_length--) + value = (value << 8) | *bufp++; + + DEBUGMSG(("dump_recv", " ASN Integer:\t%ld (0x%.2X)\n", value, value)); + + *intp = value; + return bufp; +} + + +/* + * asn_parse_unsigned_int - pulls an unsigned long out of an ASN int type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_parse_unsigned_int( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + u_long *intp IN/OUT - pointer to start of output buffer + int intsize IN - size of output buffer + */ +u_char * +asn_parse_unsigned_int(u_char *data, + size_t *datalength, + u_char *type, + u_long *intp, + size_t intsize) +{ +/* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + static const char *errpre = "parse uint"; + register u_char *bufp = data; + u_long asn_length; + register u_long value = 0; + + if (intsize != sizeof (long)){ + _asn_size_err(errpre, intsize, sizeof(long)); + return NULL; + } + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) + return NULL; + + if (((int)asn_length > (intsize + 1)) || + (((int)asn_length == intsize + 1) && *bufp != 0x00)){ + _asn_length_err(errpre, (size_t)asn_length, intsize); + return NULL; + } + *datalength -= (int)asn_length + (bufp - data); + if (*bufp & 0x80) + value = ~value; /* integer is negative */ + + DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length); + + while(asn_length--) + value = (value << 8) | *bufp++; + + DEBUGMSG(("dump_recv", " ASN UInteger:\t%ld (0x%.2X)\n", value, value)); + + *intp = value; + return bufp; +} + + +/* + * asn_build_int - builds an ASN object containing an integer. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_int( + u_char *data IN - pointer to start of output buffer + int *datalength IN/OUT - number of valid bytes left in buffer + int type IN - asn type of object + long *intp IN - pointer to start of long integer + int intsize IN - size of input buffer + */ +u_char * +asn_build_int(u_char *data, + size_t *datalength, + u_char type, + long *intp, + size_t intsize) +{ +/* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + static const char *errpre = "build int"; + register long integer; + register u_long mask; + + if (intsize != sizeof (long)){ + _asn_size_err(errpre, intsize, sizeof(long)); + return NULL; + } + integer = *intp; + /* + * Truncate "unnecessary" bytes off of the most significant end of this + * 2's complement integer. There should be no sequence of 9 + * consecutive 1's or 0's at the most significant end of the + * integer. + */ + mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); + /* mask is 0xFF800000 on a big-endian machine */ + while((((integer & mask) == 0) || ((integer & mask) == mask)) + && intsize > 1){ + intsize--; + integer <<= 8; + } + data = asn_build_header(data, datalength, type, intsize); + if (_asn_build_header_check(errpre,data,*datalength,intsize)) + return NULL; + + *datalength -= intsize; + mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + while(intsize--){ + *data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1))); + integer <<= 8; + } + return data; +} + + +/* + * asn_build_unsigned_int - builds an ASN object containing an integer. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_unsigned_int( + u_char *data IN - pointer to start of output buffer + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + u_long *intp IN - pointer to start of long integer + int intsize IN - size of input buffer + */ +u_char * +asn_build_unsigned_int(u_char *data, + size_t *datalength, + u_char type, + u_long *intp, + size_t intsize) +{ +/* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + static const char *errpre = "build uint"; + register u_long integer; + register u_long mask; + int add_null_byte = 0; + + if (intsize != sizeof (long)){ + _asn_size_err(errpre, intsize, sizeof(long)); + return NULL; + } + integer = *intp; + mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + if ((u_char)((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80){ + /* if MSB is set */ + add_null_byte = 1; + intsize++; + } else { + /* + * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer. + * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the + * integer. + */ + mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); + /* mask is 0xFF800000 on a big-endian machine */ + while((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1){ + intsize--; + integer <<= 8; + } + } + data = asn_build_header(data, datalength, type, intsize); + if (_asn_build_header_check(errpre,data,*datalength,intsize)) + return NULL; + + *datalength -= intsize; + if (add_null_byte == 1){ + *data++ = '\0'; + intsize--; + } + mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + while(intsize--){ + *data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1))); + integer <<= 8; + } + return data; +} + + +/* + * asn_parse_string - pulls an octet string out of an ASN octet string type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * "string" is filled with the octet string. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + * + * u_char * asn_parse_string( + * u_char *data IN - pointer to start of object + * int *datalength IN/OUT - number of valid bytes left in buffer + * u_char *type OUT - asn type of object + * u_char *string IN/OUT - pointer to start of output buffer + * int *strlength IN/OUT - size of output buffer + * + * + * ASN.1 octet string ::= primstring | cmpdstring + * primstring ::= 0x04 asnlength byte {byte}* + * cmpdstring ::= 0x24 asnlength string {string}* + */ +u_char * +asn_parse_string(u_char *data, + size_t *datalength, + u_char *type, + u_char *string, + size_t *strlength) +{ + static const char *errpre = "parse string"; + u_char *bufp = data; + u_long asn_length; + + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) + return NULL; + + if ((int)asn_length > *strlength){ + _asn_length_err(errpre, (size_t)asn_length, *strlength); + return NULL; + } + + DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length); + + memmove(string, bufp, asn_length); + if (*strlength > (int)asn_length) + string[asn_length] = 0; + *strlength = (int)asn_length; + *datalength -= (int)asn_length + (bufp - data); + + DEBUGIF("dump_recv") { + char *buf = (char *)malloc(1+asn_length); + sprint_asciistring(buf, string, asn_length); + DEBUGMSG(("dump_recv", " ASN String:\t%s\n", buf)); + free (buf); + } + + return bufp + asn_length; +} + + +/* + * asn_build_string - Builds an ASN octet string object containing the input string. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_string( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + u_char *string IN - pointer to start of input buffer + int strlength IN - size of input buffer + */ +u_char * +asn_build_string(u_char *data, + size_t *datalength, + u_char type, + const u_char *string, + size_t strlength) +{ +/* + * ASN.1 octet string ::= primstring | cmpdstring + * primstring ::= 0x04 asnlength byte {byte}* + * cmpdstring ::= 0x24 asnlength string {string}* + * This code will never send a compound string. + */ + data = asn_build_header(data, datalength, type, strlength); + if (_asn_build_header_check("build string", data, *datalength, strlength)) + return NULL; + + if (strlength) { + if (string == NULL) { + memset(data, 0, strlength); + } else { + memmove(data, string, strlength); + } + } + *datalength -= strlength; + return data + strlength; +} + + + +/* + * asn_parse_header - interprets the ID and length of the current object. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * in this object following the id and length. + * + * Returns a pointer to the first byte of the contents of this object. + * Returns NULL on any error. + + u_char * asn_parse_header( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + */ +u_char * +asn_parse_header(u_char *data, + size_t *datalength, + u_char *type) +{ + register u_char *bufp; + u_long asn_length; + + if (!data || !datalength || !type) { + ERROR_MSG("parse header: NULL pointer"); + return NULL; + } + bufp = data; + /* this only works on data types < 30, i.e. no extension octets */ + if (IS_EXTENSION_ID(*bufp)){ + ERROR_MSG("can't process ID >= 30"); + return NULL; + } + *type = *bufp; + bufp = asn_parse_length(bufp + 1, &asn_length); + if (_asn_parse_length_check("parse header", bufp, data, asn_length, *datalength)) + return NULL; + + DEBUGDUMPSETUP("dump_recv", data, (bufp-data)); + DEBUGMSG(("dump_recv", " ASN Header: 0x%.2X, len = %d (0x%X)\n", *data, + asn_length, asn_length)); + +#ifdef OPAQUE_SPECIAL_TYPES + + if ((*type == ASN_OPAQUE) && + (*bufp == ASN_OPAQUE_TAG1)) { + DEBUGINDENTMORE(); + DEBUGDUMPSETUP("dump_recv", data, 1); + DEBUGMSG(("dump_recv", "Opaque:\t%.2x\n", *bufp)); + DEBUGINDENTLESS(); + + /* check if 64-but counter */ + switch(*(bufp+1)) { + case ASN_OPAQUE_COUNTER64: + case ASN_OPAQUE_U64: + case ASN_OPAQUE_FLOAT: + case ASN_OPAQUE_DOUBLE: + case ASN_OPAQUE_I64: + *type = *(bufp+1); + break; + + default: + /* just an Opaque */ + *datalength = (int)asn_length; + return bufp; + } + /* value is encoded as special format */ + bufp = asn_parse_length(bufp + 2, &asn_length); + if (_asn_parse_length_check("parse opaque header", bufp, data, + asn_length, *datalength)) + return NULL; + } +#endif /* OPAQUE_SPECIAL_TYPES */ + + *datalength = (int)asn_length; + + return bufp; +} + +/* + * same as asn_parse_header with test for expected type. + */ +u_char * +asn_parse_sequence(u_char *data, + size_t *datalength, + u_char *type, + u_char expected_type, /* must be this type */ + const char *estr) /* error message prefix */ +{ + data = asn_parse_header(data, datalength, type); + if (data && (*type != expected_type)) { + char ebuf[128]; + sprintf(ebuf, "%s header type %02X: s/b %02X", estr, + (u_char)*type, (u_char)expected_type); + ERROR_MSG(ebuf); + return NULL; + } + return data; +} + + + +/* + * asn_build_header - builds an ASN header for an object with the ID and + * length specified. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * in this object following the id and length. + * + * This only works on data types < 30, i.e. no extension octets. + * The maximum length is 0xFFFF; + * + * Returns a pointer to the first byte of the contents of this object. + * Returns NULL on any error. + + u_char * asn_build_header( + u_char *data IN - pointer to start of object + size_t *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + size_t length IN - length of object + */ +u_char * +asn_build_header (u_char *data, + size_t *datalength, + u_char type, + size_t length) +{ + char ebuf[128]; + + if (*datalength < 1){ + sprintf(ebuf, "bad header length < 1 :%d, %d", *datalength, length); + ERROR_MSG(ebuf); + return NULL; + } + *data++ = type; + (*datalength)--; + return asn_build_length(data, datalength, length); +} + +/* + * asn_build_sequence - builds an ASN header for a sequence with the ID and + * length specified. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * in this object following the id and length. + * + * This only works on data types < 30, i.e. no extension octets. + * The maximum length is 0xFFFF; + * + * Returns a pointer to the first byte of the contents of this object. + * Returns NULL on any error. + + u_char * asn_build_sequence( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + int length IN - length of object + */ +u_char * +asn_build_sequence(u_char *data, + size_t *datalength, + u_char type, + size_t length) +{ + static const char *errpre = "build seq"; + char ebuf[128]; + + if (*datalength < 4){ + sprintf(ebuf, "%s: length %d < 4: PUNT", errpre, (int)*datalength); + ERROR_MSG(ebuf); + return NULL; + } + *datalength -= 4; + *data++ = type; + *data++ = (u_char)(0x02 | ASN_LONG_LEN); + *data++ = (u_char)((length >> 8) & 0xFF); + *data++ = (u_char)(length & 0xFF); + return data; +} + +/* + * asn_parse_length - interprets the length of the current object. + * On exit, length contains the value of this length field. + * + * Returns a pointer to the first byte after this length + * field (aka: the start of the data field). + * Returns NULL on any error. + + u_char * asn_parse_length( + u_char *data IN - pointer to start of length field + u_long *length OUT - value of length field + */ +u_char * +asn_parse_length(u_char *data, + u_long *length) +{ + static const char *errpre = "parse length"; + char ebuf[128]; + register u_char lengthbyte; + + if (!data || !length) { + ERROR_MSG("parse length: NULL pointer"); + return NULL; + } + lengthbyte = *data; + + if (lengthbyte & ASN_LONG_LEN){ + lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */ + if (lengthbyte == 0){ + sprintf(ebuf, "%s: indefinite length not supported", errpre); + ERROR_MSG(ebuf); + return NULL; + } + if (lengthbyte > sizeof(long)){ + sprintf(ebuf, "%s: data length %d > %d not supported", errpre, + lengthbyte, sizeof(long)); + ERROR_MSG(ebuf); + return NULL; + } + data++; + *length = 0; /* protect against short lengths */ + while(lengthbyte--) { + *length <<= 8; + *length |= *data++; + } + return data; + } else { /* short asnlength */ + *length = (long)lengthbyte; + return data + 1; + } +} + +/* + + u_char * asn_build_length( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + int length IN - length of object + */ +u_char * +asn_build_length(u_char *data, + size_t *datalength, + size_t length) +{ + static const char *errpre = "build length"; + char ebuf[128]; + + u_char *start_data = data; + + /* no indefinite lengths sent */ + if (length < 0x80){ + if (*datalength < 1){ + sprintf(ebuf, "%s: bad length < 1 :%d, %d",errpre,*datalength,length); + ERROR_MSG(ebuf); + return NULL; + } + *data++ = (u_char)length; + } else if (length <= 0xFF){ + if (*datalength < 2){ + sprintf(ebuf, "%s: bad length < 2 :%d, %d",errpre,*datalength,length); + ERROR_MSG(ebuf); + return NULL; + } + *data++ = (u_char)(0x01 | ASN_LONG_LEN); + *data++ = (u_char)length; + } else { /* 0xFF < length <= 0xFFFF */ + if (*datalength < 3){ + sprintf(ebuf, "%s: bad length < 3 :%d, %d",errpre,*datalength,length); + ERROR_MSG(ebuf); + return NULL; + } + *data++ = (u_char)(0x02 | ASN_LONG_LEN); + *data++ = (u_char)((length >> 8) & 0xFF); + *data++ = (u_char)(length & 0xFF); + } + *datalength -= (data - start_data); + return data; + +} + +/* + * asn_parse_objid - pulls an object indentifier out of an ASN object identifier type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * "objid" is filled with the object identifier. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_parse_objid( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + oid *objid IN/OUT - pointer to start of output buffer + int *objidlength IN/OUT - number of sub-id's in objid + */ +u_char * +asn_parse_objid(u_char *data, + size_t *datalength, + u_char *type, + oid *objid, + size_t *objidlength) +{ +/* + * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* + * subidentifier ::= {leadingbyte}* lastbyte + * leadingbyte ::= 1 7bitvalue + * lastbyte ::= 0 7bitvalue + */ + register u_char *bufp = data; + register oid *oidp = objid + 1; + register u_long subidentifier; + register long length; + u_long asn_length; + + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check("parse objid", bufp, data, + asn_length, *datalength)) + return NULL; + + *datalength -= (int)asn_length + (bufp - data); + + DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length); + + /* Handle invalid object identifier encodings of the form 06 00 robustly */ + if (asn_length == 0) + objid[0] = objid[1] = 0; + + length = asn_length; + (*objidlength)--; /* account for expansion of first byte */ + + while (length > 0 && (*objidlength)-- > 0){ + subidentifier = 0; + do { /* shift and add in low order 7 bits */ + subidentifier = (subidentifier << 7) + (*(u_char *)bufp & ~ASN_BIT8); + length--; + } while (*(u_char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */ +/*?? note, this test will never be true, since the largest value + of subidentifier is the value of MAX_SUBID! */ + if (subidentifier > (u_long)MAX_SUBID){ + ERROR_MSG("subidentifier too large"); + return NULL; + } + *oidp++ = (oid)subidentifier; + } + + /* + * The first two subidentifiers are encoded into the first component + * with the value (X * 40) + Y, where: + * X is the value of the first subidentifier. + * Y is the value of the second subidentifier. + */ + subidentifier = (u_long)objid[1]; + if (subidentifier == 0x2B){ + objid[0] = 1; + objid[1] = 3; + } else { + if (subidentifier < 40) { + objid[0] = 0; + objid[1] = subidentifier; + } else if (subidentifier < 80) { + objid[0] = 1; + objid[1] = subidentifier - 40; + } else if (subidentifier < 120) { + objid[0] = 2; + objid[1] = subidentifier - 80; + } else { + objid[1] = (subidentifier % 40); + objid[0] = ((subidentifier - objid[1]) / 40); + } + } + + *objidlength = (int)(oidp - objid); + + DEBUGMSG(("dump_recv", " ASN ObjID: ")); + DEBUGMSGOID(("dump_recv", objid, *objidlength)); + DEBUGMSG(("dump_recv", "\n")); + return bufp; +} + +/* + * asn_build_objid - Builds an ASN object identifier object containing the + * input string. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_objid( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + int type IN - asn type of object + oid *objid IN - pointer to start of input buffer + int objidlength IN - number of sub-id's in objid + */ +u_char * +asn_build_objid(u_char *data, + size_t *datalength, + u_char type, + oid *objid, + size_t objidlength) +{ +/* + * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* + * subidentifier ::= {leadingbyte}* lastbyte + * leadingbyte ::= 1 7bitvalue + * lastbyte ::= 0 7bitvalue + */ + size_t asnlength; + register oid *op = objid; + u_char objid_size[MAX_OID_LEN]; + register u_long objid_val; + u_long first_objid_val; + register int i; + + /* check if there are at least 2 sub-identifiers */ + if (objidlength == 0){ + /* there are not, so make OID have two with value of zero */ + objid_val = 0; + objidlength = 2; + } else if (objidlength == 1){ + /* encode the first value */ + objid_val = (op[0] * 40); + objidlength = 2; + op++; + } else { + /* combine the first two values */ + if ( op[1] > 40 ) { + ERROR_MSG("build objid: bad second subidentifier"); + return NULL; + } + objid_val = (op[0] * 40) + op[1]; + op += 2; + } + first_objid_val = objid_val; + + /* calculate the number of bytes needed to store the encoded value */ + for (i = 1, asnlength = 0;;) { + if (objid_val < (unsigned)0x80) { + objid_size[i] = 1; + asnlength += 1; + } else if (objid_val < (unsigned)0x4000) { + objid_size[i] = 2; + asnlength += 2; + } else if (objid_val < (unsigned)0x200000) { + objid_size[i] = 3; + asnlength += 3; + } else if (objid_val < (unsigned)0x10000000) { + objid_size[i] = 4; + asnlength += 4; + } else { + objid_size[i] = 5; + asnlength += 5; + } + i++; + if (i >= (int)objidlength) + break; + objid_val = *op++; + } + + /* store the ASN.1 tag and length */ + data = asn_build_header(data, datalength, type, asnlength); + if (_asn_build_header_check("build objid", data, *datalength, asnlength)) + return NULL; + + /* store the encoded OID value */ + for (i = 1, objid_val = first_objid_val, op = objid+2; + i < (int)objidlength; + i++) { + if (i != 1) objid_val = *op++; + switch (objid_size[i]) { + case 1: + *data++ = (u_char)objid_val; + break; + + case 2: + *data++ = (u_char)((objid_val>>7) | 0x80); + *data++ = (u_char)(objid_val & 0x07f); + break; + + case 3: + *data++ = (u_char)((objid_val>>14) | 0x80); + *data++ = (u_char)((objid_val>>7 & 0x7f) | 0x80); + *data++ = (u_char)(objid_val & 0x07f); + break; + + case 4: + *data++ = (u_char)((objid_val>>21) | 0x80); + *data++ = (u_char)((objid_val>>14 & 0x7f) | 0x80); + *data++ = (u_char)((objid_val>>7 & 0x7f) | 0x80); + *data++ = (u_char)(objid_val & 0x07f); + break; + + case 5: + *data++ = (u_char)((objid_val>>28) | 0x80); + *data++ = (u_char)((objid_val>>21 & 0x7f) | 0x80); + *data++ = (u_char)((objid_val>>14 & 0x7f) | 0x80); + *data++ = (u_char)((objid_val>>7 & 0x7f) | 0x80); + *data++ = (u_char)(objid_val & 0x07f); + break; + } + } + + /* return the length and data ptr */ + *datalength -= asnlength; + return data; +} + +/* + * asn_parse_null - Interprets an ASN null type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_parse_null( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + */ +u_char * +asn_parse_null(u_char *data, + size_t *datalength, + u_char *type) +{ +/* + * ASN.1 null ::= 0x05 0x00 + */ + register u_char *bufp = data; + u_long asn_length; + + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (bufp == NULL){ + ERROR_MSG("parse null: bad length"); + return NULL; + } + if (asn_length != 0){ + ERROR_MSG("parse null: malformed ASN.1 null"); + return NULL; + } + + *datalength -= (bufp - data); + + DEBUGDUMPSETUP("dump_recv", data, bufp - data); + DEBUGMSG(("dump_recv", " ASN NULL\n")); + + return bufp + asn_length; +} + + +/* + * asn_build_null - Builds an ASN null object. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_null( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + */ +u_char * +asn_build_null(u_char *data, + size_t *datalength, + u_char type) +{ +/* + * ASN.1 null ::= 0x05 0x00 + */ + return asn_build_header(data, datalength, type, 0); +} + +/* + * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * "string" is filled with the bit string. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_parse_bitstring( + u_char *data IN - pointer to start of object + size_t *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + u_char *string IN/OUT - pointer to start of output buffer + size_t *strlength IN/OUT - size of output buffer + */ +u_char * +asn_parse_bitstring(u_char *data, + size_t *datalength, + u_char *type, + u_char *string, + size_t *strlength) +{ +/* + * bitstring ::= 0x03 asnlength unused {byte}* + */ + static const char *errpre = "parse bitstring"; + register u_char *bufp = data; + u_long asn_length; + + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check(errpre, bufp, data, + asn_length, *datalength)) + return NULL; + + if ((size_t)asn_length > *strlength){ + _asn_length_err(errpre, (size_t)asn_length, *strlength); + return NULL; + } + if (_asn_bitstring_check(errpre, asn_length, *bufp)) + return NULL; + + DEBUGDUMPSETUP("dump_recv", data, bufp - data); + DEBUGMSG(("dump_recv", " ASN Bitstring: ")); + DEBUGMSGHEX(("dump_recv", data, asn_length)); + + memmove(string, bufp, asn_length); + *strlength = (int)asn_length; + *datalength -= (int)asn_length + (bufp - data); + return bufp + asn_length; +} + + +/* + * asn_build_bitstring - Builds an ASN bit string object containing the + * input string. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_bitstring( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + u_char *string IN - pointer to start of input buffer + int strlength IN - size of input buffer + */ +u_char * +asn_build_bitstring(u_char *data, + size_t *datalength, + u_char type, + u_char *string, + size_t strlength) +{ +/* + * ASN.1 bit string ::= 0x03 asnlength unused {byte}* + */ + static const char *errpre = "build bitstring"; + if (_asn_bitstring_check(errpre, strlength, *string)) + return NULL; + + data = asn_build_header(data, datalength, type, strlength); + if (_asn_build_header_check(errpre,data,*datalength,strlength)) + return NULL; + + memmove(data, string, strlength); + *datalength -= strlength; + return data + strlength; +} + + +/* + * asn_parse_unsigned_int64 - pulls a 64 bit unsigned long out of an ASN int + * type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_parse_unsigned_int64( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + struct counter64 *cp IN/OUT - pointer to counter struct + int countersize IN - size of output buffer + */ +u_char * +asn_parse_unsigned_int64(u_char *data, + size_t *datalength, + u_char *type, + struct counter64 *cp, + size_t countersize) +{ +/* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + static const char *errpre = "parse uint64"; + const int uint64sizelimit = (4 * 2) + 1; + register u_char *bufp = data; + u_long asn_length; + register u_long low = 0, high = 0; + + if (countersize != sizeof(struct counter64)){ + _asn_size_err(errpre, countersize, sizeof(struct counter64)); + return NULL; + } + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) + return NULL; + + DEBUGDUMPSETUP("dump_recv", data, bufp - data); +#ifdef OPAQUE_SPECIAL_TYPES +/* 64 bit counters as opaque */ + if ((*type == ASN_OPAQUE) && + (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && + (*bufp == ASN_OPAQUE_TAG1) && + ((*(bufp+1) == ASN_OPAQUE_COUNTER64) || + (*(bufp+1) == ASN_OPAQUE_U64))) { + DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1))); + + /* change type to Counter64 or U64 */ + *type = *(bufp+1); + /* value is encoded as special format */ + bufp = asn_parse_length(bufp + 2, &asn_length); + if (_asn_parse_length_check("parse opaque uint64", bufp, data, + asn_length, *datalength)) + return NULL; + } +#endif /* OPAQUE_SPECIAL_TYPES */ + if (((int)asn_length > uint64sizelimit) || + (((int)asn_length == uint64sizelimit) && *bufp != 0x00)){ + _asn_length_err(errpre, (size_t)asn_length, uint64sizelimit); + return NULL; + } + *datalength -= (int)asn_length + (bufp - data); + if (*bufp & 0x80){ + low = ~low; /* integer is negative */ + high = ~high; + } + + while(asn_length--){ + high = (high << 8) | ((low & 0xFF000000) >> 24); + low = (low << 8) | *bufp++; + } + + cp->low = low; + cp->high = high; + + DEBUGIF("dump_recv") { + char i64buf[I64CHARSZ+1]; + printU64(i64buf, cp); + } + + return bufp; +} + + +/* + * asn_build_unsigned_int64 - builds an ASN object containing a 64 bit integer. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_unsigned_int64( + u_char *data IN - pointer to start of output buffer + size_t *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + struct counter64 *cp IN - pointer to counter struct + size_t countersize IN - size of input buffer + */ +u_char * +asn_build_unsigned_int64(u_char *data, + size_t *datalength, + u_char type, + struct counter64 *cp, + size_t countersize) +{ +/* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + + register u_long low, high; + register u_long mask, mask2; + int add_null_byte = 0; + size_t intsize; + + if (countersize != sizeof(struct counter64)){ + _asn_size_err("build uint64", countersize, sizeof(struct counter64)); + return NULL; + } + intsize = 8; + low = cp->low; + high = cp->high; + mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + if ((u_char)((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80){ + /* if MSB is set */ + add_null_byte = 1; + intsize++; + } else { + /* + * Truncate "unnecessary" bytes off of the most significant end of this 2's + * complement integer. + * There should be no sequence of 9 consecutive 1's or 0's at the most + * significant end of the integer. + */ + mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); + /* mask2 is 0xFF800000 on a big-endian machine */ + while((((high & mask2) == 0) || ((high & mask2) == mask2)) && intsize > 1){ + intsize--; + high = (high << 8) + | ((low & mask) >> (8 * (sizeof(long) - 1))); + low <<= 8; + } + } +#ifdef OPAQUE_SPECIAL_TYPES +/* encode a Counter64 as an opaque (it also works in SNMPv1) */ + /* turn into Opaque holding special tagged value */ + if (type == ASN_OPAQUE_COUNTER64) { + /* put the tag and length for the Opaque wrapper */ + data = asn_build_header(data, datalength, ASN_OPAQUE, intsize+3); + if (_asn_build_header_check("build counter u64", data, *datalength, intsize+3)) + return NULL; + + /* put the special tag and length */ + *data++ = ASN_OPAQUE_TAG1; + *data++ = ASN_OPAQUE_COUNTER64; + *data++ = (u_char)intsize; + *datalength = *datalength - 3; + } + else +/* Encode the Unsigned int64 in an opaque */ + /* turn into Opaque holding special tagged value */ + if (type == ASN_OPAQUE_U64) { + /* put the tag and length for the Opaque wrapper */ + data = asn_build_header(data, datalength, ASN_OPAQUE, intsize+3); + if (_asn_build_header_check("build opaque u64", data, *datalength, intsize+3)) + return NULL; + + /* put the special tag and length */ + *data++ = ASN_OPAQUE_TAG1; + *data++ = ASN_OPAQUE_U64; + *data++ = (u_char)intsize; + *datalength = *datalength - 3; + } + else + { +#endif /* OPAQUE_SPECIAL_TYPES */ + data = asn_build_header(data, datalength, type, intsize); + if (_asn_build_header_check("build uint64", data, *datalength, intsize)) + return NULL; + +#ifdef OPAQUE_SPECIAL_TYPES + } +#endif /* OPAQUE_SPECIAL_TYPES */ + *datalength -= intsize; + if (add_null_byte == 1){ + *data++ = '\0'; + intsize--; + } + while(intsize--){ + *data++ = (u_char)((high & mask) >> (8 * (sizeof(long) - 1))); + high = (high << 8) + | ((low & mask) >> (8 * (sizeof(long) - 1))); + low <<= 8; + + } + return data; +} + +#ifdef OPAQUE_SPECIAL_TYPES + +/* + + u_char * asn_parse_signed_int64( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + struct counter64 *cp IN/OUT - pointer to counter struct + int countersize IN - size of output buffer + */ + +u_char * +asn_parse_signed_int64(u_char *data, + size_t *datalength, + u_char *type, + struct counter64 *cp, + size_t countersize) +{ + static const char *errpre = "parse int64"; + const int int64sizelimit = (4 * 2) + 1; + char ebuf[128]; + register u_char *bufp = data; + u_long asn_length; + register u_int low = 0, high = 0; + + if (countersize != sizeof(struct counter64)){ + _asn_size_err(errpre, countersize, sizeof(struct counter64)); + return NULL; + } + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) + return NULL; + + DEBUGDUMPSETUP("dump_recv", data, bufp - data); + if ((*type == ASN_OPAQUE) && + (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && + (*bufp == ASN_OPAQUE_TAG1) && + (*(bufp+1) == ASN_OPAQUE_I64)) { + DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1))); + /* change type to Int64 */ + *type = *(bufp+1); + /* value is encoded as special format */ + bufp = asn_parse_length(bufp + 2, &asn_length); + if (_asn_parse_length_check("parse opaque int64", bufp, data, + asn_length, *datalength)) + return NULL; + } + /* this should always have been true until snmp gets int64 PDU types */ + else { + sprintf(ebuf, "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)", + errpre, *type, (int)asn_length, *bufp, *(bufp+1)); + ERROR_MSG(ebuf); + return NULL; + } + if (((int)asn_length > int64sizelimit) || + (((int)asn_length == int64sizelimit) && *bufp != 0x00)){ + _asn_length_err(errpre, (size_t)asn_length, int64sizelimit); + return NULL; + } + *datalength -= (int)asn_length + (bufp - data); + if (*bufp & 0x80){ + low = ~low; /* integer is negative */ + high = ~high; + } + + while(asn_length--){ + high = (high << 8) | ((low & 0xFF000000) >> 24); + low = (low << 8) | *bufp++; + } + + cp->low = low; + cp->high = high; + + DEBUGIF("dump_recv") { + char i64buf[I64CHARSZ+1]; + printI64(i64buf, cp); + } + + return bufp; +} + + +/* + + u_char * asn_build_signed_int64( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + struct counter64 *cp IN - pointer to counter struct + int countersize IN - size of input buffer + */ +u_char * +asn_build_signed_int64(u_char *data, + size_t *datalength, + u_char type, + struct counter64 *cp, + size_t countersize) +{ +/* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + + struct counter64 c64; + register u_int mask, mask2; + u_long low, high; + size_t intsize; + + if (countersize != sizeof(struct counter64)){ + _asn_size_err("build int64", countersize, sizeof(struct counter64)); + return NULL; + } + intsize = 8; + memcpy(&c64, cp, sizeof(struct counter64)); /* we're may modify it */ + low = c64.low; + high = c64.high; + + /* + * Truncate "unnecessary" bytes off of the most significant end of this + * 2's complement integer. There should be no sequence of 9 + * consecutive 1's or 0's at the most significant end of the + * integer. + */ + mask = ((u_int) 0xFF) << (8 * (sizeof(u_int) - 1)); + mask2 = ((u_int) 0x1FF) << ((8 * (sizeof(u_int) - 1)) - 1); + /* mask is 0xFF800000 on a big-endian machine */ + while((((high & mask2) == 0) || ((high & mask2) == mask2)) && intsize > 1){ + intsize--; + high = (high << 8) + | ((low & mask) >> (8 * (sizeof(u_int) - 1))); + low <<= 8; + } + /* until a real int64 gets incorperated into SNMP, we are going to + encode it as an opaque instead. First, we build the opaque + header and then the int64 tag type we use to mark it as an + int64 in the opaque string. */ + data = asn_build_header(data, datalength, ASN_OPAQUE, intsize+3); + if (_asn_build_header_check("build int64", data, *datalength, intsize+3)) + return NULL; + + *data++ = ASN_OPAQUE_TAG1; + *data++ = ASN_OPAQUE_I64; + *data++ = (u_char)intsize; + *datalength -= (3 + intsize); + + while(intsize--){ + *data++ = (u_char)((high & mask) >> (8 * (sizeof(u_int) - 1))); + high = (high << 8) + | ((low & mask) >> (8 * (sizeof(u_int) - 1))); + low <<= 8; + } + return data; +} + +/* + * asn_parse_float - pulls a single precision floating-point out of an opaque type. + * + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_parse_float( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + float *floatp IN/OUT - pointer to float + int floatsize IN - size of output buffer + */ +u_char * +asn_parse_float(u_char *data, + size_t *datalength, + u_char *type, + float *floatp, + size_t floatsize) +{ + register u_char *bufp = data; + u_long asn_length; + union { + float floatVal; + long longVal; + u_char c[sizeof(float)]; + } fu; + + if (floatsize != sizeof(float)){ + _asn_size_err("parse float", floatsize, sizeof(float)); + return NULL; + } + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check("parse float", bufp, data, + asn_length, *datalength)) + return NULL; + + DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length); +/* the float is encoded as an opaque */ + if ((*type == ASN_OPAQUE) && + (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) && + (*bufp == ASN_OPAQUE_TAG1) && + (*(bufp+1) == ASN_OPAQUE_FLOAT)) { + DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1))); + + /* value is encoded as special format */ + bufp = asn_parse_length(bufp + 2, &asn_length); + if (_asn_parse_length_check("parse opaque float", bufp, data, + asn_length, *datalength)) + return NULL; + + /* change type to Float */ + *type = ASN_OPAQUE_FLOAT; + } + + if (asn_length != sizeof(float)) { + _asn_size_err("parse seq float", asn_length, sizeof(float)); + return NULL; + } + + *datalength -= (int)asn_length + (bufp - data); + memcpy(&fu.c[0], bufp, asn_length); + + /* correct for endian differences */ + fu.longVal = ntohl(fu.longVal); + + *floatp = fu.floatVal; + + DEBUGMSG(("dump_recv", "%f",*floatp)); + return bufp; +} + +/* + * asn_build_float - builds an ASN object containing a single precision floating-point + * number in an Opaque value. + * + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns NULL on any error. + + u_char * asn_build_float( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + float *floatp IN - pointer to float + int floatsize IN - size of input buffer + */ +u_char * +asn_build_float(u_char *data, + size_t *datalength, + u_char type, + float *floatp, + size_t floatsize) +{ + union { + float floatVal; + int intVal; + u_char c[sizeof(float)]; + } fu; + + if (floatsize != sizeof (float)) { + _asn_size_err("build float", floatsize, sizeof(float)); + return NULL; + } +/* encode the float as an opaque */ + /* turn into Opaque holding special tagged value */ + + /* put the tag and length for the Opaque wrapper */ + data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize+3); + if (_asn_build_header_check("build float", data, *datalength, (floatsize+3))) + return NULL; + + /* put the special tag and length */ + *data++ = ASN_OPAQUE_TAG1; + *data++ = ASN_OPAQUE_FLOAT; + *data++ = (u_char)floatsize; + *datalength = *datalength - 3; + + fu.floatVal = *floatp; + /* correct for endian differences */ + fu.intVal = htonl(fu.intVal); + + *datalength -= floatsize; + memcpy(data, &fu.c[0], floatsize); + + data += floatsize; + return data; +} + +/* + + u_char * asn_parse_double( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char *type OUT - asn type of object + double *doublep IN/OUT - pointer to double + int doublesize IN - size of output buffer + */ +u_char * +asn_parse_double(u_char *data, + size_t *datalength, + u_char *type, + double *doublep, + size_t doublesize) +{ + register u_char *bufp = data; + u_long asn_length; + long tmp; + union { + double doubleVal; + int intVal[2]; + u_char c[sizeof(double)]; + } fu; + + + if (doublesize != sizeof(double)){ + _asn_size_err("parse double", doublesize, sizeof(double)); + return NULL; + } + *type = *bufp++; + bufp = asn_parse_length(bufp, &asn_length); + if (_asn_parse_length_check("parse double", bufp, data, + asn_length, *datalength)) + return NULL; + + DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length); +/* the double is encoded as an opaque */ + if ((*type == ASN_OPAQUE) && + (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) && + (*bufp == ASN_OPAQUE_TAG1) && + (*(bufp+1) == ASN_OPAQUE_DOUBLE)) { + DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1))); + + /* value is encoded as special format */ + bufp = asn_parse_length(bufp + 2, &asn_length); + if (_asn_parse_length_check("parse opaque double", bufp, data, + asn_length, *datalength)) + return NULL; + + /* change type to Double */ + *type = ASN_OPAQUE_DOUBLE; + } + + if (asn_length != sizeof(double)) { + _asn_size_err("parse seq double", asn_length, sizeof(double)); + return NULL; + } + *datalength -= (int)asn_length + (bufp - data); + memcpy(&fu.c[0], bufp, asn_length); + + /* correct for endian differences */ + + tmp = ntohl(fu.intVal[0]); + fu.intVal[0] = ntohl(fu.intVal[1]); + fu.intVal[1] = tmp; + + *doublep = fu.doubleVal; + DEBUGMSG(("dump_recv", "%d",*doublep)); + + return bufp; +} + +/* + + u_char * asn_build_double( + u_char *data IN - pointer to start of object + int *datalength IN/OUT - number of valid bytes left in buffer + u_char type IN - asn type of object + double *doublep IN - pointer to double + int doublesize IN - size of input buffer + */ +u_char * +asn_build_double(u_char *data, + size_t *datalength, + u_char type, + double* doublep, + size_t doublesize) +{ + long tmp; + union { + double doubleVal; + int intVal[2]; + u_char c[sizeof(double)]; + } fu; + + if (doublesize != sizeof(double)){ + _asn_size_err("build double", doublesize, sizeof(double)); + return NULL; + } + +/* encode the double as an opaque */ + /* turn into Opaque holding special tagged value */ + + /* put the tag and length for the Opaque wrapper */ + data = asn_build_header(data, datalength, ASN_OPAQUE, doublesize+3); + if (_asn_build_header_check("build double", data, *datalength, doublesize+3)) + return NULL; + + /* put the special tag and length */ + *data++ = ASN_OPAQUE_TAG1; + *data++ = ASN_OPAQUE_DOUBLE; + *data++ = (u_char)doublesize; + *datalength = *datalength - 3; + + fu.doubleVal = *doublep; + /* correct for endian differences */ + tmp = htonl(fu.intVal[0]); + fu.intVal[0] = htonl(fu.intVal[1]); + fu.intVal[1] = tmp; + *datalength -= doublesize; + memcpy(data, &fu.c[0], doublesize); + + data += doublesize; + return data; +} + +#endif /* OPAQUE_SPECIAL_TYPES */ + diff --git a/packages/net/snmp/lib/current/src/callback.c b/packages/net/snmp/lib/current/src/callback.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/callback.c @@ -0,0 +1,187 @@ +//========================================================================== +// +// ./lib/current/src/callback.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* callback.c: A generic callback mechanism */ + +#include +#include +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "tools.h" +#include "callback.h" +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_debug.h" + +static struct snmp_gen_callback *thecallbacks[MAX_CALLBACK_IDS][MAX_CALLBACK_SUBIDS]; + +/* the chicken. or the egg. You pick. */ +void +init_callbacks(void) { + /* probably not needed? Should be full of 0's anyway? */ + /* (poses a problem if you put init_callbacks() inside of + init_snmp() and then want the app to register a callback before + init_snmp() is called in the first place. -- Wes */ + /* memset(thecallbacks, 0, sizeof(thecallbacks)); */ +} + +int +snmp_register_callback(int major, int minor, SNMPCallback *new_callback, + void *arg) { + + struct snmp_gen_callback *scp; + + if (major >= MAX_CALLBACK_IDS || minor >= MAX_CALLBACK_SUBIDS) { + return SNMPERR_GENERR; + } + + if (thecallbacks[major][minor] != NULL) { + /* get to the end of the list */ + for(scp = thecallbacks[major][minor]; scp->next != NULL; scp = scp->next); + + /* mallocate a new entry */ + scp->next = SNMP_MALLOC_STRUCT(snmp_gen_callback); + scp = scp->next; + } else { + /* mallocate a new entry */ + scp = SNMP_MALLOC_STRUCT(snmp_gen_callback); + + /* make the new node the head */ + thecallbacks[major][minor] = scp; + } + + if (scp == NULL) + return SNMPERR_GENERR; + + scp->sc_client_arg = arg; + scp->sc_callback = new_callback; + + DEBUGMSGTL(("callback","registered callback for maj=%d min=%d\n", + major, minor)); + + return SNMPERR_SUCCESS; +} + +int +snmp_call_callbacks(int major, int minor, void *caller_arg) { + struct snmp_gen_callback *scp; + + if (major >= MAX_CALLBACK_IDS || minor >= MAX_CALLBACK_SUBIDS) { + return SNMPERR_GENERR; + } + + DEBUGMSGTL(("callback","START calling callbacks for maj=%d min=%d\n", + major, minor)); + + /* for each registered callback of type major and minor */ + for(scp = thecallbacks[major][minor]; scp != NULL; scp = scp->next) { + + DEBUGMSGTL(("callback","calling a callback for maj=%d min=%d\n", + major, minor)); + + /* call them */ + (*(scp->sc_callback))(major, minor, caller_arg, scp->sc_client_arg); + } + + DEBUGMSGTL(("callback","END calling callbacks for maj=%d min=%d\n", + major, minor)); + + return SNMPERR_SUCCESS; +} diff --git a/packages/net/snmp/lib/current/src/default_store.c b/packages/net/snmp/lib/current/src/default_store.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/default_store.c @@ -0,0 +1,355 @@ +//========================================================================== +// +// ./lib/current/src/default_store.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* default_store.h: storage space for defaults */ + +#include +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_debug.h" +#include "snmp_logging.h" +#include "tools.h" +#include "read_config.h" +#include "default_store.h" +#include "read_config.h" +#include "system.h" + +struct ds_read_config *ds_configs = NULL; + +int ds_integers[DS_MAX_IDS][DS_MAX_SUBIDS]; +char ds_booleans[DS_MAX_IDS][DS_MAX_SUBIDS/8]; /* bit vector storage. */ +char *ds_strings[DS_MAX_IDS][DS_MAX_SUBIDS]; /* bit vector storage. */ + +int +ds_set_boolean(int storeid, int which, int value) { + + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0) + return SNMPERR_GENERR; + + DEBUGMSGTL(("ds_set_boolean","Setting %d:%d = %d/%s\n", storeid, which, + value, ((value)?"True":"False"))); + + if (value > 0) + ds_booleans[storeid][which/8] |= (1 << (which%8)); + else + ds_booleans[storeid][which/8] &= (0xff7f >> (7-(which%8))); + + return SNMPERR_SUCCESS; +} + +int +ds_toggle_boolean(int storeid, int which) { + + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0) + return SNMPERR_GENERR; + + if ((ds_booleans[storeid][which/8] & (1 << (which % 8))) == 0) + ds_booleans[storeid][which/8] |= (1 << (which%8)); + else + ds_booleans[storeid][which/8] &= (0xff7f >> (7-(which%8))); + + DEBUGMSGTL(("ds_toggle_boolean","Setting %d:%d = %d/%s\n", storeid, which, + ds_booleans[storeid][which/8], + ((ds_booleans[storeid][which/8])?"True":"False"))); + + return SNMPERR_SUCCESS; +} + +int +ds_get_boolean(int storeid, int which) { + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0) + return SNMPERR_GENERR; + + return ((ds_booleans[storeid][which/8] & (1 << (which%8))) ? 1 : 0); +} + +int +ds_set_int(int storeid, int which, int value) { + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0) + return SNMPERR_GENERR; + + DEBUGMSGTL(("ds_set_int","Setting %d:%d = %d\n", storeid, which, value)); + + ds_integers[storeid][which] = value; + return SNMPERR_SUCCESS; +} + +int +ds_get_int(int storeid, int which) { + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0) + return SNMPERR_GENERR; + + return (ds_integers[storeid][which]); +} + +int +ds_set_string(int storeid, int which, const char *value) { + + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0) + return SNMPERR_GENERR; + + DEBUGMSGTL(("ds_set_string","Setting %d:%d = %s\n", storeid, which, + value)); + + if (ds_strings[storeid][which] != NULL) + free(ds_strings[storeid][which]); + + if (value) + ds_strings[storeid][which] = strdup(value); + else + ds_strings[storeid][which] = NULL; + + return SNMPERR_SUCCESS; +} + +char * +ds_get_string(int storeid, int which) { + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0) + return NULL; + + return (ds_strings[storeid][which]); +} + +void +ds_handle_config(const char *token, char *line) { + struct ds_read_config *drsp; + char buf[SNMP_MAXBUF]; + int itmp; + + DEBUGMSGTL(("ds_handle_config", "handling %s\n", token)); + for(drsp = ds_configs; drsp != NULL && strcasecmp(token, drsp->token) != 0; + drsp = drsp->next); + if (drsp != NULL) { + DEBUGMSGTL(("ds_handle_config", + "setting: token=%s, type=%d, id=%d, which=%d\n", + drsp->token, drsp->type, drsp->storeid, drsp->which)); + switch (drsp->type) { + case ASN_BOOLEAN: + if (strncasecmp(line,"yes",3) == 0 || strncasecmp(line,"true",4) == 0) { + itmp = 1; + } else if (strncasecmp(line,"no",3) == 0 || + strncasecmp(line,"false",5) == 0) { + itmp = 0; + } else if (atoi(line) > 0) { + itmp = 1; + } else { + itmp = 0; + } + ds_set_boolean(drsp->storeid, drsp->which, itmp); + DEBUGMSGTL(("ds_handle_config", "bool: %d\n", itmp)); + break; + + case ASN_INTEGER: + ds_set_int(drsp->storeid, drsp->which, atoi(line)); + DEBUGMSGTL(("ds_handle_config", "int: %d\n", atoi(line))); + break; + + case ASN_OCTET_STR: + if (*line == '"') { + copy_word(line, buf); + ds_set_string(drsp->storeid, drsp->which, buf); + } else { + ds_set_string(drsp->storeid, drsp->which, line); + } + DEBUGMSGTL(("ds_handle_config", "string: %s\n", line)); + break; + + default: + snmp_log(LOG_CRIT,"ds_handle_config *** unknown type %d\n", drsp->type); + break; + } + } else { + snmp_log(LOG_CRIT, "ds_handle_config *** no registration for %s\n", token); + } +} + + +int +ds_register_config(u_char type, const char *ftype, const char *token, + int storeid, int which) { + struct ds_read_config *drsp; + + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0 || token == NULL) + return SNMPERR_GENERR; + + if (ds_configs == NULL) { + ds_configs = SNMP_MALLOC_STRUCT(ds_read_config); + drsp = ds_configs; + } else { + for(drsp = ds_configs; drsp->next != NULL; drsp = drsp->next); + drsp->next = SNMP_MALLOC_STRUCT(ds_read_config); + drsp = drsp->next; + } + + drsp->type = type; + drsp->token = strdup(token); + drsp->storeid = storeid; + drsp->which = which; + + switch (type) { + case ASN_BOOLEAN: + register_config_handler(ftype, token, ds_handle_config, NULL,"(1|yes|true|0|no|false)"); + break; + + case ASN_INTEGER: + register_config_handler(ftype, token, ds_handle_config, NULL,"integerValue"); + break; + + case ASN_OCTET_STR: + register_config_handler(ftype, token, ds_handle_config, NULL,"string"); + break; + + } + return SNMPERR_SUCCESS; +} + +int +ds_register_premib(u_char type, const char *ftype, const char *token, + int storeid, int which) { + struct ds_read_config *drsp; + + if (storeid >= DS_MAX_IDS || which >= DS_MAX_SUBIDS || + storeid < 0 || which < 0 || token == NULL) + return SNMPERR_GENERR; + + if (ds_configs == NULL) { + ds_configs = SNMP_MALLOC_STRUCT(ds_read_config); + drsp = ds_configs; + } else { + for(drsp = ds_configs; drsp->next != NULL; drsp = drsp->next); + drsp->next = SNMP_MALLOC_STRUCT(ds_read_config); + drsp = drsp->next; + } + + drsp->type = type; + drsp->token = strdup(token); + drsp->storeid = storeid; + drsp->which = which; + + switch (type) { + case ASN_BOOLEAN: + register_premib_handler(ftype, token, ds_handle_config, NULL,"(1|yes|true|0|no|false)"); + break; + + case ASN_INTEGER: + register_premib_handler(ftype, token, ds_handle_config, NULL,"integerValue"); + break; + + case ASN_OCTET_STR: + register_premib_handler(ftype, token, ds_handle_config, NULL,"string"); + break; + + } + return SNMPERR_SUCCESS; +} + diff --git a/packages/net/snmp/lib/current/src/int64.c b/packages/net/snmp/lib/current/src/int64.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/int64.c @@ -0,0 +1,456 @@ +//========================================================================== +// +// ./lib/current/src/int64.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/** file: test.c - test of 64-bit integer stuff +* +* +* 21-jan-1998: David Perkins +* +*/ + +#include +#include +#include +#include +#include +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#include "asn1.h" +#include "int64.h" + +#define TRUE 1 +#define FALSE 0 + +/** divBy10 - divide an unsigned 64-bit integer by 10 +* +* call with: +* u64 - number to be divided +* pu64Q - location to store quotient +* puR - location to store remainder +* +*/ +void +divBy10(U64 u64, + U64 *pu64Q, + unsigned int *puR) +{ + unsigned long ulT; + unsigned long ulQ; + unsigned long ulR; + + + /* top 16 bits */ + ulT = (u64.high>>16) & 0x0ffff; + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->high = ulQ<<16; + + /* next 16 */ + ulT = (u64.high & 0x0ffff); + ulT += (ulR<<16); + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->high = pu64Q->high | ulQ; + + /* next 16 */ + ulT = ((u64.low>>16) & 0x0ffff) + (ulR<<16); + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->low = ulQ<<16; + + /* final 16 */ + ulT = (u64.low & 0x0ffff); + ulT += (ulR<<16); + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->low = pu64Q->low | ulQ; + + *puR = (unsigned int)(ulR); + + +} /* divBy10 */ + + +/** multBy10 - multiply an unsigned 64-bit integer by 10 +* +* call with: +* u64 - number to be multiplied +* pu64P - location to store product +* +*/ +void +multBy10(U64 u64, + U64 *pu64P) +{ + unsigned long ulT; + unsigned long ulP; + unsigned long ulK; + + + /* lower 16 bits */ + ulT = u64.low & 0x0ffff; + ulP = ulT * 10; + ulK = ulP>>16; + pu64P->low = ulP & 0x0ffff; + + /* next 16 */ + ulT = (u64.low>>16) & 0x0ffff; + ulP = (ulT * 10) + ulK; + ulK = ulP>>16; + pu64P->low = (ulP & 0x0ffff)<<16 | pu64P->low; + + /* next 16 bits */ + ulT = u64.high & 0x0ffff; + ulP = (ulT * 10) + ulK; + ulK = ulP>>16; + pu64P->high = ulP & 0x0ffff; + + /* final 16 */ + ulT = (u64.high>>16) & 0x0ffff; + ulP = (ulT * 10) + ulK; + ulK = ulP>>16; + pu64P->high = (ulP & 0x0ffff)<<16 | pu64P->high; + + +} /* multBy10 */ + + +/** incrByU16 - add an unsigned 16-bit int to an unsigned 64-bit integer +* +* call with: +* pu64 - number to be incremented +* u16 - amount to add +* +*/ +void +incrByU16(U64 *pu64, + unsigned int u16) +{ + unsigned long ulT1; + unsigned long ulT2; + unsigned long ulR; + unsigned long ulK; + + + /* lower 16 bits */ + ulT1 = pu64->low; + ulT2 = ulT1 & 0x0ffff; + ulR = ulT2 + u16; + ulK = ulR>>16; + if (ulK == 0) { + pu64->low = ulT1 + u16; + return; + } + + /* next 16 bits */ + ulT2 = (ulT1>>16) & 0x0ffff; + ulR = ulT2+1; + ulK = ulR>>16; + if (ulK == 0) { + pu64->low = ulT1 + u16; + return; + } + + /* next 32 - ignore any overflow */ + pu64->low = (ulT1 + u16) & 0x0FFFFFFFFL; + pu64->high++; + +} /* incrByV16 */ + +void +incrByU32(U64 *pu64, + unsigned int u32) +{ + unsigned int tmp; + tmp = pu64->low; + pu64->low += u32; + if (pu64->low < tmp) + pu64->high++; +} + +/* pu64out = pu64one - pu64two */ +void +u64Subtract(U64 *pu64one, + U64 *pu64two, + U64 *pu64out) +{ + if (pu64one->low > pu64two->low) { + pu64out->low = 0xffffffff - pu64two->low + pu64one->low + 1; + pu64out->high = pu64one->high - pu64two->high - 1; + } else { + pu64out->low = pu64one->low - pu64two->low; + pu64out->high = pu64one->high - pu64two->high; + } +} + +/** zeroU64 - set an unsigned 64-bit number to zero +* +* call with: +* pu64 - number to be zero'ed +* +*/ +void +zeroU64(U64 *pu64) +{ + + pu64->low = 0; + pu64->high = 0; +} /* zeroU64 */ + + +/** isZeroU64 - check if an unsigned 64-bit number is +* +* call with: +* pu64 - number to be zero'ed +* +*/ +int +isZeroU64(U64 *pu64) +{ + + if ((pu64->low == 0) && (pu64->high == 0)) + return(TRUE); + else + return(FALSE); + +} /* isZeroU64 */ + +void +printU64(char * buf, /* char [I64CHARSZ+1]; */ + U64 *pu64) +{ + U64 u64a; + U64 u64b; + + char aRes [I64CHARSZ+1]; + unsigned int u; + int j; + + u64a.high = pu64->high; + u64a.low = pu64->low; + aRes[I64CHARSZ] = 0; + for (j = 0; j < I64CHARSZ; j++) { + divBy10(u64a, &u64b, &u); + aRes[(I64CHARSZ-1)-j] = (char)('0' + u); + u64a.high = u64b.high; + u64a.low = u64b.low; + if (isZeroU64(&u64a)) + break; + } + strcpy(buf, &aRes[(I64CHARSZ-1)-j]); +} + +void +printI64(char * buf, /* char [I64CHARSZ+1]; */ + U64 *pu64) +{ + U64 u64a; + U64 u64b; + + char aRes [I64CHARSZ+1]; + unsigned int u; + int j, sign=0; + + if (pu64->high & 0x80000000) { + u64a.high = ~pu64->high; + u64a.low = ~pu64->low; + sign = 1; + incrByU32(&u64a, 1); /* bit invert and incr by 1 to print 2s complement */ + } else { + u64a.high = pu64->high; + u64a.low = pu64->low; + } + + aRes[I64CHARSZ] = 0; + for (j = 0; j < I64CHARSZ; j++) { + divBy10(u64a, &u64b, &u); + aRes[(I64CHARSZ-1)-j] = (char)('0' + u); + u64a.high = u64b.high; + u64a.low = u64b.low; + if (isZeroU64(&u64a)) + break; + } + if (sign == 1) { + aRes[(I64CHARSZ-1)-j-1] = '-'; + strcpy(buf, &aRes[(I64CHARSZ-1)-j-1]); + return; + } + strcpy(buf, &aRes[(I64CHARSZ-1)-j]); +} + +int +read64(U64 *i64, + const char *string) +{ + U64 i64p; + unsigned int u; + int sign = 0; + int ok = 0; + + zeroU64(i64); + if (*string == '-') { + sign = 1; + string++; + } + + while (*string && isdigit(*string)) { + ok = 1; + u = *string - '0'; + multBy10(*i64, &i64p); + memcpy(i64, &i64p, sizeof(i64p)); + incrByU16(i64, u); + string++; + } + if (sign) { + i64->high = ~i64->high; + i64->low = ~i64->low; + incrByU16(i64,1); + } + return ok; +} + + + + +#ifdef TESTING +void +main(int argc, char *argv[]) +{ + int i; + int j; + int l; + unsigned int u; + U64 u64a; + U64 u64b; +#define MXSZ 20 + char aRes[MXSZ+1]; + + + if (argc < 2) { + printf("This program takes numbers from the command line\n" + "and prints them out.\n" + "Usage: test ...\n"); + exit(1); + } + + aRes[MXSZ] = 0; + + for (i = 1; i < argc; i++) { + l = strlen(argv[i]); + zeroU64(&u64a); + for (j = 0; j < l; j++) { + if (!isdigit(argv[i][j])) { + printf("Argument is not a number \"%s\"\n", argv[i]); + exit(1); + } + u = argv[i][j] - '0'; + multBy10(u64a, &u64b); + u64a = u64b; + incrByU16(&u64a, u); + } + + printf("number \"%s\" in hex is '%08x%08x'h\n", + argv[i], u64a.high, u64a.low); + + printf("number is \"%s\"\n", printU64(&u64a)); + for (j = 0; j < MXSZ; j++) { + divBy10(u64a, &u64b, &u); + aRes[(MXSZ-1)-j] = (char)('0' + u); + u64a = u64b; + if (isZeroU64(&u64a)) + break; + } + + printf("number is \"%s\"\n", &aRes[(MXSZ-1)-j]); + } + exit(0); +} /* main */ +#endif /* TESTING */ + +/* file: test.c */ + diff --git a/packages/net/snmp/lib/current/src/keytools.c b/packages/net/snmp/lib/current/src/keytools.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/keytools.c @@ -0,0 +1,636 @@ +//========================================================================== +// +// ./lib/current/src/keytools.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * keytools.c + */ + +#include + +#include +#include +#if HAVE_WINSOCK_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#ifdef USE_OPENSSL +# include +#else +#ifdef USE_INTERNAL_MD5 +#include "md5.h" +#endif +#endif + +#include "scapi.h" +#include "keytools.h" +#include "tools.h" +#include "snmp_debug.h" +#include "snmp_logging.h" + +#include "transform_oids.h" + +/*******************************************************************-o-****** + * generate_Ku + * + * Parameters: + * *hashtype MIB OID for the transform type for hashing. + * hashtype_len Length of OID value. + * *P Pre-allocated bytes of passpharase. + * pplen Length of passphrase. + * *Ku Buffer to contain Ku. + * *kulen Length of Ku buffer. + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_GENERR All errors. + * + * + * Convert a passphrase into a master user key, Ku, according to the + * algorithm given in RFC 2274 concerning the SNMPv3 User Security Model (USM) + * as follows: + * + * Expand the passphrase to fill the passphrase buffer space, if necessary, + * concatenation as many duplicates as possible of P to itself. If P is + * larger than the buffer space, truncate it to fit. + * + * Then hash the result with the given hashtype transform. Return + * the result as Ku. + * + * If successful, kulen contains the size of the hash written to Ku. + * + * NOTE Passphrases less than USM_LENGTH_P_MIN characters in length + * cause an error to be returned. + * (Punt this check to the cmdline apps? XXX) + */ +int +generate_Ku( oid *hashtype, u_int hashtype_len, + u_char *P, size_t pplen, + u_char *Ku, size_t *kulen) +#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) +{ + int rval = SNMPERR_SUCCESS, + nbytes = USM_LENGTH_EXPANDED_PASSPHRASE; + + u_int i, pindex = 0; + + u_char buf[USM_LENGTH_KU_HASHBLOCK], + *bufp; + +#ifdef USE_OPENSSL + EVP_MD_CTX *ctx = malloc(sizeof(EVP_MD_CTX)); +#else + MDstruct MD; +#endif + /* + * Sanity check. + */ + if ( !hashtype || !P || !Ku || !kulen + || (*kulen<=0) + || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, generate_Ku_quit); + } + + if (pplen < USM_LENGTH_P_MIN) { +#ifdef SNMP_TESTING_CODE + snmp_log(LOG_WARNING, "Warning: passphrase chosen is below the length requiremnts of the USM.\n"); +#else + snmp_set_detail("Password length too short."); + QUITFUN(SNMPERR_GENERR, generate_Ku_quit); +#endif + } + + + /* + * Setup for the transform type. + */ +#ifdef USE_OPENSSL + + if (ISTRANSFORM(hashtype, HMACMD5Auth)) + EVP_DigestInit(ctx, EVP_md5()); + else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) + EVP_DigestInit(ctx, EVP_sha1()); + else { + free(ctx); + return (SNMPERR_GENERR); + } +#else + MDbegin(&MD); +#endif /* USE_OPENSSL */ + + while (nbytes > 0) { + bufp = buf; + for (i = 0; i < USM_LENGTH_KU_HASHBLOCK; i++) { + *bufp++ = P[pindex++ % pplen]; + } +#ifdef USE_OPENSSL + EVP_DigestUpdate(ctx, buf, USM_LENGTH_KU_HASHBLOCK); +#else + if (MDupdate(&MD, buf, USM_LENGTH_KU_HASHBLOCK*8)) { + rval = SNMPERR_USM_ENCRYPTIONERROR; + goto md5_fin; + } +#endif /* USE_OPENSSL */ + + nbytes -= USM_LENGTH_KU_HASHBLOCK; + } + +#ifdef USE_OPENSSL + EVP_DigestFinal(ctx, (unsigned char *) Ku, (unsigned int *) kulen); + /* what about free() */ +#else + if (MDupdate(&MD, buf, 0)) { + rval = SNMPERR_USM_ENCRYPTIONERROR; + goto md5_fin; + } + *kulen = sc_get_properlength(hashtype, hashtype_len); + MDget(&MD, Ku, *kulen); +md5_fin: + memset(&MD, 0, sizeof(MD)); +#endif /* USE_OPENSSL */ + + +#ifdef SNMP_TESTING_CODE + DEBUGMSGTL(("generate_Ku", "generating Ku (from %s): ", P)); + for(i=0; i < *kulen; i++) + DEBUGMSG(("generate_Ku", "%02x",Ku[i])); + DEBUGMSG(("generate_Ku","\n")); +#endif /* SNMP_TESTING_CODE */ + + +generate_Ku_quit: + memset(buf, 0, sizeof(buf)); +#ifdef USE_OPENSSL + free(ctx); +#endif + return rval; + +} /* end generate_Ku() */ + +#else +_KEYTOOLS_NOT_AVAILABLE +#endif /* internal or openssl */ + + + + +/*******************************************************************-o-****** + * generate_kul + * + * Parameters: + * *hashtype + * hashtype_len + * *engineID + * engineID_len + * *Ku Master key for a given user. + * ku_len Length of Ku in bytes. + * *Kul Localized key for a given user at engineID. + * *kul_len Length of Kul buffer (IN); Length of Kul key (OUT). + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_GENERR All errors. + * + * + * Ku MUST be the proper length (currently fixed) for the given hashtype. + * + * Upon successful return, Kul contains the localized form of Ku at + * engineID, and the length of the key is stored in kul_len. + * + * The localized key method is defined in RFC2274, Sections 2.6 and A.2, and + * originally documented in: + * U. Blumenthal, N. C. Hien, B. Wijnen, + * "Key Derivation for Network Management Applications", + * IEEE Network Magazine, April/May issue, 1997. + * + * + * ASSUMES SNMP_MAXBUF >= sizeof(Ku + engineID + Ku). + * + * NOTE Localized keys for privacy transforms are generated via + * the authentication transform held by the same usmUser. + * + * XXX An engineID of any length is accepted, even if larger than + * what is spec'ed for the textual convention. + */ +int +generate_kul( oid *hashtype, u_int hashtype_len, + u_char *engineID, size_t engineID_len, + u_char *Ku, size_t ku_len, + u_char *Kul, size_t *kul_len) +#if defined(USE_OPENSSL) || defined(USE_INTERNAL_MD5) +{ + int rval = SNMPERR_SUCCESS; + u_int nbytes = 0; + size_t properlength; + + u_char buf[SNMP_MAXBUF]; + void *context = NULL; +#ifdef SNMP_TESTING_CODE + int i; +#endif + + + /* + * Sanity check. + */ + if ( !hashtype || !engineID || !Ku || !Kul || !kul_len + || (engineID_len<=0) || (ku_len<=0) || (*kul_len<=0) + || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, generate_kul_quit); + } + + + properlength = sc_get_properlength(hashtype, hashtype_len); + if (properlength == SNMPERR_GENERR) + QUITFUN(SNMPERR_GENERR, generate_kul_quit); + + + if (((int)*kul_len < properlength) || ((int)ku_len < properlength) ) { + QUITFUN(SNMPERR_GENERR, generate_kul_quit); + } + + /* + * Concatenate Ku and engineID properly, then hash the result. + * Store it in Kul. + */ + nbytes = 0; + memcpy(buf, Ku, properlength); nbytes += properlength; + memcpy(buf+nbytes, engineID, engineID_len); nbytes += engineID_len; + memcpy(buf+nbytes, Ku, properlength); nbytes += properlength; + + rval = sc_hash(hashtype, hashtype_len, buf, nbytes, Kul, kul_len); + +#ifdef SNMP_TESTING_CODE + DEBUGMSGTL(("generate_kul", "generating Kul (from Ku): ")); + for(i=0; i < *kul_len; i++) + DEBUGMSG(("generate_kul", "%02x",Kul[i])); + DEBUGMSG(("generate_kul", "keytools\n")); +#endif /* SNMP_TESTING_CODE */ + + QUITFUN(rval, generate_kul_quit); + + +generate_kul_quit: + SNMP_FREE(context); + return rval; + +} /* end generate_kul() */ + +#else +_KEYTOOLS_NOT_AVAILABLE +#endif /* internal or openssl */ + + + + +/*******************************************************************-o-****** + * encode_keychange + * + * Parameters: + * *hashtype MIB OID for the hash transform type. + * hashtype_len Length of the MIB OID hash transform type. + * *oldkey Old key that is used to encodes the new key. + * oldkey_len Length of oldkey in bytes. + * *newkey New key that is encoded using the old key. + * newkey_len Length of new key in bytes. + * *kcstring Buffer to contain the KeyChange TC string. + * *kcstring_len Length of kcstring buffer. + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_GENERR All errors. + * + * + * Uses oldkey and acquired random bytes to encode newkey into kcstring + * according to the rules of the KeyChange TC described in RFC 2274, Section 5. + * + * Upon successful return, *kcstring_len contains the length of the + * encoded string. + * + * ASSUMES Old and new key are always equal to each other, although + * this may be less than the transform type hash output + * output length (eg, using KeyChange for a DESPriv key when + * the user also uses SHA1Auth). This also implies that the + * hash placed in the second 1/2 of the key change string + * will be truncated before the XOR'ing when the hash output is + * larger than that 1/2 of the key change string. + * + * *kcstring_len will be returned as exactly twice that same + * length though the input buffer may be larger. + * + * XXX FIX: Does not handle varibable length keys. + * XXX FIX: Does not handle keys larger than the hash algorithm used. + */ +int +encode_keychange( oid *hashtype, u_int hashtype_len, + u_char *oldkey, size_t oldkey_len, + u_char *newkey, size_t newkey_len, + u_char *kcstring, size_t *kcstring_len) +#if defined(USE_OPENSSL) || defined(USE_INTERNAL_MD5) +{ + int rval = SNMPERR_SUCCESS; + size_t properlength; + size_t nbytes = 0; + + u_char *tmpbuf = NULL; + void *context = NULL; + + + /* + * Sanity check. + */ + if ( !hashtype || !oldkey || !newkey || !kcstring || !kcstring_len + || (oldkey_len<=0) || (newkey_len<=0) || (*kcstring_len<=0) + || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, encode_keychange_quit); + } + + /* + * Setup for the transform type. + */ + properlength = sc_get_properlength(hashtype, hashtype_len); + if (properlength == SNMPERR_GENERR) + QUITFUN(SNMPERR_GENERR, encode_keychange_quit); + + if ( (oldkey_len != newkey_len) || (*kcstring_len < (2*oldkey_len)) ) + { + QUITFUN(SNMPERR_GENERR, encode_keychange_quit); + } + + properlength = SNMP_MIN((int)oldkey_len, properlength); + + /* + * Use the old key and some random bytes to encode the new key + * in the KeyChange TC format: + * . Get random bytes (store in first half of kcstring), + * . Hash (oldkey | random_bytes) (into second half of kcstring), + * . XOR hash and newkey (into second half of kcstring). + * + * Getting the wrong number of random bytes is considered an error. + */ + nbytes = properlength; + +#if defined(SNMP_TESTING_CODE) && defined(RANDOMZEROS) + memset(kcstring, 0, nbytes); + DEBUGMSG(("encode_keychange", + "** Using all zero bits for \"random\" delta of )" + "the keychange string! **\n")); +#else /* !SNMP_TESTING_CODE */ + rval = sc_random(kcstring, &nbytes); + QUITFUN(rval, encode_keychange_quit); + if ((int)nbytes != properlength) { + QUITFUN(SNMPERR_GENERR, encode_keychange_quit); + } +#endif /* !SNMP_TESTING_CODE */ + + tmpbuf = (u_char *)malloc(properlength*2); + if (tmpbuf) { + memcpy(tmpbuf, oldkey, properlength); + memcpy(tmpbuf+properlength, kcstring, properlength); + + *kcstring_len -= properlength; + rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength*2, + kcstring+properlength, kcstring_len); + + QUITFUN(rval, encode_keychange_quit); + + *kcstring_len = (properlength*2); + + kcstring += properlength; + nbytes = 0; + while ((int)(nbytes++) < properlength) { + *kcstring++ = *kcstring ^ *newkey++; + } + } + +encode_keychange_quit: + if (rval != SNMPERR_SUCCESS) memset(kcstring, 0, *kcstring_len); + SNMP_FREE(tmpbuf); + SNMP_FREE(context); + + return rval; + +} /* end encode_keychange() */ + +#else +_KEYTOOLS_NOT_AVAILABLE +#endif /* internal or openssl */ + + + + +/*******************************************************************-o-****** + * decode_keychange + * + * Parameters: + * *hashtype MIB OID of the hash transform to use. + * hashtype_len Length of the hash transform MIB OID. + * *oldkey Old key that is used to encode the new key. + * oldkey_len Length of oldkey in bytes. + * *kcstring Encoded KeyString buffer containing the new key. + * kcstring_len Length of kcstring in bytes. + * *newkey Buffer to hold the extracted new key. + * *newkey_len Length of newkey in bytes. + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_GENERR All errors. + * + * + * Decodes a string of bits encoded according to the KeyChange TC described + * in RFC 2274, Section 5. The new key is extracted from *kcstring with + * the aid of the old key. + * + * Upon successful return, *newkey_len contains the length of the new key. + * + * + * ASSUMES Old key is exactly 1/2 the length of the KeyChange buffer, + * although this length may be less than the hash transform + * output. Thus the new key length will be equal to the old + * key length. + */ + +/* XXX: if the newkey is not long enough, it should be freed and remalloced */ +int +decode_keychange( oid *hashtype, u_int hashtype_len, + u_char *oldkey, size_t oldkey_len, + u_char *kcstring, size_t kcstring_len, + u_char *newkey, size_t *newkey_len) +#if defined(USE_OPENSSL) || defined(USE_INTERNAL_MD5) +{ + int rval = SNMPERR_SUCCESS; + size_t properlength = 0; + u_int nbytes = 0; + + u_char *bufp, + tmp_buf[SNMP_MAXBUF]; + size_t tmp_buf_len = SNMP_MAXBUF; + void *context = NULL; + u_char *tmpbuf = NULL; + + + + /* + * Sanity check. + */ + if ( !hashtype || !oldkey || !kcstring || !newkey || !newkey_len + || (oldkey_len<=0) || (kcstring_len<=0) || (*newkey_len<=0) + || (hashtype_len != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, decode_keychange_quit); + } + + + /* + * Setup for the transform type. + */ + properlength = sc_get_properlength(hashtype, hashtype_len); + if (properlength == SNMPERR_GENERR) + QUITFUN(SNMPERR_GENERR, decode_keychange_quit); + + + if ( ((oldkey_len*2) != kcstring_len) || (*newkey_len < oldkey_len) ) + { + QUITFUN(SNMPERR_GENERR, decode_keychange_quit); + } + + properlength = oldkey_len; + *newkey_len = properlength; + + /* + * Use the old key and the given KeyChange TC string to recover + * the new key: + * . Hash (oldkey | random_bytes) (into newkey), + * . XOR hash and encoded (second) half of kcstring (into newkey). + */ + tmpbuf = (u_char *)malloc(properlength*2); + if (tmpbuf) { + memcpy(tmpbuf, oldkey, properlength); + memcpy(tmpbuf+properlength, kcstring, properlength); + + rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength*2, + tmp_buf, &tmp_buf_len); + QUITFUN(rval, decode_keychange_quit); + + memcpy(newkey, tmp_buf, properlength); + bufp = kcstring+properlength; + nbytes = 0; + while ((int)(nbytes++) < properlength) { + *newkey++ = *newkey ^ *bufp++; + } + } + +decode_keychange_quit: + if (rval != SNMPERR_SUCCESS) { + memset(newkey, 0, properlength); + } + memset(tmp_buf, 0, SNMP_MAXBUF); + SNMP_FREE(context); + if (tmpbuf != NULL) SNMP_FREE(tmpbuf); + + return rval; + +} /* end decode_keychange() */ + +#else +_KEYTOOLS_NOT_AVAILABLE +#endif /* internal or openssl */ + diff --git a/packages/net/snmp/lib/current/src/lcd_time.c b/packages/net/snmp/lib/current/src/lcd_time.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/lcd_time.c @@ -0,0 +1,638 @@ +//========================================================================== +// +// ./lib/current/src/lcd_time.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * lcd_time.c + * + * XXX Should etimelist entries with <0,0> time tuples be timed out? + * XXX Need a routine to free the memory? (Perhaps at shutdown?) + */ + +#include + +#include +#if HAVE_WINSOCK_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "callback.h" +#include "snmpusm.h" +#include "lcd_time.h" +#include "snmp_debug.h" +#include "tools.h" +#include "scapi.h" + +#include "transform_oids.h" + + +/* + * Global static hashlist to contain Enginetime entries. + * + * New records are prepended to the appropriate list at the hash index. + */ +static Enginetime etimelist[ETIMELIST_SIZE]; + + + + +/*******************************************************************-o-****** + * get_enginetime + * + * Parameters: + * *engineID + * engineID_len + * *engineboot + * *engine_time + * + * Returns: + * SNMPERR_SUCCESS Success -- when a record for engineID is found. + * SNMPERR_GENERR Otherwise. + * + * + * Lookup engineID and return the recorded values for the + * tuple adjusted to reflect the estimated time + * at the engine in question. + * + * Special case: if engineID is NULL or if engineID_len is 0 then + * the time tuple is returned immediately as zero. + * + * XXX What if timediff wraps? >shrug< + * XXX Then: you need to increment the boots value. Now. Detecting + * this is another matter. + */ +int +get_enginetime( u_char *engineID, + u_int engineID_len, + u_int *engineboot, + u_int *engine_time, + u_int authenticated) +{ + int rval = SNMPERR_SUCCESS; + time_t timediff = 0; + Enginetime e = NULL; + + + + /* + * Sanity check. + */ + if ( !engine_time || !engineboot ) { + QUITFUN(SNMPERR_GENERR, get_enginetime_quit); + } + + + /* + * Compute estimated current engine_time tuple at engineID if + * a record is cached for it. + */ + *engine_time = *engineboot = 0; + + if ( !engineID || (engineID_len<=0) ) { + QUITFUN(SNMPERR_GENERR, get_enginetime_quit); + } + + if ( !(e = search_enginetime_list(engineID, engineID_len)) ) { + QUITFUN(SNMPERR_GENERR, get_enginetime_quit); + } + +#ifdef LCD_TIME_SYNC_OPT + if (!authenticated || e->authenticatedFlag) { +#endif + *engine_time = e->engineTime; + *engineboot = e->engineBoot; + + timediff = time(NULL) - e->lastReceivedEngineTime; +#ifdef LCD_TIME_SYNC_OPT + } +#endif + + if ( timediff > (int)(ENGINETIME_MAX - *engine_time) ) { + *engine_time = (timediff - (ENGINETIME_MAX - *engine_time)); + + /* FIX -- move this check up... should not change anything + * if engineboot is already locked. ??? + */ + if (*engineboot < ENGINEBOOT_MAX) { + *engineboot += 1; + } + + } else { + *engine_time += timediff; + } + + DEBUGMSGTL(("lcd_get_enginetime", "engineID ")); + DEBUGMSGHEX(("lcd_get_enginetime", engineID, engineID_len)); + DEBUGMSG(("lcd_get_enginetime", ": boots=%d, time=%d\n", *engineboot, + *engine_time)); + +get_enginetime_quit: + return rval; + +} /* end get_enginetime() */ + +/*******************************************************************-o-****** + * get_enginetime + * + * Parameters: + * *engineID + * engineID_len + * *engineboot + * *engine_time + * + * Returns: + * SNMPERR_SUCCESS Success -- when a record for engineID is found. + * SNMPERR_GENERR Otherwise. + * + * + * Lookup engineID and return the recorded values for the + * tuple adjusted to reflect the estimated time + * at the engine in question. + * + * Special case: if engineID is NULL or if engineID_len is 0 then + * the time tuple is returned immediately as zero. + * + * XXX What if timediff wraps? >shrug< + * XXX Then: you need to increment the boots value. Now. Detecting + * this is another matter. + */ +int +get_enginetime_ex( u_char *engineID, + u_int engineID_len, + u_int *engineboot, + u_int *engine_time, + u_int *last_engine_time, + u_int authenticated) +{ + int rval = SNMPERR_SUCCESS; + time_t timediff = 0; + Enginetime e = NULL; + + + + /* + * Sanity check. + */ + if ( !engine_time || !engineboot || !last_engine_time) { + QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit); + } + + + /* + * Compute estimated current engine_time tuple at engineID if + * a record is cached for it. + */ + *last_engine_time = *engine_time = *engineboot = 0; + + if ( !engineID || (engineID_len<=0) ) { + QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit); + } + + if ( !(e = search_enginetime_list(engineID, engineID_len)) ) { + QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit); + } + +#ifdef LCD_TIME_SYNC_OPT + if (!authenticated || e->authenticatedFlag) { +#endif + *last_engine_time = *engine_time = e->engineTime; + *engineboot = e->engineBoot; + + timediff = time(NULL) - e->lastReceivedEngineTime; +#ifdef LCD_TIME_SYNC_OPT + } +#endif + + if ( timediff > (int)(ENGINETIME_MAX - *engine_time) ) { + *engine_time = (timediff - (ENGINETIME_MAX - *engine_time)); + + /* FIX -- move this check up... should not change anything + * if engineboot is already locked. ??? + */ + if (*engineboot < ENGINEBOOT_MAX) { + *engineboot += 1; + } + + } else { + *engine_time += timediff; + } + + DEBUGMSGTL(("lcd_get_enginetime_ex", "engineID ")); + DEBUGMSGHEX(("lcd_get_enginetime_ex", engineID, engineID_len)); + DEBUGMSG(("lcd_get_enginetime_ex", ": boots=%d, time=%d\n", *engineboot, + *engine_time)); + +get_enginetime_ex_quit: + return rval; + +} /* end get_enginetime_ex() */ + + + + +/*******************************************************************-o-****** + * set_enginetime + * + * Parameters: + * *engineID + * engineID_len + * engineboot + * engine_time + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_GENERR Otherwise. + * + * + * Lookup engineID and store the given tuple + * and then stamp the record with a consistent source of local time. + * If the engineID record does not exist, create one. + * + * Special case: engineID is NULL or engineID_len is 0 defines an engineID + * that is "always set." + * + * XXX "Current time within the local engine" == time(NULL)... + */ +int +set_enginetime( u_char *engineID, + u_int engineID_len, + u_int engineboot, + u_int engine_time, + u_int authenticated) +{ + int rval = SNMPERR_SUCCESS, + iindex; + Enginetime e = NULL; + + + + /* + * Sanity check. + */ + if ( !engineID || (engineID_len <= 0) ) { + return rval; + } + + + /* + * Store the given tuple in the record + * for engineID. Create a new record if necessary. + */ + if ( !(e = search_enginetime_list(engineID, engineID_len)) ) + { + if ( (iindex = hash_engineID(engineID, engineID_len)) < 0 ) + { + QUITFUN(SNMPERR_GENERR, set_enginetime_quit); + } + + e = (Enginetime) calloc(1,sizeof(*e)); + + e->next = etimelist[iindex]; + etimelist[iindex] = e; + + e->engineID = (u_char *) calloc(1,engineID_len); + memcpy(e->engineID, engineID, engineID_len); + + e->engineID_len = engineID_len; + } +#ifdef LCD_TIME_SYNC_OPT + if (authenticated || !e->authenticatedFlag) { + e->authenticatedFlag = authenticated; +#else + if (authenticated) { +#endif + e->engineTime = engine_time; + e->engineBoot = engineboot; + e->lastReceivedEngineTime = time(NULL); + } + + e = NULL; /* Indicates a successful update. */ + + DEBUGMSGTL(("lcd_set_enginetime", "engineID ")); + DEBUGMSGHEX(("lcd_set_enginetime", engineID, engineID_len)); + DEBUGMSG(("lcd_set_enginetime", ": boots=%d, time=%d\n", engineboot, + engine_time)); + +set_enginetime_quit: + SNMP_FREE(e); + + return rval; + +} /* end set_enginetime() */ + + + + +/*******************************************************************-o-****** + * search_enginetime_list + * + * Parameters: + * *engineID + * engineID_len + * + * Returns: + * Pointer to a etimelist record with engineID -OR- + * NULL if no record exists. + * + * + * Search etimelist for an entry with engineID. + * + * ASSUMES that no engineID will have more than one record in the list. + */ +Enginetime +search_enginetime_list(u_char *engineID, u_int engineID_len) +{ + int rval = SNMPERR_SUCCESS; + Enginetime e = NULL; + + + /* + * Sanity check. + */ + if ( !engineID || (engineID_len<=0) ) { + QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit); + } + + + /* + * Find the entry for engineID if there be one. + */ + rval = hash_engineID(engineID, engineID_len); + if (rval < 0) { + QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit); + } + e = etimelist[rval]; + + for ( /*EMPTY*/; e; e = e->next ) + { + if ( (engineID_len == e->engineID_len) + && !memcmp(e->engineID, engineID, engineID_len) ) + { + break; + } + } + + +search_enginetime_list_quit: + return e; + +} /* end search_enginetime_list() */ + + + + + +/*******************************************************************-o-****** + * hash_engineID + * + * Parameters: + * *engineID + * engineID_len + * + * Returns: + * >0 etimelist index for this engineID. + * SNMPERR_GENERR Error. + * + * + * Use a cheap hash to build an index into the etimelist. Method is + * to hash the engineID, then split the hash into u_int's and add them up + * and modulo the size of the list. + * + */ +int +hash_engineID(u_char *engineID, u_int engineID_len) +{ + int rval = SNMPERR_GENERR; + size_t buf_len = SNMP_MAXBUF; + u_int additive = 0; + u_char *bufp, + buf[SNMP_MAXBUF]; + void *context = NULL; + + + + /* + * Sanity check. + */ + if ( !engineID || (engineID_len <= 0) ) { + QUITFUN(SNMPERR_GENERR, hash_engineID_quit); + } + + + /* + * Hash engineID into a list index. + */ + rval = sc_hash(usmHMACMD5AuthProtocol, + sizeof(usmHMACMD5AuthProtocol)/sizeof(oid), + engineID, engineID_len, + buf, &buf_len); + QUITFUN(rval, hash_engineID_quit); + + for ( bufp = buf; (bufp-buf) < (int)buf_len; bufp += 4 ) { + additive += (u_int) *bufp; + } + +hash_engineID_quit: + SNMP_FREE(context); + memset(buf, 0, SNMP_MAXBUF); + + return (rval < 0) ? rval : (additive % ETIMELIST_SIZE); + +} /* end hash_engineID() */ + + + + +#ifdef SNMP_TESTING_CODE +/*******************************************************************-o-****** + * dump_etimelist_entry + * + * Parameters: + * e + * count + */ +void +dump_etimelist_entry(Enginetime e, int count) +{ + u_int buflen; + char tabs[SNMP_MAXBUF], + *t = tabs, + *s; + + + + count += 1; + while (count--) { + t += sprintf(t, " "); + } + + + buflen = e->engineID_len; +#ifdef SNMP_TESTING_CODE + if ( !(s = dump_snmpEngineID(e->engineID, &buflen)) ) { +#endif + binary_to_hex(e->engineID, e->engineID_len, &s); +#ifdef SNMP_TESTING_CODE + } +#endif + + DEBUGMSGTL(("dump_etimelist", "%s\n",tabs)); + DEBUGMSGTL(("dump_etimelist", "%s%s (len=%d) <%d,%d>\n", tabs, + s, e->engineID_len, + e->engineTime, e->engineBoot)); + DEBUGMSGTL(("dump_etimelist", "%s%ld (%ld) -- %s", tabs, + e->lastReceivedEngineTime, + time(NULL) - e->lastReceivedEngineTime, + ctime(&e->lastReceivedEngineTime))); + + SNMP_FREE(s); + +} /* end dump_etimelist_entry() */ + + + + +/*******************************************************************-o-****** + * dump_etimelist + */ +void +dump_etimelist(void) +{ + int iindex = -1, + count = 0; + Enginetime e; + + + + DEBUGMSGTL(("dump_etimelist", "\n")); + + while (++iindex < ETIMELIST_SIZE) { + DEBUGMSG(("dump_etimelist", "[%d]", iindex)); + + count = 0; + e = etimelist[iindex]; + + while (e) { + dump_etimelist_entry(e, count++); + e = e->next; + } + + if (count > 0) { + DEBUGMSG(("dump_etimelist", "\n")); + } + } /* endwhile */ + + DEBUGMSG(("dump_etimelist", "\n")); + +} /* end dump_etimelist() */ +#endif /* SNMP_TESTING_CODE */ diff --git a/packages/net/snmp/lib/current/src/md5.c b/packages/net/snmp/lib/current/src/md5.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/md5.c @@ -0,0 +1,530 @@ +//========================================================================== +// +// ./lib/current/src/md5.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* +** ************************************************************************** +** md5.c -- Implementation of MD5 Message Digest Algorithm ** +** Updated: 2/16/90 by Ronald L. Rivest ** +** (C) 1990 RSA Data Security, Inc. ** +** ************************************************************************** +*/ + +/* +** To use MD5: +** -- Include md5.h in your program +** -- Declare an MDstruct MD to hold the state of the digest computation. +** -- Initialize MD using MDbegin(&MD) +** -- For each full block (64 bytes) X you wish to process, call +** MDupdate(&MD,X,512) +** (512 is the number of bits in a full block.) +** -- For the last block (less than 64 bytes) you wish to process, +** MDupdate(&MD,X,n) +** where n is the number of bits in the partial block. A partial +** block terminates the computation, so every MD computation should +** terminate by processing a partial block, even if it has n = 0. +** -- The message digest is available in MD.buffer[0] ... MD.buffer[3]. +** (Least-significant byte of each word should be output first.) +** -- You can print out the digest using MDprint(&MD) +*/ + +/* Implementation notes: +** This implementation assumes that ints are 32-bit quantities. +** If the machine stores the least-significant byte of an int in the +** least-addressed byte (eg., VAX and 8086), then LOWBYTEFIRST should be +** set to TRUE. Otherwise (eg., SUNS), LOWBYTEFIRST should be set to +** FALSE. Note that on machines with LOWBYTEFIRST FALSE the routine +** MDupdate modifies has a side-effect on its input array (the order of bytes +** in each word are reversed). If this is undesired a call to MDreverse(X) can +** reverse the bytes of X back into order after each call to MDupdate. +*/ + +/* code uses WORDS_BIGENDIAN defined by configure now -- WH 9/27/95 */ + +/* Compile-time includes +*/ + +#include + +#include +#include +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif + +#include "md5.h" + +/* Compile-time declarations of MD5 ``magic constants''. +*/ +#define I0 0x67452301 /* Initial values for MD buffer */ +#define I1 0xefcdab89 +#define I2 0x98badcfe +#define I3 0x10325476 +#define fs1 7 /* round 1 shift amounts */ +#define fs2 12 +#define fs3 17 +#define fs4 22 +#define gs1 5 /* round 2 shift amounts */ +#define gs2 9 +#define gs3 14 +#define gs4 20 +#define hs1 4 /* round 3 shift amounts */ +#define hs2 11 +#define hs3 16 +#define hs4 23 +#define is1 6 /* round 4 shift amounts */ +#define is2 10 +#define is3 15 +#define is4 21 + + +/* Compile-time macro declarations for MD5. +** Note: The ``rot'' operator uses the variable ``tmp''. +** It assumes tmp is declared as unsigned int, so that the >> +** operator will shift in zeros rather than extending the sign bit. +*/ +#define f(X,Y,Z) ((X&Y) | ((~X)&Z)) +#define g(X,Y,Z) ((X&Z) | (Y&(~Z))) +#define h(X,Y,Z) (X^Y^Z) +#define i_(X,Y,Z) (Y ^ ((X) | (~Z))) +#define rot(X,S) (tmp=X,(tmp<>(32-S))) +#define ff(A,B,C,D,i,s,lp) A = rot((A + f(B,C,D) + X[i] + lp),s) + B +#define gg(A,B,C,D,i,s,lp) A = rot((A + g(B,C,D) + X[i] + lp),s) + B +#define hh(A,B,C,D,i,s,lp) A = rot((A + h(B,C,D) + X[i] + lp),s) + B +#define ii(A,B,C,D,i,s,lp) A = rot((A + i_(B,C,D) + X[i] + lp),s) + B + +#ifdef STDC_HEADERS +#define Uns(num) num##U +#else +#define Uns(num) num +#endif /* STDC_HEADERS */ + +void MDreverse (unsigned int *); +static void MDblock (MDptr, unsigned int *); + +#ifdef SNMP_TESTING_CODE +/* MDprint(MDp) +** Print message digest buffer MDp as 32 hexadecimal digits. +** Order is from low-order byte of buffer[0] to high-order byte of buffer[3]. +** Each byte is printed with high-order hexadecimal digit first. +** This is a user-callable routine. +*/ +void +MDprint(MDptr MDp) +{ + int i,j; + for (i=0;i<4;i++) + for (j=0;j<32;j=j+8) + printf("%02x",(MDp->buffer[i]>>j) & 0xFF); + printf("\n"); + fflush(stdout); +} +#endif /* SNMP_TESTING_CODE */ + +/* MDbegin(MDp) +** Initialize message digest buffer MDp. +** This is a user-callable routine. +*/ +void +MDbegin(MDptr MDp) +{ + int i; + MDp->buffer[0] = I0; + MDp->buffer[1] = I1; + MDp->buffer[2] = I2; + MDp->buffer[3] = I3; + for (i=0;i<8;i++) MDp->count[i] = 0; + MDp->done = 0; +} + +/* MDreverse(X) +** Reverse the byte-ordering of every int in X. +** Assumes X is an array of 16 ints. +** The macro revx reverses the byte-ordering of the next word of X. +*/ +#define revx { t = (*X << 16) | (*X >> 16); \ + *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); } + +void MDreverse(unsigned int *X) +{ + register unsigned int t; + revx; revx; revx; revx; revx; revx; revx; revx; + revx; revx; revx; revx; revx; revx; revx; revx; +} + +/* MDblock(MDp,X) +** Update message digest buffer MDp->buffer using 16-word data block X. +** Assumes all 16 words of X are full of data. +** Does not update MDp->count. +** This routine is not user-callable. +*/ +static void +MDblock(MDptr MDp, + unsigned int *X) +{ + register unsigned int tmp, A, B, C, D; /* hpux sysv sun */ +#ifdef WORDS_BIGENDIAN + MDreverse(X); +#endif + A = MDp->buffer[0]; + B = MDp->buffer[1]; + C = MDp->buffer[2]; + D = MDp->buffer[3]; + + /* Update the message digest buffer */ + ff(A , B , C , D , 0 , fs1 , Uns(3614090360)); /* Round 1 */ + ff(D , A , B , C , 1 , fs2 , Uns(3905402710)); + ff(C , D , A , B , 2 , fs3 , Uns(606105819)); + ff(B , C , D , A , 3 , fs4 , Uns(3250441966)); + ff(A , B , C , D , 4 , fs1 , Uns(4118548399)); + ff(D , A , B , C , 5 , fs2 , Uns(1200080426)); + ff(C , D , A , B , 6 , fs3 , Uns(2821735955)); + ff(B , C , D , A , 7 , fs4 , Uns(4249261313)); + ff(A , B , C , D , 8 , fs1 , Uns(1770035416)); + ff(D , A , B , C , 9 , fs2 , Uns(2336552879)); + ff(C , D , A , B , 10 , fs3 , Uns(4294925233)); + ff(B , C , D , A , 11 , fs4 , Uns(2304563134)); + ff(A , B , C , D , 12 , fs1 , Uns(1804603682)); + ff(D , A , B , C , 13 , fs2 , Uns(4254626195)); + ff(C , D , A , B , 14 , fs3 , Uns(2792965006)); + ff(B , C , D , A , 15 , fs4 , Uns(1236535329)); + gg(A , B , C , D , 1 , gs1 , Uns(4129170786)); /* Round 2 */ + gg(D , A , B , C , 6 , gs2 , Uns(3225465664)); + gg(C , D , A , B , 11 , gs3 , Uns(643717713)); + gg(B , C , D , A , 0 , gs4 , Uns(3921069994)); + gg(A , B , C , D , 5 , gs1 , Uns(3593408605)); + gg(D , A , B , C , 10 , gs2 , Uns(38016083)); + gg(C , D , A , B , 15 , gs3 , Uns(3634488961)); + gg(B , C , D , A , 4 , gs4 , Uns(3889429448)); + gg(A , B , C , D , 9 , gs1 , Uns(568446438)); + gg(D , A , B , C , 14 , gs2 , Uns(3275163606)); + gg(C , D , A , B , 3 , gs3 , Uns(4107603335)); + gg(B , C , D , A , 8 , gs4 , Uns(1163531501)); + gg(A , B , C , D , 13 , gs1 , Uns(2850285829)); + gg(D , A , B , C , 2 , gs2 , Uns(4243563512)); + gg(C , D , A , B , 7 , gs3 , Uns(1735328473)); + gg(B , C , D , A , 12 , gs4 , Uns(2368359562)); + hh(A , B , C , D , 5 , hs1 , Uns(4294588738)); /* Round 3 */ + hh(D , A , B , C , 8 , hs2 , Uns(2272392833)); + hh(C , D , A , B , 11 , hs3 , Uns(1839030562)); + hh(B , C , D , A , 14 , hs4 , Uns(4259657740)); + hh(A , B , C , D , 1 , hs1 , Uns(2763975236)); + hh(D , A , B , C , 4 , hs2 , Uns(1272893353)); + hh(C , D , A , B , 7 , hs3 , Uns(4139469664)); + hh(B , C , D , A , 10 , hs4 , Uns(3200236656)); + hh(A , B , C , D , 13 , hs1 , Uns(681279174)); + hh(D , A , B , C , 0 , hs2 , Uns(3936430074)); + hh(C , D , A , B , 3 , hs3 , Uns(3572445317)); + hh(B , C , D , A , 6 , hs4 , Uns(76029189)); + hh(A , B , C , D , 9 , hs1 , Uns(3654602809)); + hh(D , A , B , C , 12 , hs2 , Uns(3873151461)); + hh(C , D , A , B , 15 , hs3 , Uns(530742520)); + hh(B , C , D , A , 2 , hs4 , Uns(3299628645)); + ii(A , B , C , D , 0 , is1 , Uns(4096336452)); /* Round 4 */ + ii(D , A , B , C , 7 , is2 , Uns(1126891415)); + ii(C , D , A , B , 14 , is3 , Uns(2878612391)); + ii(B , C , D , A , 5 , is4 , Uns(4237533241)); + ii(A , B , C , D , 12 , is1 , Uns(1700485571)); + ii(D , A , B , C , 3 , is2 , Uns(2399980690)); + ii(C , D , A , B , 10 , is3 , Uns(4293915773)); + ii(B , C , D , A , 1 , is4 , Uns(2240044497)); + ii(A , B , C , D , 8 , is1 , Uns(1873313359)); + ii(D , A , B , C , 15 , is2 , Uns(4264355552)); + ii(C , D , A , B , 6 , is3 , Uns(2734768916)); + ii(B , C , D , A , 13 , is4 , Uns(1309151649)); + ii(A , B , C , D , 4 , is1 , Uns(4149444226)); + ii(D , A , B , C , 11 , is2 , Uns(3174756917)); + ii(C , D , A , B , 2 , is3 , Uns(718787259)); + ii(B , C , D , A , 9 , is4 , Uns(3951481745)); + + MDp->buffer[0] += A; + MDp->buffer[1] += B; + MDp->buffer[2] += C; + MDp->buffer[3] += D; +#ifdef WORDS_BIGENDIAN + MDreverse(X); +#endif +} + +/* MDupdate(MDp,X,count) +** Input: MDp -- an MDptr +** X -- a pointer to an array of unsigned characters. +** count -- the number of bits of X to use. +** (if not a multiple of 8, uses high bits of last byte.) +** Update MDp using the number of bits of X given by count. +** This is the basic input routine for an MD5 user. +** The routine completes the MD computation when count < 512, so +** every MD computation should end with one call to MDupdate with a +** count less than 512. A call with count 0 will be ignored if the +** MD has already been terminated (done != 0), so an extra call with count +** 0 can be given as a ``courtesy close'' to force termination if desired. +** Returns : 0 if processing succeeds or was already done; +** -1 if processing was already done +** -2 if count was too large +*/ +int +MDupdate(MDptr MDp, + unsigned char *X, + unsigned int count) +{ + unsigned int i, tmp, bit, byte, mask; + unsigned char XX[64]; + unsigned char *p; + /* return with no error if this is a courtesy close with count + ** zero and MDp->done is true. + */ + if (count == 0 && MDp->done) return 0; + /* check to see if MD is already done and report error */ + if (MDp->done) { return -1; } +/* + if (MDp->done) { fprintf(stderr,"\nError: MDupdate MD already done."); return; } +*/ + /* Add count to MDp->count */ + tmp = count; + p = MDp->count; + while (tmp) + { tmp += *p; + *p++ = tmp; + tmp = tmp >> 8; + } + /* Process data */ + if (count == 512) + { /* Full block of data to handle */ + MDblock(MDp,(unsigned int *)X); + } + else if (count > 512) /* Check for count too large */ + return -2; +/* + { fprintf(stderr,"\nError: MDupdate called with illegal count value %d.",count); + return; + } +*/ + else /* partial block -- must be last block so finish up */ + { /* Find out how many bytes and residual bits there are */ + int copycount; + byte = count >> 3; + bit = count & 7; + copycount = byte; if (bit) copycount++; + /* Copy X into XX since we need to modify it */ + memset(XX,0,sizeof(XX)); + memcpy(XX,X,copycount); + + /* Add padding '1' bit and low-order zeros in last byte */ + mask = ((unsigned long)1) << (7 - bit); + XX[byte] = (XX[byte] | mask) & ~( mask - 1); + /* If room for bit count, finish up with this block */ + if (byte <= 55) + { for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; + MDblock(MDp,(unsigned int *)XX); + } + else /* need to do two blocks to finish up */ + { MDblock(MDp,(unsigned int *)XX); + for (i=0;i<56;i++) XX[i] = 0; + for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; + MDblock(MDp,(unsigned int *)XX); + } + /* Set flag saying we're done with MD computation */ + MDp->done = 1; + } + return 0; +} + +/* MDchecksum(data, len, MD5): do a checksum on an arbirtrary amount of data */ +int +MDchecksum(u_char *data, size_t len, u_char *mac, size_t maclen) +{ + MDstruct md; + MDstruct *MD = &md; + int rc = 0; + + MDbegin(MD); + while (len >= 64) { + rc = MDupdate(MD, data, 64*8); + if (rc) goto check_end; + data += 64; + len -= 64; + } + rc = MDupdate(MD, data, len*8); + if (rc) goto check_end; + + /* copy the checksum to the outgoing data (all of it that is requested). */ + MDget(MD, mac, maclen); + +check_end: + memset(&md,0,sizeof(md)); + return rc; +} + + +/* MDsign(data, len, MD5): do a checksum on an arbirtrary amount + of data, and prepended with a secret in the standard fashion */ +int +MDsign(u_char *data, size_t len, u_char *mac, size_t maclen, + u_char *secret, size_t secretlen) +{ +#define HASHKEYLEN 64 + + MDstruct MD; + u_char K1[HASHKEYLEN]; + u_char K2[HASHKEYLEN]; + u_char extendedAuthKey[HASHKEYLEN]; + u_char buf[HASHKEYLEN]; + size_t i; + u_char *cp; + int rc = 0; + +/* + memset(K1,0,HASHKEYLEN); + memset(K2,0,HASHKEYLEN); + memset(buf,0,HASHKEYLEN); + memset(extendedAuthKey,0,HASHKEYLEN); +*/ + + if (secretlen != 16 || secret == NULL || mac == NULL || data == NULL || + len <= 0 || maclen <= 0) { +/* DEBUGMSGTL(("md5","MD5 signing not properly initialized")); */ + return -1; + } + + memset(extendedAuthKey, 0, HASHKEYLEN); + memcpy(extendedAuthKey, secret, secretlen); + for(i = 0; i < HASHKEYLEN; i++) { + K1[i] = extendedAuthKey[i] ^ 0x36; + K2[i] = extendedAuthKey[i] ^ 0x5c; + } + + MDbegin(&MD); + rc = MDupdate(&MD, K1, HASHKEYLEN*8); + if (rc) goto update_end; + + i = len; + cp = data; + while (i >= 64) { + rc = MDupdate(&MD, cp, 64*8); + if (rc) goto update_end; + cp += 64; + i -= 64; + } + + rc = MDupdate(&MD, cp, i*8); + if (rc) goto update_end; + + memset(buf,0,HASHKEYLEN); + MDget(&MD, buf, HASHKEYLEN); + + MDbegin(&MD); + rc = MDupdate(&MD, K2, HASHKEYLEN*8); + if (rc) goto update_end; + rc = MDupdate(&MD, buf, 16*8); + if (rc) goto update_end; + + /* copy the sign checksum to the outgoing pointer */ + MDget(&MD, mac, maclen); + +update_end: + memset(buf, 0, HASHKEYLEN); + memset(K1, 0, HASHKEYLEN); + memset(K2, 0, HASHKEYLEN); + memset(extendedAuthKey, 0, HASHKEYLEN); + memset(&MD, 0, sizeof(MD)); + + return rc; +} + +void +MDget(MDstruct *MD, u_char *buf, size_t buflen) +{ + int i, j; + + /* copy the checksum to the outgoing data (all of it that is requested). */ + for(i=0; i < 4 && i*4 < (int)buflen; i++) + for(j=0; j < 4 && i*4+j < (int)buflen; j++) + buf[i*4+j] = (MD->buffer[i] >> j*8) & 0xff; +} + +/* +** End of md5.c +****************************(cut)*****************************************/ diff --git a/packages/net/snmp/lib/current/src/mib.c b/packages/net/snmp/lib/current/src/mib.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/mib.c @@ -0,0 +1,2589 @@ +//========================================================================== +// +// ./lib/current/src/mib.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * mib.c + * + * Update: 1998-07-17 + * Added print_oid_report* functions. + * + */ +/********************************************************************** + Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +#include + +#include +#include +#include +#if HAVE_NETINET_IN_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif + +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "mib.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "parse.h" +#include "int64.h" +#include "system.h" +#include "read_config.h" +#include "snmp_debug.h" +#include "default_store.h" + +static void sprint_by_type (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static int parse_subtree (struct tree *, const char *, oid *, size_t *); +static struct tree * _sprint_objid(char *buf, oid *objid, size_t objidlen); +static char *uptimeString (u_long, char *); +static void sprint_octet_string (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_opaque (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_object_identifier (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_timeticks (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_hinted_integer (char *, long, const char *, const char *); +static void sprint_integer (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_uinteger (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_gauge (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_counter (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_networkaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_ipaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_null (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_bitstring (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_nsapaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_counter64 (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_unknowntype (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_badtype (char *, struct variable_list *, struct enum_list *, const char *, const char *); +struct tree *_get_symbol(oid *objid, size_t objidlen, struct tree *subtree, char *buf, struct index_list *in_dices, char **end_of_known); + +#ifdef OPAQUE_SPECIAL_TYPES +static void sprint_float (char *, struct variable_list *, struct enum_list *, const char *, const char *); +static void sprint_double (char *, struct variable_list *, struct enum_list *, const char *, const char *); +#endif +void print_tree_node (FILE *f, struct tree *tp); + +/* helper functions for get_module_node */ +int node_to_oid(struct tree *, oid *, size_t *); +static int _add_strings_to_oid(struct tree *, char *, + oid *, size_t *, size_t); + +extern struct tree *tree_head; + +struct tree *Mib; /* Backwards compatibility */ + +oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 }; +static char Standard_Prefix[] = ".1.3.6.1.2.1"; + +/* Set default here as some uses of read_objid require valid pointer. */ +static char *Prefix = &Standard_Prefix[0]; +typedef struct _PrefixList { + const char *str; + int len; +} *PrefixListPtr, PrefixList; + +/* + * Here are the prefix strings. + * Note that the first one finds the value of Prefix or Standard_Prefix. + * Any of these MAY start with period; all will NOT end with period. + * Period is added where needed. See use of Prefix in this module. + */ +PrefixList mib_prefixes[] = { + { &Standard_Prefix[0] }, /* placeholder for Prefix data */ + { ".iso.org.dod.internet.mgmt.mib-2" }, + { ".iso.org.dod.internet.experimental" }, + { ".iso.org.dod.internet.private" }, + { ".iso.org.dod.internet.snmpParties" }, + { ".iso.org.dod.internet.snmpSecrets" }, + { NULL, 0 } /* end of list */ +}; + +static char * +uptimeString(u_long timeticks, + char *buf) +{ + int centisecs, seconds, minutes, hours, days; + + centisecs = timeticks % 100; + timeticks /= 100; + days = timeticks / (60 * 60 * 24); + timeticks %= (60 * 60 * 24); + + hours = timeticks / (60 * 60); + timeticks %= (60 * 60); + + minutes = timeticks / 60; + seconds = timeticks % 60; + + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) + sprintf(buf, "%d:%d:%02d:%02d.%02d", + days, hours, minutes, seconds, centisecs); + else { + if (days == 0){ + sprintf(buf, "%d:%02d:%02d.%02d", + hours, minutes, seconds, centisecs); + } else if (days == 1) { + sprintf(buf, "%d day, %d:%02d:%02d.%02d", + days, hours, minutes, seconds, centisecs); + } else { + sprintf(buf, "%d days, %d:%02d:%02d.%02d", + days, hours, minutes, seconds, centisecs); + } + } + return buf; +} + + + +void sprint_hexstring(char *buf, + const u_char *cp, + size_t len) +{ + + for(; len >= 16; len -= 16){ + sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + buf += strlen(buf); + cp += 8; + sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + buf += strlen(buf); + if (len > 16) { *buf++ = '\n'; *buf = 0; } + cp += 8; + } + for(; len > 0; len--){ + sprintf(buf, "%02X ", *cp++); + buf += strlen(buf); + } + *buf = '\0'; +} + +void sprint_asciistring(char *buf, + u_char *cp, + size_t len) +{ + int x; + + for(x = 0; x < (int)len; x++){ + if (isprint(*cp)){ + *buf++ = *cp++; + } else { + *buf++ = '.'; + cp++; + } +#if 0 + if ((x % 48) == 47) + *buf++ = '\n'; +#endif + } + *buf = '\0'; +} + + +/* + 0 + < 4 + hex + + 0 "" + < 4 hex Hex: oo oo oo + < 4 "fgh" Hex: oo oo oo + > 4 hex Hex: oo oo oo oo oo oo oo oo + > 4 "this is a test" + + */ + +static void +sprint_octet_string(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + int hex, x; + u_char *cp; + const char *saved_hint = hint; + char *saved_buf = buf; + + if (var->type != ASN_OCTET_STR){ + sprintf(buf, "Wrong Type (should be OCTET STRING): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + + if (hint) { + int repeat, width = 1; + long value; + char code = 'd', separ = 0, term = 0, ch; + u_char *ecp; + + *buf = 0; + cp = var->val.string; + ecp = cp + var->val_len; + while (cp < ecp) { + repeat = 1; + if (*hint) { + if (*hint == '*') { + repeat = *cp++; + hint++; + } + width = 0; + while ('0' <= *hint && *hint <= '9') + width = width * 10 + *hint++ - '0'; + code = *hint++; + if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9') + && (width != 0 || (ch != 'x' && ch != 'd' && ch != 'o'))) + separ = *hint++; + else separ = 0; + if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9') + && (width != 0 || (ch != 'x' && ch != 'd' && ch != 'o'))) + term = *hint++; + else term = 0; + if (width == 0) width = 1; + } + while (repeat && cp < ecp) { + value = 0; + if (code != 'a') + for (x = 0; x < width; x++) value = value * 256 + *cp++; + switch (code) { + case 'x': + sprintf (buf, "%lx", value); break; + case 'd': + sprintf (buf, "%ld", value); break; + case 'o': + sprintf (buf, "%lo", value); break; + case 'a': + for (x = 0; x < width && cp < ecp; x++) + *buf++ = *cp++; + *buf = 0; + break; + default: + sprintf(saved_buf, "(Bad hint ignored: %s) ", saved_hint); + sprint_octet_string(saved_buf+strlen(saved_buf), + var, enums, NULL, NULL); + return; + } + buf += strlen (buf); + if (cp < ecp && separ) *buf++ = separ; + repeat--; + } + if (term && cp < ecp) *buf++ = term; + } + if (units) sprintf (buf, " %s", units); + return; + } + + hex = 0; + for(cp = var->val.string, x = 0; x < (int)var->val_len; x++, cp++){ + if (!(isprint(*cp) || isspace(*cp))) + hex = 1; + } + if (var->val_len == 0){ + strcpy(buf, "\"\""); + return; + } + if (!hex){ + *buf++ = '"'; + sprint_asciistring(buf, var->val.string, var->val_len); + buf += strlen(buf); + *buf++ = '"'; + *buf = '\0'; + } + if (hex || ((var->val_len <= 4) && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))){ + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + *buf++ = '"'; + *buf = '\0'; + } else { + sprintf(buf, " Hex: "); + buf += strlen(buf); + } + sprint_hexstring(buf, var->val.string, var->val_len); + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + buf += strlen(buf); + *buf++ = '"'; + *buf = '\0'; + } + } + if (units) sprintf (buf, " %s", units); +} + +#ifdef OPAQUE_SPECIAL_TYPES + +static void +sprint_float(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + if (var->type != ASN_OPAQUE_FLOAT) { + sprintf(buf, "Wrong Type (should be Float): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + sprintf(buf, "Opaque: Float:"); + buf += strlen(buf); + } + sprintf(buf, " %f", *var->val.floatVal); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_double(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + if (var->type != ASN_OPAQUE_DOUBLE) { + sprintf(buf, "Wrong Type (should be Double): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + sprintf(buf, "Opaque: Double:"); + buf += strlen(buf); + } + sprintf(buf, " %f", *var->val.doubleVal); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +#endif /* OPAQUE_SPECIAL_TYPES */ + +static void +sprint_opaque(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + + if (var->type != ASN_OPAQUE +#ifdef OPAQUE_SPECIAL_TYPES + && var->type != ASN_OPAQUE_COUNTER64 + && var->type != ASN_OPAQUE_U64 + && var->type != ASN_OPAQUE_I64 + && var->type != ASN_OPAQUE_FLOAT + && var->type != ASN_OPAQUE_DOUBLE +#endif /* OPAQUE_SPECIAL_TYPES */ + ){ + sprintf(buf, "Wrong Type (should be Opaque): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } +#ifdef OPAQUE_SPECIAL_TYPES + switch(var->type) { + case ASN_OPAQUE_COUNTER64: + case ASN_OPAQUE_U64: + case ASN_OPAQUE_I64: + sprint_counter64(buf, var, enums, hint, units); + break; + + case ASN_OPAQUE_FLOAT: + sprint_float(buf, var, enums, hint, units); + break; + + case ASN_OPAQUE_DOUBLE: + sprint_double(buf, var, enums, hint, units); + break; + + case ASN_OPAQUE: +#endif + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + sprintf(buf, "OPAQUE: "); + buf += strlen(buf); + } + sprint_hexstring(buf, var->val.string, var->val_len); + buf += strlen (buf); +#ifdef OPAQUE_SPECIAL_TYPES + } +#endif + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_object_identifier(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + if (var->type != ASN_OBJECT_ID){ + sprintf(buf, "Wrong Type (should be OBJECT IDENTIFIER): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + sprintf(buf, "OID: "); + buf += strlen(buf); + } + _sprint_objid(buf, (oid *)(var->val.objid), var->val_len / sizeof(oid)); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_timeticks(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + char timebuf[32]; + + if (var->type != ASN_TIMETICKS){ + sprintf(buf, "Wrong Type (should be Timeticks): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + sprintf(buf, "Timeticks: (%lu) ", *(u_long *)(var->val.integer)); + buf += strlen(buf); + } + sprintf(buf, "%s", uptimeString(*(u_long *)(var->val.integer), timebuf)); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_hinted_integer (char *buf, + long val, + const char *hint, + const char *units) +{ + char code; + int shift, len; + char tmp[256]; + char fmt[10]; + + code = hint[0]; + if (hint [1] == '-') { + shift = atoi (hint+2); + } + else shift = 0; + fmt[0] = '%'; + fmt[1] = 'l'; + fmt[2] = code; + fmt[3] = 0; + sprintf (tmp, fmt, val); + if (shift != 0) { + len = strlen (tmp); + if (shift <= len) { + tmp[len+1] = 0; + while (shift--) { + tmp[len] = tmp[len-1]; + len--; + } + tmp[len] = '.'; + } + else { + tmp[shift+1] = 0; + while (shift) { + if (len-- > 0) tmp [shift] = tmp [len]; + else tmp[shift] = '0'; + shift--; + } + tmp[0] = '.'; + } + } + strcpy (buf, tmp); +} + +static void +sprint_integer(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + char *enum_string = NULL; + + if (var->type != ASN_INTEGER){ + sprintf(buf, "Wrong Type (should be INTEGER): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + for (; enums; enums = enums->next) + if (enums->value == *var->val.integer){ + enum_string = enums->label; + break; + } + if (enum_string == NULL || + ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM)) { + if (hint) sprint_hinted_integer(buf, *var->val.integer, hint, units); + else sprintf(buf, "%ld", *var->val.integer); + } + else if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) + sprintf(buf, "%s", enum_string); + else + sprintf(buf, "%s(%ld)", enum_string, *var->val.integer); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_uinteger(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + char *enum_string = NULL; + + if (var->type != ASN_UINTEGER){ + sprintf(buf, "Wrong Type (should be UInteger32): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + for (; enums; enums = enums->next) + if (enums->value == *var->val.integer){ + enum_string = enums->label; + break; + } + if (enum_string == NULL || + ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM)) + sprintf(buf, "%lu", *var->val.integer); + else if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) + sprintf(buf, "%s", enum_string); + else + sprintf(buf, "%s(%lu)", enum_string, *var->val.integer); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_gauge(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + if (var->type != ASN_GAUGE){ + sprintf(buf, "Wrong Type (should be Gauge): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) + sprintf(buf, "%lu", *var->val.integer); + else + sprintf(buf, "Gauge: %lu", *var->val.integer); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_counter(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + if (var->type != ASN_COUNTER){ + sprintf(buf, "Wrong Type (should be Counter): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + sprintf(buf, "%lu", *var->val.integer); + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_networkaddress(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + int x, len; + u_char *cp; + + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + sprintf(buf, "Network Address: "); + buf += strlen(buf); + } + cp = var->val.string; + len = var->val_len; + for(x = 0; x < len; x++){ + sprintf(buf, "%02X", *cp++); + buf += strlen(buf); + if (x < (len - 1)) + *buf++ = ':'; + } +} + +static void +sprint_ipaddress(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + u_char *ip; + + if (var->type != ASN_IPADDRESS){ + sprintf(buf, "Wrong Type (should be Ipaddress): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + ip = var->val.string; + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) + sprintf(buf, "%d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]); + else + sprintf(buf, "IpAddress: %d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]); +} + +static void +sprint_null(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + if (var->type != ASN_NULL){ + sprintf(buf, "Wrong Type (should be NULL): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + sprintf(buf, "NULL"); +} + +static void +sprint_bitstring(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + int len, bit; + u_char *cp; + char *enum_string; + + if (var->type != ASN_BIT_STR && var->type != ASN_OCTET_STR){ + sprintf(buf, "Wrong Type (should be BIT STRING): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + *buf++ = '"'; + *buf = '\0'; + } else { + sprintf(buf, "BITS: "); + buf += strlen(buf); + } + sprint_hexstring(buf, var->val.bitstring, var->val_len); + buf += strlen(buf); + + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + buf += strlen(buf); + *buf++ = '"'; + *buf = '\0'; + } else { + cp = var->val.bitstring; + for(len = 0; len < (int)var->val_len; len++){ + for(bit = 0; bit < 8; bit++){ + if (*cp & (0x80 >> bit)){ + enum_string = NULL; + for (; enums; enums = enums->next) + if (enums->value == (len * 8) + bit){ + enum_string = enums->label; + break; + } + if (enum_string == NULL || + ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM)) + sprintf(buf, "%d ", (len * 8) + bit); + else + sprintf(buf, "%s(%d) ", enum_string, (len * 8) + bit); + buf += strlen(buf); + } + } + cp ++; + } + } +} + +static void +sprint_nsapaddress(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + if (var->type != ASN_NSAP){ + sprintf(buf, "Wrong Type (should be NsapAddress): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ + sprintf(buf, "NsapAddress: "); + buf += strlen(buf); + } + sprint_hexstring(buf, var->val.string, var->val_len); +} + +static void +sprint_counter64(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + char a64buf[I64CHARSZ+1]; + + if (var->type != ASN_COUNTER64 +#ifdef OPAQUE_SPECIAL_TYPES + && var->type != ASN_OPAQUE_COUNTER64 + && var->type != ASN_OPAQUE_I64 + && var->type != ASN_OPAQUE_U64 +#endif + ){ + sprintf(buf, "Wrong Type (should be Counter64): "); + buf += strlen(buf); + sprint_by_type(buf, var, NULL, NULL, NULL); + return; + } + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ +#ifdef OPAQUE_SPECIAL_TYPES + if (var->type != ASN_COUNTER64) { + sprintf(buf, "Opaque: "); + buf += strlen(buf); + } +#endif +#ifdef OPAQUE_SPECIAL_TYPES + switch(var->type) { + case ASN_OPAQUE_U64: + sprintf(buf, "UInt64: "); + break; + case ASN_OPAQUE_I64: + sprintf(buf, "Int64: "); + break; + case ASN_COUNTER64: + case ASN_OPAQUE_COUNTER64: +#endif + sprintf(buf, "Counter64: "); +#ifdef OPAQUE_SPECIAL_TYPES + } +#endif + buf += strlen(buf); + } +#ifdef OPAQUE_SPECIAL_TYPES + if (var->type == ASN_OPAQUE_I64) + { + printI64(a64buf, var->val.counter64); + sprintf(buf, a64buf); + } + else +#endif + { + printU64(a64buf, var->val.counter64); + sprintf(buf, a64buf); + } + buf += strlen (buf); + if (units) sprintf (buf, " %s", units); +} + +static void +sprint_unknowntype(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ +/* sprintf(buf, "Variable has bad type"); */ + sprint_by_type(buf, var, NULL, NULL, NULL); +} + +static void +sprint_badtype(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + sprintf(buf, "Variable has bad type"); +} + +static void +sprint_by_type(char *buf, + struct variable_list *var, + struct enum_list *enums, + const char *hint, + const char *units) +{ + switch (var->type){ + case ASN_INTEGER: + sprint_integer(buf, var, enums, hint, units); + break; + case ASN_OCTET_STR: + sprint_octet_string(buf, var, enums, hint, units); + break; + case ASN_BIT_STR: + sprint_bitstring(buf, var, enums, hint, units); + break; + case ASN_OPAQUE: + sprint_opaque(buf, var, enums, hint, units); + break; + case ASN_OBJECT_ID: + sprint_object_identifier(buf, var, enums, hint, units); + break; + case ASN_TIMETICKS: + sprint_timeticks(buf, var, enums, hint, units); + break; + case ASN_GAUGE: + sprint_gauge(buf, var, enums, hint, units); + break; + case ASN_COUNTER: + sprint_counter(buf, var, enums, hint, units); + break; + case ASN_IPADDRESS: + sprint_ipaddress(buf, var, enums, hint, units); + break; + case ASN_NULL: + sprint_null(buf, var, enums, hint, units); + break; + case ASN_UINTEGER: + sprint_uinteger(buf, var, enums, hint, units); + break; + case ASN_COUNTER64: +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_U64: + case ASN_OPAQUE_I64: + case ASN_OPAQUE_COUNTER64: +#endif /* OPAQUE_SPECIAL_TYPES */ + sprint_counter64(buf, var, enums, hint, units); + break; +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_FLOAT: + sprint_float(buf, var, enums, hint, units); + break; + case ASN_OPAQUE_DOUBLE: + sprint_double(buf, var, enums, hint, units); + break; +#endif /* OPAQUE_SPECIAL_TYPES */ + default: + DEBUGMSGTL(("sprint_by_type", "bad type: %d\n", var->type)); + sprint_badtype(buf, var, enums, hint, units); + break; + } +} + + +struct tree *get_tree_head(void) +{ + return(tree_head); +} + +static char *confmibdir=NULL; +static char *confmibs=NULL; + +void +handle_mibdirs_conf(const char *token, + char *line) +{ + char *ctmp; + + if (confmibdir) { + ctmp = (char *)malloc(strlen(confmibdir) + strlen(line) + 1); + if (*line == '+') + line++; + sprintf(ctmp,"%s%c%s",confmibdir, ENV_SEPARATOR_CHAR, line); + free(confmibdir); + confmibdir = ctmp; + } else { + confmibdir=strdup(line); + } + DEBUGMSGTL(("read_config:initmib", "using mibdirs: %s\n", confmibdir)); +} + +void +handle_mibs_conf(const char *token, + char *line) +{ + char *ctmp; + + if (confmibs) { + ctmp = (char *)malloc(strlen(confmibs) + strlen(line) + 1); + if (*line == '+') + line++; + sprintf(ctmp,"%s%c%s",confmibs, ENV_SEPARATOR_CHAR, line); + free(confmibs); + confmibs = ctmp; + } else { + confmibs=strdup(line); + } + DEBUGMSGTL(("read_config:initmib", "using mibs: %s\n", confmibs)); +} + +void +handle_mibfile_conf(const char *token, + char *line) +{ + DEBUGMSGTL(("read_config:initmib", "reading mibfile: %s\n", line)); + read_mib(line); +} + +char * +snmp_out_toggle_options(char *options) +{ + while(*options) { + switch(*options++) { + case 'n': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_OIDS); + break; + case 'e': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_ENUM); + break; + case 'b': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_DONT_BREAKDOWN_OIDS); + break; + case 'q': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT); + break; + case 'f': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID); + break; + case 's': + snmp_set_suffix_only(1); + break; + case 'S': + snmp_set_suffix_only(2); + break; + default: + return options-1; + } + } + return NULL; +} + +void snmp_out_toggle_options_usage(const char *lead, FILE *outf) +{ + fprintf(outf, "%sOUTOPTS values:\n", lead); + fprintf(outf, "%s n: Print oids numerically.\n", lead); + fprintf(outf, "%s e: Print enums numerically.\n", lead); + fprintf(outf, "%s b: Dont break oid indexes down.\n", lead); + fprintf(outf, "%s q: Quick print for easier parsing.\n", lead); + fprintf(outf, "%s f: Print full oids on output.\n", lead); + fprintf(outf, "%s s: Print only last symbolic element of oid.\n", lead); + fprintf(outf, "%s S: Print MIB module-id plus last element.\n", lead); +} + +char * +snmp_in_toggle_options(char *options) +{ + while(*options) { + switch(*options++) { + case 'R': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_RANDOM_ACCESS); + break; + case 'b': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_REGEX_ACCESS); + break; + default: + return options-1; + } + } + return NULL; +} + +void snmp_in_toggle_options_usage(const char *lead, FILE *outf) +{ + fprintf(outf, "%sINOPTS values:\n", lead); + fprintf(outf, "%s R: Do random access to oid labels.\n", lead); + fprintf(outf, "%s b: Do best/regex matching to find a MIB node.\n", lead); +} + +void +register_mib_handlers (void) +{ + register_premib_handler("snmp","mibdirs", + handle_mibdirs_conf, NULL, + "[mib-dirs|+mib-dirs]"); + register_premib_handler("snmp","mibs", + handle_mibs_conf,NULL, + "[mib-tokens|+mib-tokens]"); + register_config_handler("snmp","mibfile", + handle_mibfile_conf, NULL, + "mibfile-to-read"); + + /* register the snmp.conf configuration handlers for default + parsing behaviour */ + + ds_register_premib(ASN_BOOLEAN, "snmp","showMibErrors", + DS_LIBRARY_ID, DS_LIB_MIB_ERRORS); + ds_register_premib(ASN_BOOLEAN, "snmp","strictCommentTerm", + DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM); + ds_register_premib(ASN_BOOLEAN, "snmp","mibAllowUnderline", + DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL); + ds_register_premib(ASN_INTEGER, "snmp","mibWarningLevel", + DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS); + ds_register_premib(ASN_BOOLEAN, "snmp","mibReplaceWithLatest", + DS_LIBRARY_ID, DS_LIB_MIB_REPLACE); + + ds_register_config(ASN_BOOLEAN, "snmp","printNumericEnums", + DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_ENUM); + ds_register_config(ASN_BOOLEAN, "snmp","printNumericOids", + DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_OIDS); + ds_register_config(ASN_BOOLEAN, "snmp","dontBreakdownOids", + DS_LIBRARY_ID, DS_LIB_DONT_BREAKDOWN_OIDS); + ds_register_config(ASN_BOOLEAN, "snmp","quickPrinting", + DS_LIBRARY_ID, DS_LIB_QUICK_PRINT); + ds_register_config(ASN_INTEGER, "snmp","suffixPrinting", + DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY); + + /* setup the default parser configurations, as specified by configure */ +#ifdef MIB_COMMENT_IS_EOL_TERMINATED + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, 1); +#else /* !MIB_COMMENT_IS_EOL_TERMINATED */ + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, 0); +#endif /* !MIB_COMMENT_IS_EOL_TERMINATED */ +} + +void +init_mib (void) +{ + const char *prefix; + char *env_var, *entry; + PrefixListPtr pp = &mib_prefixes[0]; + char *new_mibdirs, *homepath, *cp_home; + + if (Mib) return; + + /* Initialise the MIB directory/ies */ + + /* we can't use the environment variable directly, because strtok + will modify it. */ + + env_var = getenv("MIBDIRS"); + if ( env_var == NULL ) { + if (confmibdir != NULL) + env_var = strdup(confmibdir); + else + env_var = strdup(DEFAULT_MIBDIRS); + } else { + env_var = strdup(env_var); + } + if (*env_var == '+') { + entry = (char *)malloc(strlen(DEFAULT_MIBDIRS)+strlen(env_var)+2); + sprintf(entry, "%s%c%s", DEFAULT_MIBDIRS, ENV_SEPARATOR_CHAR, env_var+1); + free(env_var); + env_var = entry; + } + + /* replace $HOME in the path with the users home directory */ + homepath=getenv("HOME"); + + if (homepath) { + while((cp_home = strstr(env_var, "$HOME"))) { + new_mibdirs = (char *) malloc(strlen(env_var) - strlen("$HOME") + + strlen(homepath)+1); + *cp_home = 0; /* null out the spot where we stop copying */ + sprintf(new_mibdirs, "%s%s%s", env_var, homepath, + cp_home + strlen("$HOME")); + /* swap in the new value and repeat */ + free(env_var); + env_var = new_mibdirs; + } + } + + DEBUGMSGTL(("init_mib","Seen MIBDIRS: Looking in '%s' for mib dirs ...\n",env_var)); + + entry = strtok( env_var, ENV_SEPARATOR ); + while ( entry ) { + add_mibdir(entry); + entry = strtok( NULL, ENV_SEPARATOR); + } + free(env_var); + + init_mib_internals(); + + /* Read in any modules or mibs requested */ + + env_var = getenv("MIBS"); + if ( env_var == NULL ) { + if (confmibs != NULL) + env_var = strdup(confmibs); + else + env_var = strdup(DEFAULT_MIBS); + } else { + env_var = strdup(env_var); + } + if (*env_var == '+') { + entry = (char *)malloc(strlen(DEFAULT_MIBS)+strlen(env_var)+2); + sprintf(entry, "%s%c%s", DEFAULT_MIBS, ENV_SEPARATOR_CHAR, env_var+1); + free(env_var); + env_var = entry; + } + + DEBUGMSGTL(("init_mib","Seen MIBS: Looking in '%s' for mib files ...\n",env_var)); + entry = strtok( env_var, ENV_SEPARATOR ); + while ( entry ) { + if (strcasecmp(entry, DEBUG_ALWAYS_TOKEN) == 0) { + read_all_mibs(); + } + else if (strstr (entry, "/") != 0) { + read_mib(entry); + } + else { + read_module(entry); + } + entry = strtok( NULL, ENV_SEPARATOR); + } + adopt_orphans(); + free(env_var); + + env_var = getenv("MIBFILES"); + if ( env_var != NULL ) { + if (*env_var == '+') { +#ifdef DEFAULT_MIBFILES + entry = (char *)malloc(strlen(DEFAULT_MIBFILES)+strlen(env_var)+2); + sprintf(entry, "%s%c%s", DEFAULT_MIBFILES, ENV_SEPARATOR_CHAR, + env_var+1); + free(env_var); + env_var = entry; +#else + env_var = strdup(env_var+1); +#endif + } else { + env_var = strdup(env_var); + } + } else { +#ifdef DEFAULT_MIBFILES + env_var = strdup(DEFAULT_MIBFILES); +#endif + } + + if ( env_var != 0 ) { + DEBUGMSGTL(("init_mib","Seen MIBFILES: Looking in '%s' for mib files ...\n",env_var)); + entry = strtok( env_var, ENV_SEPARATOR ); + while ( entry ) { + read_mib(entry); + entry = strtok( NULL, ENV_SEPARATOR); + } + free(env_var); + } + + prefix = getenv("PREFIX"); + + if (!prefix) + prefix = Standard_Prefix; + + Prefix = (char*)malloc(strlen(prefix)+2); + strcpy(Prefix, prefix); + + DEBUGMSGTL(("init_mib","Seen PREFIX: Looking in '%s' for prefix ...\n", Prefix)); + + /* remove trailing dot */ + env_var = &Prefix[strlen(Prefix) - 1]; + if (*env_var == '.') *env_var = '\0'; + + pp->str = Prefix; /* fixup first mib_prefix entry */ + /* now that the list of prefixes is built, save each string length. */ + while (pp->str) { + pp->len = strlen(pp->str); + pp++; + } + + if (getenv("SUFFIX")) + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY, 1); + + Mib = tree_head; /* Backwards compatibility */ +} + +void +print_mib (FILE *fp) +{ + print_subtree (fp, tree_head, 0); +} + +void +print_ascii_dump (FILE *fp) +{ + fprintf(fp, "dump DEFINITIONS ::= BEGIN\n"); + print_ascii_dump_tree (fp, tree_head, 0); + fprintf(fp, "END\n"); +} + +void +set_function(struct tree *subtree) +{ + switch(subtree->type){ + case TYPE_OBJID: + subtree->printer = sprint_object_identifier; + break; + case TYPE_OCTETSTR: + subtree->printer = sprint_octet_string; + break; + case TYPE_INTEGER: + subtree->printer = sprint_integer; + break; + case TYPE_NETADDR: + subtree->printer = sprint_networkaddress; + break; + case TYPE_IPADDR: + subtree->printer = sprint_ipaddress; + break; + case TYPE_COUNTER: + subtree->printer = sprint_counter; + break; + case TYPE_GAUGE: + subtree->printer = sprint_gauge; + break; + case TYPE_TIMETICKS: + subtree->printer = sprint_timeticks; + break; + case TYPE_OPAQUE: + subtree->printer = sprint_opaque; + break; + case TYPE_NULL: + subtree->printer = sprint_null; + break; + case TYPE_BITSTRING: + subtree->printer = sprint_bitstring; + break; + case TYPE_NSAPADDRESS: + subtree->printer = sprint_nsapaddress; + break; + case TYPE_COUNTER64: + subtree->printer = sprint_counter64; + break; + case TYPE_UINTEGER: + subtree->printer = sprint_uinteger; + break; + case TYPE_OTHER: + default: + subtree->printer = sprint_unknowntype; + break; + } +} + +/* + * Read an object identifier from input string into internal OID form. + * Returns 1 if successful. + * If an error occurs, this function returns 0 and MAY set snmp_errno. + * snmp_errno is NOT set if SET_SNMP_ERROR evaluates to nothing. + * This can make multi-threaded use a tiny bit more robust. + */ +int read_objid(const char *input, + oid *output, + size_t *out_len) /* number of subid's in "output" */ +{ + struct tree *root = tree_head; + char buf[SPRINT_MAX_LEN]; + int ret; + + if (strchr(input, ':')) { + return get_node(input, output, out_len); + } + + if (*input == '.') + input++; + else { + /* get past leading '.', append '.' to Prefix. */ + if (*Prefix == '.') + strcpy(buf, Prefix+1); + else + strcpy(buf, Prefix); + strcat(buf, "."); + strcat(buf, input); + input = buf; + } + + if (root == NULL){ + SET_SNMP_ERROR(SNMPERR_NOMIB); + *out_len = 0; + return(0); + } + if ((ret = parse_subtree(root, input, output, out_len)) <= 0) + { + int errc = (ret ? ret : SNMPERR_UNKNOWN_OBJID); + SET_SNMP_ERROR(errc); + return (0); + } + *out_len = ret; + + return (1); +} + + +/* + * RECURSIVE helper methods for read_objid + * Returns: + * < 0 the SNMPERR_ errorcode + * = 0 input string is empty. + * > 0 the number of sub-identifiers found in the input string. + */ +static int +parse_subtree(struct tree *subtree, + const char *input, + oid *output, + size_t *out_len) /* number of subid's */ +{ + char buf[SPRINT_MAX_LEN], *to = buf, *cp; + u_long subid = 0; + struct tree *tp; + int ret, len; + + /* + * No empty strings. Can happen if there is a trailing '.' or two '.'s + * in a row, i.e. "..". + */ + if ((*input == '\0') || + (*input == '.')) + return (0); + + if (*input == '"' || *input == '\'') { + /* + * This is a string that should be converted into an OID + * Note: assumes variable length index is required, and prepends + * the string length. + */ + if ((cp = strchr(input+1, *input)) == NULL) { + /* error. Should be a matching quote somewhere. */ + return (0); + } + + /* is there room enough for the string in question plus its length */ + len = cp-input-1; + if ((int)*out_len <= len){ + return (SNMPERR_LONG_OID); + } + + /* copy everything in */ + if (*input++ == '"') { + /* add the length for " quoted objects */ + *output++ = len++; + } + + *out_len -= len; + while (input < cp) { + *output++ = *input++; + } + + /* Now, we assume that nothing beyond this exists in the parse + tree, which should always be true (or else we have a really wacked + mib designer somewhere. */ + input = cp + 1; /* past the quote */ + + if (*input != '.') + return (len); + + ret = parse_subtree(NULL, ++input, output, out_len); + if (ret <= 0) + return (ret); + return ret+len; + + } else if (isdigit(*input)) { + /* + * Read the number, then try to find it in the subtree. + */ + while (isdigit(*input)) { + *to++ = *input; + subid *= 10; + subid += *input++ - '0'; + } + if (*input != '.' && *input != 0) { + while (*input != 0 && *input != '.') *to++ = *input++; + *to = 0; + snmp_set_detail(buf); + return SNMPERR_BAD_SUBID; + } + *to = '\0'; + + for (tp = subtree; tp; tp = tp->next_peer) { + if (tp->subid == subid) + goto found; + } + } + else { + /* + * Read the name into a buffer. + */ + while ((*input != '\0') && + (*input != '.')) { + *to++ = *input++; + } + *to = '\0'; + + /* + * Find the name in the subtree; + */ + for (tp = subtree; tp; tp = tp->next_peer) { + if (strcasecmp(tp->label, buf) == 0) { + subid = tp->subid; + goto found; + } + } + + /* + * If we didn't find the entry, punt... + */ + if (tp == NULL) { + snmp_set_detail(buf); + return (SNMPERR_BAD_SUBID); + } + } + +found: + if(subid > (u_long)MAX_SUBID){ + snmp_set_detail(buf); + return (SNMPERR_MAX_SUBID); + } + + if ((int)*out_len <= 0){ + return (SNMPERR_LONG_OID); + } + + (*out_len)--; + *output++ = subid; + + if (*input != '.') + return (1); + + ret = parse_subtree(tp ? tp->child_list : NULL, + ++input, output, out_len); + if (ret <= 0) + return (ret); + return ret+1; +} + +static struct tree * +_sprint_objid(char *buf, + oid *objid, + size_t objidlen) /* number of subidentifiers */ +{ + char tempbuf[SPRINT_MAX_LEN], *cp; + struct tree *subtree = tree_head; + char *midpoint = 0; + + *tempbuf = '.'; /* this is a fully qualified name */ + subtree = _get_symbol(objid, objidlen, subtree, tempbuf + 1, 0, &midpoint); + if (ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS)) { + cp = tempbuf; + } else if (ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY)){ + for(cp = tempbuf; *cp; cp++) + ; + if (midpoint) + cp = midpoint-2; /* beyond the '.' */ + else { + while(cp >= tempbuf){ + if (isalpha(*cp)) + break; + cp--; + } + } + while(cp >= tempbuf){ + if (*cp == '.') + break; + cp--; + } + cp++; + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY) == 2 && cp > tempbuf) { + char modbuf[256]; + char *mod = module_name(subtree->modid, modbuf); + size_t len = strlen(mod); + if ((int)len+1 >= cp-tempbuf) { + memmove(tempbuf+len+2, cp, strlen(cp)+1); + cp = tempbuf+len+2; + } + cp -= len+2; + memcpy(cp, mod, len); + cp[len] = ':'; + cp[len+1] = ':'; + } + } + else if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID)) { + PrefixListPtr pp = &mib_prefixes[0]; + int ii; + size_t ilen, tlen; + const char *testcp; + cp = tempbuf; tlen = strlen(tempbuf); + ii = 0; + while (pp->str) { + ilen = pp->len; testcp = pp->str; + if ((tlen > ilen) && !memcmp(tempbuf, testcp, ilen)) { + cp += (ilen + 1); + break; + } + pp++; + } + } + else cp = tempbuf; + strcpy(buf, cp); + return subtree; +} + +char * sprint_objid(char *buf, oid *objid, size_t objidlen) +{ + _sprint_objid(buf,objid,objidlen); + return buf; +} + +void +print_objid(oid *objid, + size_t objidlen) /* number of subidentifiers */ +{ + fprint_objid(stdout, objid, objidlen); +} + +void +fprint_objid(FILE *f, + oid *objid, + size_t objidlen) /* number of subidentifiers */ +{ + char buf[SPRINT_MAX_LEN]; + + _sprint_objid(buf, objid, objidlen); + fprintf(f, "%s\n", buf); +} + +void +sprint_variable(char *buf, + oid *objid, + size_t objidlen, + struct variable_list *variable) +{ + struct tree *subtree; + + subtree = _sprint_objid(buf, objid, objidlen); + buf += strlen(buf); + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) + strcat(buf, " "); + else + strcat(buf, " = "); + buf += strlen(buf); + + if (variable->type == SNMP_NOSUCHOBJECT) + strcpy(buf, "No Such Object available on this agent"); + else if (variable->type == SNMP_NOSUCHINSTANCE) + strcpy(buf, "No Such Instance currently exists"); + else if (variable->type == SNMP_ENDOFMIBVIEW) + strcpy(buf, "No more variables left in this MIB View"); + else if (subtree) { + if (subtree->printer) + (*subtree->printer)(buf, variable, subtree->enums, subtree->hint, subtree->units); + else { + sprint_by_type(buf, variable, subtree->enums, subtree->hint, subtree->units); + } + } + else { /* handle rare case where tree is empty */ + sprint_by_type(buf, variable, 0, 0, 0); + } +} + +void +print_variable(oid *objid, + size_t objidlen, + struct variable_list *variable) +{ + fprint_variable(stdout, objid, objidlen, variable); +} + +void +fprint_variable(FILE *f, + oid *objid, + size_t objidlen, + struct variable_list *variable) +{ + char buf[SPRINT_MAX_LEN]; + + sprint_variable(buf, objid, objidlen, variable); + fprintf(f, "%s\n", buf); +} + +void +sprint_value(char *buf, + oid *objid, + size_t objidlen, + struct variable_list *variable) +{ + char tempbuf[SPRINT_MAX_LEN]; + struct tree *subtree = tree_head; + + if (variable->type == SNMP_NOSUCHOBJECT) + sprintf(buf, "No Such Object available on this agent"); + else if (variable->type == SNMP_NOSUCHINSTANCE) + sprintf(buf, "No Such Instance currently exists"); + else if (variable->type == SNMP_ENDOFMIBVIEW) + sprintf(buf, "No more variables left in this MIB View"); + else { + subtree = get_symbol(objid, objidlen, subtree, tempbuf); + if (subtree->printer) + (*subtree->printer)(buf, variable, subtree->enums, subtree->hint, subtree->units); + else { + sprint_by_type(buf, variable, subtree->enums, subtree->hint, subtree->units); + } + } +} + +void +print_value(oid *objid, + size_t objidlen, + struct variable_list *variable) +{ + fprint_value(stdout, objid, objidlen, variable); +} + +void +fprint_value(FILE *f, + oid *objid, + size_t objidlen, + struct variable_list *variable) +{ + char tempbuf[SPRINT_MAX_LEN]; + + sprint_value(tempbuf, objid, objidlen, variable); + fprintf(f, "%s\n", tempbuf); +} + + +/* + * Append a quoted printable string to buffer "buf" + * that represents a range of sub-identifiers "objid". + * + * Display '.' for all non-printable sub-identifiers. + * If successful, "buf" points past the appended string. + */ +char * +dump_oid_to_string(oid *objid, + size_t objidlen, + char *buf, + char quotechar) +{ + if (buf) + { int ii, alen; + char *scp; + char *cp = buf + (strlen(buf)); + scp = cp; + for (ii= 0, alen = 0; ii < (int)objidlen; ii++) + { + oid tst = objid[ii]; + if ((tst > 254) || (!isprint(tst))) + tst = (oid)'.'; + + if (alen == 0) *cp++ = quotechar; + *cp++ = (char)tst; + alen++; + } + if (alen) *cp++ = quotechar; + *cp = '\0'; + buf = cp; + } + + return buf; +} + +struct tree * +_get_symbol(oid *objid, + size_t objidlen, + struct tree *subtree, + char *buf, + struct index_list *in_dices, + char **end_of_known) +{ + struct tree *return_tree = NULL; + + if (!objid || !buf) + return NULL; + + for(; subtree; subtree = subtree->next_peer){ + if (*objid == subtree->subid){ + if (subtree->indexes) + in_dices = subtree->indexes; + if (!strncmp( subtree->label, ANON, ANON_LEN) || + ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS)) + sprintf(buf, "%lu", subtree->subid); + else + strcpy(buf, subtree->label); + goto found; + } + } + + if (end_of_known) + *end_of_known = buf; + + /* subtree not found */ + + while (in_dices && (objidlen > 0) && + !ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS) && + !ds_get_boolean(DS_LIBRARY_ID,DS_LIB_DONT_BREAKDOWN_OIDS)) { + size_t numids; + struct tree *tp; + tp = find_tree_node(in_dices->ilabel, -1); + if (0 == tp) { + /* ack. Can't find an index in the mib tree. bail */ + goto finish_it; + } + switch(tp->type) { + case TYPE_OCTETSTR: + if (in_dices->isimplied) { + numids = objidlen; + buf = dump_oid_to_string(objid, numids, buf, '\''); + } else { + numids = (size_t)*objid+1; + if (numids > objidlen) + goto finish_it; + if (numids == 1) { + *buf++ = '"'; *buf++ = '"'; + } + else + buf = dump_oid_to_string(objid+1, numids-1, buf, '"'); + } + objid += (numids); + objidlen -= (numids); + *buf++ = '.'; + *buf = '\0'; + break; + case TYPE_INTEGER: + sprintf(buf, "%lu.", *objid++); + while(*buf) + buf++; + objidlen--; + break; + case TYPE_OBJID: + if (in_dices->isimplied) { + numids = objidlen; + } else { + numids = (size_t)*objid+1; + } + if ( numids > objidlen) + goto finish_it; + _get_symbol(objid, numids, NULL, buf, NULL, NULL); + objid += (numids); + objidlen -= (numids); + buf += strlen(buf); + *buf++ = '.'; + *buf = '\0'; + break; + default: + goto finish_it; + break; + } + in_dices = in_dices->next; + } + +finish_it: + + while(objidlen-- > 0){ /* output rest of name, uninterpreted */ + sprintf(buf, "%lu.", *objid++); + while(*buf) + buf++; + } + *(buf - 1) = '\0'; /* remove trailing dot */ + return NULL; + +found: + if (objidlen > 1){ + while(*buf) + buf++; + *buf++ = '.'; + *buf = '\0'; + + return_tree = _get_symbol(objid + 1, objidlen - 1, subtree->child_list, + buf, in_dices, end_of_known); + } + if (return_tree != NULL) + return return_tree; + else + return subtree; +} + +struct tree * +get_symbol(oid *objid, + size_t objidlen, + struct tree *subtree, + char *buf) +{ + return _get_symbol(objid,objidlen,subtree,buf,0,0); +} + +/* + * Clone of get_symbol that doesn't take a buffer argument + */ +struct tree * +get_tree(oid *objid, + size_t objidlen, + struct tree *subtree) +{ + struct tree *return_tree = NULL; + + for(; subtree; subtree = subtree->next_peer){ + if (*objid == subtree->subid) + goto found; + } + + return NULL; + +found: + if (objidlen > 1) + return_tree = get_tree(objid + 1, objidlen - 1, subtree->child_list); + if (return_tree != NULL) + return return_tree; + else + return subtree; +} + +void +print_description(oid *objid, + size_t objidlen) /* number of subidentifiers */ +{ + fprint_description(stdout, objid, objidlen); +} + +void +fprint_description(FILE *f, + oid *objid, + size_t objidlen) /* number of subidentifiers */ +{ + struct tree *tp = get_tree(objid, objidlen, tree_head); + struct tree *subtree = tree_head; + fprintf(f, "%s OBJECT-TYPE\n", tp->label); + print_tree_node(f, tp); + fprintf(f, "::= {"); + while (objidlen > 1) { + for(; subtree; subtree = subtree->next_peer){ + if (*objid == subtree->subid){ + if (strncmp( subtree->label, ANON, ANON_LEN)) + fprintf(f, " %s(%lu)", subtree->label, subtree->subid); + else + fprintf(f, " %lu", subtree->subid); + break; + } + } + if (subtree == 0) break; + objid++; objidlen--; subtree = subtree->child_list; + if (subtree == 0) break; + } + fprintf(f, " %lu }\n", *objid); +} + +void +print_tree_node(FILE *f, + struct tree *tp) +{ + const char *cp; + char str[MAXTOKEN]; + int i, prevmod; + if (tp) { + module_name(tp->modid, str); + fprintf(f, " -- FROM\t%s", str); + for (i = 1, prevmod = tp->modid; i < tp->number_modules; i++) { + if (prevmod != tp->module_list[i]) { + module_name(tp->module_list[i], str); + fprintf(f, ", %s", str); + } + prevmod = tp->module_list[i]; + } + fprintf(f, "\n"); + if (tp->tc_index != -1) { + fprintf(f, " -- TEXTUAL CONVENTION %s\n", get_tc_descriptor(tp->tc_index)); + } + switch (tp->type) { + case TYPE_OBJID: cp = "OBJECT IDENTIFIER"; break; + case TYPE_OCTETSTR: cp = "OCTET STRING"; break; + case TYPE_INTEGER: cp = "INTEGER"; break; + case TYPE_NETADDR: cp = "NetworkAddress"; break; + case TYPE_IPADDR: cp = "IpAddress"; break; + case TYPE_COUNTER: cp = "Counter"; break; + case TYPE_GAUGE: cp = "Gauge"; break; + case TYPE_TIMETICKS: cp = "TimeTicks"; break; + case TYPE_OPAQUE: cp = "Opaque"; break; + case TYPE_NULL: cp = "NULL"; break; + case TYPE_COUNTER64: cp = "Counter64"; break; + case TYPE_BITSTRING: cp = "BIT STRING"; break; + case TYPE_NSAPADDRESS: cp = "NsapAddress"; break; + case TYPE_UINTEGER: cp = "UInteger32"; break; + case 0: cp = NULL; break; + default: sprintf(str,"type_%d", tp->type); cp = str; + } +#if SNMP_TESTING_CODE + if (!cp && (tp->ranges || tp->enums)) { /* ranges without type ? */ + sprintf(str,"?0 with %s %s ?", + tp->ranges ? "Range" : "", + tp->enums ? "Enum" : ""); + cp = str; + } +#endif /* SNMP_TESTING_CODE */ + if (cp) fprintf(f, " SYNTAX\t%s", cp); + if (tp->ranges) { + struct range_list *rp = tp->ranges; + int first = 1; + fprintf(f, " ("); + while (rp) { + if (first) first = 0; + else fprintf(f, " | "); + if (rp->low == rp->high) fprintf(f, "%d", rp->low); + else fprintf(f, "%d..%d", rp->low, rp->high); + rp = rp->next; + } + fprintf(f, ") "); + } + if (tp->enums) { + struct enum_list *ep = tp->enums; + int first = 1; + fprintf(f," { "); + while (ep) { + if (first) first = 0; + else fprintf(f, ", "); + fprintf(f, "%s(%d)", ep->label, ep->value); + ep = ep->next; + } + fprintf(f," } "); + } + if (cp) fprintf(f, "\n"); + if (tp->hint) fprintf(f, " DISPLAY-HINT\t\"%s\"\n", tp->hint); + if (tp->units) fprintf(f, " UNITS\t\"%s\"\n", tp->units); + switch (tp->access) { + case MIB_ACCESS_READONLY: cp = "read-only"; break; + case MIB_ACCESS_READWRITE: cp = "read-write"; break; + case MIB_ACCESS_WRITEONLY: cp = "write-only"; break; + case MIB_ACCESS_NOACCESS: cp = "not-accessible"; break; + case MIB_ACCESS_NOTIFY: cp = "accessible-for-notify"; break; + case MIB_ACCESS_CREATE: cp = "read-create"; break; + case 0: cp = NULL; break; + default: sprintf(str,"access_%d", tp->access); cp = str; + } + if (cp) fprintf(f, " MAX-ACCESS\t%s\n", cp); + switch (tp->status) { + case MIB_STATUS_MANDATORY: cp = "mandatory"; break; + case MIB_STATUS_OPTIONAL: cp = "optional"; break; + case MIB_STATUS_OBSOLETE: cp = "obsolete"; break; + case MIB_STATUS_DEPRECATED: cp = "deprecated"; break; + case MIB_STATUS_CURRENT: cp = "current"; break; + case 0: cp = NULL; break; + default: sprintf(str,"status_%d", tp->status); cp = str; + } +#if SNMP_TESTING_CODE + if (!cp && (tp->indexes)) { /* index without status ? */ + sprintf(str,"?0 with %s ?", + tp->indexes ? "Index" : ""); + cp = str; + } +#endif /* SNMP_TESTING_CODE */ + if (cp) fprintf(f, " STATUS\t%s\n", cp); + if (tp->indexes) { + struct index_list *ip = tp->indexes; + int first=1; + fprintf(f, " INDEXES\t"); + fprintf(f," { "); + while (ip) { + if (first) first = 0; + else fprintf(f, ", "); + if (ip->isimplied) + fprintf(f, "IMPLIED "); + fprintf(f, "%s", ip->ilabel); + ip = ip->next; + } + fprintf(f," }\n"); + } + if (tp->description) fprintf(f, " DESCRIPTION\t\"%s\"\n", tp->description); + } + else + fprintf(f, "No description\n"); +} + +int +get_module_node(const char *fname, + const char *module, + oid *objid, + size_t *objidlen) +{ + int modid, rc = 0; + struct tree *tp; + char *name, *cp; + + if ( !strcmp(module, "ANY") ) + modid = -1; + else { + read_module(module); + modid = which_module( module ); + if (modid == -1) return 0; + } + + /* Isolate the first component of the name ... */ + name = strdup(fname); + cp = strchr( name, '.' ); + if ( cp != NULL ) { + *cp = '\0'; + cp++; + } + /* ... and locate it in the tree. */ + tp = find_tree_node(name, modid); + if (tp){ + size_t maxlen = *objidlen; + + /* Set the first element of the object ID */ + if (node_to_oid(tp, objid, objidlen)) { + rc = 1; + + /* If the name requested was more than one element, + tag on the rest of the components */ + if (cp != NULL) + rc = _add_strings_to_oid(tp, cp, objid, objidlen, maxlen); + } + } + + free(name); + return (rc); +} + + +/* + * Populate object identifier from a node in the MIB hierarchy. + * Build up the object ID, working backwards, + * starting from the end of the objid buffer. + * When the top of the MIB tree is reached, adjust the buffer. + * + * The buffer length is set to the number of subidentifiers + * for the object identifier associated with the MIB node. + * Returns the number of subidentifiers copied. + * + * If 0 is returned, the objid buffer is too small, + * and the buffer contents are indeterminate. + * The buffer length can be used to create a larger buffer. + */ +int +node_to_oid(struct tree *tp, oid *objid, size_t *objidlen) +{ + int numids, lenids; + oid *op; + + if (!tp || !objid || !objidlen) + return 0; + + lenids = (int)*objidlen; + op = objid + lenids; /* points after the last element */ + + for(numids = 0; tp; tp = tp->parent, numids++) + { + if (numids >= lenids) continue; + --op; + *op = tp->subid; + } + + *objidlen = (size_t)numids; + if (numids > lenids) { + return 0; + } + + if (numids < lenids) + memmove(objid, op, numids * sizeof(oid)); + + return (numids); +} + +static int +_add_strings_to_oid(struct tree *tp, char *cp, + oid *objid, size_t *objidlen, + size_t maxlen) +{ + int subid; + struct tree *tp2 = NULL; + char *cp2 = NULL; + char doingquote = 0; + + while ( cp != NULL ) { + cp2 = strchr( cp, '.' ); /* Isolate the next entry */ + if ( cp2 != NULL ) { + *cp2 = '\0'; + cp2++; + } + + if ( *cp == '"' || *cp == '\'') { /* Is it the beggining + of a quoted string */ + doingquote = *cp++; + /* insert length if requested */ + if (doingquote == '"') { + if (*objidlen >= maxlen) + return 0; + objid[ *objidlen ] = (strchr(cp,doingquote) - cp); + (*objidlen)++; + } + + while(*cp != doingquote) { + if (*objidlen >= maxlen) + return 0; + objid[ *objidlen ] = *cp++; + (*objidlen)++; + } + + tp = NULL; /* must be pure numeric from here, right? */ + cp = cp2; + continue; + } + + /* Is it numeric ? */ + if ( isdigit( *cp ) ) + subid=(strtol(cp,0,0)); + else + subid = -1; + + /* Search for the appropriate child */ + if ( tp != NULL ) + tp2 = tp->child_list; + while ( tp2 != NULL ) { + if (( (int)tp2->subid == subid ) || + ( !strcasecmp( tp2->label, cp ))) { + if (*objidlen >= maxlen) + return 0; + objid[ *objidlen ] = tp2->subid; + (*objidlen)++; + tp = tp2; + break; + } + tp2 = tp2->next_peer; + } + if ( tp2 == NULL ) { + if ( subid == -1 ) { + return 0; + } + /* pure numeric from now on */ + if (*objidlen >= maxlen) + return 0; + objid[ *objidlen ] = subid; + (*objidlen)++; + tp = NULL; + } + cp = cp2; + } + + return 1; +} + + +/* + * see comments on find_best_tree_node for usage after first time. + */ +int +get_wild_node(const char *name, + oid *objid, + size_t *objidlen) +{ + struct tree *tp = find_best_tree_node(name, tree_head, NULL); + if (!tp) + return 0; + return get_node(tp->label, objid, objidlen); +} + +int +get_node(const char *name, + oid *objid, + size_t *objidlen) +{ + char *cp; + int res; + + if (( cp=strchr(name, ':')) == NULL ) + res = get_module_node( name, "ANY", objid, objidlen ); + else { + char *module; + /* + * requested name is of the form + * "module:subidentifier" + */ + module = (char *)malloc((size_t)(cp-name+1)); + memcpy(module,name,(size_t)(cp-name)); + module[cp-name] = 0; + cp++; /* cp now point to the subidentifier */ + if (*cp == ':') cp++; + + /* 'cp' and 'name' *do* go that way round! */ + res = get_module_node( cp, module, objid, objidlen ); + free(module); + } + if (res == 0) { + SET_SNMP_ERROR(SNMPERR_UNKNOWN_OBJID); + } + + return res; +} + +#ifdef testing + +main(int argc, char* argv[]) +{ + oid objid[MAX_OID_LEN]; + int objidlen = MAX_OID_LEN; + int count; + struct variable_list variable; + + init_mib(); + if (argc < 2) + print_subtree(stdout, tree_head, 0); + variable.type = ASN_INTEGER; + variable.val.integer = 3; + variable.val_len = 4; + for (argc--; argc; argc--, argv++) { + objidlen = MAX_OID_LEN; + printf("read_objid(%s) = %d\n", + argv[1], read_objid(argv[1], objid, &objidlen)); + for(count = 0; count < objidlen; count++) + printf("%d.", objid[count]); + printf("\n"); + print_variable(objid, objidlen, &variable); + } +} + +#endif /* testing */ + +/* initialize: no peers included in the report. */ +void clear_tree_flags(register struct tree *tp) +{ + for (; tp; tp = tp->next_peer) + { + tp->reported = 0; + if (tp->child_list) + clear_tree_flags(tp->child_list); /*RECURSE*/ + } +} + +/* + * Update: 1998-07-17 + * Added print_oid_report* functions. + */ +static int print_subtree_oid_report_labeledoid = 0; +static int print_subtree_oid_report_oid = 0; +static int print_subtree_oid_report_symbolic = 0; +static int print_subtree_oid_report_suffix = 0; + +/* These methods recurse. */ +static void print_parent_labeledoid(FILE *, struct tree *); +static void print_parent_oid(FILE *, struct tree *); +static void print_parent_label(FILE *, struct tree *); +static void print_subtree_oid_report(FILE *, struct tree *, int); + + +void +print_oid_report (FILE *fp) +{ + struct tree *tp; + clear_tree_flags(tree_head); + for (tp = tree_head ; tp ; tp=tp->next_peer) + print_subtree_oid_report (fp, tp, 0); +} + +void +print_oid_report_enable_labeledoid (void) +{ + print_subtree_oid_report_labeledoid = 1; +} + +void +print_oid_report_enable_oid (void) +{ + print_subtree_oid_report_oid = 1; +} + +void +print_oid_report_enable_suffix (void) +{ + print_subtree_oid_report_suffix = 1; +} + +void +print_oid_report_enable_symbolic (void) +{ + print_subtree_oid_report_symbolic = 1; +} + +/* + * helper methods for print_subtree_oid_report() + * each one traverses back up the node tree + * until there is no parent. Then, the label combination + * is output, such that the parent is displayed first. + * + * Warning: these methods are all recursive. + */ + +static void +print_parent_labeledoid(FILE *f, + struct tree *tp) +{ + if(tp) + { + if(tp->parent) + { + print_parent_labeledoid(f, tp->parent); /*RECURSE*/ + } + fprintf(f, ".%s(%lu)", tp->label, tp->subid); + } +} + +static void +print_parent_oid(FILE *f, + struct tree *tp) +{ + if(tp) + { + if(tp->parent) + { + print_parent_oid(f, tp->parent); /*RECURSE*/ + } + fprintf(f, ".%lu", tp->subid); + } +} + +static void +print_parent_label(FILE *f, + struct tree *tp) +{ + if(tp) + { + if(tp->parent) + { + print_parent_label(f, tp->parent); /*RECURSE*/ + } + fprintf(f, ".%s", tp->label); + } +} + +/* + * print_subtree_oid_report(): + * + * This methods generates variations on the original print_subtree() report. + * Traverse the tree depth first, from least to greatest sub-identifier. + * Warning: this methods recurses and calls methods that recurse. + */ + +static void +print_subtree_oid_report(FILE *f, + struct tree *tree, + int count) +{ + struct tree *tp; + + count++; + + /* sanity check */ + if(!tree) + { + return; + } + + /* + * find the not reported peer with the lowest sub-identifier. + * if no more, break the loop and cleanup. + * set "reported" flag, and create report for this peer. + * recurse using the children of this peer, if any. + */ + while (1) + { + register struct tree *ntp; + + tp = 0; + for (ntp = tree->child_list; ntp; ntp = ntp->next_peer) + { + if (ntp->reported) continue; + + if (!tp || (tp->subid > ntp->subid)) + tp = ntp; + } + if (!tp) break; + + tp->reported = 1; + + if(print_subtree_oid_report_labeledoid) + { + print_parent_labeledoid(f, tp); + fprintf(f, "\n"); + } + if(print_subtree_oid_report_oid) + { + print_parent_oid(f, tp); + fprintf(f, "\n"); + } + if(print_subtree_oid_report_symbolic) + { + print_parent_label(f, tp); + fprintf(f, "\n"); + } + if(print_subtree_oid_report_suffix) + { + int i; + for(i = 0; i < count; i++) + fprintf(f, " "); + fprintf(f, "%s(%ld) type=%d", tp->label, tp->subid, tp->type); + if (tp->tc_index != -1) fprintf(f, " tc=%d", tp->tc_index); + if (tp->hint) fprintf(f, " hint=%s", tp->hint); + if (tp->units) fprintf(f, " units=%s", tp->units); + + fprintf(f, "\n"); + } + print_subtree_oid_report(f, tp, count); /*RECURSE*/ + } +} + + +/* + * Convert timeticks to hours, minutes, seconds string. + * CMU compatible does not show centiseconds. + */ +char *uptime_string(u_long timeticks, char *buf) +{ + char tbuf[64]; + char * cp; + uptimeString(timeticks, tbuf); + cp = strrchr(tbuf, '.'); +#ifdef CMU_COMPATIBLE + if (cp) *cp = '\0'; +#endif + strcpy(buf, tbuf); + return buf; +} + +#ifdef CMU_COMPATIBLE + +int mib_TxtToOid(char *Buf, oid **OidP, size_t *LenP) +{ + return read_objid(Buf, *OidP, LenP); +} + +int mib_OidToTxt(oid *O, size_t OidLen, char *Buf, size_t BufLen) +{ + _sprint_objid(Buf, O, OidLen); + return 1; +} + +#endif /* CMU_COMPATIBLE */ diff --git a/packages/net/snmp/lib/current/src/mt_support.c b/packages/net/snmp/lib/current/src/mt_support.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/mt_support.c @@ -0,0 +1,213 @@ +//========================================================================== +// +// ./lib/current/src/mt_support.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ + +/* mt_support.c - multi-thread resource locking support */ +/* + * Author: Markku Laukkanen + * Created: 6-Sep-1999 + * History: + * 8-Sep-1999 M. Slifcak method names changed; + * use array of resource locking structures. + */ + +#include +#include +#include "mt_support.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _REENTRANT + +static +mutex_type s_res[MT_MAX_IDS][MT_LIB_MAXIMUM]; /* locking structures */ + +static mutex_type * _mt_res(int groupID, int resourceID) +{ + if (groupID < 1) return 0; + if (groupID >= MT_MAX_IDS) return 0; + if (resourceID < 1) return 0; + if (resourceID >= MT_LIB_MAXIMUM) return 0; + return (&s_res[groupID][resourceID]); +} + +static +int snmp_res_init_mutex(mutex_type * mutex) +{ + int rc = 0; +#if HAVE_PTHREAD_H + rc = pthread_mutex_init(mutex, MT_MUTEX_INIT_DEFAULT); +#elif defined(WIN32) + InitializeCriticalSection(mutex); +#endif + + return rc; +} + +int snmp_res_init(void) +{ + int ii, jj; + int rc = 0; + mutex_type *mutex; + + for (jj = 0; (0 == rc) && (jj < MT_MAX_IDS); jj++) + for (ii = 0; (0 == rc) && (ii < MT_LIB_MAXIMUM); ii++) + { + mutex = _mt_res(jj, ii); + if (!mutex) continue; + rc = snmp_res_init_mutex( mutex ); + } + + return rc; +} + +int snmp_res_destroy_mutex(int groupID, int resourceID) +{ + int rc = 0; + mutex_type *mutex = _mt_res(groupID, resourceID); + if (!mutex) return EFAULT; + +#if HAVE_PTHREAD_H + rc = pthread_mutex_destroy(mutex); +#elif defined(WIN32) + DeleteCriticalSection(mutex); +#endif + + return rc; +} + +int snmp_res_lock(int groupID, int resourceID) +{ + int rc = 0; + mutex_type *mutex = _mt_res(groupID, resourceID); + if (!mutex) return EFAULT; + +#if HAVE_PTHREAD_H + rc = pthread_mutex_lock(mutex); +#elif defined(WIN32) + EnterCriticalSection(mutex); +#endif + + return rc; +} + +int snmp_res_unlock(int groupID, int resourceID) +{ + int rc = 0; + mutex_type *mutex = _mt_res(groupID, resourceID); + if (!mutex) return EFAULT; + +#if HAVE_PTHREAD_H + rc = pthread_mutex_unlock(mutex); +#elif defined(WIN32) + LeaveCriticalSection(mutex); +#endif + + return rc; +} + + +#else /* !_REENTRANT */ + +#ifdef WIN32 + +/* Provide "do nothing" targets for Release (.DLL) builds. */ +#undef snmp_res_init +#undef snmp_res_lock +#undef snmp_res_unlock +#undef snmp_res_destroy_mutex + +int snmp_res_init(void) { return 0; } +int snmp_res_lock(int groupID, int resourceID) { return 0; } +int snmp_res_unlock(int groupID, int resourceID) { return 0; } +int snmp_res_destroy_mutex(int groupID, int resourceID) { return 0; } +#endif /* !WIN32 */ + +#endif /* !_REENTRANT */ + + +#ifdef __cplusplus +}; +#endif + diff --git a/packages/net/snmp/lib/current/src/parse.c b/packages/net/snmp/lib/current/src/parse.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/parse.c @@ -0,0 +1,3854 @@ +//========================================================================== +// +// ./lib/current/src/parse.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * parse.c + * + * Update: 1998-09-22 + * Clear nbuckets in init_node_hash. + * New method xcalloc returns zeroed data structures. + * New method alloc_node encapsulates common node creation. + * New method to configure terminate comment at end of line. + * New method to configure accept underscore in labels. + * + * Update: 1998-10-10 + * fully qualified OID parsing patch + * + * Update: 1998-10-20 + * merge_anon_children patch + * + * Update: 1998-10-21 + * Merge_parse_objectid associates information with last node in chain. + */ +/****************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +#include +#include +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#include +#include +#ifndef __ECOS +#include +#endif + +/* Wow. This is ugly. -- Wes */ +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) +#include +#endif +#if HAVE_DMALLOC_H +#include +#endif + +#include "system.h" +#include "parse.h" +#include "asn1.h" +#include "mib.h" +#include "snmp_api.h" +#include "snmp_debug.h" +#include "snmp_logging.h" +#include "default_store.h" +#include "tools.h" + +/* + * This is one element of an object identifier with either an integer + * subidentifier, or a textual string label, or both. + * The subid is -1 if not present, and label is NULL if not present. + */ +struct subid_s { + int subid; + int modid; + char *label; +}; + +#define MAXTC 1024 +struct tc { /* textual conventions */ + int type; + int modid; + char *descriptor; + char *hint; + struct enum_list *enums; + struct range_list *ranges; +} tclist[MAXTC]; + +int Line = 0; +const char *File = "(none)"; +static int anonymous = 0; + +#define SYNTAX_MASK 0x80 +/* types of tokens + Tokens wiht the SYNTAX_MASK bit set are syntax tokens */ +#define CONTINUE -1 +#define ENDOFFILE 0 +#define LABEL 1 +#define SUBTREE 2 +#define SYNTAX 3 +#define OBJID (4 | SYNTAX_MASK) +#define OCTETSTR (5 | SYNTAX_MASK) +#define INTEGER (6 | SYNTAX_MASK) +#define INTEGER32 INTEGER +#define NETADDR (7 | SYNTAX_MASK) +#define IPADDR (8 | SYNTAX_MASK) +#define COUNTER (9 | SYNTAX_MASK) +#define GAUGE (10 | SYNTAX_MASK) +#define TIMETICKS (11 | SYNTAX_MASK) +#define KW_OPAQUE (12 | SYNTAX_MASK) +#define NUL (13 | SYNTAX_MASK) +#define SEQUENCE 14 +#define OF 15 /* SEQUENCE OF */ +#define OBJTYPE 16 +#define ACCESS 17 +#define READONLY 18 +#define READWRITE 19 +#define WRITEONLY 20 +#define NOACCESS 21 +#define STATUS 22 +#define MANDATORY 23 +#define KW_OPTIONAL 24 +#define OBSOLETE 25 +/* #define RECOMMENDED 26 */ +#define PUNCT 27 +#define EQUALS 28 +#define NUMBER 29 +#define LEFTBRACKET 30 +#define RIGHTBRACKET 31 +#define LEFTPAREN 32 +#define RIGHTPAREN 33 +#define COMMA 34 +#define DESCRIPTION 35 +#define QUOTESTRING 36 +#define INDEX 37 +#define DEFVAL 38 +#define DEPRECATED 39 +#define SIZE 40 +#define BITSTRING (41 | SYNTAX_MASK) +#define NSAPADDRESS (42 | SYNTAX_MASK) +#define COUNTER64 (43 | SYNTAX_MASK) +#define OBJGROUP 44 +#define NOTIFTYPE 45 +#define AUGMENTS 46 +#define COMPLIANCE 47 +#define READCREATE 48 +#define UNITS 49 +#define REFERENCE 50 +#define NUM_ENTRIES 51 +#define MODULEIDENTITY 52 +#define LASTUPDATED 53 +#define ORGANIZATION 54 +#define CONTACTINFO 55 +#define UINTEGER32 (56 | SYNTAX_MASK) +#define CURRENT 57 +#define DEFINITIONS 58 +#define END 59 +#define SEMI 60 +#define TRAPTYPE 61 +#define ENTERPRISE 62 +/* #define DISPLAYSTR (63 | SYNTAX_MASK) */ +#define BEGIN 64 +#define IMPORTS 65 +#define EXPORTS 66 +#define ACCNOTIFY 67 +#define BAR 68 +#define RANGE 69 +#define CONVENTION 70 +#define DISPLAYHINT 71 +#define FROM 72 +#define CAPABILITIES 73 +#define MACRO 74 +#define IMPLIED 75 + +struct tok { + const char *name; /* token name */ + int len; /* length not counting nul */ + int token; /* value */ + int hash; /* hash of name */ + struct tok *next; /* pointer to next in hash table */ +}; + + +static struct tok tokens[] = { + { "obsolete", sizeof ("obsolete")-1, OBSOLETE }, + { "Opaque", sizeof ("Opaque")-1, KW_OPAQUE }, + { "optional", sizeof ("optional")-1, KW_OPTIONAL }, + { "LAST-UPDATED", sizeof ("LAST-UPDATED")-1, LASTUPDATED }, + { "ORGANIZATION", sizeof ("ORGANIZATION")-1, ORGANIZATION }, + { "CONTACT-INFO", sizeof ("CONTACT-INFO")-1, CONTACTINFO }, + { "MODULE-IDENTITY", sizeof ("MODULE-IDENTITY")-1, MODULEIDENTITY }, + { "MODULE-COMPLIANCE", sizeof ("MODULE-COMPLIANCE")-1, COMPLIANCE }, + { "DEFINITIONS", sizeof("DEFINITIONS")-1, DEFINITIONS}, + { "END", sizeof("END")-1, END}, + { "AUGMENTS", sizeof ("AUGMENTS")-1, AUGMENTS }, + { "not-accessible", sizeof ("not-accessible")-1, NOACCESS }, + { "write-only", sizeof ("write-only")-1, WRITEONLY }, + { "NsapAddress", sizeof("NsapAddress")-1, NSAPADDRESS}, + { "UNITS", sizeof("Units")-1, UNITS}, + { "REFERENCE", sizeof("REFERENCE")-1, REFERENCE}, + { "NUM-ENTRIES", sizeof("NUM-ENTRIES")-1, NUM_ENTRIES}, + { "BITSTRING", sizeof("BITSTRING")-1, BITSTRING}, + { "BIT", sizeof("BIT")-1, CONTINUE}, + { "BITS", sizeof("BITS")-1, BITSTRING}, + { "Counter64", sizeof("Counter64")-1, COUNTER64}, + { "TimeTicks", sizeof ("TimeTicks")-1, TIMETICKS }, + { "NOTIFICATION-TYPE", sizeof ("NOTIFICATION-TYPE")-1, NOTIFTYPE }, + { "OBJECT-GROUP", sizeof ("OBJECT-GROUP")-1, OBJGROUP }, + { "OBJECT-IDENTITY", sizeof ("OBJECT-IDENTITY")-1, OBJGROUP }, + { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, OBJID }, + { "OBJECT", sizeof ("OBJECT")-1, CONTINUE }, + { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR }, + { "Gauge", sizeof ("Gauge")-1, GAUGE }, + { "Gauge32", sizeof ("Gauge32")-1, GAUGE }, + { "Unsigned32", sizeof ("Unsigned32")-1, GAUGE }, + { "read-write", sizeof ("read-write")-1, READWRITE }, + { "read-create", sizeof ("read-create")-1, READCREATE }, + { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR }, + { "OCTET", sizeof ("OCTET")-1, CONTINUE }, + { "OF", sizeof ("OF")-1, OF }, + { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE }, + { "NULL", sizeof ("NULL")-1, NUL }, + { "IpAddress", sizeof ("IpAddress")-1, IPADDR }, + { "UInteger32", sizeof ("UInteger32")-1, UINTEGER32 }, + { "INTEGER", sizeof ("INTEGER")-1, INTEGER }, + { "Integer32", sizeof ("Integer32")-1, INTEGER32 }, + { "Counter", sizeof ("Counter")-1, COUNTER }, + { "Counter32", sizeof ("Counter32")-1, COUNTER }, + { "read-only", sizeof ("read-only")-1, READONLY }, + { "DESCRIPTION", sizeof ("DESCRIPTION")-1, DESCRIPTION }, + { "INDEX", sizeof ("INDEX")-1, INDEX }, + { "DEFVAL", sizeof ("DEFVAL")-1, DEFVAL }, + { "deprecated", sizeof ("deprecated")-1, DEPRECATED }, + { "SIZE", sizeof ("SIZE")-1, SIZE }, + { "MAX-ACCESS", sizeof ("MAX-ACCESS")-1, ACCESS }, + { "ACCESS", sizeof ("ACCESS")-1, ACCESS }, + { "mandatory", sizeof ("mandatory")-1, MANDATORY }, + { "current", sizeof ("current")-1, CURRENT }, + { "STATUS", sizeof ("STATUS")-1, STATUS }, + { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX }, + { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE }, + { "TRAP-TYPE", sizeof ("TRAP-TYPE")-1, TRAPTYPE }, + { "ENTERPRISE", sizeof ("ENTERPRISE")-1, ENTERPRISE }, + { "BEGIN", sizeof ("BEGIN")-1, BEGIN }, + { "IMPORTS", sizeof ("IMPORTS")-1, IMPORTS }, + { "EXPORTS", sizeof ("EXPORTS")-1, EXPORTS }, + { "accessible-for-notify", sizeof ("accessible-for-notify")-1, ACCNOTIFY }, + { "TEXTUAL-CONVENTION", sizeof ("TEXTUAL-CONVENTION")-1, CONVENTION }, + { "NOTIFICATION-GROUP", sizeof ("NOTIFICATION-GROUP")-1, NOTIFTYPE }, + { "DISPLAY-HINT", sizeof ("DISPLAY-HINT")-1, DISPLAYHINT }, + { "FROM", sizeof ("FROM")-1, FROM }, + { "AGENT-CAPABILITIES", sizeof ("AGENT-CAPABILITIES")-1, CAPABILITIES }, + { "MACRO", sizeof ("MACRO")-1, MACRO }, + { "IMPLIED", sizeof ("IMPLIED")-1, IMPLIED }, + { NULL } +}; + +static struct module_compatability *module_map_head; +static struct module_compatability module_map[] = { + { "RFC1065-SMI", "RFC1155-SMI", NULL, 0}, + { "RFC1066-MIB", "RFC1156-MIB", NULL, 0}, + /* 'mib' -> 'mib-2' */ + { "RFC1156-MIB", "RFC1158-MIB", NULL, 0}, + /* 'snmpEnableAuthTraps' -> 'snmpEnableAuthenTraps' */ + { "RFC1158-MIB", "RFC1213-MIB", NULL, 0}, + /* 'nullOID' -> 'zeroDotZero' */ + { "RFC1155-SMI", "SNMPv2-SMI", NULL, 0}, + { "RFC1213-MIB", "SNMPv2-SMI", "mib-2", 0}, + { "RFC1213-MIB", "SNMPv2-MIB", "sys", 3}, + { "RFC1213-MIB", "IF-MIB", "if", 2}, + { "RFC1213-MIB", "IP-MIB", "ip", 2}, + { "RFC1213-MIB", "IP-MIB", "icmp", 4}, + { "RFC1213-MIB", "TCP-MIB", "tcp", 3}, + { "RFC1213-MIB", "UDP-MIB", "udp", 3}, + { "RFC1213-MIB", "SNMPv2-SMI", "transmission", 0}, + { "RFC1213-MIB", "SNMPv2-MIB", "snmp", 4}, + { "RFC1271-MIB", "RMON-MIB", NULL, 0}, + { "RFC1286-MIB", "SOURCE-ROUTING-MIB", "dot1dSr", 7}, + { "RFC1286-MIB", "BRIDGE-MIB", NULL, 0}, + { "RFC1315-MIB", "FRAME-RELAY-DTE-MIB", NULL, 0}, + { "RFC1316-MIB", "CHARACTER-MIB", NULL, 0}, +}; +#define MODULE_NOT_FOUND 0 +#define MODULE_LOADED_OK 1 +#define MODULE_ALREADY_LOADED 2 +/* #define MODULE_LOAD_FAILED 3 */ +#define MODULE_LOAD_FAILED MODULE_NOT_FOUND + + +#define HASHSIZE 32 +#define BUCKET(x) (x & (HASHSIZE-1)) + +#define NHASHSIZE 128 +#define NBUCKET(x) (x & (NHASHSIZE-1)) + +static struct tok *buckets[HASHSIZE]; + +static struct node *nbuckets[NHASHSIZE]; +static struct tree *tbuckets[NHASHSIZE]; +static struct module *module_head = NULL; + +struct node *orphan_nodes = NULL; +struct tree *tree_head = NULL; + +#define NUMBER_OF_ROOT_NODES 3 +static struct module_import root_imports[NUMBER_OF_ROOT_NODES]; + +static int current_module = 0; +static int max_module = 0; +static char *last_err_module = 0; /* no repeats on "Cannot find module..." */ + +static void tree_from_node(struct tree *tp, struct node *np); +static void do_subtree (struct tree *, struct node **); +static void do_linkup (struct module *, struct node *); +static void dump_module_list (void); +static int get_token (FILE *, char *, int); +static int parseQuoteString (FILE *, char *, int); +static int tossObjectIdentifier (FILE *); +static int name_hash (const char *); +static void init_node_hash (struct node *); +static void print_error (const char *, const char *, int); +static void free_tree (struct tree *); +static void free_partial_tree (struct tree *, int); +static void free_node (struct node *); +static void build_translation_table (void); +static void init_tree_roots (void); +static void merge_anon_children (struct tree *, struct tree *); +static void unlink_tbucket(struct tree *); +static void unlink_tree(struct tree *); +static int getoid (FILE *, struct subid_s *, int); +static struct node *parse_objectid (FILE *, char *); +static int get_tc (const char *, int, int *, struct enum_list **, struct range_list **, char **); +static int get_tc_index (const char *, int); +static struct enum_list *parse_enumlist (FILE *, struct enum_list **); +static struct range_list *parse_ranges(FILE *fp, struct range_list **); +static struct node *parse_asntype (FILE *, char *, int *, char *); +static struct node *parse_objecttype (FILE *, char *); +static struct node *parse_objectgroup (FILE *, char *); +static struct node *parse_notificationDefinition (FILE *, char *); +static struct node *parse_trapDefinition (FILE *, char *); +static struct node *parse_compliance (FILE *, char *); +static struct node *parse_capabilities(FILE *, char *); +static struct node *parse_moduleIdentity (FILE *, char *); +static struct node *parse_macro(FILE *, char *); +static void parse_imports (FILE *); +static struct node *parse (FILE *, struct node *); + +static int read_module_internal (const char *); +static void read_module_replacements (const char *); +static void read_import_replacements (const char *, struct module_import *); + +static void new_module (const char *, const char *); + +static struct node *merge_parse_objectid (struct node *, FILE *, char *); +static struct index_list *getIndexes(FILE *fp, struct index_list **); +static void free_indexes(struct index_list **); +static void free_ranges(struct range_list **); +static void free_enums(struct enum_list **); +static struct range_list * copy_ranges(struct range_list *); +static struct enum_list * copy_enums(struct enum_list *); +static struct index_list * copy_indexes(struct index_list *); + +/* backwards compatibility wrappers */ +void snmp_set_mib_errors(int err) +{ + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_ERRORS, err); +} + +void snmp_set_mib_warnings(int warn) +{ + ds_set_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS, warn); +} + +void snmp_set_save_descriptions(int save) +{ + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS, save); +} + +void snmp_set_mib_comment_term(int save) +{ + /* 0=strict, 1=EOL terminated */ + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, save); +} + +void snmp_set_mib_parse_label(int save) +{ + /* 0=strict, 1=underscore OK in label */ + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL, save); +} + +/* end wrappers */ + +void snmp_mib_toggle_options_usage(const char *lead, FILE *outf) { + fprintf(outf, "%sMIBOPTS values:\n", lead); + fprintf(outf, "%s u: %sallow the usage of underlines in mib symbols.\n", + lead, ((ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL))?"dis":"")); + fprintf(outf, "%s c: %sallow the usage of \"--\" to terminate comments.\n", + lead, ((ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM))?"":"dis")); + fprintf(outf, "%s d: %ssave the descriptions of the mib objects.\n", + lead, ((ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS))?"don't ":"")); + fprintf(outf, "%s e: Disable mib errors of MIB symbols conflicts\n", + lead); + fprintf(outf, "%s w: Enable mib warnings of MIB symbols conflicts\n", + lead); + fprintf(outf, "%s W: Enable detailed warnings of MIB symbols conflicts\n", + lead); + fprintf(outf, "%s R: Replace MIB symbols from latest module\n", + lead); +} + +char *snmp_mib_toggle_options(char *options) { + if (options) { + while(*options) { + switch(*options) { + case 'u': + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL, !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL)); + break; + + case 'c': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM); + break; + + case 'e': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_MIB_ERRORS); + break; + + case 'w': + ds_set_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS, 1); + break; + + case 'W': + ds_set_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS, 2); + break; + + case 'd': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS); + break; + + case 'R': + ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_MIB_REPLACE); + break; + + default: + /* return at the unknown option */ + return options; + } + options++; + } + } + return NULL; +} + +static int +name_hash(const char* name) +{ + int hash = 0; + const char *cp; + + if (name) { + for(cp = name; *cp; cp++) { + hash += tolower(*cp); + } + } + return(hash); +} + +void +init_mib_internals (void) +{ + register struct tok *tp; + register int b, i; + int max_modc; + + if (tree_head) + return; + + /* + * Set up hash list of pre-defined tokens + */ + memset(buckets, 0, sizeof(buckets)); + for (tp = tokens; tp->name; tp++) { + tp->hash = name_hash( tp->name ); + b = BUCKET(tp->hash); + if (buckets[b]) + tp->next = buckets[b]; /* BUG ??? */ + buckets[b] = tp; + } + + /* + * Initialise other internal structures + */ + + max_modc = sizeof(module_map)/sizeof(module_map[0])-1; + for ( i = 0; i < max_modc; ++i ) + module_map[i].next = &(module_map[i+1]); + module_map[max_modc].next = NULL; + module_map_head = module_map; + + memset(nbuckets, 0, sizeof(nbuckets)); + memset(tbuckets, 0, sizeof(tbuckets)); + memset(tclist, 0, MAXTC * sizeof(struct tc)); + build_translation_table(); + init_tree_roots(); /* Set up initial roots */ + /* Relies on 'add_mibdir' having set up the modules */ +} + +static void +init_node_hash(struct node *nodes) +{ + register struct node *np, *nextp; + register int hash; + + memset(nbuckets, 0, sizeof(nbuckets)); + for(np = nodes; np;){ + nextp = np->next; + hash = NBUCKET(name_hash(np->parent)); + np->next = nbuckets[hash]; + nbuckets[hash] = np; + np = nextp; + } +} + +static int erroneousMibs = 0; + +int get_mib_parse_error_count(void) +{ + return erroneousMibs; +} + + +static void +print_error(const char *string, + const char *token, + int type) +{ + erroneousMibs++; + DEBUGMSGTL(("parse-mibs", "\n")); + if (type == ENDOFFILE) + snmp_log(LOG_ERR, "%s (EOF): At line %d in %s\n", string, Line, + File); + else if (token && *token) + snmp_log(LOG_ERR, "%s (%s): At line %d in %s\n", string, token, + Line, File); + else + snmp_log(LOG_ERR, "%s: At line %d in %s\n", string, Line, File); +} + +static void +print_module_not_found(const char *cp) +{ + if (!last_err_module || strcmp(cp, last_err_module)) + print_error("Cannot find module", cp, CONTINUE); + if (last_err_module) free(last_err_module); + last_err_module = strdup(cp); +} + +static struct node * +alloc_node(int modid) +{ + struct node *np; + np = (struct node *) calloc(1, sizeof(struct node)); + if (np) { + np->tc_index = -1; + np->modid = modid; + } + return np; +} + +static void unlink_tbucket(struct tree *tp) +{ + int hash = NBUCKET(name_hash(tp->label)); + struct tree *otp = NULL, *ntp = tbuckets[hash]; + + while (ntp && ntp != tp) { + otp = ntp; ntp = ntp->next; + } + if (!ntp) snmp_log(LOG_EMERG, "Can't find %s in tbuckets\n", tp->label); + else if (otp) otp->next = ntp->next; + else tbuckets[hash] = tp->next; +} + +static void unlink_tree(struct tree *tp) +{ + struct tree *otp = NULL, *ntp = tp->parent->child_list; + + while (ntp && ntp != tp) { + otp = ntp; ntp = ntp->next_peer; + } + if (!ntp) snmp_log(LOG_EMERG, "Can't find %s in %s's children\n", + tp->label, tp->parent->label); + else if (otp) otp->next_peer = ntp->next_peer; + else tp->parent->child_list = tp->next_peer; +} + +static void +free_partial_tree(struct tree *tp, int keep_label) +{ + if ( !tp) + return; + + /* remove the data from this tree node */ + free_enums(&tp->enums); + free_ranges(&tp->ranges); + free_indexes(&tp->indexes); + if (!keep_label) + SNMP_FREE(tp->label); + SNMP_FREE(tp->hint); + SNMP_FREE(tp->units); + SNMP_FREE(tp->description); +} + +/* + * free a tree node. Note: the node must already have been unlinked + * from the tree when calling this routine + */ +static void +free_tree(struct tree *Tree) +{ + if (!Tree) + return; + + unlink_tbucket(Tree); + free_partial_tree (Tree, FALSE); + if (Tree->number_modules > 1 ) + free((char*)Tree->module_list); + free ((char*)Tree); +} + +static void +free_node(struct node *np) +{ + if ( !np) return; + + free_enums(&np->enums); + free_ranges(&np->ranges); + free_indexes(&np->indexes); + if (np->label) free(np->label); + if (np->hint) free(np->hint); + if (np->units) free(np->units); + if (np->description) free(np->description); + if (np->parent) free(np->parent); + free((char*)np); +} + +#ifdef TEST +static void +print_nodes(FILE *fp, + struct node *root) +{ +extern void xmalloc_stats (FILE *); + struct enum_list *ep; + struct index_list *ip; + struct range_list *rp; + struct node *np; + + for(np = root; np; np = np->next){ + fprintf(fp, "%s ::= { %s %ld } (%d)\n", np->label, np->parent, + np->subid, np->type); + if (np->tc_index >= 0) + fprintf(fp, " TC = %s\n", tclist[np->tc_index].descriptor); + if (np->enums){ + fprintf(fp, " Enums: \n"); + for(ep = np->enums; ep; ep = ep->next){ + fprintf(fp, " %s(%d)\n", ep->label, ep->value); + } + } + if (np->ranges){ + fprintf(fp, " Ranges: \n"); + for(rp = np->ranges; rp; rp = rp->next){ + fprintf(fp, " %d..%d\n", rp->low, rp->high); + } + } + if (np->indexes){ + fprintf(fp, " Indexes: \n"); + for(ip = np->indexes; ip; ip = ip->next){ + fprintf(fp, " %s\n", ip->ilabel); + } + } + if (np->hint) + fprintf(fp, " Hint: %s\n", np->hint); + if (np->units) + fprintf(fp, " Units: %s\n", np->units); + } +} +#endif + +void +print_subtree(FILE *f, + struct tree *tree, + int count) +{ + struct tree *tp; + int i; + char modbuf[256]; + + for(i = 0; i < count; i++) + fprintf(f, " "); + fprintf(f, "Children of %s(%ld):\n", tree->label, tree->subid); + count++; + for(tp = tree->child_list; tp; tp = tp->next_peer){ + for(i = 0; i < count; i++) + fprintf(f, " "); + fprintf(f, "%s:%s(%ld) type=%d", + module_name(tp->module_list[0], modbuf), + tp->label, tp->subid, tp->type); + if (tp->tc_index != -1) fprintf(f, " tc=%d", tp->tc_index); + if (tp->hint) fprintf(f, " hint=%s", tp->hint); + if (tp->units) fprintf(f, " units=%s", tp->units); + if (tp->number_modules > 1) { + fprintf(f, " modules:"); + for (i = 1; i < tp->number_modules; i++) + fprintf(f, " %s", module_name(tp->module_list[i], modbuf)); + } + fprintf(f, "\n"); + } + for(tp = tree->child_list; tp; tp = tp->next_peer){ + if (tp->child_list) + print_subtree(f, tp, count); + } +} + +void +print_ascii_dump_tree(FILE *f, + struct tree *tree, + int count) +{ + struct tree *tp; + + count++; + for(tp = tree->child_list; tp; tp = tp->next_peer){ + fprintf(f, "%s OBJECT IDENTIFIER ::= { %s %ld }\n", tp->label, tree->label, tp->subid); + } + for(tp = tree->child_list; tp; tp = tp->next_peer){ + if (tp->child_list) + print_ascii_dump_tree(f, tp, count); + } +} + +static int translation_table[256]; + +static void +build_translation_table() +{ + int count; + + for(count = 0; count < 256; count++){ + switch(count){ + case OBJID: + translation_table[count] = TYPE_OBJID; + break; + case OCTETSTR: + translation_table[count] = TYPE_OCTETSTR; + break; + case INTEGER: + translation_table[count] = TYPE_INTEGER; + break; + case NETADDR: + translation_table[count] = TYPE_IPADDR; + break; + case IPADDR: + translation_table[count] = TYPE_IPADDR; + break; + case COUNTER: + translation_table[count] = TYPE_COUNTER; + break; + case GAUGE: + translation_table[count] = TYPE_GAUGE; + break; + case TIMETICKS: + translation_table[count] = TYPE_TIMETICKS; + break; + case KW_OPAQUE: + translation_table[count] = TYPE_OPAQUE; + break; + case NUL: + translation_table[count] = TYPE_NULL; + break; + case COUNTER64: + translation_table[count] = TYPE_COUNTER64; + break; + case BITSTRING: + translation_table[count] = TYPE_BITSTRING; + break; + case NSAPADDRESS: + translation_table[count] = TYPE_NSAPADDRESS; + break; + case UINTEGER32: + translation_table[count] = TYPE_UINTEGER; + break; + default: + translation_table[count] = TYPE_OTHER; + break; + } + } +} + +static void +init_tree_roots() +{ + struct tree *tp, *lasttp; + int base_modid; + int hash; + + base_modid = which_module("SNMPv2-SMI"); + if (base_modid == -1 ) + base_modid = which_module("RFC1155-SMI"); + if (base_modid == -1 ) + base_modid = which_module("RFC1213-MIB"); + + /* build root node */ + tp = (struct tree *) calloc(1, sizeof(struct tree)); + if (tp == NULL) return; + tp->label = strdup("joint-iso-ccitt"); + tp->modid = base_modid; + tp->number_modules = 1; + tp->module_list = &(tp->modid); + tp->subid = 2; + tp->tc_index = -1; + set_function(tp); /* from mib.c */ + hash = NBUCKET(name_hash(tp->label)); + tp->next = tbuckets[hash]; + tbuckets[hash] = tp; + lasttp = tp; + root_imports[0].label = strdup( tp->label ); + root_imports[0].modid = base_modid; + + /* build root node */ + tp = (struct tree *) calloc(1, sizeof(struct tree)); + if (tp == NULL) return; + tp->next_peer = lasttp; + tp->label = strdup("ccitt"); + tp->modid = base_modid; + tp->number_modules = 1; + tp->module_list = &(tp->modid); + tp->subid = 0; + tp->tc_index = -1; + set_function(tp); /* from mib.c */ + hash = NBUCKET(name_hash(tp->label)); + tp->next = tbuckets[hash]; + tbuckets[hash] = tp; + lasttp = tp; + root_imports[1].label = strdup( tp->label ); + root_imports[1].modid = base_modid; + + /* build root node */ + tp = (struct tree *) calloc(1, sizeof(struct tree)); + if (tp == NULL) return; + tp->next_peer = lasttp; + tp->label = strdup("iso"); + tp->modid = base_modid; + tp->number_modules = 1; + tp->module_list = &(tp->modid); + tp->subid = 1; + tp->tc_index = -1; + set_function(tp); /* from mib.c */ + hash = NBUCKET(name_hash(tp->label)); + tp->next = tbuckets[hash]; + tbuckets[hash] = tp; + lasttp = tp; + root_imports[2].label = strdup( tp->label ); + root_imports[2].modid = base_modid; + + tree_head = tp; +} + +#ifdef STRICT_MIB_PARSEING +#define label_compare strcasecmp +#else +#define label_compare strcmp +#endif + + +struct tree * +find_tree_node(const char *name, + int modid) +{ + struct tree *tp, *headtp; + int count, *int_p; + + if (!name || !*name) + return(NULL); + + headtp = tbuckets[NBUCKET(name_hash(name))]; + for ( tp = headtp ; tp ; tp=tp->next ) { + if ( !label_compare(tp->label, name) ) { + + if ( modid == -1 ) /* Any module */ + return(tp); + + for (int_p = tp->module_list, count=0 ; + count < tp->number_modules ; + ++count, ++int_p ) + if ( *int_p == modid ) + return(tp); + } + } + + return(NULL); +} + +/* computes a value which represents how close name1 is to name2. + * high scores mean a worse match. + * (yes, the algorithm sucks!) + */ +#define MAX_BAD 0xffffff + +u_int +compute_match(const char *search_base, const char *key) { +#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) + int rc; + regex_t parsetree; + regmatch_t pmatch; + + rc=regcomp(&parsetree, key, REG_ICASE | REG_EXTENDED); + if (rc == 0) + rc=regexec(&parsetree, search_base, 1, &pmatch, 0); + regfree(&parsetree); + if (rc == 0) { + /* found */ + return pmatch.rm_so; + } +#else /* use our own wildcard matcher */ + /* first find the longest matching substring (ick) */ + char *first = NULL, *result = NULL, *entry; + const char *position; + char *newkey = strdup(key); + + + entry = strtok( newkey, "*" ); + position = search_base; + while ( entry ) { + result = strcasestr(position, entry); + + if (result == NULL) { + free(newkey); + return MAX_BAD; + } + + if (first == NULL) + first = result; + + position = result + strlen(entry); + entry = strtok( NULL, "*" ); + } + free(newkey); + if (result) + return(first-search_base); +#endif + + /* not found */ + return MAX_BAD; +} + +/* + * Find the tree node that best matches the pattern string. + * Use the "reported" flag such that only one match + * is attempted for every node. + * + * Warning! This function may recurse. + * + * Caller _must_ invoke clear_tree_flags before first call + * to this function. This function may be called multiple times + * to ensure that the entire tree is traversed. + */ + +struct tree * +find_best_tree_node(const char *pattrn, struct tree *tree_top, u_int *match) +{ + struct tree *tp, *best_so_far = NULL, *retptr; + u_int old_match=MAX_BAD, new_match=MAX_BAD; + + if (!pattrn || !*pattrn) + return(NULL); + + if (!tree_top) + tree_top = get_tree_head(); + + for ( tp = tree_top ; tp ; tp=tp->next_peer ) { + if (!tp->reported) + new_match = compute_match(tp->label, pattrn); + tp->reported = 1; + + if (new_match < old_match) { + best_so_far = tp; + old_match = new_match; + } + if (new_match == 0) + break; /* this is the best result we can get */ + if (tp->child_list) { + retptr = find_best_tree_node(pattrn, tp->child_list, &new_match); + if (new_match < old_match) { + best_so_far = retptr; + old_match = new_match; + } + if (new_match == 0) + break; /* this is the best result we can get */ + } + } + + if (match) + *match = old_match; + return(best_so_far); +} + + +static void +merge_anon_children(struct tree *tp1, + struct tree *tp2) + /* NB: tp1 is the 'anonymous' node */ +{ + struct tree *child1, *child2, *previous; + + for ( child1 = tp1->child_list ; child1 ; ) { + + for ( child2 = tp2->child_list, previous = NULL ; + child2 ; previous = child2, child2 = child2->next_peer ) { + + if ( child1->subid == child2->subid ) { + /* + * Found 'matching' children, + * so merge them + */ + if ( !strncmp( child1->label, ANON, ANON_LEN)) { + merge_anon_children( child1, child2 ); + + child1->child_list = NULL; + previous = child1; /* Finished with 'child1' */ + child1 = child1->next_peer; + free_tree( previous ); + goto next; + } + + else if ( !strncmp( child2->label, ANON, ANON_LEN)) { + merge_anon_children( child2, child1 ); + + if ( previous ) + previous->next_peer = child2->next_peer; + else + tp2->child_list = child2->next_peer; + free_tree(child2); + + previous = child1; /* Move 'child1' to 'tp2' */ + child1 = child1->next_peer; + previous->next_peer = tp2->child_list; + tp2->child_list = previous; + for ( previous = tp2->child_list ; + previous ; + previous = previous->next_peer ) + previous->parent = tp2; + goto next; + } + else if ( !label_compare( child1->label, child2->label) ) { + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, "Warning: %s.%ld is both %s and %s (%s)\n", + tp2->label, child1->subid, + child1->label, child2->label, File); + continue; + } + else { + /* + * Two copies of the same node. + * 'child2' adopts the children of 'child1' + */ + + if ( child2->child_list ) { + for ( previous = child2->child_list ; + previous->next_peer ; + previous = previous->next_peer ) + ; /* Find the end of the list */ + previous->next_peer = child1->child_list; + } + else + child2->child_list = child1->child_list; + for ( previous = child1->child_list ; + previous ; + previous = previous->next_peer ) + previous->parent = child2; + child1->child_list = NULL; + + previous = child1; /* Finished with 'child1' */ + child1 = child1->next_peer; + free_tree( previous ); + goto next; + } + } + } + /* + * If no match, move 'child1' to 'tp2' child_list + */ + if ( child1 ) { + previous = child1; + child1 = child1->next_peer; + previous->parent = tp2; + previous->next_peer = tp2->child_list; + tp2->child_list = previous; + } + next:; + } +} + + +/* + * Find all the children of root in the list of nodes. Link them into the + * tree and out of the nodes list. + */ +static void +do_subtree(struct tree *root, + struct node **nodes) +{ + register struct tree *tp, *anon_tp=NULL; + register struct node *np, **headp; + struct node *oldnp = NULL, *child_list = NULL, *childp = NULL; + int hash; + int *int_p; + + tp = root; + headp = &nbuckets[NBUCKET(name_hash(tp->label))]; + /* + * Search each of the nodes for one whose parent is root, and + * move each into a separate list. + */ + for(np = *headp; np; np = np->next){ + if ( !label_compare(tp->label, np->parent)){ + /* take this node out of the node list */ + if (oldnp == NULL){ + *headp = np->next; /* fix root of node list */ + } else { + oldnp->next = np->next; /* link around this node */ + } + if (child_list) childp->next = np; + else child_list = np; + childp = np; + } + else { + oldnp = np; + } + + } + if (childp) childp->next = NULL; + /* + * Take each element in the child list and place it into the tree. + */ + for(np = child_list; np; np = np->next){ + anon_tp = NULL; + tp = root->child_list; + while (tp) + if (tp->subid == np->subid) break; + else tp = tp->next_peer; + if (tp) { + if (!label_compare (tp->label, np->label)) { + /* Update list of modules */ + int_p = (int *) malloc((tp->number_modules+1) * sizeof(int)); + if (int_p == NULL) return; + memcpy(int_p, tp->module_list, tp->number_modules*sizeof(int)); + int_p[tp->number_modules] = np->modid; + if (tp->number_modules > 1 ) + free((char*)tp->module_list); + ++tp->number_modules; + tp->module_list = int_p; + + if ( ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_REPLACE) ) { + /* Replace from node */ + tree_from_node(tp,np); + } + /* Handle children */ + do_subtree(tp, nodes); + continue; + } + if (!strncmp( np->label, ANON, ANON_LEN) || + !strncmp( tp->label, ANON, ANON_LEN)) { + anon_tp = tp; /* Need to merge these two trees later */ + } + else if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, "Warning: %s.%ld is both %s and %s (%s)\n", + root->label, np->subid, tp->label, np->label, File); + } + + tp = (struct tree *) calloc(1, sizeof(struct tree)); + if (tp == NULL) return; + tp->parent = root; + tp->modid = np->modid; + tp->number_modules = 1; + tp->module_list = &(tp->modid); + tree_from_node(tp, np); + tp->next_peer = root->child_list; + root->child_list = tp; + hash = NBUCKET(name_hash(tp->label)); + tp->next = tbuckets[hash]; + tbuckets[hash] = tp; +/* if (tp->type == TYPE_OTHER) */ + do_subtree(tp, nodes); /* recurse on this child if it isn't + an end node */ + if ( anon_tp ) { + if (!strncmp( tp->label, ANON, ANON_LEN)) { + /* + * The new node is anonymous, + * so merge it with the existing one. + */ + merge_anon_children( tp, anon_tp ); + + /* unlink and destroy tp */ + unlink_tree(tp); + free_tree(tp); + } + else if (!strncmp( anon_tp->label, ANON, ANON_LEN)) { + struct tree *ntp; + /* + * The old node was anonymous, + * so merge it with the existing one, + * and fill in the full information. + */ + merge_anon_children( anon_tp, tp ); + + /* unlink anon_tp from the hash */ + unlink_tbucket(anon_tp); + + /* get rid of old contents of anon_tp */ + free_partial_tree(anon_tp, FALSE); + + /* put in the current information */ + anon_tp->label = tp->label; + anon_tp->child_list = tp->child_list; + anon_tp->modid = tp->modid; + anon_tp->tc_index = tp->tc_index; + anon_tp->type = tp->type; + anon_tp->enums = tp->enums; + anon_tp->indexes = tp->indexes; + anon_tp->ranges = tp->ranges; + anon_tp->hint = tp->hint; + anon_tp->units = tp->units; + anon_tp->description = tp->description; + anon_tp->parent = tp->parent; + set_function(anon_tp); + + /* update parent pointer in moved children */ + ntp = anon_tp->child_list; + while (ntp) { + ntp->parent = anon_tp; + ntp = ntp->next_peer; + } + + /* hash in anon_tp in its new place */ + hash = NBUCKET(name_hash(anon_tp->label)); + anon_tp->next = tbuckets[hash]; + tbuckets[hash] = anon_tp; + + /* unlink and destroy tp */ + unlink_tbucket(tp); + unlink_tree(tp); + free(tp); + } + else { + /* Uh? One of these two should have been anonymous! */ + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, + "Warning: expected anonymous node (either %s or %s) in %s\n", + tp->label, anon_tp->label, File); + } + anon_tp = NULL; + } + } + /* free all nodes that were copied into tree */ + oldnp = NULL; + for(np = child_list; np; np = np->next){ + if (oldnp) + free_node(oldnp); + oldnp = np; + } + if (oldnp) + free_node(oldnp); +} + +static void do_linkup(struct module *mp, + struct node *np) +{ + struct module_import *mip; + struct node *onp; + struct tree *tp; + int i; + /* + * All modules implicitly import + * the roots of the tree + */ + if (snmp_get_do_debugging() > 1) dump_module_list(); + DEBUGMSGTL(("parse-mibs", "Processing IMPORTS for module %d %s\n", mp->modid, mp->name)); + if ( mp->no_imports == 0 ) { + mp->no_imports = NUMBER_OF_ROOT_NODES; + mp->imports = root_imports; + } + + /* + * Build the tree + */ + init_node_hash( np ); + for ( i=0, mip=mp->imports ; i < mp->no_imports ; ++i, ++mip ) { + char modbuf[256]; + DEBUGMSGTL(("parse-mibs", " Processing import: %s\n", mip->label)); + if (get_tc_index( mip->label, mip->modid ) != -1) + continue; + tp = find_tree_node( mip->label, mip->modid ); + if (!tp) { + if (mip->modid != -1) + snmp_log(LOG_WARNING, "Did not find '%s' in module %s (%s)\n", + mip->label, module_name(mip->modid, modbuf), File); + continue; + } + do_subtree( tp, &np ); + } + + /* + * If any nodes left over, + * check that they're not the result of a "fully qualified" + * name, and then add them to the list of orphans + */ + + if (!np) return; + for ( tp = tree_head ; tp ; tp=tp->next_peer ) + do_subtree( tp, &np ); + if (!np) return; + for ( np = orphan_nodes ; np && np->next ; np = np->next ) + ; /* find the end of the orphan list */ + for (i = 0; i < NHASHSIZE; i++) + if ( nbuckets[i] ) { + if ( orphan_nodes ) + onp = np->next = nbuckets[i]; + else + onp = orphan_nodes = nbuckets[i]; + nbuckets[i] = NULL; + while (onp) { + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, + "Unlinked OID in %s: %s ::= { %s %ld }\n", + (mp->name ? mp->name : ""), + (onp->label ? onp->label : ""), + (onp->parent ? onp->parent : ""), + onp->subid); + np = onp; + onp = onp->next; + } + } + + return; +} + + +/* + * Takes a list of the form: + * { iso org(3) dod(6) 1 } + * and creates several nodes, one for each parent-child pair. + * Returns 0 on error. + */ +static int +getoid(FILE *fp, + struct subid_s *id, /* an array of subids */ + int length) /* the length of the array */ +{ + register int count; + int type; + char token[MAXTOKEN]; + + if ((type = get_token(fp, token, MAXTOKEN)) != LEFTBRACKET){ + print_error("Expected \"{\"", token, type); + return 0; + } + type = get_token(fp, token, MAXTOKEN); + for(count = 0; count < length; count++, id++){ + id->label = NULL; + id->modid = current_module; + id->subid = -1; + if (type == RIGHTBRACKET){ + return count; + } else if (type != LABEL && type != NUMBER){ + print_error("Not valid for object identifier", token, type); + return 0; + } + if (type == LABEL){ + /* this entry has a label */ + id->label = strdup(token); + type = get_token(fp, token, MAXTOKEN); + if (type == LEFTPAREN){ + type = get_token(fp, token, MAXTOKEN); + if (type == NUMBER){ + id->subid = atoi(token); + if ((type = get_token(fp, token, MAXTOKEN)) != RIGHTPAREN){ + print_error("Expected a closing parenthesis", + token, type); + return 0; + } + } else { + print_error("Expected a number", token, type); + return 0; + } + } else { + continue; + } + } else if (type == NUMBER) { + /* this entry has just an integer sub-identifier */ + id->subid = atoi(token); + } + else { + print_error("Expected label or number", token, type); + return 0; + } + type = get_token(fp, token, MAXTOKEN); + } + print_error ("Too long OID", token, type); + return 0; +} + +/* + * Parse a sequence of object subidentifiers for the given name. + * The "label OBJECT IDENTIFIER ::=" portion has already been parsed. + * + * The majority of cases take this form : + * label OBJECT IDENTIFIER ::= { parent 2 } + * where a parent label and a child subidentifier number are specified. + * + * Variations on the theme include cases where a number appears with + * the parent, or intermediate subidentifiers are specified by label, + * by number, or both. + * + * Here are some representative samples : + * internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 } + * mgmt OBJECT IDENTIFIER ::= { internet 2 } + * rptrInfoHealth OBJECT IDENTIFIER ::= { snmpDot3RptrMgt 0 4 } + * + * Here is a very rare form : + * iso OBJECT IDENTIFIER ::= { 1 } + * + * Returns NULL on error. When this happens, memory may be leaked. + */ +static struct node * +parse_objectid(FILE *fp, + char *name) +{ + register int count; + register struct subid_s *op, *nop; + int length; + struct subid_s loid[32]; + struct node *np, *root = NULL, *oldnp = NULL; + struct tree *tp; + + if ((length = getoid(fp, loid, 32)) == 0){ + print_error("Bad object identifier", NULL, CONTINUE); + return NULL; + } + + /* + * Handle numeric-only object identifiers, + * by labelling the first sub-identifier + */ + op = loid; + if ( !op->label ) + for ( tp = tree_head ; tp ; tp=tp->next_peer ) + if ( (int)tp->subid == op->subid ) { + op->label = strdup(tp->label); + break; + } + + /* + * Handle "label OBJECT-IDENTIFIER ::= { subid }" + */ + if (length == 1) { + op = loid; + np = alloc_node(op->modid); + if (np == NULL) return(NULL); + np->subid = op->subid; + np->label = strdup(name); + if (op->label) free(op->label); + return np; + } + + /* + * For each parent-child subid pair in the subid array, + * create a node and link it into the node list. + */ + for(count = 0, op = loid, nop=loid+1; count < (length - 1); + count++, op++, nop++){ + /* every node must have parent's name and child's name or number */ +/* XX the next statement is always true -- does it matter ?? */ + if (op->label && (nop->label || (nop->subid != -1))){ + np = alloc_node(nop->modid); + if (np == NULL) return(NULL); + if (root == NULL) root = np; + + np->parent = strdup (op->label); + if (count == (length - 2)) { + /* The name for this node is the label for this entry */ + np->label = strdup (name); + } + else { + if (!nop->label) { + nop->label = (char *) malloc(20 + ANON_LEN); + if (nop->label == NULL) return(NULL); + sprintf(nop->label, "%s%d", ANON, anonymous++); + } + np->label = strdup (nop->label); + } + if (nop->subid != -1) + np->subid = nop->subid; + else + print_error("Warning: This entry is pretty silly", + np->label, CONTINUE); + + /* set up next entry */ + if (oldnp) oldnp->next = np; + oldnp = np; + } /* end if(op->label... */ + } + + /* free the loid array */ + for(count = 0, op = loid; count < length; count++, op++){ + if (op->label) + free(op->label); + } + + return root; +} + +static int +get_tc(const char *descriptor, + int modid, + int *tc_index, + struct enum_list **ep, + struct range_list **rp, + char **hint) +{ + int i; + struct tc *tcp; + + i = get_tc_index(descriptor, modid); + if (tc_index) *tc_index = i; + if (i != -1) + { + tcp = &tclist[i]; + if (ep) { + free_enums(ep); + *ep = copy_enums(tcp->enums); + } + if (rp) { + free_ranges(rp); + *rp = copy_ranges(tcp->ranges); + } + if (hint) { + if (*hint) free(*hint); + *hint = (tcp->hint ? strdup(tcp->hint) : NULL); + } + return tcp->type; + } + return LABEL; +} + +/* return index into tclist of given TC descriptor + return -1 if not found + */ +static int +get_tc_index(const char *descriptor, + int modid) +{ + int i; + struct tc *tcp; + struct module *mp; + struct module_import *mip; + + /* + * Check that the descriptor isn't imported + * by searching the import list + */ + + for ( mp = module_head ; mp ; mp = mp->next ) + if ( mp->modid == modid ) + break; + if ( mp ) + for ( i=0, mip=mp->imports ; i < mp->no_imports ; ++i, ++mip ) { + if ( !label_compare( mip->label, descriptor )) { + /* Found it - so amend the module ID */ + modid = mip->modid; + break; + } + } + + + for(i=0, tcp=tclist; i < MAXTC; i++, tcp++){ + if (tcp->type == 0) + break; + if (!label_compare(descriptor, tcp->descriptor) && + ((modid == tcp->modid) || (modid == -1))){ + return i; + } + } + return -1; +} + +/* translate integer tc_index to string identifier from tclist + * + * Returns pointer to string in table (should not be modified) or NULL + */ +const char * +get_tc_descriptor(int tc_index) +{ + if (tc_index < 0 || tc_index >= MAXTC) return NULL; + return (tclist[tc_index].descriptor); +} + + +/* + * Parses an enumeration list of the form: + * { label(value) label(value) ... } + * The initial { has already been parsed. + * Returns NULL on error. + */ + +static struct enum_list * +parse_enumlist(FILE *fp, struct enum_list **retp) +{ + register int type; + char token [MAXTOKEN]; + struct enum_list *ep = NULL, **epp = &ep; + + free_enums(retp); + + while((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE){ + if (type == RIGHTBRACKET) + break; + if (type == LABEL){ + /* this is an enumerated label */ + *epp = (struct enum_list *) calloc(1, sizeof(struct enum_list)); + if (*epp == NULL) return(NULL); + /* a reasonable approximation for the length */ + (*epp)->label = strdup(token); + type = get_token(fp, token, MAXTOKEN); + if (type != LEFTPAREN) { + print_error("Expected \"(\"", token, type); + return NULL; + } + type = get_token(fp, token, MAXTOKEN); + if (type != NUMBER) { + print_error("Expected integer", token, type); + return NULL; + } + (*epp)->value = atoi(token); + type = get_token(fp, token, MAXTOKEN); + if (type != RIGHTPAREN) { + print_error("Expected \")\"", token, type); + return NULL; + } + epp = &(*epp)->next; + } + } + if (type == ENDOFFILE){ + print_error("Expected \"}\"", token, type); + return NULL; + } + *retp = ep; + return ep; +} + +static struct range_list *parse_ranges(FILE *fp, struct range_list **retp) +{ int low, high; + char nexttoken[MAXTOKEN]; + int nexttype; + struct range_list *rp = NULL, **rpp = &rp; + int size = 0, taken = 1; + + free_ranges(retp); + + nexttype = get_token(fp, nexttoken, MAXTOKEN); + if (nexttype == SIZE) { + size = 1; + taken = 0; + nexttype = get_token(fp, nexttoken, MAXTOKEN); + if (nexttype != LEFTPAREN) + print_error("Expected \"(\" after SIZE", nexttoken, nexttype); + } + + do { + if (!taken) nexttype = get_token(fp, nexttoken, MAXTOKEN); + else taken = 0; + high = low = atol(nexttoken); + nexttype = get_token(fp, nexttoken, MAXTOKEN); + if (nexttype == RANGE) { + nexttype = get_token(fp, nexttoken, MAXTOKEN); + high = atol(nexttoken); + nexttype = get_token(fp, nexttoken, MAXTOKEN); + } + *rpp = (struct range_list *)calloc (1, sizeof(struct range_list)); + if (*rpp == NULL) break; + (*rpp)->low = low; + (*rpp)->high = high; + rpp = &(*rpp)->next; + + } while (nexttype == BAR); + if (size) { + if (nexttype != RIGHTPAREN) + print_error ("Expected \")\" after SIZE", nexttoken, nexttype); + nexttype = get_token(fp, nexttoken, nexttype); + } + if (nexttype != RIGHTPAREN) + print_error ("Expected \")\"", nexttoken, nexttype); + + *retp = rp; + return rp; +} + +/* + * Parses an asn type. Structures are ignored by this parser. + * Returns NULL on error. + */ +static struct node * +parse_asntype(FILE *fp, + char *name, + int *ntype, + char *ntoken) +{ + int type, i; + char token[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + char *hint = NULL; + struct tc *tcp; + int level; + + type = get_token(fp, token, MAXTOKEN); + if (type == SEQUENCE){ + level = 0; + while((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE){ + if (type == LEFTBRACKET){ + level++; + } + else if (type == RIGHTBRACKET && --level == 0){ + *ntype = get_token(fp, ntoken, MAXTOKEN); + return NULL; + } + } + print_error("Expected \"}\"", token, type); + return NULL; + } else if (type == LEFTBRACKET) { + struct node *np; + int ch_next = '{'; + ungetc(ch_next, fp); + np = parse_objectid (fp, name); + if (np != NULL) { + *ntype = get_token(fp, ntoken, MAXTOKEN); + return np; + } + return NULL; + } else { + if (type == CONVENTION) { + while (type != SYNTAX && type != ENDOFFILE) { + if (type == DISPLAYHINT) { + type = get_token(fp, token, MAXTOKEN); + if (type != QUOTESTRING) print_error("DISPLAY-HINT must be string", token, type); + else hint = strdup (token); + } + else + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + } + type = get_token(fp, token, MAXTOKEN); + } + + if (type == LABEL) + { + type = get_tc(token, current_module, NULL, NULL, NULL, NULL); + } + + /* textual convention */ + for(i = 0; i < MAXTC; i++){ + if (tclist[i].type == 0) + break; + } + + if (i == MAXTC){ + print_error("Too many textual conventions", token, type); + SNMP_FREE(hint); + return NULL; + } + if (!(type & SYNTAX_MASK)){ + print_error("Textual convention doesn't map to real type", token, + type); + SNMP_FREE(hint); + return NULL; + } + tcp = &tclist[i]; + tcp->modid = current_module; + tcp->descriptor = strdup(name); + tcp->hint = hint; + tcp->type = type; + *ntype = get_token(fp, ntoken, MAXTOKEN); + if (*ntype == LEFTPAREN){ + tcp->ranges = parse_ranges(fp, &tcp->ranges); + *ntype = get_token(fp, ntoken, MAXTOKEN); + } else if (*ntype == LEFTBRACKET) { + /* if there is an enumeration list, parse it */ + tcp->enums = parse_enumlist(fp, &tcp->enums); + *ntype = get_token(fp, ntoken, MAXTOKEN); + } + return NULL; + } +} + + +/* + * Parses an OBJECT TYPE macro. + * Returns 0 on error. + */ +static struct node * +parse_objecttype(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + char nexttoken[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + int nexttype, tctype; + register struct node *np; + + type = get_token(fp, token, MAXTOKEN); + if (type != SYNTAX){ + print_error("Bad format for OBJECT-TYPE", token, type); + return NULL; + } + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, MAXTOKEN); + if (type == LABEL){ + int tmp_index; + tctype = get_tc(token, current_module, &tmp_index, + &np->enums, &np->ranges, &np->hint); + if (tctype == LABEL && + ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS) > 1){ + print_error("Warning: No known translation for type", token, type); + } + type = tctype; + np->tc_index = tmp_index; /* store TC for later reference */ + } + np->type = type; + nexttype = get_token(fp, nexttoken, MAXTOKEN); + switch(type){ + case SEQUENCE: + if (nexttype == OF){ + nexttype = get_token(fp, nexttoken, MAXTOKEN); + nexttype = get_token(fp, nexttoken, MAXTOKEN); + } + break; + case INTEGER: + case UINTEGER32: + case COUNTER: + case GAUGE: + case BITSTRING: + case LABEL: + if (nexttype == LEFTBRACKET) { + /* if there is an enumeration list, parse it */ + np->enums = parse_enumlist(fp, &np->enums); + nexttype = get_token(fp, nexttoken, MAXTOKEN); + } else if (nexttype == LEFTPAREN){ + /* if there is a range list, parse it */ + np->ranges = parse_ranges(fp, &np->ranges); + nexttype = get_token(fp, nexttoken, MAXTOKEN); + } + break; + case OCTETSTR: + case KW_OPAQUE: + /* parse any SIZE specification */ + if (nexttype == LEFTPAREN) { + nexttype = get_token(fp, nexttoken, MAXTOKEN); + if (nexttype == SIZE) { + nexttype = get_token(fp, nexttoken, MAXTOKEN); + if (nexttype == LEFTPAREN) { + np->ranges = parse_ranges(fp, &np->ranges); + nexttype = get_token(fp, nexttoken, MAXTOKEN); /* ) */ + if (nexttype == RIGHTPAREN) + { + nexttype = get_token(fp, nexttoken, MAXTOKEN); + break; + } + } + } + print_error("Bad SIZE syntax", token, type); + free_node(np); + return NULL; + } + break; + case OBJID: + case NETADDR: + case IPADDR: + case TIMETICKS: + case NUL: + case NSAPADDRESS: + case COUNTER64: + break; + default: + print_error("Bad syntax", token, type); + free_node(np); + return NULL; + } + if (nexttype == UNITS){ + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + if (type != QUOTESTRING) { + print_error("Bad UNITS", quoted_string_buffer, type); + free_node(np); + return NULL; + } + np->units = strdup (quoted_string_buffer); + nexttype = get_token(fp, nexttoken, MAXTOKEN); + } + if (nexttype != ACCESS){ + print_error("Should be ACCESS", nexttoken, nexttype); + free_node(np); + return NULL; + } + type = get_token(fp, token, MAXTOKEN); + if (type != READONLY && type != READWRITE && type != WRITEONLY + && type != NOACCESS && type != READCREATE && type != ACCNOTIFY){ + print_error("Bad ACCESS type", token, type); + free_node(np); + return NULL; + } + np->access = type; + type = get_token(fp, token, MAXTOKEN); + if (type != STATUS){ + print_error("Should be STATUS", token, type); + free_node(np); + return NULL; + } + type = get_token(fp, token, MAXTOKEN); + if (type != MANDATORY && type != CURRENT && type != KW_OPTIONAL && + type != OBSOLETE && type != DEPRECATED){ + print_error("Bad STATUS", token, type); + free_node(np); + return NULL; + } + np->status = type; + /* + * Optional parts of the OBJECT-TYPE macro + */ + type = get_token(fp, token, MAXTOKEN); + while (type != EQUALS && type != ENDOFFILE) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", quoted_string_buffer, type); + free_node(np); + return NULL; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) { + np->description = strdup (quoted_string_buffer); + } + break; + + case REFERENCE: + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + if (type != QUOTESTRING) { + print_error("Bad REFERENCE", quoted_string_buffer, type); + free_node(np); + return NULL; + } + break; + case INDEX: + np->indexes = getIndexes(fp, &np->indexes); + if (np->indexes == NULL) { + print_error("Bad Index List",token,type); + free_node(np); + return NULL; + } + break; + + case DEFVAL: + case AUGMENTS: + case NUM_ENTRIES: + if (tossObjectIdentifier(fp) != OBJID) { + print_error("Bad Object Identifier", token, type); + free_node(np); + return NULL; + } + break; + + default: + print_error("Bad format of optional clauses", token, type); + free_node(np); + return NULL; + + } + type = get_token(fp, token, MAXTOKEN); + } + if (type != EQUALS){ + print_error("Bad format", token, type); + free_node(np); + return NULL; + } + return merge_parse_objectid(np, fp, name); +} + +/* + * Parses an OBJECT GROUP macro. + * Returns 0 on error. + * + * Also parses object-identity, since they are similar (ignore STATUS). + * - WJH 10/96 + */ +static struct node * +parse_objectgroup(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + register struct node *np; + + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, MAXTOKEN); + while (type != EQUALS && type != ENDOFFILE) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", quoted_string_buffer, type); + free_node(np); + return NULL; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) { + np->description = strdup (quoted_string_buffer); + } + break; + + case REFERENCE: + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + if (type != QUOTESTRING) { + print_error("Bad REFERENCE", quoted_string_buffer, type); + free_node(np); + return NULL; + } + break; + + default: + /* NOTHING */ + break; + } + type = get_token(fp, token, MAXTOKEN); + } + return merge_parse_objectid(np, fp, name); +} + +/* + * Parses a NOTIFICATION-TYPE macro. + * Returns 0 on error. + */ +static struct node * +parse_notificationDefinition(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + register struct node *np; + + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, MAXTOKEN); + while (type != EQUALS && type != ENDOFFILE) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", quoted_string_buffer, type); + free_node(np); + return NULL; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) { + np->description = strdup (quoted_string_buffer); + } + break; + + default: + /* NOTHING */ + break; + } + type = get_token(fp, token, MAXTOKEN); + } + return merge_parse_objectid(np, fp, name); +} + +/* + * Parses a TRAP-TYPE macro. + * Returns 0 on error. + */ +static struct node * +parse_trapDefinition(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + register struct node *np; + + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, MAXTOKEN); + while (type != EQUALS && type != ENDOFFILE) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", quoted_string_buffer, type); + free_node(np); + return NULL; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) { + np->description = strdup (quoted_string_buffer); + } + break; + case ENTERPRISE: + type = get_token(fp, token, MAXTOKEN); + if (type == LEFTBRACKET) { + type = get_token(fp, token, MAXTOKEN); + if (type != LABEL) { + print_error("Bad Trap Format", token, type); + free_node(np); + return NULL; + } + np->parent = strdup(token); + /* Get right bracket */ + type = get_token(fp, token, MAXTOKEN); + } + else if (type == LABEL) + np->parent = strdup(token); + break; + default: + /* NOTHING */ + break; + } + type = get_token(fp, token, MAXTOKEN); + } + type = get_token(fp, token, MAXTOKEN); + + np->label = strdup(name); + + if (type != NUMBER) { + print_error("Expected a Number", token, type); + free_node(np); + return NULL; + } + np->subid = atoi(token); + np->next = alloc_node(current_module); + if (np->next == NULL) { + free_node(np); + return(NULL); + } + np->next->parent = np->parent; + np->parent = (char *)malloc(strlen(np->parent)+2); + if (np->parent == NULL) { + free_node(np->next); free_node(np); + return(NULL); + } + strcpy(np->parent, np->next->parent); + strcat(np->parent, "#"); + np->next->label = strdup(np->parent); + return np; +} + + +/* + * Parses a compliance macro + * Returns 0 on error. + */ +static struct node * +parse_compliance(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + register struct node *np; + + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, MAXTOKEN); + while (type != EQUALS && type != ENDOFFILE) { + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + } + return merge_parse_objectid(np, fp, name); +} + + +/* + * Parses a capabilities macro + * Returns 0 on error. + */ +static struct node * +parse_capabilities(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + register struct node *np; + + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, MAXTOKEN); + while (type != EQUALS && type != ENDOFFILE) { + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + } + return merge_parse_objectid(np, fp, name); +} + +/* + * Parses a module identity macro + * Returns 0 on error. + */ +static struct node * +parse_moduleIdentity(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + char quoted_string_buffer[MAXQUOTESTR]; + register struct node *np; + + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, MAXTOKEN); + while (type != EQUALS && type != ENDOFFILE) { + type = get_token(fp, quoted_string_buffer, MAXQUOTESTR); + } + return merge_parse_objectid(np, fp, name); +} + + +/* + * Parses a MACRO definition + * Expect BEGIN, discard everything to end. + * Returns 0 on error. + */ +static struct node * +parse_macro(FILE *fp, + char *name) +{ + register int type; + char token[MAXTOKEN]; + struct node *np; + int iLine = Line; + + np = alloc_node(current_module); + if (np == NULL) return(NULL); + type = get_token(fp, token, sizeof(token)); + while (type != EQUALS && type != ENDOFFILE) { + type = get_token(fp, token, sizeof(token)); + } + if (type != EQUALS) return NULL; + while (type != BEGIN && type != ENDOFFILE) { + type = get_token(fp, token, sizeof(token)); + } + if (type != BEGIN) return NULL; + while (type != END && type != ENDOFFILE) { + type = get_token(fp, token, sizeof(token)); + } + if (type != END) return NULL; + + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, + "%s MACRO (lines %d..%d parsed and ignored).\n", name, iLine, Line); + + return np; +} + +/* + * Parses a module import clause + * loading any modules referenced + */ +static void +parse_imports(FILE *fp) +{ + register int type; + char token[MAXTOKEN]; + char modbuf[256]; +#define MAX_IMPORTS 256 + struct module_import import_list[MAX_IMPORTS]; + int this_module, old_current_module; + const char *old_File; + int old_line; + struct module *mp; + + int import_count=0; /* Total number of imported descriptors */ + int i=0, old_i; /* index of first import from each module */ + + type = get_token(fp, token, MAXTOKEN); + + /* + * Parse the IMPORTS clause + */ + while (type != SEMI && type != ENDOFFILE) { + if (type == LABEL ) { + if (import_count == MAX_IMPORTS ) { + print_error("Too many imported symbols", token, type); + do { + type = get_token(fp, token, MAXTOKEN); + } while (type != SEMI && type != ENDOFFILE); + return; + } + import_list[import_count++].label = strdup(token); + } + else if ( type == FROM ) { + type = get_token(fp, token, MAXTOKEN); + if ( import_count == i ) { /* All imports are handled internally */ + type = get_token(fp, token, MAXTOKEN); + continue; + } + this_module = which_module(token); + + for ( old_i=i ; inext ) + if ( mp->modid == current_module) { + if ( import_count == 0) + return; + if (mp->imports && (mp->imports != root_imports)) + { + /* this can happen if all modules are in one source file. */ + for ( i=0 ; ino_imports; ++i ) { + DEBUGMSGTL(("parse-mibs", "#### freeing Module %d '%s' %d\n", + mp->modid, mp->imports[i].label, mp->imports[i].modid)); + free((char *)mp->imports[i].label); + } + free((char*)mp->imports); + } + mp->imports = (struct module_import *) + calloc(import_count, sizeof(struct module_import)); + if (mp->imports == NULL) return; + for ( i=0 ; iimports[i].label = import_list[i].label; + mp->imports[i].modid = import_list[i].modid; + DEBUGMSGTL(("parse-mibs", "#### adding Module %d '%s' %d\n", + mp->modid, mp->imports[i].label, mp->imports[i].modid)); + } + mp->no_imports = import_count; + return; + } + + /* + * Shouldn't get this far + */ + print_module_not_found(module_name(current_module,modbuf)); + return; +} + + + +/* + * MIB module handling routines + */ + +static void dump_module_list (void) +{ + struct module *mp = module_head; + + DEBUGMSGTL(("parse-mibs", "Module list:\n")); + while (mp) { + DEBUGMSGTL(("parse-mibs", " %s %d %s %d\n", mp->name, mp->modid, mp->file, mp->no_imports)); + mp = mp->next; + } +} + +int +which_module(const char *name) +{ + struct module *mp; + + for ( mp=module_head ; mp ; mp=mp->next ) + if ( !label_compare(mp->name, name)) + return(mp->modid); + + DEBUGMSGTL(("parse-mibs", "Module %s not found\n", name)); + return(-1); +} + +/* + * module_name - copy module name to user buffer, return ptr to same. + */ +char * +module_name (int modid, + char *cp) +{ + struct module *mp; + + for ( mp=module_head ; mp ; mp=mp->next ) + if ( mp->modid == modid ) + { + strcpy(cp, mp->name); + return(cp); + } + + DEBUGMSGTL(("parse-mibs", "Module %d not found\n", modid)); + sprintf(cp, "#%d", modid); + return(cp); +} + +/* + * Backwards compatability + * Read newer modules that replace the one specified:- + * either all of them (read_module_replacements), + * or those relating to a specified identifier (read_import_replacements) + * plus an interface to add new replacement requirements + */ +void +add_module_replacement(const char *old_module, + const char *new_module_name, + const char *tag, + int len) +{ + struct module_compatability *mcp; + + mcp = (struct module_compatability *) + calloc(1, sizeof( struct module_compatability)); + if (mcp == NULL) return; + + mcp->old_module = strdup( old_module ); + mcp->new_module = strdup( new_module_name ); + if (tag) + mcp->tag = strdup( tag ); + mcp->tag_len = len; + + mcp->next = module_map_head; + module_map_head = mcp; +} + +static void +read_module_replacements(const char *name) +{ + struct module_compatability *mcp; + + for ( mcp=module_map_head ; mcp; mcp=mcp->next ) { + if ( !label_compare( mcp->old_module, name )) { + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, + "Loading replacement module %s for %s (%s)\n", + mcp->new_module, name, File); + (void)read_module( mcp->new_module ); + return; + } + } + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_ERRORS)) + print_module_not_found(name); + +} + +static void +read_import_replacements(const char *old_module_name, + struct module_import *identifier) +{ + struct module_compatability *mcp; + + /* + * Look for matches first + */ + for ( mcp=module_map_head ; mcp; mcp=mcp->next ) { + if ( !label_compare( mcp->old_module, old_module_name )) { + + if ( /* exact match */ + ( mcp->tag_len==0 && + (mcp->tag == NULL || + !label_compare( mcp->tag, identifier->label ))) || + /* prefix match */ + ( mcp->tag_len!=0 && + !strncmp( mcp->tag, identifier->label, mcp->tag_len )) + ) { + + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, + "Importing %s from replacement module %s instead of %s (%s)\n", + identifier->label, mcp->new_module, old_module_name, File); + (void)read_module( mcp->new_module ); + identifier->modid = which_module(mcp->new_module); + return; /* finished! */ + } + } + } + + /* + * If no exact match, load everything relevant + */ + read_module_replacements( old_module_name ); +} + + +/* + * Read in the named module + * Returns the root of the whole tree + * (by analogy with 'read_mib') + */ +static int +read_module_internal (const char *name) +{ + struct module *mp; + FILE *fp; + struct node *np; + + if ( tree_head == NULL ) + init_mib_internals(); /* was init_mib */ + + for ( mp=module_head ; mp ; mp=mp->next ) + if ( !label_compare(mp->name, name)) { + const char *oldFile = File; + int oldLine = Line; + + if ( mp->no_imports != -1 ) { + DEBUGMSGTL(("parse-mibs", "Module %s already loaded\n", name)); + return MODULE_ALREADY_LOADED; + } + if ((fp = fopen(mp->file, "r")) == NULL) { + snmp_log_perror(mp->file); + return MODULE_LOAD_FAILED; + } + mp->no_imports=0; /* Note that we've read the file */ + File = mp->file; + Line = 1; + /* + * Parse the file + */ + np = parse( fp, NULL ); + fclose(fp); + File = oldFile; + Line = oldLine; + return MODULE_LOADED_OK; + } + + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS) > 1) + snmp_log(LOG_WARNING, "Module %s not found\n", name); + return MODULE_NOT_FOUND; +} + +void +adopt_orphans (void) +{ + struct node *np, *onp; + struct tree *tp; + int i, adopted; + + if ( !orphan_nodes ) + return; + init_node_hash(orphan_nodes); + orphan_nodes = NULL; + + while (1) { + adopted = 0; + for ( i = 0; i < NHASHSIZE; i++) + if ( nbuckets[i] ) { + for ( np = nbuckets[i] ; np!= NULL ; np=np->next ) + tp = find_tree_node( np->parent, -1 ); + if ( tp ) { + do_subtree( tp, &np ); + adopted = 1; + } + } + if ( adopted == 0 ) + break; + } + + /* + * Report on outstanding orphans + * and link them back into the orphan list + */ + for (i = 0; i < NHASHSIZE; i++) + if ( nbuckets[i] ) { + if ( orphan_nodes ) + onp = np->next = nbuckets[i]; + else + onp = orphan_nodes = nbuckets[i]; + nbuckets[i] = NULL; + while (onp) { + char modbuf[256]; + snmp_log (LOG_WARNING, + "Unlinked OID in %s: %s ::= { %s %ld }\n", + module_name(onp->modid, modbuf), + (onp->label ? onp->label : ""), + (onp->parent ? onp->parent : ""), + onp->subid); + + np = onp; + onp = onp->next; + } + } +} + +struct tree * +read_module(const char *name) +{ + if ( read_module_internal(name) == MODULE_NOT_FOUND ) + read_module_replacements( name ); + return tree_head; +} + +void +unload_module_by_ID( int modID, struct tree *tree_top ) +{ + struct tree *tp, *prev, *next; + int i; + + prev = NULL; + for ( tp=tree_top ; tp ; tp=next ) { + next = tp->next_peer; + /* + * This next section looks rather complex. + * Essentially, this is equivalent to the code fragment: + * if (tp->modID = modID) + * tp->number_modules--; + * but handles one tree node being part of several modules. + */ + for ( i=0 ; inumber_modules ; i++ ) { + if ( tp->module_list[i] == modID ) { + tp->number_modules--; + switch ( tp->number_modules ) { + + case 0: /* That was the only module */ + tp->modid = -1; /* Mark as unused */ + break; + + case 1: /* We did have a list of two, but this is no + longer needed. Transfer the other entry + ( i.e. module_list[1-i] - think about it! ) + to the 'single' slot tp->modid, and discard + the list. + */ + tp->modid = tp->module_list[1-i]; + free(tp->module_list); + tp->module_list = NULL; /* let's be tidy */ + break; + + default: /* We still need the list, so shuffle down + all following entries to close up the gap */ + while ( i < tp->number_modules ) { + tp->module_list[i] = tp->module_list[i+1]; + i++; + } + break; + } + break; /* Don't need to look through the rest of the list */ + } + } + + /* + * OK - that's dealt with *this* node. + * Now let's look at the children. + * (Isn't recursion wonderful!) + */ + if ( tp->child_list ) + unload_module_by_ID( modID, tp->child_list ); + + + if ( tp->number_modules == 0 ) { + /* This node isn't needed any more (except perhaps + for the sake of the children) */ + if ( tp->child_list == NULL ) { + if ( prev ) + prev->next_peer = tp->next_peer; + else + tp->parent->child_list = tp->next_peer; + free_tree( tp ); + } + else + free_partial_tree( tp, TRUE ); + } + else + prev = tp; + } +} + +int +unload_module(const char *name) +{ + struct module *mp; + int modID = -1; + + for ( mp=module_head ; mp ; mp=mp->next ) + if ( !label_compare(mp->name, name)) { + modID = mp->modid; + break; + } + + if ( modID == -1 ) { + DEBUGMSGTL(("unload-mib", "Module %s not found to unload\n", name)); + return MODULE_NOT_FOUND; + } + unload_module_by_ID( modID, tree_head ); + mp->no_imports = -1; /* mark as unloaded */ + return MODULE_LOADED_OK; /* Well, you know what I mean! */ +} + +static void +new_module (const char *name, + const char *file) +{ + struct module *mp; + + for ( mp=module_head ; mp ; mp=mp->next ) + if ( !label_compare(mp->name, name)) { + DEBUGMSGTL(("parse-mibs", "Module %s already noted\n", name)); + /* Not the same file */ + if (label_compare(mp->file, file)) { + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + snmp_log(LOG_WARNING, + "Warning: Module %s was in %s now is %s\n", + name, mp->file, file); + + /* Use the new one in preference */ + free(mp->file); + mp->file = strdup(file); + } + return; + } + + /* Add this module to the list */ + DEBUGMSGTL(("parse-mibs", " Module %d %s is in %s\n", max_module, name, file)); + mp = (struct module *) calloc(1, sizeof(struct module)); + if (mp == NULL) return; + mp->name = strdup(name); + mp->file = strdup(file); + mp->imports = NULL; + mp->no_imports = -1; /* Not yet loaded */ + mp->modid = max_module; + ++max_module; + + mp->next = module_head; /* Or add to the *end* of the list? */ + module_head = mp; +} + + + + +/* + * Parses a mib file and returns a linked list of nodes found in the file. + * Returns NULL on error. + */ +static struct node * +parse(FILE *fp, + struct node *root) +{ + char token[MAXTOKEN]; + char name[MAXTOKEN]; + int type = LABEL; + int lasttype = LABEL; + +#define BETWEEN_MIBS 1 +#define IN_MIB 2 + int state = BETWEEN_MIBS; + struct node *np, *nnp; + + DEBUGMSGTL(("parse-file", "Parsing file: %s...\n", File)); + + if (last_err_module) free(last_err_module); last_err_module = 0; + + np = root; + if (np != NULL) { + /* now find end of chain */ + while(np->next) + np = np->next; + } + + while (type != ENDOFFILE){ + if (lasttype == CONTINUE) lasttype = type; + else type = lasttype = get_token(fp, token, MAXTOKEN); + + switch (type) { + case END: + if (state != IN_MIB){ + print_error("Error, END before start of MIB", NULL, type); + return NULL; + } + else { + struct module *mp; +#ifdef TEST + printf("\nNodes for Module %s:\n", name); + print_nodes( stdout, np ); +#endif + for (mp = module_head; mp; mp = mp->next) + if (mp->modid == current_module) break; + do_linkup(mp, root); + np = root = NULL; + } + state = BETWEEN_MIBS; +#ifdef TEST + if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS)) + xmalloc_stats (stderr); +#endif + continue; + case IMPORTS: + parse_imports( fp ); + continue; + case EXPORTS: + while (type != SEMI && type != ENDOFFILE) + type = get_token(fp, token, MAXTOKEN); + continue; + case LABEL: + break; + case ENDOFFILE: + continue; + default: + strcpy(name, token); + type = get_token(fp, token, MAXTOKEN); + nnp = NULL; + if (type == MACRO) { + nnp = parse_macro(fp, name); + if (nnp == NULL){ + print_error("Bad parse of MACRO", NULL, type); + /*return NULL;*/ + } + free_node(nnp); /* IGNORE */ + nnp = NULL; + } + else + print_error(name, "is a reserved word", lasttype); + continue; /* see if we can parse the rest of the file */ + } + strcpy(name, token); + type = get_token(fp, token, MAXTOKEN); + nnp = NULL; + + /* Handle obsolete method to assign an object identifier to a + module*/ + if (lasttype == LABEL && type == LEFTBRACKET) { + while (type != RIGHTBRACKET && type != ENDOFFILE) + type = get_token(fp, token, MAXTOKEN); + if (type == ENDOFFILE){ + print_error("Expected \"}\"", token, type); + return NULL; + } + type = get_token(fp, token, MAXTOKEN); + } + + switch (type) { + case DEFINITIONS: + if (state != BETWEEN_MIBS){ + print_error("Error, nested MIBS", NULL, type); + return NULL; + } + state = IN_MIB; + current_module = which_module( name ); + if ( current_module == -1 ) { + new_module(name, File); + current_module = which_module(name); + } + DEBUGMSGTL(("parse-mibs", "Parsing MIB: %d %s\n", current_module, name)); + while ((type = get_token (fp, token, MAXTOKEN)) != ENDOFFILE) + if (type == BEGIN) break; + break; + case OBJTYPE: + nnp = parse_objecttype(fp, name); + if (nnp == NULL){ + print_error("Bad parse of OBJECT-TYPE", NULL, type); + return NULL; + } + break; + case OBJGROUP: + nnp = parse_objectgroup(fp, name); + if (nnp == NULL){ + print_error("Bad parse of OBJECT-GROUP", NULL, type); + return NULL; + } + break; + case TRAPTYPE: + nnp = parse_trapDefinition(fp, name); + if (nnp == NULL){ + print_error("Bad parse of TRAP-TYPE", NULL, type); + return NULL; + } + break; + case NOTIFTYPE: + nnp = parse_notificationDefinition(fp, name); + if (nnp == NULL){ + print_error("Bad parse of NOTIFICATION-TYPE", NULL, type); + return NULL; + } + break; + case COMPLIANCE: + nnp = parse_compliance(fp, name); + if (nnp == NULL){ + print_error("Bad parse of MODULE-COMPLIANCE", NULL, type); + return NULL; + } + break; + case CAPABILITIES: + nnp = parse_capabilities(fp, name); + if (nnp == NULL){ + print_error("Bad parse of AGENT-CAPABILITIES", NULL, type); + return NULL; + } + break; + case MACRO: + nnp = parse_macro(fp, name); + if (nnp == NULL){ + print_error("Bad parse of MACRO", NULL, type); + /*return NULL;*/ + } + free_node(nnp); /* IGNORE */ + nnp = NULL; + break; + case MODULEIDENTITY: + nnp = parse_moduleIdentity(fp, name); + if (nnp == NULL){ + print_error("Bad parse of MODULE-IDENTITY", NULL, type); + return NULL; + } + break; + case OBJID: + type = get_token(fp, token, MAXTOKEN); + if (type != EQUALS){ + print_error("Expected \"::=\"", token, type); + return NULL; + } + nnp = parse_objectid(fp, name); + if (nnp == NULL){ + print_error("Bad parse of OBJECT IDENTIFIER", NULL, type); + return NULL; + } + break; + case EQUALS: + nnp = parse_asntype(fp, name, &type, token); + lasttype = CONTINUE; + break; + case ENDOFFILE: + break; + default: + print_error("Bad operator", token, type); + return NULL; + } + if (nnp) { + if (np) np->next = nnp; + else np = root = nnp; + while (np->next) np = np->next; + } + } + DEBUGMSGTL(("parse-file", "End of file (%s)\n", File)); + return root; +} + +/* return zero if character is not a label character. */ +static int +is_labelchar (int ich) +{ + if ((isalnum(ich)) || (ich == '-')) + return 1; + if (ich == '_' && ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL)) + return 1; + + return 0; +} + +/* + * Parses a token from the file. The type of the token parsed is returned, + * and the text is placed in the string pointed to by token. + * Warning: this method may recurse. + */ +static int +get_token(FILE *fp, + char *token, + int maxtlen) +{ + register int ch, ch_next; + register char *cp = token; + register int hash = 0; + register struct tok *tp; + int too_long = 0; + + /* skip all white space */ + do { + ch = getc(fp); + if (ch == '\n') + Line++; + } + while(isspace(ch) && ch != EOF); + *cp++ = ch; *cp = '\0'; + switch (ch) { + case EOF: + return ENDOFFILE; + case '"': + return parseQuoteString(fp, token, maxtlen); + case '\'': /* binary or hex constant */ + while ((ch = getc(fp)) != EOF && ch != '\'' && cp-token < maxtlen-2) + *cp++ = ch; + if (ch == '\'') { + unsigned long val = 0; + *cp++ = '\''; + *cp++ = ch = getc(fp); + *cp = 0; + cp = token+1; + switch (ch) { + case EOF: + return ENDOFFILE; + case 'b': + case 'B': + while ((ch = *cp++) != '\'') + if (ch != '0' && ch != '1') return LABEL; + else val = val * 2 + ch - '0'; + break; + case 'h': + case 'H': + while ((ch = *cp++) != '\'') + if ('0' <= ch && ch <= '9') val = val*16+ch-'0'; + else if ('a' <= ch && ch <= 'f') val = val*16+ch-'a'+10; + else if ('A' <= ch && ch <= 'F') val = val*16+ch-'A'+10; + else return LABEL; + break; + default: + return LABEL; + } + sprintf(token, "%ld", val); + return NUMBER; + } + else return LABEL; + case '(': + return LEFTPAREN; + case ')': + return RIGHTPAREN; + case '{': + return LEFTBRACKET; + case '}': + return RIGHTBRACKET; + case ';': + return SEMI; + case ',': + return COMMA; + case '|': + return BAR; + case '.': + ch_next = getc(fp); + if (ch_next == '.') return RANGE; + ungetc(ch_next, fp); + return LABEL; + case ':': + ch_next = getc(fp); + if (ch_next != ':') { + ungetc(ch_next, fp); + return LABEL; + } + ch_next = getc(fp); + if (ch_next != '=') { + ungetc(ch_next, fp); + return LABEL; + } + return EQUALS; + case '-': + ch_next = getc(fp); + if (ch_next == '-') { + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM)) { + /* Treat the rest of this line as a comment. */ + while ((ch_next != EOF) && (ch_next != '\n')) + ch_next = getc(fp); + } else { + /* Treat the rest of the line or until another '--' as a comment */ + /* (this is the "technically" correct way to parse comments) */ + ch = ' '; + ch_next = getc(fp); + while (ch_next != EOF && ch_next != '\n' && + (ch != '-' || ch_next != '-')) { + ch = ch_next; ch_next = getc(fp); + } + } + if (ch_next == EOF) return ENDOFFILE; + if (ch_next == '\n') Line++; + return get_token (fp, token, maxtlen); + } + ungetc(ch_next, fp); + default: + /* + * Accumulate characters until end of token is found. Then attempt to + * match this token as a reserved word. If a match is found, return the + * type. Else it is a label. + */ + if (!is_labelchar(ch)) return LABEL; + hash += tolower(ch); + more: + while (is_labelchar(ch_next = getc(fp))) { + hash += tolower(ch_next); + if (cp - token < maxtlen - 1) *cp++ = ch_next; + else too_long = 1; + } + ungetc(ch_next, fp); + *cp = '\0'; + + if (too_long) + print_error("Warning: token too long", token, CONTINUE); + for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) { + if ((tp->hash == hash) && (!label_compare(tp->name, token))) + break; + } + if (tp) { + if (tp->token != CONTINUE) return (tp->token); + while (isspace((ch_next = getc(fp)))) + if (ch_next == '\n') Line++; + if (ch_next == EOF) return ENDOFFILE; + if (isalnum(ch_next)) { + *cp++ = ch_next; + hash += tolower(ch_next); + goto more; + } + } + if (token[0] == '-' || isdigit(token[0])) { + for(cp = token+1; *cp; cp++) + if (!isdigit(*cp)) + return LABEL; + return NUMBER; + } + return LABEL; + } +} + +int +snmp_get_token(FILE *fp, + char *token, + int maxtlen) +{ + return get_token(fp, token, maxtlen); +} + +int +add_mibdir(const char *dirname) +{ +#ifndef ECOSFIXME_NEEDFILESYSTEM + FILE *fp, *ip; + DIR *dir, *dir2; + const char *oldFile = File; + struct dirent *file; + char token[MAXTOKEN]; + char tmpstr[300]; + int count = 0; +#ifndef WIN32 + struct stat dir_stat, idx_stat; + char tmpstr1[300]; +#endif + + DEBUGMSGTL(("parse-mibs", "Scanning directory %s\n", dirname)); +#ifndef WIN32 + sprintf(token, "%s/%s", dirname, ".index"); + if (stat(token, &idx_stat) == 0 && stat(dirname, &dir_stat) == 0) { + if (dir_stat.st_mtime < idx_stat.st_mtime) { + DEBUGMSGTL(("parse-mibs", "The index is good\n")); + if ((ip = fopen(token, "r")) != NULL) { + while (fscanf(ip, "%s %s\n", token, tmpstr) == 2) { + sprintf(tmpstr1, "%s/%s", dirname, tmpstr); + new_module(token, tmpstr1); + count++; + } + fclose(ip); + return count; + } + else DEBUGMSGTL(("parse-mibs", "Can't read index\n")); + } + else DEBUGMSGTL(("parse-mibs", "Index outdated\n")); + } + else DEBUGMSGTL(("parse-mibs", "No index\n")); +#endif + + if ((dir = opendir(dirname))) { + sprintf(tmpstr, "%s/.index", dirname); + ip = fopen(tmpstr, "w"); + while ((file = readdir(dir))) { + /* Only parse file names not beginning with a '.' */ + if (file->d_name != NULL && file->d_name[0] != '.') { + sprintf(tmpstr, "%s/%s", dirname, file->d_name); + if ((dir2 = opendir(tmpstr))) { + /* file is a directory, don't read it */ + closedir(dir2); + } else { + /* which module is this */ + if ((fp = fopen(tmpstr, "r")) == NULL) { + snmp_log_perror(tmpstr); + continue; + } + DEBUGMSGTL(("parse-mibs", "Checking file: %s...\n", tmpstr)); + Line = 1; + File = tmpstr; + get_token( fp, token, MAXTOKEN); + new_module(token, tmpstr); + count++; + fclose (fp); + if (ip) fprintf(ip, "%s %s\n", token, file->d_name); + } + } + } + File = oldFile; + closedir(dir); + if (ip) fclose(ip); + return(count); + } + return(-1); + +#else + // __ECOS + +#if 0 // MIBS not needed for agent use of library. + int count = 0; + int i; + + static const char *snmp_miblist[] = { + "EtherLike-MIB", + "IANAifType-MIB", + "IF-MIB", + "IP-MIB", + "RFC-1215", + "SNMPv2-CONF", + "SNMPv2-MIB", + "SNMPv2-SMI", + "SNMPv2-TC", + "SNMPv2-TM", + "TCP-MIB", + "UDP-MIB", + }; + + for ( i = 0; + i < sizeof(snmp_miblist)/sizeof(snmp_miblist[0]); + i++ ) { + + new_module(snmp_miblist[i],snmp_miblist[i]); + count++; + } + return(count); +#else + return 0; +#endif + +#endif +} + + +/* + * Returns the root of the whole tree + * (for backwards compatability) + */ +struct tree * +read_mib(const char *filename) +{ + FILE *fp; + char token[MAXTOKEN]; + + fp = fopen(filename, "r"); + if (fp == NULL) { + snmp_log_perror(filename); + return NULL; + } + Line = 1; + File = filename; + DEBUGMSGTL(("parse-mibs", "Parsing file: %s...\n", filename)); + get_token( fp, token, MAXTOKEN); + fclose(fp); + new_module(token, filename); + (void) read_module(token); + + return tree_head; +} + + +struct tree * +read_all_mibs() +{ + struct module *mp; + + for ( mp=module_head ; mp ; mp=mp->next ) + if ( mp->no_imports == -1 ) + read_module( mp->name ); + adopt_orphans(); + + return tree_head; +} + + +#ifdef TEST +main(int argc, char *argv[]) +{ + int i; + struct tree *tp; + ds_set_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS, 2); + + init_mib(); + + if ( argc == 1 ) + (void) read_all_mibs(); + else + for ( i=1 ; inext_peer ) + print_subtree( stdout, tp, 0 ); + free_tree( tree_head ); + + return 0; +} +#endif /* TEST */ + +static int +parseQuoteString(FILE *fp, + char *token, + int maxtlen) +{ + register int ch; + int count = 0; + int too_long = 0; + char *token_start = token; + + for (ch = getc(fp); ch != EOF; ch = getc(fp)) { + if (ch == '\r') continue; + if (ch == '\n') { + Line++; + } + else if (ch == '"') { + *token = '\0'; + if (too_long && + ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS) > 1) + { + /* show short form for brevity sake */ + char ch_save = *(token_start + 50); + *(token_start + 50) = '\0'; + print_error ("Warning: string too long", + token_start, QUOTESTRING); + *(token_start + 50) = ch_save; + } + return QUOTESTRING; + } + /* maximum description length check. If greater, keep parsing + but truncate the string */ + if (++count < maxtlen) + *token++ = ch; + else too_long = 1; + } + + return 0; +} + +/* + * struct index_list * + * getIndexes(FILE *fp): + * This routine parses a string like { blah blah blah } and returns a + * list of the strings enclosed within it. + * + */ +static struct index_list * +getIndexes(FILE *fp, struct index_list **retp) { + int type; + char token[MAXTOKEN]; + char nextIsImplied = 0; + + struct index_list *mylist = NULL; + struct index_list **mypp = &mylist; + + free_indexes(retp); + + type = get_token(fp, token, MAXTOKEN); + + if (type != LEFTBRACKET) { + return NULL; + } + + type = get_token(fp, token, MAXTOKEN); + while (type != RIGHTBRACKET && type != ENDOFFILE) { + if ((type == LABEL) || (type & SYNTAX_MASK)) { + *mypp = (struct index_list *) calloc(1, sizeof(struct index_list)); + if (*mypp) { + (*mypp)->ilabel = strdup(token); + (*mypp)->isimplied = nextIsImplied; + mypp = &(*mypp)->next; + nextIsImplied = 0; + } + } else if (type == IMPLIED) { + nextIsImplied = 1; + } + type = get_token(fp, token, MAXTOKEN); + } + + *retp = mylist; + return mylist; +} + +static void +free_indexes(struct index_list **spp) { + if (spp && *spp) { + struct index_list *pp, *npp; + + pp = *spp; *spp = NULL; + + while(pp) { + npp = pp->next; + if (pp->ilabel) free(pp->ilabel); + free(pp); + pp = npp; + } + } +} + +static void +free_ranges(struct range_list **spp) { + if (spp && *spp) { + struct range_list *pp, *npp; + + pp = *spp; *spp = NULL; + + while(pp) { + npp = pp->next; + free(pp); + pp = npp; + } + } +} + +static void +free_enums(struct enum_list **spp) +{ + if (spp && *spp) { + struct enum_list *pp, *npp; + + pp = *spp; *spp = NULL; + + while(pp) + { + npp = pp->next; + if (pp->label) free(pp->label); + free(pp); + pp = npp; + } + } +} + +static struct enum_list * +copy_enums (struct enum_list *sp) +{ + struct enum_list *xp = NULL, **spp = &xp; + + while (sp) { + *spp = (struct enum_list *) calloc(1, sizeof(struct enum_list)); + if (!*spp) break; + (*spp)->label = strdup(sp->label); + (*spp)->value = sp->value; + spp = &(*spp)->next; + sp = sp->next; + } + return (xp); +} + +static struct range_list * +copy_ranges (struct range_list *sp) +{ + struct range_list *xp = NULL, **spp = &xp; + + while (sp) { + *spp = (struct range_list *) calloc(1, sizeof(struct range_list)); + if (!*spp) break; + (*spp)->low = sp->low; + (*spp)->high = sp->high; + spp = &(*spp)->next; + sp = sp->next; + } + return (xp); +} + +static struct index_list * +copy_indexes (struct index_list *sp) +{ + struct index_list *xp = NULL, **spp = &xp; + + while (sp) { + *spp = (struct index_list *) calloc(1, sizeof(struct index_list)); + if (!*spp) break; + (*spp)->ilabel = strdup(sp->ilabel); + spp = &(*spp)->next; + sp = sp->next; + } + return (xp); +} + +/* + * This routine parses a string like { blah blah blah } and returns OBJID if + * it is well formed, and NULL if not. + */ +static int +tossObjectIdentifier(FILE *fp) +{ + int type; + char token[MAXTOKEN]; + int bracketcount = 1; + + type = get_token(fp, token, MAXTOKEN); + + if (type != LEFTBRACKET) + return 0; + while ((type != RIGHTBRACKET || bracketcount > 0) && type != ENDOFFILE ) + { + type = get_token(fp, token, MAXTOKEN); + if (type == LEFTBRACKET) + bracketcount++; + else if (type == RIGHTBRACKET) + bracketcount--; + } + + if (type == RIGHTBRACKET) + return OBJID; + else + return 0; +} + +struct tree * +find_node(const char *name, + struct tree *subtree) /* Unused */ +{ + return( find_tree_node( name, -1 )); +} + +struct module * +find_module(int mid) +{ + struct module *mp; + + for(mp=module_head; mp!=NULL; mp = mp->next) { + if (mp->modid == mid) + break; + } + if (mp != 0) + return mp; + return NULL; +} + + +static char leave_indent[256]; +static int leave_was_simple; + +static void print_mib_leaves(FILE *f, struct tree *tp, int width) +{ struct tree *ntp; + char *ip = leave_indent+strlen(leave_indent)-1; + char last_ipch = *ip; + + *ip = '+'; + if (tp->type == 0) + fprintf(f, "%s--%s(%ld)\n", leave_indent, tp->label, tp->subid); + else { + const char *acc, *typ; + int size = 0; + switch (tp->access) { + case MIB_ACCESS_NOACCESS: acc = "----"; break; + case MIB_ACCESS_READONLY: acc = "-R--"; break; + case MIB_ACCESS_WRITEONLY: acc = "--W-"; break; + case MIB_ACCESS_READWRITE: acc = "-RW-"; break; + case MIB_ACCESS_NOTIFY: acc = "---N"; break; + case MIB_ACCESS_CREATE: acc = "CR--"; break; + default: acc = " "; break; + } + switch (tp->type) { + case TYPE_OBJID: typ = "ObjID "; break; + case TYPE_OCTETSTR: typ = "String "; size = 1; break; + case TYPE_INTEGER: + if (tp->enums) typ = "EnumVal "; + else typ = "Integer "; break; + case TYPE_NETADDR: typ = "NetAddr "; break; + case TYPE_IPADDR: typ = "IpAddr "; break; + case TYPE_COUNTER: typ = "Counter "; break; + case TYPE_GAUGE: typ = "Gauge "; break; + case TYPE_TIMETICKS: typ = "TimeTicks"; break; + case TYPE_OPAQUE: typ = "Opaque "; size = 1; break; + case TYPE_NULL: typ = "Null "; break; + case TYPE_COUNTER64: typ = "Counter64"; break; + case TYPE_BITSTRING: typ = "BitString"; break; + case TYPE_NSAPADDRESS: typ = "NsapAddr "; break; + case TYPE_UINTEGER: typ = "UInteger "; break; + default: typ = " "; break; + } + fprintf(f, "%s-- %s %s %s(%ld)\n", leave_indent, acc, typ, tp->label, tp->subid); + *ip = last_ipch; + if (tp->tc_index >= 0) + fprintf(f, "%s Textual Convention: %s\n", leave_indent, + tclist[tp->tc_index].descriptor); + if (tp->enums) { + struct enum_list *ep = tp->enums; + int cpos = 0, cmax = width - strlen(leave_indent) - 16; + fprintf(f, "%s Values: ", leave_indent); + while (ep) { + char buf[80]; + int bufw; + if (ep != tp->enums) fprintf(f, ", "); + sprintf(buf, "%s(%d)", ep->label, ep->value); + cpos += (bufw = strlen(buf) + 2); + if (cpos >= cmax) { + fprintf(f, "\n%s ", leave_indent); + cpos = bufw; + } + fprintf(f, "%s", buf); + ep = ep->next; + } + fprintf(f, "\n"); + } + if (tp->ranges) { + struct range_list *rp = tp->ranges; + if (size) fprintf(f, "%s Size: ", leave_indent); + else fprintf(f, "%s Range: ", leave_indent); + while (rp) { + if (rp != tp->ranges) fprintf(f, " | "); + if (rp->low == rp->high) fprintf(f, "%d", rp->low); + else fprintf(f, "%d..%d", rp->low, rp->high); + rp = rp->next; + } + fprintf(f, "\n"); + } + } + *ip = last_ipch; + strcat(leave_indent, " |"); + leave_was_simple = tp->type != 0; + + { int i, j, count = 0; + struct leave { + oid id; + struct tree *tp; + } *leaves, *lp; + + for (ntp = tp->child_list; ntp; ntp = ntp->next_peer) count++; + if (count) { + leaves = (struct leave *)calloc(count, sizeof(struct leave)); + if (!leaves) return; + for (ntp = tp->child_list, count = 0; ntp; ntp = ntp->next_peer) { + for (i = 0, lp = leaves; i < count; i++, lp++) + if (lp->id >= ntp->subid) break; + for (j = count; j > i; j--) leaves[j] = leaves[j-1]; + lp->id = ntp->subid; + lp->tp = ntp; + count++; + } + for (i = 1, lp = leaves; i <= count; i++, lp++) { + if (!leave_was_simple || lp->tp->type == 0) + fprintf(f, "%s\n", leave_indent); + if (i == count) ip[3] = ' '; + print_mib_leaves(f, lp->tp, width); + } + free(leaves); + leave_was_simple = 0; + } + } + ip[1] = 0; +} + +void print_mib_tree(FILE *f, struct tree *tp, int width) +{ + leave_indent[0] = ' '; + leave_indent[1] = 0; + leave_was_simple = 1; + print_mib_leaves(f, tp, width); +} + + +/* + * Merge the parsed object identifier with the existing node. + * If there is a problem with the identifier, release the existing node. + */ +static struct node * +merge_parse_objectid(struct node *np, + FILE *fp, + char *name) +{ + struct node *nnp; + + nnp = parse_objectid(fp, name); + if (nnp) { + /* apply last OID sub-identifier data to the information */ + /* already collected for this node. */ + struct node *headp, *nextp; + int ncount = 0; + nextp = headp = nnp; + while (nnp->next) { + nextp = nnp; + ncount++; + nnp = nnp->next; + } + + np->label = nnp->label; + np->subid = nnp->subid; + np->modid = nnp->modid; + np->parent = nnp->parent; + free(nnp); + + if (ncount) { + nextp->next = np; + np = headp; + } + } + else { + free_node(np); np = NULL; + } + + return np; +} + +/* + * transfer data to tree from node + * + * move pointers for alloc'd data from np to tp. + * this prevents them from being freed when np is released. + * parent member is not moved. + * + * CAUTION: nodes may be repeats of existing tree nodes. + * This can happen especially when resolving IMPORT clauses. + * + */ +static void +tree_from_node(struct tree *tp, struct node *np) +{ + free_partial_tree(tp, FALSE); + + tp->label = np->label; np->label = NULL; + tp->enums = np->enums; np->enums = NULL; + tp->ranges = np->ranges; np->ranges = NULL; + tp->indexes = np->indexes; np->indexes = NULL; + tp->hint = np->hint; np->hint = NULL; + tp->units = np->units; np->units = NULL; + tp->description = np->description; np->description = NULL; + + tp->subid = np->subid; + tp->tc_index = np->tc_index; + tp->type = translation_table[np->type]; + tp->access = np->access; + tp->status = np->status; + set_function(tp); +} + diff --git a/packages/net/snmp/lib/current/src/read_config.c b/packages/net/snmp/lib/current/src/read_config.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/read_config.c @@ -0,0 +1,1116 @@ +//========================================================================== +// +// ./lib/current/src/read_config.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * read_config.c + */ + +#include + +#include +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#if HAVE_SYS_PARAM_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#include + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "mib.h" +#include "parse.h" +#include "system.h" +#include "snmp_api.h" +#include "snmp_debug.h" +#include "snmp_logging.h" +#include "snmp_impl.h" +#include "default_store.h" +#include "callback.h" + +#include "read_config.h" +#include "tools.h" + +int config_errors; + +struct config_files *config_files = NULL; + +struct config_line * +register_premib_handler(const char *type, + const char *token, + void (*parser) (const char *, char *), + void (*releaser) (void), + const char *help) +{ + struct config_line *ltmp; + ltmp = register_config_handler(type, token, parser, releaser, help); + if (ltmp != NULL) + ltmp->config_time = PREMIB_CONFIG; + return (ltmp); +} + +struct config_line * +register_app_premib_handler(const char *token, + void (*parser) (const char *, char *), + void (*releaser) (void), + const char *help) +{ + return(register_premib_handler( NULL, token, parser, releaser, help )); +} + +/*******************************************************************-o-****** + * register_config_handler + * + * Parameters: + * *type + * *token + * *parser + * *releaser + * + * Returns: + * Pointer to a new config line entry -OR- NULL on error. + */ +struct config_line * +register_config_handler(const char *type_param, + const char *token, + void (*parser) (const char *, char *), + void (*releaser) (void), + const char *help) +{ + struct config_files **ctmp = &config_files; + struct config_line **ltmp; + const char *type = type_param; + + if ( type == NULL ) + type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE); + + /* + * Find type in current list -OR- create a new file type. + */ + while (*ctmp != NULL && strcmp((*ctmp)->fileHeader, type)) { + ctmp = &((*ctmp)->next); + } + + if (*ctmp == NULL) { + *ctmp = (struct config_files *) + malloc(sizeof(struct config_files)); + if ( !*ctmp ) { + return NULL; + } + + (*ctmp)->next = NULL; + (*ctmp)->start = NULL; + (*ctmp)->fileHeader = strdup(type); + } + + /* + * Find parser type in current list -OR- create a new + * line parser entry. + */ + ltmp = &((*ctmp)->start); + + while (*ltmp != NULL && strcmp((*ltmp)->config_token, token)) { + ltmp = &((*ltmp)->next); + } + + if (*ltmp == NULL) { + *ltmp = (struct config_line *) + malloc(sizeof(struct config_line)); + if ( !*ltmp ) { + return NULL; + } + + (*ltmp)->next = NULL; + (*ltmp)->config_time = NORMAL_CONFIG; + (*ltmp)->parse_line = 0; + (*ltmp)->free_func = 0; + (*ltmp)->config_token = strdup(token); + if (help != NULL) + (*ltmp)->help = strdup(help); + + } + + /* + * Add/Replace the parse/free functions for the given line type + * in the given file type. + */ + (*ltmp)->parse_line = parser; + (*ltmp)->free_func = releaser; + + return (*ltmp); + +} /* end register_config_handler() */ + +struct config_line * +register_app_config_handler(const char *token, + void (*parser) (const char *, char *), + void (*releaser) (void), + const char *help) +{ + return(register_config_handler( NULL, token, parser, releaser, help )); +} + +void +unregister_config_handler(const char *type_param, + const char *token) +{ + struct config_files **ctmp = &config_files; + struct config_line **ltmp, *ltmp2; + const char *type = type_param; + + if ( type == NULL ) + type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE); + + /* find type in current list */ + while (*ctmp != NULL && strcmp((*ctmp)->fileHeader,type)) { + ctmp = &((*ctmp)->next); + } + + if (*ctmp == NULL) { + /* Not found, return. */ + return; + } + + ltmp = &((*ctmp)->start); + if (*ltmp == NULL) { + /* Not found, return. */ + return; + } + if (strcmp((*ltmp)->config_token,token) == 0) { + /* found it at the top of the list */ + (*ctmp)->start = (*ltmp)->next; + free((*ltmp)->config_token); + SNMP_FREE((*ltmp)->help); + free(*ltmp); + return; + } + while ((*ltmp)->next != NULL && strcmp((*ltmp)->next->config_token,token)) { + ltmp = &((*ltmp)->next); + } + if (*ltmp == NULL) { + free((*ltmp)->config_token); + SNMP_FREE((*ltmp)->help); + ltmp2 = (*ltmp)->next->next; + free((*ltmp)->next); + (*ltmp)->next = ltmp2; + } +} + +void +unregister_app_config_handler(const char *token) +{ + unregister_config_handler( NULL, token ); +} + +#ifdef TESTING +void print_config_handlers (void) +{ + struct config_files *ctmp = config_files; + struct config_line *ltmp; + + for(;ctmp != NULL; ctmp = ctmp->next) { + DEBUGMSGTL(("read_config", "read_conf: %s\n", ctmp->fileHeader)); + for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next) + DEBUGMSGTL(("read_config", " %s\n", ltmp->config_token)); + } +} +#endif + +int linecount; +const char *curfilename; + +void read_config_with_type(const char *filename, + const char *type) +{ + struct config_files *ctmp = config_files; + for(;ctmp != NULL && strcmp(ctmp->fileHeader,type); ctmp = ctmp->next); + if (ctmp) + read_config(filename, ctmp->start, EITHER_CONFIG); + else + DEBUGMSGTL(("read_config", "read_config: I have no registrations for type:%s,file:%s\n", + type, filename)); +} + +/*******************************************************************-o-****** + * read_config + * + * Parameters: + * *filename + * *line_handler + * when + * + * Read and process each line in accordance with the list of + * functions. + * + * + * For each line in , search the list of 's + * for an entry that matches the first token on the line. This comparison is + * case insensitive. + * + * For each match, check that is the designated time for the + * function to be executed before processing the line. + */ +void read_config(const char *filename, + struct config_line *line_handler, + int when) +{ + + FILE *ifile; + char line[STRINGMAX], token[STRINGMAX], tmpbuf[STRINGMAX]; + char *cptr; + int i, done; + struct config_line *lptr; + + linecount = 0; + curfilename = filename; + + if ((ifile = fopen(filename, "r")) == NULL) { +#ifdef ENOENT + if (errno == ENOENT) { + DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno))); + } else +#endif /* ENOENT */ +#ifdef EACCES + if (errno == EACCES) { + DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno))); + } else +#endif /* EACCES */ +#if defined(ENOENT) || defined(EACCES) + { + snmp_log_perror(filename); + } +#else /* defined(ENOENT) || defined(EACCES) */ + snmp_log_perror(filename); +#endif /* ENOENT */ + return; + } else { + DEBUGMSGTL(("read_config", "Reading configuration %s\n", filename)); + } + + while (fgets(line, sizeof(line), ifile) != NULL) + { + lptr = line_handler; + linecount++; + cptr = line; + i = strlen(line)-1; + if (line[i] == '\n') + line[i] = 0; + /* check blank line or # comment */ + if ((cptr = skip_white(cptr))) + { + cptr = copy_word(cptr,token); + if (cptr == NULL) { + sprintf(tmpbuf,"Blank line following %s token.", token); + config_perror(tmpbuf); + } else { + for(lptr = line_handler, done=0; + lptr != NULL && !done; + lptr = lptr->next) { + if (!strcasecmp(token,lptr->config_token)) { + if (when == EITHER_CONFIG || lptr->config_time == when) { + DEBUGMSGTL(("read_config", "%s:%d Parsing: %s\n", + filename, linecount, line)); + (*(lptr->parse_line))(token,cptr); + } + done = 1; + } + } + if (!done && when != PREMIB_CONFIG && + !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_NO_TOKEN_WARNINGS)) { + sprintf(tmpbuf,"Unknown token: %s.", token); + config_pwarn(tmpbuf); + } + } + } + } + fclose(ifile); + return; + +} /* end read_config() */ + + + +void +free_config (void) +{ + struct config_files *ctmp = config_files; + struct config_line *ltmp; + + for(;ctmp != NULL; ctmp = ctmp->next) + for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next) + if (ltmp->free_func) + (*(ltmp->free_func))(); +} + +void +read_configs (void) +{ + + char *optional_config = ds_get_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG); + char *type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE); + + DEBUGMSGTL(("read_config","reading normal configuration tokens\n")); + + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS)) + read_config_files(NORMAL_CONFIG); + + /* do this even when the normal above wasn't done */ + if (optional_config && type) + read_config_with_type(optional_config, type); + + snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, + NULL); +} + +void +read_premib_configs (void) +{ + DEBUGMSGTL(("read_config","reading premib configuration tokens\n")); + + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS)) + read_config_files(PREMIB_CONFIG); + + snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, + SNMP_CALLBACK_POST_PREMIB_READ_CONFIG, + NULL); +} + + + + +/*******************************************************************-o-****** + * read_config_files + * + * Parameters: + * when == PREMIB_CONFIG, NORMAL_CONFIG -or- EITHER_CONFIG + * + * + * Traverse the list of config file types, performing the following actions + * for each -- + * + * First, build a search path for config files. If the contents of + * environment variable SNMPCONFPATH are NULL, then use the following + * path list (where the last entry exists only if HOME is non-null): + * + * SNMPSHAREPATH:SNMPLIBPATH:${HOME}/.snmp + * + * Then, In each of these directories, read config files by the name of: + * + * /.conf -AND- + * /.local.conf + * + * where is taken from the config file type structure. + * + * + * PREMIB_CONFIG causes free_config() to be invoked prior to any other action. + * + * + * EXITs if any 'config_errors' are logged while parsing config file lines. + */ +void +read_config_files (int when) +{ +#ifndef ECOSFIXME_NEEDFILESYSTEM + + int i, j; + char configfile[300]; + char *envconfpath, *homepath; + char *cptr1, *cptr2; + char defaultPath[SPRINT_MAX_LEN]; + + struct config_files *ctmp = config_files; + struct config_line *ltmp; + struct stat statbuf; + + if (when == PREMIB_CONFIG) + free_config(); + + /* read all config file types */ + for(;ctmp != NULL; ctmp = ctmp->next) { + + ltmp = ctmp->start; + + /* read the config files */ + if ((envconfpath = getenv("SNMPCONFPATH")) == NULL) { + homepath=getenv("HOME"); + sprintf(defaultPath,"%s%c%s%c%s%s%s%s%c%s", + SNMPCONFPATH, ENV_SEPARATOR_CHAR, + SNMPSHAREPATH, ENV_SEPARATOR_CHAR, SNMPLIBPATH, + ((homepath == NULL) ? "" : ENV_SEPARATOR), + ((homepath == NULL) ? "" : homepath), + ((homepath == NULL) ? "" : "/.snmp"), + ENV_SEPARATOR_CHAR, PERSISTENT_DIRECTORY); + envconfpath = defaultPath; + } + envconfpath = strdup(envconfpath); /* prevent actually writing in env */ + DEBUGMSGTL(("read_config","config path used:%s\n", envconfpath)); + cptr1 = cptr2 = envconfpath; + i = 1; + while (i && *cptr2 != 0) { + while(*cptr1 != 0 && *cptr1 != ENV_SEPARATOR_CHAR) + cptr1++; + if (*cptr1 == 0) + i = 0; + else + *cptr1 = 0; + /* + * for proper persistent storage retrival, we need to read old backup + * copies of the previous storage files. If the application in + * question has died without the proper call to snmp_clean_persistent, + * then we read all the configuration files we can, starting with + * the oldest first. + */ + if (strncmp(cptr2, PERSISTENT_DIRECTORY, + strlen(PERSISTENT_DIRECTORY)) == 0 || + (getenv("SNMP_PERSISTENT_FILE") != NULL && + strncmp(cptr2, getenv("SNMP_PERSISTENT_FILE"), + strlen(getenv("SNMP_PERSISTENT_FILE"))) == 0)) { + /* limit this to the known storage directory only */ + for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) { + sprintf(configfile,"%s/%s.%d.conf",cptr2, ctmp->fileHeader, j); + if (stat(configfile, &statbuf) != 0) { + /* file not there, continue */ + break; + } else { + /* backup exists, read it */ + DEBUGMSGTL(("read_config_files","old config file found: %s, parsing\n", configfile)); + read_config (configfile, ltmp, when); + } + } + } + sprintf(configfile,"%s/%s.conf",cptr2, ctmp->fileHeader); + read_config (configfile, ltmp, when); + sprintf(configfile,"%s/%s.local.conf",cptr2, ctmp->fileHeader); + read_config (configfile, ltmp, when); + cptr2 = ++cptr1; + } + free(envconfpath); + } + + if (config_errors) { + snmp_log(LOG_ERR, "ucd-snmp: %d errors in config file\n", config_errors); +/* exit(1); */ + } +#endif +} + +void read_config_print_usage(const char *lead) +{ + struct config_files *ctmp = config_files; + struct config_line *ltmp; + + if (lead == NULL) + lead = ""; + + for(ctmp = config_files; ctmp != NULL; ctmp = ctmp->next) { + snmp_log(LOG_INFO, "%sIn %s.conf and %s.local.conf:\n", lead, ctmp->fileHeader, + ctmp->fileHeader); + for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next) { + if (ltmp->help != NULL) + snmp_log(LOG_INFO, "%s%s%-15s %s\n", lead, lead, ltmp->config_token, + ltmp->help); + } + } +} + +/*******************************************************************-o-****** + * read_config_store + * + * Parameters: + * *type + * *line + * + * + * Append line to a file named either ENV(SNMP_PERSISTENT_FILE) or + * "/.conf". + * Add a trailing newline to the stored file if necessary. + * + * Intended for use by applications to store permenant configuration + * information generated by sets or persistent counters. + * + */ +void +read_config_store(const char *type, const char *line) +{ +#ifdef PERSISTENT_DIRECTORY + char file[512], *filep; + FILE *fout; +#ifdef PERSISTENT_MASK + mode_t oldmask; +#endif + + /* store configuration directives in the following order of preference: + 1. ENV variable SNMP_PERSISTENT_FILE + 2. configured /.conf + */ + if ((filep = getenv("SNMP_PERSISTENT_FILE")) == NULL) { + sprintf(file,"%s/%s.conf",PERSISTENT_DIRECTORY,type); + filep = file; + } + +#ifdef PERSISTENT_MASK + oldmask = umask(PERSISTENT_MASK); +#endif + if (mkdirhier(filep, AGENT_DIRECTORY_MODE, 1)) { + snmp_log(LOG_ERR, "Failed to create the persistent directory for %s\n", + file); + } + if ((fout = fopen(filep, "a")) != NULL) { + fprintf(fout,line); + if (line[strlen(line)] != '\n') + fprintf(fout,"\n"); + DEBUGMSGTL(("read_config","storing: %s\n",line)); + fclose(fout); + } else { + DEBUGMSGTL(("read_config","open failure")); + } +#ifdef PERSISTENT_MASK + umask(oldmask); +#endif + +#endif +} /* end read_config_store() */ + +void +read_app_config_store(const char *line) +{ + read_config_store(ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE), line); +} + + + + +/*******************************************************************-o-****** + * snmp_save_persistent + * + * Parameters: + * *type + * + * + * Save the file "/.conf" into a backup copy + * called "/.%d.conf", which %d is an + * incrementing number on each call, but less than MAX_PERSISTENT_BACKUPS. + * + * Should be called just before all persistent information is supposed to be + * written to move aside the existing persistent cache. + * snmp_clean_persistent should then be called afterward all data has been + * saved to remove these backup files. + * + * Note: on an rename error, the files are removed rather than saved. + * + */ +void +snmp_save_persistent(const char *type) +{ +#ifndef ECOSFIXME_NEEDFILESYSTEM + + char file[512], fileold[512]; + struct stat statbuf; + int j; + + DEBUGMSGTL(("snmp_save_persistent","saving %s files...\n", type)); + sprintf(file,"%s/%s.conf", PERSISTENT_DIRECTORY, type); + if (stat(file, &statbuf) == 0) { + for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) { + sprintf(fileold,"%s/%s.%d.conf", PERSISTENT_DIRECTORY, type, j); + if (stat(fileold, &statbuf) != 0) { + DEBUGMSGTL(("snmp_save_persistent"," saving old config file: %s -> %s.\n", file, fileold)); + if (rename(file, fileold)) { + unlink(file);/* moving it failed, try nuking it, as leaving + it around is very bad. */ + } + break; + } + } + } +#endif +} + + +/*******************************************************************-o-****** + * snmp_clean_persistent + * + * Parameters: + * *type + * + * + * Unlink all backup files called "/.%d.conf". + * + * Should be called just after we successfull dumped the last of the + * persistent data, to remove the backup copies of previous storage dumps. + * + * XXX Worth overwriting with random bytes first? This would + * ensure that the data is destroyed, even a buffer containing the + * data persists in memory or swap. Only important if secrets + * will be stored here. + */ +void +snmp_clean_persistent(const char *type) +{ +#ifndef ECOSFIXME_NEEDFILESYSTEM + + char file[512]; + struct stat statbuf; + int j; + + DEBUGMSGTL(("snmp_clean_persistent","cleaning %s files...\n", type)); + sprintf(file,"%s/%s.conf",PERSISTENT_DIRECTORY,type); + if (stat(file, &statbuf) == 0) { + for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) { + sprintf(file,"%s/%s.%d.conf", PERSISTENT_DIRECTORY, type, j); + if (stat(file, &statbuf) == 0) { + DEBUGMSGTL(("snmp_clean_persistent"," removing old config file: %s\n", file)); + unlink(file); + } + } + } +#endif +} + + + + +/* config_perror: prints a warning string associated with a file and + line number of a .conf file and increments the error count. */ +void config_perror(const char *string) +{ + config_pwarn(string); + config_errors++; +} + +void config_pwarn(const char *string) +{ + snmp_log(LOG_WARNING, "%s: line %d: %s\n", curfilename, linecount, string); +} + +/* skip all white spaces and return 1 if found something either end of + line or a comment character */ +char *skip_white(char *ptr) +{ + + if (ptr == NULL) return (NULL); + while (*ptr != 0 && isspace(*ptr)) ptr++; + if (*ptr == 0 || *ptr == '#') return (NULL); + return (ptr); +} + +char *skip_not_white(char *ptr) +{ + + if (ptr == NULL) return (NULL); + while (*ptr != 0 && !isspace(*ptr)) ptr++; + if (*ptr == 0 || *ptr == '#') return (NULL); + return (ptr); +} + +char *skip_token(char *ptr) +{ + ptr = skip_white(ptr); + ptr = skip_not_white(ptr); + ptr = skip_white(ptr); + return (ptr); +} + +/* copy_word + copies the next 'token' from 'from' into 'to'. + currently a token is anything seperate by white space + or within quotes (double or single) (i.e. "the red rose" + is one token, \"the red rose\" is three tokens) + a '\' character will allow a quote character to be treated + as a regular character + It returns a pointer to first non-white space after the end of the token + being copied or to 0 if we reach the end.*/ + +char *copy_word(char *from, char *to) +{ + char quote; + if ( (*from == '\"') || (*from =='\'') ){ + quote = *(from++); + while ( (*from != quote) && (*from != 0) ) { + if ((*from == '\\') && (*(from+1) != 0)) { + *to++ = *(from+1); + from = from +2; + } + else *to++ = *from++; + } + if (*from == 0) { + DEBUGMSGTL(("read_config_copy_word", + "no end quote found in config string\n")); + } else from++; + } + else { + while (*from != 0 && !isspace(*from)) { + if ((*from == '\\') && (*(from+1) != 0)) { + *to++ = *(from+1); + from = from +2; + } + else *to++ = *from++; + } + } + *to = 0; + from = skip_white(from); + return(from); +} /* copy_word */ + +/* read_config_save_octet_string(): saves an octet string as a length + followed by a string of hex */ +char *read_config_save_octet_string(char *saveto, u_char *str, size_t len) { + int i; + if (str != NULL) { + sprintf(saveto, "0x"); + saveto += 2; + for(i = 0; i < (int)len; i++) { + sprintf(saveto,"%02x", str[i]); + saveto = saveto + 2; + } + return saveto; + } else { + sprintf(saveto,"\"\""); + saveto += 2; + } + return saveto; +} + +/* read_config_read_octet_string(): reads an octet string that was + saved by the read_config_save_octet_string() function */ +char *read_config_read_octet_string(char *readfrom, u_char **str, size_t *len) { + u_char *cptr=NULL; + char *cptr1; + u_int tmp; + int i; + + if (readfrom == NULL || str == NULL) + return NULL; + + if (strncasecmp(readfrom,"0x",2) == 0) { + /* A hex string submitted. How long? */ + readfrom += 2; + cptr1 = skip_not_white(readfrom); + if (cptr1) + *len = (cptr1 - readfrom); + else + *len = strlen(readfrom); + + if (*len % 2) { + DEBUGMSGTL(("read_config_read_octet_string","invalid hex string: wrong length")); + return NULL; + } + *len = *len / 2; + + /* malloc data space if needed */ + if (*str == NULL) { + if (*len == 0) { + /* null length string found */ + cptr = NULL; + + } else if (*len > 0 && (str == NULL || (cptr = (u_char *)malloc(*len)) == NULL)) { + return NULL; + } + *str = cptr; + } else { + cptr = *str; + } + + /* copy data */ + for(i = 0; i < (int)*len; i++) { + sscanf(readfrom,"%2x",&tmp); + *cptr++ = (u_char) tmp; + readfrom += 2; + } + readfrom = skip_white(readfrom); + } else { + /* Normal string */ + + /* malloc data space if needed */ + if (*str == NULL) { + char buf[SNMP_MAXBUF]; + readfrom = copy_word(readfrom, buf); + + *len = strlen(buf); + /* malloc an extra space to add a null */ + if (*len > 0 && (str == NULL || + (cptr = (u_char *) malloc(*len + 1)) + == NULL)) + return NULL; + *str = cptr; + if (cptr) + memcpy(cptr, buf, (*len+1)); + } else { + readfrom = copy_word(readfrom, (char *)*str); + } + } + + return readfrom; +} + + +/* read_config_save_objid(): saves an objid as a numerical string */ +char *read_config_save_objid(char *saveto, oid *objid, size_t len) { + int i; + + if (len == 0) { + strcat(saveto, "NULL"); + saveto += strlen(saveto); + return saveto; + } + + /* in case len=0, this makes it easier to read it back in */ + for(i=0; i < (int)len; i++) { + sprintf(saveto,".%ld", objid[i]); + saveto += strlen(saveto); + } + return saveto; +} + +/* read_config_read_objid(): reads an objid from a format saved by the above */ +char *read_config_read_objid(char *readfrom, oid **objid, size_t *len) { + + if (objid == NULL || readfrom == NULL) + return NULL; + + if (*objid != NULL) { + char buf[SPRINT_MAX_LEN]; + + if (strncmp(readfrom,"NULL",4) == 0) { + /* null length oid */ + *len = 0; + } else { + /* read_objid is touchy with trailing stuff */ + copy_word(readfrom, buf); + + /* read the oid into the buffer passed to us */ + if (!read_objid(buf, *objid, len)) { + DEBUGMSGTL(("read_config_read_objid","Invalid OID")); + return NULL; + } + } + + readfrom = skip_token(readfrom); + } else { + if (strncmp(readfrom,"NULL",4) == 0) { + /* null length oid */ + *len = 0; + readfrom = skip_token(readfrom); + } else { + /* space needs to be malloced. Call ourself recursively to figure + out how long the oid actually is */ + oid obuf[MAX_OID_LEN]; + size_t obuflen = MAX_OID_LEN; + oid *oidp = obuf; + oid **oidpp = &oidp; /* done this way for odd, untrue, gcc warnings */ + + readfrom = read_config_read_objid(readfrom, oidpp, &obuflen); + + /* Then malloc and copy the results */ + *len = obuflen; + if (*len > 0 && (*objid = (oid*)malloc(*len * sizeof(oid))) == NULL) + return NULL; + + if (obuflen > 0) + memcpy(*objid, obuf, obuflen*sizeof(oid)); + } + } + return readfrom; +} + +/* read_config_read_data(): + reads data of a given type from a token(s) on a configuration line. + + Returns: character pointer to the next token in the configuration line. + NULL if none left. + NULL if an unknown type. +*/ +char *read_config_read_data(int type, char *readfrom, void *dataptr, size_t *len) { + + int *intp; + char **charpp; + oid **oidpp; + + if (dataptr == NULL || readfrom == NULL) + return NULL; + + switch(type) { + case ASN_INTEGER: + intp = (int *) dataptr; + *intp = atoi(readfrom); + readfrom = skip_token(readfrom); + return readfrom; + + case ASN_OCTET_STR: + charpp = (char **) dataptr; + return read_config_read_octet_string(readfrom, (u_char **) charpp, len); + + case ASN_OBJECT_ID: + oidpp = (oid **) dataptr; + return read_config_read_objid(readfrom, oidpp, len); + + default: + DEBUGMSGTL(("read_config_read_data","Fail: Unknown type: %d", type)); + return NULL; + } + return NULL; +} + +/* read_config_read_data(): + reads data of a given type from a token(s) on a configuration line. + + Returns: character pointer to the next token in the configuration line. + NULL if none left. + NULL if an unknown type. +*/ +char *read_config_store_data(int type, char *storeto, void *dataptr, size_t *len) { + + int *intp; + u_char **charpp; + oid **oidpp; + + if (dataptr == NULL || storeto == NULL) + return NULL; + + switch(type) { + case ASN_INTEGER: + intp = (int *) dataptr; + sprintf(storeto," %d", *intp); + return (storeto + strlen(storeto)); + + case ASN_OCTET_STR: + charpp = (u_char **) dataptr; + return read_config_save_octet_string(storeto, *charpp, *len); + + case ASN_OBJECT_ID: + oidpp = (oid **) dataptr; + return read_config_save_objid(storeto, *oidpp, *len); + + default: + DEBUGMSGTL(("read_config_store_data","Fail: Unknown type: %d", type)); + return NULL; + } + return NULL; +} diff --git a/packages/net/snmp/lib/current/src/scapi.c b/packages/net/snmp/lib/current/src/scapi.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/scapi.c @@ -0,0 +1,809 @@ +//========================================================================== +// +// ./lib/current/src/scapi.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * scapi.c + * + */ + +#include + +#include +#if HAVE_WINSOCK_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef USE_INTERNAL_MD5 +#include "md5.h" +#endif +#include "asn1.h" +#include "tools.h" +#include "snmp_api.h" +#include "callback.h" +#include "snmpusm.h" +#include "keytools.h" +#include "snmp_debug.h" +#include "scapi.h" +#include "snmp_impl.h" +#include "system.h" + +#include "transform_oids.h" + +#ifdef USE_OPENSSL +#include +#include +#include +#endif + +#ifdef QUITFUN +#undef QUITFUN +#define QUITFUN(e, l) \ + if (e != SNMPERR_SUCCESS) { \ + rval = SNMPERR_SC_GENERAL_FAILURE; \ + goto l ; \ + } +#endif + + +/* + sc_get_properlength(oid *hashtype, u_int hashtype_len): + + Given a hashing type ("hashtype" and its length hashtype_len), return + the length of the hash result. + + Returns either the length or SNMPERR_GENERR for an unknown hashing type. +*/ +int +sc_get_properlength(oid *hashtype, u_int hashtype_len) +{ + DEBUGTRACE; + /* + * Determine transform type hash length. + */ + if ( ISTRANSFORM(hashtype, HMACMD5Auth)) { + return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5); + } + else if ( ISTRANSFORM(hashtype, HMACSHA1Auth) ) { + return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1); + } + return SNMPERR_GENERR; +} + + +/*******************************************************************-o-****** + * sc_init + * + * Returns: + * SNMPERR_SUCCESS Success. + */ +int +sc_init(void) +{ + int rval = SNMPERR_SUCCESS; + +#ifndef USE_OPENSSL +#ifdef USE_INTERNAL_MD5 + struct timeval tv; + + DEBUGTRACE; + + gettimeofday(&tv,(struct timezone *)0); + + srandom(tv.tv_sec ^ tv.tv_usec); +#else + rval = SNMPERR_SC_NOT_CONFIGURED; +#endif + /* XXX ogud: The only reason to do anything here with openssl is to + * XXX ogud: seed random number generator + */ +#endif /* ifndef USE_OPENSSL */ + return rval; +} /* end sc_init() */ + +/*******************************************************************-o-****** + * sc_random + * + * Parameters: + * *buf Pre-allocated buffer. + * *buflen Size of buffer. + * + * Returns: + * SNMPERR_SUCCESS Success. + */ +int +sc_random(u_char *buf, size_t *buflen) +#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) +{ + int rval = SNMPERR_SUCCESS; +#ifdef USE_INTERNAL_MD5 + int i; + int rndval; + u_char *ucp = buf; +#endif + + DEBUGTRACE; + +#ifdef USE_OPENSSL + RAND_bytes(buf, *buflen); /* will never fail */ +#else /* USE_INTERNAL_MD5 */ + /* fill the buffer with random integers. Note that random() + is defined in config.h and may not be truly the random() + system call if something better existed */ + rval = *buflen - *buflen%sizeof(rndval); + for(i = 0; i < rval; i += sizeof(rndval)) { + rndval = random(); + memcpy(ucp, &rndval, sizeof(rndval)); + ucp += sizeof(rndval); + } + + rndval = random(); + memcpy(ucp, &rndval, *buflen%sizeof(rndval)); + + rval = SNMPERR_SUCCESS; +#endif /* USE_OPENSSL */ + return rval; + +} /* end sc_random() */ + +#else +_SCAPI_NOT_CONFIGURED +#endif /* */ + + + +/*******************************************************************-o-****** + * sc_generate_keyed_hash + * + * Parameters: + * authtype Type of authentication transform. + * authtypelen + * *key Pointer to key (Kul) to use in keyed hash. + * keylen Length of key in bytes. + * *message Pointer to the message to hash. + * msglen Length of the message. + * *MAC Will be returned with allocated bytes containg hash. + * *maclen Length of the hash buffer in bytes; also indicates + * whether the MAC should be truncated. + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_GENERR All errs + * + * + * A hash of the first msglen bytes of message using a keyed hash defined + * by authtype is created and stored in MAC. MAC is ASSUMED to be a buffer + * of at least maclen bytes. If the length of the hash is greater than + * maclen, it is truncated to fit the buffer. If the length of the hash is + * less than maclen, maclen set to the number of hash bytes generated. + * + * ASSUMED that the number of hash bits is a multiple of 8. + */ +int +sc_generate_keyed_hash( oid *authtype, size_t authtypelen, + u_char *key, u_int keylen, + u_char *message, u_int msglen, + u_char *MAC, size_t *maclen) +#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) +{ + int rval = SNMPERR_SUCCESS; + int properlength; + + u_char buf[SNMP_MAXBUF_SMALL]; +#if defined(USE_OPENSSL) + int buf_len = sizeof(buf); + u_char *bufp = buf; +#endif + + DEBUGTRACE; + +#ifdef SNMP_TESTING_CODE +{ + int i; + DEBUGMSG(("sc_generate_keyed_hash", "sc_generate_keyed_hash(): key=0x")); + for(i=0; i< keylen; i++) + DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff)); + DEBUGMSG(("sc_generate_keyed_hash"," (%d)\n", keylen)); +} +#endif /* SNMP_TESTING_CODE */ + +/* + * Sanity check. + */ + if ( !authtype || !key || !message || !MAC || !maclen + || (keylen<=0) || (msglen<=0) || (*maclen<=0) + || (authtypelen != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); + } + + properlength = sc_get_properlength(authtype, authtypelen); + if (properlength == SNMPERR_GENERR) + return properlength; + + if ( ((int)keylen < properlength) ) { + QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); + } + + +#ifdef USE_OPENSSL + /* + * Determine transform type. + */ + if (ISTRANSFORM(authtype, HMACMD5Auth)) + HMAC(EVP_md5(), key, keylen, message, msglen, + buf, &buf_len); + else if (ISTRANSFORM(authtype, HMACSHA1Auth)) + HMAC(EVP_sha1(), key, keylen, message, msglen, + buf, &buf_len); + else { + QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); + } + if (buf_len != properlength) { + QUITFUN(rval, sc_generate_keyed_hash_quit); + } + if (*maclen > buf_len) + *maclen = buf_len; + memcpy(MAC, buf, *maclen); +#else + if ((int)*maclen > properlength) + *maclen = properlength; + if (MDsign(message, msglen, MAC, *maclen, key, keylen)) { + rval = SNMPERR_GENERR; + goto sc_generate_keyed_hash_quit; + } +#endif /* USE_OPENSSL */ + +#ifdef SNMP_TESTING_CODE + { + char *s; + int len = binary_to_hex(MAC, *maclen, &s); + + DEBUGMSGTL(("scapi","Full v3 message hash: %s\n", s)); + SNMP_ZERO(s, len); + SNMP_FREE(s); + } +#endif + + sc_generate_keyed_hash_quit: + SNMP_ZERO(buf, SNMP_MAXBUF_SMALL); + return rval; +} /* end sc_generate_keyed_hash() */ + +#else +_SCAPI_NOT_CONFIGURED +#endif /* */ + + +/* sc_hash(): a generic wrapper around whatever hashing package we are using. + + IN: + hashtype - oid pointer to a hash type + hashtypelen - length of oid pointer + buf - u_char buffer to be hashed + buf_len - integer length of buf data + MAC_len - length of the passed MAC buffer size. + + OUT: + MAC - pre-malloced space to store hash output. + MAC_len - length of MAC output to the MAC buffer. + + Returns: + SNMPERR_SUCCESS Success. + SNMP_SC_GENERAL_FAILURE Any error. +*/ + +int +sc_hash(oid *hashtype, size_t hashtypelen, u_char *buf, size_t buf_len, + u_char *MAC, size_t *MAC_len) +#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) +{ + int rval = SNMPERR_SUCCESS; + +#ifdef USE_OPENSSL + EVP_MD *hash(void); + HMAC_CTX *c = NULL; +#endif + + DEBUGTRACE; + + if (hashtype == NULL || hashtypelen < 0 || buf == NULL || + buf_len < 0 || MAC == NULL || MAC_len == NULL || + (int)(*MAC_len) < sc_get_properlength(hashtype, hashtypelen)) + return (SNMPERR_GENERR); + +#ifdef USE_OPENSSL + /* + * Determine transform type. + */ + c = malloc(sizeof(HMAC_CTX)); + if (c == NULL) + return (SNMPERR_GENERR); + + if (ISTRANSFORM(hashtype, HMACMD5Auth)) { + EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_md5()); + } + else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { + EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_sha1()); + } + else { + return(SNMPERR_GENERR); + } + EVP_DigestUpdate(&c->md_ctx, buf, buf_len); + EVP_DigestFinal(&(c->md_ctx), MAC, MAC_len); + free(c); + return (rval); +#else /* USE_INTERNAL_MD5 */ + + if (MDchecksum(buf, buf_len, MAC, *MAC_len)) { + return SNMPERR_GENERR; + } + if (*MAC_len > 16) + *MAC_len = 16; + return SNMPERR_SUCCESS; + +#endif /* USE_OPENSSL */ +} +#else /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */ +_SCAPI_NOT_CONFIGURED +#endif /* !defined(USE_OPENSSL) && !defined(USE_INTERNAL_MD5) */ + + + +/*******************************************************************-o-****** + * sc_check_keyed_hash + * + * Parameters: + * authtype Transform type of authentication hash. + * *key Key bits in a string of bytes. + * keylen Length of key in bytes. + * *message Message for which to check the hash. + * msglen Length of message. + * *MAC Given hash. + * maclen Length of given hash; indicates truncation if it is + * shorter than the normal size of output for + * given hash transform. + * Returns: + * SNMPERR_SUCCESS Success. + * SNMP_SC_GENERAL_FAILURE Any error + * + * + * Check the hash given in MAC against the hash of message. If the length + * of MAC is less than the length of the transform hash output, only maclen + * bytes are compared. The length of MAC cannot be greater than the + * length of the hash transform output. + */ +int +sc_check_keyed_hash( oid *authtype, size_t authtypelen, + u_char *key, u_int keylen, + u_char *message, u_int msglen, + u_char *MAC, u_int maclen) +#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL) +{ + int rval = SNMPERR_SUCCESS; + size_t buf_len = SNMP_MAXBUF_SMALL; + + u_char buf[SNMP_MAXBUF_SMALL]; + + DEBUGTRACE; + +#ifdef SNMP_TESTING_CODE +{ + int i; + DEBUGMSG(("scapi", "sc_check_keyed_hash(): key=0x")); + for(i=0; i< keylen; i++) + DEBUGMSG(("scapi", "%02x", key[i] & 0xff)); + DEBUGMSG(("scapi"," (%d)\n", keylen)); +} +#endif /* SNMP_TESTING_CODE */ + + /* + * Sanity check. + */ + if ( !authtype || !key || !message || !MAC + || (keylen<=0) || (msglen<=0) || (maclen<=0) + || (authtypelen != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit); + } + + + /* + * Generate a full hash of the message, then compare + * the result with the given MAC which may shorter than + * the full hash length. + */ + rval = sc_generate_keyed_hash( authtype, authtypelen, + key, keylen, + message, msglen, + buf, &buf_len); + QUITFUN(rval, sc_check_keyed_hash_quit); + + if (maclen > msglen) { + QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit); + + } else if ( memcmp(buf, MAC, maclen) != 0 ) { + QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit); + } + + +sc_check_keyed_hash_quit: + SNMP_ZERO(buf, SNMP_MAXBUF_SMALL); + + return rval; + +} /* end sc_check_keyed_hash() */ + +#else +_SCAPI_NOT_CONFIGURED +#endif /* USE_INTERNAL_MD5 */ + + + +/*******************************************************************-o-****** + * sc_encrypt + * + * Parameters: + * privtype Type of privacy cryptographic transform. + * *key Key bits for crypting. + * keylen Length of key (buffer) in bytes. + * *iv IV bits for crypting. + * ivlen Length of iv (buffer) in bytes. + * *plaintext Plaintext to crypt. + * ptlen Length of plaintext. + * *ciphertext Ciphertext to crypt. + * *ctlen Length of ciphertext. + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_SC_NOT_CONFIGURED Encryption is not supported. + * SNMPERR_SC_GENERAL_FAILURE Any other error + * + * + * Encrypt plaintext into ciphertext using key and iv. + * + * ctlen contains actual number of crypted bytes in ciphertext upon + * successful return. + */ +int +sc_encrypt( oid *privtype, size_t privtypelen, + u_char *key, u_int keylen, + u_char *iv, u_int ivlen, + u_char *plaintext, u_int ptlen, + u_char *ciphertext, size_t *ctlen) +#if defined(USE_OPENSSL) +{ + int rval = SNMPERR_SUCCESS; + u_int transform, + properlength, + properlength_iv; + u_char pad_block[32]; /* bigger than anything I need */ + u_char my_iv[32]; /* ditto */ + int pad, plast, pad_size; + des_key_schedule key_sch; + des_cblock key_struct; + + DEBUGTRACE; + + /* + * Sanity check. + */ +#if !defined(SCAPI_AUTHPRIV) + return SNMPERR_SC_NOT_CONFIGURED; +#endif + + if ( !privtype || !key || !iv || !plaintext || !ciphertext || !ctlen + || (keylen<=0) || (ivlen<=0) || (ptlen<=0) || (*ctlen<=0) + || (privtypelen != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); + } + else if ( ptlen >= *ctlen) { + QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); + } + + +#ifdef SNMP_TESTING_CODE +{ + char buf[SNMP_MAXBUF]; + + sprint_hexstring(buf, iv, ivlen); + DEBUGMSGTL(("scapi", "encrypt: IV: %s/ ", buf)); + sprint_hexstring(buf, key, keylen); + DEBUGMSG(("scapi","%s\n", buf)); + + sprint_hexstring(buf, plaintext, 16); + DEBUGMSGTL(("scapi","encrypt: string: %s\n", buf)); +} +#endif /* SNMP_TESTING_CODE */ + + + /* + * Determine privacy transform. + */ + if ( ISTRANSFORM(privtype, DESPriv) ) { + properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); + properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); + pad_size = properlength; + } else { + QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); + } + + if ( (keylen *ctlen) { + QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); /* not enough space */ + } + memset(pad_block, 0, sizeof(pad_block)); + plast = (int) ptlen - (pad_size - pad); + if (pad > 0) /* copy data into pad block if needed */ + memcpy( pad_block, plaintext + plast, pad_size - pad); + memset(&pad_block[pad_size-pad], pad, pad); /* filling in padblock */ + + memset(my_iv, 0, sizeof(my_iv)); + + if ( ISTRANSFORM(privtype, DESPriv) ) { + memcpy(key_struct, key, sizeof(key_struct)); + (void) des_key_sched(&key_struct, key_sch); + + memcpy(my_iv, iv, ivlen); + /* encrypt the data */ + des_ncbc_encrypt(plaintext, ciphertext, plast, key_sch, + (des_cblock *) &my_iv, DES_ENCRYPT); + /* then encrypt the pad block */ + des_ncbc_encrypt(pad_block, ciphertext+plast, pad_size, + key_sch, (des_cblock *)&my_iv, DES_ENCRYPT); + *ctlen = plast + pad_size; + } +sc_encrypt_quit: + /* clear memory just in case */ + memset(my_iv, 0, sizeof(my_iv)); + memset(pad_block, 0, sizeof(pad_block)); + memset(key_struct, 0, sizeof(key_struct)); + memset(key_sch, 0, sizeof(key_sch)); + return rval; + +} /* end sc_encrypt() */ + +#else +{ +# if USE_INTERNAL_MD5 + { + DEBUGMSGTL(("scapi","Encrypt function not defined.\n")); + return SNMPERR_SC_GENERAL_FAILURE; + } + +# else + _SCAPI_NOT_CONFIGURED + +# endif /* USE_INTERNAL_MD5 */ + } +#endif /* */ + + + +/*******************************************************************-o-****** + * sc_decrypt + * + * Parameters: + * privtype + * *key + * keylen + * *iv + * ivlen + * *ciphertext + * ctlen + * *plaintext + * *ptlen + * + * Returns: + * SNMPERR_SUCCESS Success. + * SNMPERR_SC_NOT_CONFIGURED Encryption is not supported. + * SNMPERR_SC_GENERAL_FAILURE Any other error + * + * + * Decrypt ciphertext into plaintext using key and iv. + * + * ptlen contains actual number of plaintext bytes in plaintext upon + * successful return. + */ +int +sc_decrypt( oid *privtype, size_t privtypelen, + u_char *key, u_int keylen, + u_char *iv, u_int ivlen, + u_char *ciphertext, u_int ctlen, + u_char *plaintext, size_t *ptlen) +#ifdef USE_OPENSSL +{ + + int rval = SNMPERR_SUCCESS; + int i, j; + u_char *my_iv[32]; + des_key_schedule key_sch; + des_cblock key_struct; + u_int properlength, + properlength_iv; + + DEBUGTRACE; + + if ( !privtype || !key || !iv || !plaintext || !ciphertext || !ptlen + || (ctlen<=0) || (*ptlen<=0) || (*ptlen < ctlen) + || (privtypelen != USM_LENGTH_OID_TRANSFORM) ) + { + QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); + } + + +#ifdef SNMP_TESTING_CODE +{ + char buf[SNMP_MAXBUF]; + + sprint_hexstring(buf, iv, ivlen); + DEBUGMSGTL(("scapi", "decrypt: IV: %s/ ", buf)); + sprint_hexstring(buf, key, keylen); + DEBUGMSG(("scapi","%s\n", buf)); +} +#endif /* SNMP_TESTING_CODE */ + + /* + * Determine privacy transform. + */ + if ( ISTRANSFORM(privtype, DESPriv) ) { + properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); + properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); + + } else { + QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); + } + + if ( (keylen from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * Simple Network Management Protocol (RFC 1067). + * + */ +/********************************************************************** + Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#include +#include + +#ifdef KINETICS +#include "gw.h" +#include "ab.h" +#include "inet.h" +#include "fp4/cmdmacro.h" +#include "fp4/pbuf.h" +#include "glob.h" +#endif + +#include +#include + +#include +#ifdef HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#ifndef NULL +#define NULL 0 +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#ifdef vms +#include +#endif + +#include "asn1.h" +#include "snmp.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "snmp_logging.h" +#include "mib.h" + +void +xdump(const u_char *cp, + size_t length, + const char *prefix) +{ + int col, count; + char *buffer; + + buffer=(char *)malloc(strlen(prefix)+80); + if (!buffer) { + snmp_log(LOG_NOTICE, "xdump: malloc failed. packet-dump skipped\n"); + return; + } + + count = 0; + while(count < (int)length){ + strcpy(buffer, prefix); + sprintf (buffer+strlen(buffer), "%.4d: ", count); + + for(col = 0; ((count + col) < (int)length) && col < 16; col++){ + sprintf(buffer+strlen(buffer), "%02X ", cp[count + col]); + if (col % 4 == 3) strcat(buffer, " "); + } + for(;col < 16;col++){ /* pad end of buffer with zeros */ + strcat(buffer, " "); + if (col % 4 == 3) strcat(buffer, " "); + } + strcat(buffer, " "); + for(col = 0; ((count + col) < (int)length) && col < 16; col++){ + buffer[col+60]=isprint(cp[count+col])?cp[count+col]:'.'; + } + buffer[col+60]='\n'; + buffer[col+60+1]=0; + snmp_log(LOG_DEBUG, "%s", buffer); + count += col; + } + snmp_log(LOG_DEBUG, "\n"); + free(buffer); + +} /* end xdump() */ + +/* + u_char * snmp_parse_var_op( + u_char *data IN - pointer to the start of object + oid *var_name OUT - object id of variable + int *var_name_len IN/OUT - length of variable name + u_char *var_val_type OUT - type of variable (int or octet string) (one byte) + int *var_val_len OUT - length of variable + u_char **var_val OUT - pointer to ASN1 encoded value of variable + int *listlength IN/OUT - number of valid bytes left in var_op_list +*/ + +u_char * +snmp_parse_var_op(u_char *data, + oid *var_name, + size_t *var_name_len, + u_char *var_val_type, + size_t *var_val_len, + u_char **var_val, + size_t *listlength) +{ + u_char var_op_type; + size_t var_op_len = *listlength; + u_char *var_op_start = data; + + data = asn_parse_sequence(data, &var_op_len, &var_op_type, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), "var_op"); + if (data == NULL){ + /* msg detail is set */ + return NULL; + } + data = asn_parse_objid(data, &var_op_len, &var_op_type, var_name, var_name_len); + if (data == NULL){ + ERROR_MSG("No OID for variable"); + return NULL; + } + if (var_op_type != (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) + return NULL; + *var_val = data; /* save pointer to this object */ + /* find out what type of object this is */ + data = asn_parse_header(data, &var_op_len, var_val_type); + if (data == NULL){ + ERROR_MSG("No header for value"); + return NULL; + } + /* XXX no check for type! */ + *var_val_len = var_op_len; + data += var_op_len; + *listlength -= (int)(data - var_op_start); + return data; +} + +/* + u_char * snmp_build_var_op( + u_char *data IN - pointer to the beginning of the output buffer + oid *var_name IN - object id of variable + int *var_name_len IN - length of object id + u_char var_val_type IN - type of variable + int var_val_len IN - length of variable + u_char *var_val IN - value of variable + int *listlength IN/OUT - number of valid bytes left in + output buffer +*/ + +u_char * +snmp_build_var_op(u_char *data, + oid *var_name, + size_t *var_name_len, + u_char var_val_type, + size_t var_val_len, + u_char *var_val, + size_t *listlength) +{ + size_t dummyLen, headerLen; + u_char *dataPtr; + + dummyLen = *listlength; + dataPtr = data; +#if 0 + data = asn_build_sequence(data, &dummyLen, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); + if (data == NULL){ + return NULL; + } +#endif + if (dummyLen < 4) + return NULL; + data += 4; + dummyLen -=4; + + headerLen = data - dataPtr; + *listlength -= headerLen; + data = asn_build_objid(data, listlength, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + var_name, *var_name_len); + if (data == NULL){ + ERROR_MSG("Can't build OID for variable"); + return NULL; + } + switch(var_val_type){ + case ASN_INTEGER: + data = asn_build_int(data, listlength, var_val_type, + (long *)var_val, var_val_len); + break; + case ASN_GAUGE: + case ASN_COUNTER: + case ASN_TIMETICKS: + case ASN_UINTEGER: + data = asn_build_unsigned_int(data, listlength, var_val_type, + (u_long *)var_val, var_val_len); + break; +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_COUNTER64: + case ASN_OPAQUE_U64: +#endif + case ASN_COUNTER64: + data = asn_build_unsigned_int64(data, listlength, var_val_type, + (struct counter64 *)var_val, + var_val_len); + break; + case ASN_OCTET_STR: + case ASN_IPADDRESS: + case ASN_OPAQUE: + case ASN_NSAP: + data = asn_build_string(data, listlength, var_val_type, + var_val, var_val_len); + break; + case ASN_OBJECT_ID: + data = asn_build_objid(data, listlength, var_val_type, + (oid *)var_val, var_val_len / sizeof(oid)); + break; + case ASN_NULL: + data = asn_build_null(data, listlength, var_val_type); + break; + case ASN_BIT_STR: + data = asn_build_bitstring(data, listlength, var_val_type, + var_val, var_val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + data = asn_build_null(data, listlength, var_val_type); + break; +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_FLOAT: + data = asn_build_float(data, listlength, var_val_type, + (float *) var_val, var_val_len); + break; + case ASN_OPAQUE_DOUBLE: + data = asn_build_double(data, listlength, var_val_type, + (double *) var_val, var_val_len); + break; + case ASN_OPAQUE_I64: + data = asn_build_signed_int64(data, listlength, var_val_type, + (struct counter64 *) var_val, + var_val_len); + break; +#endif /* OPAQUE_SPECIAL_TYPES */ + default: + ERROR_MSG("wrong type"); + return NULL; + } + if (data == NULL){ + ERROR_MSG("Can't build value"); + return NULL; + } + dummyLen = (data - dataPtr) - headerLen; + + asn_build_sequence(dataPtr, &dummyLen, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen); + return data; +} diff --git a/packages/net/snmp/lib/current/src/snmp_alarm.c b/packages/net/snmp/lib/current/src/snmp_alarm.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmp_alarm.c @@ -0,0 +1,305 @@ +//========================================================================== +// +// ./lib/current/src/snmp_alarm.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* snmp_alarm.c: generic library based alarm timers for various parts + of an application */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_debug.h" +#include "tools.h" +#include "default_store.h" +#include "callback.h" +#include "snmp_alarm.h" + +static struct snmp_alarm *thealarms; +static int start_alarms = 0; +static unsigned int regnum = 1; + +int +init_alarm_post_config(int majorid, int minorid, void *serverarg, + void *clientarg) { + start_alarms = 1; + set_an_alarm(); + return SNMPERR_SUCCESS; +} + +void +init_snmp_alarm(void) { + start_alarms = 0; + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, + init_alarm_post_config, NULL); +} + +void +sa_update_entry(struct snmp_alarm *alrm) { + if (alrm->seconds == 0) { + DEBUGMSGTL(("snmp_alarm_update_entry","illegal 0 length alarm timer specified\n")); + return; /* illegal */ + } + if (alrm->lastcall == 0) { + /* never been called yet, call seconds from now. */ + alrm->lastcall = time(NULL); + alrm->nextcall = alrm->lastcall + alrm->seconds; + } else if (alrm->nextcall == 0) { + /* We've been called but not reset for the next? call */ + if ((alrm->flags & SA_REPEAT) == SA_REPEAT) { + alrm->nextcall = alrm->lastcall + alrm->seconds; + } else { + /* single time call, remove it */ + snmp_alarm_unregister(alrm->clientreg); + } + } +} + +void +snmp_alarm_unregister(unsigned int clientreg) { + struct snmp_alarm *sa_ptr, *alrm=NULL; + + if (thealarms == NULL) + return; + + if (clientreg == thealarms->clientreg) { + alrm = thealarms; + thealarms = alrm->next; + } + else { + for(sa_ptr = thealarms; + sa_ptr != NULL && sa_ptr->next->clientreg != clientreg; + sa_ptr = sa_ptr->next); + if (sa_ptr) { + if (sa_ptr->next) { + alrm = sa_ptr->next; + sa_ptr->next = sa_ptr->next->next; + } + } + } + + /* Note: do not free the clientarg, its the clients responsibility */ + if (alrm) + free(alrm); +} + + +struct snmp_alarm * +sa_find_next(void) { + struct snmp_alarm *sa_ptr, *sa_ret = NULL; + for(sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_ptr->next) { + if (sa_ret == NULL || sa_ptr->nextcall < sa_ret->nextcall) + sa_ret = sa_ptr; + } + return sa_ret; +} + +void +run_alarms(void) { + int done=0; + struct snmp_alarm *sa_ptr; + + /* loop through everything we have repeatedly looking for the next + thing to call until all events are finally in the future again */ + DEBUGMSGTL(("snmp_alarm_run_alarms","looking for alarms to run...\n")); + while(done == 0) { + sa_ptr = sa_find_next(); + if (sa_ptr == NULL) + return; + if (sa_ptr->nextcall <= time(NULL)) { + DEBUGMSGTL(("snmp_alarm_run_alarms"," running alarm %d\n", + sa_ptr->clientreg)); + (*(sa_ptr->thecallback))(sa_ptr->clientreg, sa_ptr->clientarg); + DEBUGMSGTL(("snmp_alarm_run_alarms"," ... done\n")); + sa_ptr->lastcall = time(NULL); + sa_ptr->nextcall = 0; + sa_update_entry(sa_ptr); + } else { + done = 1; + } + } + DEBUGMSGTL(("snmp_alarm_run_alarms","Done.\n")); +} + + +RETSIGTYPE +alarm_handler(int a) { + run_alarms(); + set_an_alarm(); +} + +int +get_next_alarm_delay_time(void) { + struct snmp_alarm *sa_ptr; + int nexttime = 0; + + sa_ptr = sa_find_next(); + if (sa_ptr) { + nexttime = sa_ptr->nextcall - time(NULL); + if (nexttime <= 0) + nexttime = 1; /* occurred already, return 1 second */ + } + return nexttime; +} + + +void +set_an_alarm(void) { + int nexttime = get_next_alarm_delay_time(); + + /* we don't use signals if they asked us nicely not to. It's + expected they'll check the next alarm time and do their own + calling of run_alarms(). */ + if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG) && nexttime) { +#ifndef WIN32 +#ifdef SIGALRM +//FIXMEHMTHMT alarm(nexttime); + DEBUGMSGTL(("snmp_alarm_set_an_alarm","setting an alarm for %d seconds from now\n",nexttime)); + signal(SIGALRM, alarm_handler); +#endif /* SIGALRM */ +#endif + + } else { + DEBUGMSGTL(("snmp_alarm_set_an_alarm","no alarms found to handle\n")); + } +} + +unsigned int +snmp_alarm_register(unsigned int when, unsigned int flags, + SNMPAlarmCallback *thecallback, void *clientarg) { + struct snmp_alarm **sa_pptr; + if (thealarms != NULL) { + for(sa_pptr = &thealarms; (*sa_pptr) != NULL; + sa_pptr = &((*sa_pptr)->next)); + } else { + sa_pptr = &thealarms; + } + + *sa_pptr = SNMP_MALLOC_STRUCT(snmp_alarm); + if (*sa_pptr == NULL) + return 0; + + (*sa_pptr)->seconds = when; + (*sa_pptr)->flags = flags; + (*sa_pptr)->clientarg = clientarg; + (*sa_pptr)->thecallback = thecallback; + (*sa_pptr)->clientreg = regnum++; + sa_update_entry(*sa_pptr); + + DEBUGMSGTL(("snmp_alarm_register","registered alarm %d, secends=%d, flags=%d\n", + (*sa_pptr)->clientreg, (*sa_pptr)->seconds, (*sa_pptr)->flags)); + + if (start_alarms) + set_an_alarm(); + return (*sa_pptr)->clientreg; +} diff --git a/packages/net/snmp/lib/current/src/snmp_api.c b/packages/net/snmp/lib/current/src/snmp_api.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmp_api.c @@ -0,0 +1,4761 @@ +//========================================================================== +// +// ./lib/current/src/snmp_api.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/****************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#include + +#include +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#if HAVE_SYS_PARAM_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include + +#ifdef __ECOS +# ifdef AF_UNIX +# undef AF_UNIX // eCos does not support local sockets +# endif // AF_UNIX +#endif // __ECOS + +#endif +#if HAVE_SYS_UN_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_NET_IF_DL_H +#include +#endif +#include + +#if HAVE_LOCALE_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp.h" +#define SNMP_NEED_REQUEST_LIST +#include "snmp_api.h" +#include "snmp_client.h" +#include "snmp_impl.h" +#include "parse.h" +#include "mib.h" +#include "system.h" +#include "int64.h" +#include "snmpv3.h" +#include "read_config.h" +#include "snmp_debug.h" +#include "callback.h" +#include "snmpusm.h" +#include "tools.h" +#include "keytools.h" +#include "lcd_time.h" +#include "snmp_alarm.h" +#include "snmp_logging.h" +#include "default_store.h" +#include "mt_support.h" + +static void _init_snmp (void); + +#include "transform_oids.h" +#ifndef timercmp +#define timercmp(tvp, uvp, cmp) \ + /* CSTYLED */ \ + ((tvp)->tv_sec cmp (uvp)->tv_sec || \ + ((tvp)->tv_sec == (uvp)->tv_sec && \ + /* CSTYLED */ \ + (tvp)->tv_usec cmp (uvp)->tv_usec)) +#endif +#ifndef timerclear +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#endif + +/* + * Globals. + */ +#define PACKET_LENGTH (8 * 1024) +#define MAX_PACKET_LENGTH (32768) +#ifndef SNMP_STREAM_QUEUE_LEN +#define SNMP_STREAM_QUEUE_LEN 5 +#endif + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#ifndef FD_SET + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) memset((p), 0, sizeof(*(p))) +#endif + +static oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; +/* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_RETRIES 5 +#define DEFAULT_TIMEOUT 1000000L +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + snmp_ipaddr addr; /* address of connected peer */ + snmp_ipaddr me; /* address of local socket */ + struct request_list *requests;/* Info about outstanding requests */ + struct request_list *requestsEnd; /* ptr to end of list */ + int (*hook_pre) ( struct snmp_session*, snmp_ipaddr); + int (*hook_parse)( struct snmp_session *, struct snmp_pdu *, u_char *, size_t); + int (*hook_post) ( struct snmp_session*, struct snmp_pdu*, int ); + int (*hook_build)( struct snmp_session *, struct snmp_pdu *, u_char *, size_t *); + int (*check_packet) ( u_char *, size_t ); + u_char *packet; + long packet_len, proper_len; + size_t packet_size; + char newpkt; +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + + + +static const char *api_errors[-SNMPERR_MAX+1] = { + "No error", /* SNMPERR_SUCCESS */ + "Generic error", /* SNMPERR_GENERR */ + "Invalid local port", /* SNMPERR_BAD_LOCPORT */ + "Unknown host", /* SNMPERR_BAD_ADDRESS */ + "Unknown session", /* SNMPERR_BAD_SESSION */ + "Too long", /* SNMPERR_TOO_LONG */ + "No socket", /* SNMPERR_NO_SOCKET */ + "Cannot send V2 PDU on V1 session", /* SNMPERR_V2_IN_V1 */ + "Cannot send V1 PDU on V2 session", /* SNMPERR_V1_IN_V2 */ + "Bad value for non-repeaters", /* SNMPERR_BAD_REPEATERS */ + "Bad value for max-repetitions", /* SNMPERR_BAD_REPETITIONS */ + "Error building ASN.1 representation", /* SNMPERR_BAD_ASN1_BUILD */ + "Failure in sendto", /* SNMPERR_BAD_SENDTO */ + "Bad parse of ASN.1 type", /* SNMPERR_BAD_PARSE */ + "Bad version specified", /* SNMPERR_BAD_VERSION */ + "Bad source party specified", /* SNMPERR_BAD_SRC_PARTY */ + "Bad destination party specified", /* SNMPERR_BAD_DST_PARTY */ + "Bad context specified", /* SNMPERR_BAD_CONTEXT */ + "Bad community specified", /* SNMPERR_BAD_COMMUNITY */ + "Cannot send noAuth/desPriv", /* SNMPERR_NOAUTH_DESPRIV */ + "Bad ACL definition", /* SNMPERR_BAD_ACL */ + "Bad Party definition", /* SNMPERR_BAD_PARTY */ + "Session abort failure", /* SNMPERR_ABORT */ + "Unknown PDU type", /* SNMPERR_UNKNOWN_PDU */ + "Timeout", /* SNMPERR_TIMEOUT */ + "Failure in recvfrom", /* SNMPERR_BAD_RECVFROM */ + "Unable to determine contextEngineID", /* SNMPERR_BAD_ENG_ID */ + "Unable to determine securityName", /* SNMPERR_BAD_SEC_NAME */ + "Unable to determine securityLevel", /* SNMPERR_BAD_SEC_LEVEL */ + "ASN.1 parse error in message", /* SNMPERR_ASN_PARSE_ERR */ + "Unknown security model in message", /* SNMPERR_UNKNOWN_SEC_MODEL */ + "Invalid message (e.g. msgFlags)", /* SNMPERR_INVALID_MSG */ + "Unknown engine ID", /* SNMPERR_UNKNOWN_ENG_ID */ + "Unknown user name", /* SNMPERR_UNKNOWN_USER_NAME */ + "Unsupported security level", /* SNMPERR_UNSUPPORTED_SEC_LEVEL */ + "Authentication failure", /* SNMPERR_AUTHENTICATION_FAILURE */ + "Not in time window", /* SNMPERR_NOT_IN_TIME_WINDOW */ + "Decryption error", /* SNMPERR_DECRYPTION_ERR */ + "SCAPI general failure", /* SNMPERR_SC_GENERAL_FAILURE */ + "SCAPI sub-system not configured", /* SNMPERR_SC_NOT_CONFIGURED */ + "Key tools not available", /* SNMPERR_KT_NOT_AVAILABLE */ + "Unknown Report message", /* SNMPERR_UNKNOWN_REPORT */ + "USM generic error", /* SNMPERR_USM_GENERICERROR */ + "USM unknown security name", /* SNMPERR_USM_UNKNOWNSECURITYNAME */ + "USM unsupported security level", /* SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL */ + "USM encryption error", /* SNMPERR_USM_ENCRYPTIONERROR */ + "USM authentication failure", /* SNMPERR_USM_AUTHENTICATIONFAILURE */ + "USM parse error", /* SNMPERR_USM_PARSEERROR */ + "USM unknown engineID", /* SNMPERR_USM_UNKNOWNENGINEID */ + "USM not in time window", /* SNMPERR_USM_NOTINTIMEWINDOW */ + "USM decryption error", /* SNMPERR_USM_DECRYPTIONERROR */ + "MIB not initialized", /* SNMPERR_NOMIB */ + "Value out of range", /* SNMPERR_RANGE */ + "Sub-id out of range", /* SNMPERR_MAX_SUBID */ + "Bad sub-id in object identifier", /* SNMPERR_BAD_SUBID */ + "Object identifier too long", /* SNMPERR_LONG_OID */ + "Bad value name", /* SNMPERR_BAD_NAME */ + "Bad value notation", /* SNMPERR_VALUE */ + "Unknown Object Identifier", /* SNMPERR_UNKNOWN_OBJID */ + "No PDU in snmp_send", /* SNMPERR_NULL_PDU */ + "Missing variables in PDU", /* SNMPERR_NO_VARS */ + "Bad variable type", /* SNMPERR_VAR_TYPE */ + "Out of memory (malloc failure)", /* SNMPERR_MALLOC */ +}; + +static const char * usmSecLevelName[] = + { + "BAD_SEC_LEVEL", + "noAuthNoPriv", + "authNoPriv", + "authPriv" + }; + +/* + * Multiple threads may changes these variables. + * Suggest using the Single API, which does not use Sessions. + * + * Reqid may need to be protected. Time will tell... + * + */ +/*MTCRITICAL_RESOURCE*/ +/* use token in comments to individually protect these resources */ +struct session_list *Sessions = NULL; /* MT_LIB_SESSION */ +static long Reqid = 0; /* MT_LIB_REQUESTID */ +static long Msgid = 0; /* MT_LIB_MESSAGEID */ +static long Sessid = 0; /* MT_LIB_SESSIONID */ +static long Transid = 0; /* MT_LIB_TRANSID */ +int snmp_errno = 0; +/*END MTCRITICAL_RESOURCE*/ + +/*struct timeval Now;*/ + +/* + * global error detail storage + */ +static char snmp_detail[192]; +static int snmp_detail_f = 0; + +/* + * Prototypes. + */ +int snmp_build (struct snmp_session *, struct snmp_pdu *, u_char *, size_t *); +static int snmp_parse (void *, struct snmp_session *, struct snmp_pdu *, u_char *, size_t); +static void * snmp_sess_pointer (struct snmp_session *); + +static void snmpv3_calc_msg_flags (int, int, u_char *); +static int snmpv3_verify_msg (struct request_list *, struct snmp_pdu *); +static int snmpv3_build_probe_pdu (struct snmp_pdu **); +static int snmpv3_build (struct snmp_session *, struct snmp_pdu *, + u_char *, size_t *); +static int snmp_parse_version (u_char *, size_t); +static int snmp_resend_request (struct session_list *slp, + struct request_list *rp, + int incr_retries); + +#ifndef HAVE_STRERROR +const char *strerror(int err) +{ + extern const char *sys_errlist[]; + extern int sys_nerr; + + if (err < 0 || err >= sys_nerr) return "Unknown error"; + return sys_errlist[err]; +} +#endif + + +long +snmp_get_next_reqid (void) +{ + long retVal; + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_REQUESTID); + retVal = 1 + Reqid; /*MTCRITICAL_RESOURCE*/ + if (!retVal) retVal = 2; + Reqid = retVal; + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_REQUESTID); + return retVal; +} + +long +snmp_get_next_msgid (void) +{ + long retVal; + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_MESSAGEID); + retVal = 1 + Msgid; /*MTCRITICAL_RESOURCE*/ + if (!retVal) retVal = 2; + Msgid = retVal; + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_MESSAGEID); + return retVal; +} + +long +snmp_get_next_sessid (void) +{ + long retVal; + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSIONID); + retVal = 1 + Sessid; /*MTCRITICAL_RESOURCE*/ + if (!retVal) retVal = 2; + Sessid = retVal; + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSIONID); + return retVal; +} + +long +snmp_get_next_transid (void) +{ + long retVal; + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_TRANSID); + retVal = 1 + Transid; /*MTCRITICAL_RESOURCE*/ + if (!retVal) retVal = 2; + Transid = retVal; + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_TRANSID); + return retVal; +} + +void +snmp_perror(const char *prog_string) +{ + const char *str; + int xerr; + xerr = snmp_errno; /*MTCRITICAL_RESOURCE*/ + str = snmp_api_errstring(xerr); + snmp_log(LOG_ERR,"%s: %s\n",prog_string, str); +} + +void +snmp_set_detail(const char *detail_string) +{ + if (detail_string != NULL) { + strncpy((char *)snmp_detail, detail_string, sizeof(snmp_detail)); + snmp_detail[sizeof(snmp_detail)-1] = '\0'; + snmp_detail_f = 1; + } +} + +/* returns pointer to static data */ +/* results not guaranteed in multi-threaded use */ +const char * +snmp_api_errstring(int snmp_errnumber) +{ + const char *msg = ""; + static char msg_buf [256]; + if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR){ + msg = api_errors[-snmp_errnumber]; + } else if (snmp_errnumber != SNMPERR_SUCCESS) { + msg = "Unknown Error"; + } + if (snmp_detail_f) { + sprintf (msg_buf, "%s (%s)", msg, snmp_detail); + snmp_detail_f = 0; + } + else + strcpy(msg_buf,msg); + + return (msg_buf); +} + +/* + * snmp_error - return error data + * Inputs : address of errno, address of snmp_errno, address of string + * Caller must free the string returned after use. + */ +void +snmp_error(struct snmp_session *psess, + int *p_errno, + int *p_snmp_errno, + char **p_str) +{ + char buf[SPRINT_MAX_LEN]; + int snmp_errnumber; + + if (p_errno) *p_errno = psess->s_errno; + if (p_snmp_errno) *p_snmp_errno = psess->s_snmp_errno; + if (p_str == NULL) return; + + strcpy(buf, ""); + snmp_errnumber = psess->s_snmp_errno; + if (snmp_errnumber >= SNMPERR_MAX && snmp_errnumber <= SNMPERR_GENERR){ + strcpy(buf, api_errors[-snmp_errnumber]); + } else { + if (snmp_errnumber) + sprintf(buf, "Unknown Error %d", snmp_errnumber); + } + + /* append a useful system errno interpretation. */ + if (psess->s_errno) + sprintf (&buf[strlen(buf)], " (%s)", strerror(psess->s_errno)); + *p_str = strdup(buf); +} + +/* + * snmp_sess_error - same as snmp_error for single session API use. + */ +void +snmp_sess_error(void *sessp, + int *p_errno, + int *p_snmp_errno, + char **p_str) +{ + struct session_list *slp = (struct session_list*)sessp; + + if ((slp) && (slp->session)) + snmp_error(slp->session, p_errno, p_snmp_errno, p_str); +} + +/* snmp_sess_perror(): print a error stored in a session pointer */ +void +snmp_sess_perror(const char *prog_string, struct snmp_session *ss) { + char *err; + snmp_error(ss, NULL, NULL, &err); + snmp_log(LOG_ERR, "%s: %s\n", prog_string, err); + free(err); +} + + +/* + * Primordial SNMP library initialization. + * Initializes mutex locks. + * Invokes minimum required initialization for displaying MIB objects. + * Gets initial request ID for all transactions, + * and finds which port SNMP over UDP uses. + * SNMP over AppleTalk or IPX is not currently supported. + * + * Warning: no debug messages here. + */ +static void +_init_snmp (void) +{ +#ifdef HAVE_GETSERVBYNAME + struct servent *servp; +#endif + + struct timeval tv; + long tmpReqid, tmpMsgid; + u_short s_port = SNMP_PORT; + + if (Reqid) return; + Reqid = 1; /* quick set to avoid multiple inits */ + + snmp_res_init(); /* initialize the mt locking structures */ + init_mib_internals(); + + gettimeofday(&tv,(struct timezone *)0); + /*Now = tv;*/ + + /* get pseudo-random values for request ID and message ID */ + /* don't allow zero value to repeat init */ +#ifdef SVR4 + srand48(tv.tv_sec ^ tv.tv_usec); + tmpReqid = lrand48(); + tmpMsgid = lrand48(); +#else + srandom(tv.tv_sec ^ tv.tv_usec); + tmpReqid = random(); + tmpMsgid = random(); +#endif + + if (tmpReqid == 0) tmpReqid = 1; + if (tmpMsgid == 0) tmpMsgid = 1; + Reqid = tmpReqid; + Msgid = tmpMsgid; + +#ifdef HAVE_GETSERVBYNAME + servp = getservbyname("snmp", "udp"); + if (servp) { + /* store it in host byte order */ + s_port = ntohs(servp->s_port); + } +#endif + ds_set_int(DS_LIBRARY_ID, DS_LIB_DEFAULT_PORT, s_port); +} + +/* + * Initializes the session structure. + * May perform one time minimal library initialization. + * No MIB file processing is done via this call. + */ +void +snmp_sess_init(struct snmp_session *session) +{ + _init_snmp(); + + /* initialize session to default values */ + + memset(session, 0, sizeof(struct snmp_session)); + session->remote_port = SNMP_DEFAULT_REMPORT; + session->timeout = SNMP_DEFAULT_TIMEOUT; + session->retries = SNMP_DEFAULT_RETRIES; + session->version = SNMP_DEFAULT_VERSION; +} + + +void +register_default_handlers(void) { + ds_register_config(ASN_BOOLEAN, "snmp","dumpPacket", + DS_LIBRARY_ID, DS_LIB_DUMP_PACKET); + ds_register_config(ASN_INTEGER, "snmp","defaultPort", + DS_LIBRARY_ID, DS_LIB_DEFAULT_PORT); + ds_register_config(ASN_OCTET_STR, "snmp","defCommunity", + DS_LIBRARY_ID, DS_LIB_COMMUNITY); + ds_register_premib(ASN_BOOLEAN, "snmp", "noTokenWarnings", + DS_LIBRARY_ID, DS_LIB_NO_TOKEN_WARNINGS); + ds_register_config(ASN_OCTET_STR, "snmp","noRangeCheck", + DS_LIBRARY_ID, DS_LIB_DONT_CHECK_RANGE ); +} + + +/*******************************************************************-o-****** + * init_snmp + * + * Parameters: + * *type Label for the config file "type" used by calling entity. + * + * Call appropriately the functions to do config file loading and + * mib module parsing in the correct order. + */ +void +init_snmp(const char *type) +{ + static int done_init = 0; /* To prevent double init's. */ + + if (done_init) { + return; + } + + done_init = 1; + + _init_snmp(); + +/* set our current locale properly to initialize isprint() type functions */ +#ifdef HAVE_SETLOCALE + setlocale(LC_CTYPE, ""); +#endif + + snmp_debug_init(); /* should be done first, to turn on debugging ASAP */ + if ( type != NULL ) + ds_set_string(DS_LIBRARY_ID, DS_LIB_APPTYPE, type); + init_callbacks(); + init_snmp_logging(); + snmp_init_statistics(); + register_mib_handlers(); + register_default_handlers(); + init_snmpv3(type); + init_snmp_alarm(); + + read_premib_configs(); + init_mib(); + + read_configs(); + +} /* end init_snmp() */ + +void +snmp_store(const char *type) { + DEBUGMSGTL(("snmp_store","storing stuff...\n")); + snmp_save_persistent(type); + snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, NULL); + snmp_clean_persistent(type); +} + + +/* snmp_shutdown(const char *type): + + Parameters: + *type Label for the config file "type" used by calling entity. + + Does the appropriate shutdown calls for the library, saving + persistent data, clean up, etc... +*/ +void +snmp_shutdown(const char *type) { + snmp_store(type); + snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN, NULL); + snmp_close_sessions(); +} + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(struct snmp_session *session) +{ + struct session_list *slp; + slp = (struct session_list *)snmp_sess_open(session); + if (!slp) return NULL; + + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + slp->next = Sessions; + Sessions = slp; + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); + + return (slp->session); +} + +/* extended open */ +struct snmp_session *snmp_open_ex ( + struct snmp_session *session, + int (*fpre_parse) (struct snmp_session *, snmp_ipaddr), + int (*fparse) (struct snmp_session *, struct snmp_pdu *, u_char *, size_t), + int (*fpost_parse) (struct snmp_session *, struct snmp_pdu *, int), + int (*fbuild) (struct snmp_session *, struct snmp_pdu *, u_char *, size_t *), + int (*fcheck) (u_char *, size_t ) +) +{ + struct session_list *slp; + slp = (struct session_list *)snmp_sess_open(session); + if (!slp) return NULL; + slp->internal->hook_pre = fpre_parse; + slp->internal->hook_parse = fparse; + slp->internal->hook_post = fpost_parse; + slp->internal->hook_build = fbuild; + slp->internal->check_packet = fcheck; + + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + slp->next = Sessions; + Sessions = slp; + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); + + return (slp->session); +} + +static struct session_list * +_sess_copy( struct snmp_session *in_session) +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct snmp_session *session; + char *cp; + u_char *ucp; + size_t i; + + in_session->s_snmp_errno = 0; + in_session->s_errno = 0; + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1,sizeof(struct session_list)); + if (slp == NULL) { + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + + isp = (struct snmp_internal_session *)calloc(1,sizeof(struct snmp_internal_session)); + if (isp == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + + slp->internal = isp; + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)malloc(sizeof(struct snmp_session)); + if (slp->session == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + memmove(slp->session, in_session, sizeof(struct snmp_session)); + session = slp->session; + + /* zero out pointers so if we have to free the session we wont free mem + owned by in_session */ + session->peername = NULL; + session->community = NULL; + session->contextEngineID = NULL; + session->contextName = NULL; + session->securityEngineID = NULL; + session->securityName = NULL; + session->securityAuthProto = NULL; + session->securityPrivProto = NULL; + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (in_session->peername != NULL){ + session->peername = (char *)malloc(strlen(in_session->peername) + 1); + if (session->peername == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + strcpy(session->peername, in_session->peername); + } + + /* Fill in defaults if necessary */ + if (in_session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + ucp = (u_char *)malloc(in_session->community_len); + if (ucp != NULL) + memmove(ucp, in_session->community, in_session->community_len); + } else { + if ((cp = ds_get_string(DS_LIBRARY_ID, DS_LIB_COMMUNITY)) != NULL) { + session->community_len = strlen(cp); + ucp = (u_char *)malloc(session->community_len); + if (ucp) + memmove(ucp, cp, session->community_len); + } + else { +#ifdef NO_ZEROLENGTH_COMMUNITY + session->community_len = strlen(DEFAULT_COMMUNITY); + ucp = (u_char *)malloc(session->community_len); + if (ucp) + memmove(ucp, DEFAULT_COMMUNITY, session->community_len); +#else + ucp = (u_char *)strdup(""); +#endif + } + } + + if (ucp == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + session->community = ucp; /* replace pointer with pointer to new data */ + + if (session->securityLevel <= 0) + session->securityLevel = ds_get_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL); + + if (session->securityLevel == 0) + session->securityLevel = SNMP_SEC_LEVEL_NOAUTH; + + if (in_session->securityAuthProtoLen > 0) { + session->securityAuthProto = + (oid*)malloc(in_session->securityAuthProtoLen * sizeof(oid)); + if (session->securityAuthProto == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + memmove(session->securityAuthProto, in_session->securityAuthProto, + in_session->securityAuthProtoLen * sizeof(oid)); + } else if (get_default_authtype(&i) != NULL) { + session->securityAuthProto = + snmp_duplicate_objid(get_default_authtype(NULL), i); + session->securityAuthProtoLen = i; + } + + if (in_session->securityPrivProtoLen > 0) { + session->securityPrivProto = + (oid*)malloc((unsigned)in_session->securityPrivProtoLen * sizeof(oid)); + if (session->securityPrivProto == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + memmove(session->securityPrivProto, in_session->securityPrivProto, + in_session->securityPrivProtoLen * sizeof(oid)); + } else if (get_default_privtype(&i) != NULL) { + session->securityPrivProto = + snmp_duplicate_objid(get_default_privtype(NULL), i); + session->securityPrivProtoLen = i; + } + + if (in_session->securityEngineIDLen > 0) { + ucp = (u_char*)malloc((unsigned)in_session->securityEngineIDLen * + sizeof(u_char)); + if (ucp == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + memmove(ucp, in_session->securityEngineID, + in_session->securityEngineIDLen * sizeof(u_char)); + session->securityEngineID = ucp; + + } + + if (in_session->contextEngineIDLen > 0) { + ucp = (u_char*)malloc((unsigned)in_session->contextEngineIDLen * + sizeof(u_char)); + if (ucp == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + memmove(ucp, in_session->contextEngineID, + in_session->contextEngineIDLen * sizeof(u_char)); + session->contextEngineID = ucp; + } else if (in_session->securityEngineIDLen > 0) { + /* default contextEngineID to securityEngineIDLen if defined */ + ucp = (u_char*)malloc((unsigned)in_session->securityEngineIDLen * + sizeof(u_char)); + if (ucp == NULL) { + snmp_sess_close(slp); + in_session->s_snmp_errno = SNMPERR_MALLOC; + return(NULL); + } + memmove(ucp, in_session->securityEngineID, + in_session->securityEngineIDLen * sizeof(u_char)); + session->contextEngineID = ucp; + session->contextEngineIDLen = in_session->securityEngineIDLen; + } + + if (in_session->contextName) { + session->contextName = strdup(in_session->contextName); + if (session->contextName == NULL) { + snmp_sess_close(slp); + return(NULL); + } + } else if ((cp = ds_get_string(DS_LIBRARY_ID, DS_LIB_CONTEXT)) != NULL) { + cp = strdup(cp); + if (cp == NULL) { + snmp_sess_close(slp); + return(NULL); + } + session->contextName = cp; + session->contextNameLen = strlen(cp); + } else { + cp = strdup(SNMP_DEFAULT_CONTEXT); + session->contextName = cp; + session->contextNameLen = strlen(cp); + } + + if (in_session->securityName) { + session->securityName = strdup(in_session->securityName); + if (session->securityName == NULL) { + snmp_sess_close(slp); + return(NULL); + } + } else if ((cp = ds_get_string(DS_LIBRARY_ID, DS_LIB_SECNAME)) != NULL) { + cp = strdup(cp); + if (cp == NULL) { + snmp_sess_close(slp); + return(NULL); + } + session->securityName = cp; + session->securityNameLen = strlen(cp); + } + + if ((in_session->securityAuthKeyLen <= 0) && + (cp = ds_get_string(DS_LIBRARY_ID, DS_LIB_AUTHPASSPHRASE))) { + session->securityAuthKeyLen = USM_AUTH_KU_LEN; + if (generate_Ku(session->securityAuthProto, + session->securityAuthProtoLen, + (u_char*)cp, strlen(cp), + session->securityAuthKey, + &session->securityAuthKeyLen) != SNMPERR_SUCCESS) { + snmp_set_detail("Error generating Ku from authentication pass phrase."); + snmp_sess_close(slp); + return NULL; + } + } + + if ((in_session->securityPrivKeyLen <= 0) && + (cp = ds_get_string(DS_LIBRARY_ID, DS_LIB_PRIVPASSPHRASE))) { + session->securityPrivKeyLen = USM_PRIV_KU_LEN; + if (generate_Ku(session->securityAuthProto, + session->securityAuthProtoLen, + (u_char *)cp, strlen(cp), + session->securityPrivKey, + &session->securityPrivKeyLen) != SNMPERR_SUCCESS) { + snmp_set_detail("Error generating Ku from privacy pass phrase."); + snmp_sess_close(slp); + return NULL; + } + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = DEFAULT_TIMEOUT; + session->sessid = snmp_get_next_sessid(); + + return( slp ); +} + +struct session_list * +snmp_sess_copy( struct snmp_session *pss) +{ + struct session_list * psl; + psl = _sess_copy(pss); + if ( !psl) { + if ( !pss->s_snmp_errno) + pss->s_snmp_errno = SNMPERR_GENERR; + SET_SNMP_ERROR(pss->s_snmp_errno); + } + return psl; +} + +/*******************************************************************-o-****** + * snmp_sess_open + * + * Parameters: + * *in_session + * + * Returns: + * Pointer to a session in the session list -OR- FIX -- right? + * NULL on failure. + * + * The "spin-free" version of snmp_open. + */ +static void * +_sess_open(struct snmp_session *in_session) +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct snmp_session *session; + int sd; + in_addr_t addr; + struct sockaddr_in *isp_addr, *meIp; +#ifdef HAVE_GETHOSTBYNAME + struct hostent *hp; +#endif + struct snmp_pdu *pdu, *response; + int status; + size_t i, addr_size; + char *cp = NULL; + + in_session->s_snmp_errno = 0; + in_session->s_errno = 0; + + if (Reqid == 0) + _init_snmp(); + + if ((slp = snmp_sess_copy( in_session )) == NULL ) + return( NULL ); + isp = slp->internal; + session = slp->session; + + if ( isp->addr.sa_family == AF_UNSPEC ) { + if ( session->peername && session->peername[0] == '/' ) { +#ifdef AF_UNIX + isp->addr.sa_family = AF_UNIX; + strcpy( isp->addr.sa_data, session->peername); +#else /* AF_UNIX */ + snmp_log(LOG_ERR,"%s:%d: _sess_open invalid session name %s- unix sockets not supported \n", + __FILE__,__LINE__, + session->peername); + return(NULL); +#endif /* AF_UNIX */ + + } else { + isp->addr.sa_family = AF_INET; + isp_addr = (struct sockaddr_in *)&(isp->addr); + if (session->peername != SNMP_DEFAULT_PEERNAME) { + + /* Try and extract an appended port number */ + cp = strchr( session->peername, ':' ); + if ( cp ) { + *cp = '\0'; + cp++; + session->remote_port = atoi( cp ); + if ( session->local_port ) /* i.e. server */ + session->local_port = session->remote_port; + } + + /* Interpret the peername as an IP port ... */ + cp = strchr( session->peername, '.' ); + if ( !cp && (( i = atoi( session->peername )) != 0 )) { + session->remote_port = i; + if ( session->local_port ) /* i.e. server */ + session->local_port = session->remote_port; + } + + /* ... failing that, as an IP address ... */ + else if ((int)(addr = inet_addr(session->peername)) != -1){ + memmove(&isp_addr->sin_addr, &addr, sizeof(isp_addr->sin_addr)); + } else { + /* .... failing that, as a hostname */ +#ifdef HAVE_GETHOSTBYNAME + hp = gethostbyname(session->peername); + if (hp == NULL){ + in_session->s_snmp_errno = SNMPERR_BAD_ADDRESS; + in_session->s_errno = errno; + snmp_set_detail(session->peername); + snmp_sess_close(slp); + return 0; + } else { + memmove(&isp_addr->sin_addr, hp->h_addr, hp->h_length); + } + +#else /* HAVE_GETHOSTBYNAME */ + snmp_log(LOG_ERR,"%s:%d: _sess_open do not have get host by name - cannot resolve %s \n", + __FILE__,__LINE__, + session->peername); + return(0); +#endif /* HAVE_GETHOSTBYNAME */ + + } + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + short iport = ds_get_int(DS_LIBRARY_ID, DS_LIB_DEFAULT_PORT); + isp_addr->sin_port = htons(iport); + } else { + isp_addr->sin_port = htons(session->remote_port); + } + } else { + isp_addr->sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + } + } + + + if ( session->local_port ) { + /* + * If the session structure includes a non-null value for + * local_port, then this session is intended as a server. + * This means that the isp->addr structure will not be + * needed to contact a remote entity. + * + * By using this address as the local address to bind to, + * we can provide a facility for listening on selected + * (rather than all) interfaces. + */ + memcpy( &isp->me, &isp->addr, sizeof(isp->me)); + + if ( isp->addr.sa_family == AF_INET ) { + /* + * Remember to use the specified local port, + * rather than the (default?) remote one. + * If no local interface address is specified, + * default to listening on all interfaces, + * rather than the default connection host + * (SNMP_DEFAULT_ADDRESS) + */ + meIp = (struct sockaddr_in*)&(isp->me); + meIp->sin_port = htons(session->local_port); + if (session->peername == SNMP_DEFAULT_PEERNAME) + meIp->sin_addr.s_addr = INADDR_ANY; + } + } + else { + memset(&isp->me, '\0', sizeof(isp->me)); + isp->me.sa_family = isp->addr.sa_family; + if ( isp->me.sa_family == AF_INET ) { + meIp = (struct sockaddr_in*)&(isp->me); + meIp->sin_addr.s_addr = INADDR_ANY; + meIp->sin_port = htons(session->local_port); + } +#ifdef AF_UNIX + else if ( isp->me.sa_family == AF_UNIX ) { + /* Need a unique socket name */ +#ifndef UNIX_SOCKET_BASE_NAME +#define UNIX_SOCKET_BASE_NAME "/tmp/s." +#endif + +#ifndef WIN32 + strcpy( isp->me.sa_data, UNIX_SOCKET_BASE_NAME ); + strcat( isp->me.sa_data, "XXXXXX" ); + mktemp( isp->me.sa_data ); +#endif + } +#endif /* AF_UNIX */ + } + addr_size = snmp_socket_length(isp->me.sa_family); + + /* Set up connections */ + if ( session->flags & SNMP_FLAGS_STREAM_SOCKET ) { + if ( session->local_port != 0 ) + session->flags |= SNMP_FLAGS_LISTENING; + sd = socket(isp->me.sa_family, SOCK_STREAM, 0); + } + else + sd = socket(isp->me.sa_family, SOCK_DGRAM, 0); + if (sd < 0){ + in_session->s_snmp_errno = SNMPERR_NO_SOCKET; + in_session->s_errno = errno; + snmp_set_detail(strerror(errno)); + snmp_sess_close(slp); + return 0; + } + isp->sd = sd; + +#ifdef SO_BSDCOMPAT + /* Patch for Linux. Without this, UDP packets that fail get an ICMP + * response. Linux turns the failed ICMP response into an error message + * and return value, unlike all other OS's. + */ + { + int one=1; + setsockopt(sd, SOL_SOCKET, SO_BSDCOMPAT, &one, sizeof(one)); + } +#endif /* SO_BSDCOMPAT */ + +//#ifndef __ECOS +#ifndef SERVER_REQUIRES_CLIENT_SOCKET + if (!(( session->flags & SNMP_FLAGS_STREAM_SOCKET ) && +#ifdef AF_UNIX + ( isp->me.sa_family == AF_UNIX ) && +#endif /* AF_UNIX */ + ( session->local_port == 0 ))) { + + /* Client Unix-domain stream sockets don't need to 'bind' */ +#endif + if (bind(sd, (struct sockaddr *)&isp->me, addr_size) != 0){ + in_session->s_snmp_errno = SNMPERR_BAD_LOCPORT; + in_session->s_errno = errno; + snmp_set_detail(strerror(errno)); + snmp_sess_close(slp); + return 0; + } +#ifndef SERVER_REQUIRES_CLIENT_SOCKET + } +#endif +//#endif // not __ECOS + + if ( session->flags & SNMP_FLAGS_STREAM_SOCKET ) { + if ( session->local_port == 0 ) { /* Client session */ + + if ( connect( sd, (struct sockaddr *)&(isp->addr), + snmp_socket_length(isp->addr.sa_family)) != 0 ) { + in_session->s_snmp_errno = SNMPERR_BAD_LOCPORT; + in_session->s_errno = errno; + snmp_set_detail(strerror(errno)); + snmp_sess_close(slp); + return 0; + } + } else { /* Server session */ + + if ( listen( sd, SNMP_STREAM_QUEUE_LEN ) != 0 ) { + in_session->s_snmp_errno = SNMPERR_BAD_LOCPORT; + in_session->s_errno = errno; + snmp_set_detail(strerror(errno)); + snmp_sess_close(slp); + return 0; + } + } + } + + /* if we are opening a V3 session and we don't know engineID + we must probe it - this must be done after the session is + created and inserted in the list so that the response can + handled correctly */ + if (session->version == SNMP_VERSION_3) { + if (session->securityEngineIDLen == 0 && + (session->securityEngineIDLen & SNMP_FLAGS_DONT_PROBE) != + SNMP_FLAGS_DONT_PROBE) { + snmpv3_build_probe_pdu(&pdu); + DEBUGMSGTL(("snmp_api","probing for engineID...\n")); + status = snmp_sess_synch_response(slp, pdu, &response); + + if ((response == NULL) && (status == STAT_SUCCESS)) status = STAT_ERROR; + + switch (status) { + case STAT_SUCCESS: + in_session->s_snmp_errno = SNMPERR_INVALID_MSG; /* XX?? */ + DEBUGMSGTL(("snmp_sess_open", + "error: expected Report as response to probe: %s (%d)\n", + snmp_errstring(response->errstat), response->errstat)); + break; + case STAT_ERROR: /* this is what we expected -> Report == STAT_ERROR */ + in_session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID; + break; + case STAT_TIMEOUT: + in_session->s_snmp_errno = SNMPERR_TIMEOUT; + default: + DEBUGMSGTL(("snmp_sess_open", + "unable to connect with remote engine: %s (%d)\n", + snmp_api_errstring(session->s_snmp_errno), + session->s_snmp_errno)); + break; + } + if (slp->session->securityEngineIDLen == 0) { + DEBUGMSGTL(("snmp_api","unable to determine remote engine ID\n")); + snmp_sess_close(slp); + return NULL; + } + in_session->s_snmp_errno = SNMPERR_SUCCESS; + if (snmp_get_do_debugging()) { + DEBUGMSGTL(("snmp_sess_open", " probe found engineID: ")); + for(i = 0; i < slp->session->securityEngineIDLen; i++) + DEBUGMSG(("snmp_sess_open", "%02x", + slp->session->securityEngineID[i])); + DEBUGMSG(("snmp_sess_open","\n")); + } + } + /* if boot/time supplied set it for this engineID */ + if (session->engineBoots || session->engineTime) { + set_enginetime(session->securityEngineID, session->securityEngineIDLen, + session->engineBoots, session->engineTime, TRUE); + } + if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) { + in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME; /* XX?? */ + DEBUGMSGTL(("snmp_api","snmp_sess_open(): failed(2) to create a new user from session\n")); + snmp_sess_close(slp); + return NULL; + } + } + + + return (void *)slp; +} /* end snmp_sess_open() */ + +void * +snmp_sess_open(struct snmp_session *pss) +{ + void * pvoid; + pvoid = _sess_open(pss); + if ( !pvoid) { + SET_SNMP_ERROR(pss->s_snmp_errno); + } + return pvoid; +} + + + +/* create_user_from_session(struct snmp_session *session): + + creates a user in the usm table from the information in a session + + Parameters: + session -- IN: pointer to the session to use when creating the user. + + Returns: + SNMPERR_SUCCESS + SNMPERR_GENERR +*/ +int +create_user_from_session(struct snmp_session *session) +{ + struct usmUser *user; + + + /* now that we have the engineID, create an entry in the USM list + for this user using the information in the session */ + user = usm_get_user_from_list(session->securityEngineID, + session->securityEngineIDLen, + session->securityName, + usm_get_userList(), 0); + if (user == NULL) { + DEBUGMSGTL(("snmp_api","Building user %s...\n",session->securityName)); + /* user doesn't exist so we create and add it */ + user = (struct usmUser *) calloc(1,sizeof(struct usmUser)); + if (user == NULL) + return SNMPERR_GENERR; + + /* copy in the securityName */ + if (session->securityName) { + user->name = strdup(session->securityName); + user->secName = strdup(session->securityName); + if (user->name == NULL || user->secName == NULL) { + usm_free_user(user); + return SNMPERR_GENERR; + } + } + + /* copy in the engineID */ + if (memdup(&user->engineID, session->securityEngineID, + session->securityEngineIDLen) != SNMPERR_SUCCESS) { + usm_free_user(user); + return SNMPERR_GENERR; + } + user->engineIDLen = session->securityEngineIDLen; + + /* copy the auth protocol */ + if (session->securityAuthProto != NULL) { + user->authProtocol = + snmp_duplicate_objid(session->securityAuthProto, + session->securityAuthProtoLen); + if (user->authProtocol == NULL) { + usm_free_user(user); + return SNMPERR_GENERR; + } + user->authProtocolLen = session->securityAuthProtoLen; + } + + /* copy the priv protocol */ + if (session->securityPrivProto != NULL) { + user->privProtocol = + snmp_duplicate_objid(session->securityPrivProto, + session->securityPrivProtoLen); + if (user->privProtocol == NULL) { + usm_free_user(user); + return SNMPERR_GENERR; + } + user->privProtocolLen = session->securityPrivProtoLen; + } + + /* copy in the authentication Key, and convert to the localized version */ + if (session->securityAuthKey != NULL && session->securityAuthKeyLen != 0) { + user->authKey = (u_char *)malloc (USM_LENGTH_KU_HASHBLOCK); + user->authKeyLen = USM_LENGTH_KU_HASHBLOCK; + if (generate_kul( user->authProtocol, user->authProtocolLen, + session->securityEngineID, session->securityEngineIDLen, + session->securityAuthKey, session->securityAuthKeyLen, + user->authKey, &user->authKeyLen ) != SNMPERR_SUCCESS) { + usm_free_user(user); + return SNMPERR_GENERR; + } + } + + /* copy in the privacy Key, and convert to the localized version */ + if (session->securityPrivKey != NULL && session->securityPrivKeyLen != 0) { + user->privKey = (u_char *)malloc (USM_LENGTH_KU_HASHBLOCK); + user->privKeyLen = USM_LENGTH_KU_HASHBLOCK; + if (generate_kul( user->authProtocol, user->authProtocolLen, + session->securityEngineID, session->securityEngineIDLen, + session->securityPrivKey, session->securityPrivKeyLen, + user->privKey, &user->privKeyLen ) != SNMPERR_SUCCESS) { + usm_free_user(user); + return SNMPERR_GENERR; + } + } + + /* add the user into the database */ + usm_add_user(user); + } + + return SNMPERR_SUCCESS; + + +} /* end create_user_from_session() */ + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_sess_close(void *sessp) +{ + struct session_list *slp = (struct session_list *)sessp; + struct snmp_internal_session *isp; + struct snmp_session *sesp; + + if (slp == NULL) + return 0; + + isp = slp->internal; slp->internal = 0; + if (isp) { + struct request_list *rp, *orp; + + SNMP_FREE(isp->packet); + + if (isp->sd != -1) + { +#ifndef HAVE_CLOSESOCKET + close(isp->sd); +#else + closesocket(isp->sd); +#endif +#ifdef AF_UNIX + if ( isp->me.sa_family == AF_UNIX ) + unlink( isp->me.sa_data ); +#endif /* AF_UNIX */ + } + + /* Free each element in the input request list. */ + rp = isp->requests; + while(rp){ + orp = rp; + rp = rp->next_request; + snmp_free_pdu(orp->pdu); + free((char *)orp); + } + + free((char *)isp); + } + + sesp = slp->session; slp->session = 0; + if (sesp) { + SNMP_FREE(sesp->peername); + SNMP_FREE(sesp->community); + SNMP_FREE(sesp->contextEngineID); + SNMP_FREE(sesp->contextName); + SNMP_FREE(sesp->securityEngineID); + SNMP_FREE(sesp->securityName); + SNMP_FREE(sesp->securityAuthProto); + SNMP_FREE(sesp->securityPrivProto); + free((char *)sesp); + } + + free((char *)slp); + + return 1; +} + +int +snmp_close(struct snmp_session *session) +{ + struct session_list *slp = NULL, *oslp = NULL; + + { /*MTCRITICAL_RESOURCE*/ + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + if (Sessions && Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); + } /*END MTCRITICAL_RESOURCE*/ + if (slp == NULL){ + return 0; + } + return snmp_sess_close((void *)slp); +} + +int +snmp_close_sessions( void ) +{ + struct session_list *slp; + + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + while ( Sessions ) { + slp = Sessions; + Sessions = Sessions->next; + snmp_sess_close((void *)slp); + } + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); + return 1; +} + +static int +snmpv3_build_probe_pdu (struct snmp_pdu **pdu) +{ + struct usmUser *user; + + /* create the pdu */ + if (!pdu) return -1; + *pdu = snmp_pdu_create(SNMP_MSG_GET); + (*pdu)->version = SNMP_VERSION_3; + (*pdu)->securityName = strdup(""); + (*pdu)->securityNameLen = strlen((*pdu)->securityName); + (*pdu)->securityLevel = SNMP_SEC_LEVEL_NOAUTH; + (*pdu)->securityModel = SNMP_SEC_MODEL_USM; + + /* create the empty user */ + user = usm_get_user(NULL, 0, (*pdu)->securityName); + if (user == NULL) { + user = (struct usmUser *) calloc(1,sizeof(struct usmUser)); + user->name = strdup((*pdu)->securityName); + user->secName = strdup((*pdu)->securityName); + user->authProtocolLen = sizeof(usmNoAuthProtocol)/sizeof(oid); + user->authProtocol = + snmp_duplicate_objid(usmNoAuthProtocol, user->authProtocolLen); + user->privProtocolLen = sizeof(usmNoPrivProtocol)/sizeof(oid); + user->privProtocol = + snmp_duplicate_objid(usmNoPrivProtocol, user->privProtocolLen); + usm_add_user(user); + } + return 0; +} + +static void +snmpv3_calc_msg_flags (int sec_level, int msg_command, u_char *flags) +{ + *flags = 0; + if (sec_level == SNMP_SEC_LEVEL_AUTHNOPRIV) + *flags = SNMP_MSG_FLAG_AUTH_BIT; + else if (sec_level == SNMP_SEC_LEVEL_AUTHPRIV) + *flags = SNMP_MSG_FLAG_AUTH_BIT | SNMP_MSG_FLAG_PRIV_BIT; + + if (SNMP_CMD_CONFIRMED(msg_command)) *flags |= SNMP_MSG_FLAG_RPRT_BIT; + + return; +} + +static int +snmpv3_verify_msg(struct request_list *rp, struct snmp_pdu *pdu) +{ + struct snmp_pdu *rpdu; + + if (!rp || !rp->pdu || !pdu) return 0; + /* Reports don't have to match anything according to the spec */ + if (pdu->command == SNMP_MSG_REPORT) return 1; + rpdu = rp->pdu; + if (rp->request_id != pdu->reqid || rpdu->reqid != pdu->reqid) return 0; + if (rpdu->version != pdu->version) return 0; + if (rpdu->securityModel != pdu->securityModel) return 0; + if (rpdu->securityLevel != pdu->securityLevel) return 0; + + if (rpdu->contextEngineIDLen != pdu->contextEngineIDLen || + memcmp(rpdu->contextEngineID, pdu->contextEngineID, + pdu->contextEngineIDLen)) + return 0; + if (rpdu->contextNameLen != pdu->contextNameLen || + memcmp(rpdu->contextName, pdu->contextName, pdu->contextNameLen)) + return 0; + if (rpdu->securityEngineIDLen != pdu->securityEngineIDLen || + memcmp(rpdu->securityEngineID, pdu->securityEngineID, + pdu->securityEngineIDLen)) + return 0; + if (rpdu->securityNameLen != pdu->securityNameLen || + memcmp(rpdu->securityName, pdu->securityName, pdu->securityNameLen)) + return 0; + return 1; +} + + +/* SNMPv3 + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +static int +snmpv3_build(struct snmp_session *session, + struct snmp_pdu *pdu, + u_char *packet, + size_t *out_length) +{ + int ret; + + session->s_snmp_errno = 0; + session->s_errno = 0; + + /* do validation for PDU types */ + switch (pdu->command) { + case SNMP_MSG_RESPONSE: + case SNMP_MSG_TRAP2: + case SNMP_MSG_REPORT: + pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE); + /* Fallthrough */ + case SNMP_MSG_GET: + case SNMP_MSG_GETNEXT: + case SNMP_MSG_SET: + case SNMP_MSG_INFORM: + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + break; + + case SNMP_MSG_GETBULK: + if (pdu->max_repetitions < 0) { + session->s_snmp_errno = SNMPERR_BAD_REPETITIONS; + return -1; + } + if (pdu->non_repeaters < 0) { + session->s_snmp_errno = SNMPERR_BAD_REPEATERS; + return -1; + } + break; + + case SNMP_MSG_TRAP: + session->s_snmp_errno = SNMPERR_V1_IN_V2; + return -1; + + default: + session->s_snmp_errno = SNMPERR_UNKNOWN_PDU; + return -1; + } + + if (pdu->securityEngineIDLen == 0) { + if (session->securityEngineIDLen) { + snmpv3_clone_engineID(&pdu->securityEngineID, + &pdu->securityEngineIDLen, + session->securityEngineID, + session->securityEngineIDLen); + } + } + + if (pdu->contextEngineIDLen == 0) { + if (session->contextEngineIDLen) { + snmpv3_clone_engineID(&pdu->contextEngineID, + &pdu->contextEngineIDLen, + session->contextEngineID, + session->contextEngineIDLen); + } else if (pdu->securityEngineIDLen) { + snmpv3_clone_engineID(&pdu->contextEngineID, + &pdu->contextEngineIDLen, + pdu->securityEngineID, + pdu->securityEngineIDLen); + } + } + + if (pdu->contextName == NULL) { + if (!session->contextName){ + session->s_snmp_errno = SNMPERR_BAD_CONTEXT; + return -1; + } + pdu->contextName = strdup(session->contextName); + if (pdu->contextName == NULL) { + session->s_snmp_errno = SNMPERR_GENERR; + return -1; + } + pdu->contextNameLen = session->contextNameLen; + } + pdu->securityModel = SNMP_SEC_MODEL_USM; + if (pdu->securityNameLen == 0 && pdu->securityName == 0) { + if (session->securityNameLen == 0){ + session->s_snmp_errno = SNMPERR_BAD_SEC_NAME; + return -1; + } + pdu->securityName = strdup(session->securityName); + if (pdu->securityName == NULL) { + session->s_snmp_errno = SNMPERR_GENERR; + return -1; + } + pdu->securityNameLen = session->securityNameLen; + } + if (pdu->securityLevel == 0) { + if (session->securityLevel == 0) { + session->s_snmp_errno = SNMPERR_BAD_SEC_LEVEL; + return -1; + } + pdu->securityLevel = session->securityLevel; + } + DEBUGMSGTL(("snmp_build", + "Building SNMPv3 message (secName:\"%s\", secLevel:%s)...\n", + ((session->securityName) ? (char *)session->securityName : + ((pdu->securityName) ? (char *)pdu->securityName : + "ERROR: undefined")), + usmSecLevelName[pdu->securityLevel])); + + ret = snmpv3_packet_build(pdu, packet, out_length, NULL, 0); + if (-1 != ret) { + session->s_snmp_errno = ret; + } + + return ret; + +} /* end snmpv3_build() */ + + + + +static u_char * +snmpv3_header_build(struct snmp_pdu *pdu, u_char *packet, + size_t *out_length, size_t length, u_char **msg_hdr_e) + +{ + u_char *global_hdr, *global_hdr_e; + u_char *cp; + u_char msg_flags; + long max_size; + long sec_model; + u_char *pb, *pb0e; + + /* Save current location and build SEQUENCE tag and length placeholder + * for SNMP message sequence (actual length inserted later) + */ + cp = asn_build_sequence(packet, out_length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), length); + if (cp == NULL) return NULL; + if (msg_hdr_e != NULL) + *msg_hdr_e = cp; + pb0e = cp; + + + /* store the version field - msgVersion + */ + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->version, sizeof(pdu->version)); + if (cp == NULL) return NULL; + + global_hdr = cp; + /* msgGlobalData HeaderData */ + cp = asn_build_sequence(cp, out_length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); + if (cp == NULL) return NULL; + global_hdr_e = cp; + + + /* msgID */ + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &pdu->msgid, sizeof(pdu->msgid)); + if (cp == NULL) return NULL; + + /* msgMaxSize */ + max_size = SNMP_MAX_MSG_SIZE; + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &max_size, sizeof(max_size)); + if (cp == NULL) return NULL; + + /* msgFlags */ + snmpv3_calc_msg_flags(pdu->securityLevel, pdu->command, &msg_flags); + cp = asn_build_string(cp, out_length, + (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + &msg_flags, sizeof(msg_flags)); + if (cp == NULL) return NULL; + + /* msgSecurityModel */ + sec_model = SNMP_SEC_MODEL_USM; + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &sec_model, sizeof(sec_model)); + if (cp == NULL) return NULL; + + + /* insert actual length of globalData + */ + pb = asn_build_sequence(global_hdr, out_length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + cp - global_hdr_e); + if (pb == NULL) return NULL; + + + /* insert the actual length of the entire packet + */ + pb = asn_build_sequence(packet, out_length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + length + (cp - pb0e)); + if (pb == NULL) return NULL; + + return cp; + +} /* end snmpv3_header_build() */ + + + +static u_char * +snmpv3_scopedPDU_header_build(struct snmp_pdu *pdu, + u_char *packet, size_t *out_length, + u_char **spdu_e) + +{ + size_t init_length; + u_char *scopedPdu, *pb; + + + init_length = *out_length; + + pb = scopedPdu = packet; + pb = asn_build_sequence(pb, out_length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); + if (pb == NULL) return NULL; + if (spdu_e) + *spdu_e = pb; + + pb = asn_build_string(pb, out_length, + (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + pdu->contextEngineID, pdu->contextEngineIDLen); + if (pb == NULL) return NULL; + + pb = asn_build_string(pb, out_length, + (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + (u_char *)pdu->contextName, pdu->contextNameLen); + if (pb == NULL) return NULL; + + return pb; + +} /* end snmpv3_scopedPDU_header_build() */ + + +/* returns 0 if success, -1 if fail, not 0 if USM build failure */ +int +snmpv3_packet_build(struct snmp_pdu *pdu, u_char *packet, size_t *out_length, + u_char *pdu_data, size_t pdu_data_len) +{ + u_char *global_data, *sec_params, *spdu_hdr_e; + size_t global_data_len, sec_params_len; + u_char spdu_buf[SNMP_MAX_MSG_SIZE]; + size_t spdu_buf_len, spdu_len; + u_char *cp; + int result; + + global_data = packet; + + /* + * build the headers for the packet, returned addr = start of secParams + */ + sec_params = snmpv3_header_build(pdu, global_data, out_length, 0, NULL); + if (sec_params == NULL) return -1; + global_data_len = sec_params - global_data; + sec_params_len = *out_length; /* length left in packet buf for sec_params */ + + + /* + * build a scopedPDU structure into spdu_buf + */ + spdu_buf_len = SNMP_MAX_MSG_SIZE; + cp = snmpv3_scopedPDU_header_build(pdu,spdu_buf,&spdu_buf_len,&spdu_hdr_e); + if (cp == NULL) return -1; + + /* build the PDU structure onto the end of spdu_buf + */ + if (pdu_data) { + memcpy(cp, pdu_data, pdu_data_len); + cp += pdu_data_len; + } else { + cp = snmp_pdu_build(pdu, cp, &spdu_buf_len); + if (cp == NULL) return -1; + } + + + /* + * re-encode the actual ASN.1 length of the scopedPdu + */ + spdu_len = cp - spdu_hdr_e; /* length of scopedPdu minus ASN.1 headers */ + spdu_buf_len = SNMP_MAX_MSG_SIZE; + if (asn_build_sequence(spdu_buf, &spdu_buf_len, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + spdu_len) == NULL) + return -1; + spdu_len = cp - spdu_buf; /* the length of the entire scopedPdu */ + + + /* + * call the security module to possibly encrypt and authenticate the + * message - the entire message to transmitted on the wire is returned + */ + cp = NULL; *out_length = SNMP_MAX_MSG_SIZE; + result = + usm_generate_out_msg( + SNMP_VERSION_3, + global_data, global_data_len, + SNMP_MAX_MSG_SIZE, + SNMP_SEC_MODEL_USM, + pdu->securityEngineID, pdu->securityEngineIDLen, + pdu->securityName, pdu->securityNameLen, + pdu->securityLevel, + spdu_buf, spdu_len, + pdu->securityStateRef, + sec_params, &sec_params_len, + &cp, out_length); + + return result; + +} /* end snmpv3_packet_build() */ + + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +static int +_snmp_build(struct snmp_session *session, + struct snmp_pdu *pdu, + u_char *packet, + size_t *out_length) +{ + u_char *h0, *h0e = 0, *h1; + u_char *cp; + size_t length; + long version; + + session->s_snmp_errno = 0; + session->s_errno = 0; + + if (pdu->version == SNMP_VERSION_3) + return snmpv3_build(session, pdu, packet, out_length); + + switch (pdu->command) { + case SNMP_MSG_RESPONSE: + pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE); + /* Fallthrough */ + case SNMP_MSG_GET: + case SNMP_MSG_GETNEXT: + case SNMP_MSG_SET: + /* all versions support these PDU types */ + /* initialize defaulted PDU fields */ + + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + break; + + case SNMP_MSG_TRAP2: + pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE); + /* Fallthrough */ + case SNMP_MSG_INFORM: + /* not supported in SNMPv1 and SNMPsec */ + if (pdu->version == SNMP_VERSION_1) { + session->s_snmp_errno = SNMPERR_V2_IN_V1; + return -1; + } + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + break; + + case SNMP_MSG_GETBULK: + /* not supported in SNMPv1 and SNMPsec */ + if (pdu->version == SNMP_VERSION_1) { + session->s_snmp_errno = SNMPERR_V2_IN_V1; + return -1; + } + if (pdu->max_repetitions < 0) { + session->s_snmp_errno = SNMPERR_BAD_REPETITIONS; + return -1; + } + if (pdu->non_repeaters < 0) { + session->s_snmp_errno = SNMPERR_BAD_REPEATERS; + return -1; + } + break; + + case SNMP_MSG_TRAP: + /* *only* supported in SNMPv1 and SNMPsec */ + if (pdu->version != SNMP_VERSION_1) { + session->s_snmp_errno = SNMPERR_V1_IN_V2; + return -1; + } + /* initialize defaulted Trap PDU fields */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)malloc(sizeof(DEFAULT_ENTERPRISE)); + memmove(pdu->enterprise, DEFAULT_ENTERPRISE, + sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + /* don't expect a response */ + pdu->flags &= (~UCD_MSG_FLAG_EXPECT_RESPONSE); + break; + + case SNMP_MSG_REPORT: /* SNMPv3 only */ + default: + session->s_snmp_errno = SNMPERR_UNKNOWN_PDU; + return -1; + } + + /* save length */ + length = *out_length; + + /* setup administrative fields based on version */ + /* build the message wrapper and all the administrative fields + upto the PDU sequence + (note that actual length of message will be inserted later) */ + h0 = packet; + switch (pdu->version) { + case SNMP_VERSION_1: + case SNMP_VERSION_2c: +#ifdef NO_ZEROLENGTH_COMMUNITY + if (pdu->community_len == 0){ + if (session->community_len == 0){ + session->s_snmp_errno = SNMPERR_BAD_ADDRESS; + return -1; + } + pdu->community = (u_char *)malloc(session->community_len); + memmove(pdu->community, session->community, + session->community_len); + pdu->community_len = session->community_len; + } +#else /* !NO_ZEROLENGTH_COMMUNITY */ + if (! (pdu->community_len != 0 && + pdu->command == SNMP_MSG_RESPONSE )) { + /* copy session community exactly to pdu community */ + if (0 == session->community_len) { + SNMP_FREE(pdu->community); pdu->community = 0; + } + else if (pdu->community_len == session->community_len) { + memmove(pdu->community, session->community, + session->community_len); + } + else { + SNMP_FREE(pdu->community); + pdu->community = (u_char *)malloc(session->community_len); + memmove(pdu->community, session->community, + session->community_len); + } + pdu->community_len = session->community_len; + } +#endif /* !NO_ZEROLENGTH_COMMUNITY */ + + DEBUGMSGTL(("snmp_send","Building SNMPv%d message...\n", (1 + pdu->version))); + /* Save current location and build SEQUENCE tag and length + placeholder for SNMP message sequence + (actual length will be inserted later) */ + cp = asn_build_sequence(packet, out_length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + 0); + if (cp == NULL) + return -1; + h0e = cp; + + /* store the version field */ + version = pdu->version; + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &version, sizeof(version)); + if (cp == NULL) + return -1; + + /* store the community string */ + cp = asn_build_string(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), + pdu->community, pdu->community_len); + if (cp == NULL) + return -1; + break; + + case SNMP_VERSION_2p: + case SNMP_VERSION_sec: + case SNMP_VERSION_2u: + case SNMP_VERSION_2star: + default: + session->s_snmp_errno = SNMPERR_BAD_VERSION; + return -1; + } + + h1 = cp; + cp = snmp_pdu_build(pdu, cp, out_length); + if (cp == NULL) + return -1; + + /* insert the actual length of the message sequence */ + switch (pdu->version) { + case SNMP_VERSION_1: + case SNMP_VERSION_2c: + asn_build_sequence(packet, &length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + cp - h0e); + break; + + case SNMP_VERSION_2p: + case SNMP_VERSION_sec: + case SNMP_VERSION_2u: + case SNMP_VERSION_2star: + default: + session->s_snmp_errno = SNMPERR_BAD_VERSION; + return -1; + } + *out_length = cp - packet; + return 0; +} + +int +snmp_build(struct snmp_session *pss, + struct snmp_pdu *pdu, + u_char *packet, + size_t *out_length) +{ + int rc; + rc = _snmp_build(pss,pdu,packet,out_length); + if (rc) { + if ( !pss->s_snmp_errno) + pss->s_snmp_errno = SNMPERR_BAD_ASN1_BUILD; + SET_SNMP_ERROR(pss->s_snmp_errno); + rc = -1; + } + return rc; +} + +/* on error, returns NULL (likely an encoding problem). */ +u_char * +snmp_pdu_build (struct snmp_pdu *pdu, u_char *cp, size_t *out_length) +{ + u_char *h1, *h1e, *h2, *h2e; + struct variable_list *vp; + struct sockaddr_in *pduIp = (struct sockaddr_in *)&(pdu->agent_addr); + size_t length; + + length = *out_length; + /* Save current location and build PDU tag and length placeholder + (actual length will be inserted later) */ + h1 = cp; + cp = asn_build_sequence(cp, out_length, (u_char)pdu->command, 0); + if (cp == NULL) + return NULL; + h1e = cp; + + /* store fields in the PDU preceeding the variable-bindings sequence */ + if (pdu->command != SNMP_MSG_TRAP){ + /* PDU is not an SNMPv1 trap */ + + /* request id */ + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return NULL; + + /* error status (getbulk non-repeaters) */ + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return NULL; + + /* error index (getbulk max-repetitions) */ + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return NULL; + } else { + /* an SNMPv1 trap PDU */ + + /* enterprise */ + cp = asn_build_objid(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return NULL; + + /* agent-addr */ + cp = asn_build_string(cp, out_length, + (u_char)(ASN_IPADDRESS | ASN_PRIMITIVE), + (u_char *)&pduIp->sin_addr.s_addr, + sizeof(pduIp->sin_addr.s_addr)); + if (cp == NULL) + return NULL; + + /* generic trap */ + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return NULL; + + /* specific trap */ + cp = asn_build_int(cp, out_length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return NULL; + + /* timestamp */ + cp = asn_build_unsigned_int(cp, out_length, + (u_char)(ASN_TIMETICKS | ASN_PRIMITIVE), + &pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return NULL; + } + + /* Save current location and build SEQUENCE tag and length placeholder + for variable-bindings sequence + (actual length will be inserted later) */ + h2 = cp; + cp = asn_build_sequence(cp, out_length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + 0); + if (cp == NULL) + return NULL; + h2e = cp; + + /* Store variable-bindings */ + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, + vp->val_len, (u_char *)vp->val.string, + out_length); + if (cp == NULL) + return NULL; + } + + /* insert actual length of variable-bindings sequence */ + asn_build_sequence(h2,&length,(u_char)(ASN_SEQUENCE|ASN_CONSTRUCTOR),cp-h2e); + + /* insert actual length of PDU sequence */ + asn_build_sequence(h1, &length, (u_char)pdu->command, cp - h1e); + + return cp; +} + + +/* + * Parses the packet received to determine version, either directly + * from packets version field or inferred from ASN.1 construct. + */ +static int +snmp_parse_version (u_char *data, size_t length) +{ + u_char type; + long version = SNMPERR_BAD_VERSION; + + data = asn_parse_sequence(data, &length, &type, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), "version"); + if (data) { + data = asn_parse_int(data, &length, &type, &version, sizeof(version)); + if (!data) return SNMPERR_BAD_VERSION; + } + return version; +} + + +int +snmpv3_parse( + struct snmp_pdu *pdu, + u_char *data, + size_t *length, + u_char **after_header) +{ + u_char type, msg_flags; + long ver, msg_max_size, msg_sec_model; + size_t max_size_response; + u_char tmp_buf[SNMP_MAX_MSG_SIZE]; + size_t tmp_buf_len; + u_char pdu_buf[SNMP_MAX_MSG_SIZE]; + size_t pdu_buf_len = SNMP_MAX_MSG_SIZE; + u_char *sec_params; + u_char *msg_data; + u_char *cp; + size_t asn_len, msg_len; + int ret, ret_val; + + + msg_data = data; + msg_len = *length; + + + /* message is an ASN.1 SEQUENCE + */ + DEBUGDUMPHEADER("dump_recv", "Parsing SNMPv3 Message\n"); + data = asn_parse_sequence(data, length, &type, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), "message"); + if (data == NULL){ + /* error msg detail is set */ + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + DEBUGINDENTLESS(); + return SNMPERR_ASN_PARSE_ERR; + } + + /* parse msgVersion + */ + DEBUGDUMPHEADER("dump_recv", "Parsing SNMPv3 Version Number\n"); + data = asn_parse_int(data, length, &type, &ver, sizeof(ver)); + DEBUGINDENTLESS(); + if (data == NULL){ + ERROR_MSG("bad parse of version"); + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + DEBUGINDENTLESS(); + return SNMPERR_ASN_PARSE_ERR; + } + pdu->version = ver; + + /* parse msgGlobalData sequence + */ + cp = data; + asn_len = *length; + DEBUGDUMPHEADER("dump_recv", "Parsing msgGlobalData\n"); + data = asn_parse_sequence(data, &asn_len, &type, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), "msgGlobalData"); + if (data == NULL){ + /* error msg detail is set */ + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + DEBUGINDENTADD(-4); + return SNMPERR_ASN_PARSE_ERR; + } + *length -= data - cp; /* subtract off the length of the header */ + + /* msgID */ + DEBUGDUMPHEADER("dump_recv", "Parsing msgID\n"); + data = asn_parse_int(data, length, &type, &pdu->msgid, sizeof(pdu->msgid)); + DEBUGINDENTLESS(); + if (data == NULL) { + ERROR_MSG("error parsing msgID"); + DEBUGINDENTADD(-4); + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + return SNMPERR_ASN_PARSE_ERR; + } + + /* msgMaxSize */ + DEBUGDUMPHEADER("dump_recv", "Parsing msgMaxSize\n"); + data = asn_parse_int(data, length, &type, &msg_max_size, + sizeof(msg_max_size)); + DEBUGINDENTLESS(); + if (data == NULL) { + ERROR_MSG("error parsing msgMaxSize"); + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + DEBUGINDENTADD(-4); + return SNMPERR_ASN_PARSE_ERR; + } + + /* msgFlags */ + tmp_buf_len = SNMP_MAX_MSG_SIZE; + DEBUGDUMPHEADER("dump_recv", "Parsing msgFlags\n"); + data = asn_parse_string(data, length, &type, tmp_buf, &tmp_buf_len); + DEBUGINDENTLESS(); + if (data == NULL || tmp_buf_len != 1) { + ERROR_MSG("error parsing msgFlags"); + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + DEBUGINDENTADD(-4); + return SNMPERR_ASN_PARSE_ERR; + } + msg_flags = *tmp_buf; + if (msg_flags & SNMP_MSG_FLAG_RPRT_BIT) + pdu->flags |= SNMP_MSG_FLAG_RPRT_BIT; + else + pdu->flags &= (~SNMP_MSG_FLAG_RPRT_BIT); + + /* msgSecurityModel */ + DEBUGDUMPHEADER("dump_recv", "Parsing msgSecurityModel\n"); + data = asn_parse_int(data, length, &type, &msg_sec_model, + sizeof(msg_sec_model)); + DEBUGINDENTADD(-4); /* return from global data indent */ + if (data == NULL) { + ERROR_MSG("error parsing msgSecurityModel"); + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + DEBUGINDENTLESS(); + return SNMPERR_ASN_PARSE_ERR; + } + if (msg_sec_model != SNMP_SEC_MODEL_USM) { + ERROR_MSG("unknown security model"); + snmp_increment_statistic(STAT_SNMPUNKNOWNSECURITYMODELS); + DEBUGINDENTLESS(); + return SNMPERR_UNKNOWN_SEC_MODEL; + } + pdu->securityModel = msg_sec_model; + + if (msg_flags & SNMP_MSG_FLAG_PRIV_BIT && + !(msg_flags & SNMP_MSG_FLAG_AUTH_BIT)) { + ERROR_MSG("invalid message, illegal msgFlags"); + snmp_increment_statistic(STAT_SNMPINVALIDMSGS); + DEBUGINDENTLESS(); + return SNMPERR_INVALID_MSG; + } + pdu->securityLevel = ( (msg_flags & SNMP_MSG_FLAG_AUTH_BIT) + ? ( (msg_flags & SNMP_MSG_FLAG_PRIV_BIT) + ? SNMP_SEC_LEVEL_AUTHPRIV + : SNMP_SEC_LEVEL_AUTHNOPRIV ) + : SNMP_SEC_LEVEL_NOAUTH ); + /* end of msgGlobalData */ + + /* securtityParameters OCTET STRING begins after msgGlobalData */ + sec_params = data; + pdu->contextEngineID = (u_char *)calloc(1,SNMP_MAX_ENG_SIZE); + pdu->contextEngineIDLen = SNMP_MAX_ENG_SIZE; + pdu->securityEngineID = (u_char *)calloc(1,SNMP_MAX_ENG_SIZE); + pdu->securityEngineIDLen = SNMP_MAX_ENG_SIZE; + pdu->securityName = (char *)calloc(1,SNMP_MAX_SEC_NAME_SIZE); + pdu->securityNameLen = SNMP_MAX_SEC_NAME_SIZE; + + memset(pdu_buf, 0, pdu_buf_len); + cp = pdu_buf; + + DEBUGDUMPHEADER("dump_recv", "Parsing USM msgSecurityParameters\n"); + ret_val = usm_process_in_msg(SNMP_VERSION_3, msg_max_size, + sec_params, msg_sec_model, pdu->securityLevel, + msg_data, msg_len, + pdu->securityEngineID, &pdu->securityEngineIDLen, + pdu->securityName, &pdu->securityNameLen, + &cp, + &pdu_buf_len, &max_size_response, + &pdu->securityStateRef); + DEBUGINDENTLESS(); + + if (ret_val != SNMPERR_SUCCESS) { + snmpv3_scopedPDU_parse(pdu, cp, &pdu_buf_len); /* DO ignore return code */ + DEBUGINDENTLESS(); + return ret_val; + } + + /* parse plaintext ScopedPDU sequence */ + *length = pdu_buf_len; + DEBUGDUMPHEADER("dump_recv", "Parsing ScopedPdu\n"); + data = snmpv3_scopedPDU_parse(pdu, cp, length); + if (data == NULL) { + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + DEBUGINDENTADD(-4); + return SNMPERR_ASN_PARSE_ERR; + } + + /* parse the PDU. + */ + if (after_header != NULL) { + tmp_buf_len = *length; + *after_header = data; + } + + DEBUGDUMPHEADER("dump_recv", "Parsing PDU\n"); + ret = snmp_pdu_parse(pdu, data, length); + DEBUGINDENTADD(-8); + + if (after_header != NULL) + *length = tmp_buf_len; + + if (ret != SNMPERR_SUCCESS) { + ERROR_MSG("error parsing PDU"); + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + return SNMPERR_ASN_PARSE_ERR; + } + + return SNMPERR_SUCCESS; +} /* end snmpv3_parse() */ + +#define ERROR_STAT_LENGTH 11 + +int +snmpv3_make_report(struct snmp_pdu *pdu, int error) +{ + + long ltmp; + static oid unknownSecurityLevel[] = {1,3,6,1,6,3,15,1,1,1,0}; + static oid notInTimeWindow[] = {1,3,6,1,6,3,15,1,1,2,0}; + static oid unknownUserName[] = {1,3,6,1,6,3,15,1,1,3,0}; + static oid unknownEngineID[] = {1,3,6,1,6,3,15,1,1,4,0}; + static oid wrongDigest[] = {1,3,6,1,6,3,15,1,1,5,0}; + static oid decryptionError[] = {1,3,6,1,6,3,15,1,1,6,0}; + oid *err_var; + int err_var_len; + int stat_ind; + + switch (error) { + case SNMPERR_USM_UNKNOWNENGINEID: + stat_ind = STAT_USMSTATSUNKNOWNENGINEIDS; + err_var = unknownEngineID; + err_var_len = ERROR_STAT_LENGTH; + break; + case SNMPERR_USM_UNKNOWNSECURITYNAME: + stat_ind = STAT_USMSTATSUNKNOWNUSERNAMES; + err_var = unknownUserName; + err_var_len = ERROR_STAT_LENGTH; + break; + case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL: + stat_ind = STAT_USMSTATSUNSUPPORTEDSECLEVELS; + err_var = unknownSecurityLevel; + err_var_len = ERROR_STAT_LENGTH; + break; + case SNMPERR_USM_AUTHENTICATIONFAILURE: + stat_ind = STAT_USMSTATSWRONGDIGESTS; + err_var = wrongDigest; + err_var_len = ERROR_STAT_LENGTH; + break; + case SNMPERR_USM_NOTINTIMEWINDOW: + stat_ind = STAT_USMSTATSNOTINTIMEWINDOWS; + err_var = notInTimeWindow; + err_var_len = ERROR_STAT_LENGTH; + break; + case SNMPERR_USM_DECRYPTIONERROR: + stat_ind = STAT_USMSTATSDECRYPTIONERRORS; + err_var = decryptionError; + err_var_len = ERROR_STAT_LENGTH; + break; + default: + return SNMPERR_GENERR; + break; + } + + snmp_free_varbind(pdu->variables); /* free the current varbind */ + + pdu->variables = NULL; + SNMP_FREE(pdu->securityEngineID); + pdu->securityEngineID = snmpv3_generate_engineID(&pdu->securityEngineIDLen); + SNMP_FREE(pdu->contextEngineID); + pdu->contextEngineID = snmpv3_generate_engineID(&pdu->contextEngineIDLen); + pdu->command = SNMP_MSG_REPORT; + pdu->errstat = 0; + pdu->errindex = 0; + pdu->contextName = strdup(""); + pdu->contextNameLen = strlen(pdu->contextName); + + /* reports shouldn't cache previous data. */ + /* FIX - yes they should but USM needs to follow new EoP to determine + which cached values to use + */ + if (pdu->securityStateRef) { + usm_free_usmStateReference(pdu->securityStateRef); + pdu->securityStateRef = NULL; + } + + if (error != SNMPERR_USM_NOTINTIMEWINDOW) + pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH; + else + pdu->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; + + /* find the appropriate error counter + */ + ltmp = snmp_get_statistic(stat_ind); + + /* return the appropriate error counter + */ + snmp_pdu_add_variable(pdu, err_var, err_var_len, + ASN_COUNTER, (u_char *) <mp, sizeof(ltmp)); + + return SNMPERR_SUCCESS; +} /* end snmpv3_make_report() */ + + +int +snmpv3_get_report_type(struct snmp_pdu *pdu) +{ + static oid snmpMPDStats[] = {1,3,6,1,6,3,11,2,1}; + static oid usmStats[] = {1,3,6,1,6,3,15,1,1}; + struct variable_list *vp; + int rpt_type = SNMPERR_UNKNOWN_REPORT; + + if (pdu == NULL || pdu->variables == NULL) return rpt_type; + vp = pdu->variables; + if (vp->name_length == REPORT_STATS_LEN+2) { + if (memcmp(snmpMPDStats,vp->name,REPORT_STATS_LEN*sizeof(oid)) == 0) { + switch (vp->name[REPORT_STATS_LEN]) { + case REPORT_snmpUnknownSecurityModels_NUM: + rpt_type = SNMPERR_UNKNOWN_SEC_MODEL; + break; + case REPORT_snmpInvalidMsgs_NUM: + rpt_type = SNMPERR_INVALID_MSG; + break; + } + } else if (memcmp(usmStats,vp->name,REPORT_STATS_LEN*sizeof(oid)) == 0) { + switch (vp->name[REPORT_STATS_LEN]) { + case REPORT_usmStatsUnsupportedSecLevels_NUM: + rpt_type = SNMPERR_UNSUPPORTED_SEC_LEVEL; + break; + case REPORT_usmStatsNotInTimeWindows_NUM: + rpt_type = SNMPERR_NOT_IN_TIME_WINDOW; + break; + case REPORT_usmStatsUnknownUserNames_NUM: + rpt_type = SNMPERR_UNKNOWN_USER_NAME; + break; + case REPORT_usmStatsUnknownEngineIDs_NUM: + rpt_type = SNMPERR_UNKNOWN_ENG_ID; + break; + case REPORT_usmStatsWrongDigests_NUM: + rpt_type = SNMPERR_AUTHENTICATION_FAILURE; + break; + case REPORT_usmStatsDecryptionErrors_NUM: + rpt_type = SNMPERR_DECRYPTION_ERR; + break; + } + } + } + DEBUGMSGTL(("report", "Report type: %d\n", rpt_type)); + return rpt_type; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. + * If any errors are encountered, -1 or USM error is returned. + * Otherwise, a 0 is returned. + */ +static int +_snmp_parse(void * sessp, + struct snmp_session *session, + struct snmp_pdu *pdu, + u_char *data, + size_t length) +{ + u_char community[COMMUNITY_MAX_LEN]; + size_t community_length = COMMUNITY_MAX_LEN; + int result = -1; + + session->s_snmp_errno = 0; + session->s_errno = 0; + + /* Ensure all incoming PDUs have a unique means of identification + (This is not restricted to AgentX handling, + though that is where the need becomes visible) */ + pdu->transid = snmp_get_next_transid(); + + if (session->version != SNMP_DEFAULT_VERSION) + pdu->version = session->version; + else + pdu->version = snmp_parse_version(data,length); + + switch (pdu->version) { + case SNMP_VERSION_1: + case SNMP_VERSION_2c: + DEBUGMSGTL(("snmp_api","Parsing SNMPv%d message...\n", (1 + pdu->version))); + + /* authenticates message and returns length if valid */ + DEBUGDUMPSETUP("dump_recv", data, 4); + DEBUGMSG(("dump_recv", "SNMPv%d message\n", (1+pdu->version))); + + DEBUGINDENTMORE(); + data = snmp_comstr_parse(data, &length, + community, &community_length, + &pdu->version); + DEBUGINDENTLESS(); + if (data == NULL) + return -1; + + if (pdu->version != session->version && + session->version != SNMP_DEFAULT_VERSION) + { + session->s_snmp_errno = SNMPERR_BAD_VERSION; + return -1; + } + + /* maybe get the community string. */ + pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH; + pdu->securityModel = (pdu->version == SNMP_VERSION_1) ? + SNMP_SEC_MODEL_SNMPv1 : SNMP_SEC_MODEL_SNMPv2c; + SNMP_FREE(pdu->community); + pdu->community_len = 0; + pdu->community = (u_char *)0; + if (community_length) { + pdu->community_len = community_length; + pdu->community = (u_char *)malloc(community_length); + memmove(pdu->community, community, community_length); + } + if (session->authenticator){ + data = session->authenticator(data, &length, + community, + community_length); + if (data == NULL) + { + session->s_snmp_errno = SNMPERR_AUTHENTICATION_FAILURE; + return -1; + } + } + result = snmp_pdu_parse(pdu, data, &length); + break; + + case SNMP_VERSION_3: + result = snmpv3_parse(pdu, data, &length, NULL); + DEBUGMSGTL(("snmp_parse", + "Parsed SNMPv3 message (secName:%s, secLevel:%s): %s\n", + pdu->securityName, usmSecLevelName[pdu->securityLevel], + snmp_api_errstring(result))); + + if (result) { + if (!sessp) + session->s_snmp_errno = result; + else + + /* handle reportable errors */ + switch (result) { + case SNMPERR_USM_UNKNOWNENGINEID: + case SNMPERR_USM_UNKNOWNSECURITYNAME: + case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL: + case SNMPERR_USM_AUTHENTICATIONFAILURE: + case SNMPERR_USM_NOTINTIMEWINDOW: + case SNMPERR_USM_DECRYPTIONERROR: + if (SNMP_CMD_CONFIRMED(pdu->command) || + (pdu->command == 0 && + (pdu->flags & SNMP_MSG_FLAG_RPRT_BIT ))) { + struct snmp_pdu *pdu2; + int flags = pdu->flags; + pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; + pdu2 = snmp_clone_pdu(pdu); + pdu->flags = pdu2->flags = flags; + snmpv3_make_report(pdu2, result); + snmp_sess_send(sessp, pdu2); + } + break; + default: + session->s_snmp_errno = result; + break; + } + } + break; + case SNMPERR_BAD_VERSION: + ERROR_MSG("error parsing snmp message version"); + snmp_increment_statistic(STAT_SNMPINASNPARSEERRS); + session->s_snmp_errno = SNMPERR_BAD_VERSION; + break; + case SNMP_VERSION_sec: + case SNMP_VERSION_2u: + case SNMP_VERSION_2star: + case SNMP_VERSION_2p: + default: + ERROR_MSG("unsupported snmp message version"); + snmp_increment_statistic(STAT_SNMPINBADVERSIONS); + session->s_snmp_errno = SNMPERR_BAD_VERSION; + break; + } + + return result; +} + +static int +snmp_parse(void *sessp, + struct snmp_session *pss, + struct snmp_pdu *pdu, + u_char *data, + size_t length) +{ + int rc; + + rc = _snmp_parse(sessp,pss,pdu,data,length); + if (rc) { + if ( !pss->s_snmp_errno) + pss->s_snmp_errno = SNMPERR_BAD_PARSE; + SET_SNMP_ERROR(pss->s_snmp_errno); + } + + return rc; +} + +int +snmp_pdu_parse(struct snmp_pdu *pdu, u_char *data, size_t *length) { + u_char type; + u_char msg_type; + u_char *var_val; + int badtype; + size_t len; + size_t four; + struct variable_list *vp = NULL; + struct sockaddr_in *pduIp = (struct sockaddr_in *)&(pdu->agent_addr); + oid objid[MAX_OID_LEN]; + + badtype = 0; + + DEBUGPRINTINDENT("dump_recv"); + DEBUGINDENTMORE(); + DEBUGMSG(("dump_recv", "PDU\n")); + /* Get the PDU type */ + data = asn_parse_header(data, length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + pdu->flags &= (~UCD_MSG_FLAG_RESPONSE_PDU); + + /* get the fields in the PDU preceeding the variable-bindings sequence */ + switch (pdu->command) { + case SNMP_MSG_TRAP: + /* enterprise */ + pdu->enterprise_length = MAX_OID_LEN; + data = asn_parse_objid(data, length, &type, objid, + &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)malloc(pdu->enterprise_length * sizeof(oid)); + memmove(pdu->enterprise, objid, pdu->enterprise_length * sizeof(oid)); + + /* agent-addr */ + four = 4; + pduIp->sin_family = AF_INET; + data = asn_parse_string(data, length, &type, + (u_char *)&pduIp->sin_addr.s_addr, + &four); + if (data == NULL) + return -1; + + /* generic trap */ + data = asn_parse_int(data, length, &type, (long *)&pdu->trap_type, + sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + /* specific trap */ + data = asn_parse_int(data, length, &type, (long *)&pdu->specific_type, + sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + + /* timestamp */ + data = asn_parse_unsigned_int(data, length, &type, &pdu->time, + sizeof(pdu->time)); + if (data == NULL) + return -1; + + break; + + case SNMP_MSG_RESPONSE: + case SNMP_MSG_REPORT: + pdu->flags |= UCD_MSG_FLAG_RESPONSE_PDU; + /* fallthrough */ + + default: + /* PDU is not an SNMPv1 TRAP */ + + /* request id */ + DEBUGDUMPHEADER("dump_recv", "Parsing request_id\n"); + data = asn_parse_int(data, length, &type, &pdu->reqid, + sizeof(pdu->reqid)); + DEBUGINDENTLESS(); + if (data == NULL) { + return -1; + } + + /* error status (getbulk non-repeaters) */ + DEBUGDUMPHEADER("dump_recv", "Parsing error status\n"); + data = asn_parse_int(data, length, &type, &pdu->errstat, + sizeof(pdu->errstat)); + DEBUGINDENTLESS(); + if (data == NULL) { + return -1; + } + + /* error index (getbulk max-repetitions) */ + DEBUGDUMPHEADER("dump_recv", "Parsing error index\n"); + data = asn_parse_int(data, length, &type, &pdu->errindex, + sizeof(pdu->errindex)); + DEBUGINDENTLESS(); + if (data == NULL) { + return -1; + } + } + + /* get header for variable-bindings sequence */ + DEBUGDUMPHEADER("dump_recv", "VarBindList:\n"); + data = asn_parse_sequence(data, length, &type, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), "varbinds"); + if (data == NULL) + return -1; + + /* get each varBind sequence */ + while((int)*length > 0){ + struct variable_list *vptemp; + vptemp = (struct variable_list *)malloc(sizeof(*vptemp)); + if (0 == vptemp) { + return -1; + } + if (0 == vp){ + pdu->variables = vptemp; + } else { + vp->next_variable = vptemp; + } + vp = vptemp; + + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name_length = MAX_OID_LEN; + vp->name = 0; + DEBUGDUMPHEADER("dump_recv", "VarBind:\n"); + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, + &vp->val_len, &var_val, length); + if (data == NULL) + return -1; + if (snmp_set_var_objid(vp, objid, vp->name_length)) + return -1; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)vp->buf; + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, + (long *)vp->val.integer, + sizeof(vp->val.integer)); + break; + case ASN_COUNTER: + case ASN_GAUGE: + case ASN_TIMETICKS: + case ASN_UINTEGER: + vp->val.integer = (long *)vp->buf; + vp->val_len = sizeof(u_long); + asn_parse_unsigned_int(var_val, &len, &vp->type, + (u_long *)vp->val.integer, + sizeof(vp->val.integer)); + break; +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_COUNTER64: + case ASN_OPAQUE_U64: +#endif /* OPAQUE_SPECIAL_TYPES */ + case ASN_COUNTER64: + vp->val.counter64 = (struct counter64 *)vp->buf; + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_FLOAT: + vp->val.floatVal = (float *)vp->buf; + vp->val_len = sizeof(float); + asn_parse_float(var_val, &len, &vp->type, + vp->val.floatVal, + vp->val_len); + break; + case ASN_OPAQUE_DOUBLE: + vp->val.doubleVal = (double *)vp->buf; + vp->val_len = sizeof(double); + asn_parse_double(var_val, &len, &vp->type, + vp->val.doubleVal, + vp->val_len); + break; + case ASN_OPAQUE_I64: + vp->val.counter64 = (struct counter64 *)vp->buf; + vp->val_len = sizeof(struct counter64); + asn_parse_signed_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + + break; +#endif /* OPAQUE_SPECIAL_TYPES */ + case ASN_OCTET_STR: + case ASN_IPADDRESS: + case ASN_OPAQUE: + case ASN_NSAP: + if (vp->val_len < sizeof(vp->buf)){ + vp->val.string = (u_char *)vp->buf; + } else { + vp->val.string = (u_char *)malloc((unsigned)vp->val_len); + } + asn_parse_string(var_val, &len, &vp->type, vp->val.string, + &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_OID_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)malloc((unsigned)vp->val_len); + memmove(vp->val.objid, objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + case ASN_BIT_STR: + vp->val.bitstring = (u_char *)malloc(vp->val_len); + asn_parse_bitstring(var_val, &len, &vp->type, + vp->val.bitstring, &vp->val_len); + break; + default: + snmp_log(LOG_ERR,"bad type returned (%x)\n", vp->type); + badtype = 1; + break; + } + DEBUGINDENTLESS(); + } + DEBUGINDENTLESS(); + DEBUGINDENTLESS(); + return badtype; +} + +/* snmp v3 utility function to parse into the scopedPdu. stores contextName + and contextEngineID in pdu struct. Also stores pdu->command (handy for + Report generation). + + returns pointer to begining of PDU or NULL on error. +*/ +u_char * +snmpv3_scopedPDU_parse(struct snmp_pdu *pdu, + u_char *cp, + size_t *length) +{ + u_char tmp_buf[SNMP_MAX_MSG_SIZE]; + size_t tmp_buf_len; + u_char type; + size_t asn_len; + u_char* data; + + pdu->command = 0; /* initialize so we know if it got parsed */ + asn_len = *length; + data = asn_parse_sequence(cp, &asn_len, &type, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), "plaintext scopedPDU"); + if (data == NULL){ + return NULL; + } + *length -= data - cp; + + /* contextEngineID from scopedPdu */ + DEBUGDUMPHEADER("dump_recv", "Parsing contextEngineID\n"); + data = asn_parse_string(data, length, &type, pdu->contextEngineID, + &pdu->contextEngineIDLen); + DEBUGINDENTLESS(); + if (data == NULL) { + ERROR_MSG("error parsing contextEngineID from scopedPdu"); + return NULL; + } + + /* check that it agrees with engineID returned from USM above + * only a warning because this could be legal if we are a proxy + */ + if (pdu->securityEngineIDLen != pdu->contextEngineIDLen || + memcmp(pdu->securityEngineID, pdu->contextEngineID, + pdu->securityEngineIDLen) != 0) { + DEBUGMSGTL(("scopedPDU_parse", + "inconsistent engineID information in message\n")); + } + + /* parse contextName from scopedPdu + */ + tmp_buf_len = SNMP_MAX_CONTEXT_SIZE; + DEBUGDUMPHEADER("dump_recv", "Parsing contextName\n"); + data = asn_parse_string(data, length, &type, tmp_buf, &tmp_buf_len); + DEBUGINDENTLESS(); + if (data == NULL) { + ERROR_MSG("error parsing contextName from scopedPdu"); + return NULL; + } + + if (tmp_buf_len) { + pdu->contextName = (char *)malloc(tmp_buf_len); + memmove(pdu->contextName, tmp_buf, tmp_buf_len); + pdu->contextNameLen = tmp_buf_len; + } else { + pdu->contextName = strdup(""); + pdu->contextNameLen = 0; + } + + /* Get the PDU type */ + asn_len = *length; + DEBUGDUMPHEADER("dump_recv", "Parsing PDU type\n"); + cp = asn_parse_header(data, &asn_len, &type); + DEBUGINDENTLESS(); + if (cp == NULL) + return NULL; + + pdu->command = type; + + return data; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(struct snmp_session *session, + struct snmp_pdu *pdu) +{ + return snmp_async_send(session, pdu, NULL, NULL); +} + +int +snmp_sess_send(void *sessp, + struct snmp_pdu *pdu) +{ + return snmp_sess_async_send(sessp, pdu, NULL, NULL); +} + +/* + * int snmp_async_send(session, pdu, callback, cb_data) + * struct snmp_session *session; + * struct snmp_pdu *pdu; + * snmp_callback callback; + * void *cb_data; + * + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session and store callback and data, + * then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 0. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occurred. + */ +int +snmp_async_send(struct snmp_session *session, + struct snmp_pdu *pdu, + snmp_callback callback, + void *cb_data) +{ + void *sessp = snmp_sess_pointer(session); + return snmp_sess_async_send(sessp, pdu, callback, cb_data); +} + +static int +_sess_async_send(void *sessp, + struct snmp_pdu *pdu, + snmp_callback callback, + void *cb_data) +{ + struct session_list *slp = (struct session_list *)sessp; + struct snmp_session *session; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + size_t length = PACKET_LENGTH; + struct sockaddr_in *isp_addr; + struct sockaddr_in *pduIp; + int result, addr_size; + long reqid; + + session = slp->session; isp = slp->internal; + if (!session || !isp) { + DEBUGMSGTL(("sess_read","send fail: closing...\n")); + return 0; + } + + session->s_snmp_errno = 0; + session->s_errno = 0; + + if (pdu == NULL) { + session->s_snmp_errno = SNMPERR_NULL_PDU; + return 0; + } +#if TEMPORARILY_DISABLED + /* + * NULL variable are allowed in certain PDU types. + * In particular, SNMPv3 engineID probes are of this form. + * There is an internal PDU flag to indicate that this + * is acceptable, but until the construction of engineID + * probes can be amended to set this flag, we'll simply + * skip this test altogether. + */ + if (pdu->variables == NULL) { + switch (pdu->command) { + case SNMP_MSG_GET: + case SNMP_MSG_SET: + case SNMP_MSG_GETNEXT: + case SNMP_MSG_GETBULK: + case SNMP_MSG_RESPONSE: + case SNMP_MSG_TRAP2: + case SNMP_MSG_REPORT: + case SNMP_MSG_INFORM: + session->s_snmp_errno = snmp_errno = SNMPERR_NO_VARS; + return 0; + case SNMP_MSG_TRAP: + break; + } + } +#endif + + pduIp = (struct sockaddr_in *)&(pdu->address); + pdu->flags |= UCD_MSG_FLAG_EXPECT_RESPONSE; + + /* check/setup the version */ + if (pdu->version == SNMP_DEFAULT_VERSION) { + if (session->version == SNMP_DEFAULT_VERSION) { + session->s_snmp_errno = SNMPERR_BAD_VERSION; + return 0; + } + pdu->version = session->version; + } else if (session->version == SNMP_DEFAULT_VERSION) { + /* It's OK */ + } else if (pdu->version != session->version) { + /* ENHANCE: we should support multi-lingual sessions */ + session->s_snmp_errno = SNMPERR_BAD_VERSION; + return 0; + } + + if (pdu->address.sa_family == AF_UNSPEC){ + isp_addr = (struct sockaddr_in *)&(isp->addr); + if (isp->addr.sa_family == AF_UNSPEC || + (isp->addr.sa_family == AF_INET && + isp_addr->sin_addr.s_addr == SNMP_DEFAULT_ADDRESS)){ + session->s_snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + memmove(&pdu->address, &(isp->addr), sizeof(isp->addr)); + } + + addr_size = snmp_socket_length(pdu->address.sa_family); + + /* build the message to send */ + if (isp->hook_build) + result = isp->hook_build(session, pdu, packet, &length); + else + result = snmp_build(session, pdu, packet, &length); + if (result < 0){ + return 0; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET)){ + snmp_log(LOG_DEBUG, "\nSending %u bytes to %s:%hu\n", length, + inet_ntoa(pduIp->sin_addr), ntohs(pduIp->sin_port)); + xdump(packet, length, ""); + } + + /* send the message */ +#if !defined(__ECOS) + if ( session->flags & SNMP_FLAGS_STREAM_SOCKET ) { + result = send(isp->sd, (char *)packet, length, 0); + } + else +#endif + result = sendto(isp->sd, (char *)packet, length, 0, + (struct sockaddr *)&pdu->address, addr_size); + if ( result < 0){ + session->s_snmp_errno = SNMPERR_BAD_SENDTO; + session->s_errno = errno; + return 0; + } + + reqid = pdu->reqid; + + /* add to pending requests list if expect a response */ + if (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE) { + struct request_list *rp; + struct timeval tv; + + rp = (struct request_list *)calloc( 1, sizeof(struct request_list)); + if (rp == NULL) { + session->s_snmp_errno = SNMPERR_GENERR; + return 0; + } + + gettimeofday(&tv, (struct timezone *)0); + rp->pdu = pdu; + rp->request_id = pdu->reqid; + rp->message_id = pdu->msgid; + rp->callback = callback; + rp->cb_data = cb_data; + rp->retries = 0; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; + + /* XX lock should be per session ! */ + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + if (isp->requestsEnd){ + rp->next_request = isp->requestsEnd->next_request; + isp->requestsEnd->next_request = rp; + isp->requestsEnd = rp; + } else { + rp->next_request = isp->requests; + isp->requests = rp; + isp->requestsEnd = rp; + } + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); + } + else + snmp_free_pdu(pdu); /* free v1 or v2 TRAP PDU */ + + return reqid; +} + +int +snmp_sess_async_send(void *sessp, + struct snmp_pdu *pdu, + snmp_callback callback, + void *cb_data) +{ + int rc; + + if (sessp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; /*MTCRITICAL_RESOURCE*/ + return(0); + } + rc = _sess_async_send(sessp,pdu,callback,cb_data); + if (rc == 0) { + struct session_list *psl; + struct snmp_session *pss; + psl = (struct session_list *)sessp; + pss = psl->session; + SET_SNMP_ERROR(pss->s_snmp_errno); + } + return rc; +} + + +/* + * Frees the variable and any malloc'd data associated with it. + */ +void +snmp_free_var(struct variable_list *var) +{ + if (!var) return; + + if (var->name != var->name_loc) + SNMP_FREE(var->name); + if (var->val.string != var->buf) + SNMP_FREE(var->val.string); + + free((char *)var); +} + +void snmp_free_varbind(struct variable_list *var) +{ + struct variable_list *ptr; + while(var) { + ptr = var->next_variable; + snmp_free_var(var); + var = ptr; + } +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu *pdu) +{ + if (!pdu) return; + + snmp_free_varbind(pdu->variables); + SNMP_FREE(pdu->enterprise); + SNMP_FREE(pdu->community); + SNMP_FREE(pdu->contextEngineID); + SNMP_FREE(pdu->securityEngineID); + SNMP_FREE(pdu->contextName); + SNMP_FREE(pdu->securityName); + free((char *)pdu); +} + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fd_set *fdset) +{ + struct session_list *slp; + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + for(slp = Sessions; slp; slp = slp->next){ + snmp_sess_read((void *)slp, fdset); + } + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); +} + +/* Same as snmp_read, but works just one session. */ +/* returns 0 if success, -1 if fail */ +/* MTR: can't lock here and at snmp_read */ +/* Beware recursive send maybe inside snmp_read callback function. */ +int +_sess_read(void *sessp, + fd_set *fdset) +{ + struct session_list *slp = (struct session_list *)sessp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH], *packetptr = packet, *ucp = 0; + snmp_ipaddr from; + struct sockaddr_in *fromIp = (struct sockaddr_in *)&from; + size_t length = 0; + struct snmp_pdu *pdu; + struct request_list *rp, *orp = NULL; + int ret; + int addrlen; + int fromlength; + + sp = slp->session; isp = slp->internal; + if (!sp || !isp) { + DEBUGMSGTL(("sess_read","read fail: closing...\n")); + return 0; + } + + if ((!isp->newpkt && !(FD_ISSET(isp->sd, fdset)))) { + DEBUGMSGTL(("sess_read","not reading...\n")); + return 0; + } + + sp->s_snmp_errno = 0; + sp->s_errno = 0; + + if ( sp->flags & SNMP_FLAGS_STREAM_SOCKET ) { + if ( sp->flags & SNMP_FLAGS_LISTENING ) { + /* + * Accept the new stream based connection, + * and create a new session for it. + */ + struct session_list *new_slp; + int new_sd; + + addrlen = sizeof(struct sockaddr); + new_sd = accept(isp->sd, (struct sockaddr *)&(isp->addr), &addrlen); + if ( new_sd == -1 ) { + sp->s_snmp_errno = SNMPERR_BAD_RECVFROM; + sp->s_errno = errno; + snmp_set_detail(strerror(errno)); + return -1; + } + + new_slp = snmp_sess_copy( sp ); + if ( new_slp == NULL ) + return -1; + { /*MTCRITICAL_RESOURCE*/ + /* indirectly accesses the Sessions list */ + /* MTR snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); */ + new_slp->next = slp->next; + slp->next = new_slp; + + sp = new_slp->session; + isp = new_slp->internal; + memcpy((u_char *)isp, + (u_char *)slp->internal, + sizeof(*slp->internal)); + isp->sd = new_sd; + isp->addr.sa_family = isp->me.sa_family; + sp->flags &= (~SNMP_FLAGS_LISTENING); + /* MTR snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); */ + } /*END MTCRITICAL_RESOURCE*/ + } + memcpy((u_char *)&from, (u_char *)&(isp->addr), sizeof( isp->addr )); + } + else + memset(&from, 0, sizeof(from)); + fromlength = sizeof from; +#if !defined(__ECOS) + if ( sp->flags & SNMP_FLAGS_STREAM_SOCKET ) { + if (!isp->newpkt) + length = recv(isp->sd, (char *)packet, PACKET_LENGTH, 0); + } else { +#endif + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, + (struct sockaddr *)&from, &fromlength); + if (from.sa_family == AF_UNSPEC) + from.sa_family = AF_INET; /* bad bad bad OS, no bone! */ +#if !defined(__ECOS) + } +#endif + + if (length == -1) { + sp->s_snmp_errno = SNMPERR_BAD_RECVFROM; + sp->s_errno = errno; + snmp_set_detail(strerror(errno)); + return -1; + } + + /* Remote end closed connection */ + if ((length == 0 && !isp->newpkt) && + (sp->flags & SNMP_FLAGS_STREAM_SOCKET )) { + isp->sd = -1; /* Mark session for deletion */ + /* XXX: its not properly closing... */ + /* Don't unlink the server listening socket prematurely */ +#ifdef AF_UNIX + if (( isp->me.sa_family == AF_UNIX ) && + !( sp->flags & SNMP_FLAGS_LISTENING )) + isp->me.sa_family = AF_UNSPEC; +#endif /*AF_UNIX */ + return -1; + } + + if (sp->flags & SNMP_FLAGS_STREAM_SOCKET ) { + + if (isp->newpkt == 1) { + /* move the old memory down, if we have saved data */ + memmove(isp->packet, isp->packet+isp->proper_len, isp->proper_len); + isp->newpkt = 0; + isp->packet_len -= isp->proper_len; + isp->proper_len = 0; + } + + /* malloc the save space if needed */ + if (isp->packet == NULL) { + isp->packet_size = (PACKET_LENGTH < length)?length:PACKET_LENGTH; + isp->packet = (u_char *) malloc(isp->packet_size); + } + + /* do we have enough space? */ + if (isp->packet_size < (isp->packet_len + length)) { + if (isp->packet_size+length > MAX_PACKET_LENGTH) { + /* maximum length exceeded, drop connection */ + snmp_log(LOG_ERR,"Maximum saved packet size exceeded.\n"); + isp->sd = -1; + /* Don't unlink the server listening socket prematurely */ + /* XXX: do this?? */ +#ifdef AF_UNIX + if (( isp->me.sa_family == AF_UNIX ) && + !( sp->flags & SNMP_FLAGS_LISTENING )) + isp->me.sa_family = AF_UNSPEC; +#endif /*AF_UNIX */ + return -1; + } + isp->packet_size = isp->packet_size*2; + if (isp->packet_size < (isp->packet_len + length)) + isp->packet_size = (isp->packet_len + length); /* shouldn't happen */ + isp->packet = (u_char *) realloc(isp->packet, isp->packet_size); + } + + /* add the new data to the end of our buffer */ + memcpy(isp->packet+isp->packet_len, packet, length); + isp->packet_len += length; + + /* check for agentx length parser */ + if (isp->proper_len == 0) { + /* get the total data length we're expecting (and need to wait for) */ + if (isp->check_packet) + isp->proper_len = isp->check_packet(isp->packet, isp->packet_len); + else + isp->proper_len = asn_check_packet(isp->packet, isp->packet_len); + + if (isp->proper_len > MAX_PACKET_LENGTH) { + /* illegal length, drop the connection */ + snmp_log(LOG_ERR,"Maximum packet size exceeded in a request.\n"); + isp->sd = -1; + /* Don't unlink the server listening socket prematurely */ + /* XXX: do this?? */ +#ifdef AF_UNIX + if (( isp->me.sa_family == AF_UNIX ) && + !( sp->flags & SNMP_FLAGS_LISTENING )) + isp->me.sa_family = AF_UNSPEC; +#endif /*AF_UNIX */ + return -1; + } + } + + /* if its not long enough now, give up and contiune waiting */ + if (isp->proper_len == 0 || isp->packet_len < isp->proper_len) { + DEBUGMSGTL(("sess_read", "short packet! (%d/%d)\n", + isp->packet_len, isp->proper_len)); + return 0; + } + + /* else we need to continue, and process the saved data. + Careful though, we may have more than is needed! save it! */ + packetptr = isp->packet; + length = isp->proper_len; + if (isp->packet_len - isp->proper_len == 0) { + isp->packet_len -= isp->proper_len; + isp->proper_len = 0; + } else if (isp->packet_len - isp->proper_len < 0) { + snmp_log(LOG_ERR,"something seriously wrong, packet size calculations are negative.\n"); + isp->packet_len = 0; + isp->proper_len = 0; + } else if (isp->packet_len - isp->proper_len > 0) { + isp->newpkt = 1; + } + } + + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET)){ + snmp_log(LOG_DEBUG, "\nReceived %d bytes from %s:%hu\n", length, + inet_ntoa(fromIp->sin_addr), ntohs(fromIp->sin_port)); + xdump(packetptr, length, ""); + } + if ( isp->hook_pre ) { + if ( isp->hook_pre( sp, from ) == 0 ) + return -1; + } + + pdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu)); + memset (pdu, 0, sizeof(*pdu)); + pdu->address = from; + + if ( isp->hook_parse ) + ret = isp->hook_parse(sp, pdu, packetptr, length); + else + ret = snmp_parse(sessp, sp, pdu, packetptr, length); + if ( isp->hook_post ) { + if ( isp->hook_post( sp, pdu, ret ) == 0 ) { + snmp_free_pdu(pdu); + return -1; + } + } + if (ret != SNMP_ERR_NOERROR) { + snmp_free_pdu(pdu); + return -1; + } + + if (pdu->flags & UCD_MSG_FLAG_RESPONSE_PDU) { + /* call USM to free any securityStateRef supplied with the message */ + if (pdu->securityStateRef) { + usm_free_usmStateReference(pdu->securityStateRef); + pdu->securityStateRef = NULL; + } + for(rp = isp->requests; rp; orp = rp, rp = rp->next_request) { + snmp_callback callback; + void *magic; + if (pdu->version == SNMP_VERSION_3) { + /* msgId must match for V3 messages */ + if (rp->message_id != pdu->msgid) continue; + /* check that message fields match original, + * if not, no further processing */ + if (!snmpv3_verify_msg(rp,pdu)) break; + } else { + if (rp->request_id != pdu->reqid) continue; + } + if (rp->callback) { + callback = rp->callback; + magic = rp->cb_data; + } else { + callback = sp->callback; + magic = sp->callback_magic; + } + + /* MTR snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); ?* XX lock should be per session ! */ + if (callback == NULL || + callback(RECEIVED_MESSAGE,sp,pdu->reqid,pdu,magic) == 1){ + if (pdu->command == SNMP_MSG_REPORT) { + if (sp->s_snmp_errno == SNMPERR_NOT_IN_TIME_WINDOW) { + /* trigger immediate retry on recoverable Reports + * (notInTimeWindow), incr_retries == TRUE to prevent + * inifinite resend */ + if (rp->retries <= sp->retries) { + snmp_resend_request(slp, rp, TRUE); + break; + } + } else { + if (SNMPV3_IGNORE_UNAUTH_REPORTS) break; + } + /* handle engineID discovery - */ + if (!sp->securityEngineIDLen && pdu->securityEngineIDLen) { + sp->securityEngineID = (u_char *)malloc(pdu->securityEngineIDLen); + memcpy(sp->securityEngineID, pdu->securityEngineID, + pdu->securityEngineIDLen); + sp->securityEngineIDLen = pdu->securityEngineIDLen; + if (!sp->contextEngineIDLen) { + sp->contextEngineID = (u_char *)malloc(pdu->securityEngineIDLen); + memcpy(sp->contextEngineID, pdu->securityEngineID, + pdu->securityEngineIDLen); + sp->contextEngineIDLen = pdu->securityEngineIDLen; + } + } + } + /* successful, so delete request */ + if (isp->requests == rp){ + /* first in list */ + isp->requests = rp->next_request; + if (isp->requestsEnd == rp) + isp->requestsEnd = NULL; + } else { + orp->next_request = rp->next_request; + if (isp->requestsEnd == rp) + isp->requestsEnd = orp; + } + snmp_free_pdu(rp->pdu); + free((char *)rp); + /* there shouldn't be any more requests with the + same reqid */ + break; + } + /* MTR snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); ?* XX lock should be per session ! */ + } + } else { + if (sp->callback) + { + /* MTR snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); */ + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, + sp->callback_magic); + /* MTR snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); */ + } + } + /* call USM to free any securityStateRef supplied with the message */ + if (pdu->securityStateRef && pdu->command == SNMP_MSG_TRAP2) { + usm_free_usmStateReference(pdu->securityStateRef); + pdu->securityStateRef = NULL; + } + snmp_free_pdu(pdu); + return 0; +} + +/* returns 0 if success, -1 if fail */ +int +snmp_sess_read(void *sessp, + fd_set *fdset) + { + struct session_list *psl; + struct snmp_session *pss; + int rc; + + rc = _sess_read(sessp, fdset); + psl = (struct session_list *)sessp; + pss = psl->session; + if (rc && pss->s_snmp_errno) { + SET_SNMP_ERROR(pss->s_snmp_errno); + } + return rc; +} + + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * The value of block indicates how the timeout value is interpreted. + * If block is true on input, the timeout value will be treated as undefined, + * but it must be available for setting in snmp_select_info. On return, + * block is set to true if the value returned for timeout is undefined; + * when block is set to false, timeout may be used as a parmeter to 'select'. + * + * snmp_select_info returns the number of open sockets. (i.e. The number of + * sessions open) + */ + +int +snmp_select_info(int *numfds, + fd_set *fdset, + struct timeval *timeout, + int *block) + /* input: set to 1 if input timeout value is undefined */ + /* set to 0 if input timeout value is defined */ + /* output: set to 1 if output timeout value is undefined */ + /* set to 0 if output rimeout vlaue id defined */ +{ + return snmp_sess_select_info((void *)0, numfds, fdset, timeout, block); +} + +/* Same as snmp_select_info, but works just one session. */ +int +snmp_sess_select_info(void *sessp, + int *numfds, + fd_set *fdset, + struct timeval *timeout, + int *block) +{ + struct session_list *slptest = (struct session_list *)sessp; + struct session_list *slp, *next=NULL, *prev=NULL; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int timer_set = 0; + int active = 0, requests = 0; + int next_alarm = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + * If a single session is specified, do just for that session. + */ + if (sessp) slp = slptest; else slp = Sessions; + for(; slp; slp = next){ + isp = slp->internal; + if (!isp) { + DEBUGMSGTL(("sess_select","select fail: closing...\n")); + continue; /* close in progress - skip this one */ + } + + if (isp->sd == -1) { + if (sessp == NULL) { + /* This session was marked for deletion */ + if ( prev == NULL ) + Sessions = slp->next; + else + prev->next = slp->next; + next = slp->next; + } + snmp_sess_close( slp ); + continue; + } + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if ((!timerisset(&earliest) + || (timercmp(&rp->expire, &earliest, <)))) + earliest = rp->expire; + } + } + if (isp->newpkt) { + /* don't block at all, more data waiting to be processed */ + DEBUGMSGTL(("sess_select","more data in buffer, not blocking\n")); + requests++; + timer_set = 1; + *block = 0; + } + active++; + if (slp == slptest) break; + prev = slp; + next = slp->next; + } + + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG)) { + next_alarm = get_next_alarm_delay_time(); + } + if (next_alarm == 0 && requests == 0) { /* if none are active, skip arithmetic */ + *block = 1; /* can block - timeout value is undefined if no requests*/ + return active; + } + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now,(struct timezone *)0); + /*Now = now;*/ + + if (next_alarm != 0 && earliest.tv_sec > next_alarm) { + earliest.tv_sec = next_alarm; + earliest.tv_usec = 0; + } + + if (timer_set || earliest.tv_sec < now.tv_sec) { + earliest.tv_sec = 0; + earliest.tv_usec = 100; + } + else if (earliest.tv_sec == now.tv_sec) { + earliest.tv_sec = 0; + earliest.tv_usec = (earliest.tv_usec - now.tv_usec); + if (earliest.tv_usec < 0) { + earliest.tv_usec = 100; + } + } + else { + earliest.tv_sec = (earliest.tv_sec - now.tv_sec); + earliest.tv_usec = (earliest.tv_usec - now.tv_usec); + if (earliest.tv_usec < 0) { + earliest.tv_sec --; + earliest.tv_usec = (1000000L + earliest.tv_usec); + } + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if ((*block || (timercmp(&earliest, timeout, <)))){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from snmp_select_info + * expires, but it is idempotent, so snmp_timeout can be polled (probably a + * cpu expensive proposition). snmp_timeout checks to see if any of the + * sessions have an outstanding request that has timed out. If it finds one + * (or more), and that pdu has more retries available, a new packet is formed + * from the pdu and is resent. If there are no more retries available, the + * callback for the session is used to alert the user of the timeout. + */ +void +snmp_timeout (void) +{ + struct session_list *slp; + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + for(slp = Sessions; slp; slp = slp->next){ + snmp_sess_timeout((void *)slp); + } + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); +} + +static int +snmp_resend_request(struct session_list *slp, struct request_list *rp, + int incr_retries) +{ + u_char packet[PACKET_LENGTH]; + size_t length = PACKET_LENGTH; + struct timeval tv; + struct snmp_session *sp; + struct snmp_internal_session *isp; + struct timeval now; + int result, addr_size; + + sp = slp->session; isp = slp->internal; + if (!sp || !isp) { + DEBUGMSGTL(("sess_read","resend fail: closing...\n")); + return 0; + } + + if (incr_retries) rp->retries++; + + /* always increment msgId for resent messages */ + rp->pdu->msgid = rp->message_id = snmp_get_next_msgid(); + + /* retransmit this pdu */ + if (snmp_build(sp, rp->pdu, packet, &length) < 0){ + /* this should never happen */ + return -1; + } + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET)){ + struct sockaddr_in *pduIp; + pduIp = (struct sockaddr_in *)&(rp->pdu->address); + snmp_log(LOG_DEBUG, "\nResending %d bytes to %s:%hu\n", length, + inet_ntoa(pduIp->sin_addr), ntohs(pduIp->sin_port)); + xdump(packet, length, ""); + } + + addr_size = snmp_socket_length(rp->pdu->address.sa_family); + +#if !defined(__ECOS) + if ( sp->flags & SNMP_FLAGS_STREAM_SOCKET ) + result = send(isp->sd, (char *)packet, length, 0); + else +#endif + result = sendto(isp->sd, (char *)packet, length, 0, + (struct sockaddr *)&rp->pdu->address, addr_size); + if ( result < 0){ + sp->s_snmp_errno = SNMPERR_BAD_SENDTO; + sp->s_errno = errno; + snmp_set_detail(strerror(errno)); + return -1; + } + else { + gettimeofday(&now, (struct timezone *)0); + tv = now; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; + } + return 0; +} + +void +snmp_sess_timeout(void *sessp) +{ + struct session_list *slp = (struct session_list*)sessp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + struct request_list *rp, *orp = NULL, *freeme = NULL; + struct timeval now; + snmp_callback callback; + void *magic; + + sp = slp->session; isp = slp->internal; + if (!sp || !isp) { + DEBUGMSGTL(("sess_read","timeout fail: closing...\n")); + return; + } + + gettimeofday(&now,(struct timezone *)0); + + /* + * For each request outstanding, check to see if it has expired. + */ + for(rp = isp->requests; rp; rp = rp->next_request){ + if (freeme != NULL){ + /* frees rp's after the for loop goes on to the next_request */ + free((char *)freeme); + freeme = NULL; + } + if ((timercmp(&rp->expire, &now, <))){ + /* this timer has expired */ + if (rp->retries >= sp->retries){ + if (rp->callback) { + callback = rp->callback; + magic = rp->cb_data; + } else { + callback = sp->callback; + magic = sp->callback_magic; + } + /* No more chances, delete this entry */ + if (callback) + callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, magic); + if (isp->requests == rp){ + isp->requests = rp->next_request; + if (isp->requestsEnd == rp) + isp->requestsEnd = NULL; + } else { + orp->next_request = rp->next_request; + if (isp->requestsEnd == rp) + isp->requestsEnd = orp; + } + snmp_free_pdu(rp->pdu); /* FIX rp is already free'd! */ + freeme = rp; + continue; /* don't update orp below */ + } else { + if (snmp_resend_request(slp, rp, TRUE)) break; + } + } + orp = rp; + } + if (freeme != NULL){ + free((char *)freeme); + freeme = NULL; + } +} + +/* lexicographical compare two object identifiers. + * Returns -1 if name1 < name2, + * 0 if name1 = name2, + * 1 if name1 > name2 + * + * Caution: this method is called often by + * command responder applications (ie, agent). + */ +int +snmp_oid_compare(const oid *in_name1, + size_t len1, + const oid *in_name2, + size_t len2) +{ + register int len, res; + register const oid * name1 = in_name1; + register const oid * name2 = in_name2; + + /* len = minimum of len1 and len2 */ + if (len1 < len2) + len = len1; + else + len = len2; + /* find first non-matching OID */ + while(len-- > 0){ + res = *(name1++) - *(name2++); + if (res < 0) + return -1; + if (res > 0) + return 1; + } + /* both OIDs equal up to length of shorter OID */ + if (len1 < len2) + return -1; + if (len2 < len1) + return 1; + return 0; +} + +/* + * Add a variable with the requested name to the end of the list of + * variables for this pdu. + */ +struct variable_list * +snmp_pdu_add_variable(struct snmp_pdu *pdu, + oid *name, + size_t name_length, + u_char type, + u_char *value, + size_t len) +{ + return snmp_varlist_add_variable(&pdu->variables, name, name_length, type, + value, len); +} + +/* + * Add a variable with the requested name to the end of the list of + * variables for this pdu. + */ +struct variable_list * +snmp_varlist_add_variable(struct variable_list **varlist, + oid *name, + size_t name_length, + u_char type, + u_char *value, + size_t len) +{ + struct variable_list *vars, *vtmp; + int largeval = 1; + + if (varlist == NULL) + return NULL; + + vars = (struct variable_list *)malloc(sizeof(struct variable_list)); + if (vars == NULL) + return NULL; + + vars->next_variable = 0; vars->name = 0; vars->val.string = 0; + + /* use built-in storage for smaller values */ + if (len <= sizeof(vars->buf)) { + vars->val.string = (u_char *)vars->buf; + largeval = 0; + } + + vars->type = type; + vars->val_len = len; + switch(type){ + case ASN_INTEGER: + case ASN_UNSIGNED: + case ASN_TIMETICKS: + case ASN_IPADDRESS: + case ASN_COUNTER: + memmove(vars->val.integer, value, vars->val_len); + vars->val_len = sizeof(long); + break; + + case ASN_OBJECT_ID: + case ASN_PRIV_INCL_RANGE: + case ASN_PRIV_EXCL_RANGE: + if (largeval) { + vars->val.objid = (oid *)malloc(vars->val_len); + } + memmove(vars->val.objid, value, vars->val_len); + break; + + case ASN_OCTET_STR: + case ASN_OPAQUE: + case ASN_NSAP: + if (largeval) { + vars->val.string = (u_char *)malloc(vars->val_len); + } + memmove(vars->val.string, value, vars->val_len); + break; + + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + vars->val_len = 0; + vars->val.string = NULL; + break; + +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_U64: + case ASN_OPAQUE_I64: +#endif /* OPAQUE_SPECIAL_TYPES */ + case ASN_COUNTER64: + vars->val_len = sizeof(struct counter64); + memmove(vars->val.counter64, value, vars->val_len); + break; + +#ifdef OPAQUE_SPECIAL_TYPES + case ASN_OPAQUE_FLOAT: + vars->val_len = sizeof(float); + memmove(vars->val.floatVal, value, vars->val_len); + break; + + case ASN_OPAQUE_DOUBLE: + vars->val_len = sizeof(double); + memmove(vars->val.doubleVal, value, vars->val_len); + +#endif /* OPAQUE_SPECIAL_TYPES */ + + default: + snmp_set_detail("Internal error in type switching\n"); + snmp_free_var(vars); + return (0); + } + + if (name != NULL && snmp_set_var_objid(vars, name, name_length)) { + snmp_free_var(vars); + return (0); + } + + /* put only qualified variable onto varlist */ + if (*varlist == NULL){ + *varlist = vars; + } else { + for(vtmp = *varlist; + vtmp->next_variable; + vtmp = vtmp->next_variable) + ; + + vtmp->next_variable = vars; + } + + return vars; +} + +/* + * Parses dotted notation object identifier + * into unsigned character array. + * Returns: SNMPERR_RANGE if any sub-identifier > 255. + * Returns: SNMPERR_VALUE if input string is not octet string. + * Returns: non-negative number of sub-identifiers parsed, + */ +int +ascii_to_binary(const char *cp, + u_char *bufp) +{ + int subidentifier; + u_char *bp = bufp; + + for(; *cp != '\0'; cp++){ + if (isspace(*cp) || *cp == '.') + continue; + if (!isdigit(*cp)){ + return SNMPERR_VALUE; + } + subidentifier = atoi(cp); + if (subidentifier > 255){ + return SNMPERR_RANGE; + } + *bp++ = (u_char)subidentifier; + while(isdigit(*cp)) + cp++; + cp--; + } + return bp - bufp; +} + +int +hex_to_binary(const char *str, + u_char *bufp) +{ + int len, itmp; + if (!bufp) return -1; + if (*str && *str == '0' && (*(str+1) == 'x' || *(str+1) == 'X')) str += 2; + for (len = 0; *str; str++) { + if (isspace(*str)) continue; + if (!isxdigit(*str)) return -1; + len++; + if (sscanf(str++, "%2x", &itmp) == 0) return -1; + *bufp++ = itmp; + if (!*str) return -1; /* odd number of chars is an error */ + } + return len; +} + + +/* + * Add a variable with the requested name to the end of the list of + * variables for this pdu. + * Returns: + * may set these error types : + * SNMPERR_RANGE - type, value, or length not found or out of range + * SNMPERR_VALUE - value is not correct + * SNMPERR_BAD_NAME - name is not found + * + * returns 0 if success, error if failure. + */ +int +snmp_add_var(struct snmp_pdu *pdu, + oid *name, + size_t name_length, + char type, + const char *value) +{ + int result = 0; + u_char buf[SPRINT_MAX_LEN]; + size_t tint; + long ltmp; + struct tree *tp; + struct enum_list *ep; + struct range_list *rp; +#ifdef OPAQUE_SPECIAL_TYPES + double dtmp; + float ftmp; + struct counter64 c64tmp; +#endif /* OPAQUE_SPECIAL_TYPES */ + + switch(type){ + case 'i': + tp = get_tree(name, name_length, get_tree_head()); + if (sscanf(value, "%ld", <mp) != 1) { + ep = tp ? tp->enums : NULL; + while (ep) { + if (strcmp(value, ep->label) == 0) { + ltmp = ep->value; + break; + } + ep = ep->next; + } + if (!ep) { + result = SNMPERR_BAD_NAME; + snmp_set_detail(value); + break; + } + } + + if (tp && tp->ranges && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_CHECK_RANGE)) { + rp = tp->ranges; + while (rp) { + if (rp->low <= ltmp && ltmp <= rp->high) break; + rp = rp->next; + } + if (!rp) { + result = SNMPERR_RANGE; + snmp_set_detail("Value"); + break; + } + } + snmp_pdu_add_variable(pdu, name, name_length, ASN_INTEGER, + (u_char *) <mp, sizeof(ltmp)); + break; + + case 'u': + if (sscanf(value, "%lu", <mp) == 1) + snmp_pdu_add_variable(pdu, name, name_length, ASN_UNSIGNED, + (u_char *) <mp, sizeof(ltmp)); + else goto fail; + break; + + case 'c': + if (sscanf(value, "%lu", <mp) == 1) + snmp_pdu_add_variable(pdu, name, name_length, ASN_COUNTER, + (u_char *) <mp, sizeof(ltmp)); + else goto fail; + break; + + case 't': + if (sscanf(value, "%lu", <mp) == 1) + snmp_pdu_add_variable(pdu, name, name_length, ASN_TIMETICKS, + (u_char *) <mp, sizeof(long)); + else goto fail; + break; + + case 'a': + if ((ltmp = inet_addr(value)) != (long)-1) + snmp_pdu_add_variable(pdu, name, name_length, ASN_IPADDRESS, + (u_char *) <mp, sizeof(long)); + else goto fail; + break; + + case 'o': + tint = sizeof(buf) / sizeof(oid); + if (read_objid(value, (oid *)buf, &tint)) + snmp_pdu_add_variable(pdu, name, name_length, ASN_OBJECT_ID, buf, + sizeof(oid)*tint); + else result = snmp_errno; + break; + + case 's': + case 'x': + case 'd': + if (type == 'd'){ + ltmp = ascii_to_binary(value, buf); + } else if (type == 's'){ + strcpy((char*)buf, value); + ltmp = strlen((char*)buf); + } else if (type == 'x'){ + ltmp = hex_to_binary(value, buf); + } + if (ltmp < 0) { + result = SNMPERR_VALUE; + snmp_set_detail(value); + break; + } + tp = get_tree(name, name_length, get_tree_head()); + if (tp && tp->ranges && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_CHECK_RANGE)) { + rp = tp->ranges; + while (rp) { + if (rp->low <= ltmp && ltmp <= rp->high) break; + rp = rp->next; + } + if (!rp) { + result = SNMPERR_RANGE; + snmp_set_detail("Length"); + break; + } + } + snmp_pdu_add_variable(pdu, name, name_length, ASN_OCTET_STR, buf, ltmp); + break; + + case 'n': + snmp_pdu_add_variable(pdu, name, name_length, ASN_NULL, 0, 0); + break; + +#ifdef OPAQUE_SPECIAL_TYPES + case 'U': + if (read64(&c64tmp, value)) + snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_U64, + (u_char *) &c64tmp, sizeof(c64tmp)); + else goto fail; + break; + + case 'I': + if (read64(&c64tmp, value)) + snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_I64, + (u_char *) &c64tmp, sizeof(c64tmp)); + else goto fail; + break; + + case 'F': + if (sscanf(value, "%f", &ftmp) == 1) + snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_FLOAT, + (u_char *) &ftmp, sizeof(ftmp)); + else goto fail; + break; + + case 'D': + if (sscanf(value, "%lf", &dtmp) == 1) + snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_DOUBLE, + (u_char *) &dtmp, sizeof(dtmp)); + else goto fail; + break; +#endif /* OPAQUE_SPECIAL_TYPES */ + + default: + result = SNMPERR_VAR_TYPE; + sprintf((char *)buf, "%c", type); + snmp_set_detail((const char *)buf); + break; + } + + SET_SNMP_ERROR(result); + return result; + +fail: + result = SNMPERR_VALUE; + snmp_set_detail(value); + SET_SNMP_ERROR(result); + return result; +} + +/* + * returns NULL or internal pointer to session + * use this pointer for the other snmp_sess* routines, + * which guarantee action will occur ONLY for this given session. + */ +void * +snmp_sess_pointer(struct snmp_session *session) +{ + struct session_list *slp; + + snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + break; + } + } + snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); + + if (slp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; /*MTCRITICAL_RESOURCE*/ + return(NULL); + } + return((void *)slp); +} + +/* + * Input : an opaque pointer, returned by snmp_sess_open. + * returns NULL or pointer to session. + */ +struct snmp_session * +snmp_sess_session(void *sessp) +{ + struct session_list *slp = (struct session_list *)sessp; + if (slp == NULL) return(NULL); + return (slp->session); +} +#ifdef CMU_COMPATIBLE + +char * +snmp_pdu_type(struct snmp_pdu *PDU) +{ + switch(PDU->command) { + case SNMP_MSG_GET: + return("GET"); + break; + case SNMP_MSG_GETNEXT: + return("GETNEXT"); + break; + case SNMP_MSG_RESPONSE: + return("RESPONSE"); + break; + case SNMP_MSG_SET: + return("SET"); + break; + case SNMP_MSG_GETBULK: + return("GETBULK"); + break; + case SNMP_MSG_INFORM: + return("INFORM"); + break; + case SNMP_MSG_TRAP2: + return("V2TRAP"); + break; + case SNMP_MSG_REPORT: + return("REPORT"); + break; + + case SNMP_MSG_TRAP: + return("V1TRAP"); + break; + default: + return("Unknown"); + break; + } +} + +/* + * cmu_snmp_parse - emulate CMU library's snmp_parse. + * + * Parse packet, storing results into PDU. + * Returns community string if success, NULL if fail. + * WARNING: may return a zero length community string. + * + * Note: + * Some CMU-aware apps call init_mib(), but do not + * initialize a session. + * Check Reqid to make sure that this module is initialized. + */ + +u_char * +cmu_snmp_parse (struct snmp_session *session, + struct snmp_pdu *pdu, + u_char *data, + size_t length) +{ + u_char *bufp = NULL; + + if (Reqid == 0) { + snmp_sess_init(session); /* gimme a break! */ + } + + switch(pdu->version) { + case SNMP_VERSION_1: + case SNMP_VERSION_2c: + case SNMP_DEFAULT_VERSION: + break; + default: + return NULL; + } +#ifndef NO_INTERNAL_VARLIST + if (snmp_parse( 0, session, pdu, data, length) != SNMP_ERR_NOERROR){ + return NULL; + } +#else +/* + * while there are two versions of variable_list: + * use an internal variable list for snmp_parse; + * clone the result. + */ +if (1) { +struct snmp_pdu *snmp_clone_pdu (struct snmp_pdu *); +struct snmp_pdu *snmp_2clone_pdu(struct snmp_pdu *from_pdu, struct snmp_pdu *to_pdu); + + struct snmp_pdu *ipdu; + ipdu = snmp_clone_pdu(pdu); + if (snmp_parse( 0, session, ipdu, data, length) != SNMP_ERR_NOERROR){ + snmp_free_internal_pdu(ipdu); + return NULL; + } + pdu = snmp_2clone_pdu(ipdu, pdu); + snmp_free_internal_pdu(ipdu); +} +#endif /* NO_INTERNAL_VAR_LIST */ + + /* Add a null to meet the caller's expectations. */ + + bufp = (u_char *)malloc(1+pdu->community_len); + if (bufp && pdu->community_len) { + memcpy(bufp, pdu->community, pdu->community_len); + bufp[pdu->community_len] = '\0'; + } + return(bufp); +} + + +#endif /* CMU_COMPATIBLE */ + +/* snmp_duplicate_objid: duplicates (mallocs) an objid based on the + input objid */ +oid * +snmp_duplicate_objid(oid *objToCopy, size_t objToCopyLen) +{ + oid *returnOid; + returnOid = (oid *) malloc(objToCopyLen*sizeof(oid)); + if (returnOid) { + memmove(returnOid, objToCopy, objToCopyLen*sizeof(oid)); + } + return returnOid; +} + +/* generic statistics counter functions */ +static u_int statistics[MAX_STATS]; + +u_int +snmp_increment_statistic(int which) +{ + if (which >= 0 && which < MAX_STATS) { + statistics[which]++; + return statistics[which]; + } + return 0; +} + +u_int +snmp_increment_statistic_by(int which, int count) +{ + if (which >= 0 && which < MAX_STATS) { + statistics[which] += count; + return statistics[which]; + } + return 0; +} + +u_int +snmp_get_statistic(int which) +{ + if (which >= 0 && which < MAX_STATS) + return statistics[which]; + return 0; +} + +void +snmp_init_statistics(void) +{ + memset(statistics, 0, sizeof(statistics)); +} + +/* returns the length of a socket structure */ + +size_t snmp_socket_length( int family) +{ + size_t length; + switch (family) + { +#ifndef cygwin +#ifndef WIN32 +#ifdef AF_UNIX + case AF_UNIX: + length = sizeof (struct sockaddr_un); + break; +#endif /* AF_UNIX */ +#endif +#endif + +#ifndef aix3 +#ifdef AF_LINK + case AF_LINK: +#ifdef _MAX_SA_LEN + length = _MAX_SA_LEN; +#elif SOCK_MAXADDRLEN + length = SOCK_MAXADDRLEN; +#else + length = sizeof (struct sockaddr_dl); +#endif + break; +#endif /* AF_LINK */ +#endif + + case AF_INET: + length = sizeof (struct sockaddr_in); + break; + default: + length = sizeof (struct sockaddr); + break; + } + + return length; +} + +/* + * For compatibility with applications built using + * previous versions only. + */ + +/* use s_snmp_errno instead */ +int snmp_get_errno (void) { return SNMPERR_SUCCESS; } + +/* synch_reset and synch_setup are no longer used. */ +void snmp_synch_reset (struct snmp_session * notused) {} +void snmp_synch_setup (struct snmp_session * notused) {} + +/* provide for backwards compatibility */ +void +snmp_set_dump_packet(int x) { + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET, x); +} + +int +snmp_get_dump_packet(void) { + return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET); +} + +void +snmp_set_quick_print(int x) { + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT, x); +} + +int +snmp_get_quick_print(void) { + return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT); +} + + +void +snmp_set_suffix_only(int x) { + ds_set_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY, x); +} + +int +snmp_get_suffix_only(void) { + return ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY); +} + +void +snmp_set_full_objid(int x) { + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID, x); +} + +int +snmp_get_full_objid(void) { + return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY); +} + +void +snmp_set_random_access(int x) { + ds_set_boolean(DS_LIBRARY_ID, DS_LIB_RANDOM_ACCESS, x); +} + +int +snmp_get_random_access(void) { + return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_RANDOM_ACCESS); +} + diff --git a/packages/net/snmp/lib/current/src/snmp_auth.c b/packages/net/snmp/lib/current/src/snmp_auth.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmp_auth.c @@ -0,0 +1,315 @@ +//========================================================================== +// +// ./lib/current/src/snmp_auth.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmp_auth.c + * + * Community name parse/build routines. + */ +/********************************************************************** + Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#include + +#ifdef KINETICS +#include "gw.h" +#include "fp4/cmdmacro.h" +#endif + +#include +#if HAVE_STRING_H +#include +#else +#include +#endif +#include +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#if HAVE_WINSOCK_H +#include +#endif + +#ifdef vms +#include +#endif + +#include "asn1.h" +#include "snmp.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "mib.h" +#include "md5.h" +#include "system.h" +#include "tools.h" +#include "snmp_debug.h" +#include "scapi.h" + +/* + * Globals. + */ + +/*******************************************************************-o-****** + * snmp_comstr_parse + * + * Parameters: + * *data (I) Message. + * *length (I/O) Bytes left in message. + * *psid (O) Community string. + * *slen (O) Length of community string. + * *version (O) Message version. + * + * Returns: + * Pointer to the remainder of data. + * + * + * Parse the header of a community string-based message such as that found + * in SNMPv1 and SNMPv2c. + */ +u_char * +snmp_comstr_parse(u_char *data, + size_t *length, + u_char *psid, + size_t *slen, + long *version) +{ + u_char type; + long ver; + + + /* Message is an ASN.1 SEQUENCE. + */ + data = asn_parse_sequence(data, length, &type, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), "auth message"); + if (data == NULL){ + return NULL; + } + + /* First field is the version. + */ + DEBUGDUMPHEADER("dump_recv", "Parsing SNMP version\n"); + data = asn_parse_int(data, length, &type, &ver, sizeof(ver)); + DEBUGINDENTLESS(); + *version = ver; + if (data == NULL){ + ERROR_MSG("bad parse of version"); + return NULL; + } + + /* second field is the community string for SNMPv1 & SNMPv2c */ + DEBUGDUMPHEADER("dump_recv", "Parsing community string\n"); + data = asn_parse_string(data, length, &type, psid, slen); + DEBUGINDENTLESS(); + if (data == NULL){ + ERROR_MSG("bad parse of community"); + return NULL; + } + psid[*slen] = '\0'; + return (u_char *)data; + +} /* end snmp_comstr_parse() */ + + + + +/*******************************************************************-o-****** + * snmp_comstr_build + * + * Parameters: + * *data + * *length + * *psid + * *slen + * *version + * messagelen + * + * Returns: + * Pointer into 'data' after built section. + * + * + * Build the header of a community string-based message such as that found + * in SNMPv1 and SNMPv2c. + * + * NOTE: The length of the message will have to be inserted later, + * if not known. + * + * NOTE: Version is an 'int'. (CMU had it as a long, but was passing + * in a *int. Grrr.) Assign version to verfix and pass in + * that to asn_build_int instead which expects a long. -- WH + */ +u_char * +snmp_comstr_build( u_char *data, + size_t *length, + u_char *psid, + size_t *slen, + long *version, + size_t messagelen) +{ + long verfix = *version; + u_char *h1 = data; + u_char *h1e; + size_t hlength = *length; + + + /* Build the the message wrapper (note length will be inserted later). + */ + data = asn_build_sequence(data, length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); + if (data == NULL){ + return NULL; + } + h1e = data; + + + /* Store the version field. + */ + data = asn_build_int(data, length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &verfix, sizeof(verfix)); + if (data == NULL){ + return NULL; + } + + + /* Store the community string. + */ + data = asn_build_string(data, length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), + psid, *(u_char *)slen); + if (data == NULL){ + return NULL; + } + + + /* Insert length. + */ + asn_build_sequence(h1, &hlength, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + data-h1e + messagelen); + + + return data; + +} /* end snmp_comstr_build() */ + diff --git a/packages/net/snmp/lib/current/src/snmp_client.c b/packages/net/snmp/lib/current/src/snmp_client.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmp_client.c @@ -0,0 +1,809 @@ +//========================================================================== +// +// ./lib/current/src/snmp_client.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmp_client.c - a toolkit of common functions for an SNMP client. + * + */ +/********************************************************************** + Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#include + +#include +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#if HAVE_WINSOCK_H +#include +#endif + +#include "asn1.h" +#include "snmp.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "snmp_client.h" +#include "mib.h" + + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#ifndef FD_SET + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) memset((p), 0, sizeof(*(p))) +#endif + +#define PARTY_MIB_BASE ".1.3.6.1.6.3.3.1.3.127.0.0.1.1" +#define CONTEXT_MIB_BASE ".1.3.6.1.6.3.3.1.4.127.0.0.1.1" + + +struct snmp_pdu * +snmp_pdu_create(int command) +{ + struct snmp_pdu *pdu; + struct sockaddr_in *pduIp; + + pdu = (struct snmp_pdu *)calloc(1,sizeof(struct snmp_pdu)); + if (pdu) { + pduIp = (struct sockaddr_in *)&(pdu->address); + pdu->version = SNMP_DEFAULT_VERSION; + pdu->command = command; + pdu->errstat = SNMP_DEFAULT_ERRSTAT; + pdu->errindex = SNMP_DEFAULT_ERRINDEX; + pduIp->sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + pdu->securityNameLen = 0; + pdu->contextNameLen = 0; + pdu->reqid = snmp_get_next_reqid(); + pdu->msgid = snmp_get_next_msgid(); + } + return pdu; + +} + + +/* + * Add a null variable with the requested name to the end of the list of + * variables for this pdu. + */ +struct variable_list* snmp_add_null_var(struct snmp_pdu * pdu, + oid *name, + size_t name_length) +{ + return snmp_pdu_add_variable(pdu, name, name_length, ASN_NULL, NULL, 0); +} + + + +int +snmp_synch_input(int op, + struct snmp_session *session, + int reqid, + struct snmp_pdu *pdu, + void *magic) +{ + struct synch_state *state = (struct synch_state *)magic; + int rpt_type; + + if (reqid != state->reqid && pdu->command != SNMP_MSG_REPORT) + return 0; + + state->waiting = 0; + if (op == RECEIVED_MESSAGE) { + if (pdu->command == SNMP_MSG_REPORT) { + rpt_type = snmpv3_get_report_type(pdu); + if (SNMPV3_IGNORE_UNAUTH_REPORTS || + rpt_type == SNMPERR_NOT_IN_TIME_WINDOW) + state->waiting = 1; + state->pdu = NULL; + state->status = STAT_ERROR; + session->s_snmp_errno = rpt_type; + SET_SNMP_ERROR(rpt_type); + } else if (pdu->command == SNMP_MSG_RESPONSE) { + /* clone the pdu to return to snmp_synch_response */ + state->pdu = snmp_clone_pdu(pdu); + state->status = STAT_SUCCESS; + session->s_snmp_errno = SNMPERR_SUCCESS; + } + } else if (op == TIMED_OUT){ + state->pdu = NULL; + state->status = STAT_TIMEOUT; + session->s_snmp_errno = SNMPERR_TIMEOUT; + SET_SNMP_ERROR(SNMPERR_TIMEOUT); + } + + return 1; +} + + +/* + * Clone an SNMP variable data structure. + * Sets pointers to structure private storage, or + * allocates larger object identifiers and values as needed. + * + * Caller must make list association for cloned variable. + * + * Returns 0 if successful. + */ +int +snmp_clone_var(struct variable_list *var, struct variable_list *newvar) +{ + if (!newvar || !var) return 1; + + memmove(newvar, var, sizeof(struct variable_list)); + newvar->next_variable = 0; newvar->name = 0; newvar->val.string = 0; + + /* + * Clone the object identifier and the value. + * Allocate memory iff original will not fit into local storage. + */ + if (snmp_set_var_objid(newvar, var->name, var->name_length)) + return 1; + + /* need a pointer and a length to copy a string value. */ + if (var->val.string && var->val_len) { + if (var->val.string != &var->buf[0]){ + if (var->val_len <= sizeof(var->buf)) + newvar->val.string = newvar->buf; + else { + newvar->val.string = (u_char *)malloc(var->val_len); + if (!newvar->val.string) return 1; + } + memmove(newvar->val.string, var->val.string, var->val_len); + } + else { /* fix the pointer to new local store */ + newvar->val.string = newvar->buf; + } + } + else { + newvar->val.string = 0; newvar->val_len = 0; + } + + return 0; +} + + +/* + * Possibly make a copy of source memory buffer. + * Will reset destination pointer if source pointer is NULL. + * Returns 0 if successful, 1 if memory allocation fails. + */ +int +snmp_clone_mem(void ** dstPtr, void * srcPtr, unsigned len) +{ + *dstPtr = 0; + if (srcPtr){ + *dstPtr = malloc(len + 1); + if (! *dstPtr){ + return 1; + } + memmove(*dstPtr, srcPtr, len); + /* this is for those routines that expect 0-terminated strings!!! + someone should rather have called strdup + */ + ((char *)*dstPtr)[len] = 0; + } + return 0; +} + + +/* + * Creates and allocates a clone of the input PDU, + * but does NOT copy the variables. + * This function should be used with another function, + * such as _copy_pdu_vars. + * + * Returns a pointer to the cloned PDU if successful. + * Returns 0 if failure. + */ +static +struct snmp_pdu * +_clone_pdu_header(struct snmp_pdu *pdu) +{ + struct snmp_pdu *newpdu; + + newpdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu)); + if (!newpdu) return 0; + memmove(newpdu, pdu, sizeof(struct snmp_pdu)); + + /* reset copied pointers if copy fails */ + newpdu->variables = 0; newpdu->enterprise = 0; newpdu->community = 0; + newpdu->securityEngineID = 0; newpdu->securityName = 0; + newpdu->contextEngineID = 0; newpdu->contextName = 0; + + /* copy buffers individually. If any copy fails, all are freed. */ + if ( snmp_clone_mem((void **)&newpdu->enterprise, pdu->enterprise, + sizeof(oid)*pdu->enterprise_length) + || snmp_clone_mem((void **)&newpdu->community, pdu->community, + pdu->community_len) + || snmp_clone_mem((void **)&newpdu->contextEngineID, pdu->contextEngineID, + pdu->contextEngineIDLen) + || snmp_clone_mem((void **)&newpdu->securityEngineID, pdu->securityEngineID, + pdu->securityEngineIDLen) + || snmp_clone_mem((void **)&newpdu->contextName, pdu->contextName, + pdu->contextNameLen) + || snmp_clone_mem((void **)&newpdu->securityName, pdu->securityName, + pdu->securityNameLen) + ) + { + snmp_free_pdu(newpdu); return 0; + } + return newpdu; +} + + +/* + * Copy some or all variables from source PDU to target PDU. + * This function consolidates many of the needs of PDU variables: + * Clone PDU : copy all the variables. + * Split PDU : skip over some variables to copy other variables. + * Fix PDU : remove variable associated with error index. + * + * Designed to work with _clone_pdu_header. + * + * If drop_err is set, drop any variable associated with errindex. + * If skip_count is set, skip the number of variable in pdu's list. + * While copy_count is greater than zero, copy pdu variables to newpdu. + * + * If an error occurs, newpdu is freed and pointer is set to 0. + * + * Returns a pointer to the cloned PDU if successful. + * Returns 0 if failure. + */ +static +struct snmp_pdu * +_copy_pdu_vars(struct snmp_pdu *pdu, /* source PDU */ + struct snmp_pdu *newpdu, /* target PDU */ + int drop_err, /* !=0 drop errored variable */ + int skip_count, /* !=0 number of variables to skip */ + int copy_count) /* !=0 number of variables to copy */ +{ + struct variable_list *var, *newvar, *oldvar; + int ii, copied; + + if (!newpdu) return 0; /* where is PDU to copy to ? */ + + var = pdu->variables; + while (var && (skip_count-- > 0)) /* skip over pdu variables */ + var = var->next_variable; + + oldvar = 0; ii = 0; copied = 0; + if (pdu->flags & UCD_MSG_FLAG_FORCE_PDU_COPY) + copied = 1; /* We're interested in 'empty' responses too */ + while (var && (copy_count-- > 0)) + { + /* errindex starts from 1. If drop_err, skip the errored variable */ + if (drop_err && (++ii == pdu->errindex)) { + var = var->next_variable; continue; + } + + /* clone the next variable. Cleanup if alloc fails */ + newvar = (struct variable_list *)malloc(sizeof(struct variable_list)); + if (snmp_clone_var(var, newvar)){ + if (newvar) free((char *)newvar); + snmp_free_pdu(newpdu); return 0; + } + copied++; + + /* add cloned variable to new PDU */ + if (0 == newpdu->variables) newpdu->variables = newvar; + if (oldvar) oldvar->next_variable = newvar; + oldvar = newvar; + + var = var->next_variable; + } + /* Error if bad errindex or if target PDU has no variables copied */ + if ((drop_err && (ii < pdu->errindex)) +#if TEMPORARILY_DISABLED + /* SNMPv3 engineID probes are allowed to be empty. + See the comment in snmp_api.c for further details */ + || copied == 0 +#endif + ) { + snmp_free_pdu(newpdu); return 0; + } + return newpdu; +} + + +/* + * Creates (allocates and copies) a clone of the input PDU. + * If drop_err is set, don't copy any variable associated with errindex. + * This function is called by snmp_clone_pdu and snmp_fix_pdu. + * + * Returns a pointer to the cloned PDU if successful. + * Returns 0 if failure. + */ +static +struct snmp_pdu * +_clone_pdu(struct snmp_pdu *pdu, int drop_err) +{ + struct snmp_pdu *newpdu; + newpdu = _clone_pdu_header(pdu); + newpdu = _copy_pdu_vars(pdu, newpdu, + drop_err, + 0, 10000); /* skip none, copy all */ + + return newpdu; +} + + +/* + * This function will clone a PDU including all of its variables. + * + * Returns a pointer to the cloned PDU if successful. + * Returns 0 if failure + */ +struct snmp_pdu * +snmp_clone_pdu(struct snmp_pdu *pdu) +{ + return _clone_pdu(pdu, 0); /* copies all variables */ +} + + +/* + * This function will clone a PDU including some of its variables. + * + * If skip_count is not zero, it defines the number of variables to skip. + * If copy_count is not zero, it defines the number of variables to copy. + * + * Returns a pointer to the cloned PDU if successful. + * Returns 0 if failure. + */ +struct snmp_pdu * +snmp_split_pdu(struct snmp_pdu *pdu, int skip_count, int copy_count) +{ + struct snmp_pdu *newpdu; + newpdu = _clone_pdu_header(pdu); + newpdu = _copy_pdu_vars(pdu, newpdu, + 0, /* don't drop any variables */ + skip_count, + copy_count); + + return newpdu; +} + + +/* + * If there was an error in the input pdu, creates a clone of the pdu + * that includes all the variables except the one marked by the errindex. + * The command is set to the input command and the reqid, errstat, and + * errindex are set to default values. + * If the error status didn't indicate an error, the error index didn't + * indicate a variable, the pdu wasn't a get response message, or there + * would be no remaining variables, this function will return 0. + * If everything was successful, a pointer to the fixed cloned pdu will + * be returned. + */ +struct snmp_pdu * +snmp_fix_pdu(struct snmp_pdu *pdu, int command) +{ + struct snmp_pdu *newpdu; + + if ((pdu->command != SNMP_MSG_RESPONSE) + || (pdu->errstat == SNMP_ERR_NOERROR) + || (0 == pdu->variables) + || (pdu->errindex <= 0)) + { + return 0; /* pre-condition tests fail */ + } + + newpdu = _clone_pdu(pdu, 1); /* copies all except errored variable */ + if (!newpdu) + return 0; + if (!newpdu->variables) { + snmp_free_pdu(newpdu); + return 0; /* no variables. "should not happen" */ + } + newpdu->command = command; + newpdu->reqid = snmp_get_next_reqid(); + newpdu->msgid = snmp_get_next_msgid(); + newpdu->errstat = SNMP_DEFAULT_ERRSTAT; + newpdu->errindex = SNMP_DEFAULT_ERRINDEX; + + return newpdu; +} + + +/* + * Returns the number of variables bound to a PDU structure + */ +unsigned long +snmp_varbind_len(struct snmp_pdu * pdu) +{ + register struct variable_list *vars; + unsigned long retVal = 0; + if (pdu) + for (vars = pdu->variables; vars; vars = vars->next_variable) + { + retVal++; + } + + return retVal; +} + +/* + * Add object identifier name to SNMP variable. + * If the name is large, additional memory is allocated. + * Returns 0 if successful. + */ + +int +snmp_set_var_objid (struct variable_list *vp, + const oid *objid, size_t name_length) +{ + size_t len = sizeof(oid) * name_length; + + /* use built-in storage for smaller values */ + if (len <= sizeof(vp->name_loc)) { + vp->name = vp->name_loc; + } + else { + vp->name = (oid *)malloc(len); + if (!vp->name) return 1; + } + memmove(vp->name, objid, len); + vp->name_length = name_length; + return 0; +} + +/* + * Add some value to SNMP variable. + * If the value is large, additional memory is allocated. + * Returns 0 if successful. + */ + +int +snmp_set_var_value(struct variable_list *newvar, + u_char *val_str, size_t val_len) +{ + if (newvar->val.string && + newvar->val.string != newvar->buf) + { + free(newvar->val.string); + } + + newvar->val.string = 0; newvar->val_len = 0; + + /* need a pointer and a length to copy a string value. */ + if (val_str && val_len) + { + if (val_len <= sizeof(newvar->buf)) + newvar->val.string = newvar->buf; + else { + newvar->val.string = (u_char *)malloc(val_len); + if (!newvar->val.string) return 1; + } + memmove(newvar->val.string, val_str, val_len); + newvar->val_len = val_len; + } + + return 0; +} + + +int +snmp_synch_response_cb(struct snmp_session *ss, + struct snmp_pdu *pdu, + struct snmp_pdu **response, + snmp_callback pcb) +{ + struct synch_state lstate, *state; + snmp_callback cbsav; + void * cbmagsav; + int numfds, count; + fd_set fdset; + struct timeval timeout, *tvp; + int block; + + memset((void *)&lstate, 0, sizeof(lstate)); + state = &lstate; + cbsav = ss->callback; + cbmagsav = ss->callback_magic; + ss->callback = pcb; + ss->callback_magic = (void *)state; + + if ((state->reqid = snmp_send(ss, pdu)) == 0){ + snmp_free_pdu(pdu); + state->status = STAT_ERROR; + } + else + state->waiting = 1; + + while(state->waiting){ + numfds = 0; + FD_ZERO(&fdset); + block = SNMPBLOCK; + tvp = &timeout; + timerclear(tvp); + snmp_select_info(&numfds, &fdset, tvp, &block); + if (block == 1) + tvp = NULL; /* block without timeout */ + count = select(numfds, &fdset, 0, 0, tvp); + if (count > 0){ + snmp_read(&fdset); + } else switch(count){ + case 0: + snmp_timeout(); + break; + case -1: + if (errno == EINTR){ + continue; + } else { + snmp_errno = SNMPERR_GENERR; + /* CAUTION! if another thread closed the socket(s) + waited on here, the session structure was freed. + It would be nice, but we can't rely on the pointer. + ss->s_snmp_errno = SNMPERR_GENERR; + ss->s_errno = errno; + */ + snmp_set_detail(strerror(errno)); + } + /* FALLTHRU */ + default: + state->status = STAT_ERROR; + state->waiting = 0; + } + } + *response = state->pdu; + ss->callback = cbsav; + ss->callback_magic = cbmagsav; + return state->status; +} + +int +snmp_synch_response(struct snmp_session *ss, + struct snmp_pdu *pdu, + struct snmp_pdu **response) +{ + return snmp_synch_response_cb(ss,pdu,response,snmp_synch_input); +} + +int +snmp_sess_synch_response(void *sessp, + struct snmp_pdu *pdu, + struct snmp_pdu **response) +{ + struct snmp_session *ss; + struct synch_state lstate, *state; + snmp_callback cbsav; + void * cbmagsav; + int numfds, count; + fd_set fdset; + struct timeval timeout, *tvp; + int block; + + ss = snmp_sess_session(sessp); + memset((void *)&lstate, 0, sizeof(lstate)); + state = &lstate; + cbsav = ss->callback; + cbmagsav = ss->callback_magic; + ss->callback = snmp_synch_input; + ss->callback_magic = (void *)state; + + if ((state->reqid = snmp_sess_send(sessp, pdu)) == 0){ + snmp_free_pdu(pdu); + state->status = STAT_ERROR; + } + else + state->waiting = 1; + + while(state->waiting){ + numfds = 0; + FD_ZERO(&fdset); + block = SNMPBLOCK; + tvp = &timeout; + timerclear(tvp); + snmp_sess_select_info(sessp, &numfds, &fdset, tvp, &block); + if (block == 1) + tvp = NULL; /* block without timeout */ + count = select(numfds, &fdset, 0, 0, tvp); + if (count > 0){ + snmp_sess_read(sessp, &fdset); + } else switch(count){ + case 0: + snmp_sess_timeout(sessp); + break; + case -1: + if (errno == EINTR){ + continue; + } else { + snmp_errno = SNMPERR_GENERR; + /* CAUTION! if another thread closed the socket(s) + waited on here, the session structure was freed. + It would be nice, but we can't rely on the pointer. + ss->s_snmp_errno = SNMPERR_GENERR; + ss->s_errno = errno; + */ + snmp_set_detail(strerror(errno)); + } + /* FALLTHRU */ + default: + state->status = STAT_ERROR; + state->waiting = 0; + } + } + *response = state->pdu; + ss->callback = cbsav; + ss->callback_magic = cbmagsav; + return state->status; +} + + +const char *error_string[19] = { + "(noError) No Error", + "(tooBig) Response message would have been too large.", + "(noSuchName) There is no such variable name in this MIB.", + "(badValue) The value given has the wrong type or length.", + "(readOnly) The two parties used do not have access to use the specified SNMP PDU.", + "(genError) A general failure occured", + "noAccess", + "wrongType", + "wrongLength", + "wrongEncoding", + "wrongValue", + "noCreation", + "inconsistentValue", + "resourceUnavailable", + "commitFailed", + "undoFailed", + "authorizationError", + "notWritable", + "inconsistentName" +}; + +const char * +snmp_errstring(int errstat) +{ + if (errstat <= MAX_SNMP_ERR && errstat >= SNMP_ERR_NOERROR){ + return error_string[errstat]; + } else { + return "Unknown Error"; + } +} diff --git a/packages/net/snmp/lib/current/src/snmp_debug.c b/packages/net/snmp/lib/current/src/snmp_debug.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmp_debug.c @@ -0,0 +1,341 @@ +//========================================================================== +// +// ./lib/current/src/snmp_debug.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +#include + +#include +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#include +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_STDARG_H +#include +#else +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "mib.h" +#include "snmp_api.h" +#include "read_config.h" +#include "snmp_debug.h" +#include "snmp_impl.h" +#include "snmp_logging.h" + +static int dodebug = SNMP_ALWAYS_DEBUG; +static int debug_num_tokens=0; +static char *debug_tokens[MAX_DEBUG_TOKENS]; +static int debug_print_everything=0; + +/* indent debugging: provide a space padded section to return an indent for */ +static int debugindent=0; +#define INDENTMAX 80 +static char debugindentchars[] = " "; + +char * +debug_indent(void) { + return debugindentchars; +} + +void +debug_indent_add(int amount) { + if (debugindent+amount >= 0 && debugindent+amount < 80) { + debugindentchars[debugindent] = ' '; + debugindent += amount; + debugindentchars[debugindent] = '\0'; + } +} + +void +#if HAVE_STDARG_H +DEBUGP(const char *first, ...) +#else +DEBUGP(va_alist) + va_dcl +#endif +{ + va_list args; +#if HAVE_STDARG_H + va_start(args, first); +#else + const char *first; + va_start(args); + first = va_arg(args, const char *); +#endif + + if (dodebug && (debug_print_everything || debug_num_tokens == 0)) { + fprintf(stderr, "%s: ", DEBUG_ALWAYS_TOKEN); + vfprintf(stderr, first, args); + } + va_end(args); +} + +void +DEBUGPOID(oid *theoid, + size_t len) +{ + char c_oid[SPRINT_MAX_LEN]; + sprint_objid(c_oid,theoid,len); + DEBUGP(c_oid); +} + +void debug_config_register_tokens(const char *configtoken, char *tokens) { + debug_register_tokens(tokens); +} + +void debug_config_turn_on_debugging(const char *configtoken, char *line) { + snmp_set_do_debugging(atoi(line)); +} + +void +snmp_debug_init(void) { + debugindentchars[0] = '\0'; /* zero out the debugging indent array. */ + register_premib_handler("snmp","doDebugging", + debug_config_turn_on_debugging, NULL, + "(1|0)"); + register_premib_handler("snmp","debugTokens", + debug_config_register_tokens, NULL, + "token[,token...]"); +} + +void debug_register_tokens(char *tokens) { + char *newp, *cp; + + if (tokens == 0 || *tokens == 0) + return; + + newp = strdup(tokens); /* strtok messes it up */ + cp = strtok(newp, DEBUG_TOKEN_DELIMITER); + while(cp) { + if (strlen(cp) < MAX_DEBUG_TOKEN_LEN) { + if (strcasecmp(cp, DEBUG_ALWAYS_TOKEN) == 0) + debug_print_everything = 1; + else if (debug_num_tokens < MAX_DEBUG_TOKENS) + debug_tokens[debug_num_tokens++] = strdup(cp); + } + cp = strtok(NULL, DEBUG_TOKEN_DELIMITER); + } + free(newp); +} + + +/* + debug_is_token_registered(char *TOKEN): + + returns SNMPERR_SUCCESS + or SNMPERR_GENERR + + if TOKEN has been registered and debugging support is turned on. +*/ +int +debug_is_token_registered(const char *token) { + int i; + + /* debugging flag is on or off */ + if (!dodebug) + return SNMPERR_GENERR; + + if (debug_num_tokens == 0 || debug_print_everything) { + /* no tokens specified, print everything */ + return SNMPERR_SUCCESS; + } else { + for(i=0; i < debug_num_tokens; i++) { + if (strncmp(debug_tokens[i], token, strlen(debug_tokens[i])) == 0) { + return SNMPERR_SUCCESS; + } + } + } + return SNMPERR_GENERR; +} + +void +#if HAVE_STDARG_H +debugmsg(const char *token, const char *format, ...) +#else +debugmsg(va_alist) + va_dcl +#endif +{ + va_list debugargs; + +#if HAVE_STDARG_H + va_start(debugargs,format); +#else + const char *format; + const char *token; + + va_start(debugargs); + token = va_arg(debugargs, const char *); + format = va_arg(debugargs, const char *); /* ??? */ +#endif + + if (debug_is_token_registered(token) == SNMPERR_SUCCESS) { + snmp_vlog(LOG_DEBUG, format, debugargs); + } + va_end(debugargs); +} + +void +debugmsg_oid(const char *token, oid *theoid, size_t len) { + char c_oid[SPRINT_MAX_LEN]; + + sprint_objid(c_oid, theoid, len); + debugmsg(token, c_oid); +} + +void +debugmsg_hex(const char *token, u_char *thedata, size_t len) { + char buf[SPRINT_MAX_LEN]; + + sprint_hexstring(buf, thedata, len); + debugmsg(token, buf); +} + +void +debugmsg_hextli(const char *token, u_char *thedata, size_t len) { + char buf[SPRINT_MAX_LEN]; + int incr; + + /*XX tracing lines removed from this function DEBUGTRACE; */ + DEBUGIF(token) { + for(incr = 16; len > 0; len -= incr, thedata += incr) { + if ((int)len < incr) incr = len; + /*XXnext two lines were DEBUGPRINTINDENT(token);*/ + debugmsgtoken(token, "%s", debug_indent()); + debugmsg(token, "%s", debug_indent()); + sprint_hexstring(buf, thedata, incr); + debugmsg(token, buf); + } + } +} + +void +#if HAVE_STDARG_H +debugmsgtoken(const char *token, const char *format, ...) +#else +debugmsgtoken(va_alist) + va_dcl +#endif +{ + va_list debugargs; + +#if HAVE_STDARG_H + va_start(debugargs,format); +#else + const char *token; + + va_start(debugargs); + token = va_arg(debugargs, const char *); +#endif + + debugmsg(token, "%s: ", token); + + va_end(debugargs); +} + +/* for speed, these shouldn't be in default_storage space */ +void +snmp_set_do_debugging(int val) +{ + dodebug = val; +} + +int +snmp_get_do_debugging (void) +{ + return dodebug; +} diff --git a/packages/net/snmp/lib/current/src/snmp_logging.c b/packages/net/snmp/lib/current/src/snmp_logging.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmp_logging.c @@ -0,0 +1,387 @@ +//========================================================================== +// +// ./lib/current/src/snmp_logging.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* logging.c - generic logging for snmp-agent + * Contributed by Ragnar Kjørstad, ucd@ragnark.vestdata.no 1999-06-26 */ + +#include "config.h" +#include +#if HAVE_MALLOC_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#include +#ifndef __ECOS +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#include +#if HAVE_SYSLOG_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_STDARG_H +#include +#else +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#ifdef WIN32 +#include +#endif + +#include "asn1.h" +#include "default_store.h" +#include "snmp_logging.h" +#include "callback.h" +#define LOGLENGTH 1024 + +static int do_syslogging=0; +static int do_filelogging=0; +static int do_stderrlogging=1; +static int do_log_callback=0; +static int newline = 1; +static FILE *logfile; + +void +init_snmp_logging(void) { + ds_register_premib(ASN_BOOLEAN, "snmp", "logTimestamp", DS_LIBRARY_ID, + DS_LIB_LOG_TIMESTAMP); +} + +int +snmp_get_do_logging(void) { + return (do_syslogging || do_filelogging || do_stderrlogging || + do_log_callback); +} + + +static char * +sprintf_stamp (time_t *now, char *sbuf) +{ + time_t Now; + struct tm *tm; + + if (now == NULL) { + now = &Now; + time (now); + } + tm = localtime (now); + sprintf(sbuf, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d ", + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + return sbuf; +} + +void +snmp_disable_syslog(void) { +#if HAVE_SYSLOG_H + if (do_syslogging) + closelog(); +#endif + do_syslogging=0; +} + + +void +snmp_disable_filelog(void) { + if (do_filelogging) + { + fputs("\n",logfile); + fclose(logfile); + } + do_filelogging=0; +} + + +void +snmp_disable_stderrlog(void) { + do_stderrlogging=0; +} + + +void +snmp_disable_log(void) { + snmp_disable_syslog(); + snmp_disable_filelog(); + snmp_disable_stderrlog(); + snmp_disable_calllog(); +} + + +void +snmp_enable_syslog(void) +{ + snmp_disable_syslog(); +#if HAVE_SYSLOG_H + openlog("ucd-snmp", LOG_CONS|LOG_PID, LOG_DAEMON); + do_syslogging=1; +#endif +} + + +void +snmp_enable_filelog(const char *logfilename, int dont_zero_log) +{ + snmp_disable_filelog(); + logfile=fopen(logfilename, dont_zero_log ? "a" : "w"); + if (logfile) { + do_filelogging=1; + setvbuf(logfile, NULL, _IOLBF, BUFSIZ); + } + else + do_filelogging=0; +} + + +void +snmp_enable_stderrlog(void) { + do_stderrlogging=1; +} + + +void +snmp_enable_calllog(void) { + do_log_callback = 1; +} + + +void +snmp_disable_calllog(void) { + do_log_callback = 0; +} + + +void +snmp_log_string (int priority, const char *string) +{ + char sbuf[40]; + struct snmp_log_message slm; + +#if HAVE_SYSLOG_H + if (do_syslogging) { + syslog(priority, string); + } +#endif + + if (do_log_callback) { + slm.priority = priority; + slm.msg = string; + snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, &slm); + } + + if (do_filelogging || do_stderrlogging) { + + if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_LOG_TIMESTAMP) && newline) { + sprintf_stamp(NULL, (char *)&sbuf); + } else { + strcpy(sbuf, ""); + } + newline = string[strlen(string)-1] == '\n'; + + if (do_filelogging) + fprintf(logfile, "%s%s", sbuf, string); + + if (do_stderrlogging) + fprintf(stderr, "%s%s", sbuf, string); + } +} + +int +snmp_vlog (int priority, const char *format, va_list ap) +{ + char buffer[LOGLENGTH]; + int length; +#if HAVE_VSNPRINTF + char *dynamic; + + length=vsnprintf(buffer, LOGLENGTH, format, ap); +#else + length=vsprintf(buffer, format, ap); +#endif + + if (length == 0) + return(0); /* Empty string */ + + if (length == -1) { + snmp_log_string(LOG_ERR, "Could not format log-string\n"); + return(-1); + } + + if (length < LOGLENGTH) { + snmp_log_string(priority, buffer); + return(0); + } + +#if HAVE_VSNPRINTF + dynamic=malloc(length+1); + if (dynamic==NULL) { + snmp_log_string(LOG_ERR, "Could not allocate memory for log-message\n"); + snmp_log_string(priority, buffer); + return(-2); + } + + vsnprintf(dynamic, length+1, format, ap); + snmp_log_string(priority, dynamic); + free(dynamic); + return(0); + +#else + snmp_log_string(priority, buffer); + snmp_log_string(LOG_ERR, "Log-message too long!\n"); + return(-3); +#endif +} + + +int +#if HAVE_STDARG_H +snmp_log (int priority, const char *format, ...) +#else +snmp_log (va_alist) + va_dcl +#endif +{ + va_list ap; + int ret; +#if HAVE_STDARG_H + va_start(ap, format); +#else + int priority; + const char *format; + va_start(ap); + + priority = va_arg(ap, int); + format = va_arg(ap, const char *); +#endif + ret=snmp_vlog(priority, format, ap); + va_end(ap); + return(ret); +} + +/* + * log a critical error. + */ +void +snmp_log_perror(const char *s) +{ + char *error = strerror(errno); + if (s) { + if (error) + snmp_log(LOG_ERR, "%s: %s\n", s, error); + else + snmp_log(LOG_ERR, "%s: Error %d out-of-range\n", s, errno); + } else { + if (error) + snmp_log(LOG_ERR, "%s\n", error); + else + snmp_log(LOG_ERR, "Error %d out-of-range\n", errno); + } +} + diff --git a/packages/net/snmp/lib/current/src/snmpusm.c b/packages/net/snmp/lib/current/src/snmpusm.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmpusm.c @@ -0,0 +1,2815 @@ +//========================================================================== +// +// ./lib/current/src/snmpusm.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmpusm.c + * + * Routines to manipulate a information about a "user" as + * defined by the SNMP-USER-BASED-SM-MIB MIB. + * + * All functions usm_set_usmStateReference_*() return 0 on success, -1 + * otherwise. + * + * !! Tab stops set to 4 in some parts of this file. !! + * (Designated on a per function.) + */ + +#include + +#include +#if HAVE_WINSOCK_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "snmp_debug.h" +#include "callback.h" +#include "tools.h" +#include "keytools.h" +#include "snmp.h" +#include "read_config.h" +#include "snmpv3.h" +#include "snmp-tc.h" +#include "lcd_time.h" +#include "scapi.h" +#include "callback.h" +#include "default_store.h" +#include "snmpusm.h" + +#include "transform_oids.h" + +static u_int dummy_etime, dummy_eboot; /* For ISENGINEKNOWN(). */ + +/* + * Globals. + */ +static u_int salt_integer; + /* 1/2 of seed for the salt. Cf. RFC2274, Sect 8.1.1.1. + */ + +int reportErrorOnUnknownID = 0; + /* Should be determined based on msg type. + */ + +static struct usmUser *initialUser = NULL; +static struct usmUser *noNameUser = NULL; + +/* + * Prototypes + */ +int +usm_check_secLevel_vs_protocols(int level, + oid *authProtocol, u_int authProtocolLen, + oid *privProtocol, u_int privProtocolLen); + +/* + * Set a given field of the secStateRef. + * + * Allocate bytes for type pointed to by ref->. + * Then copy in and record its length in ref->. + * + * Return 0 on success, -1 otherwise. + */ +#define MAKE_ENTRY( type, item, len, field, field_len ) \ +{ \ + if (ref == NULL) \ + return -1; \ + if (ref->field != NULL) { \ + SNMP_ZERO(ref->field, ref->field_len); \ + SNMP_FREE(ref->field); \ + } \ + ref->field_len = 0; \ + if (len == 0 || item == NULL) { \ + return 0; \ + } \ + if ((ref->field = (type*) malloc (len * sizeof(type))) == NULL) \ + { \ + return -1; \ + } \ + \ + memcpy (ref->field, item, len * sizeof(type)); \ + ref->field_len = len; \ + \ + return 0; \ +} + + +void +usm_set_reportErrorOnUnknownID (int value) +{ + reportErrorOnUnknownID = value; +} + + +struct usmStateReference * +usm_malloc_usmStateReference(void) +{ + struct usmStateReference *retval = (struct usmStateReference *) + calloc(1,sizeof(struct usmStateReference)); + + return retval; +} /* end usm_malloc_usmStateReference() */ + + +void +usm_free_usmStateReference (void *old) +{ + struct usmStateReference *old_ref = (struct usmStateReference *)old; + + if (old_ref) { + + SNMP_FREE(old_ref->usr_name); + SNMP_FREE(old_ref->usr_engine_id); + SNMP_FREE(old_ref->usr_auth_protocol); + SNMP_FREE(old_ref->usr_priv_protocol); + + if (old_ref->usr_auth_key) { + SNMP_ZERO(old_ref->usr_auth_key, old_ref->usr_auth_key_length); + SNMP_FREE(old_ref->usr_auth_key); + } + if (old_ref->usr_priv_key) { + SNMP_ZERO(old_ref->usr_priv_key, old_ref->usr_priv_key_length); + SNMP_FREE(old_ref->usr_priv_key); + } + + SNMP_ZERO(old_ref, sizeof(*old_ref)); + SNMP_FREE(old_ref); + + } + +} /* end usm_free_usmStateReference() */ + + + +int +usm_set_usmStateReference_name ( + struct usmStateReference *ref, + char *name, + size_t name_len) +{ + MAKE_ENTRY (char,name,name_len,usr_name,usr_name_length); +} + +int +usm_set_usmStateReference_engine_id ( + struct usmStateReference *ref, + u_char *engine_id, + size_t engine_id_len) +{ + MAKE_ENTRY (u_char,engine_id,engine_id_len, + usr_engine_id,usr_engine_id_length); +} + +int +usm_set_usmStateReference_auth_protocol ( + struct usmStateReference *ref, + oid *auth_protocol, + size_t auth_protocol_len) +{ + MAKE_ENTRY (oid ,auth_protocol,auth_protocol_len, + usr_auth_protocol,usr_auth_protocol_length); +} + +int +usm_set_usmStateReference_auth_key ( + struct usmStateReference *ref, + u_char *auth_key, + size_t auth_key_len) +{ + MAKE_ENTRY (u_char,auth_key,auth_key_len, + usr_auth_key,usr_auth_key_length); +} + +int +usm_set_usmStateReference_priv_protocol ( + struct usmStateReference *ref, + oid *priv_protocol, + size_t priv_protocol_len) +{ + MAKE_ENTRY (oid,priv_protocol,priv_protocol_len, + usr_priv_protocol,usr_priv_protocol_length); +} + +int +usm_set_usmStateReference_priv_key ( + struct usmStateReference *ref, + u_char *priv_key, + size_t priv_key_len) +{ + MAKE_ENTRY (u_char,priv_key,priv_key_len, + usr_priv_key,usr_priv_key_length); +} + +int +usm_set_usmStateReference_sec_level ( + struct usmStateReference *ref, + int sec_level) +{ + if (ref == NULL) return -1; + ref->usr_sec_level = sec_level; + return 0; +} + + + +#ifdef SNMP_TESTING_CODE +/*******************************************************************-o-****** + * emergency_print + * + * Parameters: + * *field + * length + * + * This is a print routine that is solely included so that it can be + * used in gdb. Don't use it as a function, it will be pulled before + * a real release of the code. + * + * tab stop 4 + * + * XXX fflush() only works on FreeBSD; core dumps on Sun OS's + */ +void +emergency_print (u_char *field, u_int length) +{ + int iindex; + int start=0; + int stop=25; + + while (start < stop) + { + for (iindex = start; iindex < stop; iindex++) + printf ("%02X ", field[iindex]); + + printf ("\n"); + start = stop; + stop = stop+25 1) + { + len--; + number <<= 8; + } + + return len; + +} /* end asn_predict_length() */ + + + + +/*******************************************************************-o-****** + * asn_predict_length + * + * Parameters: + * type + * *ptr + * u_char_len + * + * Returns: + * Length in bytes: 1 + + , where + * + * 1 For the ASN.1 type. + * # of bytes to store length of data. + * Length of data associated with ASN.1 type. + * + * This gives the number of bytes that the ASN.1 encoder (in asn1.c) will + * use to encode a particular integer value. This is as broken as the + * currently used encoder. + * + * XXX How is chosen, exactly?? + */ +int +asn_predict_length (int type, u_char *ptr, size_t u_char_len) +{ + + if (type & ASN_SEQUENCE) return 1+3+u_char_len; + + if (type & ASN_INTEGER) + { + u_long value; + memcpy (&value, ptr, u_char_len); + u_char_len = asn_predict_int_length (type, value, u_char_len); + } + + if (u_char_len < 0x80) + return 1+1+u_char_len; + else if (u_char_len < 0xFF) + return 1+2+u_char_len; + else + return 1+3+u_char_len; + +} /* end asn_predict_length() */ + + + + +/*******************************************************************-o-****** + * usm_calc_offsets + * + * Parameters: + * (See list below...) + * + * Returns: + * 0 On success, + * -1 Otherwise. + * + * + * This routine calculates the offsets into an outgoing message buffer + * for the necessary values. The outgoing buffer will generically + * look like this: + * + * SNMPv3 Message + * SEQ len[11] + * INT len version + * Header + * SEQ len + * INT len MsgID + * INT len msgMaxSize + * OST len msgFlags (OST = OCTET STRING) + * INT len msgSecurityModel + * MsgSecurityParameters + * [1] OST len[2] + * SEQ len[3] + * OST len msgAuthoritativeEngineID + * INT len msgAuthoritativeEngineBoots + * INT len msgAuthoritativeEngineTime + * OST len msgUserName + * OST len[4] [5] msgAuthenticationParameters + * OST len[6] [7] msgPrivacyParameters + * MsgData + * [8] OST len[9] [10] encryptedPDU + * or + * [8,10] SEQUENCE len[9] scopedPDU + * [12] + * + * The bracketed points will be needed to be identified ([x] is an index + * value, len[x] means a length value). Here is a semantic guide to them: + * + * [1] = globalDataLen (input) + * [2] = otstlen + * [3] = seq_len + * [4] = msgAuthParmLen (may be 0 or 12) + * [5] = authParamsOffset + * [6] = msgPrivParmLen (may be 0 or 8) + * [7] = privParamsOffset + * [8] = globalDataLen + msgSecParmLen + * [9] = datalen + * [10] = dataOffset + * [11] = theTotalLength - the length of the header itself + * [12] = theTotalLength + */ +int +usm_calc_offsets ( + size_t globalDataLen, /* SNMPv3Message + HeaderData */ + int secLevel, + size_t secEngineIDLen, + size_t secNameLen, + size_t scopedPduLen, /* An BER encoded sequence. */ + u_long engineboots, /* XXX (asn1.c works in long, not int.) */ + long engine_time, /* XXX (asn1.c works in long, not int.) */ + + size_t *theTotalLength, /* globalDataLen + msgSecurityP. + msgData */ + size_t *authParamsOffset,/* Distance to auth bytes. */ + size_t *privParamsOffset,/* Distance to priv bytes. */ + size_t *dataOffset, /* Distance to scopedPdu SEQ -or- the + * crypted (data) portion of msgData. */ + + size_t *datalen, /* Size of msgData OCTET STRING encoding. */ + size_t *msgAuthParmLen, /* Size of msgAuthenticationParameters. */ + size_t *msgPrivParmLen, /* Size of msgPrivacyParameters. */ + size_t *otstlen, /* Size of msgSecurityP. O.S. encoding. */ + size_t *seq_len, /* Size of msgSecurityP. SEQ data. */ + size_t *msgSecParmLen) /* Size of msgSecurityP. SEQ. */ +{ + int engIDlen, /* Sizes of OCTET STRING and SEQ encodings */ + engBtlen, /* for fields within */ + engTmlen, /* msgSecurityParameters portion of */ + namelen, /* SNMPv3Message. */ + authlen, + privlen; + + /* + * If doing authentication, msgAuthParmLen = 12 else msgAuthParmLen = 0. + * If doing encryption, msgPrivParmLen = 8 else msgPrivParmLen = 0. + */ + *msgAuthParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV + || secLevel == SNMP_SEC_LEVEL_AUTHPRIV)?12:0; + + *msgPrivParmLen = (secLevel == SNMP_SEC_LEVEL_AUTHPRIV)?8:0; + + + /* + * Calculate lengths. + */ + if ( (engIDlen = asn_predict_length(ASN_OCTET_STR, + 0, secEngineIDLen)) == -1 ) + { + return -1; + } + + if ( (engBtlen = asn_predict_length (ASN_INTEGER, + (u_char*)&engineboots,sizeof(long))) == -1 ) + { + return -1; + } + + if ( (engTmlen = asn_predict_length (ASN_INTEGER, + (u_char*)&engine_time,sizeof(long))) == -1 ) + { + return -1; + } + + if ( (namelen = asn_predict_length (ASN_OCTET_STR,0,secNameLen))==-1 ) + { + return -1; + } + + if ( (authlen = asn_predict_length (ASN_OCTET_STR, + 0,*msgAuthParmLen)) == -1 ) + { + return -1; + } + + if ( (privlen = asn_predict_length (ASN_OCTET_STR, + 0,*msgPrivParmLen)) == -1 ) + { + return -1; + } + + *seq_len = engIDlen + engBtlen + engTmlen + namelen + authlen + privlen; + + if ( (*otstlen = asn_predict_length (ASN_SEQUENCE, + 0, *seq_len)) == -1 ) + { + return -1; + } + + if ( (*msgSecParmLen = asn_predict_length (ASN_OCTET_STR, + 0,*otstlen)) == -1 ) + { + return -1; + } + + *authParamsOffset = globalDataLen + + + (*msgSecParmLen - *seq_len) + + engIDlen + engBtlen + engTmlen + namelen + + (authlen - *msgAuthParmLen); + + *privParamsOffset = *authParamsOffset + *msgAuthParmLen + + (privlen - *msgPrivParmLen); + + + /* + * Compute the size of the plaintext. Round up to account for cipher + * block size, if necessary. + * + * XXX This is hardwired for 1DES... If scopedPduLen is already + * a multiple of 8, then *add* 8 more; otherwise, round up + * to the next multiple of 8. + * + * FIX Calculation of encrypted portion of msgData and consequent + * setting and sanity checking of theTotalLength, et al. should + * occur *after* encryption has taken place. + */ + if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + scopedPduLen = ( scopedPduLen % 8 ) + ? ROUNDUP8(scopedPduLen) + : scopedPduLen + 8; + + if ((*datalen = + asn_predict_length (ASN_OCTET_STR,0,scopedPduLen))==-1) + { + return -1; + } + } + else + { + *datalen = scopedPduLen; + } + + *dataOffset = globalDataLen + *msgSecParmLen + + (*datalen - scopedPduLen); + *theTotalLength = globalDataLen + *msgSecParmLen + *datalen; + + return 0; + +} /* end usm_calc_offsets() */ + + + + + +/*******************************************************************-o-****** + * usm_set_salt + * + * Parameters: + * *iv (O) Buffer to contain IV. + * *iv_length (O) Length of iv. + * *priv_salt (I) Salt portion of private key. + * priv_salt_length (I) Length of priv_salt. + * *msgSalt (I/O) Pointer salt portion of outgoing msg buffer. + * + * Returns: + * 0 On success, + * -1 Otherwise. + * + * Determine the initialization vector for the DES-CBC encryption. + * (Cf. RFC 2274, 8.1.1.1.) + * + * iv is defined as the concatenation of engineBoots and the + * salt integer. + * The salt integer is incremented. + * The resulting salt is copied into the msgSalt buffer. + * The result of the concatenation is then XORed with the salt + * portion of the private key (last 8 bytes). + * The IV result is returned individually for further use. + */ +int +usm_set_salt ( u_char *iv, + size_t *iv_length, + u_char *priv_salt, + size_t priv_salt_length, + u_char *msgSalt) +{ + size_t propersize_salt = BYTESIZE(USM_MAX_SALT_LENGTH); + int net_boots; + int net_salt_int; + /* net_* should be encoded in network byte order. XXX Why? + */ + int iindex; + + + /* + * Sanity check. + */ + if ( !iv || !iv_length || !priv_salt || !msgSalt + || (*iv_length != propersize_salt) + || (priv_salt_length < propersize_salt) ) + { + return -1; + } + + + net_boots = htonl(snmpv3_local_snmpEngineBoots()); + net_salt_int = htonl(salt_integer); + + salt_integer += 1; + + memcpy(iv, &net_boots, propersize_salt/2); + memcpy(iv+(propersize_salt/2), &net_salt_int, propersize_salt/2); + + memcpy(msgSalt, iv, propersize_salt); + + + /* + * Turn the salt into an IV: XOR with salt + * portion of priv_key. + */ + for (iindex = 0; iindex < (int)propersize_salt; iindex++) + iv[iindex] ^= priv_salt[iindex]; + + + return 0; + +} /* end usm_set_salt() */ + + + + +/*******************************************************************-o-****** + * usm_generate_out_msg + * + * Parameters: + * (See list below...) + * + * Returns: + * SNMPERR_SUCCESS On success. + * SNMPERR_USM_AUTHENTICATIONFAILURE + * SNMPERR_USM_ENCRYPTIONERROR + * SNMPERR_USM_GENERICERROR + * SNMPERR_USM_UNKNOWNSECURITYNAME + * SNMPERR_USM_GENERICERROR + * SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL + * + * + * Generates an outgoing message. + * + * XXX Beware of misnomers! + */ +int +usm_generate_out_msg ( + int msgProcModel, /* (UNUSED) */ + + u_char *globalData, /* IN */ + /* Pointer to msg header data will point to the beginning + * of the entire packet buffer to be transmitted on wire, + * memory will be contiguous with secParams, typically + * this pointer will be passed back as beginning of + * wholeMsg below. asn seq. length is updated w/ new length. + * + * While this points to a buffer that should be big enough + * for the whole message, only the first two parts + * of the message are completed, namely SNMPv3Message and + * HeaderData. globalDataLen (next parameter) represents + * the length of these two completed parts. + */ + + size_t globalDataLen, /* IN - Length of msg header data. */ + int maxMsgSize, /* (UNUSED) */ + int secModel, /* (UNUSED) */ + u_char *secEngineID, /* IN - Pointer snmpEngineID. */ + size_t secEngineIDLen, /* IN - SnmpEngineID length. */ + char *secName, /* IN - Pointer to securityName. */ + size_t secNameLen, /* IN - SecurityName length. */ + int secLevel, /* IN - AuthNoPriv, authPriv etc. */ + + u_char *scopedPdu, /* IN */ + /* Pointer to scopedPdu will be encrypted by USM if needed + * and written to packet buffer immediately following + * securityParameters, entire msg will be authenticated by + * USM if needed. + */ + + size_t scopedPduLen, /* IN - scopedPdu length. */ + + void *secStateRef, /* IN */ + /* secStateRef, pointer to cached info provided only for + * Response, otherwise NULL. + */ + + u_char *secParams, /* OUT */ + /* BER encoded securityParameters pointer to offset within + * packet buffer where secParams should be written, the + * entire BER encoded OCTET STRING (including header) is + * written here by USM secParams = globalData + + * globalDataLen. + */ + + size_t *secParamsLen, /* IN/OUT - Len available, len returned. */ + + u_char **wholeMsg, /* OUT */ + /* Complete authenticated/encrypted message - typically + * the pointer to start of packet buffer provided in + * globalData is returned here, could also be a separate + * buffer. + */ + + size_t *wholeMsgLen) /* IN/OUT - Len available, len returned. */ +{ + size_t otstlen; + size_t seq_len; + size_t msgAuthParmLen; + size_t msgPrivParmLen; + size_t msgSecParmLen; + size_t authParamsOffset; + size_t privParamsOffset; + size_t datalen; + size_t dataOffset; + size_t theTotalLength; + + u_char *ptr; + size_t ptr_len; + size_t remaining; + size_t offSet; + u_int boots_uint; + u_int time_uint; + long boots_long; + long time_long; + + /* + Indirection because secStateRef values override parameters. + + None of these are to be free'd - they are either pointing to + what's in the secStateRef or to something either in the + actual prarmeter list or the user list. + */ + + char *theName = NULL; + u_int theNameLength = 0; + u_char *theEngineID = NULL; + u_int theEngineIDLength = 0; + u_char *theAuthKey = NULL; + u_int theAuthKeyLength = 0; + oid *theAuthProtocol = NULL; + u_int theAuthProtocolLength = 0; + u_char *thePrivKey = NULL; + u_int thePrivKeyLength = 0; + oid *thePrivProtocol = NULL; + u_int thePrivProtocolLength = 0; + int theSecLevel = 0; /* No defined const for bad + * value (other then err). + */ + + + DEBUGMSGTL(("usm","USM processing has begun.\n")); + + if (secStateRef != NULL) + { + /* To hush the compiler for now. XXX */ + struct usmStateReference *ref + = (struct usmStateReference *)secStateRef; + + theName = ref->usr_name; + theNameLength = ref->usr_name_length; + theEngineID = ref->usr_engine_id; + theEngineIDLength = ref->usr_engine_id_length; + + if (!theEngineIDLength) { + theEngineID = secEngineID; + theEngineIDLength = secEngineIDLen; + } + + theAuthProtocol = ref->usr_auth_protocol; + theAuthProtocolLength = ref->usr_auth_protocol_length; + theAuthKey = ref->usr_auth_key; + theAuthKeyLength = ref->usr_auth_key_length; + thePrivProtocol = ref->usr_priv_protocol; + thePrivProtocolLength = ref->usr_priv_protocol_length; + thePrivKey = ref->usr_priv_key; + thePrivKeyLength = ref->usr_priv_key_length; + theSecLevel = ref->usr_sec_level; + } + + /* + * Identify the user record. + */ + else + { + struct usmUser *user; + + /* we do allow an unknown user name for + unauthenticated requests. */ + if ( (user = + usm_get_user(secEngineID, secEngineIDLen, secName)) + == NULL && + secLevel != SNMP_SEC_LEVEL_NOAUTH) + { + DEBUGMSGTL(("usm","Unknown User\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_UNKNOWNSECURITYNAME; + } + + theName = secName; + theNameLength = secNameLen; + theEngineID = secEngineID; + theSecLevel = secLevel; + theEngineIDLength = secEngineIDLen; + if (user) { + theAuthProtocol = user->authProtocol; + theAuthProtocolLength = user->authProtocolLen; + theAuthKey = user->authKey; + theAuthKeyLength = user->authKeyLen; + thePrivProtocol = user->privProtocol; + thePrivProtocolLength = user->privProtocolLen; + thePrivKey = user->privKey; + thePrivKeyLength = user->privKeyLen; + } else { + /* unknown users can not do authentication (obviously) */ + theAuthProtocol = usmNoAuthProtocol; + theAuthProtocolLength = sizeof(usmNoAuthProtocol)/sizeof(oid); + theAuthKey = NULL; + theAuthKeyLength = 0; + thePrivProtocol = usmNoPrivProtocol; + thePrivProtocolLength = sizeof(usmNoPrivProtocol)/sizeof(oid); + thePrivKey = NULL; + thePrivKeyLength = 0; + } + } /* endif -- secStateRef==NULL */ + + + /* + From here to the end of the function, avoid reference to + secName, secEngineID, secLevel, and associated lengths. + */ + + + /* + * Check to see if the user can use the requested sec services. + */ + if (usm_check_secLevel_vs_protocols( + theSecLevel, + theAuthProtocol, theAuthProtocolLength, + theAuthProtocol, theAuthProtocolLength) == 1) + { + DEBUGMSGTL(("usm","Unsupported Security Level\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL; + } + + + /* + * Retrieve the engine information. + * + * XXX No error is declared in the EoP when sending messages to + * unknown engines, processing continues w/ boots/time == (0,0). + */ + if (get_enginetime (theEngineID, theEngineIDLength, + &boots_uint, &time_uint, FALSE) == -1) + { + DEBUGMSGTL(("usm","%s\n", "Failed to find engine data.")); + } + + boots_long = boots_uint; + time_long = time_uint; + + + /* + * Set up the Offsets. + */ + if (usm_calc_offsets (globalDataLen, theSecLevel, theEngineIDLength, + theNameLength, scopedPduLen, boots_long, time_long, + &theTotalLength, &authParamsOffset, + &privParamsOffset, &dataOffset, &datalen, + &msgAuthParmLen, &msgPrivParmLen, + &otstlen, &seq_len, &msgSecParmLen) == -1) + { + DEBUGMSGTL(("usm","Failed calculating offsets.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_GENERICERROR; + } + + /* + So, we have the offsets for the three parts that need to be + determined, and an overall length. Now we need to make + sure all of this would fit in the outgoing buffer, and + whether or not we need to make a new buffer, etc. + */ + + + /* + * Set wholeMsg as a pointer to globalData. Sanity check for + * the proper size. + * + * Mark workspace in the message with bytes of all 1's to make it + * easier to find mistakes in raw message dumps. + */ + ptr = *wholeMsg = globalData; + if (theTotalLength > *wholeMsgLen) + { + DEBUGMSGTL(("usm","Message won't fit in buffer.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_GENERICERROR; + } + + ptr_len = *wholeMsgLen = theTotalLength; + +#ifdef SNMP_TESTING_CODE + memset (&ptr[globalDataLen], 0xFF, theTotalLength-globalDataLen); +#endif /* SNMP_TESTING_CODE */ + + + /* + * Do the encryption. + */ + if (theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + size_t encrypted_length = theTotalLength - dataOffset; + size_t salt_length = BYTESIZE(USM_MAX_SALT_LENGTH); + u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)]; + + /* XXX Hardwired to seek into a 1DES private key! + */ + if ( usm_set_salt( salt, &salt_length, + thePrivKey+8, thePrivKeyLength-8, + &ptr[privParamsOffset]) + == -1 ) + { + DEBUGMSGTL(("usm","Can't set DES-CBC salt.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_GENERICERROR; + } + + if ( sc_encrypt( + thePrivProtocol, thePrivProtocolLength, + thePrivKey, thePrivKeyLength, + salt, salt_length, + scopedPdu, scopedPduLen, + &ptr[dataOffset], &encrypted_length) + != SNMP_ERR_NOERROR ) + { + DEBUGMSGTL(("usm","DES-CBC error.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_ENCRYPTIONERROR; + } + + +#ifdef SNMP_TESTING_CODE + if ( debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { + dump_chunk("usm/dump", "This data was encrypted:", + scopedPdu, scopedPduLen); + dump_chunk("usm/dump", "salt + Encrypted form:", + salt, salt_length); + dump_chunk("usm/dump", NULL, + &ptr[dataOffset], encrypted_length); + dump_chunk("usm/dump", "*wholeMsg:", + *wholeMsg, theTotalLength); + } +#endif + + + ptr = *wholeMsg; + ptr_len = *wholeMsgLen = theTotalLength; + + + /* + * XXX Sanity check for salt length should be moved up + * under usm_calc_offsets() or tossed. + */ + if ( (encrypted_length != (theTotalLength - dataOffset)) + || (salt_length != msgPrivParmLen) ) + { + DEBUGMSGTL(("usm","DES-CBC length error.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_ENCRYPTIONERROR; + } + + DEBUGMSGTL(("usm","Encryption successful.\n")); + } + + /* + * No encryption for you! + */ + else + { + memcpy( &ptr[dataOffset], scopedPdu, scopedPduLen ); + } + + + + /* + * Start filling in the other fields (in prep for authentication). + * + * offSet is an octet string header, which is different from all + * the other headers. + */ + remaining = ptr_len - globalDataLen; + + offSet = ptr_len - remaining; + asn_build_header (&ptr[offSet], &remaining, + (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), otstlen); + + offSet = ptr_len - remaining; + asn_build_sequence (&ptr[offSet], &remaining, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), seq_len); + + offSet = ptr_len - remaining; + asn_build_string (&ptr[offSet], &remaining, + (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + theEngineID, theEngineIDLength); + + offSet = ptr_len - remaining; + asn_build_int (&ptr[offSet], &remaining, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &boots_long, sizeof(long)); + + offSet = ptr_len - remaining; + asn_build_int (&ptr[offSet], &remaining, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &time_long, sizeof(long)); + + offSet = ptr_len - remaining; + asn_build_string (&ptr[offSet], &remaining, + (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + (u_char *)theName, theNameLength); + + + /* + Note: if there is no authentication being done, + msgAuthParmLen is 0, and there is no effect (other than + inserting a zero-length header) of the following + statements. + */ + + offSet = ptr_len - remaining; + asn_build_header( + &ptr[offSet], + &remaining, + (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + msgAuthParmLen); + + if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV + || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + offSet = ptr_len - remaining; + memset (&ptr[offSet],0,msgAuthParmLen); + } + + remaining -= msgAuthParmLen; + + + /* + Note: if there is no encryption being done, msgPrivParmLen + is 0, and there is no effect (other than inserting a + zero-length header) of the following statements. + */ + + offSet = ptr_len - remaining; + asn_build_header( + &ptr[offSet], + &remaining, + (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + msgPrivParmLen); + + remaining -= msgPrivParmLen; /* Skipping the IV already there. */ + + + /* + * For privacy, need to add the octet string header for it. + */ + if (theSecLevel==SNMP_SEC_LEVEL_AUTHPRIV) + { + offSet = ptr_len - remaining; + asn_build_header( + &ptr[offSet], + &remaining, + (u_char)(ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + theTotalLength - dataOffset ); + } + + + /* + * Adjust overall length and store it as the first SEQ length + * of the SNMPv3Message. + * + * FIX 4 is a magic number! + */ + remaining = theTotalLength; + asn_build_sequence (ptr, &remaining, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), theTotalLength-4); + + + /* + * Now, time to consider / do authentication. + */ + if (theSecLevel == SNMP_SEC_LEVEL_AUTHNOPRIV + || theSecLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + size_t temp_sig_len = msgAuthParmLen; + u_char *temp_sig = (u_char *) malloc (temp_sig_len); + + if (temp_sig == NULL) + { + DEBUGMSGTL(("usm","Out of memory.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_GENERICERROR; + } + + if ( sc_generate_keyed_hash ( + theAuthProtocol, theAuthProtocolLength, + theAuthKey, theAuthKeyLength, + ptr, ptr_len, + temp_sig, &temp_sig_len) + != SNMP_ERR_NOERROR ) + { + /* FIX temp_sig_len defined?! + */ + SNMP_ZERO(temp_sig, temp_sig_len); + SNMP_FREE(temp_sig); + DEBUGMSGTL(("usm","Signing failed.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_AUTHENTICATIONFAILURE; + } + + if (temp_sig_len != msgAuthParmLen) + { + SNMP_ZERO(temp_sig, temp_sig_len); + SNMP_FREE(temp_sig); + DEBUGMSGTL(("usm","Signing lengths failed.\n")); + usm_free_usmStateReference (secStateRef); + return SNMPERR_USM_AUTHENTICATIONFAILURE; + } + + memcpy (&ptr[authParamsOffset], temp_sig, msgAuthParmLen); + + SNMP_ZERO(temp_sig, temp_sig_len); + SNMP_FREE(temp_sig); + + } /* endif -- create keyed hash */ + + + usm_free_usmStateReference (secStateRef); + + DEBUGMSGTL(("usm","USM processing completed.\n")); + + return SNMPERR_SUCCESS; + +} /* end usm_generate_out_msg() */ + + + + +/*******************************************************************-o-****** + * usm_parse_security_parameters + * + * Parameters: + * (See list below...) + * + * Returns: + * 0 On success, + * -1 Otherwise. + * + * tab stop 4 + * + * Extracts values from the security header and data portions of the + * incoming buffer. + */ +int +usm_parse_security_parameters ( + u_char *secParams, + size_t remaining, + u_char *secEngineID, + size_t *secEngineIDLen, + u_int *boots_uint, + u_int *time_uint, + char *secName, + size_t *secNameLen, + u_char *signature, + size_t *signature_length, + u_char *salt, + size_t *salt_length, + u_char **data_ptr) +{ + u_char *parse_ptr = secParams; + u_char *value_ptr; + u_char *next_ptr; + u_char type_value; + + size_t octet_string_length = remaining; + size_t sequence_length; + size_t remaining_bytes; + + long boots_long; + long time_long; + + u_int origNameLen; + + + /* + * Eat the first octet header. + */ + if ((value_ptr = asn_parse_sequence (parse_ptr, &octet_string_length, + &type_value, + (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + "usm first octet")) == NULL) + { + /* RETURN parse error */ return -1; + } + + + /* + * Eat the sequence header. + */ + parse_ptr = value_ptr; + sequence_length = octet_string_length; + + if ((value_ptr = asn_parse_sequence (parse_ptr, &sequence_length, + &type_value, + (ASN_SEQUENCE | ASN_CONSTRUCTOR), + "usm sequence")) == NULL) + { + /* RETURN parse error */ return -1; + } + + + /* + * Retrieve the engineID. + */ + parse_ptr = value_ptr; + remaining_bytes = sequence_length; + + DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineID\n"); + if ( (next_ptr + = asn_parse_string (parse_ptr, &remaining_bytes, &type_value, + secEngineID, secEngineIDLen)) == NULL ) + { + DEBUGINDENTLESS(); + /* RETURN parse error */ return -1; + } + DEBUGINDENTLESS(); + + if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR)) + { + /* RETURN parse error */ return -1; + } + + + /* + * Retrieve the engine boots, notice switch in the way next_ptr and + * remaining_bytes are used (to accomodate the asn code). + */ + DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineBoots\n"); + if ((next_ptr = asn_parse_int (next_ptr, &remaining_bytes, &type_value, + &boots_long, sizeof(long))) == NULL) + { + DEBUGINDENTLESS(); + /* RETURN parse error */ return -1; + } + DEBUGINDENTLESS(); + + if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_INTEGER)) + { + DEBUGINDENTLESS(); + /* RETURN parse error */ return -1; + } + + *boots_uint = (u_int) boots_long; + + + /* + * Retrieve the time value. + */ + DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthoritativeEngineTime\n"); + if ((next_ptr = asn_parse_int (next_ptr, &remaining_bytes, &type_value, + &time_long, sizeof(long))) == NULL) + { + /* RETURN parse error */ return -1; + } + + if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_INTEGER)) + { + DEBUGINDENTLESS(); + /* RETURN parse error */ return -1; + } + + *time_uint = (u_int) time_long; + + + /* + * Retrieve the secName. + */ + origNameLen = *secNameLen; + + DEBUGDUMPHEADER("dump_recv", "Parsing msgUserName\n"); + if ( (next_ptr + = asn_parse_string (next_ptr, &remaining_bytes, &type_value, + (u_char *)secName, secNameLen)) == NULL ) + { + DEBUGINDENTLESS(); + /* RETURN parse error */ return -1; + } + DEBUGINDENTLESS(); + + /* FIX -- doesn't this also indicate a buffer overrun? + */ + if ((int)origNameLen < *secNameLen + 1) + { + /* RETURN parse error, but it's really a parameter error */ + return -1; + } + + secName[*secNameLen] = '\0'; + + if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR)) + { + /* RETURN parse error */ return -1; + } + + + /* + * Retrieve the signature and blank it if there. + */ + DEBUGDUMPHEADER("dump_recv", "Parsing msgAuthenticationParameters\n"); + if ( (next_ptr + = asn_parse_string (next_ptr, &remaining_bytes, &type_value, + signature, signature_length)) == NULL ) + { + DEBUGINDENTLESS(); + /* RETURN parse error */ return -1; + } + DEBUGINDENTLESS(); + + if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR)) + { + /* RETURN parse error */ return -1; + } + + if (*signature_length != 0) /* Blanking for authentication step later */ + { + memset (next_ptr-(u_long)*signature_length, + 0, *signature_length); + } + + + /* + * Retrieve the salt. + * + * Note that the next ptr is where the data section starts. + */ + DEBUGDUMPHEADER("dump_recv", "Parsing msgPrivacyParameters\n"); + if ( (*data_ptr + = asn_parse_string (next_ptr, &remaining_bytes, &type_value, + salt, salt_length)) == NULL ) + { + DEBUGINDENTLESS(); + /* RETURN parse error */ return -1; + } + DEBUGINDENTLESS(); + + if (type_value != (u_char) (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR)) + { + /* RETURN parse error */ return -1; + } + + return 0; + +} /* end usm_parse_security_parameters() */ + + + + +/*******************************************************************-o-****** + * usm_check_and_update_timeliness + * + * Parameters: + * *secEngineID + * secEngineIDen + * boots_uint + * time_uint + * *error + * + * Returns: + * 0 On success, + * -1 Otherwise. + * + * + * Performs the incoming timeliness checking and setting. + */ +int +usm_check_and_update_timeliness( + u_char *secEngineID, + size_t secEngineIDLen, + u_int boots_uint, + u_int time_uint, + int *error) +{ + u_char myID[USM_MAX_ID_LENGTH]; + int myIDLength = snmpv3_get_engineID(myID, USM_MAX_ID_LENGTH); + u_int myBoots; + u_int myTime; + + + + if ( (myIDLength > USM_MAX_ID_LENGTH) || (myIDLength < 0) ) + { + /* We're probably already screwed...buffer overwrite. XXX? */ + DEBUGMSGTL(("usm","Buffer overflow.\n")); + *error = SNMPERR_USM_GENERICERROR; + return -1; + } + + myBoots = snmpv3_local_snmpEngineBoots(); + myTime = snmpv3_local_snmpEngineTime(); + + + /* + * IF the time involved is local + * Make sure message is inside the time window + * ELSE + * IF boots is higher or boots is the same and time is higher + * remember this new data + * ELSE + * IF !(boots same and time within USM_TIME_WINDOW secs) + * Message is too old + * ELSE + * Message is ok, but don't take time + * ENDIF + * ENDIF + * ENDIF + */ + + /* + * This is a local reference. + */ + if ( (int)secEngineIDLen == myIDLength + && memcmp (secEngineID, myID, myIDLength) == 0 ) + { + u_int time_difference = myTime > time_uint ? + myTime - time_uint : time_uint - myTime; + + if (boots_uint == ENGINEBOOT_MAX + || boots_uint != myBoots + || time_difference > USM_TIME_WINDOW) + { + if ( snmp_increment_statistic( + STAT_USMSTATSNOTINTIMEWINDOWS) == 0 ) + { + DEBUGMSGTL(("usm","%s\n", + "Failed to increment statistic.")); + } + + DEBUGMSGTL(("usm","%s\n", "Not in local time window.")); + *error = SNMPERR_USM_NOTINTIMEWINDOW; + return -1; + } + + *error = SNMPERR_SUCCESS; + return 0; + } + + /* + * This is a remote reference. + */ + else + { + u_int theirBoots, + theirTime, + theirLastTime; + u_int time_difference; + + if ( get_enginetime_ex( secEngineID, secEngineIDLen, + &theirBoots, &theirTime, + &theirLastTime, + TRUE) + != SNMPERR_SUCCESS) + { + DEBUGMSGTL(("usm","%s\n", + "Failed to get remote engine's times.")); + + *error = SNMPERR_USM_GENERICERROR; + return -1; + } + + time_difference = theirTime > time_uint ? + theirTime - time_uint : time_uint - theirTime; + + + /* + * XXX Contrary to the pseudocode: + * See if boots is invalid first. + */ + if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint) + { + DEBUGMSGTL(("usm","%s\n", "Remote boot count invalid.")); + + *error = SNMPERR_USM_NOTINTIMEWINDOW; + return -1; + } + + + /* + * Boots is ok, see if the boots is the same but the time + * is old. + */ + if (theirBoots == boots_uint && time_uint < theirLastTime) + { + if(time_difference > USM_TIME_WINDOW) + { + DEBUGMSGTL(("usm","%s\n", "Message too old.")); + *error = SNMPERR_USM_NOTINTIMEWINDOW; + return -1; + } + + else /* Old, but acceptable */ + { + *error = SNMPERR_SUCCESS; + return 0; + } + } + + + /* + Message is ok, either boots has been advanced, or + time is greater than before with the same boots. + */ + + if ( set_enginetime( secEngineID, secEngineIDLen, + boots_uint, time_uint, + TRUE) + != SNMPERR_SUCCESS) + { + DEBUGMSGTL(("usm","%s\n", "Failed updating remote boot/time.")); + *error = SNMPERR_USM_GENERICERROR; + return -1; + } + + *error = SNMPERR_SUCCESS; + return 0; /* Fresh message and time updated */ + + } /* endif -- local or remote time reference. */ + + +} /* end usm_check_and_update_timeliness() */ + + + + +/*******************************************************************-o-****** + * usm_process_in_msg + * + * Parameters: + * (See list below...) + * + * Returns: + * SNMPERR_SUCCESS On success. + * SNMPERR_USM_AUTHENTICATIONFAILURE + * SNMPERR_USM_DECRYPTIONERROR + * SNMPERR_USM_GENERICERROR + * SNMPERR_USM_PARSEERROR + * SNMPERR_USM_UNKNOWNENGINEID + * SNMPERR_USM_PARSEERROR + * SNMPERR_USM_UNKNOWNSECURITYNAME + * SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL + * + * + * ASSUMES size of decrypt_buf will always be >= size of encrypted sPDU. + * + * FIX Memory leaks if secStateRef is allocated and a return occurs + * without cleaning up. May contain secrets... + */ +int +usm_process_in_msg ( + int msgProcModel, /* (UNUSED) */ + size_t maxMsgSize, /* IN - Used to calc maxSizeResponse. */ + + u_char *secParams, /* IN - BER encoded securityParameters.*/ + int secModel, /* (UNUSED) */ + int secLevel, /* IN - AuthNoPriv, authPriv etc. */ + + u_char *wholeMsg, /* IN - Original v3 message. */ + size_t wholeMsgLen, /* IN - Msg length. */ + + u_char *secEngineID, /* OUT - Pointer snmpEngineID. */ + size_t *secEngineIDLen, /* IN/OUT - Len available, len returned. */ + /* NOTE: Memory provided by caller. */ + + char *secName, /* OUT - Pointer to securityName. */ + size_t *secNameLen, /* IN/OUT - Len available, len returned. */ + + u_char **scopedPdu, /* OUT - Pointer to plaintext scopedPdu.*/ + size_t *scopedPduLen, /* IN/OUT - Len available, len returned. */ + + size_t *maxSizeResponse, /* OUT - Max size of Response PDU. */ + void **secStateRf) /* OUT - Ref to security state. */ +{ + size_t remaining = wholeMsgLen + - (u_int) + ((u_long)*secParams-(u_long)*wholeMsg); + u_int boots_uint; + u_int time_uint; + u_char signature[BYTESIZE(USM_MAX_KEYEDHASH_LENGTH)]; + size_t signature_length = BYTESIZE(USM_MAX_KEYEDHASH_LENGTH); + u_char salt[BYTESIZE(USM_MAX_SALT_LENGTH)]; + size_t salt_length = BYTESIZE(USM_MAX_SALT_LENGTH); + u_char iv[BYTESIZE(USM_MAX_SALT_LENGTH)]; + u_int iv_length = BYTESIZE(USM_MAX_SALT_LENGTH); + u_char *data_ptr; + u_char *value_ptr; + u_char type_value; + u_char *end_of_overhead; + int error; + int i; + struct usmStateReference **secStateRef = (struct usmStateReference **)secStateRf; + + struct usmUser *user; + + + DEBUGMSGTL(("usm","USM processing begun...\n")); + + + if (secStateRef) /* FIX -- huh? destroy it? */ + { + *secStateRef = usm_malloc_usmStateReference(); + if (*secStateRef == NULL) + { + DEBUGMSGTL(("usm", "Out of memory.\n")); + return SNMPERR_USM_GENERICERROR; + } + } + + + /* + * Make sure the *secParms is an OCTET STRING. + * Extract the user name, engine ID, and security level. + */ + if ( usm_parse_security_parameters ( + secParams, remaining, + secEngineID, secEngineIDLen, + &boots_uint, &time_uint, + secName, secNameLen, + signature, &signature_length, + salt, &salt_length, + &data_ptr) + == -1 ) + { + DEBUGMSGTL(("usm","Parsing failed.\n")); + if (snmp_increment_statistic (STAT_SNMPINASNPARSEERRS)==0) + { + DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); + } + return SNMPERR_USM_PARSEERROR; + } + + + if (secStateRef) + { + /* Cache the name, engine ID, and security level, + * per step 2 (section 3.2) + */ + if ( usm_set_usmStateReference_name ( + *secStateRef, secName, *secNameLen) == -1 ) + { + DEBUGMSGTL(("usm","%s\n", "Couldn't cache name.")); + return SNMPERR_USM_GENERICERROR; + } + + if ( usm_set_usmStateReference_engine_id ( + *secStateRef, secEngineID, *secEngineIDLen) == -1 ) + { + DEBUGMSGTL(("usm","%s\n", "Couldn't cache engine id.")); + return SNMPERR_USM_GENERICERROR; + } + + if ( usm_set_usmStateReference_sec_level ( + *secStateRef, secLevel) == -1 ) + { + DEBUGMSGTL(("usm","%s\n", "Couldn't cache security level.")); + return SNMPERR_USM_GENERICERROR; + } + } + + + /* + * Locate the engine ID record. + * If it is unknown, then either create one or note this as an error. + */ + if (reportErrorOnUnknownID) + { + if (ISENGINEKNOWN(secEngineID, *secEngineIDLen)==FALSE) + { + DEBUGMSGTL(("usm","Unknown Engine ID.\n")); + if (snmp_increment_statistic ( + STAT_USMSTATSUNKNOWNENGINEIDS)==0) + { + DEBUGMSGTL(("usm","%s\n", + "Failed to increment statistic.")); + } + return SNMPERR_USM_UNKNOWNENGINEID; + } + } + else + { + if ( ENSURE_ENGINE_RECORD(secEngineID,*secEngineIDLen) + != SNMPERR_SUCCESS ) + { + DEBUGMSGTL(("usm","%s\n", "Couldn't ensure engine record.")); + return SNMPERR_USM_GENERICERROR; + } + + } + + + /* + * Locate the User record. + * If the user/engine ID is unknown, report this as an error. + */ + if ( (user = + usm_get_user(secEngineID, *secEngineIDLen, secName)) + == NULL ) + { + DEBUGMSGTL(("usm","Unknown User.\n")); + if (snmp_increment_statistic (STAT_USMSTATSUNKNOWNUSERNAMES)==0) + { + DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); + } + return SNMPERR_USM_UNKNOWNSECURITYNAME; + } + + + /* + * Make sure the security level is appropriate. + */ + if (usm_check_secLevel(secLevel, user) == 1) + { + DEBUGMSGTL(("usm","Unsupported Security Level.\n")); + if (snmp_increment_statistic + (STAT_USMSTATSUNSUPPORTEDSECLEVELS)==0) + { + DEBUGMSGTL(("usm","%s\n", "Failed to increment statistic.")); + } + return SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL; + } + + + /* + * Check the authentication credentials of the message. + */ + if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV + || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + if ( sc_check_keyed_hash ( + user->authProtocol, user->authProtocolLen, + user->authKey, user->authKeyLen, + wholeMsg, wholeMsgLen, + signature, signature_length) + != SNMP_ERR_NOERROR ) + { + DEBUGMSGTL(("usm","Verification failed.\n")); + if (snmp_increment_statistic + (STAT_USMSTATSWRONGDIGESTS)==0) + { + DEBUGMSGTL(("usm","%s\n", + "Failed to increment statistic.")); + } + return SNMPERR_USM_AUTHENTICATIONFAILURE; + } + + DEBUGMSGTL(("usm","Verification succeeded.\n")); + } + + + /* + * Steps 10-11 user is already set - relocated before timeliness + * check in case it fails - still save user data for response. + * + * Cache the keys and protocol oids, per step 11 (s3.2). + */ + if (secStateRef) + { + if (usm_set_usmStateReference_auth_protocol (*secStateRef, + user->authProtocol, user->authProtocolLen) ==-1) + { + DEBUGMSGTL(("usm","%s\n", + "Couldn't cache authentication protocol.")); + return SNMPERR_USM_GENERICERROR; + } + + if (usm_set_usmStateReference_auth_key (*secStateRef, + user->authKey, user->authKeyLen) == -1) + { + DEBUGMSGTL(("usm","%s\n", "Couldn't cache authentiation key.")); + return SNMPERR_USM_GENERICERROR; + } + + if (usm_set_usmStateReference_priv_protocol (*secStateRef, + user->privProtocol, user->privProtocolLen) ==-1) + { + DEBUGMSGTL(("usm","%s\n", "Couldn't cache privacy protocol.")); + return SNMPERR_USM_GENERICERROR; + } + + if (usm_set_usmStateReference_priv_key (*secStateRef, + user->privKey, user->privKeyLen) == -1) + { + DEBUGMSGTL(("usm","%s\n", "Couldn't cache privacy key.")); + return SNMPERR_USM_GENERICERROR; + } + } + + + /* + * Perform the timeliness/time manager functions. + */ + if (secLevel == SNMP_SEC_LEVEL_AUTHNOPRIV + || secLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + if ( usm_check_and_update_timeliness ( + secEngineID, *secEngineIDLen, + boots_uint, time_uint, &error) == -1 ) + { + return error; + } + } + +#ifdef LCD_TIME_SYNC_OPT + /* + * Cache the unauthenticated time to use in case we don't have + * anything better - this guess will be no worse than (0,0) + * that we normally use. + */ + else + { + set_enginetime(secEngineID, *secEngineIDLen, + boots_uint, time_uint, FALSE); + } +#endif /* LCD_TIME_SYNC_OPT */ + + + /* + * If needed, decrypt the scoped PDU. + */ + if (secLevel == SNMP_SEC_LEVEL_AUTHPRIV) + { + remaining = wholeMsgLen - (data_ptr - wholeMsg); + + if ((value_ptr = asn_parse_sequence (data_ptr, &remaining, + &type_value, + (ASN_UNIVERSAL|ASN_PRIMITIVE|ASN_OCTET_STR), + "encrypted sPDU")) == NULL) + { + DEBUGMSGTL(("usm","%s\n", + "Failed while parsing encrypted sPDU.")); + if (snmp_increment_statistic + (STAT_SNMPINASNPARSEERRS)==0) + { + DEBUGMSGTL(("usm","%s\n", + "Failed increment statistic.")); + } + return SNMPERR_USM_PARSEERROR; + } + + end_of_overhead = value_ptr; + + /* + * XOR the salt with the last (iv_length) bytes + * of the priv_key to obtain the IV. + */ + for (i = 0; i < (int)iv_length; i++) + iv[i] = salt[i] ^ user->privKey[iv_length + i]; + + if (sc_decrypt ( + user->privProtocol, user->privProtocolLen, + user->privKey, user->privKeyLen, + iv, iv_length, + value_ptr, remaining, + *scopedPdu, scopedPduLen) + != SNMP_ERR_NOERROR) + { + DEBUGMSGTL(("usm","%s\n", "Failed decryption.")); + if (snmp_increment_statistic + (STAT_USMSTATSDECRYPTIONERRORS)==0) + { + DEBUGMSGTL(("usm","%s\n", + "Failed increment statistic.")); + } + return SNMPERR_USM_DECRYPTIONERROR; + } + +#ifdef SNMP_TESTING_CODE + if ( debug_is_token_registered("usm/dump") == SNMPERR_SUCCESS) { + dump_chunk("usm/dump", "Decrypted chunk:", + *scopedPdu, *scopedPduLen); + dump_chunk("usm/dump", "IV + Encrypted form:", + salt, salt_length); + dump_chunk("usm/dump", NULL, + value_ptr, remaining); + } +#endif + } + + /* + * sPDU is plaintext. + */ + else + { + *scopedPdu = data_ptr; + *scopedPduLen = wholeMsgLen - (data_ptr - wholeMsg); + end_of_overhead = data_ptr; + + } /* endif -- PDU decryption */ + + + /* + * Calculate the biggest sPDU for the response (i.e., whole - ovrhd). + * + * FIX Correct? + */ + *maxSizeResponse = maxMsgSize - (int) + ((u_long)end_of_overhead - (u_long)wholeMsg); + + + DEBUGMSGTL(("usm","USM processing completed.\n")); + + return SNMPERR_SUCCESS; + +} /* end usm_process_in_msg() */ + +void +init_usm(void) { + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, + init_usm_post_config, NULL); +} + +/* + * initializations for the USM. + * + * Should be called after the configuration files have been read. + * + * Set "arbitrary" portion of salt to a random number. + */ +int +init_usm_post_config(int majorid, int minorid, void *serverarg, + void *clientarg) { + size_t salt_integer_len = sizeof(salt_integer); + + initialUser = usm_create_initial_user("initial", usmHMACMD5AuthProtocol, + USM_LENGTH_OID_TRANSFORM, + usmDESPrivProtocol, + USM_LENGTH_OID_TRANSFORM); + SNMP_FREE(initialUser->engineID); + initialUser->engineIDLen = 0; + + if ( sc_random((u_char *) &salt_integer, &salt_integer_len) != SNMPERR_SUCCESS ) + { + DEBUGMSGTL(("usm","sc_random() failed: using time() as salt.\n")); + salt_integer = (u_int) time(NULL); + salt_integer_len = sizeof(salt_integer); + } + + noNameUser = usm_create_initial_user("", usmHMACMD5AuthProtocol, + USM_LENGTH_OID_TRANSFORM, + usmDESPrivProtocol, + USM_LENGTH_OID_TRANSFORM); + SNMP_FREE(noNameUser->engineID); + noNameUser->engineIDLen = 0; + + return SNMPERR_SUCCESS; +} /* end init_usm_post_config() */ + + +/* + * Local storage (LCD) of the default user list. + */ +static struct usmUser *userList=NULL; + +struct usmUser * +usm_get_userList(void) +{ + return userList; +} + + + +/*******************************************************************-o-****** + * usm_check_secLevel + * + * Parameters: + * level + * *user + * + * Returns: + * 0 On success, + * -1 Otherwise. + * + * Checks that a given security level is valid for a given user. + */ +int +usm_check_secLevel(int level, struct usmUser *user) +{ + + if ( level == SNMP_SEC_LEVEL_AUTHPRIV + && (snmp_oid_compare(user->privProtocol, user->privProtocolLen, + usmNoPrivProtocol, sizeof(usmNoPrivProtocol)/sizeof(oid))==0) ) + { + return 1; + } + if ( (level == SNMP_SEC_LEVEL_AUTHPRIV || level == SNMP_SEC_LEVEL_AUTHNOPRIV) + && (snmp_oid_compare(user->authProtocol, user->authProtocolLen, + usmNoAuthProtocol, sizeof(usmNoAuthProtocol)/sizeof(oid))==0) ) + { + return 1; + } + + return 0; + +} /* end usm_check_secLevel() */ + + + + +/*******************************************************************-o-****** + * usm_check_secLevel_vs_protocols + * + * Parameters: + * level + * *authProtocol + * authProtocolLen + * *privProtocol + * privProtocolLen + * + * Returns: + * 0 On success, + * -1 Otherwise. + * + * Same as above but with explicitly named transform types instead of taking + * from the usmUser structure. + */ +int +usm_check_secLevel_vs_protocols(int level, + oid *authProtocol, u_int authProtocolLen, + oid *privProtocol, u_int privProtocolLen) +{ + + if ( level == SNMP_SEC_LEVEL_AUTHPRIV + && (snmp_oid_compare(privProtocol, privProtocolLen, usmNoPrivProtocol, + sizeof(usmNoPrivProtocol)/sizeof(oid))==0) ) + { + return 1; + } + if ( (level == SNMP_SEC_LEVEL_AUTHPRIV || level == SNMP_SEC_LEVEL_AUTHNOPRIV) + && (snmp_oid_compare(authProtocol, authProtocolLen, usmNoAuthProtocol, + sizeof(usmNoAuthProtocol)/sizeof(oid))==0) ) + { + return 1; + } + + return 0; + +} /* end usm_check_secLevel_vs_protocols() */ + + + + +/* usm_get_user(): Returns a user from userList based on the engineID, + engineIDLen and name of the requested user. */ + +struct usmUser * +usm_get_user(u_char *engineID, size_t engineIDLen, char *name) +{ + DEBUGMSGTL(("usm","getting user %s\n", name)); + return usm_get_user_from_list(engineID, engineIDLen, name, userList, 1); +} + +struct usmUser * +usm_get_user_from_list(u_char *engineID, size_t engineIDLen, + char *name, struct usmUser *puserList, int use_default) +{ + struct usmUser *ptr; + char noName[] = ""; + if (name == NULL) + name = noName; + for (ptr = puserList; ptr != NULL; ptr = ptr->next) { + if (!strcmp(ptr->name, name) && + ptr->engineIDLen == engineIDLen && + ((ptr->engineID == NULL && engineID == NULL) || + (ptr->engineID != NULL && engineID != NULL && + memcmp(ptr->engineID, engineID, engineIDLen) == 0))) + return ptr; + } + /* return "" user used to facilitate engineID discovery */ + if (use_default && !strcmp(name, "")) return noNameUser; + /* this next line may be vestigial from when the draft used 'initial' + to discover engineID, also did not remove creation if 'inital' user + -gsm 2/6/99 */ + if (use_default && !strcmp(name, "initial")) return initialUser; + return NULL; +} + +/* usm_add_user(): Add's a user to the userList, sorted by the + engineIDLength then the engineID then the name length then the name + to facilitate getNext calls on a usmUser table which is indexed by + these values. + + Note: userList must not be NULL (obviously), as thats a rather trivial + addition and is left to the API user. + + returns the head of the list (which could change due to this add). +*/ + +struct usmUser * +usm_add_user(struct usmUser *user) +{ + struct usmUser *uptr; + uptr = usm_add_user_to_list(user, userList); + if (uptr != NULL) + userList = uptr; + return uptr; +} + +struct usmUser * +usm_add_user_to_list(struct usmUser *user, + struct usmUser *puserList) +{ + struct usmUser *nptr, *pptr; + + /* loop through puserList till we find the proper, sorted place to + insert the new user */ + for (nptr = puserList, pptr = NULL; nptr != NULL; + pptr = nptr, nptr = nptr->next) { + if (nptr->engineIDLen > user->engineIDLen) + break; + + if (user->engineID == NULL && nptr->engineID != NULL) + break; + + if (nptr->engineIDLen == user->engineIDLen && + (nptr->engineID != NULL && user->engineID != NULL && + memcmp(nptr->engineID, user->engineID, user->engineIDLen) > 0)) + break; + + if (!(nptr->engineID == NULL && user->engineID != NULL)) { + if (nptr->engineIDLen == user->engineIDLen && + ((nptr->engineID == NULL && user->engineID == NULL) || + memcmp(nptr->engineID, user->engineID, user->engineIDLen) == 0) && + strlen(nptr->name) > strlen(user->name)) + break; + + if (nptr->engineIDLen == user->engineIDLen && + ((nptr->engineID == NULL && user->engineID == NULL) || + memcmp(nptr->engineID, user->engineID, user->engineIDLen) == 0) && + strlen(nptr->name) == strlen(user->name) && + strcmp(nptr->name, user->name) > 0) + break; + + if (nptr->engineIDLen == user->engineIDLen && + ((nptr->engineID == NULL && user->engineID == NULL) || + memcmp(nptr->engineID, user->engineID, user->engineIDLen) == 0) && + strlen(nptr->name) == strlen(user->name) && + strcmp(nptr->name, user->name) == 0) + /* the user is an exact match of a previous entry. Bail */ + return NULL; + } + } + + /* nptr should now point to the user that we need to add ourselves + in front of, and pptr should be our new 'prev'. */ + + /* change our pointers */ + user->prev = pptr; + user->next = nptr; + + /* change the next's prev pointer */ + if (user->next) + user->next->prev = user; + + /* change the prev's next pointer */ + if (user->prev) + user->prev->next = user; + + /* rewind to the head of the list and return it (since the new head + could be us, we need to notify the above routine who the head now is. */ + for(pptr = user; pptr->prev != NULL; pptr = pptr->prev); + return pptr; +} + +/* usm_remove_user(): finds and removes a user from a list */ +struct usmUser * +usm_remove_user(struct usmUser *user) +{ + return usm_remove_user_from_list(user, &userList); +} + +struct usmUser * +usm_remove_user_from_list(struct usmUser *user, + struct usmUser **ppuserList) +{ + struct usmUser *nptr, *pptr; + + /* NULL pointers aren't allowed */ + if (ppuserList == NULL) + return NULL; + + /* find the user in the list */ + for (nptr = *ppuserList, pptr = NULL; nptr != NULL; + pptr = nptr, nptr = nptr->next) { + if (nptr == user) + break; + } + + if (nptr) { + /* remove the user from the linked list */ + if (pptr) { + pptr->next = nptr->next; + } + if (nptr->next) { + nptr->next->prev = pptr; + } + } else { + /* user didn't exit */ + return NULL; + } + if (nptr == *ppuserList) /* we're the head of the list, need to change + the head to the next user */ + *ppuserList = nptr->next; + return *ppuserList; +} /* end usm_remove_user_from_list() */ + + + + +/* usm_free_user(): calls free() on all needed parts of struct usmUser and + the user himself. + + Note: This should *not* be called on an object in a list (IE, + remove it from the list first, and set next and prev to NULL), but + will try to reconnect the list pieces again if it is called this + way. If called on the head of the list, the entire list will be + lost. */ +struct usmUser * +usm_free_user(struct usmUser *user) +{ + if (user == NULL) + return NULL; + + SNMP_FREE(user->engineID); + SNMP_FREE(user->name); + SNMP_FREE(user->secName); + SNMP_FREE(user->cloneFrom); + SNMP_FREE(user->userPublicString); + SNMP_FREE(user->authProtocol); + SNMP_FREE(user->privProtocol); + + if (user->authKey != NULL) { + SNMP_ZERO(user->authKey, user->authKeyLen); + SNMP_FREE(user->authKey); + } + + if (user->privKey != NULL) { + SNMP_ZERO(user->privKey, user->privKeyLen); + SNMP_FREE(user->privKey); + } + + + /* FIX Why not put this check *first?* + */ + if (user->prev != NULL) { /* ack, this shouldn't happen */ + user->prev->next = user->next; + } + if (user->next != NULL) { + user->next->prev = user->prev; + if (user->prev != NULL) /* ack this is really bad, because it means + we'll loose the head of some structure tree */ + DEBUGMSGTL(("usm","Severe: Asked to free the head of a usmUser tree somewhere.")); + } + + + SNMP_ZERO(user, sizeof(*user)); + SNMP_FREE(user); + + return NULL; /* for convenience to returns from calling functions */ + +} /* end usm_free_user() */ + + + + +/* take a given user and clone the security info into another */ +struct usmUser * +usm_cloneFrom_user(struct usmUser *from, struct usmUser *to) +{ + /* copy the authProtocol oid row pointer */ + SNMP_FREE(to->authProtocol); + + if ((to->authProtocol = + snmp_duplicate_objid(from->authProtocol,from->authProtocolLen)) != NULL) + to->authProtocolLen = from->authProtocolLen; + else + to->authProtocolLen = 0; + + + /* copy the authKey */ + SNMP_FREE(to->authKey); + + if (from->authKeyLen > 0 && + (to->authKey = (u_char *) malloc(from->authKeyLen)) + != NULL) { + to->authKeyLen = from->authKeyLen; + memcpy(to->authKey, from->authKey, to->authKeyLen); + } else { + to->authKey = NULL; + to->authKeyLen = 0; + } + + + /* copy the privProtocol oid row pointer */ + SNMP_FREE(to->privProtocol); + + if ((to->privProtocol = + snmp_duplicate_objid(from->privProtocol,from->privProtocolLen)) != NULL) + to->privProtocolLen = from->privProtocolLen; + else + to->privProtocolLen = 0; + + /* copy the privKey */ + SNMP_FREE(to->privKey); + + if (from->privKeyLen > 0 && + (to->privKey = (u_char *) malloc(from->privKeyLen)) + != NULL) { + to->privKeyLen = from->privKeyLen; + memcpy(to->privKey, from->privKey, to->privKeyLen); + } else { + to->privKey = NULL; + to->privKeyLen = 0; + } + return to; +} + +/* usm_create_user(void): + create a default empty user, instantiating only the auth/priv + protocols to noAuth and noPriv OID pointers +*/ +struct usmUser * +usm_create_user(void) +{ + struct usmUser *newUser; + + /* create the new user */ + newUser = (struct usmUser *) calloc(1,sizeof(struct usmUser)); + if (newUser == NULL) + return NULL; + + /* fill the auth/priv protocols */ + if ((newUser->authProtocol = + snmp_duplicate_objid(usmNoAuthProtocol, + sizeof(usmNoAuthProtocol)/sizeof(oid))) == NULL) + return usm_free_user(newUser); + newUser->authProtocolLen = sizeof(usmNoAuthProtocol)/sizeof(oid); + + if ((newUser->privProtocol = + snmp_duplicate_objid(usmNoPrivProtocol, + sizeof(usmNoPrivProtocol)/sizeof(oid))) == NULL) + return usm_free_user(newUser); + newUser->privProtocolLen = sizeof(usmNoPrivProtocol)/sizeof(oid); + + /* set the storage type to nonvolatile, and the status to ACTIVE */ + newUser->userStorageType = ST_NONVOLATILE; + newUser->userStatus = RS_ACTIVE; + return newUser; + +} /* end usm_clone_user() */ + + + + +/* usm_create_initial_user(void): + creates an initial user, filled with the defaults defined in the + USM document. +*/ +struct usmUser * +usm_create_initial_user(const char *name, oid *authProtocol, size_t authProtocolLen, + oid *privProtocol, size_t privProtocolLen) +{ + struct usmUser *newUser = usm_create_user(); + if (newUser == NULL) + return NULL; + + if ((newUser->name = strdup(name)) == NULL) + return usm_free_user(newUser); + + if ((newUser->secName = strdup(name)) == NULL) + return usm_free_user(newUser); + + if ((newUser->engineID = snmpv3_generate_engineID(&newUser->engineIDLen)) == NULL) + return usm_free_user(newUser); + + if ((newUser->cloneFrom = (oid *) malloc(sizeof(oid)*2)) == NULL) + return usm_free_user(newUser); + newUser->cloneFrom[0] = 0; + newUser->cloneFrom[1] = 0; + newUser->cloneFromLen = 2; + + SNMP_FREE(newUser->privProtocol); + if ((newUser->privProtocol = (oid *) malloc(privProtocolLen*sizeof(oid))) + == NULL) + return usm_free_user(newUser); + newUser->privProtocolLen = privProtocolLen; + memcpy(newUser->privProtocol, privProtocol, privProtocolLen*sizeof(oid)); + + SNMP_FREE(newUser->authProtocol); + if ((newUser->authProtocol = (oid *) malloc(authProtocolLen*sizeof(oid))) + == NULL) + return usm_free_user(newUser); + newUser->authProtocolLen = authProtocolLen; + memcpy(newUser->authProtocol, authProtocol, authProtocolLen*sizeof(oid)); + + newUser->userStatus = RS_ACTIVE; + newUser->userStorageType = ST_READONLY; + + return newUser; +} + +/* this is a callback that can store all known users based on a + previously registered application ID */ +int +usm_store_users(int majorID, int minorID, void *serverarg, void *clientarg) +{ + /* figure out our application name */ + char *appname = (char *) clientarg; + if (appname == NULL) + appname = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE); + + /* save the user base */ + usm_save_users("usmUser", appname); + + /* never fails */ + return SNMPERR_SUCCESS; +} + + +/* usm_save_users(): saves a list of users to the persistent cache */ +void +usm_save_users(const char *token, const char *type) +{ + usm_save_users_from_list(userList, token, type); +} + +void +usm_save_users_from_list(struct usmUser *puserList, const char *token, + const char *type) +{ + struct usmUser *uptr; + for (uptr = puserList; uptr != NULL; uptr = uptr->next) { + if (uptr->userStorageType == ST_NONVOLATILE) + usm_save_user(uptr, token, type); + } +} + +/* usm_save_user(): saves a user to the persistent cache */ +void +usm_save_user(struct usmUser *user, const char *token, const char *type) +{ + char line[4096]; + char *cptr; + + memset(line, 0, sizeof(line)); + + sprintf(line, "%s %d %d ", token, user->userStatus, user->userStorageType); + cptr = &line[strlen(line)]; /* the NULL */ + cptr = read_config_save_octet_string(cptr, user->engineID, user->engineIDLen); + *cptr++ = ' '; + cptr = read_config_save_octet_string(cptr, (u_char *)user->name, + (user->name == NULL) ? 0 : + strlen(user->name)+1); + *cptr++ = ' '; + cptr = read_config_save_octet_string(cptr, (u_char *)user->secName, + (user->secName == NULL) ? 0 : + strlen(user->secName)+1); + *cptr++ = ' '; + cptr = read_config_save_objid(cptr, user->cloneFrom, user->cloneFromLen); + *cptr++ = ' '; + cptr = read_config_save_objid(cptr, user->authProtocol, + user->authProtocolLen); + *cptr++ = ' '; + cptr = read_config_save_octet_string(cptr, user->authKey, user->authKeyLen); + *cptr++ = ' '; + cptr = read_config_save_objid(cptr, user->privProtocol, + user->privProtocolLen); + *cptr++ = ' '; + cptr = read_config_save_octet_string(cptr, user->privKey, user->privKeyLen); + *cptr++ = ' '; + cptr = read_config_save_octet_string(cptr, user->userPublicString, + (user->userPublicString == NULL) ? 0 : + strlen((char *)user->userPublicString)+1); + read_config_store(type, line); +} + +/* usm_parse_user(): reads in a line containing a saved user profile + and returns a pointer to a newly created struct usmUser. */ +struct usmUser * +usm_read_user(char *line) +{ + struct usmUser *user; + size_t len; + + user = usm_create_user(); + if (user == NULL) + return NULL; + + user->userStatus = atoi(line); + line = skip_token(line); + user->userStorageType = atoi(line); + line = skip_token(line); + line = read_config_read_octet_string(line, &user->engineID, + &user->engineIDLen); + + /* set the lcd entry for this engineID to the minimum boots/time + values so that its a known engineid and won't return a report pdu. + This is mostly important when receiving v3 traps so that the usm + will at least continue processing them. */ + set_enginetime(user->engineID, user->engineIDLen, 1, 0, 0); + + line = read_config_read_octet_string(line, (u_char **)&user->name, + &len); + line = read_config_read_octet_string(line, (u_char **)&user->secName, + &len); + SNMP_FREE(user->cloneFrom); + user->cloneFromLen = 0; + + line = read_config_read_objid(line, &user->cloneFrom, &user->cloneFromLen); + + SNMP_FREE(user->authProtocol); + user->authProtocolLen = 0; + + line = read_config_read_objid(line, &user->authProtocol, + &user->authProtocolLen); + line = read_config_read_octet_string(line, &user->authKey, + &user->authKeyLen); + SNMP_FREE(user->privProtocol); + user->privProtocolLen = 0; + + line = read_config_read_objid(line, &user->privProtocol, + &user->privProtocolLen); + line = read_config_read_octet_string(line, &user->privKey, + &user->privKeyLen); + line = read_config_read_octet_string(line, &user->userPublicString, + &len); + return user; +} + +/* snmpd.conf parsing routines */ +void +usm_parse_config_usmUser(const char *token, char *line) +{ + struct usmUser *uptr; + + uptr = usm_read_user(line); + usm_add_user(uptr); +} + + + + +/*******************************************************************-o-****** + * usm_set_password + * + * Parameters: + * *token + * *line + * + * + * format: userSetAuthPass secname engineIDLen engineID pass + * or: userSetPrivPass secname engineIDLen engineID pass + * or: userSetAuthKey secname engineIDLen engineID KuLen Ku + * or: userSetPrivKey secname engineIDLen engineID KuLen Ku + * or: userSetAuthLocalKey secname engineIDLen engineID KulLen Kul + * or: userSetPrivLocalKey secname engineIDLen engineID KulLen Kul + * + * type is: 1=passphrase; 2=Ku; 3=Kul. + * + * + * ASSUMES Passwords are null-terminated printable strings. + */ +void +usm_set_password(const char *token, char *line) +{ + char *cp; + char nameBuf[SNMP_MAXBUF]; + u_char *engineID; + size_t engineIDLen; + struct usmUser *user; + + cp = copy_word(line, nameBuf); + if (cp == NULL) { + config_perror("invalid name specifier"); + return; + } + + DEBUGMSGTL(("usm", "comparing: %s and %s\n", cp, WILDCARDSTRING)); + if (strncmp(cp, WILDCARDSTRING, strlen(WILDCARDSTRING)) == 0) { + /* match against all engineIDs we know about */ + cp = skip_token(cp); + for(user = userList; user != NULL; user = user->next) { + if (strcmp(user->secName, nameBuf) == 0) { + usm_set_user_password(user, token, cp); + } + } + } else { + cp = read_config_read_octet_string(cp, &engineID, &engineIDLen); + if (cp == NULL) { + config_perror("invalid engineID specifier"); + return; + } + + user = usm_get_user(engineID, engineIDLen, nameBuf); + if (user == NULL) { + config_perror("not a valid user/engineID pair"); + return; + } + usm_set_user_password(user, token, cp); + } +} + +/* uses the rest of LINE to configure USER's password of type TOKEN */ +void +usm_set_user_password(struct usmUser *user, const char *token, char *line) +{ + char *cp = line; + u_char *engineID = user->engineID; + size_t engineIDLen = user->engineIDLen; + + u_char **key; + size_t *keyLen; + u_char userKey[SNMP_MAXBUF_SMALL]; + size_t userKeyLen = SNMP_MAXBUF_SMALL; + int type, ret; + + /* + * Retrieve the "old" key and set the key type. + */ + if (strcmp(token, "userSetAuthPass") == 0) { + key = &user->authKey; + keyLen = &user->authKeyLen; + type = 0; + } else if (strcmp(token, "userSetPrivPass") == 0) { + key = &user->privKey; + keyLen = &user->privKeyLen; + type = 0; + } else if (strcmp(token, "userSetAuthKey") == 0) { + key = &user->authKey; + keyLen = &user->authKeyLen; + type = 1; + } else if (strcmp(token, "userSetPrivKey") == 0) { + key = &user->privKey; + keyLen = &user->privKeyLen; + type = 1; + } else if (strcmp(token, "userSetAuthLocalKey") == 0) { + key = &user->authKey; + keyLen = &user->authKeyLen; + type = 2; + } else if (strcmp(token, "userSetPrivLocalKey") == 0) { + key = &user->privKey; + keyLen = &user->privKeyLen; + type = 2; + } else { + /* no old key, or token was not recognized */ + return; + } + + if (*key) { + /* (destroy and) free the old key */ + memset(*key, 0, *keyLen); + free(*key); + } + + if (type == 0) { + /* convert the password into a key + */ + ret = generate_Ku( user->authProtocol, user->authProtocolLen, + (u_char *)cp, strlen(cp), + userKey, &userKeyLen ); + + if (ret != SNMPERR_SUCCESS) { + config_perror("setting key failed (in sc_genKu())"); + return; + } + } else if (type == 1) { + cp = read_config_read_octet_string(cp, (u_char **) &userKey, &userKeyLen); + + if (cp == NULL) { + config_perror("invalid user key"); + return; + } + } + + if (type < 2) { + *key = (u_char *)malloc(SNMP_MAXBUF_SMALL); + *keyLen = SNMP_MAXBUF_SMALL; + ret = generate_kul( user->authProtocol, user->authProtocolLen, + engineID, engineIDLen, + userKey, userKeyLen, + *key, keyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("setting key failed (in generate_kul())"); + return; + } + + /* (destroy and) free the old key */ + memset(userKey, 0, sizeof(userKey)); + + } else { + /* the key is given, copy it in */ + cp = read_config_read_octet_string(cp, key, keyLen); + + if (cp == NULL) { + config_perror("invalid localized user key"); + return; + } + } +} /* end usm_set_password() */ diff --git a/packages/net/snmp/lib/current/src/snmpv3.c b/packages/net/snmp/lib/current/src/snmpv3.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/snmpv3.c @@ -0,0 +1,838 @@ +//========================================================================== +// +// ./lib/current/src/snmpv3.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * snmpv3.c + */ + +#include + +#include +#include +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_STDLIB_H +# include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "system.h" +#include "asn1.h" +#include "snmpv3.h" +#include "callback.h" +#include "snmpusm.h" +#include "snmp.h" +#include "snmp_api.h" +#include "snmp_impl.h" +#include "read_config.h" +#include "lcd_time.h" +#include "scapi.h" +#include "tools.h" +#include "keytools.h" +#include "lcd_time.h" +#include "snmp_debug.h" +#include "snmp_logging.h" +#include "default_store.h" + +#include "transform_oids.h" + +static u_long engineBoots = 1; +static unsigned char *engineID = NULL; +static size_t engineIDLength = 0; +static unsigned char *oldEngineID = NULL; +static size_t oldEngineIDLength = 0; +static struct timeval snmpv3starttime; + +/* + * Set up default snmpv3 parameter value storage. + */ +static oid *defaultAuthType = NULL; +static size_t defaultAuthTypeLen = 0; +static oid *defaultPrivType = NULL; +static size_t defaultPrivTypeLen = 0; + +void +snmpv3_authtype_conf(const char *word, char *cptr) +{ + if (strcasecmp(cptr,"MD5") == 0) + defaultAuthType = usmHMACMD5AuthProtocol; + else if (strcasecmp(cptr,"SHA") == 0) + defaultAuthType = usmHMACMD5AuthProtocol; + else + config_perror("Unknown authentication type"); + defaultAuthTypeLen = USM_LENGTH_OID_TRANSFORM; + DEBUGMSGTL(("snmpv3","set default authentication type: %s\n", cptr)); +} + +oid * +get_default_authtype(size_t *len) +{ + if (defaultAuthType == NULL) { + defaultAuthType = SNMP_DEFAULT_AUTH_PROTO; + defaultAuthTypeLen = SNMP_DEFAULT_AUTH_PROTOLEN; + } + if (len) + *len = defaultAuthTypeLen; + return defaultAuthType; +} + +void +snmpv3_privtype_conf(const char *word, char *cptr) +{ + if (strcasecmp(cptr,"DES") == 0) + defaultPrivType = SNMP_DEFAULT_PRIV_PROTO; + else + config_perror("Unknown privacy type"); + defaultPrivTypeLen = SNMP_DEFAULT_PRIV_PROTOLEN; + DEBUGMSGTL(("snmpv3","set default privacy type: %s\n", cptr)); +} + +oid * +get_default_privtype(size_t *len) +{ + if (defaultAuthType == NULL) { + defaultAuthType = usmDESPrivProtocol; + defaultPrivTypeLen = USM_LENGTH_OID_TRANSFORM; + } + if (len) + *len = defaultPrivTypeLen; + return defaultPrivType; +} + +/*******************************************************************-o-****** + * snmpv3_secLevel_conf + * + * Parameters: + * *word + * *cptr + * + * Line syntax: + * defSecurityLevel "noAuthNoPriv" | "authNoPriv" | "authPriv" + */ +void +snmpv3_secLevel_conf(const char *word, char *cptr) +{ + char buf[1024]; + + if (strcasecmp(cptr,"noAuthNoPriv") == 0 || strcmp(cptr, "1") == 0 + || strcasecmp(cptr, "nanp") == 0) + ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_NOAUTH); + else if (strcasecmp(cptr,"authNoPriv") == 0 || strcmp(cptr, "2") == 0 + || strcasecmp(cptr, "anp") == 0) + ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHNOPRIV); + else if (strcasecmp(cptr,"authPriv") == 0 || strcmp(cptr, "3") == 0 + || strcasecmp(cptr, "ap") == 0) + ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHPRIV); + else { + sprintf(buf,"Unknown security level: %s", cptr); + config_perror(buf); + } + DEBUGMSGTL(("snmpv3","default secLevel set to: %s = %d\n", cptr, + ds_get_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL))); +} + +/*******************************************************************-o-****** + * setup_engineID + * + * Parameters: + * **eidp + * *text Printable (?) text to be plugged into the snmpEngineID. + * + * Return: + * Length of allocated engineID string in bytes, -OR- + * -1 on error. + * + * + * Create an snmpEngineID using text and the local IP address. If eidp + * is defined, use it to return a pointer to the newly allocated data. + * Otherwise, use the result to define engineID defined in this module. + * + * Line syntax: + * engineID | NULL + * + * XXX What if a node has multiple interfaces? + * XXX What if multiple engines all choose the same address? + * (answer: You're screwed, because you might need a kul database + * which is dependant on the current engineID. Enumeration and other + * tricks won't work). + */ +int +setup_engineID(u_char **eidp, const char *text) +{ + int enterpriseid = htonl(ENTERPRISE_NUMBER), + localsetup = (eidp) ? 0 : 1; + /* Use local engineID if *eidp == NULL. */ +#ifdef HAVE_GETHOSTNAME + u_char buf[SNMP_MAXBUF_SMALL]; + struct hostent *hent; +#endif + u_char *bufp = NULL; + size_t len; + + + /* + * Determine length of the engineID string. + */ + if (text) { + len = 5+strlen(text); /* 5 leading bytes+text. */ + + } else { + len = 5 + 4; /* 5 leading bytes + four byte IPv4 address */ +#ifdef HAVE_GETHOSTNAME + gethostname((char *)buf, sizeof(buf)); + hent = gethostbyname((char *)buf); +#ifdef AF_INET6 + if (hent && hent->h_addrtype == AF_INET6) + len += 12; /* 16 bytes total for IPv6 address. */ +#endif +#endif /* HAVE_GETHOSTNAME */ + } /* endif -- text (1) */ + + + /* + * Allocate memory and store enterprise ID. + */ + if ((bufp = (u_char *) malloc(len)) == NULL) { + snmp_log_perror("setup_engineID malloc"); + return -1; + } + + memcpy(bufp, &enterpriseid, sizeof(enterpriseid)); /* XXX Must be 4 bytes! */ + bufp[0] |= 0x80; + + + /* + * Store the given text -OR- the first found IP address. + */ + if (text) { + bufp[4] = 4; + memcpy((char *)bufp+5, text, strlen(text)); + + } else { + bufp[4] = 1; +#ifdef HAVE_GETHOSTNAME + gethostname((char *)buf, sizeof(buf)); + hent = gethostbyname((char *)buf); + + if (hent && hent->h_addrtype == AF_INET) { + memcpy(bufp+5, hent->h_addr_list[0], hent->h_length); + +#ifdef AF_INET6 + } else if (hent && hent->h_addrtype == AF_INET6) { + bufp[4] = 2; + memcpy(bufp+5, hent->h_addr_list[0], hent->h_length); +#endif + + } else { /* Unknown address type. Default to 127.0.0.1. */ + + bufp[5] = 127; + bufp[6] = 0; + bufp[7] = 0; + bufp[8] = 1; + } +#else /* HAVE_GETHOSTNAME */ + /* Unknown address type. Default to 127.0.0.1. */ + + bufp[5] = 127; + bufp[6] = 0; + bufp[7] = 0; + bufp[8] = 1; +#endif /* HAVE_GETHOSTNAME */ + + } /* endif -- text (2) */ + + + /* + * Pass the string back to the calling environment, or use it for + * our local engineID. + */ + if (localsetup) { + SNMP_FREE(engineID); + engineID = bufp; + engineIDLength = len; + + } else { + *eidp = bufp; + } + + + return len; + +} /* end setup_engineID() */ + +void +usm_parse_create_usmUser(const char *token, char *line) { + char *cp; + char buf[SNMP_MAXBUF_MEDIUM]; + struct usmUser *newuser; + u_char userKey[SNMP_MAXBUF_SMALL]; + size_t userKeyLen = SNMP_MAXBUF_SMALL; + int ret; + + newuser = usm_create_user(); + + /* READ: Security Name */ + cp = copy_word(line, buf); + newuser->secName = strdup(buf); + newuser->name = strdup(buf); + + newuser->engineID = snmpv3_generate_engineID(&ret); + if ( ret < 0 ) { + usm_free_user(newuser); + return; + } + newuser->engineIDLen = ret; + + if (!cp) + goto add; /* no authentication or privacy type */ + + /* READ: Authentication Type */ + if (strncmp(cp, "MD5", 3) == 0) { + memcpy(newuser->authProtocol, usmHMACMD5AuthProtocol, + sizeof(usmHMACMD5AuthProtocol)); + } else if (strncmp(cp, "SHA", 3) == 0) { + memcpy(newuser->authProtocol, usmHMACSHA1AuthProtocol, + sizeof(usmHMACSHA1AuthProtocol)); + } else { + config_perror("Unknown authentication protocol"); + usm_free_user(newuser); + return; + } + + cp = skip_token(cp); + + /* READ: Authentication Pass Phrase */ + if (!cp) { + config_perror("no authentication pass phrase"); + usm_free_user(newuser); + return; + } + cp = copy_word(cp, buf); + /* And turn it into a localized key */ + ret = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, + (u_char *)buf, strlen(buf), + userKey, &userKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating auth key from pass phrase."); + usm_free_user(newuser); + return; + } + newuser->authKeyLen = + sc_get_properlength(newuser->authProtocol, newuser->authProtocolLen); + newuser->authKey = (u_char *) malloc(newuser->authKeyLen); + ret = generate_kul(newuser->authProtocol, newuser->authProtocolLen, + newuser->engineID, newuser->engineIDLen, + userKey, userKeyLen, + newuser->authKey, &newuser->authKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating localized auth key (Kul) from Ku."); + usm_free_user(newuser); + return; + } + + if (!cp) + goto add; /* no privacy type (which is legal) */ + + /* READ: Privacy Type */ + if (strncmp(cp, "DES", 3) == 0) { + memcpy(newuser->privProtocol, usmDESPrivProtocol, + sizeof(usmDESPrivProtocol)); + } else { + config_perror("Unknown privacy protocol"); + usm_free_user(newuser); + return; + } + + cp = skip_token(cp); + /* READ: Authentication Pass Phrase */ + if (!cp) { + /* assume the same as the authentication key */ + memdup(&newuser->privKey, newuser->authKey, newuser->authKeyLen); + } else { + cp = copy_word(cp, buf); + /* And turn it into a localized key */ + ret = generate_Ku(newuser->authProtocol, newuser->authProtocolLen, + (u_char *)buf, strlen(buf), + userKey, &userKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating priv key from pass phrase."); + usm_free_user(newuser); + return; + } + + ret = sc_get_properlength(newuser->authProtocol, newuser->authProtocolLen); + if (ret < 0) { + config_perror("Error getting proper key length for priv algorithm."); + usm_free_user(newuser); + return; + } + newuser->privKeyLen = ret; + + newuser->privKey = (u_char *) malloc(newuser->privKeyLen); + ret = generate_kul(newuser->authProtocol, newuser->authProtocolLen, + newuser->engineID, newuser->engineIDLen, + userKey, userKeyLen, + newuser->privKey, &newuser->privKeyLen ); + if (ret != SNMPERR_SUCCESS) { + config_perror("Error generating localized priv key (Kul) from Ku."); + usm_free_user(newuser); + return; + } + } +add: + usm_add_user(newuser); + DEBUGMSGTL(("usmUser","created a new user %s\n", newuser->secName)); +} + +/*******************************************************************-o-****** + * engineBoots_conf + * + * Parameters: + * *word + * *cptr + * + * Line syntax: + * engineBoots + */ +void +engineBoots_conf(const char *word, char *cptr) +{ + engineBoots = atoi(cptr)+1; + DEBUGMSGTL(("snmpv3","engineBoots: %d\n",engineBoots)); +} + + + +/*******************************************************************-o-****** + * engineID_conf + * + * Parameters: + * *word + * *cptr + * + * This function reads a string from the configuration file and uses that + * string to initialize the engineID. It's assumed to be human readable. + */ +void +engineID_conf(const char *word, char *cptr) +{ + setup_engineID(NULL, cptr); + DEBUGMSGTL(("snmpv3","initialized engineID with: %s\n",cptr)); +} + +void +version_conf(const char *word, char *cptr) +{ + if (strcmp(cptr,"1") == 0) { + ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_1); + } else if (strcasecmp(cptr,"2c") == 0) { + ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_2c); + } else if (strcmp(cptr,"3") == 0) { + ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_3); + } else { + config_perror("Unknown version specification"); + return; + } + DEBUGMSGTL(("snmpv3","set default version to %d\n", + ds_get_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION))); +} + +/* engineID_old_conf(const char *, char *): + + Reads a octet string encoded engineID into the oldEngineID and + oldEngineIDLen pointers. +*/ +void +oldengineID_conf(const char *word, char *cptr) +{ + read_config_read_octet_string(cptr, &oldEngineID, &oldEngineIDLength); +} + + +/*******************************************************************-o-****** + * init_snmpv3 + * + * Parameters: + * *type Label for the config file "type" used by calling entity. + * + * Set time and engineID. + * Set parsing functions for config file tokens. + * Initialize SNMP Crypto API (SCAPI). + */ +void +init_snmpv3(const char *type) { + gettimeofday(&snmpv3starttime, NULL); + + if (type == NULL) + type = "snmpapp"; + + if (type && !strcmp(type,"snmpapp")) { + setup_engineID(NULL,"__snmpapp__"); + } else { + setup_engineID(NULL, NULL); + } + + /* initialize submodules */ + init_usm(); + + /* we need to be called back later */ + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, + init_snmpv3_post_config, NULL); + /* we need to be called back later */ + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, + snmpv3_store, (void *) type); + + +#if !defined(USE_INTERNAL_MD5) + /* doesn't belong here at all */ + sc_init(); +#endif /* !USE_INTERNAL_MD5 */ + + /* register all our configuration handlers (ack, there's a lot) */ + + /* handle engineID setup before everything else which may depend on it */ + register_premib_handler(type,"engineID", engineID_conf, NULL, "string"); + register_premib_handler(type,"oldEngineID", oldengineID_conf, NULL, NULL); + register_config_handler(type,"engineBoots", engineBoots_conf, NULL, NULL); + + /* default store config entries */ + ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityName", DS_LIBRARY_ID, + DS_LIB_SECNAME); + ds_register_config(ASN_OCTET_STR, "snmp", "defContext", DS_LIBRARY_ID, + DS_LIB_CONTEXT); + ds_register_config(ASN_OCTET_STR, "snmp", "defPassphrase", DS_LIBRARY_ID, + DS_LIB_PASSPHRASE); + ds_register_config(ASN_OCTET_STR, "snmp", "defAuthPassphrase", DS_LIBRARY_ID, + DS_LIB_AUTHPASSPHRASE); + ds_register_config(ASN_OCTET_STR, "snmp", "defPrivPassphrase", DS_LIBRARY_ID, + DS_LIB_PRIVPASSPHRASE); + register_config_handler("snmp","defVersion", version_conf, NULL, "1|2c|3"); + + register_config_handler("snmp","defAuthType", snmpv3_authtype_conf, NULL, + "MD5|SHA"); + register_config_handler("snmp","defPrivType", snmpv3_privtype_conf, NULL, + "DES (currently the only possible value)"); + register_config_handler("snmp","defSecurityLevel", snmpv3_secLevel_conf, + NULL, "noAuthNoPriv|authNoPriv|authPriv"); + register_config_handler(type,"userSetAuthPass", usm_set_password, NULL, + "secname engineIDLen engineID pass"); + register_config_handler(type,"userSetPrivPass", usm_set_password, NULL, + "secname engineIDLen engineID pass"); + register_config_handler(type,"userSetAuthKey", usm_set_password, NULL, + "secname engineIDLen engineID KuLen Ku"); + register_config_handler(type,"userSetPrivKey", usm_set_password, NULL, + "secname engineIDLen engineID KuLen Ku"); + register_config_handler(type,"userSetAuthLocalKey", usm_set_password, NULL, + "secname engineIDLen engineID KulLen Kul"); + register_config_handler(type,"userSetPrivLocalKey", usm_set_password, NULL, + "secname engineIDLen engineID KulLen Kul"); +} + +/* + * initializations for SNMPv3 to be called after the configuration files + * have been read. + */ + +int +init_snmpv3_post_config(int majorid, int minorid, void *serverarg, + void *clientarg) { + + int engineIDLen; + u_char *c_engineID; + + c_engineID = snmpv3_generate_engineID(&engineIDLen); + + if ( engineIDLen < 0 ) { + /* Somethine went wrong - help! */ + return SNMPERR_GENERR; + } + + /* if our engineID has changed at all, the boots record must be set to 1 */ + if (engineIDLen != (int)oldEngineIDLength || + oldEngineID == NULL || c_engineID == NULL || + memcmp(oldEngineID, c_engineID, engineIDLen) != 0) { + engineBoots = 1; + } + + /* set our local engineTime in the LCD timing cache */ + set_enginetime(c_engineID, engineIDLen, + snmpv3_local_snmpEngineBoots(), + snmpv3_local_snmpEngineTime(), + TRUE); + + free(c_engineID); + return SNMPERR_SUCCESS; +} + +/*******************************************************************-o-****** + * store_snmpv3 + * + * Parameters: + * *type + */ +int +snmpv3_store(int majorID, int minorID, void *serverarg, void *clientarg) { + char line[SNMP_MAXBUF_SMALL]; + u_char c_engineID[SNMP_MAXBUF_SMALL]; + int engineIDLen; + const char *type = (const char *) clientarg; + + if (type == NULL) /* should never happen, since the arg is ours */ + type = "unknown"; + + sprintf(line, "engineBoots %ld", engineBoots); + read_config_store(type, line); + + engineIDLen = snmpv3_get_engineID(c_engineID, SNMP_MAXBUF_SMALL); + + if (engineIDLen) { + /* store the engineID used for this run */ + sprintf(line, "oldEngineID "); + read_config_save_octet_string(line+strlen(line), c_engineID, + engineIDLen); + read_config_store(type, line); + } + return SNMPERR_SUCCESS; +} /* snmpv3_store() */ + +u_long +snmpv3_local_snmpEngineBoots(void) +{ + return engineBoots; +} + + +/*******************************************************************-o-****** + * snmpv3_get_engineID + * + * Parameters: + * *buf + * buflen + * + * Returns: + * Length of engineID On Success + * SNMPERR_GENERR Otherwise. + * + * + * Store engineID in buf; return the length. + * + */ +int +snmpv3_get_engineID(u_char *buf, size_t buflen) +{ + /* + * Sanity check. + */ + if ( !buf || (buflen < engineIDLength) ) { + return SNMPERR_GENERR; + } + + memcpy(buf,engineID,engineIDLength); + return engineIDLength; + +} /* end snmpv3_get_engineID() */ + +/*******************************************************************-o-****** + * snmpv3_clone_engineID + * + * Parameters: + * **dest + * *dest_len + * src + * srclen + * + * Returns: + * Length of engineID On Success + * 0 Otherwise. + * + * + * Clones engineID, creates memory + * + */ +int +snmpv3_clone_engineID(u_char **dest, size_t* destlen, u_char*src, size_t srclen) +{ + if ( !dest || !destlen ) return 0; + + *dest = NULL; *destlen = 0; + + if (srclen && src) { + *dest = (u_char*)malloc((unsigned)srclen * sizeof(u_char)); + if (*dest == NULL) return 0; + memmove(*dest, src, srclen * sizeof(u_char)); + *destlen = srclen; + } + return *destlen; +} /* end snmpv3_clone_engineID() */ + + +/*******************************************************************-o-****** + * snmpv3_generate_engineID + * + * Parameters: + * *length + * + * Returns: + * Pointer to copy of engineID On Success. + * NULL If malloc() or snmpv3_get_engineID() + * fail. + * + * Generates a malloced copy of our engineID. + * + * 'length' is set to the length of engineID -OR- < 0 on failure. + */ +u_char * +snmpv3_generate_engineID(int *length) +{ + u_char *newID; + newID = (u_char *) malloc(engineIDLength); + + if (newID) { + *length = snmpv3_get_engineID(newID, engineIDLength); + } + + if (*length < 0) { + SNMP_FREE(newID); + newID = NULL; + } + + return newID; + +} /* end snmpv3_generate_engineID() */ + +/* snmpv3_local_snmpEngineTime(): return the number of seconds since the + snmpv3 engine last incremented engine_boots */ +u_long +snmpv3_local_snmpEngineTime(void) +{ + struct timeval now; + + gettimeofday(&now, NULL); + return calculate_time_diff(&now, &snmpv3starttime)/100; +} + +#ifdef SNMP_TESTING_CODE +/* snmpv3_set_engineBootsAndTime(): this function does not exist. Go away. */ +/* It certainly should never be used, unless in a testing scenero, + which is why it was created */ +void +snmpv3_set_engineBootsAndTime(int boots, int ttime) { + engineBoots = boots; + gettimeofday(&snmpv3starttime, NULL); + snmpv3starttime.tv_sec -= ttime; +} +#endif diff --git a/packages/net/snmp/lib/current/src/system.c b/packages/net/snmp/lib/current/src/system.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/system.c @@ -0,0 +1,818 @@ +//========================================================================== +// +// ./lib/current/src/system.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * system.c + */ +/*********************************************************** + Copyright 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * System dependent routines go here + */ +#include +#include +#include + +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif + +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include + +#if HAVE_NETINET_IN_H +#include +#endif + +#if HAVE_WINSOCK_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_NET_IF_H +#include +#endif + +#if HAVE_SYS_SOCKIO_H +#include +#endif + +#if HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_NLIST_H +#include +#endif + +#if HAVE_SYS_FILE_H +#include +#endif + +#if HAVE_KSTAT_H +#include +#endif + +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_SYSCTL_H +#include +#endif + +#if HAVE_STRING_H +#include +#else +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#include "asn1.h" +#include "snmp_api.h" +#include "tools.h" +#include "system.h" +#include "snmp_logging.h" + +#define NUM_NETWORKS 32 /* max number of interfaces to check */ + +#ifndef IFF_LOOPBACK +# define IFF_LOOPBACK 0 +#endif + +#define LOOPBACK 0x7f000001 + + + +/* ********************************************* */ +#ifdef WIN32 +# define WIN32_LEAN_AND_MEAN +# define WIN32IO_IS_STDIO +# define PATHLEN 1024 + +# include +# include + + +/* The idea here is to read all the directory names into a string table + * (separated by nulls) and when one of the other dir functions is called + * return the pointer to the current file name. + */ +DIR * +opendir(const char *filename) +{ + DIR *p; + long len; + long idx; + char scannamespc[PATHLEN]; + char *scanname = scannamespc; + struct stat sbuf; + WIN32_FIND_DATA FindData; + HANDLE fh; + + /* check to see if filename is a directory */ + if (stat(filename, &sbuf) < 0 || sbuf.st_mode & S_IFDIR == 0) { + return NULL; + } + + /* get the file system characteristics */ +/* if(GetFullPathName(filename, SNMP_MAXPATH, root, &dummy)) { + * if(dummy = strchr(root, '\\')) + * *++dummy = '\0'; + * if(GetVolumeInformation(root, volname, SNMP_MAXPATH, &serial, + * &maxname, &flags, 0, 0)) { + * downcase = !(flags & FS_CASE_IS_PRESERVED); + * } + * } + * else { + * downcase = TRUE; + * } + */ + + /* Create the search pattern */ + strcpy(scanname, filename); + + if(strchr("/\\", *(scanname + strlen(scanname) - 1)) == NULL) + strcat(scanname, "/*"); + else + strcat(scanname, "*"); + + /* do the FindFirstFile call */ + fh = FindFirstFile(scanname, &FindData); + if(fh == INVALID_HANDLE_VALUE) { + return NULL; + } + + /* Get us a DIR structure */ + p = (DIR*)malloc(sizeof(DIR)); + /* Newz(1303, p, 1, DIR); */ + if(p == NULL) + return NULL; + + /* now allocate the first part of the string table for + * the filenames that we find. + */ + idx = strlen(FindData.cFileName)+1; + p->start = (char*)malloc(idx); + /* New(1304, p->start, idx, char);*/ + if(p->start == NULL) { + free(p); + return NULL; + } + strcpy(p->start, FindData.cFileName); +/* if(downcase) + * strlwr(p->start); + */ + p->nfiles = 0; + + /* loop finding all the files that match the wildcard + * (which should be all of them in this directory!). + * the variable idx should point one past the null terminator + * of the previous string found. + */ + while (FindNextFile(fh, &FindData)) { + len = strlen(FindData.cFileName); + /* bump the string table size by enough for the + * new name and it's null terminator + */ + p->start = (char*)realloc((void*)p->start, idx+len+1); + /* Renew(p->start, idx+len+1, char);*/ + if(p->start == NULL) { + free(p); + return NULL; + } + strcpy(&p->start[idx], FindData.cFileName); +/* if (downcase) + * strlwr(&p->start[idx]); + */ + p->nfiles++; + idx += len+1; + } + FindClose(fh); + p->size = idx; + p->curr = p->start; + return p; +} + + +/* Readdir just returns the current string pointer and bumps the + * string pointer to the nDllExport entry. + */ +struct direct * +readdir(DIR *dirp) +{ + int len; + static int dummy = 0; + + if (dirp->curr) { + /* first set up the structure to return */ + len = strlen(dirp->curr); + strcpy(dirp->dirstr.d_name, dirp->curr); + dirp->dirstr.d_namlen = len; + + /* Fake an inode */ + dirp->dirstr.d_ino = dummy++; + + /* Now set up for the nDllExport call to readdir */ + dirp->curr += len + 1; + if (dirp->curr >= (dirp->start + dirp->size)) { + dirp->curr = NULL; + } + + return &(dirp->dirstr); + } + else + return NULL; +} + +/* free the memory allocated by opendir */ +int +closedir(DIR *dirp) +{ + free(dirp->start); + free(dirp); + return 1; +} + +#ifndef HAVE_GETTIMEOFDAY + +int gettimeofday(struct timeval *tv, + struct timezone *tz) +{ + struct _timeb timebuffer; + + _ftime(&timebuffer); + tv->tv_usec = timebuffer.millitm * 1000; + tv->tv_sec = timebuffer.time; + return(0); +} +#endif /* !HAVE_GETTIMEOFDAY */ + +in_addr_t get_myaddr(void) +{ + char local_host[130]; + int result; + LPHOSTENT lpstHostent; + SOCKADDR_IN in_addr, remote_in_addr; + SOCKET hSock; + int nAddrSize = sizeof(SOCKADDR); + + in_addr.sin_addr.s_addr = INADDR_ANY; + + result = gethostname(local_host, sizeof(local_host)); + if (result == 0) + { + lpstHostent = gethostbyname((LPSTR)local_host); + if (lpstHostent) + { + in_addr.sin_addr.s_addr = *((u_long FAR *) (lpstHostent->h_addr)); + return((in_addr_t)in_addr.sin_addr.s_addr); + } + } + + /* if we are here, than we don't have host addr */ + hSock = socket(AF_INET, SOCK_DGRAM, 0); + if (hSock != INVALID_SOCKET) + { + /* connect to any port and address */ + remote_in_addr.sin_family = AF_INET; + remote_in_addr.sin_port = htons(IPPORT_ECHO); + remote_in_addr.sin_addr.s_addr = inet_addr("128.22.33.11"); + result=connect(hSock,(LPSOCKADDR)&remote_in_addr,sizeof(SOCKADDR)); + if (result != SOCKET_ERROR) + { + /* get local ip address */ + getsockname(hSock, (LPSOCKADDR)&in_addr,(int FAR *)&nAddrSize); + } + closesocket(hSock); + } + return((in_addr_t)in_addr.sin_addr.s_addr); +} + +long get_uptime (void) +{ + return (0); /* not implemented */ +} + +char * +winsock_startup (void) +{ + WORD VersionRequested; + WSADATA stWSAData; + int i; + static char errmsg[100]; + + VersionRequested = MAKEWORD(1,1); + i = WSAStartup(VersionRequested, &stWSAData); + if (i != 0) + { + if (i == WSAVERNOTSUPPORTED) + sprintf(errmsg,"Unable to init. socket lib, does not support 1.1"); + else + { + sprintf(errmsg,"Socket Startup error %d", i); + } + return(errmsg); + } + return(NULL); +} + +void winsock_cleanup (void) +{ + WSACleanup(); +} + +#else /* ! WIN32 */ +/*******************************************************************/ + +/* + * XXX What if we have multiple addresses? + * XXX Could it be computed once then cached? + */ +in_addr_t get_myaddr (void) +{ + int sd; + struct ifconf ifc; + struct ifreq conf[NUM_NETWORKS], *ifrp, ifreq; + struct sockaddr_in *in_addr; + int count; + int interfaces; /* number of interfaces returned by ioctl */ + + if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return 0; + ifc.ifc_len = sizeof(conf); + ifc.ifc_buf = (caddr_t)conf; + if (ioctl(sd, SIOCGIFCONF, (char *)&ifc) < 0){ + close(sd); + return 0; + } + ifrp = ifc.ifc_req; + interfaces = ifc.ifc_len / sizeof(struct ifreq); + for(count = 0; count < interfaces; count++, ifrp++){ + ifreq = *ifrp; + if (ioctl(sd, SIOCGIFFLAGS, (char *)&ifreq) < 0) + continue; + in_addr = (struct sockaddr_in *)&ifrp->ifr_addr; + if ((ifreq.ifr_flags & IFF_UP) +#ifdef IFF_RUNNING + && (ifreq.ifr_flags & IFF_RUNNING) +#endif /* IFF_RUNNING */ + && !(ifreq.ifr_flags & IFF_LOOPBACK) + && in_addr->sin_addr.s_addr != LOOPBACK){ +#ifdef SYS_IOCTL_H_HAS_SIOCGIFADDR + if (ioctl(sd, SIOCGIFADDR, (char *)&ifreq) < 0) + continue; + in_addr = (struct sockaddr_in *)&(ifreq.ifr_addr); +#endif + close(sd); + return in_addr->sin_addr.s_addr; + } + } + close(sd); + return 0; +} + + +#if !defined(solaris2) && !defined(linux) && !defined(cygwin) && !defined(__ECOS) +/* + * Returns boottime in centiseconds(!). + * Caches this for future use. + */ +long get_boottime (void) +{ + static long boottime_csecs = 0; + struct timeval boottime; +#ifdef CAN_USE_SYSCTL + int mib[2]; + size_t len; +#else + int kmem; + static struct nlist nl[] = { +#if !defined(hpux) + { (char*)"_boottime" }, +#else + { (char*)"boottime" }, +#endif + { (char*)"" } + }; +#endif + + + if ( boottime_csecs != 0 ) + return( boottime_csecs ); + +#ifdef CAN_USE_SYSCTL + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + + len = sizeof(boottime); + + sysctl(mib, 2, &boottime, &len, NULL, NULL); + boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000); +#else /* CAN_USE_SYSCTL */ + if ((kmem = open("/dev/kmem", 0)) < 0) + return 0; + nlist(KERNEL_LOC, nl); + if (nl[0].n_type == 0){ + close(kmem); + return 0; + } + + lseek(kmem, (long)nl[0].n_value, L_SET); + read(kmem, &boottime, sizeof(boottime)); + close(kmem); + boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000); +#endif /* CAN_USE_SYSCTL */ + + return( boottime_csecs ); +} +#endif + +/* + * Returns uptime in centiseconds(!). + */ +#if !defined(__ECOS) +long get_uptime (void) +{ +#if !defined(solaris2) && !defined(linux) && !defined(cygwin) + struct timeval now; + long boottime_csecs, nowtime_csecs; + + boottime_csecs = get_boottime(); + if (boottime_csecs == 0) + return 0; + gettimeofday(&now,(struct timezone *)0); + nowtime_csecs = (now.tv_sec * 100) + (now.tv_usec / 10000); + + return (nowtime_csecs - boottime_csecs); +#endif + +#ifdef solaris2 + kstat_ctl_t *ksc = kstat_open(); + kstat_t *ks; + kid_t kid; + kstat_named_t *named; + u_long lbolt = 0; + + if (ksc) { + ks = kstat_lookup (ksc, "unix", -1, "system_misc"); + if (ks) { + kid = kstat_read (ksc, ks, NULL); + if (kid != -1) { + named = kstat_data_lookup(ks, "lbolt"); + if (named) { + lbolt = named->value.ul; + } + } + } + kstat_close(ksc); + } + return lbolt; +#endif /* solaris2 */ + +#ifdef linux + FILE *in = fopen ("/proc/uptime", "r"); + long uptim = 0, a, b; + if (in) { + if (2 == fscanf (in, "%ld.%ld", &a, &b)) + uptim = a * 100 + b; + fclose (in); + } + return uptim; +#endif /* linux */ + return (0); /* not implemented */ +} +#endif // not __ECOS + +#ifndef HAVE_GETTIMEOFDAY + +int gettimeofday(struct timeval *tv, + struct timezone *tz) +{ + + tv->tv_usec = 0; + tv->tv_sec = time(NULL); + return(0); +} +#endif /* !HAVE_GETTIMEOFDAY */ + + +#endif /* ! WIN32 */ +/*******************************************************************/ + +#ifndef HAVE_STRNCASECMP + +/* test for NULL pointers before and NULL characters after + * comparing possibly non-NULL strings. + * WARNING: This function does NOT check for array overflow. + */ +int strncasecmp(const char *s1, const char *s2, size_t nch) +{ + size_t ii; + int res = -1; + + if (!s1) { + if (!s2) return 0; + return (-1); + } + if (!s2) + return (1); + + for (ii = 0; (ii < nch) && *s1 && *s2; ii++, s1++, s2++) + { + res = (int) (tolower(*s1) - tolower(*s2)); + if (res != 0) break; + } + + if ( ii == nch ) { + s1--; s2--; + } + + if (! *s1) { + if (! *s2) return 0; + return (-1); + } + if (! *s2) + return (1); + + return (res); +} + +int strcasecmp(const char *s1, const char *s2) +{ + return strncasecmp(s1, s2, 1000000); +} + +#endif /* HAVE_STRNCASECMP */ + + +#ifndef HAVE_STRDUP +char * +strdup(const char *src) +{ + int len; + char *dst; + + len = strlen(src) + 1; + if ((dst = (char *)malloc(len)) == NULL) + return(NULL); + strcpy(dst, src); + return(dst); +} +#endif /* HAVE_STRDUP */ + +#ifndef HAVE_SETENV +int setenv(const char *name, + const char *value, + int overwrite) +{ + char *cp; + int ret; + + if (overwrite == 0) { + if (getenv(name)) return 0; + } + cp = (char*)malloc(strlen(name)+strlen(value)+2); + if (cp == NULL) return -1; + sprintf(cp, "%s=%s", name, value); + ret = putenv(cp); + return ret; +} +#endif /* HAVE_SETENV */ + +int +calculate_time_diff(struct timeval *now, struct timeval *then) +{ + struct timeval tmp, diff; + memcpy(&tmp, now, sizeof(struct timeval)); + tmp.tv_sec--; + tmp.tv_usec += 1000000L; + diff.tv_sec = tmp.tv_sec - then->tv_sec; + diff.tv_usec = tmp.tv_usec - then->tv_usec; + if (diff.tv_usec > 1000000L){ + diff.tv_usec -= 1000000L; + diff.tv_sec++; + } + return ((diff.tv_sec * 100) + (diff.tv_usec / 10000)); +} + +#ifndef HAVE_STRCASESTR +/* + * only glibc2 has this. + */ +char *strcasestr(const char *haystack, const char *needle) +{ + const char *cp1=haystack, *cp2=needle; + const char *cx; + int tstch1, tstch2; + + /* printf("looking for '%s' in '%s'\n", needle, haystack); */ + if (cp1 && cp2 && *cp1 && *cp2) + for (cp1=haystack, cp2=needle; *cp1; ) { + cx = cp1; cp2 = needle; + do { + /* printf("T'%c' ", *cp1); */ + if (! *cp2) { /* found the needle */ + /* printf("\nfound '%s' in '%s'\n", needle, cx); */ + return (char *)cx; + } + if (! *cp1) + break; + + tstch1 = toupper(*cp1); + tstch2 = toupper(*cp2); + if (tstch1 != tstch2) + break; + /* printf("M'%c' ", *cp1); */ + cp1++; cp2++; + } + while (1); + if (*cp1) + cp1++; + } + /* printf("\n"); */ + if (cp1 && *cp1) + return (char *)cp1; + + return NULL; +} +#endif + +#if !defined(__ECOS) +int +mkdirhier(const char *pathname, mode_t mode, int skiplast) { + struct stat sbuf; + char *ourcopy = strdup(pathname); + char *entry; + char buf[SNMP_MAXPATH]; + + entry = strtok( ourcopy, "/" ); + + buf[0] = '\0'; + /* check to see if filename is a directory */ + while ( entry ) { + strcat(buf,"/"); + strcat(buf, entry); + entry = strtok( NULL, "/"); + if (entry == NULL && skiplast) + break; + if (stat(buf, &sbuf) < 0) { + /* DNE, make it */ + snmp_log(LOG_INFO, "Creating directory: %s\n", buf); +#ifdef WIN32 + CreateDirectory(buf, NULL); +#else + mkdir(buf, mode); +#endif + } else { + /* exists, is it a file? */ + if ((sbuf.st_mode & S_IFDIR) == 0) { + /* ack! can't make a directory on top of a file */ + free(ourcopy); + return SNMPERR_GENERR; + } + } + } + free(ourcopy); + return SNMPERR_SUCCESS; +} +#endif + + +#ifdef __ECOS +#include + +long get_boottime (void) +{ + return 1l; +} + +long get_uptime (void) +{ + return cyg_current_time(); +} + +#endif + diff --git a/packages/net/snmp/lib/current/src/tools.c b/packages/net/snmp/lib/current/src/tools.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/tools.c @@ -0,0 +1,635 @@ +//========================================================================== +// +// ./lib/current/src/tools.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * tools.c + */ + +#include + +#include +#include +#include +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_WINSOCK_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "system.h" +#include "snmp_api.h" +#include "snmp_debug.h" +#include "snmp_debug.h" +#include "tools.h" +#include "mib.h" +#include "scapi.h" + + +/*******************************************************************-o-****** + * free_zero + * + * Parameters: + * *buf Pointer at bytes to free. + * size Number of bytes in buf. + */ +void +free_zero(void *buf, size_t size) +{ + if (buf) { + memset(buf, 0, size); + free(buf); + } + +} /* end free_zero() */ + + + + +/*******************************************************************-o-****** + * malloc_random + * + * Parameters: + * size Number of bytes to malloc() and fill with random bytes. + * + * Returns pointer to allocaed & set buffer on success, size contains + * number of random bytes filled. + * + * buf is NULL and *size set to KMT error value upon failure. + * + */ +u_char * +malloc_random(size_t *size) +{ + int rval = SNMPERR_SUCCESS; + u_char *buf = (u_char *)calloc (1, *size); + + if (buf) { + rval = sc_random(buf, size); + + if (rval < 0) { + free_zero(buf, *size); + buf = NULL; + } else { + *size = rval; + } + } + + return buf; + +} /* end malloc_random() */ + + + + +/*******************************************************************-o-****** + * memdup + * + * Parameters: + * to Pointer to allocate and copy memory to. + * from Pointer to copy memory from. + * size Size of the data to be copied. + * + * Returns + * SNMPERR_SUCCESS On success. + * SNMPERR_GENERR On failure. + */ +int +memdup(u_char **to, const u_char *from, size_t size) +{ + if (to == NULL) + return SNMPERR_GENERR; + if (from == NULL) { + *to = NULL; + return SNMPERR_SUCCESS; + } + if ((*to = (u_char *)malloc(size)) == NULL) + return SNMPERR_GENERR; + memcpy(*to, from, size); + return SNMPERR_SUCCESS; + +} /* end memdup() */ + + + + +/*******************************************************************-o-****** + * binary_to_hex + * + * Parameters: + * *input Binary data. + * len Length of binary data. + * **output NULL terminated string equivalent in hex. + * + * Returns: + * olen Length of output string not including NULL terminator. + * + * FIX Is there already one of these in the UCD SNMP codebase? + * The old one should be used, or this one should be moved to + * snmplib/snmp_api.c. + */ +u_int +binary_to_hex(const u_char *input, size_t len, char **output) +{ + u_int olen = (len * 2) + 1; + char *s = (char *) calloc(1,olen), + *op = s; + const u_char *ip = input; + + + while (ip-input < (int)len) { + *op++ = VAL2HEX( (*ip >> 4) & 0xf ); + *op++ = VAL2HEX( *ip & 0xf ); + ip++; + } + *op = '\0'; + + *output = s; + return olen; + +} /* end binary_to_hex() */ + + + + +/*******************************************************************-o-****** + * hex_to_binary2 + * + * Parameters: + * *input Printable data in base16. + * len Length in bytes of data. + * **output Binary data equivalent to input. + * + * Returns: + * SNMPERR_GENERR Failure. + * Otherwise, Length of allocated string. + * + * + * Input of an odd length is right aligned. + * + * FIX Another version of "hex-to-binary" which takes odd length input + * strings. It also allocates the memory to hold the binary data. + * Should be integrated with the official hex_to_binary() function. + */ +int +hex_to_binary2(const u_char *input, size_t len, char **output) +{ + u_int olen = (len/2) + (len%2); + char *s = (char *)calloc (1,olen), + *op = s; + const u_char *ip = input; + + + *output = NULL; + *op = 0; + if (len%2) { + if(!isxdigit(*ip)) goto hex_to_binary2_quit; + *op++ = HEX2VAL( *ip ); ip++; + } + + while (ip-input < (int)len) { + if(!isxdigit(*ip)) goto hex_to_binary2_quit; + *op = HEX2VAL( *ip ) << 4; ip++; + + if(!isxdigit(*ip)) goto hex_to_binary2_quit; + *op++ += HEX2VAL( *ip ); ip++; + } + + *output = s; + return olen; + +hex_to_binary2_quit: + free_zero(s, olen); + return -1; + +} /* end hex_to_binary2() */ + + + + +/*******************************************************************-o-****** + * dump_chunk + * + * Parameters: + * *title (May be NULL.) + * *buf + * size + */ +void +dump_chunk(const char *debugtoken, const char *title, const u_char *buf, int size) +{ + u_int printunit = 64; /* XXX Make global. */ + char chunk[SNMP_MAXBUF], + *s, *sp; + + if ( title && (*title != '\0') ) { + DEBUGMSGTL((debugtoken, "%s\n", title)); + } + + + memset(chunk, 0, SNMP_MAXBUF); + size = binary_to_hex(buf, size, &s); + sp = s; + + while (size > 0) + { + if (size > (int)printunit) { + strncpy(chunk, sp, printunit); + chunk[printunit] = '\0'; + DEBUGMSGTL((debugtoken, "\t%s\n", chunk)); + } else { + DEBUGMSGTL((debugtoken, "\t%s\n", sp)); + } + + sp += printunit; + size -= printunit; + } + + + SNMP_FREE(s); + +} /* end dump_chunk() */ + + + + +/*******************************************************************-o-****** + * dump_snmpEngineID + * + * Parameters: + * *estring + * *estring_len + * + * Returns: + * Allocated memory pointing to a string of buflen char representing + * a printf'able form of the snmpEngineID. + * + * -OR- NULL on error. + * + * + * Translates the snmpEngineID TC into a printable string. From RFC 2271, + * Section 5 (pp. 36-37): + * + * First bit: 0 Bit string structured by means non-SNMPv3. + * 1 Structure described by SNMPv3 SnmpEngineID TC. + * + * Bytes 1-4: Enterprise ID. (High bit of first byte is ignored.) + * + * Byte 5: 0 (RESERVED by IANA.) + * 1 IPv4 address. ( 4 octets) + * 2 IPv6 address. ( 16 octets) + * 3 MAC address. ( 6 octets) + * 4 Locally defined text. (0-27 octets) + * 5 Locally defined octets. (0-27 octets) + * 6-127 (RESERVED for enterprise.) + * + * Bytes 6-32: (Determined by byte 5.) + * + * + * Non-printable characters are given in hex. Text is given in quotes. + * IP and MAC addresses are given in standard (UN*X) conventions. Sections + * are comma separated. + * + * esp, remaining_len and s trace the state of the constructed buffer. + * s will be defined if there is something to return, and it will point + * to the end of the constructed buffer. + * + * + * ASSUME "Text" means printable characters. + * + * XXX Must the snmpEngineID always have a minimum length of 12? + * (Cf. part 2 of the TC definition.) + * XXX Does not enforce upper-bound of 32 bytes. + * XXX Need a switch to decide whether to use DNS name instead of a simple + * IP address. + * + * FIX Use something other than sprint_hexstring which doesn't add + * trailing spaces and (sometimes embedded) newlines... + */ +#ifdef SNMP_TESTING_CODE +char * +dump_snmpEngineID(const u_char *estring, size_t *estring_len) +{ +#define eb(b) ( *(esp+b) & 0xff ) + + int rval = SNMPERR_SUCCESS, + gotviolation = 0, + slen = 0; + u_int remaining_len; + + char buf[SNMP_MAXBUF], + *s = NULL, + *t; + const u_char *esp = estring; + + struct in_addr iaddr; + + + + /* + * Sanity check. + */ + if ( !estring || (*estring_len <= 0) ) { + QUITFUN(SNMPERR_GENERR, dump_snmpEngineID_quit); + } + remaining_len = *estring_len; + memset(buf, 0, SNMP_MAXBUF); + + + + /* + * Test first bit. Return immediately with a hex string, or + * begin by formatting the enterprise ID. + */ + if ( !(*esp & 0x80) ) { + sprint_hexstring(buf, esp, remaining_len); + s = strchr(buf, '\0'); + s -= 1; + goto dump_snmpEngineID_quit; + } + + s = buf; + s += sprintf(s, "enterprise %d, ", ((*(esp+0)&0x7f) << 24) | + ((*(esp+1)&0xff) << 16) | + ((*(esp+2)&0xff) << 8) | + ((*(esp+3)&0xff)) ); + /* XXX Ick. */ + + if (remaining_len < 5) { /* XXX Violating string. */ + goto dump_snmpEngineID_quit; + } + + esp += 4; /* Incremented one more in the switch below. */ + remaining_len -= 5; + + + + /* + * Act on the fifth byte. + */ + switch ((int) *esp++) { + case 1: /* IPv4 address. */ + + if (remaining_len < 4) goto dump_snmpEngineID_violation; + memcpy(&iaddr.s_addr, esp, 4); + + if ( !(t = inet_ntoa(iaddr)) ) goto dump_snmpEngineID_violation; + s += sprintf(s, "%s", t); + + esp += 4; + remaining_len -= 4; + break; + + case 2: /* IPv6 address. */ + + if (remaining_len < 16) goto dump_snmpEngineID_violation; + + s += sprintf( s, + "%02X%02X %02X%02X %02X%02X %02X%02X::" + "%02X%02X %02X%02X %02X%02X %02X%02X", + eb(0), eb(1), eb(2), eb(3), + eb(4), eb(5), eb(6), eb(7), + eb(8), eb(9), eb(10), eb(11), + eb(12), eb(13), eb(14), eb(15) ); + + esp += 16; + remaining_len -= 16; + break; + + case 3: /* MAC address. */ + + if (remaining_len < 6) goto dump_snmpEngineID_violation; + + s += sprintf( s, "%02X:%02X:%02X:%02X:%02X:%02X", + eb(0), eb(1), eb(2), eb(3), eb(4), eb(5) ); + + esp += 6; + remaining_len -= 6; + break; + + case 4: /* Text. */ + + /* Doesn't exist on all (many) architectures */ + /* s += snprintf(s, remaining_len+3, "\"%s\"", esp); */ + s += sprintf(s, "\"%s\"", esp); + goto dump_snmpEngineID_quit; + break; /*NOTREACHED*/ + + case 5: /* Octets. */ + + sprint_hexstring(s, esp, remaining_len); + s = strchr(buf, '\0'); + s -= 1; + goto dump_snmpEngineID_quit; + break; /*NOTREACHED*/ + + +dump_snmpEngineID_violation: + case 0: /* Violation of RESERVED, + * -OR- of expected length. + */ + gotviolation = 1; + s += sprintf(s, "!!! "); + + default: /* Unknown encoding. */ + + if ( !gotviolation ) { + s += sprintf(s, "??? "); + } + sprint_hexstring(s, esp, remaining_len); + s = strchr(buf, '\0'); + s -= 1; + + goto dump_snmpEngineID_quit; + + } /* endswitch */ + + + + /* + * Cases 1-3 (IP and MAC addresses) should not have trailing + * octets, but perhaps they do. Throw them in too. XXX + */ + if (remaining_len > 0) { + s += sprintf(s, " (??? "); + + sprint_hexstring(s, esp, remaining_len); + s = strchr(buf, '\0'); + s -= 1; + + s += sprintf(s, ")"); + } + + + +dump_snmpEngineID_quit: + if (s) { + slen = s-buf+1; + s = calloc(1,slen); + memcpy(s, buf, (slen)-1); + } + + memset(buf, 0, SNMP_MAXBUF); /* XXX -- Overkill? XXX: Yes! */ + + return s; + +#undef eb +} /* end dump_snmpEngineID() */ +#endif /* SNMP_TESTING_CODE */ + + +/* + * create a new time marker. + * NOTE: Caller must free time marker when no longer needed. + */ +marker_t atime_newMarker(void) +{ + marker_t pm = (marker_t)calloc(1,sizeof(struct timeval)); + gettimeofday((struct timeval *)pm, 0); + return pm; +} + +/* + * set a time marker. + */ +void atime_setMarker(marker_t pm) +{ + if (! pm) return; + + gettimeofday((struct timeval *)pm, 0); +} + +/* + * Test: Has (marked time plus delta) exceeded current time ? + * Returns 0 if test fails or cannot be tested (no marker). + */ +int atime_ready( marker_t pm, int deltaT) +{ + struct timeval txdelta, txnow; + if (! pm) return 0; + + memcpy((void *)&txdelta, pm, sizeof(txdelta)); + while (deltaT > 1000) { + txdelta.tv_sec ++; + deltaT -= 1000; + } + txdelta.tv_usec = (deltaT * 1000) + txdelta.tv_usec; + + gettimeofday(&txnow, 0); + if (timercmp(&txnow, &txdelta, <)) + return 0; + + return 1; +} diff --git a/packages/net/snmp/lib/current/src/vacm.c b/packages/net/snmp/lib/current/src/vacm.c new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/vacm.c @@ -0,0 +1,546 @@ +//========================================================================== +// +// ./lib/current/src/vacm.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/* + * vacm.c + * + * SNMPv3 View-based Access Control Model + */ + +#include + +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STRING_H +#include +#else +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if TIME_WITH_SYS_TIME +# ifdef WIN32 +# include +# else +# include +# endif +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_WINSOCK_H +#include +#endif + +#if HAVE_NETINET_IN_H +#include +#endif + +#if HAVE_DMALLOC_H +#include +#endif + +#include "asn1.h" +#include "snmp.h" +#include "snmp_api.h" +#include "vacm.h" +#include "snmp_debug.h" + +static struct vacm_viewEntry *viewList = NULL, *viewScanPtr = NULL; +static struct vacm_accessEntry *accessList = NULL, *accessScanPtr = NULL; +static struct vacm_groupEntry *groupList = NULL, *groupScanPtr = NULL; + +struct vacm_viewEntry * +vacm_getViewEntry(const char *viewName, + oid *viewSubtree, + size_t viewSubtreeLen) +{ + struct vacm_viewEntry *vp, *vpret = NULL; + char view[VACMSTRINGLEN]; + int found, glen; + + glen = (int)strlen(viewName); + if (glen < 0 || glen >= VACM_MAX_STRING) + return NULL; + view[0] = glen; + strcpy(view+1, viewName); + for(vp = viewList; vp; vp = vp->next){ + if (!memcmp(view, vp->viewName,glen+1) + && viewSubtreeLen >= vp->viewSubtreeLen) { + int mask = 0x80, maskpos = 0; + int oidpos; + found = 1; + for (oidpos = 0; found && oidpos < (int)vp->viewSubtreeLen; oidpos++) { + if ((vp->viewMask[maskpos] & mask) != 0) { + if (viewSubtree[oidpos] != vp->viewSubtree[oidpos]) + found = 0; + } + if (mask == 1) { + mask = 0x80; + maskpos++; + } + else mask >>= 1; + } + if (found) { + /* match successful, keep this node if its longer than + the previous or (equal and lexicographically greater + than the previous). */ + if (vpret == NULL || vp->viewSubtreeLen > vpret->viewSubtreeLen || + (vp->viewSubtreeLen == vpret->viewSubtreeLen && + snmp_oid_compare(vp->viewSubtree, vp->viewSubtreeLen, + vpret->viewSubtree, + vpret->viewSubtreeLen) > 0)) + vpret = vp; + } + } + } + DEBUGMSGTL(("vacm:getView", ", %s", (vpret)?"found":"none")); + return vpret; +} + +void +vacm_scanViewInit (void) +{ + viewScanPtr = viewList; +} + +struct vacm_viewEntry * +vacm_scanViewNext (void) +{ + struct vacm_viewEntry *returnval = viewScanPtr; + if (viewScanPtr) viewScanPtr = viewScanPtr->next; + return returnval; +} + +struct vacm_viewEntry * +vacm_createViewEntry(const char *viewName, + oid *viewSubtree, + size_t viewSubtreeLen) +{ + struct vacm_viewEntry *vp, *lp, *op = NULL; + int cmp, glen; + + glen = (int)strlen(viewName); + if (glen < 0 || glen >= VACM_MAX_STRING) + return NULL; + vp = (struct vacm_viewEntry *)calloc(1, sizeof(struct vacm_viewEntry)); + if (vp == NULL) + return NULL; + vp->reserved = (struct vacm_viewEntry *)calloc(1, sizeof(struct vacm_viewEntry)); + if (vp->reserved == NULL) { + free(vp); + return NULL; + } + + vp->viewName[0] = glen; + strcpy(vp->viewName+1, viewName); + memcpy(vp->viewSubtree, viewSubtree, viewSubtreeLen * sizeof(oid)); + vp->viewSubtreeLen = viewSubtreeLen; + + lp = viewList; + while (lp) { + cmp = memcmp(lp->viewName, vp->viewName, glen+1); + if (cmp > 0) break; + if (cmp < 0) goto next; + +next: + op = lp; + lp = lp->next; + } + vp->next = lp; + if (op) op->next = vp; + else viewList = vp; + return vp; +} + +void +vacm_destroyViewEntry(const char *viewName, + oid *viewSubtree, + size_t viewSubtreeLen) +{ + struct vacm_viewEntry *vp, *lastvp = NULL; + + if (viewList && !strcmp(viewList->viewName+1, viewName) + && viewList->viewSubtreeLen == viewSubtreeLen + && !memcmp((char *)viewList->viewSubtree, (char *)viewSubtree, + viewSubtreeLen * sizeof(oid))){ + vp = viewList; + viewList = viewList->next; + } else { + for (vp = viewList; vp; vp = vp->next){ + if (!strcmp(vp->viewName+1, viewName) + && vp->viewSubtreeLen == viewSubtreeLen + && !memcmp((char *)vp->viewSubtree, (char *)viewSubtree, + viewSubtreeLen * sizeof(oid))) + break; + lastvp = vp; + } + if (!vp) + return; + lastvp->next = vp->next; + } + if (vp->reserved) + free(vp->reserved); + free(vp); + return; +} + +void vacm_destroyAllViewEntries (void) +{ + struct vacm_viewEntry *vp; + while ((vp = viewList)) { + viewList = vp->next; + if (vp->reserved) free(vp->reserved); + free(vp); + } +} + +struct vacm_groupEntry * +vacm_getGroupEntry(int securityModel, + const char *securityName) +{ + struct vacm_groupEntry *vp; + char secname[VACMSTRINGLEN]; + int glen; + + glen = (int)strlen(securityName); + if (glen < 0 || glen >= VACM_MAX_STRING) + return NULL; + secname[0] = glen; + strcpy(secname+1, securityName); + + for (vp = groupList; vp; vp = vp->next) { + if ((securityModel == vp->securityModel || vp->securityModel == SNMP_SEC_MODEL_ANY) + && !memcmp(vp->securityName, secname,glen+1)) + return vp; + } + return NULL; +} + +void +vacm_scanGroupInit (void) +{ + groupScanPtr = groupList; +} + +struct vacm_groupEntry * +vacm_scanGroupNext (void) +{ + struct vacm_groupEntry *returnval = groupScanPtr; + if (groupScanPtr) groupScanPtr = groupScanPtr->next; + return returnval; +} + +struct vacm_groupEntry * +vacm_createGroupEntry(int securityModel, + const char *securityName) +{ + struct vacm_groupEntry *gp, *lg, *og; + int cmp, glen; + + glen = (int)strlen(securityName); + if (glen < 0 || glen >= VACM_MAX_STRING) + return NULL; + gp = (struct vacm_groupEntry *)calloc(1, sizeof(struct vacm_groupEntry)); + if (gp == NULL) + return NULL; + gp->reserved = (struct vacm_groupEntry *)calloc(1, sizeof(struct vacm_groupEntry)); + if (gp->reserved == NULL) { + free(gp); + return NULL; + } + + gp->securityModel = securityModel; + gp->securityName[0] = glen; + strcpy(gp->securityName+1, securityName); + + lg = groupList; + og = NULL; + while (lg) { + if (lg->securityModel > securityModel) break; + if (lg->securityModel == securityModel && + (cmp = memcmp(lg->securityName, gp->securityName, glen+1)) > 0) break; + /* if (lg->securityModel == securityModel && cmp == 0) abort(); */ + og = lg; lg = lg->next; + } + gp->next = lg; + if (og == NULL) groupList = gp; + else og->next = gp; + return gp; +} + +void +vacm_destroyGroupEntry(int securityModel, + const char *securityName) +{ + struct vacm_groupEntry *vp, *lastvp = NULL; + + if (groupList && groupList->securityModel == securityModel + && !strcmp(groupList->securityName+1, securityName)) { + vp = groupList; + groupList = groupList->next; + } else { + for (vp = groupList; vp; vp = vp->next){ + if (vp->securityModel == securityModel + && !strcmp(vp->securityName+1, securityName)) + break; + lastvp = vp; + } + if (!vp) + return; + lastvp->next = vp->next; + } + if (vp->reserved) + free(vp->reserved); + free(vp); + return; +} + +void vacm_destroyAllGroupEntries (void) +{ + struct vacm_groupEntry *gp; + while ((gp = groupList)) { + groupList = gp->next; + if (gp->reserved) free(gp->reserved); + free(gp); + } +} + +struct vacm_accessEntry * +vacm_getAccessEntry(const char *groupName, + const char *contextPrefix, + int securityModel, + int securityLevel) +{ + struct vacm_accessEntry *vp; + char group[VACMSTRINGLEN]; + char context[VACMSTRINGLEN]; + int glen, clen; + + glen = (int)strlen(groupName); + if (glen < 0 || glen >= VACM_MAX_STRING) + return NULL; + clen = (int)strlen(contextPrefix); + if (clen < 0 || clen >= VACM_MAX_STRING) + return NULL; + + group[0] = glen; + strcpy(group+1, groupName); + context[0] = clen; + strcpy(context+1, contextPrefix); + for(vp = accessList; vp; vp = vp->next){ + if ((securityModel == vp->securityModel || vp->securityModel == SNMP_SEC_MODEL_ANY) + && securityLevel >= vp->securityLevel + && !memcmp(vp->groupName, group, glen+1) + && !memcmp(vp->contextPrefix, context, clen+1)) + return vp; + } + return NULL; +} + +void +vacm_scanAccessInit (void) +{ + accessScanPtr = accessList; +} + +struct vacm_accessEntry * +vacm_scanAccessNext (void) +{ + struct vacm_accessEntry *returnval = accessScanPtr; + if (accessScanPtr) accessScanPtr = accessScanPtr->next; + return returnval; +} + +struct vacm_accessEntry * +vacm_createAccessEntry(const char *groupName, + const char *contextPrefix, + int securityModel, + int securityLevel) +{ + struct vacm_accessEntry *vp, *lp, *op = NULL; + int cmp, glen, clen; + + glen = (int)strlen(groupName); + if (glen < 0 || glen >= VACM_MAX_STRING) + return NULL; + clen = (int)strlen(contextPrefix); + if (clen < 0 || clen >= VACM_MAX_STRING) + return NULL; + vp = (struct vacm_accessEntry *)calloc(1, sizeof(struct vacm_accessEntry)); + if (vp == NULL) + return NULL; + vp->reserved = (struct vacm_accessEntry *)calloc(1, sizeof(struct vacm_accessEntry)); + if (vp->reserved == NULL) { + free(vp); + return NULL; + } + + vp->securityModel = securityModel; + vp->securityLevel = securityLevel; + vp->groupName[0] = glen; + strcpy(vp->groupName+1, groupName); + vp->contextPrefix[0] = clen; + strcpy(vp->contextPrefix+1, contextPrefix); + + lp = accessList; + while (lp) { + cmp = memcmp(lp->groupName, vp->groupName, glen+1); + if (cmp > 0) break; + if (cmp < 0) goto next; + cmp = memcmp(lp->contextPrefix, vp->contextPrefix, clen+1); + if (cmp > 0) break; + if (cmp < 0) goto next; + if (lp->securityModel > securityModel) break; + if (lp->securityModel < securityModel) goto next; + if (lp->securityLevel > securityLevel) break; +next: + op = lp; + lp = lp->next; + } + vp->next = lp; + if (op == NULL) accessList = vp; + else op->next = vp; + return vp; +} + +void +vacm_destroyAccessEntry(const char *groupName, + const char *contextPrefix, + int securityModel, + int securityLevel) +{ + struct vacm_accessEntry *vp, *lastvp = NULL; + + if (accessList && accessList->securityModel == securityModel + && accessList->securityModel == securityModel + && !strcmp(accessList->groupName+1, groupName) + && !strcmp(accessList->contextPrefix+1, contextPrefix)) { + vp = accessList; + accessList = accessList->next; + } else { + for (vp = accessList; vp; vp = vp->next){ + if (vp->securityModel == securityModel + && vp->securityLevel == securityLevel + && !strcmp(vp->groupName+1, groupName) + && !strcmp(vp->contextPrefix+1, contextPrefix)) + break; + lastvp = vp; + } + if (!vp) + return; + lastvp->next = vp->next; + } + if (vp->reserved) + free(vp->reserved); + free(vp); + return; +} + +void vacm_destroyAllAccessEntries (void) +{ + struct vacm_accessEntry *ap; + while ((ap = accessList)) { + accessList = ap->next; + if (ap->reserved) free(ap->reserved); + free(ap); + } +} + +/* returns 1 if vacm has *any* configuration entries in it (regardless + of weather or not there is enough to make a decision based on it), + else return 0 */ +int vacm_is_configured(void) { + if (viewList == NULL && accessList == NULL && groupList == NULL) + return 0; + return 1; +} + diff --git a/packages/net/tcpip/current/ChangeLog b/packages/net/tcpip/current/ChangeLog --- a/packages/net/tcpip/current/ChangeLog +++ b/packages/net/tcpip/current/ChangeLog @@ -1,3 +1,53 @@ +2000-06-23 Hugo Tyson + + * src/ecos/support.c (cyg_net_mbuf_alloc, cyg_kmem_init): Align + the mbuf pool to MSIZE [128] bytes. That way dtom() works, nasty + though it is. That's needed for ip reassembly in ip_input.c, when + dealing with large icmp-layer packets eg. ping -s 2000 ... + +2000-06-21 Hugo Tyson + + * include/lib/libkern/libkern.h: Do not define assert multiple + times; guarded by __ECOS. + + * include/sys/param.h (MAX,MIN): Only define if undef. + +2000-06-21 Hugo Tyson + + * cdl/net.cdl: Build the new tests; in fact build them + unconditionally. + + * src/lib/network_support.c (init_all_network_interfaces): + Initialize loopback device[s] using init_loopback_interface(), + providing a sensible default route et al. Multiple devs: lo1 will + be 127.0.*1*.1, and so on; class C netmasks will be used. + + init_all_network_interfaces() is also made thread-safe as well as + idempotent, so other threads (or daemons) can call it to make sure + the net is up. + + * src/ecos/support.c (cyg_net_init): Add a call to loopattach() if + there are indeed loopback dev(s) configured. This does the + equivalent of the init of a device from the table, but simpler. + + * tests/udp_lo_test.c (udp_server): New testcase... + * tests/tcp_lo_select.c (tcp_server): New testcase... + * tests/tcp_lo_test.c (tcp_client): New testcase... + * tests/ping_lo_test.c (net_test): New testcase, unconditionally + built loopback device test. Will run on platforms with no network + interfaces. + +2000-06-16 Jonathan Larmour + + * include/bootp.h: Remove RCS id tag + * include/netinet/ip_auth.h: Ditto + * include/netinet/ip_fil.h: Ditto + * include/netinet/ip_fil_compat.h: Ditto + * include/netinet/ip_frag.h: Ditto + * include/netinet/ip_nat.h: Ditto + * include/netinet/ip_proxy.h: Ditto + * include/netinet/ip_state.h: Ditto + 2000-06-08 Hugo Tyson * include/netinet/ip_var.h: Export ipforwarding as well as diff --git a/packages/net/tcpip/current/cdl/net.cdl b/packages/net/tcpip/current/cdl/net.cdl --- a/packages/net/tcpip/current/cdl/net.cdl +++ b/packages/net/tcpip/current/cdl/net.cdl @@ -295,27 +295,37 @@ cdl_package CYGPKG_NET { no_define default_value 0 description " - This option enables the building of the network tests - which at this time are just demos." + This option enables the building of additional network tests + which at this time are just demos; otherwise only loopback + interface tests will be built." cdl_option CYGPKG_NET_TESTS { display "Networking tests" flavor data no_define calculated { CYGPKG_NET_BUILD_TESTS ? \ - "tests/mbuf_test \ - tests/socket_test \ - tests/ftp_test \ - tests/server_test \ - tests/nc_test_master \ - tests/nc_test_slave \ - tests/tftp_client_test \ - tests/tftp_server_test \ - tests/tcp_echo \ - tests/set_mac_address \ - tests/flood \ - tests/ping_test" - : "" } + "tests/mbuf_test \ + tests/socket_test \ + tests/ftp_test \ + tests/server_test \ + tests/nc_test_master \ + tests/nc_test_slave \ + tests/tftp_client_test \ + tests/tftp_server_test \ + tests/tcp_echo \ + tests/set_mac_address \ + tests/flood \ + tests/ping_test \ + tests/ping_lo_test \ + tests/tcp_lo_test \ + tests/udp_lo_test \ + tests/tcp_lo_select" + : + "tests/ping_lo_test \ + tests/tcp_lo_test \ + tests/udp_lo_test \ + tests/tcp_lo_select" + } description " This option specifies the set of tests for the networking package." diff --git a/packages/net/tcpip/current/include/bootp.h b/packages/net/tcpip/current/include/bootp.h --- a/packages/net/tcpip/current/include/bootp.h +++ b/packages/net/tcpip/current/include/bootp.h @@ -80,9 +80,6 @@ SOFTWARE. /* * Bootstrap Protocol (BOOTP). RFC951 and RFC1395. * - * $Id: bootp.h,v 1.3 2000/06/16 16:44:25 jlarmour Exp $ - * - * * This file specifies the "implementation-independent" BOOTP protocol * information which is common to both client and server. * diff --git a/packages/net/tcpip/current/include/lib/libkern/libkern.h b/packages/net/tcpip/current/include/lib/libkern/libkern.h --- a/packages/net/tcpip/current/include/lib/libkern/libkern.h +++ b/packages/net/tcpip/current/include/lib/libkern/libkern.h @@ -174,6 +174,7 @@ abs(j) } #endif +#ifndef __ECOS #ifdef NDEBUG /* tradition! */ #define assert(e) ((void)0) #else @@ -209,10 +210,13 @@ abs(j) __assert("debugging ", __FILE__, __LINE__, "e")) #endif #endif +#endif /* Prototypes for non-quad routines. */ +#ifndef __ECOS void __assert __P((const char *, const char *, int, const char *)) __attribute__ ((__noreturn__)); +#endif int bcmp __P((const void *, const void *, size_t)); int ffs __P((int)); int locc __P((int, char *, u_int)); diff --git a/packages/net/tcpip/current/include/netinet/ip_auth.h b/packages/net/tcpip/current/include/netinet/ip_auth.h --- a/packages/net/tcpip/current/include/netinet/ip_auth.h +++ b/packages/net/tcpip/current/include/netinet/ip_auth.h @@ -61,8 +61,6 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * $Id: ip_auth.h,v 1.3 2000/06/16 16:44:26 jlarmour Exp $ - * */ #ifndef _NETINET_IP_AUTH_H__ diff --git a/packages/net/tcpip/current/include/netinet/ip_fil.h b/packages/net/tcpip/current/include/netinet/ip_fil.h --- a/packages/net/tcpip/current/include/netinet/ip_fil.h +++ b/packages/net/tcpip/current/include/netinet/ip_fil.h @@ -62,7 +62,6 @@ * to the original author and the contributors. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_fil.h,v 1.3 2000/06/16 16:44:26 jlarmour Exp $ */ #ifndef _NETINET_IP_FIL_H__ diff --git a/packages/net/tcpip/current/include/netinet/ip_fil_compat.h b/packages/net/tcpip/current/include/netinet/ip_fil_compat.h --- a/packages/net/tcpip/current/include/netinet/ip_fil_compat.h +++ b/packages/net/tcpip/current/include/netinet/ip_fil_compat.h @@ -62,7 +62,6 @@ * to the original author and the contributors. * * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_fil_compat.h,v 1.3 2000/06/16 16:44:26 jlarmour Exp $ */ #ifndef _NETINET_IP_COMPAT_H__ diff --git a/packages/net/tcpip/current/include/netinet/ip_frag.h b/packages/net/tcpip/current/include/netinet/ip_frag.h --- a/packages/net/tcpip/current/include/netinet/ip_frag.h +++ b/packages/net/tcpip/current/include/netinet/ip_frag.h @@ -62,7 +62,6 @@ * to the original author and the contributors. * * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 1.3 2000/06/16 16:44:26 jlarmour Exp $ */ #ifndef _NETINET_IP_FRAG_H__ diff --git a/packages/net/tcpip/current/include/netinet/ip_nat.h b/packages/net/tcpip/current/include/netinet/ip_nat.h --- a/packages/net/tcpip/current/include/netinet/ip_nat.h +++ b/packages/net/tcpip/current/include/netinet/ip_nat.h @@ -62,7 +62,6 @@ * to the original author and the contributors. * * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 1.3 2000/06/16 16:44:26 jlarmour Exp $ */ #ifndef _NETINET_IP_NAT_H__ diff --git a/packages/net/tcpip/current/include/netinet/ip_proxy.h b/packages/net/tcpip/current/include/netinet/ip_proxy.h --- a/packages/net/tcpip/current/include/netinet/ip_proxy.h +++ b/packages/net/tcpip/current/include/netinet/ip_proxy.h @@ -61,7 +61,6 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * $Id: ip_proxy.h,v 1.3 2000/06/16 16:44:26 jlarmour Exp $ */ #ifndef _NETINET_IP_PROXY_H__ diff --git a/packages/net/tcpip/current/include/netinet/ip_state.h b/packages/net/tcpip/current/include/netinet/ip_state.h --- a/packages/net/tcpip/current/include/netinet/ip_state.h +++ b/packages/net/tcpip/current/include/netinet/ip_state.h @@ -62,7 +62,6 @@ * to the original author and the contributors. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * $Id: ip_state.h,v 1.3 2000/06/16 16:44:26 jlarmour Exp $ */ #ifndef _NETINET_IP_STATE_H__ diff --git a/packages/net/tcpip/current/include/sys/param.h b/packages/net/tcpip/current/include/sys/param.h --- a/packages/net/tcpip/current/include/sys/param.h +++ b/packages/net/tcpip/current/include/sys/param.h @@ -264,8 +264,12 @@ /* Macros for min/max. */ #ifndef _KERNEL -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) +# ifndef MIN +# define MIN(a,b) (((a)<(b))?(a):(b)) +# endif +# ifndef MAX +# define MAX(a,b) (((a)>(b))?(a):(b)) +# endif #endif #ifndef __ECOS diff --git a/packages/net/tcpip/current/src/ecos/support.c b/packages/net/tcpip/current/src/ecos/support.c --- a/packages/net/tcpip/current/src/ecos/support.c +++ b/packages/net/tcpip/current/src/ecos/support.c @@ -65,10 +65,14 @@ #include +#include + #include #include #include +#include + #include // Used for system-wide "ticks per second" @@ -249,6 +253,9 @@ cyg_net_mbuf_alloc(int type, int flags) res = cyg_mempool_fix_alloc(net_mbufs); } FINISH_STATS(stats_mbuf_alloc); + // Check that this nastiness works OK + CYG_ASSERT( dtom(res) == res, "dtom failed, base of mbuf" ); + CYG_ASSERT( dtom((char *)res + MSIZE/2) == res, "dtom failed, mid mbuf" ); return (res); } @@ -274,6 +281,7 @@ cyg_net_cluster_alloc(void) static void cyg_kmem_init(void) { + unsigned char *p; diag_printf("Network stack using %d bytes for misc space\n", NET_MEMPOOL_SIZE); diag_printf(" %d bytes for mbufs\n", NET_MBUFS_SIZE); diag_printf(" %d bytes for mbuf clusters\n", NET_CLUSTERS_SIZE); @@ -281,8 +289,10 @@ cyg_kmem_init(void) NET_MEMPOOL_SIZE, &net_mem, &net_mem_pool); - cyg_mempool_fix_create(&net_mbufs_area, - NET_MBUFS_SIZE, + // Align the mbufs on MSIZE boudaries so that dtom() can work. + p = (unsigned char *)(((long)(&net_mbufs_area) + MSIZE - 1) & ~(MSIZE-1)); + cyg_mempool_fix_create(p, + ((&(net_mbufs_area[NET_MBUFS_SIZE])) - p) & ~(MSIZE-1), MSIZE, &net_mbufs, &net_mbufs_pool); @@ -568,6 +578,8 @@ cyg_netint(cyg_addrword_t param) // extern void cyg_do_net_init(void); // Linker magic to execute this function as 'init' extern void ifinit(void); +extern void loopattach(int); + void cyg_net_init(void) { @@ -604,6 +616,12 @@ cyg_net_init(void) t->status = 0; // Device not [currently] available } } + // And attack the loopback interface +#ifdef CYGPKG_NET_NLOOP +#if 0 < CYGPKG_NET_NLOOP + loopattach(0); +#endif +#endif // Start up the network processing ifinit(); domaininit(); diff --git a/packages/net/tcpip/current/src/lib/network_support.c b/packages/net/tcpip/current/src/lib/network_support.c --- a/packages/net/tcpip/current/src/lib/network_support.c +++ b/packages/net/tcpip/current/src/lib/network_support.c @@ -42,7 +42,7 @@ //#####DESCRIPTIONBEGIN#### // // Author(s): gthomas -// Contributors: gthomas +// Contributors: gthomas, sorin@netappi.com ("Sorin Babeanu"), hmt // Date: 2000-01-10 // Purpose: // Description: @@ -70,6 +70,8 @@ #include #include +#include // for 'sprintf()' + #include #include #include @@ -88,6 +90,97 @@ const char *eth1_name = "eth1"; #define _string(s) #s #define string(s) _string(s) + +#ifdef CYGPKG_NET_NLOOP +#if 0 < CYGPKG_NET_NLOOP +// +// Initialize loopback interface ---------- Added by sorin@netappi.com +// +cyg_bool_t init_loopback_interface(int lo) +{ + struct sockaddr_in *addrp; + struct ifreq ifr; + int s; + int one = 1; + struct ecos_rtentry route; + struct in_addr netmask, gateway; + + //diag_printf("Init_loopback_interface\n"); + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + perror("socket"); + return false; + } + if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) { + perror("setsockopt"); + return false; + } + + addrp = (struct sockaddr_in *) &ifr.ifr_addr; + memset(addrp, 0, sizeof(*addrp)); + addrp->sin_family = AF_INET; + addrp->sin_len = sizeof(*addrp); + addrp->sin_port = 0; + // Make an address 127.0..1 to manage multiple loopback ifs. + // (There is normally only 1, so it's the standard 127.0.0.1) + addrp->sin_addr.s_addr = htonl((0x100 * lo) + INADDR_LOOPBACK) ; + + // Init the one we were told to + sprintf(ifr.ifr_name, "lo%d", lo); + + if (ioctl(s, SIOCSIFADDR, &ifr)) { + perror("SIOCIFADDR"); + return false; + } + +#if 1 < CYGPKG_NET_NLOOP + // We cheat to make different nets for multiple loopback devs + addrp->sin_addr.s_addr = netmask.s_addr = htonl(IN_CLASSC_NET); +#else + // + addrp->sin_addr.s_addr = netmask.s_addr = htonl(IN_CLASSA_NET); +#endif + if (ioctl(s, SIOCSIFNETMASK, &ifr)) { + perror("SIOCSIFNETMASK"); + return false; + } + ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; + if (ioctl(s, SIOCSIFFLAGS, &ifr)) { + perror("SIOCSIFFLAGS"); + return false; + } + + gateway.s_addr = htonl(INADDR_LOOPBACK); + memset(&route, 0, sizeof(route)); + addrp->sin_family = AF_INET; + addrp->sin_port = 0; + addrp->sin_addr.s_addr = htonl((0x100 * lo) + INADDR_LOOPBACK) & netmask.s_addr; + memcpy(&route.rt_dst, addrp, sizeof(*addrp)); + addrp->sin_addr = netmask; + memcpy(&route.rt_genmask, addrp, sizeof(*addrp)); + addrp->sin_addr = gateway; + memcpy(&route.rt_gateway, addrp, sizeof(*addrp)); + + route.rt_dev = ifr.ifr_name; + route.rt_flags = RTF_UP|RTF_GATEWAY; + route.rt_metric = 0; + + if (ioctl(s, SIOCADDRT, &route)) { + diag_printf("Route - dst: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_dst)->sin_addr)); + diag_printf(", mask: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_genmask)->sin_addr)); + diag_printf(", gateway: %s\n", inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); + if (errno != EEXIST) { + perror("SIOCADDRT 3"); + return false; + } + } + close(s); + return true; +} +#endif +#endif + + #if defined(CYGHWR_NET_DRIVER_ETH0_ADDRS_IP) \ || defined(CYGHWR_NET_DRIVER_ETH1_ADDRS_IP) // @@ -152,6 +245,18 @@ build_bootp_record(struct bootp *bp, void init_all_network_interfaces(void) { + static volatile int in_init_all_network_interfaces = 0; + + cyg_scheduler_lock(); + while ( in_init_all_network_interfaces ) { + // Another thread is doing this... + cyg_scheduler_unlock(); + cyg_thread_delay( 10 ); + cyg_scheduler_lock(); + } + in_init_all_network_interfaces = 1; + cyg_scheduler_unlock(); + #ifdef CYGHWR_NET_DRIVER_ETH0 if ( ! eth0_up ) { // Make this call idempotent #ifdef CYGHWR_NET_DRIVER_ETH0_BOOTP @@ -222,4 +327,19 @@ init_all_network_interfaces(void) } #endif #endif + +#ifdef CYGPKG_NET_NLOOP +#if 0 < CYGPKG_NET_NLOOP + { + static int loop_init = 0; + int i; + if ( 0 == loop_init++ ) + for ( i = 0; i < CYGPKG_NET_NLOOP; i++ ) + init_loopback_interface( i ); + } +#endif +#endif + + // Open the monitor to other threads. + in_init_all_network_interfaces = 0; } diff --git a/packages/net/tcpip/current/tests/ping_lo_test.c b/packages/net/tcpip/current/tests/ping_lo_test.c new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/tests/ping_lo_test.c @@ -0,0 +1,258 @@ +//========================================================================== +// +// tests/ping_lo_test.c +// +// Simple test of PING (ICMP) and networking support +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas, sorin@netappi.com +// Contributors: gthomas, sorin@netappi.com +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// PING test code + +#include + +#include + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +static char stack[STACK_SIZE]; +static cyg_thread thread_data; +static cyg_handle_t thread_handle; + +#define NUM_PINGS 16 +#define MAX_PACKET 4096 +static unsigned char pkt1[MAX_PACKET], pkt2[MAX_PACKET]; + +#define UNIQUEID 0x1234 + +void +pexit(char *s) +{ + CYG_TEST_FAIL_FINISH( s ); +} + +// Compute INET checksum +int +inet_cksum(u_short *addr, int len) +{ + register int nleft = len; + register u_short *w = addr; + register u_short answer; + register u_int sum = 0; + u_short odd_byte = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), + * we add sequential 16 bit words to it, and at the end, fold + * back all the carry bits from the top 16 bits into the lower + * 16 bits. + */ + while( nleft > 1 ) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if( nleft == 1 ) { + *(u_char *)(&odd_byte) = *(u_char *)w; + sum += odd_byte; + } + + /* + * add back carry outs from top 16 bits to low 16 bits + */ + sum = (sum >> 16) + (sum & 0x0000ffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} + +static int +show_icmp(unsigned char *pkt, int len, + struct sockaddr_in *from, struct sockaddr_in *to) +{ + cyg_tick_count_t *tp, tv; + struct ip *ip; + struct icmp *icmp; + tv = cyg_current_time(); + ip = (struct ip *)pkt; + if ((len < sizeof(*ip)) || ip->ip_v != IPVERSION) { + diag_printf("%s: Short packet or not IP! - Len: %d, Version: %d\n", + inet_ntoa(from->sin_addr), len, ip->ip_v); + return 0; + } + icmp = (struct icmp *)(pkt + sizeof(*ip)); + len -= (sizeof(*ip) + 8); + tp = (cyg_tick_count_t *)&icmp->icmp_data; + if (icmp->icmp_type != ICMP_ECHOREPLY) { + diag_printf("%s: Invalid ICMP - type: %d\n", + inet_ntoa(from->sin_addr), icmp->icmp_type); + return 0; + } + if (icmp->icmp_id != UNIQUEID) { + diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n", + inet_ntoa(from->sin_addr), UNIQUEID, icmp->icmp_id); + } + diag_printf("%d bytes from %s: ", len, inet_ntoa(from->sin_addr)); + diag_printf("icmp_seq=%d", icmp->icmp_seq); + diag_printf(", time=%dms\n", (int)(tv - *tp)*10); + return (from->sin_addr.s_addr == to->sin_addr.s_addr); +} + +static void +ping_host(int s, struct sockaddr_in *host) +{ + struct icmp *icmp = (struct icmp *)pkt1; + int icmp_len = 64; + int seq, ok_recv, bogus_recv; + cyg_tick_count_t *tp; + long *dp; + struct sockaddr_in from; + int i, len, fromlen; + + ok_recv = 0; + bogus_recv = 0; + diag_printf("PING server %s\n", inet_ntoa(host->sin_addr)); + for (seq = 0; seq < NUM_PINGS; seq++) { + // Build ICMP packet + icmp->icmp_type = ICMP_ECHO; + icmp->icmp_code = 0; + icmp->icmp_cksum = 0; + icmp->icmp_seq = seq; + icmp->icmp_id = 0x1234; + // Set up ping data + tp = (cyg_tick_count_t *)&icmp->icmp_data; + *tp++ = cyg_current_time(); + dp = (long *)tp; + for (i = sizeof(*tp); i < icmp_len; i += sizeof(*dp)) { + *dp++ = i; + } + // Add checksum + icmp->icmp_cksum = inet_cksum( (u_short *)icmp, icmp_len+8); + // Send it off + if (sendto(s, icmp, icmp_len+8, 0, (struct sockaddr *)host, sizeof(*host)) < 0) { + perror("sendto"); + continue; + } + // Wait for a response + fromlen = sizeof(from); + len = recvfrom(s, pkt2, sizeof(pkt2), 0, (struct sockaddr *)&from, &fromlen); + if (len < 0) { + perror("recvfrom"); + } else { + if (show_icmp(pkt2, len, &from, host)) { + ok_recv++; + } else { + bogus_recv++; + } + } + } + diag_printf("Sent %d packets, received %d OK, %d bad\n", NUM_PINGS, ok_recv, bogus_recv); +} + +static void +ping_test_loopback( int lo ) +{ + struct protoent *p; + struct timeval tv; + struct sockaddr_in host; + int s; + + if ((p = getprotobyname("icmp")) == (struct protoent *)0) { + perror("getprotobyname"); + return; + } + s = socket(AF_INET, SOCK_RAW, p->p_proto); + if (s < 0) { + perror("socket"); + return; + } + tv.tv_sec = 1; + tv.tv_usec = 0; + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + // Set up host address + host.sin_family = AF_INET; + host.sin_addr.s_addr = htonl(INADDR_LOOPBACK + (0x100 * lo)); + host.sin_port = 0; + ping_host(s, &host); + // Now try a bogus host + host.sin_addr.s_addr = htonl(ntohl(host.sin_addr.s_addr) + 32); + ping_host(s, &host); +} + +void +net_test(cyg_addrword_t p) +{ + int i; + diag_printf("Start PING test\n"); + init_all_network_interfaces(); +#if NLOOP > 0 + for ( i = 0; i < NLOOP; i++ ) + ping_test_loopback( i ); + for ( i = 0; i < NLOOP; i++ ) + ping_test_loopback( i ); + CYG_TEST_PASS_FINISH( "Done pinging loopback" ); +#endif + CYG_TEST_NA( "No loopback devs" ); +} + +void +cyg_start(void) +{ + // Create a main thread, so we can run the scheduler and have time 'pass' + cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY-4,// Priority - just a number + net_test, // entry + 0, // entry parameter + "Loopback ping test", // Name + &stack[0], // Stack + STACK_SIZE, // Size + &thread_handle, // Handle + &thread_data // Thread data structure + ); + cyg_thread_resume(thread_handle); // Start it + cyg_scheduler_start(); +} diff --git a/packages/net/tcpip/current/tests/tcp_lo_select.c b/packages/net/tcpip/current/tests/tcp_lo_select.c new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/tests/tcp_lo_select.c @@ -0,0 +1,304 @@ +//========================================================================== +// +// tests/tcp_lo_test.c +// +// Simple TCP throughput test +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): sorin@netappi.com +// Contributors: gthomas,sorin@netappi.com +// Date: 2000-05-24 + + +// Network throughput test code + +#include + +#include + +#define SOURCE_PORT1 9990 +#define SOURCE_PORT2 9991 + +#define NUM_BUF 1024 +#define MAX_BUF 8192 +static unsigned char data_buf1[MAX_BUF]; +static unsigned char data_buf2[MAX_BUF]; +static unsigned char data_buf_write1[MAX_BUF]="Client 1 is alive. You may continue ...."; +static unsigned char data_buf_write2[MAX_BUF]="Client 2 is alive. You may continue ...."; + + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x10000) + +static char stack_server[STACK_SIZE]; +static cyg_thread server_thread_data; +static cyg_handle_t server_thread_handle; + +static char stack_client1[STACK_SIZE]; +static cyg_thread client1_thread_data; +static cyg_handle_t client1_thread_handle; + +static char stack_client2[STACK_SIZE]; +static cyg_thread client2_thread_data; +static cyg_handle_t client2_thread_handle; + + +#define MAIN_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-4 + +void +pexit(char *s) +{ + CYG_TEST_FAIL_FINISH( s ); +} + + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +void server(void) +{ + int s_s1, e_s1, s_s2, e_s2; + struct sockaddr_in e_s1_addr,e_s2_addr,local; + fd_set in_fds; + int len; + int num; + + char *hello_string=" Hello eCos network \n"; + diag_printf("TCP SERVER:"); + diag_printf(hello_string); + + s_s1 = socket(AF_INET, SOCK_STREAM, 0); + if (s_s1 < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_len = sizeof(local); + local.sin_port = ntohs(SOURCE_PORT1); + local.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if(bind(s_s1, (struct sockaddr *) &local, sizeof(local)) < 0) { + pexit("bind /source_1/ error"); + } + listen(s_s1, SOMAXCONN); + + s_s2 = socket(AF_INET, SOCK_STREAM, 0); + if (s_s2 < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_len = sizeof(local); + local.sin_port = ntohs(SOURCE_PORT2); + local.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if(bind(s_s2, (struct sockaddr *) &local, sizeof(local)) < 0) { + pexit("bind /source_2/ error"); + } + listen(s_s2, SOMAXCONN); + + + e_s1 = 0; e_s2 = 0; + + + while (true) { + FD_ZERO(&in_fds); + FD_SET(s_s1, &in_fds); + FD_SET(s_s2, &in_fds); + num = select ( max(s_s1,s_s2)+1, &in_fds,0,0,0); + if (FD_ISSET(s_s1,&in_fds)) { + len = sizeof(e_s1_addr); + if ((e_s1 = accept(s_s1,(struct sockaddr *)&e_s1_addr,&len))<0) + { + pexit("accept /source_1/"); + } + diag_printf("TCP SERVER connection from %s: %d\n", + inet_ntoa(e_s1_addr.sin_addr),ntohs(e_s1_addr.sin_port)); + } + if (FD_ISSET(s_s2,&in_fds)) { + len = sizeof(e_s2_addr); + if ((e_s2 = accept(s_s2,(struct sockaddr *)&e_s2_addr,&len))<0) + { + pexit("accept /source_2/"); + } + diag_printf("TCP SERVER connection from %s: %d\n", + inet_ntoa(e_s2_addr.sin_addr), ntohs(e_s2_addr.sin_port)); + } + + if ((e_s1 != 0) && ( e_s2 != 0)) { + break; + } + + } /* while (true) */ + + if ((len = read(e_s1, data_buf1, MAX_BUF)) < 0 ) + { + perror("I/O error"); + } + diag_printf("SERVER : %s\n",data_buf1); + + if ((len = read(e_s2, data_buf2, MAX_BUF)) < 0 ) + { + perror("I/O error"); + } + diag_printf("SERVER : %s\n",data_buf2); + +} + +void client1(void) +{ + int s_source; + struct sockaddr_in local; + int len; + + diag_printf("client 1 :started\n"); + + s_source = socket(AF_INET, SOCK_STREAM, 0); + if (s_source < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_port = htons(SOURCE_PORT1); + local.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (connect(s_source, (struct sockaddr *)&local, sizeof(local)) < 0) { + pexit("Can't connect to target"); + } + + if ((len = write(s_source,data_buf_write1,40)) < 0) { + CYG_TEST_FAIL_FINISH("Error writing buffer"); + } +} + +void client2(void) +{ + int s_source; + struct sockaddr_in local; + int len; + + diag_printf("client 2 :started\n"); + + s_source = socket(AF_INET, SOCK_STREAM, 0); + if (s_source < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_port = htons(SOURCE_PORT2); + local.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (connect(s_source, (struct sockaddr *)&local, sizeof(local)) < 0) { + pexit("Can't connect to target"); + } + + if ((len = write(s_source,data_buf_write2,40)) < 0) { + CYG_TEST_FAIL_FINISH("Error writing buffer"); + } +} + + +void +tcp_server(cyg_addrword_t param) +{ + init_all_network_interfaces(); + diag_printf("Start TCP server - test\n"); + cyg_thread_resume(client1_thread_handle); // Start it + cyg_thread_resume(client2_thread_handle); // Start it +#if NLOOP > 0 + server(); + CYG_TEST_PASS_FINISH("Server returned OK"); +#endif + CYG_TEST_NA( "No loopback devs" ); +} + +void +tcp_client_1(cyg_addrword_t param) +{ + diag_printf("Start TCP client 1 - test\n"); +#if NLOOP > 0 + client1(); +#endif +} + +void +tcp_client_2(cyg_addrword_t param) +{ + diag_printf("Start TCP client 2 - test\n"); +#if NLOOP > 0 + client2(); +#endif +} + + +void +cyg_start(void) +{ + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + tcp_server, // entry + 0, // entry parameter + "TCP loopback server", // Name + &stack_server[0], // Stack + STACK_SIZE, // Size + &server_thread_handle, // Handle + &server_thread_data // Thread data structure + ); + cyg_thread_resume(server_thread_handle); // Start it + + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + tcp_client_1, // entry + 0, // entry parameter + "TCP loopback client1", // Name + &stack_client1[0], // Stack + STACK_SIZE, // Size + &client1_thread_handle, // Handle + &client1_thread_data // Thread data structure + ); + + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + tcp_client_2, // entry + 0, // entry parameter + "TCP llopback client2", // Name + &stack_client2[0], // Stack + STACK_SIZE, // Size + &client2_thread_handle, // Handle + &client2_thread_data // Thread data structure + ); + + cyg_scheduler_start(); +} + diff --git a/packages/net/tcpip/current/tests/tcp_lo_test.c b/packages/net/tcpip/current/tests/tcp_lo_test.c new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/tests/tcp_lo_test.c @@ -0,0 +1,213 @@ +//========================================================================== +// +// tests/tcp_lo_test.c +// +// Simple TCP throughput test +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): sorin@netappi.com +// Contributors: gthomas,sorin@netappi.com, hmt +// Date: 2000-05-24 + + +// Network throughput test code + +#include + +#include + +#define SOURCE_PORT 9990 +#define SINK_PORT 9991 + +#define NUM_BUF 1024 +#define MAX_BUF 8192 +static unsigned char data_buf[MAX_BUF]; +static unsigned char data_buf_write[MAX_BUF]="Client is alive. You may continue ...."; + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x10000) +static char stack_server[STACK_SIZE]; +static cyg_thread server_thread_data; +static cyg_handle_t server_thread_handle; + +static char stack_client[STACK_SIZE]; +static cyg_thread client_thread_data; +static cyg_handle_t client_thread_handle; + + +#define MAIN_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-4 + +void +pexit(char *s) +{ + CYG_TEST_FAIL_FINISH( s ); +} + + +void server(void) +{ + int s_source, e_source; + struct sockaddr_in e_source_addr, local; + int one = 1; + fd_set in_fds; + int len; + + char *hello_string=" Hello eCos network \n"; + diag_printf("TCP SERVER:"); + diag_printf(hello_string); + + s_source = socket(AF_INET, SOCK_STREAM, 0); + if (s_source < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_len = sizeof(local); + local.sin_port = ntohs(SOURCE_PORT); + local.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) { + pexit("bind /source/ error"); + } + if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { + pexit("setsockopt /source/ SO_REUSEADDR"); + } + if (setsockopt(s_source, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) { + pexit("setsockopt /source/ SO_REUSEPORT"); + } + listen(s_source, SOMAXCONN); + + e_source = 0; + while (true) { + FD_ZERO(&in_fds); + FD_SET(s_source, &in_fds); + if ((e_source = accept(s_source,(struct sockaddr *)&e_source_addr,&len))<0) { + pexit("accept /source/"); + } + diag_printf("TCP SERVER connection from %s: %d\n", + inet_ntoa(e_source_addr.sin_addr),ntohs(e_source_addr.sin_port)); + + if (e_source != 0) { + break; + } + } /* while (true) */ + + if ((len = read(e_source, data_buf, MAX_BUF)) < 0 ) { + CYG_TEST_FAIL_FINISH( "I/O error" ); + } + diag_printf("SERVER : %s\n",data_buf); + +} + +void client(void) +{ + int s_source; + struct sockaddr_in local; + int len; + + diag_printf("client:started\n"); + + s_source = socket(AF_INET, SOCK_STREAM, 0); + if (s_source < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_port = htons(SOURCE_PORT); + local.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (connect(s_source, (struct sockaddr *)&local, sizeof(local)) < 0) { + pexit("Can't connect to target"); + } + + if ((len = write(s_source,data_buf_write,40)) < 0){ + CYG_TEST_FAIL_FINISH( "Error writing buffer"); + } +} + +void +tcp_server(cyg_addrword_t param) +{ + init_all_network_interfaces(); + diag_printf("Start TCP server - test\n"); + cyg_thread_resume(client_thread_handle); // Start it +#if NLOOP > 0 + server(); + CYG_TEST_PASS_FINISH( "server returned OK" ); +#endif + CYG_TEST_NA( "No loopback devs" ); +} + +void +tcp_client(cyg_addrword_t param) +{ + diag_printf("Start TCP client - test\n"); +#if NLOOP > 0 + client(); +#endif +} + + + +void +cyg_start(void) +{ + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + tcp_server, // entry + 0, // entry parameter + "TCP loopback server", // Name + &stack_server[0], // Stack + STACK_SIZE, // Size + &server_thread_handle, // Handle + &server_thread_data // Thread data structure + ); + cyg_thread_resume(server_thread_handle); // Start it + + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + tcp_client, // entry + 0, // entry parameter + "TCP loopback client", // Name + &stack_client[0], // Stack + STACK_SIZE, // Size + &client_thread_handle, // Handle + &client_thread_data // Thread data structure + ); + cyg_scheduler_start(); +} + + + diff --git a/packages/net/tcpip/current/tests/udp_lo_test.c b/packages/net/tcpip/current/tests/udp_lo_test.c new file mode 100644 --- /dev/null +++ b/packages/net/tcpip/current/tests/udp_lo_test.c @@ -0,0 +1,188 @@ +//========================================================================== +// +// tests/udp_lo_test.c +// +// Simple UDP throughput test +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): sorin@netappi.com +// Contributors: gthomas,sorin@netappi.com, hmt +// Date: 2000-05-24 + + +// Network throughput test code + +#include + +#include + +#define SOURCE_PORT 9990 +#define SINK_PORT 9991 + +#define NUM_BUF 1024 +#define MAX_BUF 8192 +static unsigned char data_buf[MAX_BUF]; +static unsigned char data_buf_write[MAX_BUF]="Client UDP is alive. You may continue ...."; + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x10000) +static char stack_server[STACK_SIZE]; +static cyg_thread server_thread_data; +static cyg_handle_t server_thread_handle; + +static char stack_client[STACK_SIZE]; +static cyg_thread client_thread_data; +static cyg_handle_t client_thread_handle; + + +#define MAIN_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-4 + +void +pexit(char *s) +{ + CYG_TEST_FAIL_FINISH( s ); +} + + +void server(void) +{ + int s_source; + struct sockaddr_in local,c_addr; + int c_len; + int len; + + char *hello_string=" Hello eCos network \n"; + diag_printf("UDP SERVER:"); + diag_printf(hello_string); + + s_source = socket(AF_INET, SOCK_DGRAM, 0); + if (s_source < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_len = sizeof(local); + local.sin_port = ntohs(SOURCE_PORT); + local.sin_addr.s_addr = htonl(INADDR_ANY); //accepts everyone... + if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) { + pexit("bind /source/ error"); + } + c_len = sizeof(c_addr); + + if ((len = recvfrom(s_source, data_buf, sizeof(data_buf),0, + (struct sockaddr *)&c_addr,&c_len)) < 0 ) { + CYG_TEST_FAIL_FINISH("I/O error"); + } + diag_printf("SERVER : message arrived from %s\n",inet_ntoa(c_addr.sin_addr)); + diag_printf("SERVER : Message : %s\n",data_buf); + close(s_source); +} + +void client(void) +{ + int s_source; + struct sockaddr_in local; + int len; + + diag_printf("client:started\n"); + + s_source = socket(AF_INET, SOCK_DGRAM, 0); + if (s_source < 0) { + pexit("stream socket"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_port = htons(SOURCE_PORT); + local.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if ( (len= sendto(s_source,data_buf_write,sizeof(data_buf_write), + 0,(struct sockaddr *)&local,sizeof(local))) < 0 ) { + CYG_TEST_FAIL_FINISH("Error writing buffer"); + } + close(s_source); +} + +void +udp_server(cyg_addrword_t param) +{ + init_all_network_interfaces(); + diag_printf("Start UDP server - test\n"); + cyg_thread_resume(client_thread_handle); // Start the other one +#if NLOOP > 0 + server(); + CYG_TEST_PASS_FINISH("Server returned OK"); +#endif + CYG_TEST_NA( "No loopback devs" ); +} + +void +udp_client(cyg_addrword_t param) +{ + diag_printf("Start UDP client - test\n"); +#if NLOOP > 0 + client(); +#endif +} + + + +void +cyg_start(void) +{ + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + udp_server, // entry + 0, // entry parameter + "UDP loopback server", // Name + &stack_server[0], // Stack + STACK_SIZE, // Size + &server_thread_handle, // Handle + &server_thread_data // Thread data structure + ); + cyg_thread_resume(server_thread_handle); // Start it + + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + udp_client, // entry + 0, // entry parameter + "UDP loopback client", // Name + &stack_client[0], // Stack + STACK_SIZE, // Size + &client_thread_handle, // Handle + &client_thread_data // Thread data structure + ); + cyg_scheduler_start(); +} +