~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to agent/mibgroup/winExtDLL.c

  • Committer: Bazaar Package Importer
  • Author(s): Jochen Friedrich
  • Date: 2010-06-10 18:02:54 UTC
  • mto: (1.4.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 44.
  • Revision ID: james.westby@ubuntu.com-20100610180254-6ezvupl2clicwdqf
ImportĀ upstreamĀ versionĀ 5.4.3~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  winExtDLL Net-SNMP extension
3
 
 *  (c) 2006 Alex Burger
4
 
 *
5
 
 *  Created 9/9/06
6
 
 *
7
 
 * Purpose:  To load Windows SNMP Service extension DLLs provided with Windows
8
 
 *           (such as hostmib.dll).  This allows Net-SNMP to be a replacement 
9
 
 *           for the Windows SNMP service.
10
 
 *
11
 
 * Notes:    This extension requires the PSDK including the Snmp.h header file.
12
 
 *           Including Snmp.h will conflict with existing Net-SNMP defines for
13
 
 *           ASN_OCTETSTRING etc.  To resolve this, create a copy of Snmp.h in
14
 
 *           the PSDK include/ folder called Snmp-winExtDLL.h and change all
15
 
 *           occurances of ASN_ to MS_ASN_
16
 
 *
17
 
 *           This extension requires that the Windows SNMP Service is installed
18
 
 *           but set to disabled.  This is required so that the extension DLLs 
19
 
 *           are available for loading, and also because this extension and the 
20
 
 *           existing Windows extensions use the Windows SNMP API from snmpapi.dll.
21
 
 *
22
 
 *           This extension is NOT for dynamically loading Net-SNMP extensions.
23
 
 */
24
 
 
25
 
#include <windows.h>
26
 
#include <cstdio>
27
 
#include <Snmp-winExtDLL.h>                  // Modified Windows SDK snmp.h.  See Notes above
28
 
#include <mgmtapi.h>
29
 
#include <string.h>
30
 
 
31
 
/*
32
 
 * include important headers 
33
 
 */
 
1
/**
 
2
 * @brief winExtDLL Net-SNMP agent extension module.
 
3
 *
 
4
 * Copyright (c) 2006-2009 Alex Burger.
 
5
 * Copyright (c) 2009-2010 Bart Van Assche <bart.vanassche@gmail.com>.
 
6
 *
 
7
 * This Net-SNMP agent extension module loads Windows SNMP Extension Agent
 
8
 * DLLs in the Net-SNMP agent. Not only extension DLLs provided with Windows
 
9
 * (e.g. hostmib.dll) but also third-party extension DLLs are supported. This
 
10
 * allows Net-SNMP to be a replacement for the Windows SNMP service, and makes
 
11
 * it possible to use the SNMPv3 protocol.
 
12
 *
 
13
 * @see See also <a href="http://msdn.microsoft.com/en-us/library/aa378988(VS.85).aspx">SNMP Functions</a>
 
14
 *   for more information about Microsoft's SNMP Extension Agent API.
 
15
 *
 
16
 * @note In order to use this agent extension module, the Windows SNMP service
 
17
 *   must be installed first and must be disabled. Installing the Windows SNMP
 
18
 *   service is the only way to install the Windows Extension DLLs and to make
 
19
 *   sure that information about these DLLs is present in the registry.
 
20
 *
 
21
 * @note All Windows extension DLLs are loaded during startup of the Net-SNMP
 
22
 *   service. The Net-SNMP service must be restarted to load new modules. This
 
23
 *   extension is NOT for dynamically loading Net-SNMP extensions.
 
24
 *
 
25
 *
 
26
 * History:
 
27
 * - 2010/03/19:
 
28
 *    * Multi-varbind set request PDUs are now handled correctly.
 
29
 *    * If loading an extension DLL fails, the reason why this failed is now
 
30
 *      logged.
 
31
 *    * Fixed a memory leak that occurred when SnmpExtensionQuery() or
 
32
 *      SnmpExtensionQueryEx() failed while processing an SNMP PDU. Note:
 
33
 *      occurrence of an SNMP error does not make these functions fail, and
 
34
 *      it is not yet known whether or not it was possible to trigger this
 
35
 *      memory leak.
 
36
 * - 2010/03/17: Fixed bug 2971257. Multi-varbind getNext requests with OIDs
 
37
 *     in reverse lexicographical order are again processed correctly.
 
38
 * - 2010/01/22: Compiles now with MinGW too.
 
39
 * - 2009/12/11:
 
40
 *   * The value of sysUpTime.0 reported by inetmib1.dll is now correct.
 
41
 *   * A linkUp or linkDown trap is now sent after the status of a network
 
42
 *     interface has changed.
 
43
 * - 2009/03/26: 
 
44
 *   * Removed several artificial limits. Result: more than 100 SNMP extension
 
45
 *     DLLs can now be loaded simultaneously and more than 100 OID ranges can
 
46
 *     now be registered. Loading e.g. the Dell OpenManage SNMP extension DLL
 
47
 *     does no longer crash Net-SNMP. 
 
48
 *   * Number of OID ranges registered during startup is now logged.
 
49
 *   * It is no longer attempted to free the Broadcom SNMP extension DLLs
 
50
 *     bcmif.dll and baspmgnt.dll since doing so triggers a deadlock.
 
51
 *   * Added support for reregistration of an OID prefix. As an example, both
 
52
 *     both Microsoft's inetmib1.dll and the Eicon Diva divasnmpx.dll register
 
53
 *     the OID prefix iso.org.dod.internet.mgmt.mib-2.interfaces
 
54
 *     (.1.3.6.1.2.1.2). WinExtDLL will process OIDs with this prefix by using
 
55
 *     the handler that was registered last for the OID prefix. A message will
 
56
 *     be logged indicating that a handler has been replaced.
 
57
 * - 2009/03/10:
 
58
 *   * Fixed several bugs in var_winExtDLL(): looking up extension DLL info
 
59
 *     based on the OID in a varbind is wrong. It does happen during GetNext
 
60
 *     processing that Net-SNMP passes intentionally varbinds to a handler
 
61
 *     with OIDs that are outside the range registered by the handler. Fixed
 
62
 *     this by filling in a pointer to the extension DLL info in
 
63
 *     netsnmp_mib_handler::myvoid and by using that information in the
 
64
 *     var_winExtDLL() handler function.
 
65
 *   * SetRequest PDUs are now passed once to an extension DLL instead of
 
66
 *     four times.
 
67
 *   * The error status and error index of a multi-varbind set request is now
 
68
 *     filled in correctly.
 
69
 *   * Added support for the SNMP extension DLL three-phase SNMP set.
 
70
 *   * Made traps SNMPv2 compliant by adding the sysUpTime.0 varbind.
 
71
 *   * The varbind list generated by extension DLLs for e.g. linkUp and
 
72
 *     linkDown traps is now passed to Net-SNMP. Previously this varbind list
 
73
 *     was discarded for generic traps.
 
74
 *   * Fixed memory leaks triggered by Get and GetNext PDU processing.
 
75
 *   * Added missing RegCloseKey() calls.
 
76
 *   * Added shutdown function shutdown_winExtDLL().
 
77
 *   * Replaced #include <cstdio> by #include <stdio.h> such that this source
 
78
 *     file compiles with Visual Studio 2005.
 
79
 *   * Removed many unused local variables.
 
80
 *   * Fixed several other compiler warnings.
 
81
 * - 2006/09/09: creation of this file.
 
82
 */
 
83
 
34
84
#include <net-snmp/net-snmp-config.h>
35
 
#if HAVE_STDLIB_H
 
85
#include <net-snmp/agent/mib_module_config.h>
 
86
 
 
87
#ifdef USING_WINEXTDLL_MODULE
 
88
 
 
89
#include <net-snmp/types.h>
 
90
 
 
91
#include <assert.h>
 
92
#include <stdio.h>
36
93
#include <stdlib.h>
37
 
#endif
38
 
#if HAVE_STRING_H
39
94
#include <string.h>
40
 
#else
41
 
#include <strings.h>
42
 
#endif
43
 
 
44
 
/*
45
 
 * needed by util_funcs.h 
46
 
 */
47
 
#if TIME_WITH_SYS_TIME
48
 
# ifdef WIN32
49
 
#  include <sys/timeb.h>
50
 
# else
51
 
#  include <sys/time.h>
52
 
# endif
53
 
# include <time.h>
54
 
#else
55
 
# if HAVE_SYS_TIME_H
56
 
#  include <sys/time.h>
57
 
# else
58
 
#  include <time.h>
59
 
# endif
60
 
#endif
61
 
 
62
 
#if HAVE_WINSOCK_H
63
 
#include <winsock.h>
64
 
#endif
65
 
#if HAVE_NETINET_IN_H
66
 
#include <netinet/in.h>
67
 
#endif
 
95
#include <time.h>
 
96
#include <windows.h>
 
97
#include "../../win32/Snmp-winExtDLL.h"
 
98
#include "../../win32/MgmtApi-winExtDLL.h"
68
99
 
69
100
#include <net-snmp/net-snmp-includes.h>
70
101
#include <net-snmp/agent/net-snmp-agent-includes.h>
71
 
 
72
102
#include "util_funcs.h"
73
 
 
74
103
#include "winExtDLL.h"
75
104
 
76
 
#define SZBUF_MAX               1024
77
 
#define SZBUF_DLLNAME_MAX       254
78
 
#define MAX_WINEXT_DLLS         100
79
 
#define MAX_KEY_LENGTH          255
 
105
 
80
106
#define MAX_VALUE_NAME          16383
81
 
#define MAX_WINEXT_TRAP_EVENTS  100
82
 
 
83
 
#define DEBUGMSGWINOID(x)     do {if (_DBG_IF_) {__DBGMSGWINOID(x);} }while(0)
84
 
#define __DBGMSGWINOID(x)     debugmsg_win_oid x
85
 
void debugmsg_win_oid(const char *token, const AsnObjectIdentifier * theoid);
86
 
 
87
 
/* Structure to hold name, pointers to functions and MIB tree supported by
88
 
 * each Windows SNMP Extension DLL */
89
 
typedef struct {
90
 
  char          dll_name[SZBUF_DLLNAME_MAX];
91
 
  DWORD (WINAPI *xSnmpExtensionInit)(DWORD, HANDLE*, AsnObjectIdentifier*);
92
 
  DWORD (WINAPI *xSnmpExtensionInitEx)(AsnObjectIdentifier*);
93
 
  DWORD (WINAPI *xSnmpExtensionQuery)(BYTE, SnmpVarBindList* ,AsnInteger32* ,AsnInteger32*);
94
 
  DWORD (WINAPI *xSnmpExtensionQueryEx)(DWORD, DWORD, SnmpVarBindList*, AsnOctetString*, AsnInteger32*, AsnInteger32*);
95
 
  BOOL  (WINAPI *xSnmpExtensionTrap)( AsnObjectIdentifier *, AsnInteger *, AsnInteger *, AsnTimeticks *, SnmpVarBindList * );
96
 
  HANDLE        *subagentTrapEvent;
97
 
  netsnmp_handler_registration *my_handler;
98
 
  oid           name[MAX_OID_LEN];              //   pSupportedView in Net-SNMP format
99
 
  size_t        name_length;
100
 
  AsnObjectIdentifier pSupportedView;
101
 
} winExtensionAgents;
102
 
 
103
 
winExtensionAgents winExtensionAgent[MAX_WINEXT_DLLS];
104
 
winExtensionAgents winExtensionAgent_temp;      /* For sorting */
105
 
int winExtensionAgent_index = 0;
106
 
 
107
 
char *extDLLs[MAX_WINEXT_DLLS];
108
 
int extDLLs_index = 0;
109
 
 
110
 
HANDLE *subagentTrapEvents[MAX_WINEXT_TRAP_EVENTS];
111
 
int subagentTrapEvents_index = 0;
112
 
 
113
 
void winExtDLL_free_config_winExtDLL(void);
114
 
 
115
 
void read_ExtensionAgents_list();
116
 
void read_ExtensionAgents_list2(const TCHAR *);
117
 
 
118
 
void subagentTrapCheck();
119
 
 
120
 
void send_trap(
121
 
    AsnObjectIdentifier *, 
122
 
    AsnInteger *, 
123
 
    AsnInteger *, 
124
 
    AsnTimeticks *,    
125
 
    SnmpVarBindList *);
126
 
 
127
 
void init_winExtDLL(void)
128
 
{
129
 
  // Windows SNMP
130
 
  DWORD dwUptimeReference = 0;
131
 
  HANDLE subagentTrapEvent;
132
 
  AsnObjectIdentifier pSupportedView;
133
 
  BOOL result;
134
 
  HANDLE hThread;
135
 
  DWORD IDThread;
136
 
 
137
 
  char dll_name[SZBUF_DLLNAME_MAX];
138
 
  DWORD (WINAPI *xSnmpExtensionInit)(DWORD, HANDLE*, AsnObjectIdentifier*);
139
 
  DWORD (WINAPI *xSnmpExtensionInitEx)(AsnObjectIdentifier*);
140
 
  DWORD (WINAPI *xSnmpExtensionQuery)(BYTE, SnmpVarBindList* ,AsnInteger32* ,AsnInteger32*);
141
 
  DWORD (WINAPI *xSnmpExtensionQueryEx)(DWORD, DWORD, SnmpVarBindList*, AsnOctetString*, AsnInteger32*, AsnInteger32*);
142
 
  BOOL  (WINAPI *xSnmpExtensionTrap)( AsnObjectIdentifier *, AsnInteger *, AsnInteger *, AsnTimeticks *, SnmpVarBindList * );
143
 
 
144
 
  // Net-SNMP
145
 
  oid name[MAX_OID_LEN];
146
 
  size_t length = 0;
147
 
  int i;
148
 
  int DLLnum = 0;
149
 
  int winExtensionAgent_num = 0;
150
 
  
151
 
  int iter, indx;
152
 
  
153
 
  netsnmp_handler_registration *my_handler;
154
 
 
155
 
  HANDLE hInst = NULL;
156
 
 
157
 
  DEBUGMSGTL(("winExtDLL", "init_winExtDLL called\n"));
158
 
 
159
 
  read_ExtensionAgents_list();  
160
 
  
161
 
  DEBUGMSGTL(("winExtDLL", "winExtDLL enabled.\n"));   
162
 
  
163
 
  DEBUGMSGTL(("winExtDLL", "Size of winExtensionAgent: %d\n",sizeof(winExtensionAgent) / sizeof(winExtensionAgents)));
164
 
 
165
 
  for(i=0; i <= sizeof(winExtensionAgent) / sizeof(winExtensionAgents); i++) {
166
 
    winExtensionAgent[0].xSnmpExtensionInit = NULL;
167
 
    winExtensionAgent[0].xSnmpExtensionInitEx = NULL;
168
 
  }
169
 
 
170
 
  /* Load all the DLLs */
171
 
  for (DLLnum = 0; DLLnum <= extDLLs_index; DLLnum++) {
172
 
 
173
 
    if (! (extDLLs[DLLnum]))
174
 
      continue;
175
 
 
176
 
    DEBUGMSGTL(("winExtDLL", "-----------------------------------------\n"));
177
 
    DEBUGMSGTL(("winExtDLL", "DLL to load: %s, DLL number: %d, winExtensionAgent_num: %d\n", extDLLs[DLLnum], DLLnum,
178
 
          winExtensionAgent_num));
179
 
    DEBUGMSGTL(("winExtDLL", "Size of DLL to load: %d\n", strlen(extDLLs[DLLnum])));
180
 
    
181
 
    hInst = LoadLibrary(extDLLs[DLLnum]);
182
 
    
183
 
    if (hInst == NULL)
184
 
    {
185
 
      DEBUGMSGTL(("winExtDLL","Could not load Windows extension DLL %s.\n", extDLLs[DLLnum]));
186
 
      snmp_log(LOG_ERR,
187
 
          "Could not load Windows extension DLL: %s.\n", extDLLs[DLLnum]);
188
 
      continue;
189
 
    }
190
 
    else {
191
 
      DEBUGMSGTL(("winExtDLL","DLL loaded.\n"));
192
 
    }
193
 
 
194
 
    // Create local copy of DLL name and functions
195
 
    strncpy(dll_name, extDLLs[DLLnum], SZBUF_DLLNAME_MAX-1);
196
 
    xSnmpExtensionInit = (DWORD (WINAPI *)(DWORD, HANDLE*, AsnObjectIdentifier*)) 
197
 
      GetProcAddress ((HMODULE) hInst, "SnmpExtensionInit");
198
 
    xSnmpExtensionInitEx = (DWORD (WINAPI *)(AsnObjectIdentifier*)) 
199
 
      GetProcAddress ((HMODULE) hInst, "SnmpExtensionInitEx");
200
 
    xSnmpExtensionQuery = (DWORD (WINAPI *)(BYTE, SnmpVarBindList* ,AsnInteger32* ,AsnInteger32*)) 
201
 
      GetProcAddress ((HMODULE) hInst, "SnmpExtensionQuery");
202
 
    xSnmpExtensionQueryEx = (DWORD (WINAPI *)(DWORD, DWORD, SnmpVarBindList*, AsnOctetString*, AsnInteger32*, AsnInteger32*))
203
 
      GetProcAddress ((HMODULE) hInst, "SnmpExtensionQueryEx");
204
 
    xSnmpExtensionTrap = (BOOL  (WINAPI *)(AsnObjectIdentifier *, AsnInteger *, AsnInteger *, AsnTimeticks *, SnmpVarBindList * ))
205
 
      GetProcAddress ((HMODULE) hInst, "SnmpExtensionTrap");
206
 
 
207
 
    if (xSnmpExtensionQuery)
208
 
      DEBUGMSGTL(("winExtDLL", "xSnmpExtensionQuery found\n"));
209
 
    if (xSnmpExtensionQueryEx)
210
 
      DEBUGMSGTL(("winExtDLL", "xSnmpExtensionQueryEx found\n"));
211
 
    if (xSnmpExtensionQuery)
212
 
      DEBUGMSGTL(("winExtDLL", "xSnmpExtensionTrap found\n"));
213
 
 
214
 
    // Store DLL name and functions in winExtensionAgent array
215
 
    strncpy(winExtensionAgent[winExtensionAgent_num].dll_name, dll_name, SZBUF_DLLNAME_MAX-1);
216
 
    winExtensionAgent[winExtensionAgent_num].xSnmpExtensionInit = xSnmpExtensionInit;
217
 
    winExtensionAgent[winExtensionAgent_num].xSnmpExtensionInitEx = xSnmpExtensionInitEx;
218
 
    winExtensionAgent[winExtensionAgent_num].xSnmpExtensionQuery = xSnmpExtensionQuery;
219
 
    winExtensionAgent[winExtensionAgent_num].xSnmpExtensionQueryEx = xSnmpExtensionQueryEx;
220
 
    winExtensionAgent[winExtensionAgent_num].xSnmpExtensionTrap = xSnmpExtensionTrap;
221
 
 
222
 
    // Init and get first supported view from Windows SNMP extension DLL  
223
 
    result = xSnmpExtensionInit(dwUptimeReference, &subagentTrapEvent, &pSupportedView);
224
 
 
225
 
    DEBUGMSGTL(("winExtDLL", "Supported view: "));
226
 
    DEBUGMSGWINOID(("winExtDLL", &pSupportedView));
227
 
    DEBUGMSG(("winExtDLL", "\n"));
228
 
 
229
 
    // Store the subagent's trap handler, even if it's NULL
230
 
    winExtensionAgent[winExtensionAgent_num].subagentTrapEvent = subagentTrapEvent;
231
 
 
232
 
    // Store the subagent's trap handler in a global array for use by waitformultipleobjects()
233
 
    if (subagentTrapEvent) {
234
 
      DEBUGMSGTL(("winExtDLL", "Trap handler defined.  Storing...\n"));
235
 
      subagentTrapEvents[subagentTrapEvents_index] = subagentTrapEvent;
236
 
      subagentTrapEvents_index++;
237
 
    }
238
 
 
239
 
    // Convert OID from Windows 'supported view' to Net-SNMP
240
 
    for (i = 0; i < (pSupportedView.idLength > MAX_OID_LEN?MAX_OID_LEN:pSupportedView.idLength); i++) {
241
 
      name[i] = (oid)pSupportedView.ids[i];
242
 
    }
243
 
    length = i;
244
 
 
245
 
    // Store supported view in Net-SNMP format
246
 
    memcpy(winExtensionAgent[winExtensionAgent_num].name, name, sizeof(name));
247
 
    winExtensionAgent[winExtensionAgent_num].name_length = length;
248
 
 
249
 
    DEBUGMSGTL(("winExtDLL", "Windows OID converted to Net-SNMP: "));
250
 
    DEBUGMSGOID(("winExtDLL", name, length));
251
 
    DEBUGMSG(("winExtDLL", "\n"));
252
 
 
253
 
    // Store supported view in Windows format
254
 
    SnmpUtilOidCpy(&winExtensionAgent[winExtensionAgent_num].pSupportedView,&pSupportedView);
255
 
 
256
 
    // Create handler registration
257
 
    winExtensionAgent[winExtensionAgent_num].my_handler = netsnmp_create_handler_registration("winExtDLL",
258
 
        var_winExtDLL,
259
 
        name,
260
 
        length,
261
 
        HANDLER_CAN_RWRITE);
262
 
    
263
 
    if (!winExtensionAgent[winExtensionAgent_num].my_handler) {
264
 
      snmp_log(LOG_ERR,
265
 
          "malloc failed registering handler for winExtDLL");
266
 
      DEBUGMSGTL(("winExtDLL", "malloc failed registering handler for winExtDLL"));
267
 
      return (-1);
268
 
    }
269
 
    else {
270
 
      DEBUGMSGTL(("winExtDLL", "handler registered\n"));
271
 
    }
272
 
    
273
 
    // Register handler with Net-SNMP
274
 
    netsnmp_register_handler(winExtensionAgent[winExtensionAgent_num].my_handler);
275
 
 
276
 
    // Check for additional supported views and register them with the same handler
277
 
    if (winExtensionAgent[winExtensionAgent_num].xSnmpExtensionInitEx) {
278
 
      DEBUGMSGTL(("winExtDLL", "xSnmpExtensionInitEx found\n"));
279
 
 
280
 
      winExtensionAgent_num++;
281
 
 
282
 
      while (1) { // Loop looking for more supported views
283
 
        // Store DLL name and functions in winExtensionAgent array  
284
 
        strncpy(winExtensionAgent[winExtensionAgent_num].dll_name, dll_name, SZBUF_DLLNAME_MAX-1);
285
 
        winExtensionAgent[winExtensionAgent_num].xSnmpExtensionInit = xSnmpExtensionInit;
286
 
        winExtensionAgent[winExtensionAgent_num].xSnmpExtensionInitEx = xSnmpExtensionInitEx;
287
 
        winExtensionAgent[winExtensionAgent_num].xSnmpExtensionQuery = xSnmpExtensionQuery;
288
 
        winExtensionAgent[winExtensionAgent_num].xSnmpExtensionQueryEx = xSnmpExtensionQueryEx;
289
 
        winExtensionAgent[winExtensionAgent_num].xSnmpExtensionTrap = xSnmpExtensionTrap;     
290
 
        winExtensionAgent[winExtensionAgent_num].subagentTrapEvent = NULL;
291
 
        // Get extra supported view
292
 
        result = xSnmpExtensionInitEx(&pSupportedView);
293
 
 
294
 
        if (! (result)) {
295
 
          winExtensionAgent_num--;
296
 
          break;
297
 
        }
298
 
 
299
 
        DEBUGMSGTL(("winExtDLL", "result of xSnmpExtensionInitEx: %d\n",result));
300
 
      
301
 
        DEBUGMSGTL(("winExtDLL", "Supported view: "));
302
 
        DEBUGMSGWINOID(("winExtDLL", &pSupportedView));
303
 
        DEBUGMSG(("winExtDLL", "\n"));
304
 
        
305
 
        // Convert OID from Windows 'supported view' to Net-SNMP
306
 
        for (i = 0; i < (pSupportedView.idLength > MAX_OID_LEN?MAX_OID_LEN:pSupportedView.idLength); i++) {
307
 
          name[i] = (oid)pSupportedView.ids[i];
308
 
        }
309
 
        length = i;
310
 
  
311
 
        // Store supported view in Net-SNMP format
312
 
        memcpy(winExtensionAgent[winExtensionAgent_num].name, name, sizeof(name));
313
 
        winExtensionAgent[winExtensionAgent_num].name_length = length;
314
 
 
315
 
        DEBUGMSGTL(("winExtDLL", "Windows OID converted to Net-SNMP: "));
316
 
        DEBUGMSGOID(("winExtDLL", name, length));
317
 
        DEBUGMSG(("winExtDLL", "\n"));
318
 
  
319
 
        // Store supported view in Windows format
320
 
        SnmpUtilOidCpy(&winExtensionAgent[winExtensionAgent_num].pSupportedView,&pSupportedView);
321
 
  
 
107
#define MS_ASN_UINTEGER32 MS_ASN_UNSIGNED32
 
108
 
 
109
 
 
110
typedef         BOOL(WINAPI *
 
111
                     PFNSNMPEXTENSIONINIT) (DWORD dwUpTimeReference,
 
112
                                            HANDLE * phSubagentTrapEvent,
 
113
                                            AsnObjectIdentifier *
 
114
                                            pFirstSupportedRegion);
 
115
 
 
116
typedef         BOOL(WINAPI *
 
117
                     PFNSNMPEXTENSIONINITEX) (AsnObjectIdentifier *
 
118
                                              pNextSupportedRegion);
 
119
 
 
120
typedef         BOOL(WINAPI *
 
121
                     PFNSNMPEXTENSIONMONITOR) (LPVOID pAgentMgmtData);
 
122
 
 
123
typedef         BOOL(WINAPI * PFNSNMPEXTENSIONQUERY) (BYTE bPduType,
 
124
                                                      SnmpVarBindList *
 
125
                                                      pVarBindList,
 
126
                                                      AsnInteger32 *
 
127
                                                      pErrorStatus,
 
128
                                                      AsnInteger32 *
 
129
                                                      pErrorIndex);
 
130
 
 
131
typedef         BOOL(WINAPI * PFNSNMPEXTENSIONQUERYEX) (UINT nRequestType,
 
132
                                                        UINT
 
133
                                                        nTransactionId,
 
134
                                                        SnmpVarBindList *
 
135
                                                        pVarBindList,
 
136
                                                        AsnOctetString *
 
137
                                                        pContextInfo,
 
138
                                                        AsnInteger32 *
 
139
                                                        pErrorStatus,
 
140
                                                        AsnInteger32 *
 
141
                                                        pErrorIndex);
 
142
 
 
143
typedef         BOOL(WINAPI * PFNSNMPEXTENSIONTRAP) (AsnObjectIdentifier *
 
144
                                                     pEnterpriseOid,
 
145
                                                     AsnInteger32 *
 
146
                                                     pGenericTrapId,
 
147
                                                     AsnInteger32 *
 
148
                                                     pSpecificTrapId,
 
149
                                                     AsnTimeticks *
 
150
                                                     pTimeStamp,
 
151
                                                     SnmpVarBindList *
 
152
                                                     pVarBindList);
 
153
 
 
154
typedef         VOID(WINAPI * PFNSNMPEXTENSIONCLOSE) (void);
 
155
 
 
156
/**
 
157
 * Extensible array, a data structure similar to the C++ STL class
 
158
 * std::vector<>.
 
159
 */
 
160
typedef struct {
 
161
    /** Pointer to the memory allocated for the array. */
 
162
    void           *p;
 
163
    /** Number of bytes occupied by a single element.  */
 
164
    size_t          elem_size;
 
165
    /** Number of elements that have been allocated.   */
 
166
    int             reserved;
 
167
    /** Number of elements currently in use.           */
 
168
    int             size;
 
169
} xarray;
 
170
 
 
171
/**
 
172
 * Information managed by winExtDLL about Windows SNMP extension DLL's.
 
173
 */
 
174
typedef struct {
 
175
    char           *dll_name;                        /**< Dynamically allocated DLL name. */
 
176
    HANDLE          dll_handle;                      /**< DLL handle. */
 
177
    PFNSNMPEXTENSIONINIT pfSnmpExtensionInit;
 
178
    PFNSNMPEXTENSIONINITEX pfSnmpExtensionInitEx;
 
179
    PFNSNMPEXTENSIONQUERY pfSnmpExtensionQuery;
 
180
    PFNSNMPEXTENSIONQUERYEX pfSnmpExtensionQueryEx;
 
181
    PFNSNMPEXTENSIONTRAP pfSnmpExtensionTrap;
 
182
    HANDLE          subagentTrapEvent;
 
183
} winextdll;
 
184
 
 
185
/**
 
186
 * Information managed by winExtDLL about a single view of a Windows SNMP
 
187
 * extension DLL.
 
188
 */
 
189
typedef struct {
 
190
    winextdll      *winextdll_info;
 
191
    netsnmp_handler_registration *my_handler;
 
192
    oid             name[MAX_OID_LEN];                   /**< OID of this view. */
 
193
    size_t          name_length;
 
194
} winextdll_view;
 
195
 
 
196
/**
 
197
 * Per varbind SNMP extension DLL context information for SNMP set operations.
 
198
 */
 
199
typedef struct context_info_s {
 
200
    struct context_info_s *next;
 
201
    int             index;
 
202
    AsnOctetString  context_info;
 
203
} context_info;
 
204
 
 
205
 
 
206
/*
 
207
 * External function declarations. 
 
208
 */
 
209
void __declspec(dllimport) WINAPI SnmpSvcInitUptime(void);
 
210
 
 
211
 
 
212
/*
 
213
 * Local functions declarations. 
 
214
 */
 
215
static int      basename_equals(const char *path, const char *basename);
 
216
static int      register_netsnmp_handler(winextdll_view *
 
217
                                         const ext_dll_view_info);
 
218
static void     read_extension_dlls_from_registry(void);
 
219
static void     read_extension_dlls_from_registry_at(const char *const subkey);
 
220
static char    *read_extension_dll_path_from_registry(const TCHAR *);
 
221
static void     subagentTrapCheck(unsigned int clientreg, void *clientarg);
 
222
static int      var_winExtDLL(netsnmp_mib_handler *handler,
 
223
                              netsnmp_handler_registration *reginfo,
 
224
                              netsnmp_agent_request_info *reqinfo,
 
225
                              netsnmp_request_info *requests);
 
226
static int      append_windows_varbind_list(netsnmp_variable_list **
 
227
                                            const net_snmp_varbinds,
 
228
                                            const SnmpVarBindList *
 
229
                                            const win_varbinds);
 
230
static int      append_windows_varbind(netsnmp_variable_list **
 
231
                                       const net_snmp_varbinds,
 
232
                                       const SnmpVarBind *
 
233
                                       const win_varbind);
 
234
static int      convert_to_windows_varbind_list(SnmpVarBindList *
 
235
                                                pVarBindList,
 
236
                                                netsnmp_variable_list *
 
237
                                                netsnmp_varbinds);
 
238
static int      convert_win_snmp_err(const int win_snmp_err);
 
239
static winextdll_view *lookup_view_by_oid(oid * const name,
 
240
                                          const size_t name_len);
 
241
static void     copy_oid(oid * const to_name, size_t * const to_name_len,
 
242
                         const oid * const from_name,
 
243
                         const size_t from_name_len);
 
244
static UINT    *copy_oid_to_new_windows_oid(AsnObjectIdentifier *
 
245
                                            const windows_oid,
 
246
                                            const oid * const name,
 
247
                                            const size_t name_len);
 
248
static void     send_trap(const AsnObjectIdentifier * const,
 
249
                          const AsnInteger, const AsnInteger,
 
250
                          const AsnTimeticks,
 
251
                          const SnmpVarBindList * const);
 
252
static u_char  *winsnmp_memdup(const void *src, const size_t len);
 
253
#if 0
 
254
static void     xarray_init(xarray * a, size_t elem_size);
 
255
#endif
 
256
static void     xarray_destroy(xarray * a);
 
257
static void    *xarray_push_back(xarray * a, const void *elem);
 
258
#if 0
 
259
static void     xarray_erase(xarray * a, void *const elem);
 
260
#endif
 
261
static void    *xarray_reserve(xarray * a, int reserved);
 
262
 
 
263
 
 
264
/*
 
265
 * Local variable definitions. 
 
266
 */
 
267
#define WINEXTDLL(i)            ((winextdll*)s_winextdll.p)[i]
 
268
#define WINEXTDLL_VIEW(i)       ((winextdll_view*)s_winextdll_view.p)[i]
 
269
#define TRAPEVENT(i)            ((HANDLE*)s_trapevent.p)[i]
 
270
#define TRAPEVENT_TO_DLLINFO(i) ((winextdll**)s_trapevent_to_dllinfo.p)[i]
 
271
static xarray   s_winextdll = { 0, sizeof(winextdll) };
 
272
static xarray   s_winextdll_view = { 0, sizeof(winextdll_view) };
 
273
static xarray   s_trapevent = { 0, sizeof(HANDLE) };
 
274
static xarray   s_trapevent_to_dllinfo = { 0, sizeof(winextdll *) };
 
275
static context_info *context_info_head;
 
276
 
 
277
 
 
278
/*
 
279
 * Function definitions. 
 
280
 */
 
281
 
 
282
/** Initialize the winExtDLL extension agent. */
 
283
void
 
284
init_winExtDLL(void)
 
285
{
 
286
    BOOL            result;
 
287
    int             i;
 
288
 
 
289
    DEBUGMSG(("winExtDLL", "init_winExtDLL started.\n"));
 
290
 
 
291
    SnmpSvcInitUptime();
 
292
 
 
293
    read_extension_dlls_from_registry();
 
294
 
 
295
    DEBUGMSG(("winExtDLL",
 
296
              "init_winExtDLL: found %d extension DLLs in the registry.\n",
 
297
              s_winextdll.size));
 
298
 
 
299
    xarray_reserve(&s_winextdll, 128);
 
300
 
 
301
    /*
 
302
     * Load all the DLLs 
 
303
     */
 
304
    for (i = 0; i < s_winextdll.size; i++) {
 
305
        winextdll      *const ext_dll_info = &WINEXTDLL(i);
 
306
        AsnObjectIdentifier view;
 
307
        winextdll_view  ext_dll_view_info;
 
308
 
 
309
        assert(ext_dll_info);
 
310
        if (!ext_dll_info->dll_name)
 
311
            continue;
 
312
 
 
313
        DEBUGMSG(("winExtDLL", "loading DLL %s.\n",
 
314
                  ext_dll_info->dll_name));
 
315
        ext_dll_info->dll_handle = LoadLibrary(ext_dll_info->dll_name);
 
316
 
 
317
        if (ext_dll_info->dll_handle == NULL) {
 
318
            const DWORD     dwErrorcode = GetLastError();
 
319
            LPTSTR          lpMsgBuf;
 
320
 
 
321
            FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
 
322
                          FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrorcode,
 
323
                          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
324
                          (LPTSTR) & lpMsgBuf, 0, NULL);
 
325
            if (lpMsgBuf) {
 
326
                LPTSTR          p;
 
327
 
 
328
                /*
 
329
                 * Remove trailing "\r\n".
 
330
                 */
 
331
                p = strchr(lpMsgBuf, '\r');
 
332
                if (p)
 
333
                    *p = '\0';
 
334
            }
 
335
            snmp_log(LOG_ERR,
 
336
                     "init_winExtDLL: could not load SNMP extension"
 
337
                     " DLL %s: %s\n",
 
338
                     ext_dll_info->dll_name, lpMsgBuf ? lpMsgBuf : "(?)");
 
339
            if (lpMsgBuf)
 
340
                LocalFree(lpMsgBuf);
 
341
            continue;
 
342
        }
 
343
 
 
344
        /*
 
345
         * Store DLL name and functions in s_extension_dll_info array. 
 
346
         */
 
347
        ext_dll_info->pfSnmpExtensionInit = (PFNSNMPEXTENSIONINIT)
 
348
            GetProcAddress(ext_dll_info->dll_handle, "SnmpExtensionInit");
 
349
        ext_dll_info->pfSnmpExtensionInitEx = (PFNSNMPEXTENSIONINITEX)
 
350
            GetProcAddress(ext_dll_info->dll_handle,
 
351
                           "SnmpExtensionInitEx");
 
352
        ext_dll_info->pfSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY)
 
353
            GetProcAddress(ext_dll_info->dll_handle, "SnmpExtensionQuery");
 
354
        ext_dll_info->pfSnmpExtensionQueryEx = (PFNSNMPEXTENSIONQUERYEX)
 
355
            GetProcAddress(ext_dll_info->dll_handle,
 
356
                           "SnmpExtensionQueryEx");
 
357
        ext_dll_info->pfSnmpExtensionTrap = (PFNSNMPEXTENSIONTRAP)
 
358
            GetProcAddress(ext_dll_info->dll_handle, "SnmpExtensionTrap");
 
359
 
 
360
 
 
361
        if (ext_dll_info->pfSnmpExtensionQuery == NULL
 
362
            && ext_dll_info->pfSnmpExtensionQueryEx == NULL) {
 
363
            snmp_log(LOG_ERR,
 
364
                     "error in extension DLL %s: SNMP query function missing.\n",
 
365
                     ext_dll_info->dll_name);
 
366
        }
 
367
 
 
368
        /*
 
369
         * Init and get first supported view from Windows SNMP extension DLL.
 
370
         * Note: although according to the documentation of SnmpExtensionInit()
 
371
         * the first argument of this function should be ignored by extension
 
372
         * DLLs, passing the value GetTickCount() / 10 is necessary to make
 
373
         * inetmib1.dll work correctly. Passing zero as the first argument
 
374
         * causes inetmib1.dll to report an incorrect value for sysUpTime.0
 
375
         * and also causes the same DLL not to send linkUp or linkDown traps.
 
376
         */
 
377
        ext_dll_info->subagentTrapEvent = NULL;
 
378
        view.idLength = 0;
 
379
        view.ids = 0;
 
380
        result =
 
381
            ext_dll_info->pfSnmpExtensionInit(GetTickCount() / 10,
 
382
                                              &ext_dll_info->
 
383
                                              subagentTrapEvent, &view);
 
384
 
 
385
        if (!result) {
 
386
            snmp_log(LOG_ERR,
 
387
                     "init_winExtDLL: initialization of DLL %s failed.\n",
 
388
                     ext_dll_info->dll_name);
 
389
            FreeLibrary(ext_dll_info->dll_handle);
 
390
            ext_dll_info->dll_handle = 0;
 
391
            continue;
 
392
        }
 
393
 
 
394
        if (ext_dll_info->subagentTrapEvent != NULL) {
 
395
            xarray_push_back(&s_trapevent,
 
396
                             &ext_dll_info->subagentTrapEvent);
 
397
            xarray_push_back(&s_trapevent_to_dllinfo, &ext_dll_info);
 
398
        }
 
399
 
 
400
        memset(&ext_dll_view_info, 0, sizeof(ext_dll_view_info));
 
401
        ext_dll_view_info.winextdll_info = ext_dll_info;
 
402
        copy_oid(ext_dll_view_info.name, &ext_dll_view_info.name_length,
 
403
                 view.ids, view.idLength);
 
404
        xarray_push_back(&s_winextdll_view, &ext_dll_view_info);
 
405
 
 
406
        /*
 
407
         * Loop looking for more supported views. 
 
408
         */
 
409
        while (ext_dll_info->pfSnmpExtensionInitEx
 
410
               && ext_dll_info->pfSnmpExtensionInitEx(&view)) {
 
411
            memset(&ext_dll_view_info, 0, sizeof(ext_dll_view_info));
 
412
            ext_dll_view_info.winextdll_info = ext_dll_info;
 
413
            copy_oid(ext_dll_view_info.name,
 
414
                     &ext_dll_view_info.name_length, view.ids,
 
415
                     view.idLength);
 
416
            xarray_push_back(&s_winextdll_view, &ext_dll_view_info);
 
417
        }
 
418
    }
 
419
 
 
420
    /*
 
421
     * Note: since register_netsnmp_handler() writes a pointer to the
 
422
     * winextdll_view in one of the Net-SNMP data structures, it is not
 
423
     * allowed to move winextdll_view data structures in memory after
 
424
     * registration with Net-SNMP. Or: register_snmp_handler() must be called
 
425
     * only once it is sure that the size of array s_winextdll_view won't change
 
426
     * anymore.
 
427
     */
 
428
    for (i = 0; i < s_winextdll_view.size; i++)
 
429
        register_netsnmp_handler(&WINEXTDLL_VIEW(i));
 
430
 
 
431
    DEBUGMSG(("winExtDLL",
 
432
              "init_winExtDLL: registered %d OID ranges.\n",
 
433
              s_winextdll_view.size));
 
434
 
 
435
    /*
 
436
     * Let Net-SNMP call subagentTrapCheck() once per second. 
 
437
     */
 
438
    if (s_trapevent.size)
 
439
        snmp_alarm_register(1, SA_REPEAT, subagentTrapCheck, NULL);
 
440
 
 
441
    DEBUGMSG(("winExtDLL", "init_winExtDLL finished.\n"));
 
442
}
 
443
 
 
444
void
 
445
shutdown_winExtDLL(void)
 
446
{
 
447
    int             i;
 
448
 
 
449
    DEBUGMSG(("winExtDLL", "shutdown_winExtDLL() started.\n"));
 
450
 
 
451
    for (i = s_winextdll_view.size - 1; i >= 0; i--) {
 
452
        winextdll_view *const v = &WINEXTDLL_VIEW(i);
 
453
        if (v && v->my_handler) {
 
454
            DEBUGIF("winExtDLL") {
 
455
                DEBUGMSG(("winExtDLL",
 
456
                          "unregistering handler for DLL %s and OID prefix ",
 
457
                          v->winextdll_info->dll_name));
 
458
                DEBUGMSGOID(("winExtDLL", v->name, v->name_length));
 
459
                DEBUGMSG(("winExtDLL", " ("));
 
460
                DEBUGMSGSUBOID(("winExtDLL", v->name, v->name_length));
 
461
                DEBUGMSG(("winExtDLL", ").\n"));
 
462
            }
 
463
            netsnmp_unregister_handler(v->my_handler);
 
464
        }
 
465
    }
 
466
    xarray_destroy(&s_winextdll_view);
 
467
 
 
468
    for (i = s_winextdll.size - 1; i >= 0; i--) {
 
469
        winextdll      *const ext_dll_info = &WINEXTDLL(i);
 
470
        /*
 
471
         * Freeing the Broadcom SNMP extension libraries triggers a deadlock,
 
472
         * so skip bcmif.dll and baspmgnt.dll. 
 
473
         */
 
474
        if (ext_dll_info->dll_handle != 0
 
475
            && !basename_equals(ext_dll_info->dll_name, "bcmif.dll")
 
476
            && !basename_equals(ext_dll_info->dll_name, "baspmgnt.dll")) {
 
477
            DEBUGMSG(("winExtDLL", "unloading %s.\n",
 
478
                      ext_dll_info->dll_name));
 
479
            FreeLibrary(ext_dll_info->dll_handle);
 
480
        }
 
481
        free(ext_dll_info->dll_name);
 
482
    }
 
483
    xarray_destroy(&s_winextdll);
 
484
 
 
485
    xarray_destroy(&s_trapevent_to_dllinfo);
 
486
 
 
487
    xarray_destroy(&s_trapevent);
 
488
 
 
489
    DEBUGMSG(("winExtDLL", "shutdown_winExtDLL() finished.\n"));
 
490
}
 
491
 
 
492
/**
 
493
 * Compare the basename of a path with a given string.
 
494
 *
 
495
 * @return 1 if the basename matches, 0 if not.
 
496
 */
 
497
static int
 
498
basename_equals(const char *path, const char *basename)
 
499
{
 
500
    const size_t    path_len = strlen(path);
 
501
    const size_t    basename_len = strlen(basename);
 
502
 
 
503
    assert(strchr(path, '/') == 0);
 
504
    assert(strchr(basename, '/') == 0);
 
505
    assert(strchr(basename, '\\') == 0);
 
506
 
 
507
    return path_len >= basename_len + 1
 
508
        && path[path_len - basename_len - 1] == '\\'
 
509
        && stricmp(path + path_len - basename_len, basename) == 0;
 
510
}
 
511
 
 
512
/**
 
513
 * Register a single OID subtree with Net-SNMP.
 
514
 *
 
515
 * @return 1 if successful, 0 if not.
 
516
 */
 
517
int
 
518
register_netsnmp_handler(winextdll_view * const ext_dll_view_info)
 
519
{
 
520
    winextdll      *ext_dll_info;
 
521
    winextdll_view *previously_registered_view;
 
522
 
 
523
    ext_dll_info = ext_dll_view_info->winextdll_info;
 
524
 
 
525
    previously_registered_view
 
526
        = lookup_view_by_oid(ext_dll_view_info->name,
 
527
                             ext_dll_view_info->name_length);
 
528
 
 
529
    if (previously_registered_view) {
 
530
        size_t          oid_namelen, outlen;
 
531
        char           *oid_name;
 
532
        int             buffer_large_enough;
 
533
 
 
534
        oid_namelen = 0;
 
535
        outlen = 0;
 
536
        oid_name = NULL;
 
537
        buffer_large_enough =
 
538
            sprint_realloc_objid((u_char **) & oid_name, &oid_namelen,
 
539
                                 &outlen, 1, ext_dll_view_info->name,
 
540
                                 ext_dll_view_info->name_length);
 
541
        snmp_log(LOG_INFO, "OID range %s%s: replacing handler %s by %s.\n",
 
542
                 oid_name ? oid_name : "",
 
543
                 buffer_large_enough ? "" : " [TRUNCATED]",
 
544
                 previously_registered_view->winextdll_info->dll_name,
 
545
                 ext_dll_view_info->winextdll_info->dll_name);
 
546
        if (oid_name)
 
547
            free(oid_name);
 
548
 
 
549
        previously_registered_view->winextdll_info = ext_dll_info;
 
550
        memset(ext_dll_view_info, 0, sizeof(*ext_dll_view_info));
 
551
        return 1;
 
552
    } else {
322
553
        // Create handler registration
323
 
        winExtensionAgent[winExtensionAgent_num].my_handler = netsnmp_create_handler_registration("winExtDLL",
324
 
            var_winExtDLL,
325
 
            name,
326
 
            length,
327
 
            HANDLER_CAN_RWRITE);
328
 
        
329
 
        if (!winExtensionAgent[winExtensionAgent_num].my_handler) {
330
 
          snmp_log(LOG_ERR,
331
 
              "malloc failed registering handler for winExtDLL");
332
 
          DEBUGMSGTL(("winExtDLL", "malloc failed registering handler for winExtDLL"));
333
 
          return (-1);
334
 
        }
335
 
        else {
336
 
          DEBUGMSGTL(("winExtDLL", "handler registered\n"));
337
 
        }
338
 
        
339
 
        // Register handler with Net-SNMP
340
 
        netsnmp_register_handler(winExtensionAgent[winExtensionAgent_num].my_handler);
341
 
 
342
 
        winExtensionAgent_num++;
343
 
      } 
344
 
    }
345
 
    winExtensionAgent_num++;
346
 
  }
347
 
 
348
 
 
349
 
  winExtensionAgent_index = winExtensionAgent_num-1;             // Array index
350
 
  DEBUGMSGTL(("winExtDLL", "winExtensionAgent_index: %d\n",winExtensionAgent_index));
351
 
 
352
 
  /* Reverse sort array of winExtensionAgents */
353
 
  i = sizeof(winExtensionAgent) / sizeof(winExtensionAgents);
354
 
  //DEBUGMSGTL(("winExtDLL", "Sorting...\n"));
355
 
  for (iter=0; iter < i-1; iter++) {
356
 
    for (indx=0; indx < i-1; indx++) {
357
 
      if (snmp_oidtree_compare(winExtensionAgent[indx].name, winExtensionAgent[indx].name_length,
358
 
            winExtensionAgent[indx+1].name, winExtensionAgent[indx+1].name_length) < 0) {
359
 
        winExtensionAgent_temp = winExtensionAgent[indx];
360
 
        winExtensionAgent[indx] = winExtensionAgent[indx+1];
361
 
        winExtensionAgent[indx+1] = winExtensionAgent_temp;
362
 
      }
363
 
    }
364
 
  }
365
 
  DEBUGMSGTL(("winExtDLL", "Dumping sorted Windows extension OIDs\n"));
366
 
  for (i=0; winExtensionAgent[i].xSnmpExtensionInit; i++) {
367
 
    DEBUGMSGTL(("winExtDLL", "DLL name: %s, view: ",winExtensionAgent[i].dll_name));
368
 
    DEBUGMSGOID(("winExtDLL", winExtensionAgent[i].name, winExtensionAgent[i].name_length));
369
 
    DEBUGMSG(("winExtDLL", "\n"));
370
 
  }
371
 
 
372
 
  DEBUGMSGTL(("winExtDLL", "Number of subagentTrapEvents: %d\n",subagentTrapEvents_index));
373
 
 
374
 
  if (subagentTrapEvents_index) {
375
 
    
376
 
    DEBUGMSGTL(("winExtDLL", "Setting alarm check for subagent trap events every 5 seconds\n"));
377
 
    snmp_alarm_register(5,      /* seconds */
378
 
        SA_REPEAT,              /* repeat (every x seconds). */
379
 
        subagentTrapCheck,      /* our callback */
380
 
        NULL                    /* no callback data needed */
381
 
        );    
382
 
  }
383
 
}
384
 
 
385
 
int
 
554
        ext_dll_view_info->my_handler
 
555
            = netsnmp_create_handler_registration(ext_dll_info->dll_name,
 
556
                                                  var_winExtDLL,
 
557
                                                  ext_dll_view_info->name,
 
558
                                                  ext_dll_view_info->
 
559
                                                  name_length,
 
560
                                                  HANDLER_CAN_RWRITE);
 
561
 
 
562
        if (ext_dll_view_info->my_handler) {
 
563
            ext_dll_view_info->my_handler->handler->myvoid =
 
564
                ext_dll_view_info;
 
565
            if (netsnmp_register_handler(ext_dll_view_info->my_handler)
 
566
                == MIB_REGISTERED_OK) {
 
567
                DEBUGIF("winExtDLL") {
 
568
                    DEBUGMSG(("winExtDLL",
 
569
                              "registering handler for DLL %s and OID prefix ",
 
570
                              ext_dll_info->dll_name));
 
571
                    DEBUGMSGOID(("winExtDLL", ext_dll_view_info->name,
 
572
                                 ext_dll_view_info->name_length));
 
573
                    DEBUGMSG(("winExtDLL", " ("));
 
574
                    DEBUGMSGSUBOID(("winExtDLL", ext_dll_view_info->name,
 
575
                                    ext_dll_view_info->name_length));
 
576
                    DEBUGMSG(("winExtDLL", ").\n"));
 
577
                }
 
578
                return 1;
 
579
            } else {
 
580
                snmp_log(LOG_ERR, "handler registration failed.\n");
 
581
                ext_dll_view_info->my_handler = 0;
 
582
            }
 
583
        } else {
 
584
            snmp_log(LOG_ERR, "handler creation failed.\n");
 
585
        }
 
586
    }
 
587
 
 
588
    return 0;
 
589
}
 
590
 
 
591
/**
 
592
 * Allocate SNMP extension DLL context information. Such context information
 
593
 * is necessary to allow an extension DLL to process a set request.
 
594
 *
 
595
 * @param[in] index Varbind index in original PDU.
 
596
 *
 
597
 * @return NULL if context information for the specified index was already
 
598
 *   allocated, and otherwise a pointer to the newly allocated context
 
599
 *   information.
 
600
 */
 
601
static context_info *
 
602
alloc_context_info(const int index)
 
603
{
 
604
    context_info   *p;
 
605
 
 
606
    DEBUGMSG(("winExtDLL:context_info", "alloc_context_info(%d)\n",
 
607
              index));
 
608
 
 
609
    for (p = context_info_head; p; p = p->next) {
 
610
        if (p->index == index) {
 
611
            assert(FALSE);
 
612
            return NULL;
 
613
        }
 
614
    }
 
615
 
 
616
    p = calloc(1, sizeof(context_info));
 
617
    p->next = context_info_head;
 
618
    context_info_head = p;
 
619
    p->index = index;
 
620
 
 
621
    return p;
 
622
}
 
623
 
 
624
/**
 
625
 * Deallocate SNMP extension DLL context information.
 
626
 *
 
627
 * @param[in] index Varbind index in original PDU.
 
628
 */
 
629
static void
 
630
free_context_info(const int index)
 
631
{
 
632
    context_info  **pprev = &context_info_head;
 
633
    context_info   *p;
 
634
 
 
635
    DEBUGMSG(("winExtDLL:context_info", "free_context_info(%d)\n", index));
 
636
 
 
637
    for (p = context_info_head; p; p = p->next) {
 
638
        if (p->index == index) {
 
639
            *pprev = p->next;
 
640
            free(p);
 
641
            break;
 
642
        }
 
643
        pprev = &p->next;
 
644
    }
 
645
}
 
646
 
 
647
/**
 
648
 * Look up SNMP extension DLL context information.
 
649
 *
 
650
 * @param[in] index Varbind index in original PDU.
 
651
 */
 
652
static AsnOctetString *
 
653
get_context_info(const int index)
 
654
{
 
655
    context_info   *p;
 
656
 
 
657
    DEBUGMSG(("winExtDLL:context_info", "get_context_info(%d)\n", index));
 
658
 
 
659
    for (p = context_info_head; p; p = p->next)
 
660
        if (p->index == index)
 
661
            return &p->context_info;
 
662
 
 
663
    assert(FALSE);
 
664
    return NULL;
 
665
}
 
666
 
 
667
static int
386
668
var_winExtDLL(netsnmp_mib_handler *handler,
387
669
              netsnmp_handler_registration *reginfo,
388
670
              netsnmp_agent_request_info *reqinfo,
389
671
              netsnmp_request_info *requests)
390
672
{
391
 
 
392
 
    netsnmp_request_info *request = requests;
393
 
    netsnmp_variable_list *var;
394
 
    oid             oid_requested[MAX_OID_LEN];
395
 
    size_t          oid_requested_length;
396
 
    
397
 
    static char     ret_szbuf_temp[SZBUF_MAX];          // Holder for return strings
398
 
    static oid      ret_oid[MAX_OID_LEN];               // Holder for return OIDs
399
 
    static size_t   ret_oid_length = 0;                 // Holder for return OIDs
400
 
    static long     ret_long;                           // Holder for all other returns
401
 
 
402
 
    static char     set_szbuf_temp[SZBUF_MAX];          // Holder for set strings    
403
 
    static oid      set_oid[MAX_OID_LEN];               // Holder for set OIDs
404
 
    static size_t   set_oid_length = 0;                 // Holder for set OIDs
405
 
    oid             *temp_oid;
406
 
    size_t          temp_oid_length;
407
 
    
408
 
    static int      temp;
409
 
    static u_long   accesses = 7;
410
 
    u_char          netsnmp_ASN_type;
411
 
    u_char          windows_ASN_type;
412
 
 
413
 
    char          *stringtemp;
414
 
 
415
 
    // WinSNMP variables:
416
 
    BOOL result;   
417
 
    SnmpVarBind *mySnmpVarBind;
418
 
    AsnInteger32 pErrorStatus;
419
 
    AsnInteger32 pErrorIndex;
420
 
    SnmpVarBindList pVarBindList;  
421
 
    int i=0;
422
 
    int j=0;
423
 
 
424
 
    DWORD (WINAPI *xSnmpExtensionQuery)(BYTE, SnmpVarBindList* ,AsnInteger32* ,AsnInteger32*);
425
 
    DWORD (WINAPI *xSnmpExtensionQueryEx)(DWORD, DWORD, SnmpVarBindList*, AsnOctetString*, AsnInteger32*, AsnInteger32*);
426
 
    DWORD (WINAPI *next_xSnmpExtensionQuery)(BYTE, SnmpVarBindList* ,AsnInteger32* ,AsnInteger32*);
427
 
    DWORD (WINAPI *next_xSnmpExtensionQueryEx)(DWORD, DWORD, SnmpVarBindList*, AsnOctetString*, AsnInteger32*, AsnInteger32*);
428
 
    AsnObjectIdentifier winExtensionAgent_pSupportedView;               // Support view of this extension agent
429
 
    oid winExtensionAgent_name[MAX_OID_LEN];                            // Support view of this extension agent
430
 
    size_t winExtensionAgent_name_length;                               // Support view of this extension agent
431
 
 
432
 
    int match_winExtensionAgent_index = -1;
433
 
 
434
 
    DEBUGMSGTL(("winExtDLL", "-----------------------------------------\n"));
435
 
    DEBUGMSGTL(("winExtDLL", "var_winExtDLL handler starting, mode = %d\n",
436
 
                reqinfo->mode));
437
 
    
 
673
    winextdll_view *const ext_dll_view_info = handler->myvoid;
 
674
    winextdll      *ext_dll_info;
 
675
    netsnmp_request_info *request;
 
676
    UINT            nRequestType;
 
677
    const char     *mode_name;
 
678
    int             rc;
 
679
 
 
680
    assert(ext_dll_view_info);
 
681
    ext_dll_info = ext_dll_view_info->winextdll_info;
 
682
#if ! defined(NDEBUG)
 
683
    assert(ext_dll_view_info ==
 
684
           lookup_view_by_oid(reginfo->rootoid, reginfo->rootoid_len));
 
685
#endif
 
686
 
 
687
    if (ext_dll_info == 0) {
 
688
        DEBUGMSG(("winExtDLL",
 
689
                  "internal error: no matching extension DLL found.\n"));
 
690
        assert(0);
 
691
        return SNMP_ERR_GENERR;
 
692
    }
 
693
 
438
694
    switch (reqinfo->mode) {
439
695
    case MODE_GET:
 
696
        mode_name = "GET";
 
697
        nRequestType = SNMP_EXTENSION_GET;
 
698
        assert(!context_info_head);
 
699
        break;
440
700
    case MODE_GETNEXT:
441
 
 
442
 
      if (reqinfo->mode == MODE_GET)
443
 
        DEBUGMSGTL(("winExtDLL", "GET requested\n"));
444
 
      else if (reqinfo->mode == MODE_GETNEXT)
445
 
        DEBUGMSGTL(("winExtDLL", "GETNEXT requested\n"));
446
 
      
447
 
      for (request = requests; request; request=request->next) {
448
 
        
449
 
        var = request->requestvb;
450
 
 
451
 
        // Make copy of requested OID
452
 
        for (i = 0; i < (var->name_length > MAX_OID_LEN? MAX_OID_LEN: var->name_length); i++) {
453
 
          oid_requested[i] = var->name[i];
454
 
        }
455
 
        oid_requested_length = i;
456
 
        
457
 
        DEBUGMSGTL(("winExtDLL", "Requested: "));
458
 
        DEBUGMSGOID(("winExtDLL", oid_requested, oid_requested_length));
459
 
        DEBUGMSG(("winExtDLL", "\n"));       
460
 
 
461
 
        DEBUGMSGTL(("winExtDLL", "Var type requested: %d\n",var->type));
462
 
 
463
 
        /* Loop through all the winExtensionAgent's looking for a matching handler */
464
 
        xSnmpExtensionQuery = NULL;
465
 
        xSnmpExtensionQueryEx = NULL;
466
 
        next_xSnmpExtensionQuery = NULL;
467
 
        next_xSnmpExtensionQueryEx = NULL;
468
 
 
469
 
        DEBUGMSGTL(("winExtDLL", "Looping through all the winExtensionAgent's looking for a matching handler (exact).\n"));
470
 
        // Search starting with lowest so a walk of .1.3 starts with the lowest extension
471
 
        for (i = winExtensionAgent_index; winExtensionAgent[i].xSnmpExtensionInit && i >= 0; i--) {          
472
 
 
473
 
          /*DEBUGMSGTL(("winExtDLL", "Comparing: "));
474
 
          DEBUGMSGOID(("winExtDLL", var->name, var->name_length));
475
 
          DEBUGMSG(("winExtDLL", "\n"));       
476
 
 
477
 
          DEBUGMSGTL(("winExtDLL", "to:        "));
478
 
          DEBUGMSGOID(("winExtDLL", winExtensionAgent[i].name, winExtensionAgent[i].name_length));
479
 
          DEBUGMSG(("winExtDLL", "\n"));*/
480
 
 
481
 
          if (snmp_oidtree_compare(var->name, var->name_length, winExtensionAgent[i].name, 
482
 
                winExtensionAgent[i].name_length) == 0) {
483
 
 
484
 
            DEBUGMSGTL(("winExtDLL", "Found exact match: "));
485
 
            DEBUGMSGOID(("winExtDLL", winExtensionAgent[i].name, winExtensionAgent[i].name_length));
486
 
            DEBUGMSG(("winExtDLL", "\n"));
487
 
            match_winExtensionAgent_index = i;
488
 
            //DEBUGMSGTL(("winExtDLL", "Index: %d\n",match_winExtensionAgent_index));
489
 
            break;
490
 
          }
491
 
        }
492
 
 
493
 
        if (match_winExtensionAgent_index == -1) {
494
 
          DEBUGMSGTL(("winExtDLL", "Looping through all the winExtensionAgent's looking for a matching handler (next best).\n"));
495
 
          for (i=0; winExtensionAgent[i].xSnmpExtensionInit && i < MAX_WINEXT_DLLS; i++) {
496
 
            
497
 
            /*DEBUGMSGTL(("winExtDLL", "Comparing: "));
498
 
            DEBUGMSGOID(("winExtDLL", var->name, var->name_length));
499
 
            DEBUGMSG(("winExtDLL", "\n"));       
500
 
            
501
 
            DEBUGMSGTL(("winExtDLL", "to:        "));
502
 
            DEBUGMSGOID(("winExtDLL", winExtensionAgent[i].name, winExtensionAgent[i].name_length));
503
 
            DEBUGMSG(("winExtDLL", "\n"));       
504
 
            DEBUGMSGTL(("winExtDLL", "and:       "));
505
 
            DEBUGMSGOID(("winExtDLL", winExtensionAgent[i+1].name, winExtensionAgent[i+1].name_length));
506
 
            DEBUGMSG(("winExtDLL", "\n"));       */
507
 
 
508
 
            if (snmp_oidtree_compare(var->name, var->name_length, winExtensionAgent[i].name, 
509
 
                  winExtensionAgent[i].name_length) <= 0 &&
510
 
                snmp_oidtree_compare(var->name, var->name_length, winExtensionAgent[i+1].name, 
511
 
                  winExtensionAgent[i+1].name_length) >= 0                      // FIXME:  Checking past the last extension?
512
 
               ) {
513
 
              DEBUGMSGTL(("winExtDLL", "Found best match: "));
514
 
              DEBUGMSGOID(("winExtDLL", winExtensionAgent[i].name, winExtensionAgent[i].name_length));
515
 
              DEBUGMSG(("winExtDLL", "\n"));
516
 
              match_winExtensionAgent_index = i;
517
 
              //DEBUGMSGTL(("winExtDLL", "Index: %d\n",match_winExtensionAgent_index));
518
 
              break;
519
 
            }
520
 
          }
521
 
        }
522
 
 
523
 
        //DEBUGMSG(("winExtDLL", "Index: %d\n",match_winExtensionAgent_index));
524
 
 
525
 
        if (match_winExtensionAgent_index == -1) {
526
 
          DEBUGMSGTL(("winExtDLL","Could not find a handler for the requested OID.  This should never happen!!\n"));
527
 
          return SNMP_ERR_GENERR;
528
 
        }
529
 
 
530
 
        // Make copy of current extension's OID
531
 
        for (j = 0; j < (winExtensionAgent[i].name_length > MAX_OID_LEN? MAX_OID_LEN: winExtensionAgent[i].name_length); j++) {
532
 
          winExtensionAgent_name[j] = winExtensionAgent[i].name[j];
533
 
        }
534
 
        winExtensionAgent_name_length = j;
535
 
 
536
 
        xSnmpExtensionQuery = winExtensionAgent[i].xSnmpExtensionQuery;
537
 
        xSnmpExtensionQueryEx = winExtensionAgent[i].xSnmpExtensionQueryEx;
538
 
        SnmpUtilOidCpy(&winExtensionAgent_pSupportedView, &winExtensionAgent[i].pSupportedView);
539
 
 
540
 
        if (! (xSnmpExtensionQuery || xSnmpExtensionQueryEx)) {
541
 
          if (reqinfo->mode == MODE_GET) {
542
 
            DEBUGMSGTL(("winExtDLL","Could not find a handler for the requested OID.  This should never happen!!\n"));
543
 
            return SNMP_ERR_GENERR;
544
 
          }
545
 
          else {
546
 
            DEBUGMSGTL(("winExtDLL","Could not find a handler for the requested OID.  Returning SNMP_ERR_NOSUCHNAME.\n"));
547
 
            return SNMP_ERR_NOSUCHNAME;
548
 
          }
549
 
        }
550
 
        
551
 
        // Query
552
 
        pVarBindList.list = (SnmpVarBind *) SnmpUtilMemAlloc(sizeof (SnmpVarBind));
553
 
        if (pVarBindList.list) {
554
 
 
555
 
          // Convert OID from Net-SNMP to Windows         
556
 
         
557
 
          pVarBindList.list->name.ids = (UINT *) SnmpUtilMemAlloc(sizeof (UINT) *var->name_length);
558
 
          
559
 
          if (pVarBindList.list->name.ids) {
560
 
            // Actual copy
561
 
            
562
 
            for (i = 0; i < var->name_length; i++) {
563
 
              pVarBindList.list->name.ids[i] = (UINT)var->name[i];
564
 
            }
565
 
            pVarBindList.list->name.idLength = i;
566
 
            
567
 
            DEBUGMSGTL(("winExtDLL", "Windows OID: "));
568
 
            DEBUGMSGWINOID(("winExtDLL", pVarBindList.list));
569
 
            DEBUGMSG(("winExtDLL", "\n"));
570
 
            
571
 
          }
572
 
          else {
573
 
            DEBUGMSGTL(("winExtDLL", "\nyCould not allocate memory for Windows SNMP varbind.\n"));
574
 
            return (0);
575
 
          }
576
 
 
577
 
          //pVarBindList.list = pVarBindList.list;
578
 
 
579
 
          pVarBindList.len = 1;          
580
 
        }
581
 
        else {
582
 
          DEBUGMSGTL(("winExtDLL", "Could not allocate memory for Windows SNMP varbind list.\n"));
583
 
          return (0);
584
 
        }        
585
 
                
586
 
        if (reqinfo->mode == MODE_GET) {
587
 
          DEBUGMSGTL(("winExtDLL", "win: MODE_GET\n"));
588
 
          if (xSnmpExtensionQueryEx) {
589
 
            DEBUGMSGTL(("winExtDLL", "Calling xSnmpExtensionQueryEx\n"));
590
 
            result = xSnmpExtensionQueryEx(SNMP_PDU_GET, 1, &pVarBindList, NULL, &pErrorStatus, &pErrorIndex);
591
 
          }
592
 
          else { 
593
 
            DEBUGMSGTL(("winExtDLL", "Calling xSnmpExtensionQuery\n"));
594
 
            result = xSnmpExtensionQuery(SNMP_PDU_GET, &pVarBindList, &pErrorStatus, &pErrorIndex);
595
 
          } 
596
 
        }
597
 
        else if (reqinfo->mode == MODE_GETNEXT) {
598
 
          DEBUGMSGTL(("winExtDLL", "win: MODE_GETNEXT -\n"));
599
 
          if (xSnmpExtensionQueryEx) {
600
 
            DEBUGMSGTL(("winExtDLL", "Calling xSnmpExtensionQueryEx\n"));
601
 
            result = xSnmpExtensionQueryEx(SNMP_PDU_GETNEXT, 1, &pVarBindList, NULL, &pErrorStatus, &pErrorIndex);
602
 
          }
603
 
          else { 
604
 
            DEBUGMSGTL(("winExtDLL", "Calling xSnmpExtensionQuery\n"));
605
 
            result = xSnmpExtensionQuery(SNMP_PDU_GETNEXT, &pVarBindList, &pErrorStatus, &pErrorIndex);
606
 
          } 
607
 
 
608
 
          DEBUGMSGTL(("winExtDLL", "Windows OID returned from xSnmpExtensionQuery(Ex): "));
609
 
          DEBUGMSGWINOID(("winExtDLL", pVarBindList.list));
610
 
          DEBUGMSG(("winExtDLL", "\n"));
611
 
 
612
 
          // Convert OID from Windows to Net-SNMP so Net-SNMP has the new 'next' OID
613
 
          // FIXME:  Do we need to realloc var->name or is is MAX_OID_LEN?
614
 
          for (i = 0; i < (pVarBindList.list->name.idLength > MAX_OID_LEN?MAX_OID_LEN:pVarBindList.list->name.idLength); i++) {
615
 
            var->name[i] = (oid)pVarBindList.list->name.ids[i];
616
 
          }
617
 
          var->name_length = i;
618
 
 
619
 
          DEBUGMSGTL(("winExtDLL", "Comparing: "));
620
 
          DEBUGMSGOID(("winExtDLL", var->name, var->name_length));
621
 
          DEBUGMSG(("winExtDLL", "\n"));       
622
 
 
623
 
          DEBUGMSGTL(("winExtDLL", "to:        "));
624
 
          DEBUGMSGOID(("winExtDLL", winExtensionAgent_name, winExtensionAgent_name_length));
625
 
          DEBUGMSG(("winExtDLL", "\n"));       
626
 
          
627
 
 
628
 
          // If the OID we got back is less than or equal to what we requested, increment the current supported view
629
 
          // and send it back instead.
630
 
          if (snmp_oid_compare(var->name, var->name_length, oid_requested, oid_requested_length) <= 0) {
631
 
            DEBUGMSGTL(("winExtDLL", "xSnmpExtensionQuery(Ex) returned an OID less than or equal to what we requested\n"));
632
 
            DEBUGMSGTL(("winExtDLL", " Setting return OID to be equal to current supported view, plus one\n"));
633
 
 
634
 
            // Set var->name to be equal to current supported view, plus one
635
 
            for (i = 0; i < (winExtensionAgent_name_length > MAX_OID_LEN? MAX_OID_LEN: winExtensionAgent_name_length); i++) {
636
 
              var->name[i] = winExtensionAgent_name[i];
637
 
            }
638
 
            var->name_length = i;
639
 
            var->name[i-1]++;
640
 
 
641
 
            //return SNMP_ERR_NOSUCHNAME;
642
 
            
643
 
          }
644
 
 
645
 
          // If the OID we got back is outside our view, increment the current supported view and send it back instead.
646
 
          // This is for Windows extension agents that support multiple views.  We want Net-SNMP to decide if we should be
647
 
          // called for this OID, not the extension agent, just in case there is a Net-SNMP agent in between.
648
 
          else if (snmp_oidtree_compare(var->name, var->name_length, winExtensionAgent_name, winExtensionAgent_name_length) > 0) {
649
 
            DEBUGMSGTL(("winExtDLL", "xSnmpExtensionQuery(Ex) returned an OID outside our view\n"));
650
 
            DEBUGMSGTL(("winExtDLL", " Setting return OID to be equal to current supported view, plus one\n"));
651
 
 
652
 
            // Set var->name to be equal to current supported view, plus one
653
 
            for (i = 0; i < (winExtensionAgent_name_length > MAX_OID_LEN? MAX_OID_LEN: winExtensionAgent_name_length); i++) {
654
 
              var->name[i] = winExtensionAgent_name[i];
655
 
            }
656
 
            var->name_length = i;
657
 
            var->name[i-1]++;
658
 
 
659
 
            //return SNMP_ERR_NOSUCHNAME;
660
 
            
661
 
          }
662
 
       }       
663
 
        DEBUGMSGTL(("winExtDLL", "OID being sent back to Net-SNMP: "));
664
 
        DEBUGMSGOID(("winExtDLL", var->name, var->name_length));
665
 
        DEBUGMSG(("winExtDLL", "\n"));
666
 
 
667
 
        DEBUGMSGTL(("winExtDLL", "win: Result of xSnmpExtensionQuery(Ex): %d\n",result));
668
 
        
669
 
        DEBUGMSGTL(("winExtDLL", "win: Error status of xSnmpExtensionQuery(Ex): %d\n",pErrorStatus));
670
 
 
671
 
        DEBUGMSGTL(("winExtDLL", "win: asnType: %d\n",pVarBindList.list->value.asnType));
672
 
      
673
 
        // Set Net-SNMP ASN type based on closest match to Windows ASN type
674
 
        switch (pVarBindList.list->value.asnType) {
675
 
          case MS_ASN_OCTETSTRING:
676
 
            netsnmp_ASN_type = ASN_OCTET_STR;
677
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_OCTETSTRING = ASN_OCTET_STR\n"));
678
 
            break;
679
 
          case MS_ASN_INTEGER:          // And MS_ASN_INTEGER32
680
 
            netsnmp_ASN_type = ASN_INTEGER;
681
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_INTEGER = ASN_INTEGER\n"));
682
 
            break;
683
 
          case MS_ASN_UNSIGNED32:       // SNMP v2
684
 
            netsnmp_ASN_type = ASN_UNSIGNED;
685
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_UNSIGNED32 = ASN_UNSIGNED\n"));
686
 
            break;
687
 
          case MS_ASN_COUNTER64:       // SNMP v2
688
 
            netsnmp_ASN_type = ASN_COUNTER64;
689
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER64 = ASN_COUNTER64\n"));
690
 
            break;
691
 
          case MS_ASN_BITS:
692
 
            netsnmp_ASN_type = ASN_BIT_STR;
693
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_BITS = ASN_BIT_STR\n"));
694
 
            break;
695
 
          case MS_ASN_OBJECTIDENTIFIER:
696
 
            netsnmp_ASN_type = ASN_OBJECT_ID;
697
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_OBJECTIDENTIFIER = ASN_OBJECT_ID\n"));
698
 
            break;
699
 
          case MS_ASN_SEQUENCE:
700
 
            netsnmp_ASN_type = ASN_SEQUENCE;
701
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_SEQUENCE = ASN_SEQUENCE\n"));
702
 
            break;
703
 
          case MS_ASN_IPADDRESS:
704
 
            netsnmp_ASN_type = ASN_IPADDRESS;
705
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_IPADDRESS = ASN_IPADDRESS\n"));
706
 
            break;
707
 
          case MS_ASN_COUNTER32:
708
 
            netsnmp_ASN_type = ASN_COUNTER;
709
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER32 = ASN_COUNTER\n"));
710
 
            break;
711
 
          case MS_ASN_GAUGE32:
712
 
            netsnmp_ASN_type = ASN_GAUGE;
713
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_GAUGE32 = ASN_GAUGE\n"));
714
 
            break;
715
 
          case MS_ASN_TIMETICKS:
716
 
            netsnmp_ASN_type = ASN_TIMETICKS;
717
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_TIMETICKS = ASN_TIMETICKS\n"));
718
 
            break;
719
 
          case MS_ASN_OPAQUE:
720
 
            netsnmp_ASN_type = ASN_OPAQUE;
721
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_OPAQUE = ASN_OPAQUE\n"));
722
 
            break;
723
 
          default:
724
 
            netsnmp_ASN_type = ASN_INTEGER;
725
 
            DEBUGMSGTL(("winExtDLL", "unknown MS ASN type.  Defaulting to ASN_INTEGER\n"));
726
 
            break;
727
 
        }
728
 
 
729
 
        DEBUGMSGTL(("winExtDLL", "Net-SNMP object type for returned value: %d\n",netsnmp_ASN_type));
730
 
 
731
 
        switch (pVarBindList.list->value.asnType) {
732
 
          case MS_ASN_IPADDRESS:
733
 
          case MS_ASN_OCTETSTRING:           
734
 
            
735
 
            strncpy(ret_szbuf_temp, pVarBindList.list->value.asnValue.string.stream, (pVarBindList.list->value.asnValue.string.length > 
736
 
                  SZBUF_MAX?SZBUF_MAX:pVarBindList.list->value.asnValue.string.length));
737
 
           
738
 
            if (pVarBindList.list->value.asnValue.string.length < SZBUF_MAX) 
739
 
              ret_szbuf_temp[pVarBindList.list->value.asnValue.string.length] = '\0';
740
 
            else
741
 
              ret_szbuf_temp[SZBUF_MAX-1] = '\0';
742
 
 
743
 
            // Printing strings that have a comma in them via DEBUGMSGTL doesn't work..
744
 
            DEBUGMSGTL(("winExtDLL", "Note:  Sometimes junk is outputted here even though the string is fine.  Problem with DEBUGMSGTL?\n",ret_szbuf_temp));
745
 
            DEBUGMSGTL(("winExtDLL", "win: String: %s\n",ret_szbuf_temp));
746
 
            DEBUGMSGTL(("winExtDLL", "win: length of string response: %d\n",strlen(ret_szbuf_temp)));
747
 
            
748
 
            snmp_set_var_typed_value(var, netsnmp_ASN_type,
749
 
                ret_szbuf_temp,
750
 
                strlen(ret_szbuf_temp));
751
 
            //return SNMP_ERR_NOERROR;           
752
 
            break;
753
 
 
754
 
          case MS_ASN_INTEGER:          // And MS_ASN_INTEGER32
755
 
          case MS_ASN_UNSIGNED32:
756
 
          case MS_ASN_COUNTER64:
757
 
          case MS_ASN_BITS:
758
 
          case MS_ASN_SEQUENCE:
759
 
          case MS_ASN_COUNTER32:
760
 
          case MS_ASN_GAUGE32:
761
 
          case MS_ASN_TIMETICKS:
762
 
          case MS_ASN_OPAQUE:
763
 
 
764
 
            DEBUGMSGTL(("winExtDLL", "win: Long: %ld\n",pVarBindList.list->value.asnValue.number));
765
 
 
766
 
            ret_long = pVarBindList.list->value.asnValue.number;
767
 
 
768
 
            // Return results
769
 
            snmp_set_var_typed_value(var, netsnmp_ASN_type,
770
 
                &ret_long,
771
 
                sizeof(ret_long));
772
 
            //return SNMP_ERR_NOERROR;           
773
 
            break;
774
 
 
775
 
          case MS_ASN_OBJECTIDENTIFIER:
776
 
            // Convert OID to Net-SNMP
777
 
 
778
 
            DEBUGMSGTL(("winExtDLL", "Returned OID: "));
779
 
            DEBUGMSGWINOID(("winExtDLL", &pVarBindList.list->value.asnValue.object));
780
 
            DEBUGMSG(("winExtDLL", "\n"));
781
 
           
782
 
            // Convert OID from Windows to Net-SNMP
783
 
            for (i = 0; i < (pVarBindList.list->value.asnValue.object.idLength > MAX_OID_LEN?MAX_OID_LEN:
784
 
                  pVarBindList.list->value.asnValue.object.idLength); i++) {
785
 
              ret_oid[i] = (oid)pVarBindList.list->value.asnValue.object.ids[i];
786
 
            }
787
 
            ret_oid_length = i;
788
 
           
789
 
            DEBUGMSGTL(("winExtDLL", "Windows OID converted to Net-SNMP: "));
790
 
            DEBUGMSGOID(("winExtDLL", ret_oid, ret_oid_length));
791
 
            DEBUGMSG(("winExtDLL", "\n"));
792
 
                      
793
 
            snmp_set_var_typed_value(var, netsnmp_ASN_type,
794
 
                ret_oid,
795
 
                ret_oid_length  * sizeof(oid));
796
 
            //return SNMP_ERR_NOERROR;           
797
 
            
798
 
            break;
799
 
            
800
 
          default:
801
 
            // The Windows agent didn't return data so set values to NULL
802
 
            // FIXME:  We never get here.  We set it to INTEGER above..
803
 
            snmp_set_var_typed_value(var, NULL,
804
 
                NULL,
805
 
                NULL);
806
 
            break;
807
 
        }
808
 
        if (&pVarBindList)
809
 
          SnmpUtilVarBindListFree(&pVarBindList);
810
 
      }  
811
 
      break;
812
 
 
813
 
    case MODE_SET_RESERVE1:     
 
701
        mode_name = "GETNEXT";
 
702
        nRequestType = SNMP_EXTENSION_GET_NEXT;
 
703
        assert(!context_info_head);
 
704
        break;
 
705
    case MODE_SET_RESERVE1:
 
706
        mode_name = "SET_RESERVE1";
 
707
        nRequestType = SNMP_EXTENSION_SET_TEST;
 
708
        break;
814
709
    case MODE_SET_RESERVE2:
 
710
        mode_name = "SET_RESERVE2";
 
711
        return SNMP_ERR_NOERROR;
815
712
    case MODE_SET_ACTION:
816
 
 
817
 
      DEBUGMSGTL(("winExtDLL", "SET requested\n"));
818
 
      
819
 
      for (request = requests; request; request=request->next) {
820
 
 
821
 
        var = request->requestvb;
822
 
        
823
 
        DEBUGMSGTL(("winExtDLL", "requested: "));
824
 
        DEBUGMSGOID(("winExtDLL", var->name, var->name_length));
825
 
        DEBUGMSG(("winExtDLL", "\n"));       
826
 
 
827
 
        DEBUGMSGTL(("winExtDLL", "Var type requested: %d\n",var->type));
828
 
 
829
 
        /* Loop through all the winExtensionAgent's looking for a matching handler */
830
 
        xSnmpExtensionQuery = NULL;
831
 
        xSnmpExtensionQueryEx = NULL;
832
 
        for (i=0; winExtensionAgent[i].xSnmpExtensionInit && i < MAX_WINEXT_DLLS; i++) {
833
 
          DEBUGMSGTL(("winExtDLL", "Looping through all the winExtensionAgent's looking for a matching handler.\n"));
834
 
          
835
 
          if (snmp_oidtree_compare(var->name, var->name_length, winExtensionAgent[i].name, 
836
 
                winExtensionAgent[i].name_length) >= 0) {
837
 
            DEBUGMSGTL(("winExtDLL", "Found match: "));
838
 
            DEBUGMSGOID(("winExtDLL", winExtensionAgent[i].name, winExtensionAgent[i].name_length));
839
 
            DEBUGMSG(("winExtDLL", "\n"));
840
 
            xSnmpExtensionQuery = winExtensionAgent[i].xSnmpExtensionQuery;
841
 
            xSnmpExtensionQueryEx = winExtensionAgent[i].xSnmpExtensionQueryEx;
842
 
            break;
843
 
          }
844
 
        }
845
 
 
846
 
        if (! (xSnmpExtensionQuery || xSnmpExtensionQueryEx)) {
847
 
          DEBUGMSGTL(("winExtDLL","Could not find a handler for the requested OID.  This should never happen!!\n"));
848
 
          return SNMP_ERR_GENERR;
849
 
        }
850
 
 
851
 
        // Set Windows ASN type based on closest match to Net-SNMP ASN type
852
 
        switch (var->type) {
853
 
          case ASN_OCTET_STR:
854
 
            windows_ASN_type = MS_ASN_OCTETSTRING;
855
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_OCTETSTRING = ASN_OCTET_STR\n"));
856
 
            break;
857
 
          case ASN_INTEGER:          // And MS_ASN_INTEGER32
858
 
            windows_ASN_type = MS_ASN_INTEGER;
859
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_INTEGER = ASN_INTEGER\n"));
860
 
            break;
861
 
          case ASN_UNSIGNED:
862
 
            windows_ASN_type = MS_ASN_UNSIGNED32;
863
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_UNSIGNED32 = ASN_UNSIGNED\n"));
864
 
            break;
865
 
          case ASN_COUNTER64:
866
 
            windows_ASN_type = MS_ASN_COUNTER64;
867
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER64 = ASN_COUNTER64\n"));
868
 
            break;
869
 
          case ASN_BIT_STR:
870
 
            windows_ASN_type = MS_ASN_BITS;
871
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_BITS = ASN_BIT_STR\n"));
872
 
            break;
873
 
          case ASN_OBJECT_ID:
874
 
            windows_ASN_type = MS_ASN_OBJECTIDENTIFIER;
875
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_OBJECTIDENTIFIER = ASN_OBJECT_ID\n"));
876
 
            break;
877
 
          case ASN_SEQUENCE:
878
 
            windows_ASN_type = MS_ASN_SEQUENCE;
879
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_SEQUENCE = ASN_SEQUENCE\n"));
880
 
            break;
881
 
          case ASN_IPADDRESS:
882
 
            windows_ASN_type = MS_ASN_IPADDRESS;
883
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_IPADDRESS = ASN_IPADDRESS\n"));
884
 
            break;
885
 
          case ASN_COUNTER:
886
 
            windows_ASN_type = MS_ASN_COUNTER32;
887
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER32 = ASN_COUNTER\n"));
888
 
            break;
889
 
//          case ASN_GAUGE:                     // Same as UNSIGNED
890
 
//            windows_ASN_type = MS_ASN_GAUGE32;
891
 
//            DEBUGMSGTL(("winExtDLL", "MS_ASN_GAUGE32 = ASN_GAUGE\n"));
892
 
//          break;
893
 
          case ASN_TIMETICKS:
894
 
            windows_ASN_type = MS_ASN_TIMETICKS;
895
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_TIMETICKS = ASN_TIMETICKS\n"));
896
 
            break;
897
 
          case ASN_OPAQUE:
898
 
            windows_ASN_type = MS_ASN_OPAQUE;
899
 
            DEBUGMSGTL(("winExtDLL", "MS_ASN_OPAQUE = ASN_OPAQUE\n"));
900
 
            break;
901
 
          default:
902
 
            windows_ASN_type = MS_ASN_INTEGER;
903
 
            DEBUGMSGTL(("winExtDLL", "unknown MS ASN type.  Defaulting to ASN_INTEGER\n"));
904
 
            break;
905
 
        }
906
 
 
907
 
        DEBUGMSGTL(("winExtDLL", "Net-SNMP object type for returned value: %d\n",windows_ASN_type));
908
 
 
909
 
        // Query
910
 
        pVarBindList.list = (SnmpVarBind *) SnmpUtilMemAlloc(sizeof (SnmpVarBind));
911
 
        if (pVarBindList.list) {
912
 
          // Convert OID from Net-SNMP to Windows         
913
 
          pVarBindList.list->name.ids = (UINT *) SnmpUtilMemAlloc(sizeof (UINT) *var->name_length);
914
 
 
915
 
          if (pVarBindList.list->name.ids) {
916
 
            // Actual copy
917
 
            for (i = 0; i < var->name_length; i++) {
918
 
              pVarBindList.list->name.ids[i] = (UINT)var->name[i];
919
 
            }
920
 
            pVarBindList.list->name.idLength = i;
921
 
 
922
 
            // Print OID
923
 
            DEBUGMSGTL(("winExtDLL","Windows OID length: %d\n",pVarBindList.list->name.idLength));
924
 
            DEBUGMSGTL(("winExtDLL","Windows OID: "));
925
 
            DEBUGMSGWINOID(("winExtDLL", pVarBindList.list));
926
 
            DEBUGMSG(("winExtDLL", "\n"));
927
 
          }
928
 
          else {
929
 
            DEBUGMSGTL(("winExtDLL", "\nyCould not allocate memory for Windows SNMP varbind.\n"));
930
 
            return (0);
931
 
          }
932
 
          //pVarBindList.list = pVarBindList.list;
933
 
          pVarBindList.len = 1;          
934
 
        }
935
 
        else {
936
 
          DEBUGMSGTL(("winExtDLL", "\nyCould not allocate memory for Windows SNMP varbind list.\n"));
937
 
          return (0);
938
 
        }
939
 
                        
940
 
        // Set Windows ASN type
941
 
        pVarBindList.list->value.asnType = windows_ASN_type;
942
 
          
943
 
        switch (var->type) {
944
 
          case ASN_IPADDRESS:
945
 
          case ASN_OCTET_STR:            
946
 
 
947
 
            strncpy(set_szbuf_temp, var->val.string, (var->val_len > SZBUF_MAX?SZBUF_MAX:var->val_len));
948
 
 
949
 
            // Make sure string is terminated
950
 
            set_szbuf_temp[var->val_len > SZBUF_MAX?SZBUF_MAX:var->val_len] = '\0';
951
 
 
952
 
            DEBUGMSGTL(("winExtDLL", "String to write: %s\n",set_szbuf_temp));
953
 
            DEBUGMSGTL(("winExtDLL", "Length of string to write: %d\n",strlen(set_szbuf_temp)));
954
 
 
955
 
            pVarBindList.list->value.asnValue.string.stream = set_szbuf_temp;
956
 
            pVarBindList.list->value.asnValue.string.length = strlen(set_szbuf_temp);
957
 
            pVarBindList.list->value.asnValue.string.dynamic = 0;
958
 
            
959
 
            break;
960
 
 
961
 
          case ASN_INTEGER:          // And MS_ASN_INTEGER32
962
 
          case ASN_UNSIGNED:
963
 
          case ASN_COUNTER64:
964
 
          case ASN_BIT_STR:
965
 
          case ASN_SEQUENCE:
966
 
          case ASN_COUNTER:
967
 
          case ASN_TIMETICKS:
968
 
          case ASN_OPAQUE:        
969
 
            
970
 
            pVarBindList.list->value.asnValue.number = *(var->val.integer);
971
 
            break;
972
 
              
973
 
          case ASN_OBJECT_ID:
974
 
            
975
 
            // Convert OID from Net-SNMP to Windows
976
 
            temp_oid = var->val.objid;
977
 
            temp_oid_length = var->val_len / sizeof(oid);           
978
 
            
979
 
            DEBUGMSGTL(("winExtDLL","Sizeof var->val.objid: %d\n", temp_oid_length));
980
 
 
981
 
            DEBUGMSGTL(("winExtDLL","OID: from user "));
982
 
            DEBUGMSGOID(("winExtDLL", temp_oid, temp_oid_length));
983
 
            DEBUGMSG(("winExtDLL","\n"));
984
 
            
985
 
            mySnmpVarBind->name.ids = (UINT *) SnmpUtilMemAlloc(sizeof (UINT) * temp_oid_length);
986
 
 
987
 
            if (mySnmpVarBind->name.ids) {
988
 
              // Actual copy
989
 
              for (i = 0; i < temp_oid_length; i++) {
990
 
                mySnmpVarBind->name.ids[i] = (UINT)temp_oid[i];
991
 
              }
992
 
              mySnmpVarBind->name.idLength = i;
993
 
              
994
 
              // Print OID
995
 
              DEBUGMSGTL(("winExtDLL","Windows OID length: %d\n",mySnmpVarBind->name.idLength));
996
 
              DEBUGMSGTL(("winExtDLL","Windows OID: "));
997
 
              DEBUGMSGWINOID(("winExtDLL", mySnmpVarBind));
998
 
              DEBUGMSG(("winExtDLL", "\n"));
999
 
            }
1000
 
            else {
1001
 
              DEBUGMSGTL(("winExtDLL", "\nyCould not allocate memory for Windows SNMP varbind.\n"));
1002
 
              return SNMP_ERR_GENERR;
1003
 
            }
1004
 
            SnmpUtilOidCpy(&pVarBindList.list->value.asnValue.object, &mySnmpVarBind->name);
1005
 
            //pVarBindList.list->value.asnValue.object = mySnmpVarBind->name;
1006
 
            if (mySnmpVarBind)
1007
 
              SnmpUtilVarBindFree(mySnmpVarBind);
1008
 
            
1009
 
          default:
1010
 
            break;      
1011
 
        }  
1012
 
 
1013
 
        if (xSnmpExtensionQueryEx) {
1014
 
          DEBUGMSGTL(("winExtDLL", "Calling xSnmpExtensionQueryEx\n"));
1015
 
          result = xSnmpExtensionQueryEx(SNMP_PDU_SET, 1, &pVarBindList, NULL, &pErrorStatus, &pErrorIndex);
1016
 
        }
1017
 
        else { 
1018
 
          DEBUGMSGTL(("winExtDLL", "Calling xSnmpExtensionQuery\n"));
1019
 
          result = xSnmpExtensionQuery(SNMP_PDU_SET, &pVarBindList, &pErrorStatus, &pErrorIndex);
1020
 
        }
1021
 
 
1022
 
        DEBUGMSGTL(("winExtDLL", "win: Result of xSnmpExtensionQuery: %d\n",result));        
1023
 
        DEBUGMSGTL(("winExtDLL", "win: Error status of xSnmpExtensionQuery: %d\n",pErrorStatus));
1024
 
        DEBUGMSGTL(("winExtDLL", "win: asnType: %d\n",pVarBindList.list->value.asnType));
1025
 
 
1026
 
        if (result == 0) {
1027
 
          DEBUGMSGTL(("winExtDLL", "\nyxWindows SnmpExtensionQuery failure.\n"));
1028
 
          return SNMP_ERR_GENERR;
1029
 
        }
1030
 
        
1031
 
        if (&pVarBindList)
1032
 
          SnmpUtilVarBindListFree(&pVarBindList);
1033
 
 
1034
 
        if (pErrorStatus) {
1035
 
          switch (pErrorStatus) {
1036
 
            case SNMP_ERRORSTATUS_INCONSISTENTNAME:
1037
 
              return SNMP_ERR_GENERR;
1038
 
            default:
1039
 
              return pErrorStatus;
1040
 
              break;
1041
 
          }
1042
 
        }
1043
 
      }
1044
 
      break;     
1045
 
 
 
713
        mode_name = "SET_ACTION";
 
714
        return SNMP_ERR_NOERROR;
1046
715
    case MODE_SET_UNDO:
 
716
        mode_name = "SET_UNDO";
 
717
        nRequestType = SNMP_EXTENSION_SET_UNDO;
 
718
        break;
1047
719
    case MODE_SET_COMMIT:
 
720
        mode_name = "SET_COMMIT";
 
721
        nRequestType = SNMP_EXTENSION_SET_COMMIT;
 
722
        break;
1048
723
    case MODE_SET_FREE:
1049
 
 
1050
 
      break;
1051
 
      
 
724
        mode_name = "SET_FREE";
 
725
        nRequestType = SNMP_EXTENSION_SET_CLEANUP;
 
726
        break;
1052
727
    default:
1053
 
        snmp_log(LOG_WARNING, "unsupported mode for winExtDLL called (%d)\n",
1054
 
                               reqinfo->mode);
 
728
        DEBUGMSG(("winExtDLL",
 
729
                  "internal error: invalid mode %d.\n", reqinfo->mode));
 
730
        assert(0);
1055
731
        return SNMP_ERR_NOERROR;
1056
732
    }
1057
733
 
1058
 
    return SNMP_ERR_NOERROR;
1059
 
}
1060
 
 
1061
 
void winExtDLL_free_config_winExtDLL(void) {
1062
 
}
1063
 
 
1064
 
void read_ExtensionAgents_list() {
1065
 
  HKEY          hKey; 
1066
 
  unsigned char * key_value = NULL;
1067
 
  DWORD         key_value_size = 0;
1068
 
  DWORD         key_value_type = 0;
1069
 
  DWORD         valueSize = MAX_VALUE_NAME; 
1070
 
  int           i;
1071
 
  TCHAR         valueName[MAX_VALUE_NAME];
1072
 
  TCHAR         valueName2[MAX_VALUE_NAME];
1073
 
  DWORD         retCode;
1074
 
  
1075
 
  DEBUGMSGTL(("winExtDLL", "read_ExtensionAgents_list called\n"));
1076
 
 
1077
 
  /* The Windows SNMP service stores the list of extension agents to be loaded in the
1078
 
   * registry under HKLM\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ExtensionAgents.
1079
 
   * This list contains a list of other keys that contain the actual file path to the DLL.
1080
 
   */
1081
 
 
1082
 
  /* Open SYSTEM\\CurrentControlSet\\Services\\SNMP\\Parameters\\ExtensionAgent */
1083
 
  retCode = RegOpenKeyExA(
1084
 
      HKEY_LOCAL_MACHINE, 
1085
 
      "SYSTEM\\CurrentControlSet\\Services\\SNMP\\Parameters\\ExtensionAgents", 
1086
 
      0, 
1087
 
      KEY_QUERY_VALUE, 
1088
 
      &hKey);
1089
 
  
1090
 
  if (retCode == ERROR_SUCCESS) {
1091
 
    /* Enumerate list of extension agents.  This is a list of other keys that contain the
1092
 
     * actual filename of the extension agent.  */
1093
 
    for (i=0; retCode==ERROR_SUCCESS; i++) 
1094
 
    { 
1095
 
      valueSize = MAX_VALUE_NAME; 
1096
 
      valueName[0] = '\0'; 
1097
 
      retCode = RegEnumValue(
1098
 
          hKey,
1099
 
          i,
1100
 
          valueName, 
1101
 
          &valueSize, 
1102
 
          NULL, 
1103
 
          NULL,
1104
 
          NULL,
1105
 
          NULL);
1106
 
      
1107
 
      if (retCode == ERROR_SUCCESS ) 
1108
 
      { 
1109
 
        /* Get key name that contains the actual filename of the extension agent */
1110
 
        DEBUGMSGTL(("winExtDLL", "-----------------------------------------\n"));
1111
 
        DEBUGMSGTL(("winExtDLL", "Registry: (%d) %s\n", i+1, valueName));
1112
 
        
1113
 
        key_value_size = MAX_VALUE_NAME;
1114
 
        if (RegQueryValueExA(
1115
 
              hKey, 
1116
 
              valueName, 
1117
 
              NULL, 
1118
 
              &key_value_type, 
1119
 
              valueName2, 
1120
 
              &key_value_size) == ERROR_SUCCESS) {
1121
 
        }
1122
 
        DEBUGMSGTL(("winExtDLL", "key_value: %s\n",valueName2));
1123
 
        read_ExtensionAgents_list2(valueName2);
1124
 
        extDLLs_index++;
1125
 
      }
 
734
    rc = SNMP_ERR_NOERROR;
 
735
 
 
736
    for (request = requests; request; request = request->next) {
 
737
        netsnmp_variable_list *varbind;
 
738
        SnmpVarBindList win_varbinds;
 
739
        AsnInteger32    ErrorStatus;
 
740
        AsnInteger32    ErrorIndex;
 
741
        BOOL            result;
 
742
        BOOL            copy_value;
 
743
 
 
744
        memset(&win_varbinds, 0, sizeof(win_varbinds));
 
745
 
 
746
        if (request->processed || rc != SNMP_ERR_NOERROR)
 
747
            goto free_win_varbinds;
 
748
 
 
749
        if (reqinfo->mode == MODE_SET_RESERVE1)
 
750
            alloc_context_info(request->index);
 
751
 
 
752
        varbind = request->requestvb;
 
753
        assert(varbind);
 
754
 
 
755
        /*
 
756
         * Convert the Net-SNMP varbind to a Windows SNMP varbind list.
 
757
         */
 
758
        rc = convert_to_windows_varbind_list(&win_varbinds, varbind);
 
759
        if (rc != SNMP_ERR_NOERROR) {
 
760
            DEBUGMSG(("winExtDLL",
 
761
                      "converting varbind list to Windows format failed with"
 
762
                      " error code %d.\n", request->status));
 
763
            netsnmp_request_set_error(requests, rc);
 
764
            goto free_win_varbinds;
 
765
        }
 
766
 
 
767
        assert(win_varbinds.len == 1);
 
768
 
 
769
        /*
 
770
         * For a GetNext PDU, if the varbind OID comes lexicographically
 
771
         * before the root OID of this handler, replace it by the root OID.
 
772
         */
 
773
        if (reqinfo->mode == MODE_GETNEXT
 
774
            && snmp_oid_compare(win_varbinds.list[0].name.ids,
 
775
                                win_varbinds.list[0].name.idLength,
 
776
                                reginfo->rootoid,
 
777
                                reginfo->rootoid_len) < 0) {
 
778
            AsnObjectIdentifier Root =
 
779
                { reginfo->rootoid_len, reginfo->rootoid };
 
780
            SnmpUtilOidCpy(&win_varbinds.list[0].name, &Root);
 
781
        }
 
782
 
 
783
        if (ext_dll_info->pfSnmpExtensionQueryEx) {
 
784
            result = ext_dll_info->pfSnmpExtensionQueryEx(nRequestType,
 
785
                                                          1,
 
786
                                                          &win_varbinds,
 
787
                                                          get_context_info(request->index),
 
788
                                                          &ErrorStatus,
 
789
                                                          &ErrorIndex);
 
790
        } else if (ext_dll_info->pfSnmpExtensionQuery) {
 
791
            result =
 
792
                ext_dll_info->pfSnmpExtensionQuery((BYTE) nRequestType,
 
793
                                                   &win_varbinds,
 
794
                                                   &ErrorStatus,
 
795
                                                   &ErrorIndex);
 
796
        } else {
 
797
            snmp_log(LOG_ERR,
 
798
                     "error in extension DLL %s: SNMP query function missing.\n",
 
799
                     ext_dll_info->dll_name);
 
800
            result = FALSE;
 
801
        }
 
802
 
 
803
        if (!result) {
 
804
            snmp_log(LOG_ERR,
 
805
                     "extension DLL %s: SNMP query function failed.\n",
 
806
                     ext_dll_info->dll_name);
 
807
            rc = SNMP_ERR_GENERR;
 
808
            goto free_win_varbinds;
 
809
        }
 
810
 
 
811
        rc = convert_win_snmp_err(ErrorStatus);
 
812
        if (rc != SNMP_ERR_NOERROR) {
 
813
            DEBUGMSG(("winExtDLL",
 
814
                      "extension DLL %s: SNMP query function returned error code %lu (Windows) / %d (Net-SNMP).\n",
 
815
                      ext_dll_info->dll_name, ErrorStatus, rc));
 
816
            assert(ErrorIndex == 1);
 
817
            netsnmp_request_set_error(requests, rc);
 
818
            if (rc == SNMP_NOSUCHOBJECT || rc == SNMP_NOSUCHINSTANCE
 
819
                || rc == SNMP_ERR_NOSUCHNAME)
 
820
                rc = SNMP_ERR_NOERROR;
 
821
            goto free_win_varbinds;
 
822
        }
 
823
 
 
824
        copy_value = FALSE;
 
825
        if (reqinfo->mode == MODE_GET)
 
826
            copy_value = TRUE;
 
827
        else if (reqinfo->mode == MODE_GETNEXT) {
 
828
            const SnmpVarBind *win_varbind;
 
829
 
 
830
            win_varbind = &win_varbinds.list[0];
 
831
 
 
832
            /*
 
833
             * Verify whether the OID returned by the extension DLL fits
 
834
             * inside the OID range this handler has been registered
 
835
             * with. Also compare the OID passed to the extension DLL with
 
836
             * the OID returned by the same DLL. If the DLL returned a
 
837
             * lexicographically earlier OID, this means that there is no
 
838
             * next OID in the MIB implemented by the DLL.
 
839
             *
 
840
             * Note: for some GetNext requests BoundsChecker will report
 
841
             * that the code below accesses a dangling pointer. This is
 
842
             * a limitation of BoundsChecker: apparently BoundsChecker is
 
843
             * not able to cope with reallocation of memory for
 
844
             * win_varbind by an SNMP extension DLL that has not been
 
845
             * instrumented by BoundsChecker.
 
846
             */
 
847
            if (netsnmp_oid_is_subtree(ext_dll_view_info->name,
 
848
                                       ext_dll_view_info->name_length,
 
849
                                       win_varbind->name.ids,
 
850
                                       win_varbind->name.idLength) == 0
 
851
                && snmp_oid_compare(varbind->name, varbind->name_length,
 
852
                                    win_varbind->name.ids,
 
853
                                    win_varbind->name.idLength) < 0) {
 
854
                /*
 
855
                 * Copy the OID returned by the extension DLL to the
 
856
                 * Net-SNMP varbind.
 
857
                 */
 
858
                snmp_set_var_objid(varbind,
 
859
                                   win_varbind->name.ids,
 
860
                                   win_varbind->name.idLength);
 
861
                copy_value = TRUE;
 
862
            }
 
863
        }
 
864
        if (copy_value) {
 
865
            netsnmp_variable_list *result_vb;
 
866
 
 
867
            /*
 
868
             * Copy the value returned by the extension DLL to the Net-SNMP
 
869
             * varbind.
 
870
             */
 
871
            result_vb = NULL;
 
872
            rc = append_windows_varbind(&result_vb, &win_varbinds.list[0]);
 
873
            assert(result_vb || rc != SNMP_ERR_NOERROR);
 
874
            if (result_vb) {
 
875
                snmp_set_var_typed_value(varbind,
 
876
                                         result_vb->type,
 
877
                                         result_vb->val.string,
 
878
                                         result_vb->val_len);
 
879
                snmp_free_varbind(result_vb);
 
880
            } else {
 
881
                netsnmp_request_set_error(requests, rc);
 
882
                goto free_win_varbinds;
 
883
            }
 
884
        }
 
885
 
 
886
free_win_varbinds:
 
887
        if (reqinfo->mode == MODE_SET_COMMIT
 
888
            || reqinfo->mode == MODE_SET_UNDO
 
889
            || reqinfo->mode == MODE_SET_FREE)
 
890
            free_context_info(request->index);
 
891
        if (win_varbinds.list)
 
892
            SnmpUtilVarBindListFree(&win_varbinds);
1126
893
    }
1127
 
    if (extDLLs_index)
1128
 
      extDLLs_index--;
1129
 
  }
1130
 
}
1131
 
 
1132
 
void read_ExtensionAgents_list2(const TCHAR *keyName) {
1133
 
  HKEY          hKey; 
1134
 
  unsigned char * key_value = NULL;
1135
 
  DWORD         key_value_size = 0;
1136
 
  DWORD         key_value_type = 0;
1137
 
  DWORD         valueSize = MAX_VALUE_NAME; 
1138
 
  TCHAR         valueName[MAX_VALUE_NAME];
1139
 
  TCHAR         valueNameExpanded[MAX_VALUE_NAME];
1140
 
  int           i;
1141
 
  DWORD         retCode;
1142
 
  
1143
 
  DEBUGMSGTL(("winExtDLL", "read_ExtensionAgents_list2 called\n"));
1144
 
  DEBUGMSGTL(("winExtDLL", "Registry: Opening key %s\n", keyName));
1145
 
 
1146
 
  /* Open extension agent's key */
1147
 
  retCode = RegOpenKeyExA(
1148
 
      HKEY_LOCAL_MACHINE, 
1149
 
      keyName, 
1150
 
      0, 
1151
 
      KEY_QUERY_VALUE, 
1152
 
      &hKey);
1153
 
  
1154
 
  if (retCode == ERROR_SUCCESS) {
1155
 
    /* Read Pathname value */
1156
 
 
1157
 
    DEBUGMSGTL(("winExtDLL", "Registry: Reading value for %s\n", keyName));
1158
 
       
1159
 
    key_value_size = MAX_VALUE_NAME;
1160
 
    retCode = RegQueryValueExA(
1161
 
        hKey, 
1162
 
        "Pathname", 
1163
 
        NULL, 
1164
 
        &key_value_type, 
1165
 
        valueName, 
1166
 
        &key_value_size);
1167
 
    
 
894
 
 
895
    return rc;
 
896
}
 
897
 
 
898
/**
 
899
 * Iterate over the SNMP extension DLL information in the registry and store
 
900
 * the retrieved information in s_winextdll[].
 
901
 *
 
902
 * At the time an SNMP extension DLL is installed, some information about the
 
903
 * DLL is written to the registry at one of the two following locations:
 
904
 * HKLM\SYSTEM\CurrentControlSet\Control\SNMP\Parameters\ExtensionAgents for
 
905
 * Windows Vista, Windows 7 and Windows 2008 or
 
906
 * HKLM\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ExtensionAgents for
 
907
 * earlier Windows versions. Under this key zero or more REG_SZ values are
 
908
 * stored with the names of registry keys containing the DLL path.
 
909
 */
 
910
void
 
911
read_extension_dlls_from_registry()
 
912
{
 
913
    DEBUGMSGTL(("winExtDLL",
 
914
                "read_extension_dlls_from_registry called\n"));
 
915
 
 
916
    read_extension_dlls_from_registry_at
 
917
        ("SYSTEM\\CurrentControlSet\\Services\\SNMP\\Parameters\\ExtensionAgents");
 
918
    read_extension_dlls_from_registry_at
 
919
        ("SYSTEM\\CurrentControlSet\\Control\\SNMP\\Parameters\\ExtensionAgents");
 
920
}
 
921
 
 
922
void
 
923
read_extension_dlls_from_registry_at(const char *const subkey)
 
924
{
 
925
    DWORD           retCode;
 
926
    HKEY            hKey;
 
927
    int             i;
 
928
    DWORD           valueSize;
 
929
    TCHAR           valueName[MAX_VALUE_NAME];
 
930
    DWORD           dataType;
 
931
    TCHAR           data[MAX_VALUE_NAME];
 
932
    DWORD           dataSize;
 
933
 
 
934
    retCode = RegOpenKeyExA(HKEY_LOCAL_MACHINE, subkey,
 
935
                            0, KEY_QUERY_VALUE, &hKey);
 
936
 
1168
937
    if (retCode == ERROR_SUCCESS) {
1169
 
      valueName[key_value_size-1] = NULL;               /* Make sure last element is a NULL */        
1170
 
      DEBUGMSGTL(("winExtDLL", "Extension agent Pathname size: %d\n",key_value_size));
1171
 
      DEBUGMSGTL(("winExtDLL", "Extension agent Pathname: %s\n",valueName));
1172
 
 
1173
 
      if (ExpandEnvironmentStrings(valueName, valueNameExpanded, MAX_VALUE_NAME)) {
1174
 
        DEBUGMSGTL(("winExtDLL", "Extension agent Pathname expanded: %s\n",valueNameExpanded));
1175
 
        if (extDLLs_index < MAX_WINEXT_DLLS) {
1176
 
 
1177
 
          extDLLs[extDLLs_index] = strdup(valueNameExpanded);
1178
 
          
1179
 
          if (extDLLs[extDLLs_index]) {
1180
 
            strcpy(extDLLs[extDLLs_index], valueNameExpanded );
1181
 
            DEBUGMSGTL(("winExtDLL", "Extension agent Pathname expanded extDLLs: %s\n",extDLLs[extDLLs_index]));
1182
 
            DEBUGMSGTL(("winExtDLL", "Extension agent Pathname size: %d\n",strlen(extDLLs[extDLLs_index])));
1183
 
          }
1184
 
          else {
1185
 
            DEBUGMSGTL(("winExtDLL", "Could not allocate memory for extDLLs[%d]\n",extDLLs_index));
1186
 
          }
1187
 
        }
1188
 
      }
1189
 
      else {
1190
 
        DEBUGMSGTL(("winExtDLL", "ExpandEnvironmentStrings failed\n"));
1191
 
      }      
1192
 
    }
1193
 
  }
1194
 
}
1195
 
 
1196
 
// Called by alarm to check for traps waiting to be processed.
1197
 
void subagentTrapCheck() {
1198
 
  DWORD dwWaitResult;
1199
 
  BOOL bResult;
1200
 
  int i;
1201
 
  netsnmp_variable_list *notification_vars = NULL;
1202
 
 
1203
 
  // Windows SNMP
1204
 
  AsnObjectIdentifier   pEnterprise;
1205
 
  AsnInteger            pGenericTrap;
1206
 
  AsnInteger            pSpecificTrap;
1207
 
  AsnTimeticks          pTimeStamp;
1208
 
  SnmpVarBindList       pVariableBindings;
1209
 
 
1210
 
  DEBUGMSGTL(("winExtDLL", "subagentTrapMonitor called\n"));
1211
 
 
1212
 
  dwWaitResult = WaitForMultipleObjects(
1213
 
      subagentTrapEvents_index,
1214
 
      subagentTrapEvents,
1215
 
      FALSE,
1216
 
      0);
1217
 
 
1218
 
  if (! (dwWaitResult) || (dwWaitResult == WAIT_TIMEOUT))
1219
 
    return;
1220
 
  
1221
 
  DEBUGMSGTL(("winExtDLL", "---------------------------------------------\n"));
1222
 
  DEBUGMSGTL(("winExtDLL", "subagentTrapCheck found a trap event (index: %d)\n",dwWaitResult));
1223
 
  
1224
 
  /* Loop through all the winExtensionAgent's looking for a matching handler */
1225
 
  for (i=0;  winExtensionAgent[i].xSnmpExtensionInit && i < MAX_WINEXT_DLLS; i++) {
1226
 
    DEBUGMSGTL(("winExtDLL", "Looping through all the winExtensionAgent's looking for a matching trap handler.\n"));
1227
 
 
1228
 
    if (winExtensionAgent[i].subagentTrapEvent == subagentTrapEvents[dwWaitResult]) {
1229
 
      DEBUGMSGTL(("winExtDLL", "Found match: "));
1230
 
      DEBUGMSGOID(("winExtDLL", winExtensionAgent[i].name, winExtensionAgent[i].name_length));
1231
 
      DEBUGMSG(("winExtDLL", "\n"));
1232
 
 
1233
 
      if (winExtensionAgent[i].xSnmpExtensionTrap)
1234
 
        DEBUGMSGTL(("winExtDLL", "xSnmpExtensionTrap exists for this subagent\n"));
1235
 
      else {
1236
 
        DEBUGMSGTL(("winExtDLL", "xSnmpExtensionTrap does NOT exist for this subagent\n"));
1237
 
        continue;
1238
 
      }
1239
 
 
1240
 
      pEnterprise.ids = NULL;
1241
 
      pEnterprise.idLength = 0;
1242
 
      pGenericTrap = pSpecificTrap = NULL;
1243
 
      pTimeStamp = 0;
1244
 
      pVariableBindings.list = NULL;
1245
 
      pVariableBindings.len = 0;
1246
 
 
1247
 
      DEBUGMSGTL(("winExtDLL", "Calling SnmpExtensionTrap\n"));
1248
 
      bResult = winExtensionAgent[i].xSnmpExtensionTrap(
1249
 
          &pEnterprise,
1250
 
          &pGenericTrap,
1251
 
          &pSpecificTrap,
1252
 
          &pTimeStamp,
1253
 
          &pVariableBindings);
1254
 
      
1255
 
      DEBUGMSGTL(("winExtDLL", "result of SnmpExtensionTrap call:  %d\n",bResult));
1256
 
 
1257
 
      
1258
 
      DEBUGMSGTL(("winExtDLL", "GenericTrap: %d\n",pGenericTrap));
1259
 
      DEBUGMSGTL(("winExtDLL", "SpecificTrap: %d\n",pSpecificTrap));
1260
 
 
1261
 
      if (pEnterprise.idLength)
1262
 
        DEBUGMSGTL(("winExtDLL", "pEnterprise is not 0\n"));
1263
 
      else
1264
 
        DEBUGMSGTL(("winExtDLL", "pEnterprise is 0\n"));
1265
 
 
1266
 
      // Assume that if enterprise length is >0, it's a real trap and not a cleanup call
1267
 
      // FIXME:  Not sure if this is correct.  Need to test with agent that sends a non-enterprise trap
1268
 
      if (pEnterprise.idLength) {
1269
 
        
1270
 
        // Send the trap
1271
 
        send_trap(
1272
 
            &pEnterprise, 
1273
 
            &pGenericTrap, 
1274
 
            &pSpecificTrap, 
1275
 
            &pTimeStamp,
1276
 
            &pVariableBindings);
1277
 
      }
1278
 
 
1279
 
      // Look for more traps from this agent (if result is TRUE there are more traps)
1280
 
      while(bResult) {
1281
 
        DEBUGMSGTL(("winExtDLL", "More traps to process.  Calling SnmpExtensionTrap again\n"));
1282
 
 
1283
 
        pEnterprise.ids = NULL;
1284
 
        pEnterprise.idLength = 0;
1285
 
        pGenericTrap = pSpecificTrap = NULL;
1286
 
        pTimeStamp = 0;
1287
 
        pVariableBindings.list = NULL;
1288
 
        pVariableBindings.len = 0;
1289
 
 
1290
 
        bResult = winExtensionAgent[i].xSnmpExtensionTrap(
1291
 
            &pEnterprise,
1292
 
            &pGenericTrap,
1293
 
            &pSpecificTrap,
1294
 
            &pTimeStamp,
1295
 
            &pVariableBindings);
1296
 
        
1297
 
        DEBUGMSGTL(("winExtDLL", "result of SnmpExtensionTrap call:  %d\n",bResult));
1298
 
 
1299
 
        // Assume that if enterprise length is >0, it's a real trap and not a cleanup call
1300
 
        // FIXME:  Not sure if this is correct.  Need to test with agent that sends a non-enterprise trap
1301
 
        if (pEnterprise.idLength) {
1302
 
          
1303
 
          DEBUGMSGTL(("winExtDLL", "GenericTrap: %d\n",pGenericTrap));
1304
 
          DEBUGMSGTL(("winExtDLL", "SpecificTrap: %d\n",pSpecificTrap));
1305
 
 
1306
 
          if (pEnterprise.idLength)
1307
 
            DEBUGMSGTL(("winExtDLL", "pEnterprise is not 0\n"));
1308
 
          else
1309
 
            DEBUGMSGTL(("winExtDLL", "pEnterprise is 0\n"));
1310
 
          
1311
 
          // Send the trap
1312
 
          send_trap(
1313
 
              &pEnterprise, 
1314
 
              &pGenericTrap, 
1315
 
              &pSpecificTrap,
1316
 
              &pTimeStamp,
1317
 
              &pVariableBindings);
1318
 
        }
1319
 
        SnmpUtilVarBindListFree(&pVariableBindings);
1320
 
      }
1321
 
      break;
1322
 
    }
1323
 
  }
1324
 
 
1325
 
  // Events should be auto-reset, but just in case..
1326
 
  ResetEvent(dwWaitResult);
1327
 
 
1328
 
  return 1;
1329
 
}
1330
 
 
1331
 
 
1332
 
void send_trap(
1333
 
    AsnObjectIdentifier *pEnterprise, 
1334
 
    AsnInteger *pGenericTrap, 
1335
 
    AsnInteger *pSpecificTrap, 
1336
 
    AsnTimeticks *pTimeStamp,
1337
 
    SnmpVarBindList *pVariableBindings) {
1338
 
 
1339
 
  int           i, j;
1340
 
  SnmpVarBind   mySnmpVarBind;
1341
 
  oid           my_oid[MAX_OID_LEN];               // Holder for pVariableBindings OIDs
1342
 
  size_t        my_oid_length = 0;                 // Holder for pVariableBindings OIDs
1343
 
 
1344
 
  oid           enterprise_oid[MAX_OID_LEN];       // Holder for enterprise OID
1345
 
  size_t        enterprise_oid_length = 0;          // Holder for enterprise OID
1346
 
 
1347
 
  oid           ret_oid[MAX_OID_LEN];               // Holder for return OIDs
1348
 
  size_t        ret_oid_length = 0;                 // Holder for return OIDs
1349
 
 
1350
 
  char          *stringtemp;
1351
 
 
1352
 
  /*
1353
 
   * here is where we store the variables to be sent in the trap 
1354
 
   */
1355
 
  netsnmp_variable_list *notification_vars = NULL;
1356
 
  
1357
 
  /*
1358
 
   * In the notification, we have to assign our notification OID to
1359
 
   * the snmpTrapOID.0 object. Here is it's definition. 
1360
 
   */
1361
 
  oid             objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
1362
 
  size_t          objid_snmptrap_len = OID_LENGTH(objid_snmptrap);
1363
 
 
1364
 
  DEBUGMSGTL(("winExtDLL", "send_trap() called\n"));
1365
 
  DEBUGMSGTL(("winExtDLL", "pVariableBindings length: %d\n",pVariableBindings->len));
1366
 
 
1367
 
  if (*pGenericTrap != 6) {
1368
 
    DEBUGMSGTL(("winExtDLL", "Working on generic trap\n"));
1369
 
    DEBUGMSGTL(("winExtDLL", "sending v1 trap\n"));
1370
 
    send_easy_trap(*pGenericTrap, *pSpecificTrap);
1371
 
    return;
1372
 
  }
1373
 
 
1374
 
  // Convert enterprise OID from Windows to Net-SNMP so Net-SNMP
1375
 
  for (j = 0; j < (pEnterprise->idLength > MAX_OID_LEN?MAX_OID_LEN:pEnterprise->idLength); j++) {
1376
 
    enterprise_oid[j] = (oid)pEnterprise->ids[j];
1377
 
  }
1378
 
  enterprise_oid_length = j;
1379
 
 
1380
 
  DEBUGMSGTL(("winExtDLL", "Enterprise OID: "));
1381
 
  DEBUGMSGOID(("winExtDLL", enterprise_oid, enterprise_oid_length));
1382
 
  DEBUGMSG(("winExtDLL", "\n"));
1383
 
 
1384
 
  // We need to copy .0.specific trap to copy of enterprise and use that for objid_snmptrap!!
1385
 
 
1386
 
  for (i = 0; i < enterprise_oid_length; i++) {
1387
 
    my_oid[i] = enterprise_oid[i];
1388
 
  }
1389
 
  my_oid_length = i;
1390
 
 
1391
 
  my_oid[my_oid_length] = 0;
1392
 
  my_oid_length++;
1393
 
 
1394
 
  my_oid[my_oid_length] = *pSpecificTrap;
1395
 
  my_oid_length++;
1396
 
 
1397
 
  DEBUGMSGTL(("winExtDLL", "Trap OID (snmpTrapOID.0): "));
1398
 
  DEBUGMSGOID(("winExtDLL", my_oid, my_oid_length));
1399
 
  DEBUGMSG(("winExtDLL", "\n"));
1400
 
 
1401
 
  /*
1402
 
   * add in the trap definition object 
1403
 
   */
1404
 
  snmp_varlist_add_variable(&notification_vars,
1405
 
      /*
1406
 
       * the snmpTrapOID.0 variable 
1407
 
       */
1408
 
      objid_snmptrap, objid_snmptrap_len,
1409
 
      /*
1410
 
       * value type is an OID 
1411
 
       */
1412
 
      ASN_OBJECT_ID,
1413
 
      /*
1414
 
       * value contents is our notification OID 
1415
 
       */
1416
 
      (u_char *) my_oid,
1417
 
      /*
1418
 
       * size in bytes
1419
 
       */
1420
 
      my_oid_length  * sizeof(oid));
1421
 
 
1422
 
  for (i = 0; i< pVariableBindings->len; i++) {
1423
 
 
1424
 
    mySnmpVarBind = pVariableBindings->list[i];
1425
 
 
1426
 
    // Convert OID from Windows to Net-SNMP so Net-SNMP
1427
 
    for (j = 0; j < (mySnmpVarBind.name.idLength > MAX_OID_LEN?MAX_OID_LEN:mySnmpVarBind.name.idLength); j++) {
1428
 
      my_oid[j] = (oid)mySnmpVarBind.name.ids[j];
1429
 
    }
1430
 
    my_oid_length = j;
1431
 
 
1432
 
    DEBUGMSGTL(("winExtDLL", "OID in trap variable binding: "));
1433
 
    DEBUGMSGOID(("winExtDLL", my_oid, my_oid_length));
1434
 
    DEBUGMSG(("winExtDLL", "\n"));
1435
 
 
1436
 
    // Set Net-SNMP ASN type based on closest match to Windows ASN type
1437
 
    switch (mySnmpVarBind.value.asnType) {
1438
 
      case MS_ASN_OCTETSTRING:        // AsnOctetString
1439
 
        stringtemp = netsnmp_strdup_and_null(mySnmpVarBind.value.asnValue.string.stream, mySnmpVarBind.value.asnValue.string.length);
1440
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_OCTETSTRING = ASN_OCTET_STR\n"));
1441
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_OCTETSTRING = %s\n",stringtemp));
1442
 
        snmp_varlist_add_variable(&notification_vars,
1443
 
            my_oid, my_oid_length,
1444
 
            ASN_OCTET_STR,
1445
 
            stringtemp,
1446
 
            strlen(stringtemp));
1447
 
        break;
1448
 
      case MS_ASN_INTEGER:          // And MS_ASN_INTEGER32
1449
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_INTEGER = ASN_INTEGER\n"));
1450
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_INTEGER = %d\n",mySnmpVarBind.value.asnValue.number));
1451
 
        snmp_varlist_add_variable(&notification_vars,
1452
 
            my_oid, my_oid_length,
1453
 
            ASN_INTEGER,
1454
 
            (u_char *)&mySnmpVarBind.value.asnValue.number,
1455
 
            sizeof(mySnmpVarBind.value.asnValue.number));
1456
 
        break;
1457
 
      case MS_ASN_UNSIGNED32:       // SNMP v2
1458
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_UNSIGNED32 = ASN_UNSIGNED\n"));
1459
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_UNSIGNED32 = %d\n",mySnmpVarBind.value.asnValue.unsigned32));
1460
 
        snmp_varlist_add_variable(&notification_vars,
1461
 
            my_oid, my_oid_length,
1462
 
            ASN_UNSIGNED,
1463
 
            (u_char *)&mySnmpVarBind.value.asnValue.unsigned32,
1464
 
            sizeof(mySnmpVarBind.value.asnValue.unsigned32));
1465
 
        break;
1466
 
      case MS_ASN_COUNTER64:       // SNMP v2
1467
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER64 = ASN_COUNTER64\n"));
1468
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER64 = %d\n",mySnmpVarBind.value.asnValue.counter64));
1469
 
        snmp_varlist_add_variable(&notification_vars,
1470
 
            my_oid, my_oid_length,
1471
 
            ASN_COUNTER64,
1472
 
            (u_char *)&mySnmpVarBind.value.asnValue.counter64,
1473
 
            sizeof(mySnmpVarBind.value.asnValue.counter64));
1474
 
        break;
1475
 
      case MS_ASN_BITS:               // AsnOctetString
1476
 
        stringtemp = netsnmp_strdup_and_null(mySnmpVarBind.value.asnValue.bits.stream, mySnmpVarBind.value.asnValue.bits.length);
1477
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_BITS = ASN_BIT_STR\n"));
1478
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_BITS = %s\n",stringtemp));
1479
 
        snmp_varlist_add_variable(&notification_vars,
1480
 
            my_oid, my_oid_length,
1481
 
            ASN_BIT_STR,
1482
 
            stringtemp,
1483
 
            strlen(stringtemp));
1484
 
        break;
1485
 
      case MS_ASN_OBJECTIDENTIFIER:   // AsnObjectIdentifier
1486
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_OBJECTIDENTIFIER = ASN_OBJECT_ID\n"));
1487
 
        // Convert OID to Net-SNMP
1488
 
 
1489
 
        DEBUGMSGTL(("winExtDLL", "Returned OID: "));
1490
 
        DEBUGMSGWINOID(("winExtDLL", &mySnmpVarBind.value.asnValue.object));
1491
 
        DEBUGMSG(("winExtDLL", "\n"));
1492
 
        
1493
 
        // Convert OID from Windows to Net-SNMP
1494
 
        for (i = 0; i < (mySnmpVarBind.value.asnValue.object.idLength > MAX_OID_LEN?MAX_OID_LEN:
1495
 
              mySnmpVarBind.value.asnValue.object.idLength); i++) {
1496
 
          ret_oid[i] = (oid)mySnmpVarBind.value.asnValue.object.ids[i];
1497
 
        }
1498
 
        ret_oid_length = i;
1499
 
        
1500
 
        DEBUGMSGTL(("winExtDLL", "Windows OID converted to Net-SNMP: "));
1501
 
        DEBUGMSGOID(("winExtDLL", ret_oid, ret_oid_length));
1502
 
        DEBUGMSG(("winExtDLL", "\n"));
1503
 
 
1504
 
        snmp_varlist_add_variable(&notification_vars,
1505
 
            my_oid, my_oid_length,
1506
 
            ASN_OBJECT_ID,
1507
 
            (u_char *)&ret_oid,
1508
 
            ret_oid_length * sizeof(oid));
1509
 
        break;
1510
 
      case MS_ASN_SEQUENCE:           // AsnOctetString
1511
 
        stringtemp = netsnmp_strdup_and_null(mySnmpVarBind.value.asnValue.sequence.stream, mySnmpVarBind.value.asnValue.sequence.length);
1512
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_SEQUENCE = ASN_SEQUENCE\n"));
1513
 
        snmp_varlist_add_variable(&notification_vars,
1514
 
            my_oid, my_oid_length,
1515
 
            ASN_SEQUENCE,
1516
 
            stringtemp,
1517
 
            strlen(stringtemp));
1518
 
        break;
1519
 
      case MS_ASN_IPADDRESS:          // AsnOctetString
1520
 
        stringtemp = netsnmp_strdup_and_null(mySnmpVarBind.value.asnValue.address.stream, mySnmpVarBind.value.asnValue.address.length);
1521
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_IPADDRESS = ASN_IPADDRESS\n"));
1522
 
        snmp_varlist_add_variable(&notification_vars,
1523
 
            my_oid, my_oid_length,
1524
 
            ASN_IPADDRESS,
1525
 
            stringtemp,
1526
 
            strlen(stringtemp));
1527
 
        break;
1528
 
      case MS_ASN_COUNTER32:          
1529
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER32 = ASN_COUNTER\n"));
1530
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_COUNTER32 = %d\n",mySnmpVarBind.value.asnValue.counter));
1531
 
        snmp_varlist_add_variable(&notification_vars,
1532
 
            my_oid, my_oid_length,
1533
 
            ASN_COUNTER,
1534
 
            (u_char *)&mySnmpVarBind.value.asnValue.counter,
1535
 
            sizeof(mySnmpVarBind.value.asnValue.counter));
1536
 
        break;
1537
 
      case MS_ASN_GAUGE32:
1538
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_GAUGE32 = ASN_GAUGE\n"));
1539
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_GAUGE32 = %d\n",mySnmpVarBind.value.asnValue.gauge));
1540
 
        snmp_varlist_add_variable(&notification_vars,
1541
 
            my_oid, my_oid_length,
1542
 
            ASN_GAUGE,
1543
 
            (u_char *)&mySnmpVarBind.value.asnValue.gauge,
1544
 
            sizeof(mySnmpVarBind.value.asnValue.gauge));
1545
 
        break;
1546
 
      case MS_ASN_TIMETICKS:
1547
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_TIMETICKS = ASN_TIMETICKS\n"));
1548
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_TIMETICKS = %d\n",mySnmpVarBind.value.asnValue.ticks));
1549
 
        snmp_varlist_add_variable(&notification_vars,
1550
 
            my_oid, my_oid_length,
1551
 
            ASN_TIMETICKS,
1552
 
            (u_char *)&mySnmpVarBind.value.asnValue.ticks,
1553
 
            sizeof(mySnmpVarBind.value.asnValue.ticks));
1554
 
        break;
1555
 
      case MS_ASN_OPAQUE:             // AsnOctetString
1556
 
        stringtemp = netsnmp_strdup_and_null(mySnmpVarBind.value.asnValue.arbitrary.stream, mySnmpVarBind.value.asnValue.arbitrary.length);
1557
 
        DEBUGMSGTL(("winExtDLL", "MS_ASN_OPAQUE = ASN_OPAQUE\n"));
1558
 
        snmp_varlist_add_variable(&notification_vars,
1559
 
            my_oid, my_oid_length,
1560
 
            ASN_OPAQUE,
1561
 
            stringtemp,
1562
 
            strlen(stringtemp));          break;
1563
 
      default:
1564
 
        DEBUGMSGTL(("winExtDLL", "Defaulting to ASN_INTEGER\n"));
1565
 
        break;
1566
 
    }
1567
 
  }
1568
 
  /*
1569
 
   * send the trap out.  This will send it to all registered
1570
 
   * receivers (see the "SETTING UP TRAP AND/OR INFORM DESTINATIONS"
1571
 
   * section of the snmpd.conf manual page. 
1572
 
   */
1573
 
 
1574
 
  DEBUGMSGTL(("winExtDLL", "sending v2 trap\n"));
1575
 
  send_v2trap(notification_vars);
1576
 
 
1577
 
  /*
1578
 
   * free the created notification variable list 
1579
 
   */
1580
 
  DEBUGMSGTL(("winExtDLL", "cleaning up\n"));
1581
 
  snmp_free_varbind(notification_vars);
1582
 
}
1583
 
 
1584
 
/* DEBUGMSGWINOID */
1585
 
void
1586
 
debugmsg_win_oid(const char *token, const AsnObjectIdentifier * theoid)
1587
 
{
1588
 
    u_char          buf[1024];
1589
 
    u_char          temp[10];
1590
 
    size_t          buf_len = 0, out_len = 0;
 
938
        for (i = 0; ; i++) {
 
939
            valueSize = sizeof(valueName);
 
940
            dataSize = sizeof(data);
 
941
            retCode = RegEnumValue(hKey, i, valueName, &valueSize, NULL,
 
942
                                   &dataType, (BYTE *) data, &dataSize);
 
943
 
 
944
            if (retCode != ERROR_SUCCESS)
 
945
                break;
 
946
            if (dataType == REG_SZ) {
 
947
                winextdll       ext_dll_info;
 
948
 
 
949
                memset(&ext_dll_info, 0, sizeof(ext_dll_info));
 
950
                ext_dll_info.dll_name =
 
951
                    read_extension_dll_path_from_registry(data);
 
952
                if (ext_dll_info.dll_name) {
 
953
                    xarray_push_back(&s_winextdll, &ext_dll_info);
 
954
                    DEBUGMSG(("winExtDLL", "registry key %s: DLL %s.\n",
 
955
                              data, ext_dll_info.dll_name));
 
956
                }
 
957
            }
 
958
        }
 
959
        RegCloseKey(hKey);
 
960
    }
 
961
}
 
962
 
 
963
/** Store the DLL path in dynamically allocated memory. */
 
964
char           *
 
965
read_extension_dll_path_from_registry(const TCHAR * keyName)
 
966
{
 
967
    HKEY            hKey;
 
968
    DWORD           key_value_type = 0;
 
969
    TCHAR           valueName[MAX_VALUE_NAME];
 
970
    DWORD           key_value_size = MAX_VALUE_NAME;
 
971
    TCHAR           valueNameExpanded[MAX_VALUE_NAME];
 
972
    DWORD           retCode;
 
973
    char           *result = 0;
 
974
 
 
975
    retCode = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
 
976
                            keyName, 0, KEY_QUERY_VALUE, &hKey);
 
977
 
 
978
    if (retCode != ERROR_SUCCESS)
 
979
        return 0;
 
980
 
 
981
    retCode = RegQueryValueExA(hKey,
 
982
                               "Pathname",
 
983
                               NULL,
 
984
                               &key_value_type,
 
985
                               (BYTE *) valueName, &key_value_size);
 
986
 
 
987
    if (retCode != ERROR_SUCCESS) {
 
988
        RegCloseKey(hKey);
 
989
        return 0;
 
990
    }
 
991
 
 
992
    if (key_value_type == REG_EXPAND_SZ) {
 
993
        if (ExpandEnvironmentStrings
 
994
            (valueName, valueNameExpanded, MAX_VALUE_NAME))
 
995
            result = strdup(valueNameExpanded);
 
996
    } else if (key_value_type == REG_SZ)
 
997
        result = strdup(valueName);
 
998
 
 
999
    RegCloseKey(hKey);
 
1000
    return result;
 
1001
}
 
1002
 
 
1003
/**
 
1004
 * Callback function called by the Net-SNMP agent to check for traps waiting
 
1005
 * to be processed.
 
1006
 */
 
1007
void
 
1008
subagentTrapCheck(unsigned int clientreg, void *clientarg)
 
1009
{
 
1010
    while (1) {
 
1011
        DWORD           dwWaitResult;
 
1012
        BOOL            bResult;
 
1013
        int             i;
 
1014
        int             j;
 
1015
        const winextdll *ext_dll_info;
 
1016
 
 
1017
        dwWaitResult = WaitForMultipleObjects(s_trapevent.size,
 
1018
                                              &TRAPEVENT(0), FALSE, 0);
 
1019
 
 
1020
        i = dwWaitResult - WAIT_OBJECT_0;
 
1021
        if (i < 0 || i >= s_trapevent.size) {
 
1022
            assert(dwWaitResult == WAIT_TIMEOUT);
 
1023
            return;
 
1024
        }
 
1025
 
 
1026
        assert(s_trapevent.size == s_trapevent_to_dllinfo.size);
 
1027
        ext_dll_info = TRAPEVENT_TO_DLLINFO(i);
 
1028
        assert(ext_dll_info->subagentTrapEvent == TRAPEVENT(i));
 
1029
 
 
1030
        /*
 
1031
         * Reset the signalled event just in case the extension DLL erroneously
 
1032
         * allocated a manual-reset event instead of an auto-reset event. It is
 
1033
         * important to reset the event BEFORE traps are processed, otherwise a
 
1034
         * race condition is triggered between the extension DLL setting the
 
1035
         * event and this code resetting the event.
 
1036
         */
 
1037
        ResetEvent(TRAPEVENT(i));
 
1038
 
 
1039
        if (!ext_dll_info->pfSnmpExtensionTrap) {
 
1040
            snmp_log(LOG_ERR,
 
1041
                     "internal error in SNMP extension DLL %s: a trap is ready"
 
1042
                     " but the function SnmpExtensionTrap() is missing.\n",
 
1043
                     ext_dll_info->dll_name);
 
1044
            return;
 
1045
        }
 
1046
 
 
1047
        /*
 
1048
         * Process at most hundred traps per extension DLL. If the extension DLL
 
1049
         * has more traps waiting, that's probably a bug in the extension DLL.
 
1050
         */
 
1051
        for (j = 0; j < 100; j++) {
 
1052
            AsnObjectIdentifier Enterprise = { 0, NULL };
 
1053
            AsnInteger      GenericTrap = 0;
 
1054
            AsnInteger      SpecificTrap = 0;
 
1055
            AsnTimeticks    TimeStamp = 0;
 
1056
            SnmpVarBindList TrapVarbinds = { NULL, 0 };
 
1057
 
 
1058
            bResult = ext_dll_info->pfSnmpExtensionTrap(&Enterprise,
 
1059
                                                        &GenericTrap,
 
1060
                                                        &SpecificTrap,
 
1061
                                                        &TimeStamp,
 
1062
                                                        &TrapVarbinds);
 
1063
 
 
1064
            if (!bResult)
 
1065
                break;
 
1066
 
 
1067
            send_trap(&Enterprise, GenericTrap, SpecificTrap, TimeStamp,
 
1068
                      &TrapVarbinds);
 
1069
 
 
1070
            SnmpUtilVarBindListFree(&TrapVarbinds);
 
1071
        }
 
1072
    }
 
1073
}
 
1074
 
 
1075
void
 
1076
send_trap(const AsnObjectIdentifier * const pEnterprise,
 
1077
          const AsnInteger GenericTrap,
 
1078
          const AsnInteger SpecificTrap,
 
1079
          const AsnTimeticks TimeStamp,
 
1080
          const SnmpVarBindList * const pTrapVarbinds)
 
1081
{
 
1082
    /*
 
1083
     * A quote from the paragraph in RFC 1908 about SNMPv1 to SNMPv2c
 
1084
     * trap translation (http://www.ietf.org/rfc/rfc1908.txt):
 
1085
     * <quote>
 
1086
     * If a Trap-PDU is received, then it is mapped into a SNMPv2-Trap-
 
1087
     * PDU.  This is done by prepending onto the variable-bindings field
 
1088
     * two new bindings:  sysUpTime.0 [6], which takes its value from the
 
1089
     * timestamp field of the Trap-PDU; and, snmpTrapOID.0 [6], which is
 
1090
     * calculated thusly:  if the value of generic-trap field is
 
1091
     * `enterpriseSpecific', then the value used is the concatenation of
 
1092
     * the enterprise field from the Trap-PDU with two additional sub-
 
1093
     * identifiers, `0', and the value of the specific-trap field;
 
1094
     * otherwise, the value of the corresponding trap defined in [6] is
 
1095
     * used.
 
1096
     * </quote>
 
1097
     *
 
1098
     * Reference [6] refers to RFC 1907 (http://www.ietf.org/rfc/rfc1907.txt),
 
1099
     * where the generic trap OIDs have been defined as follows:
 
1100
     * coldStart             ::= { snmpTraps 1 }
 
1101
     * warmStart             ::= { snmpTraps 2 }
 
1102
     * linkDown              ::= { snmpTraps 3 }
 
1103
     * linkUp                ::= { snmpTraps 4 }
 
1104
     * authenticationFailure ::= { snmpTraps 5 }
 
1105
     * egpNeighborLoss       ::= { snmpTraps 6 }
 
1106
     */
 
1107
    static const oid sysuptime_oid[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
 
1108
    static const size_t sysuptime_oid_len = OID_LENGTH(sysuptime_oid);
 
1109
 
 
1110
    static const oid snmptrap_oid[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
 
1111
    static const size_t snmptrap_oid_len = OID_LENGTH(snmptrap_oid);
 
1112
 
 
1113
    static const oid snmptraps_oid[] = { 1, 3, 6, 1, 6, 3, 1, 1, 5 };
 
1114
    static const size_t snmptraps_oid_len = OID_LENGTH(snmptraps_oid);
 
1115
 
 
1116
    oid             vb2_oid[MAX_OID_LEN];
 
1117
    size_t          vb2_oid_len;
 
1118
 
 
1119
    netsnmp_variable_list *notification_vars = NULL;
 
1120
 
 
1121
 
 
1122
    /*
 
1123
     * Append the varbind (sysUpTime.0, TimeStamp). 
 
1124
     */
 
1125
    snmp_varlist_add_variable(&notification_vars,
 
1126
                              sysuptime_oid, sysuptime_oid_len,
 
1127
                              ASN_TIMETICKS,
 
1128
                              (const u_char *) &TimeStamp,
 
1129
                              sizeof(TimeStamp));
 
1130
 
 
1131
    if (GenericTrap == SNMP_GENERICTRAP_ENTERSPECIFIC) {
 
1132
        /*
 
1133
         * Enterprise specific trap: compute the OID
 
1134
         * *pEnterprise + ".0." + SpecificTrap.
 
1135
         */
 
1136
        copy_oid(vb2_oid, &vb2_oid_len,
 
1137
                 pEnterprise->ids, pEnterprise->idLength);
 
1138
        vb2_oid[vb2_oid_len++] = 0;
 
1139
        vb2_oid[vb2_oid_len++] = SpecificTrap;
 
1140
    } else {
 
1141
        /*
 
1142
         * Generic trap: compute the OID snmpTraps + "." + GenericTrap.
 
1143
         * Since the GenericTrap values are those defined in SNMPv1, since
 
1144
         * these values start at zero, and since the corresponding values in
 
1145
         * SNMPv2 start at one, translate the GenericTrap value accordingly.
 
1146
         * See also http://www.ietf.org/rfc/rfc1214.txt and
 
1147
         * http://www.ietf.org/rfc/rfc3418.txt.
 
1148
         */
 
1149
        copy_oid(vb2_oid, &vb2_oid_len, snmptraps_oid, snmptraps_oid_len);
 
1150
        vb2_oid[vb2_oid_len++] = GenericTrap + 1;
 
1151
    }
 
1152
 
 
1153
    /*
 
1154
     * Append the varbind (snmpTrap, vb2_oid). 
 
1155
     */
 
1156
    snmp_varlist_add_variable(&notification_vars,
 
1157
                              snmptrap_oid, snmptrap_oid_len,
 
1158
                              ASN_OBJECT_ID,
 
1159
                              (u_char *) vb2_oid,
 
1160
                              vb2_oid_len * sizeof(vb2_oid[0]));
 
1161
 
 
1162
    /*
 
1163
     * Append all the varbinds in pTrapVarbinds. 
 
1164
     */
 
1165
    append_windows_varbind_list(&notification_vars, pTrapVarbinds);
 
1166
 
 
1167
    /*
 
1168
     * Send trap. 
 
1169
     */
 
1170
    send_v2trap(notification_vars);
 
1171
 
 
1172
    /*
 
1173
     * Free the memory allocated for notification_vars. 
 
1174
     */
 
1175
    snmp_free_varbind(notification_vars);
 
1176
}
 
1177
 
 
1178
/**
 
1179
 * Convert a Windows varbind to a Net-SNMP varbind and add it to the list of
 
1180
 * varbinds 'net_snmp_varbinds'.
 
1181
 *
 
1182
 * @note The memory allocated inside this function must be freed by the caller
 
1183
 *   as follows: snmp_free_varbind(*net_snmp_varbinds).
 
1184
 */
 
1185
static int
 
1186
append_windows_varbind_list(netsnmp_variable_list **
 
1187
                            const net_snmp_varbinds,
 
1188
                            const SnmpVarBindList * const win_varbinds)
 
1189
{
 
1190
    int             i, status = SNMP_ERR_NOERROR;
 
1191
 
 
1192
    for (i = 0; i < win_varbinds->len; i++) {
 
1193
        status =
 
1194
            append_windows_varbind(net_snmp_varbinds,
 
1195
                                   &win_varbinds->list[i]);
 
1196
        if (status != SNMP_ERR_NOERROR)
 
1197
            break;
 
1198
    }
 
1199
    return status;
 
1200
}
 
1201
 
 
1202
static int
 
1203
append_windows_varbind(netsnmp_variable_list ** const net_snmp_varbinds,
 
1204
                       const SnmpVarBind * const win_varbind)
 
1205
{
 
1206
    switch (win_varbind->value.asnType) {
 
1207
    case MS_ASN_INTEGER:
 
1208
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1209
                                  win_varbind->name.idLength,
 
1210
                                  ASN_INTEGER,
 
1211
                                  (const u_char *) &win_varbind->value.
 
1212
                                  asnValue.number,
 
1213
                                  sizeof(win_varbind->value.asnValue.
 
1214
                                         number));
 
1215
        break;
 
1216
    case MS_ASN_BITS:
 
1217
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1218
                                  win_varbind->name.idLength,
 
1219
                                  ASN_BIT_STR,
 
1220
                                  win_varbind->value.asnValue.bits.stream,
 
1221
                                  win_varbind->value.asnValue.bits.length);
 
1222
        break;
 
1223
    case MS_ASN_OCTETSTRING:
 
1224
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1225
                                  win_varbind->name.idLength,
 
1226
                                  ASN_OCTET_STR,
 
1227
                                  win_varbind->value.asnValue.string.
 
1228
                                  stream,
 
1229
                                  win_varbind->value.asnValue.string.
 
1230
                                  length);
 
1231
        break;
 
1232
    case MS_ASN_NULL:
 
1233
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1234
                                  win_varbind->name.idLength,
 
1235
                                  ASN_NULL, 0, 0);
 
1236
        break;
 
1237
    case MS_ASN_OBJECTIDENTIFIER:
 
1238
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1239
                                  win_varbind->name.idLength,
 
1240
                                  ASN_OBJECT_ID,
 
1241
                                  (u_char *) win_varbind->value.asnValue.
 
1242
                                  object.ids,
 
1243
                                  win_varbind->value.asnValue.object.
 
1244
                                  idLength * sizeof(oid));
 
1245
        break;
 
1246
 
 
1247
        /*
 
1248
         * MS_ASN_INTEGER32: synonym for MS_ASN_INTEGER. 
 
1249
         */
 
1250
 
 
1251
    case MS_ASN_SEQUENCE:
 
1252
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1253
                                  win_varbind->name.idLength,
 
1254
                                  ASN_SEQUENCE,
 
1255
                                  win_varbind->value.asnValue.sequence.
 
1256
                                  stream,
 
1257
                                  win_varbind->value.asnValue.sequence.
 
1258
                                  length);
 
1259
        break;
 
1260
    case MS_ASN_IPADDRESS:
 
1261
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1262
                                  win_varbind->name.idLength,
 
1263
                                  ASN_IPADDRESS,
 
1264
                                  win_varbind->value.asnValue.address.
 
1265
                                  stream,
 
1266
                                  win_varbind->value.asnValue.address.
 
1267
                                  length);
 
1268
        break;
 
1269
    case MS_ASN_COUNTER32:
 
1270
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1271
                                  win_varbind->name.idLength,
 
1272
                                  ASN_COUNTER,
 
1273
                                  (const u_char *) &win_varbind->value.
 
1274
                                  asnValue.counter,
 
1275
                                  sizeof(win_varbind->value.asnValue.
 
1276
                                         counter));
 
1277
        break;
 
1278
    case MS_ASN_GAUGE32:
 
1279
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1280
                                  win_varbind->name.idLength,
 
1281
                                  ASN_GAUGE,
 
1282
                                  (const u_char *) &win_varbind->value.
 
1283
                                  asnValue.gauge,
 
1284
                                  sizeof(win_varbind->value.asnValue.
 
1285
                                         gauge));
 
1286
        break;
 
1287
    case MS_ASN_TIMETICKS:
 
1288
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1289
                                  win_varbind->name.idLength,
 
1290
                                  ASN_TIMETICKS,
 
1291
                                  (const u_char *) &win_varbind->value.
 
1292
                                  asnValue.ticks,
 
1293
                                  sizeof(win_varbind->value.asnValue.
 
1294
                                         ticks));
 
1295
        break;
 
1296
    case MS_ASN_OPAQUE:        // AsnOctetString
 
1297
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1298
                                  win_varbind->name.idLength,
 
1299
                                  ASN_OPAQUE,
 
1300
                                  win_varbind->value.asnValue.arbitrary.
 
1301
                                  stream,
 
1302
                                  win_varbind->value.asnValue.arbitrary.
 
1303
                                  length);
 
1304
        break;
 
1305
    case MS_ASN_COUNTER64:
 
1306
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1307
                                  win_varbind->name.idLength,
 
1308
                                  ASN_COUNTER64,
 
1309
                                  (const u_char *) &win_varbind->value.
 
1310
                                  asnValue.counter64,
 
1311
                                  sizeof(win_varbind->value.asnValue.
 
1312
                                         counter64));
 
1313
        break;
 
1314
    case MS_ASN_UINTEGER32:
 
1315
        snmp_varlist_add_variable(net_snmp_varbinds, win_varbind->name.ids,
 
1316
                                  win_varbind->name.idLength,
 
1317
                                  ASN_UNSIGNED,
 
1318
                                  (const u_char *) &win_varbind->value.
 
1319
                                  asnValue.unsigned32,
 
1320
                                  sizeof(win_varbind->value.asnValue.
 
1321
                                         unsigned32));
 
1322
        break;
 
1323
    default:
 
1324
        return SNMP_ERR_GENERR;
 
1325
    }
 
1326
 
 
1327
    return SNMP_ERR_NOERROR;
 
1328
}
 
1329
 
 
1330
/**
 
1331
 * Convert a Net-SNMP varbind to a WinSNMP varbind list.
 
1332
 *
 
1333
 * @param[out] pVarBindList WinSNMP varbind list, initialized by this
 
1334
 *               function.
 
1335
 * @param[in]  varbind Net-SNMP varbind.
 
1336
 */
 
1337
int
 
1338
convert_to_windows_varbind_list(SnmpVarBindList * pVarBindList,
 
1339
                                netsnmp_variable_list * varbind)
 
1340
{
 
1341
    SnmpVarBind    *win_varbind;
 
1342
 
 
1343
    assert(pVarBindList);
 
1344
    assert(varbind);
 
1345
 
 
1346
    pVarBindList->len = 1;
 
1347
    pVarBindList->list
 
1348
        = (SnmpVarBind *) SnmpUtilMemAlloc(pVarBindList->len
 
1349
                                           *
 
1350
                                           sizeof(pVarBindList->list[0]));
 
1351
    if (pVarBindList->list == 0)
 
1352
        goto generr;
 
1353
 
 
1354
    memset(&pVarBindList->list[0], 0, sizeof(pVarBindList->list[0]));
 
1355
 
 
1356
    win_varbind = &pVarBindList->list[0];
 
1357
 
 
1358
    if (varbind->name
 
1359
        && !copy_oid_to_new_windows_oid(&win_varbind->name,
 
1360
                                        varbind->name,
 
1361
                                        varbind->name_length))
 
1362
        goto generr;
 
1363
 
 
1364
    switch (varbind->type) {
 
1365
    case ASN_BOOLEAN:
 
1366
        // There is no equivalent type in Microsoft's <snmp.h>.
 
1367
        assert(0);
 
1368
        win_varbind->value.asnType = MS_ASN_INTEGER;
 
1369
        win_varbind->value.asnValue.number = *(varbind->val.integer);
 
1370
        break;
 
1371
    case ASN_INTEGER:
 
1372
        win_varbind->value.asnType = MS_ASN_INTEGER;
 
1373
        win_varbind->value.asnValue.number = *(varbind->val.integer);
 
1374
        break;
 
1375
    case ASN_BIT_STR:
 
1376
        win_varbind->value.asnType = MS_ASN_BITS;
 
1377
        win_varbind->value.asnValue.string.stream
 
1378
            = winsnmp_memdup(varbind->val.string, varbind->val_len);
 
1379
        win_varbind->value.asnValue.string.length =
 
1380
            (UINT) (varbind->val_len);
 
1381
        win_varbind->value.asnValue.string.dynamic = TRUE;
 
1382
        break;
 
1383
    case ASN_OCTET_STR:
 
1384
        win_varbind->value.asnType = MS_ASN_OCTETSTRING;
 
1385
        win_varbind->value.asnValue.string.stream
 
1386
            = winsnmp_memdup(varbind->val.string, varbind->val_len);
 
1387
        win_varbind->value.asnValue.string.length =
 
1388
            (UINT) (varbind->val_len);
 
1389
        win_varbind->value.asnValue.string.dynamic = TRUE;
 
1390
        break;
 
1391
    case ASN_NULL:
 
1392
        win_varbind->value.asnType = MS_ASN_NULL;
 
1393
        memset(&win_varbind->value, 0, sizeof(win_varbind->value));
 
1394
        break;
 
1395
    case ASN_OBJECT_ID:
 
1396
        win_varbind->value.asnType = MS_ASN_OBJECTIDENTIFIER;
 
1397
        if (!copy_oid_to_new_windows_oid
 
1398
            (&win_varbind->value.asnValue.object, varbind->val.objid,
 
1399
             varbind->val_len / sizeof(varbind->val.objid[0])))
 
1400
            return SNMP_ERR_GENERR;
 
1401
        break;
 
1402
    case ASN_SEQUENCE:
 
1403
        win_varbind->value.asnType = MS_ASN_SEQUENCE;
 
1404
        win_varbind->value.asnValue.string.stream
 
1405
            = winsnmp_memdup(varbind->val.string, varbind->val_len);
 
1406
        win_varbind->value.asnValue.string.length =
 
1407
            (UINT) (varbind->val_len);
 
1408
        win_varbind->value.asnValue.string.dynamic = TRUE;
 
1409
        break;
 
1410
    case ASN_SET:
 
1411
        // There is no equivalent type in Microsoft's <snmp.h>.
 
1412
        assert(0);
 
1413
        win_varbind->value.asnType = MS_ASN_INTEGER;
 
1414
        win_varbind->value.asnValue.number = *(varbind->val.integer);
 
1415
        break;
 
1416
    case ASN_IPADDRESS:
 
1417
        win_varbind->value.asnType = MS_ASN_IPADDRESS;
 
1418
        win_varbind->value.asnValue.string.stream
 
1419
            = winsnmp_memdup(varbind->val.string, varbind->val_len);
 
1420
        win_varbind->value.asnValue.string.length =
 
1421
            (UINT) (varbind->val_len);
 
1422
        win_varbind->value.asnValue.string.dynamic = TRUE;
 
1423
        break;
 
1424
    case ASN_COUNTER:
 
1425
        win_varbind->value.asnType = MS_ASN_COUNTER32;
 
1426
        win_varbind->value.asnValue.counter = *(varbind->val.integer);
 
1427
        break;
 
1428
        /*
 
1429
         * ASN_GAUGE == ASN_UNSIGNED 
 
1430
         */
 
1431
    case ASN_UNSIGNED:
 
1432
        win_varbind->value.asnType = MS_ASN_UNSIGNED32;
 
1433
        win_varbind->value.asnValue.unsigned32 = *(varbind->val.integer);
 
1434
        break;
 
1435
    case ASN_TIMETICKS:
 
1436
        win_varbind->value.asnType = MS_ASN_TIMETICKS;
 
1437
        win_varbind->value.asnValue.ticks = *(varbind->val.integer);
 
1438
        break;
 
1439
    case ASN_OPAQUE:
 
1440
        win_varbind->value.asnType = MS_ASN_OPAQUE;
 
1441
        win_varbind->value.asnValue.string.stream
 
1442
            = winsnmp_memdup(varbind->val.string, varbind->val_len);
 
1443
        win_varbind->value.asnValue.string.length =
 
1444
            (UINT) (varbind->val_len);
 
1445
        win_varbind->value.asnValue.string.dynamic = TRUE;
 
1446
        break;
 
1447
    case ASN_COUNTER64:
 
1448
        win_varbind->value.asnType = MS_ASN_COUNTER64;
 
1449
        win_varbind->value.asnValue.counter64.HighPart
 
1450
            = varbind->val.counter64->high;
 
1451
        win_varbind->value.asnValue.counter64.LowPart
 
1452
            = varbind->val.counter64->low;
 
1453
        break;
 
1454
    default:
 
1455
        assert(0);
 
1456
        goto generr;
 
1457
    }
 
1458
 
 
1459
    return SNMP_ERR_NOERROR;
 
1460
 
 
1461
  generr:
 
1462
    SnmpUtilVarBindListFree(pVarBindList);
 
1463
    memset(pVarBindList, 0, sizeof(*pVarBindList));
 
1464
    return SNMP_ERR_GENERR;
 
1465
}
 
1466
 
 
1467
/** Convert a Windows SNMP error code to the equivalent Net-SNMP error code. */
 
1468
int
 
1469
convert_win_snmp_err(const int win_snmp_err)
 
1470
{
 
1471
    switch (win_snmp_err) {
 
1472
    case SNMP_ERRORSTATUS_NOERROR:
 
1473
        return SNMP_ERR_NOERROR;
 
1474
    case SNMP_ERRORSTATUS_TOOBIG:
 
1475
        return SNMP_ERR_TOOBIG;
 
1476
    case SNMP_ERRORSTATUS_NOSUCHNAME:
 
1477
        /*
 
1478
         * Note: SNMP extension DLLs return SNMP_ERRORSTATUS_NOSUCHNAME
 
1479
         * when either noSuchObject or noSuchInstance should be returned to
 
1480
         * the SNMP manager (assuming SNMPv2c or SNMPv3). Unfortunately it
 
1481
         * is not possible without consulting the MIB to find out whether
 
1482
         * either SNMP_NOSUCHINSTANCE or SNMP_NOSUCHOBJECT should be returned.
 
1483
         * See also RFC 1448.
 
1484
         */
 
1485
        return SNMP_NOSUCHINSTANCE;
 
1486
    case SNMP_ERRORSTATUS_BADVALUE:
 
1487
        return SNMP_ERR_BADVALUE;
 
1488
    case SNMP_ERRORSTATUS_READONLY:
 
1489
        return SNMP_ERR_READONLY;
 
1490
    case SNMP_ERRORSTATUS_GENERR:
 
1491
        return SNMP_ERR_GENERR;
 
1492
    case SNMP_ERRORSTATUS_NOACCESS:
 
1493
        return SNMP_ERR_NOACCESS;
 
1494
    case SNMP_ERRORSTATUS_WRONGTYPE:
 
1495
        return SNMP_ERR_WRONGTYPE;
 
1496
    case SNMP_ERRORSTATUS_WRONGLENGTH:
 
1497
        return SNMP_ERR_WRONGLENGTH;
 
1498
    case SNMP_ERRORSTATUS_WRONGENCODING:
 
1499
        return SNMP_ERR_WRONGENCODING;
 
1500
    case SNMP_ERRORSTATUS_WRONGVALUE:
 
1501
        return SNMP_ERR_WRONGVALUE;
 
1502
    case SNMP_ERRORSTATUS_NOCREATION:
 
1503
        return SNMP_ERR_NOCREATION;
 
1504
    case SNMP_ERRORSTATUS_INCONSISTENTVALUE:
 
1505
        return SNMP_ERR_INCONSISTENTVALUE;
 
1506
    case SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE:
 
1507
        return SNMP_ERR_RESOURCEUNAVAILABLE;
 
1508
    case SNMP_ERRORSTATUS_COMMITFAILED:
 
1509
        return SNMP_ERR_COMMITFAILED;
 
1510
    case SNMP_ERRORSTATUS_UNDOFAILED:
 
1511
        return SNMP_ERR_UNDOFAILED;
 
1512
    case SNMP_ERRORSTATUS_AUTHORIZATIONERROR:
 
1513
        return SNMP_ERR_AUTHORIZATIONERROR;
 
1514
    case SNMP_ERRORSTATUS_NOTWRITABLE:
 
1515
        return SNMP_ERR_NOTWRITABLE;
 
1516
    case SNMP_ERRORSTATUS_INCONSISTENTNAME:
 
1517
        return SNMP_ERR_INCONSISTENTNAME;
 
1518
    }
 
1519
    assert(0);
 
1520
    return SNMP_ERR_GENERR;
 
1521
}
 
1522
 
 
1523
/**
 
1524
 * Look up the extension DLL view that was registered with the given OID.
 
1525
 */
 
1526
static winextdll_view *
 
1527
lookup_view_by_oid(oid * const name, const size_t name_len)
 
1528
{
1591
1529
    int             i;
1592
1530
 
1593
 
    buf[0] = '\0';
1594
 
 
1595
 
    for (i = 0; i < theoid->idLength; i++) {
1596
 
      sprintf(temp, ".%d", theoid->ids[i]);
1597
 
      strcat(buf, temp);
1598
 
    }
1599
 
 
1600
 
    if (buf != NULL) {
1601
 
      debugmsg(token, "%s", buf);
1602
 
      //DEBUGMSGTL((token, "%s\n", buf));
1603
 
    }
1604
 
}
1605
 
 
 
1531
    for (i = 0; i < s_winextdll_view.size; i++) {
 
1532
        if (netsnmp_oid_equals(WINEXTDLL_VIEW(i).name,
 
1533
                               WINEXTDLL_VIEW(i).name_length,
 
1534
                               name, name_len) == 0
 
1535
            && WINEXTDLL_VIEW(i).my_handler) {
 
1536
            return &WINEXTDLL_VIEW(i);
 
1537
        }
 
1538
    }
 
1539
 
 
1540
    return NULL;
 
1541
}
 
1542
 
 
1543
/**
 
1544
 * Copy an OID.
 
1545
 *
 
1546
 * @param[out] to_name       Number of elements written to destination OID.
 
1547
 * @param[out] to_name_len   Length of destination OID. Must have at least
 
1548
 *                           min(from_name_len, MAX_OID_LEN) elements.
 
1549
 * @param[in]  from_name     Original OID.
 
1550
 * @param[in]  from_name_len Length of original OID.
 
1551
 */
 
1552
static void
 
1553
copy_oid(oid * const to_name, size_t * const to_name_len,
 
1554
         const oid * const from_name, const size_t from_name_len)
 
1555
{
 
1556
    int             j;
 
1557
 
 
1558
    assert(to_name);
 
1559
    assert(to_name_len);
 
1560
    assert(from_name);
 
1561
 
 
1562
    for (j = 0; j < from_name_len && j < MAX_OID_LEN; j++)
 
1563
        to_name[j] = from_name[j];
 
1564
 
 
1565
    *to_name_len = j;
 
1566
}
 
1567
 
 
1568
/**
 
1569
 * Convert a Net-SNMP OID into a Windows OID and allocate memory for the
 
1570
 * Windows OID.
 
1571
 *
 
1572
 * @param[out] windows_oid   Pointer to a AsnObjectIdentifier.
 
1573
 * @param[in]  name   Pointer to an array with elements of type oid
 
1574
 *           and length name_len.
 
1575
 * @param[in]  name_len Number of elements of input and output OID.
 
1576
 */
 
1577
static UINT    *
 
1578
copy_oid_to_new_windows_oid(AsnObjectIdentifier * const windows_oid,
 
1579
                            const oid * const name, const size_t name_len)
 
1580
{
 
1581
    assert(windows_oid);
 
1582
    assert(windows_oid->ids == 0);
 
1583
    assert(windows_oid->idLength == 0);
 
1584
    assert(name);
 
1585
 
 
1586
    windows_oid->ids
 
1587
        =
 
1588
        (UINT *) winsnmp_memdup(name,
 
1589
                                sizeof(windows_oid->ids[0]) * name_len);
 
1590
    windows_oid->idLength = (UINT) name_len;
 
1591
    return windows_oid->ids;
 
1592
}
 
1593
 
 
1594
static u_char  *
 
1595
winsnmp_memdup(const void *src, const size_t len)
 
1596
{
 
1597
    u_char         *p;
 
1598
 
 
1599
    assert(len == (UINT) len);
 
1600
 
 
1601
    p = SnmpUtilMemAlloc((UINT) len);
 
1602
    if (p)
 
1603
        memcpy(p, src, len);
 
1604
    return p;
 
1605
}
 
1606
 
 
1607
#if 0
 
1608
/** Initialize array 'a'. */
 
1609
static void
 
1610
xarray_init(xarray * a, size_t elem_size)
 
1611
{
 
1612
    assert(a);
 
1613
 
 
1614
    memset(a, 0, sizeof(*a));
 
1615
    a->elem_size = elem_size;
 
1616
}
 
1617
#endif
 
1618
 
 
1619
/** Deallocate any memory that was dynamically allocated for 'a'. */
 
1620
static void
 
1621
xarray_destroy(xarray * a)
 
1622
{
 
1623
    assert(a);
 
1624
 
 
1625
    xarray_reserve(a, 0);
 
1626
}
 
1627
 
 
1628
/**
 
1629
 * Append the contents of the address range [ elem, elem + a->elem_size [ to a.
 
1630
 *
 
1631
 * Resize a if necessary.
 
1632
 *
 
1633
 * @return A pointer to the address where the data has been copied upon success,
 
1634
 *         or NULL upon failure.
 
1635
 */
 
1636
static void    *
 
1637
xarray_push_back(xarray * a, const void *elem)
 
1638
{
 
1639
    assert(a);
 
1640
    assert(elem);
 
1641
    assert(a->size <= a->reserved);
 
1642
 
 
1643
    if (a->size == a->reserved)
 
1644
        xarray_reserve(a, a->reserved == 0 ? 16 : 2 * a->reserved);
 
1645
    if (a->size < a->reserved) {
 
1646
        assert(a->size < a->reserved);
 
1647
        return memcpy((char *) (a->p) + a->elem_size * a->size++, elem,
 
1648
                      a->elem_size);
 
1649
    }
 
1650
    return NULL;
 
1651
}
 
1652
 
 
1653
#if 0
 
1654
/** Erase [ elem, elem + a->elem_size [ from a. */
 
1655
static void
 
1656
xarray_erase(xarray * a, void *const elem)
 
1657
{
 
1658
    assert(a);
 
1659
    assert(a->size >= 1);
 
1660
    assert(a->p <= elem);
 
1661
    assert((const char *) elem + a->elem_size <=
 
1662
           (char *) a->p + a->size * a->elem_size);
 
1663
    assert(((const char *) elem - (char *) a->p) % a->elem_size == 0);
 
1664
 
 
1665
    a->size--;
 
1666
    memmove((char *) elem, (char *) elem + a->elem_size,
 
1667
            a->size - ((const char *) elem -
 
1668
                       (char *) a->p) / a->elem_size);
 
1669
}
 
1670
#endif
 
1671
 
 
1672
/**
 
1673
 * Change the number of allocated elements to 'reserved'.
 
1674
 *
 
1675
 * Can be used either for enlarging or for shrinking the memory allocated for
 
1676
 * 'a'. Does not modify 'a' if memory allocation fails. Newly allocted memory
 
1677
 * is not initialized.
 
1678
 *
 
1679
 * @return != NULL upon success, NULL upon failure.
 
1680
 */
 
1681
static void    *
 
1682
xarray_reserve(xarray * a, int reserved)
 
1683
{
 
1684
    assert(a);
 
1685
    assert(a->size <= a->reserved);
 
1686
 
 
1687
    if ((a->p = realloc(a->p, a->elem_size * reserved)))
 
1688
        a->reserved = reserved;
 
1689
    else
 
1690
        a->reserved = 0;
 
1691
    return a->p;
 
1692
}
 
1693
 
 
1694
#endif                          /* USING_WINEXTDLL_MODULE */