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

« back to all changes in this revision

Viewing changes to agent/mibgroup/mibII/at.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Template MIB group implementation - at.c
 
3
 *
 
4
 */
 
5
 
 
6
/* Portions of this file are subject to the following copyright(s).  See
 
7
 * the Net-SNMP's COPYING file for more details and other copyrights
 
8
 * that may apply:
 
9
 */
 
10
/*
 
11
 * Portions of this file are copyrighted by:
 
12
 * Copyright ļæ½ 2003 Sun Microsystems, Inc. All rights reserved.
 
13
 * Use is subject to license terms specified in the COPYING file
 
14
 * distributed with the Net-SNMP package.
 
15
 */
 
16
 
 
17
#include <net-snmp/net-snmp-config.h>
 
18
#if HAVE_STRING_H
 
19
#include <string.h>
 
20
#else
 
21
#include <strings.h>
 
22
#endif
 
23
#if HAVE_STDLIB_H
 
24
#include <stdlib.h>
 
25
#endif
 
26
#if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL)
 
27
#define _KERNEL 1
 
28
#define _I_DEFINED_KERNEL
 
29
#endif
 
30
#include <sys/types.h>
 
31
#if TIME_WITH_SYS_TIME
 
32
# ifdef WIN32
 
33
#  include <sys/timeb.h>
 
34
# else
 
35
# include <sys/time.h>
 
36
# endif
 
37
# include <time.h>
 
38
#else
 
39
# if HAVE_SYS_TIME_H
 
40
#  include <sys/time.h>
 
41
# else
 
42
#  include <time.h>
 
43
# endif
 
44
#endif
 
45
#if HAVE_SYS_SOCKET_H
 
46
#include <sys/socket.h>
 
47
#endif
 
48
 
 
49
#if HAVE_NETINET_IN_H
 
50
#include <netinet/in.h>
 
51
#endif
 
52
#if HAVE_NET_IF_H
 
53
#include <net/if.h>
 
54
#endif
 
55
#if HAVE_NET_IF_VAR_H
 
56
#include <net/if_var.h>
 
57
#endif
 
58
#ifdef _I_DEFINED_KERNEL
 
59
#undef _KERNEL
 
60
#endif
 
61
 
 
62
#if HAVE_NETINET_IF_ETHER_H
 
63
#include <netinet/if_ether.h>
 
64
#endif
 
65
#if HAVE_INET_MIB2_H
 
66
#include <inet/mib2.h>
 
67
#endif
 
68
#if HAVE_SYS_PARAM_H
 
69
#include <sys/param.h>
 
70
#endif
 
71
#if HAVE_SYS_SYSCTL_H
 
72
#include <sys/sysctl.h>
 
73
#endif
 
74
#if HAVE_NET_IF_DL_H
 
75
#ifndef dynix
 
76
#include <net/if_dl.h>
 
77
#else
 
78
#include <sys/net/if_dl.h>
 
79
#endif
 
80
#endif
 
81
#if HAVE_SYS_STREAM_H
 
82
#include <sys/stream.h>
 
83
#endif
 
84
#if HAVE_NET_ROUTE_H
 
85
#include <net/route.h>
 
86
#endif
 
87
#ifdef solaris2
 
88
#include "kernel_sunos5.h"
 
89
#endif
 
90
#if HAVE_WINSOCK_H
 
91
#include <winsock.h>
 
92
#endif
 
93
#if HAVE_DMALLOC_H
 
94
#include <dmalloc.h>
 
95
#endif
 
96
 
 
97
#ifdef hpux11
 
98
#include <sys/mib.h>
 
99
#include <netinet/mib_kern.h>
 
100
#endif                          /* hpux11 */
 
101
 
 
102
#include <net-snmp/net-snmp-includes.h>
 
103
#include <net-snmp/agent/net-snmp-agent-includes.h>
 
104
#include <net-snmp/agent/auto_nlist.h>
 
105
 
 
106
#include "at.h"
 
107
#include "interfaces.h"
 
108
 
 
109
#if defined(HAVE_SYS_SYSCTL_H) && !defined(CAN_USE_SYSCTL)
 
110
# if defined(RTF_LLINFO) && !defined(irix6)
 
111
#  define CAN_USE_SYSCTL 1
 
112
# endif
 
113
#endif
 
114
 
 
115
#ifdef cygwin
 
116
#define WIN32
 
117
#include <windows.h>
 
118
#endif
 
119
 
 
120
        /*********************
 
121
         *
 
122
         *  Kernel & interface information,
 
123
         *   and internal forward declarations
 
124
         *
 
125
         *********************/
 
126
 
 
127
#ifndef WIN32
 
128
#ifndef solaris2
 
129
static void     ARP_Scan_Init(void);
 
130
#ifdef ARP_SCAN_FOUR_ARGUMENTS
 
131
static int      ARP_Scan_Next(u_long *, char *, u_long *, u_short *);
 
132
#else
 
133
static int      ARP_Scan_Next(u_long *, char *, u_long *);
 
134
#endif
 
135
#endif
 
136
#endif
 
137
 
 
138
        /*********************
 
139
         *
 
140
         *  Public interface functions
 
141
         *
 
142
         *********************/
 
143
 
 
144
/*
 
145
 * define the structure we're going to ask the agent to register our
 
146
 * information at 
 
147
 */
 
148
struct variable1 at_variables[] = {
 
149
    {ATIFINDEX, ASN_INTEGER, RONLY, var_atEntry, 1, {1}},
 
150
    {ATPHYSADDRESS, ASN_OCTET_STR, RONLY, var_atEntry, 1, {2}},
 
151
    {ATNETADDRESS, ASN_IPADDRESS, RONLY, var_atEntry, 1, {3}}
 
152
};
 
153
 
 
154
/*
 
155
 * Define the OID pointer to the top of the mib tree that we're
 
156
 * registering underneath 
 
157
 */
 
158
oid             at_variables_oid[] = { SNMP_OID_MIB2, 3, 1, 1 };
 
159
 
 
160
void
 
161
init_at(void)
 
162
{
 
163
    /*
 
164
     * register ourselves with the agent to handle our mib tree 
 
165
     */
 
166
    REGISTER_MIB("mibII/at", at_variables, variable1, at_variables_oid);
 
167
#ifdef solaris2
 
168
    init_kernel_sunos5();
 
169
#endif
 
170
}
 
171
 
 
172
#ifndef WIN32
 
173
#ifndef solaris2
 
174
 
 
175
/*
 
176
 * var_atEntry(...
 
177
 * Arguments:
 
178
 * vp     IN      - pointer to variable entry that points here
 
179
 * name    IN/OUT  - IN/name requested, OUT/name found
 
180
 * length  IN/OUT  - length of IN/OUT oid's 
 
181
 * exact   IN      - TRUE if an exact match was requested
 
182
 * var_len OUT     - length of variable or 0 if function returned
 
183
 * write_method
 
184
 * 
 
185
 */
 
186
 
 
187
u_char         *
 
188
var_atEntry(struct variable *vp,
 
189
            oid * name,
 
190
            size_t * length,
 
191
            int exact, size_t * var_len, WriteMethod ** write_method)
 
192
{
 
193
    /*
 
194
     * Address Translation table object identifier is of form:
 
195
     * 1.3.6.1.2.1.3.1.1.1.interface.1.A.B.C.D,  where A.B.C.D is IP address.
 
196
     * Interface is at offset 10,
 
197
     * IPADDR starts at offset 12.
 
198
     *
 
199
     * IP Net to Media table object identifier is of form:
 
200
     * 1.3.6.1.2.1.4.22.1.1.1.interface.A.B.C.D,  where A.B.C.D is IP address.
 
201
     * Interface is at offset 10,
 
202
     * IPADDR starts at offset 11.
 
203
     */
 
204
    u_char         *cp;
 
205
    oid            *op;
 
206
    oid             lowest[16];
 
207
    oid             current[16];
 
208
    static char     PhysAddr[6], LowPhysAddr[6];
 
209
    u_long          Addr, LowAddr, foundone;
 
210
#ifdef ARP_SCAN_FOUR_ARGUMENTS
 
211
    u_short         ifIndex, lowIfIndex = 0;
 
212
#endif                          /* ARP_SCAN_FOUR_ARGUMENTS */
 
213
    u_long          ifType, lowIfType = 0;
 
214
 
 
215
    int             oid_length;
 
216
 
 
217
    /*
 
218
     * fill in object part of name for current (less sizeof instance part) 
 
219
     */
 
220
    memcpy((char *) current, (char *) vp->name,
 
221
           (int) vp->namelen * sizeof(oid));
 
222
 
 
223
    if (current[6] == 3) {      /* AT group oid */
 
224
        oid_length = 16;
 
225
    } else {                    /* IP NetToMedia group oid */
 
226
        oid_length = 15;
 
227
    }
 
228
 
 
229
    LowAddr = 0;                /* Don't have one yet */
 
230
    foundone = 0;
 
231
    ARP_Scan_Init();
 
232
    for (;;) {
 
233
#ifdef ARP_SCAN_FOUR_ARGUMENTS
 
234
        if (ARP_Scan_Next(&Addr, PhysAddr, &ifType, &ifIndex) == 0)
 
235
            break;
 
236
        current[10] = ifIndex;
 
237
 
 
238
        if (current[6] == 3) {  /* AT group oid */
 
239
            current[11] = 1;
 
240
            op = current + 12;
 
241
        } else {                /* IP NetToMedia group oid */
 
242
            op = current + 11;
 
243
        }
 
244
#else                           /* ARP_SCAN_FOUR_ARGUMENTS */
 
245
        if (ARP_Scan_Next(&Addr, PhysAddr, &ifType) == 0)
 
246
            break;
 
247
        current[10] = 1;
 
248
 
 
249
        if (current[6] == 3) {  /* AT group oid */
 
250
            current[11] = 1;
 
251
            op = current + 12;
 
252
        } else {                /* IP NetToMedia group oid */
 
253
            op = current + 11;
 
254
        }
 
255
#endif                          /* ARP_SCAN_FOUR_ARGUMENTS */
 
256
        cp = (u_char *) & Addr;
 
257
        *op++ = *cp++;
 
258
        *op++ = *cp++;
 
259
        *op++ = *cp++;
 
260
        *op++ = *cp++;
 
261
 
 
262
        if (exact) {
 
263
            if (snmp_oid_compare(current, oid_length, name, *length) == 0) {
 
264
                memcpy((char *) lowest, (char *) current,
 
265
                       oid_length * sizeof(oid));
 
266
                LowAddr = Addr;
 
267
                foundone = 1;
 
268
#ifdef ARP_SCAN_FOUR_ARGUMENTS
 
269
                lowIfIndex = ifIndex;
 
270
#endif                          /*  ARP_SCAN_FOUR_ARGUMENTS */
 
271
                memcpy(LowPhysAddr, PhysAddr, sizeof(PhysAddr));
 
272
                lowIfType = ifType;
 
273
                break;          /* no need to search further */
 
274
            }
 
275
        } else {
 
276
            if ((snmp_oid_compare(current, oid_length, name, *length) > 0)
 
277
                && ((foundone == 0)
 
278
                    ||
 
279
                    (snmp_oid_compare
 
280
                     (current, oid_length, lowest, oid_length) < 0))) {
 
281
                /*
 
282
                 * if new one is greater than input and closer to input than
 
283
                 * previous lowest, save this one as the "next" one.
 
284
                 */
 
285
                memcpy((char *) lowest, (char *) current,
 
286
                       oid_length * sizeof(oid));
 
287
                LowAddr = Addr;
 
288
                foundone = 1;
 
289
#ifdef ARP_SCAN_FOUR_ARGUMENTS
 
290
                lowIfIndex = ifIndex;
 
291
#endif                          /*  ARP_SCAN_FOUR_ARGUMENTS */
 
292
                memcpy(LowPhysAddr, PhysAddr, sizeof(PhysAddr));
 
293
                lowIfType = ifType;
 
294
            }
 
295
        }
 
296
    }
 
297
    if (foundone == 0)
 
298
        return (NULL);
 
299
 
 
300
    memcpy((char *) name, (char *) lowest, oid_length * sizeof(oid));
 
301
    *length = oid_length;
 
302
    *write_method = 0;
 
303
    switch (vp->magic) {
 
304
    case IPMEDIAIFINDEX:       /* also ATIFINDEX */
 
305
        *var_len = sizeof long_return;
 
306
#ifdef ARP_SCAN_FOUR_ARGUMENTS
 
307
        long_return = lowIfIndex;
 
308
#else                           /* ARP_SCAN_FOUR_ARGUMENTS */
 
309
#if NO_DUMMY_VALUES
 
310
        return NULL;
 
311
#endif
 
312
        long_return = 1;        /* XXX */
 
313
#endif                          /* ARP_SCAN_FOUR_ARGUMENTS */
 
314
        return (u_char *) & long_return;
 
315
    case IPMEDIAPHYSADDRESS:   /* also ATPHYSADDRESS */
 
316
        *var_len = sizeof(LowPhysAddr);
 
317
        return (u_char *) LowPhysAddr;
 
318
    case IPMEDIANETADDRESS:    /* also ATNETADDRESS */
 
319
        *var_len = sizeof long_return;
 
320
        long_return = LowAddr;
 
321
        return (u_char *) & long_return;
 
322
    case IPMEDIATYPE:
 
323
        *var_len = sizeof long_return;
 
324
        long_return = lowIfType;
 
325
        return (u_char *) & long_return;
 
326
    default:
 
327
        DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_atEntry\n",
 
328
                    vp->magic));
 
329
    }
 
330
    return NULL;
 
331
}
 
332
#else                           /* solaris2 */
 
333
 
 
334
typedef struct if_ip {
 
335
    int             ifIdx;
 
336
    IpAddress       ipAddr;
 
337
} if_ip_t;
 
338
 
 
339
static int
 
340
AT_Cmp(void *addr, void *ep)
 
341
{
 
342
    mib2_ipNetToMediaEntry_t *mp = (mib2_ipNetToMediaEntry_t *) ep;
 
343
    int             ret = -1;
 
344
    DEBUGMSGTL(("mibII/at", "......... AT_Cmp %lx<>%lx %d<>%d (%.5s)\n",
 
345
                mp->ipNetToMediaNetAddress, ((if_ip_t *) addr)->ipAddr,
 
346
                ((if_ip_t *) addr)->ifIdx,
 
347
                Interface_Index_By_Name(mp->ipNetToMediaIfIndex.o_bytes,
 
348
                                        mp->ipNetToMediaIfIndex.o_length),
 
349
                mp->ipNetToMediaIfIndex.o_bytes));
 
350
    if (mp->ipNetToMediaNetAddress != ((if_ip_t *) addr)->ipAddr)
 
351
        ret = 1;
 
352
    else if (((if_ip_t *) addr)->ifIdx !=
 
353
             Interface_Index_By_Name(mp->ipNetToMediaIfIndex.o_bytes,
 
354
                                     mp->ipNetToMediaIfIndex.o_length))
 
355
        ret = 1;
 
356
    else
 
357
        ret = 0;
 
358
    DEBUGMSGTL(("mibII/at", "......... AT_Cmp returns %d\n", ret));
 
359
    return ret;
 
360
}
 
361
 
 
362
u_char         *
 
363
var_atEntry(struct variable * vp,
 
364
            oid * name,
 
365
            size_t * length,
 
366
            int exact, size_t * var_len, WriteMethod ** write_method)
 
367
{
 
368
    /*
 
369
     * object identifier is of form:
 
370
     * 1.3.6.1.2.1.3.1.1.1.interface.1.A.B.C.D,  where A.B.C.D is IP address.
 
371
     * Interface is at offset 10,
 
372
     * IPADDR starts at offset 12.
 
373
     */
 
374
#define AT_MAX_NAME_LENGTH      16
 
375
#define AT_IFINDEX_OFF  10
 
376
    u_char         *cp;
 
377
    oid            *op;
 
378
    oid             lowest[AT_MAX_NAME_LENGTH];
 
379
    oid             current[AT_MAX_NAME_LENGTH];
 
380
    if_ip_t         NextAddr;
 
381
    mib2_ipNetToMediaEntry_t entry;
 
382
    static mib2_ipNetToMediaEntry_t Lowentry;
 
383
    int             Found = 0;
 
384
    req_e           req_type;
 
385
    int             offset, olength;
 
386
 
 
387
    /*
 
388
     * fill in object part of name for current (less sizeof instance part) 
 
389
     */
 
390
 
 
391
    DEBUGMSGTL(("mibII/at", "var_atEntry: "));
 
392
    DEBUGMSGOID(("mibII/at", vp->name, vp->namelen));
 
393
    DEBUGMSG(("mibII/at", " %d\n", exact));
 
394
 
 
395
    memset(&Lowentry, 0, sizeof(Lowentry));
 
396
    memcpy((char *) current, (char *) vp->name, vp->namelen * sizeof(oid));
 
397
    lowest[0] = 1024;
 
398
    for (NextAddr.ipAddr = (u_long) - 1, NextAddr.ifIdx = 255, req_type =
 
399
         GET_FIRST;;
 
400
         NextAddr.ipAddr = entry.ipNetToMediaNetAddress, NextAddr.ifIdx =
 
401
         current[AT_IFINDEX_OFF], req_type = GET_NEXT) {
 
402
        if (getMibstat
 
403
            (MIB_IP_NET, &entry, sizeof(mib2_ipNetToMediaEntry_t),
 
404
             req_type, &AT_Cmp, &NextAddr) != 0)
 
405
            break;
 
406
        current[AT_IFINDEX_OFF] =
 
407
            Interface_Index_By_Name(entry.ipNetToMediaIfIndex.o_bytes,
 
408
                                    entry.ipNetToMediaIfIndex.o_length);
 
409
        if (current[6] == 3) {  /* AT group oid */
 
410
            current[AT_IFINDEX_OFF + 1] = 1;
 
411
            offset = AT_IFINDEX_OFF + 2;
 
412
            olength = AT_IFINDEX_OFF + 6;
 
413
        } else {
 
414
            offset = AT_IFINDEX_OFF + 1;
 
415
            olength = AT_IFINDEX_OFF + 5;
 
416
        }
 
417
        COPY_IPADDR(cp, (u_char *) & entry.ipNetToMediaNetAddress, op,
 
418
                    current + offset);
 
419
        if (exact) {
 
420
            if (snmp_oid_compare(current, olength, name, *length) == 0) {
 
421
                memcpy((char *) lowest, (char *) current,
 
422
                       olength * sizeof(oid));
 
423
                Lowentry = entry;
 
424
                Found++;
 
425
                break;          /* no need to search further */
 
426
            }
 
427
        } else {
 
428
            if (snmp_oid_compare(current, olength, name, *length) > 0
 
429
                && snmp_oid_compare(current, olength, lowest,
 
430
                                    *length) < 0) {
 
431
                /*
 
432
                 * if new one is greater than input and closer to input than
 
433
                 * previous lowest, and is not equal to it, save this one as the "next" one.
 
434
                 */
 
435
                memcpy((char *) lowest, (char *) current,
 
436
                       olength * sizeof(oid));
 
437
                Lowentry = entry;
 
438
                Found++;
 
439
            }
 
440
        }
 
441
    }
 
442
    DEBUGMSGTL(("mibII/at", "... Found = %d\n", Found));
 
443
    if (Found == 0)
 
444
        return (NULL);
 
445
    memcpy((char *) name, (char *) lowest, olength * sizeof(oid));
 
446
    *length = olength;
 
447
    *write_method = 0;
 
448
    switch (vp->magic) {
 
449
    case IPMEDIAIFINDEX:
 
450
        *var_len = sizeof long_return;
 
451
        long_return =
 
452
            Interface_Index_By_Name(Lowentry.ipNetToMediaIfIndex.o_bytes,
 
453
                                    Lowentry.ipNetToMediaIfIndex.o_length);
 
454
        return (u_char *) & long_return;
 
455
    case IPMEDIAPHYSADDRESS:
 
456
        *var_len = Lowentry.ipNetToMediaPhysAddress.o_length;
 
457
        return Lowentry.ipNetToMediaPhysAddress.o_bytes;
 
458
    case IPMEDIANETADDRESS:
 
459
        *var_len = sizeof(Lowentry.ipNetToMediaNetAddress);
 
460
        return (u_char *) &Lowentry.ipNetToMediaNetAddress;
 
461
    case IPMEDIATYPE:
 
462
        *var_len = sizeof long_return;
 
463
        long_return = Lowentry.ipNetToMediaType;
 
464
        return (u_char *) & long_return;
 
465
    default:
 
466
        DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_atEntry\n",
 
467
                    vp->magic));
 
468
    }
 
469
    return NULL;
 
470
}
 
471
#endif                          /* solaris2 */
 
472
 
 
473
 
 
474
        /*********************
 
475
         *
 
476
         *  Internal implementation functions
 
477
         *
 
478
         *********************/
 
479
 
 
480
#ifndef solaris2
 
481
 
 
482
static int      arptab_size, arptab_current;
 
483
#if CAN_USE_SYSCTL
 
484
static char    *lim, *rtnext;
 
485
static char    *at = 0;
 
486
#else
 
487
#ifdef STRUCT_ARPHD_HAS_AT_NEXT
 
488
static struct arphd *at = 0;
 
489
static struct arptab *at_ptr, at_entry;
 
490
static struct arpcom at_com;
 
491
#elif defined(hpux11)
 
492
static mib_ipNetToMediaEnt *at = (mib_ipNetToMediaEnt *) 0;
 
493
#else
 
494
 
 
495
/*
 
496
 * at used to be allocated every time we needed to look at the arp cache.
 
497
 * This cause us to parse /proc/net/arp twice for each request and didn't
 
498
 * allow us to filter things like we'd like to.  So now we use it 
 
499
 * semi-statically.  We initialize it to size 0 and if we need more room
 
500
 * we realloc room for ARP_CACHE_INCR more entries in the table.
 
501
 * We never release what we've taken . . .
 
502
 */
 
503
#define ARP_CACHE_INCR 1024
 
504
static struct arptab *at = NULL;
 
505
static int      arptab_curr_max_size = 0;
 
506
 
 
507
#endif
 
508
#endif                          /* CAN_USE_SYSCTL */
 
509
 
 
510
static void
 
511
ARP_Scan_Init(void)
 
512
{
 
513
#ifndef CAN_USE_SYSCTL
 
514
#ifndef linux
 
515
#ifdef hpux11
 
516
 
 
517
    int             fd;
 
518
    struct nmparms  p;
 
519
    int             val;
 
520
    unsigned int    ulen;
 
521
    int             ret;
 
522
 
 
523
    if (at)
 
524
        free(at);
 
525
    at = (mib_ipNetToMediaEnt *) 0;
 
526
    arptab_size = 0;
 
527
 
 
528
    if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
 
529
        p.objid = ID_ipNetToMediaTableNum;
 
530
        p.buffer = (void *) &val;
 
531
        ulen = sizeof(int);
 
532
        p.len = &ulen;
 
533
        if ((ret = get_mib_info(fd, &p)) == 0)
 
534
            arptab_size = val;
 
535
 
 
536
        if (arptab_size > 0) {
 
537
            ulen = (unsigned) arptab_size *sizeof(mib_ipNetToMediaEnt);
 
538
            at = (mib_ipNetToMediaEnt *) malloc(ulen);
 
539
            p.objid = ID_ipNetToMediaTable;
 
540
            p.buffer = (void *) at;
 
541
            p.len = &ulen;
 
542
            if ((ret = get_mib_info(fd, &p)) < 0)
 
543
                arptab_size = 0;
 
544
        }
 
545
 
 
546
        close_mib(fd);
 
547
    }
 
548
 
 
549
    arptab_current = 0;
 
550
 
 
551
#else                           /* hpux11 */
 
552
 
 
553
    if (!at) {
 
554
        auto_nlist(ARPTAB_SIZE_SYMBOL, (char *) &arptab_size,
 
555
                   sizeof arptab_size);
 
556
#ifdef STRUCT_ARPHD_HAS_AT_NEXT
 
557
        at = (struct arphd *) malloc(arptab_size * sizeof(struct arphd));
 
558
#else
 
559
        at = (struct arptab *) malloc(arptab_size * sizeof(struct arptab));
 
560
#endif
 
561
    }
 
562
#ifdef STRUCT_ARPHD_HAS_AT_NEXT
 
563
    auto_nlist(ARPTAB_SYMBOL, (char *) at,
 
564
               arptab_size * sizeof(struct arphd));
 
565
    at_ptr = at[0].at_next;
 
566
#else
 
567
    auto_nlist(ARPTAB_SYMBOL, (char *) at,
 
568
               arptab_size * sizeof(struct arptab));
 
569
#endif
 
570
    arptab_current = 0;
 
571
 
 
572
#endif                          /* hpux11 */
 
573
#else                           /* linux */
 
574
 
 
575
    static time_t   tm = 0;     /* Time of last scan */
 
576
    FILE           *in;
 
577
    int             i;
 
578
    char            line[128];
 
579
    int             za, zb, zc, zd, ze, zf, zg, zh, zi, zj;
 
580
    char            ifname[21];
 
581
 
 
582
    arptab_current = 0;         /* Anytime this is called we need to reset 'current' */
 
583
 
 
584
    if (time(NULL) < tm + 1) {  /*Our cool one second cache implementation :-) */
 
585
        return;
 
586
    }
 
587
 
 
588
    in = fopen("/proc/net/arp", "r");
 
589
    if (!in) {
 
590
        snmp_log(LOG_ERR, "snmpd: Cannot open /proc/net/arp\n");
 
591
        arptab_size = 0;
 
592
        return;
 
593
    }
 
594
 
 
595
    /*
 
596
     * Get rid of the header line 
 
597
     */
 
598
    fgets(line, sizeof(line), in);
 
599
 
 
600
    i = 0;
 
601
    while (fgets(line, sizeof(line), in)) {
 
602
        u_long          tmp_a;
 
603
        int             tmp_flags;
 
604
        if (i >= arptab_curr_max_size) {
 
605
            struct arptab  *newtab = (struct arptab *)
 
606
                realloc(at, (sizeof(struct arptab) *
 
607
                             (arptab_curr_max_size + ARP_CACHE_INCR)));
 
608
            if (newtab == at) {
 
609
                snmp_log(LOG_ERR,
 
610
                         "Error allocating more space for arpcache.  "
 
611
                         "Cache will continue to be limited to %d entries",
 
612
                         arptab_curr_max_size);
 
613
                break;
 
614
            } else {
 
615
                arptab_curr_max_size += ARP_CACHE_INCR;
 
616
                at = newtab;
 
617
            }
 
618
        }
 
619
        if (12 !=
 
620
            sscanf(line,
 
621
                   "%d.%d.%d.%d 0x%*x 0x%x %x:%x:%x:%x:%x:%x %*[^ ] %20s\n",
 
622
                   &za, &zb, &zc, &zd, &tmp_flags, &ze, &zf, &zg, &zh, &zi,
 
623
                   &zj, ifname)) {
 
624
            snmp_log(LOG_ERR, "Bad line in /proc/net/arp: %s", line);
 
625
            continue;
 
626
        }
 
627
        /*
 
628
         * Invalidated entries have their flag set to 0.
 
629
         * * We want to ignore them 
 
630
         */
 
631
        if (tmp_flags == 0) {
 
632
            continue;
 
633
        }
 
634
        at[i].at_flags = tmp_flags;
 
635
        at[i].at_enaddr[0] = ze;
 
636
        at[i].at_enaddr[1] = zf;
 
637
        at[i].at_enaddr[2] = zg;
 
638
        at[i].at_enaddr[3] = zh;
 
639
        at[i].at_enaddr[4] = zi;
 
640
        at[i].at_enaddr[5] = zj;
 
641
        tmp_a = ((u_long) za << 24) |
 
642
            ((u_long) zb << 16) | ((u_long) zc << 8) | ((u_long) zd);
 
643
        at[i].at_iaddr.s_addr = htonl(tmp_a);
 
644
        at[i].if_index = Interface_Index_By_Name(ifname, strlen(ifname));
 
645
        i++;
 
646
    }
 
647
    arptab_size = i;
 
648
 
 
649
    fclose(in);
 
650
    time(&tm);
 
651
#endif                          /* linux */
 
652
#else                           /* CAN_USE_SYSCTL */
 
653
 
 
654
    int             mib[6];
 
655
    size_t          needed;
 
656
 
 
657
    mib[0] = CTL_NET;
 
658
    mib[1] = PF_ROUTE;
 
659
    mib[2] = 0;
 
660
    mib[3] = AF_INET;
 
661
    mib[4] = NET_RT_FLAGS;
 
662
    mib[5] = RTF_LLINFO;
 
663
 
 
664
    if (at)
 
665
        free(at);
 
666
    rtnext = lim = at = 0;
 
667
 
 
668
    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
 
669
        snmp_log_perror("route-sysctl-estimate");
 
670
    else {
 
671
        if ((at = malloc(needed ? needed : 1)) == NULL)
 
672
            snmp_log_perror("malloc");
 
673
        else {
 
674
            if (sysctl(mib, 6, at, &needed, NULL, 0) < 0)
 
675
                snmp_log_perror("actual retrieval of routing table");
 
676
            else {
 
677
                lim = at + needed;
 
678
                rtnext = at;
 
679
            }
 
680
        }
 
681
    }
 
682
 
 
683
#endif                          /* CAN_USE_SYSCTL */
 
684
}
 
685
 
 
686
#ifdef ARP_SCAN_FOUR_ARGUMENTS
 
687
static int
 
688
ARP_Scan_Next(u_long * IPAddr, char *PhysAddr, u_long * ifType,
 
689
              u_short * ifIndex)
 
690
#else
 
691
static int
 
692
ARP_Scan_Next(u_long * IPAddr, char *PhysAddr, u_long * ifType)
 
693
#endif
 
694
{
 
695
#ifndef CAN_USE_SYSCTL
 
696
#ifdef linux
 
697
    if (arptab_current < arptab_size) {
 
698
        /*
 
699
         * copy values 
 
700
         */
 
701
        *IPAddr = at[arptab_current].at_iaddr.s_addr;
 
702
        *ifType =
 
703
            (at[arptab_current].
 
704
             at_flags & ATF_PERM) ? 4 /*static */ : 3 /*dynamic */ ;
 
705
        *ifIndex = at[arptab_current].if_index;
 
706
        memcpy(PhysAddr, &at[arptab_current].at_enaddr,
 
707
               sizeof(at[arptab_current].at_enaddr));
 
708
 
 
709
        /*
 
710
         * increment to point next entry 
 
711
         */
 
712
        arptab_current++;
 
713
        /*
 
714
         * return success 
 
715
         */
 
716
        return (1);
 
717
    }
 
718
#elif defined(hpux11)
 
719
    if (arptab_current < arptab_size) {
 
720
        /*
 
721
         * copy values 
 
722
         */
 
723
        *IPAddr = at[arptab_current].NetAddr;
 
724
        memcpy(PhysAddr, at[arptab_current].PhysAddr.o_bytes,
 
725
               at[arptab_current].PhysAddr.o_length);
 
726
        *ifType = at[arptab_current].Type;
 
727
        *ifIndex = at[arptab_current].IfIndex;
 
728
        /*
 
729
         * increment to point next entry 
 
730
         */
 
731
        arptab_current++;
 
732
        /*
 
733
         * return success 
 
734
         */
 
735
        return (1);
 
736
    }
 
737
#elif !defined(ARP_SCAN_FOUR_ARGUMENTS) || defined(hpux)
 
738
    register struct arptab *atab;
 
739
 
 
740
    while (arptab_current < arptab_size) {
 
741
#ifdef STRUCT_ARPHD_HAS_AT_NEXT
 
742
        /*
 
743
         * The arp table is an array of linked lists of arptab entries.
 
744
         * Unused slots have pointers back to the array entry itself 
 
745
         */
 
746
 
 
747
        if (at_ptr == (auto_nlist_value(ARPTAB_SYMBOL) +
 
748
                       arptab_current * sizeof(struct arphd))) {
 
749
            /*
 
750
             * Usused 
 
751
             */
 
752
            arptab_current++;
 
753
            at_ptr = at[arptab_current].at_next;
 
754
            continue;
 
755
        }
 
756
 
 
757
        klookup(at_ptr, (char *) &at_entry, sizeof(struct arptab));
 
758
        klookup(at_entry.at_ac, (char *) &at_com, sizeof(struct arpcom));
 
759
 
 
760
        at_ptr = at_entry.at_next;
 
761
        atab = &at_entry;
 
762
        *ifIndex = at_com.ac_if.if_index;       /* not strictly ARPHD */
 
763
#else                           /* STRUCT_ARPHD_HAS_AT_NEXT */
 
764
        atab = &at[arptab_current++];
 
765
#endif                          /* STRUCT_ARPHD_HAS_AT_NEXT */
 
766
        if (!(atab->at_flags & ATF_COM))
 
767
            continue;
 
768
        *ifType = (atab->at_flags & ATF_PERM) ? 4 : 3;
 
769
        *IPAddr = atab->at_iaddr.s_addr;
 
770
#if defined (sunV3) || defined(sparc) || defined(hpux)
 
771
        memcpy(PhysAddr, (char *) &atab->at_enaddr,
 
772
               sizeof(atab->at_enaddr));
 
773
#endif
 
774
#if defined(mips) || defined(ibm032)
 
775
        memcpy(PhysAddr, (char *) atab->at_enaddr,
 
776
               sizeof(atab->at_enaddr));
 
777
#endif
 
778
        return (1);
 
779
    }
 
780
#endif                          /* linux || hpux11 || !ARP_SCAN_FOUR_ARGUMENTS || hpux */
 
781
 
 
782
    return 0;                   /* we need someone with an irix box to fix this section */
 
783
 
 
784
#else                           /* !CAN_USE_SYSCTL */
 
785
    struct rt_msghdr *rtm;
 
786
    struct sockaddr_inarp *sin;
 
787
    struct sockaddr_dl *sdl;
 
788
 
 
789
    while (rtnext < lim) {
 
790
        rtm = (struct rt_msghdr *) rtnext;
 
791
        sin = (struct sockaddr_inarp *) (rtm + 1);
 
792
        sdl = (struct sockaddr_dl *) (sin + 1);
 
793
        rtnext += rtm->rtm_msglen;
 
794
        if (sdl->sdl_alen) {
 
795
            *IPAddr = sin->sin_addr.s_addr;
 
796
            memcpy(PhysAddr, (char *) LLADDR(sdl), sdl->sdl_alen);
 
797
            *ifIndex = sdl->sdl_index;
 
798
            *ifType = 1;        /* XXX */
 
799
            return (1);
 
800
        }
 
801
    }
 
802
    return (0);                 /* "EOF" */
 
803
#endif                          /* !CAN_USE_SYSCTL */
 
804
}
 
805
#endif                          /* solaris2 */
 
806
 
 
807
#else                           /* WIN32 */
 
808
#include <iphlpapi.h>
 
809
 
 
810
extern WriteMethod write_arp;
 
811
MIB_IPNETROW   *arp_row = NULL;
 
812
int             create_flag = 0;
 
813
 
 
814
u_char         *
 
815
var_atEntry(struct variable *vp,
 
816
            oid * name,
 
817
            size_t * length,
 
818
            int exact, size_t * var_len, WriteMethod ** write_method)
 
819
{
 
820
    /*
 
821
     * Address Translation table object identifier is of form:
 
822
     * 1.3.6.1.2.1.3.1.?.interface.1.A.B.C.D,  where A.B.C.D is IP address.
 
823
     * Interface is at offset 10,
 
824
     * IPADDR starts at offset 12.
 
825
     *
 
826
     * IP Net to Media table object identifier is of form:
 
827
     * 1.3.6.1.2.1.4.22.1.?.interface.A.B.C.D,  where A.B.C.D is IP address.
 
828
     * Interface is at offset 10,
 
829
     * IPADDR starts at offset 11.
 
830
     */
 
831
    u_char         *cp;
 
832
    oid            *op;
 
833
    oid             lowest[16];
 
834
    oid             current[16];
 
835
    int             oid_length;
 
836
    int             lowState = -1;      /* Don't have one yet */
 
837
    PMIB_IPNETTABLE pIpNetTable = NULL;
 
838
    DWORD           status = NO_ERROR;
 
839
    DWORD           dwActualSize = 0;
 
840
    UINT            i;
 
841
    u_char          dest_addr[4];
 
842
 
 
843
    /*
 
844
     * fill in object part of name for current (less sizeof instance part) 
 
845
     */
 
846
    memcpy((char *) current, (char *) vp->name,
 
847
           (int) vp->namelen * sizeof(oid));
 
848
 
 
849
    if (current[6] == 3) {      /* AT group oid */
 
850
        oid_length = 16;
 
851
    } else {                    /* IP NetToMedia group oid */
 
852
        oid_length = 15;
 
853
    }
 
854
 
 
855
    status = GetIpNetTable(pIpNetTable, &dwActualSize, TRUE);
 
856
    if (status == ERROR_INSUFFICIENT_BUFFER) {
 
857
        pIpNetTable = (PMIB_IPNETTABLE) malloc(dwActualSize);
 
858
        if (pIpNetTable != NULL) {
 
859
            /*
 
860
             * Get the sorted IpNet Table 
 
861
             */
 
862
            status = GetIpNetTable(pIpNetTable, &dwActualSize, TRUE);
 
863
        }
 
864
    }
 
865
 
 
866
 
 
867
    if (status == NO_ERROR) {
 
868
        for (i = 0; i < pIpNetTable->dwNumEntries; ++i) {
 
869
            current[10] = pIpNetTable->table[i].dwIndex;
 
870
 
 
871
 
 
872
            if (current[6] == 3) {      /* AT group oid */
 
873
                current[11] = 1;
 
874
                op = current + 12;
 
875
            } else {            /* IP NetToMedia group oid */
 
876
                op = current + 11;
 
877
            }
 
878
            cp = (u_char *) & pIpNetTable->table[i].dwAddr;
 
879
            *op++ = *cp++;
 
880
            *op++ = *cp++;
 
881
            *op++ = *cp++;
 
882
            *op++ = *cp++;
 
883
 
 
884
            if (exact) {
 
885
                if (snmp_oid_compare(current, oid_length, name, *length) ==
 
886
                    0) {
 
887
                    memcpy((char *) lowest, (char *) current,
 
888
                           oid_length * sizeof(oid));
 
889
                    lowState = 0;
 
890
                    break;      /* no need to search further */
 
891
                }
 
892
            } else {
 
893
                if (snmp_oid_compare(current, oid_length, name, *length) >
 
894
                    0) {
 
895
                    memcpy((char *) lowest, (char *) current,
 
896
                           oid_length * sizeof(oid));
 
897
                    lowState = 0;
 
898
                    break;      /* As the table is sorted, no need to search further */
 
899
                }
 
900
            }
 
901
        }
 
902
    }
 
903
    if (arp_row == NULL) {
 
904
        /*
 
905
         * Free allocated memory in case of SET request's FREE phase 
 
906
         */
 
907
        arp_row = (PMIB_IPNETROW) malloc(sizeof(MIB_IPNETROW));
 
908
    }
 
909
 
 
910
    if (lowState < 0 || status != NO_ERROR) {
 
911
        /*
 
912
         * for creation of new row, only ipNetToMediaTable case is considered 
 
913
         */
 
914
        if (*length == 15 || *length == 16) {
 
915
            create_flag = 1;
 
916
            *write_method = write_arp;
 
917
            arp_row->dwIndex = name[10];
 
918
 
 
919
            if (*length == 15) {        /* ipNetToMediaTable */
 
920
                i = 11;
 
921
            } else {            /* at Table */
 
922
 
 
923
                i = 12;
 
924
            }
 
925
 
 
926
            dest_addr[0] = (u_char) name[i];
 
927
            dest_addr[1] = (u_char) name[i + 1];
 
928
            dest_addr[2] = (u_char) name[i + 2];
 
929
            dest_addr[3] = (u_char) name[i + 3];
 
930
            arp_row->dwAddr = *((DWORD *) dest_addr);
 
931
 
 
932
            arp_row->dwType = 4;        /* Static */
 
933
            arp_row->dwPhysAddrLen = 0;
 
934
        }
 
935
        free(pIpNetTable);
 
936
        return (NULL);
 
937
    }
 
938
 
 
939
    create_flag = 0;
 
940
    memcpy((char *) name, (char *) lowest, oid_length * sizeof(oid));
 
941
    *length = oid_length;
 
942
    *write_method = write_arp;
 
943
    *arp_row = pIpNetTable->table[i];
 
944
 
 
945
    switch (vp->magic) {
 
946
    case IPMEDIAIFINDEX:       /* also ATIFINDEX */
 
947
        *var_len = sizeof long_return;
 
948
        long_return = pIpNetTable->table[i].dwIndex;
 
949
        free(pIpNetTable);
 
950
        return (u_char *) & long_return;
 
951
    case IPMEDIAPHYSADDRESS:   /* also ATPHYSADDRESS */
 
952
        *var_len = pIpNetTable->table[i].dwPhysAddrLen;
 
953
        memcpy(return_buf, pIpNetTable->table[i].bPhysAddr, *var_len);
 
954
        free(pIpNetTable);
 
955
        return (u_char *) return_buf;
 
956
    case IPMEDIANETADDRESS:    /* also ATNETADDRESS */
 
957
        *var_len = sizeof long_return;
 
958
        long_return = pIpNetTable->table[i].dwAddr;
 
959
        free(pIpNetTable);
 
960
        return (u_char *) & long_return;
 
961
    case IPMEDIATYPE:
 
962
        *var_len = sizeof long_return;
 
963
        long_return = pIpNetTable->table[i].dwType;
 
964
        free(pIpNetTable);
 
965
        return (u_char *) & long_return;
 
966
    default:
 
967
        DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_atEntry\n",
 
968
                    vp->magic));
 
969
    }
 
970
    return NULL;
 
971
}
 
972
 
 
973
int
 
974
write_arp(int action,
 
975
          u_char * var_val,
 
976
          u_char var_val_type,
 
977
          size_t var_val_len, u_char * statP, oid * name, size_t length)
 
978
{
 
979
    int             var, retval = SNMP_ERR_NOERROR;
 
980
    static PMIB_IPNETROW oldarp_row = NULL;
 
981
    MIB_IPNETROW    temp_row;
 
982
    DWORD           status = NO_ERROR;
 
983
 
 
984
    /*
 
985
     * IP Net to Media table object identifier is of form:
 
986
     * 1.3.6.1.2.1.4.22.1.?.interface.A.B.C.D,  where A.B.C.D is IP address.
 
987
     * Interface is at offset 10,
 
988
     * IPADDR starts at offset 11.
 
989
     */
 
990
 
 
991
    if (name[6] == 3) {         /* AT group oid */
 
992
        if (length != 16) {
 
993
            snmp_log(LOG_ERR, "length error\n");
 
994
            return SNMP_ERR_NOCREATION;
 
995
        }
 
996
    } else {                    /* IP NetToMedia group oid */
 
997
        if (length != 15) {
 
998
            snmp_log(LOG_ERR, "length error\n");
 
999
            return SNMP_ERR_NOCREATION;
 
1000
        }
 
1001
    }
 
1002
 
 
1003
 
 
1004
    /*
 
1005
     * #define for ipNetToMediaTable entries are 1 less than corresponding sub-id in MIB
 
1006
     * * i.e. IPMEDIAIFINDEX defined as 0, but ipNetToMediaIfIndex registered as 1
 
1007
     */
 
1008
    var = name[9] - 1;
 
1009
    switch (action) {
 
1010
    case RESERVE1:
 
1011
        switch (var) {
 
1012
        case IPMEDIAIFINDEX:
 
1013
            if (var_val_type != ASN_INTEGER) {
 
1014
                snmp_log(LOG_ERR, "not integer\n");
 
1015
                return SNMP_ERR_WRONGTYPE;
 
1016
            }
 
1017
            if ((*((int *) var_val)) < 0) {
 
1018
                snmp_log(LOG_ERR, "invalid media ifIndex");
 
1019
                return SNMP_ERR_WRONGVALUE;
 
1020
            }
 
1021
            if (var_val_len > sizeof(int)) {
 
1022
                snmp_log(LOG_ERR, "bad length\n");
 
1023
                return SNMP_ERR_WRONGLENGTH;
 
1024
            }
 
1025
            break;
 
1026
        case IPMEDIANETADDRESS:
 
1027
            if (var_val_type != ASN_IPADDRESS) {
 
1028
                snmp_log(LOG_ERR, "not IP Address\n");
 
1029
                return SNMP_ERR_WRONGTYPE;
 
1030
            }
 
1031
            if ((*((int *) var_val)) < 0) {
 
1032
                snmp_log(LOG_ERR, "invalid media net address");
 
1033
                return SNMP_ERR_WRONGVALUE;
 
1034
            }
 
1035
            if (var_val_len > sizeof(DWORD)) {
 
1036
                snmp_log(LOG_ERR, "bad length\n");
 
1037
                return SNMP_ERR_WRONGLENGTH;
 
1038
            }
 
1039
            break;
 
1040
        case IPMEDIATYPE:
 
1041
            if (var_val_type != ASN_INTEGER) {
 
1042
                snmp_log(LOG_ERR, "not integer\n");
 
1043
                return SNMP_ERR_WRONGTYPE;
 
1044
            }
 
1045
            if ((*((int *) var_val)) < 1 || (*((int *) var_val)) > 4) {
 
1046
                snmp_log(LOG_ERR, "invalid media type");
 
1047
                return SNMP_ERR_WRONGVALUE;
 
1048
            }
 
1049
            if (var_val_len > sizeof(int)) {
 
1050
                snmp_log(LOG_ERR, "bad length\n");
 
1051
                return SNMP_ERR_WRONGLENGTH;
 
1052
            }
 
1053
            break;
 
1054
        case IPMEDIAPHYSADDRESS:
 
1055
            if (var_val_type != ASN_OCTET_STR) {
 
1056
                snmp_log(LOG_ERR, "not octet str");
 
1057
                return SNMP_ERR_WRONGTYPE;
 
1058
            }
 
1059
            if (var_val_len != 6) {
 
1060
                snmp_log(LOG_ERR, "not correct ipAddress length: %d",
 
1061
                         var_val_len);
 
1062
                return SNMP_ERR_WRONGLENGTH;
 
1063
            }
 
1064
            break;
 
1065
        default:
 
1066
            DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_rte\n",
 
1067
                        var + 1));
 
1068
            return SNMP_ERR_NOTWRITABLE;
 
1069
        }
 
1070
        break;
 
1071
    case RESERVE2:
 
1072
        /*
 
1073
         * Save the old value, in case of UNDO 
 
1074
         */
 
1075
        if (oldarp_row == NULL) {
 
1076
            oldarp_row = (PMIB_IPNETROW) malloc(sizeof(MIB_IPNETROW));
 
1077
            *oldarp_row = *arp_row;
 
1078
        }
 
1079
        break;
 
1080
    case ACTION:               /* Perform the SET action (if reversible) */
 
1081
        switch (var) {
 
1082
 
 
1083
        case IPMEDIAIFINDEX:
 
1084
            temp_row = *arp_row;
 
1085
            arp_row->dwIndex = *((int *) var_val);
 
1086
            /*
 
1087
             * In case of new entry, physical address is mandatory.
 
1088
             * * SetIpNetEntry will be done in COMMIT case 
 
1089
             */
 
1090
            if (!create_flag) {
 
1091
                if (SetIpNetEntry(arp_row) != NO_ERROR) {
 
1092
                    arp_row->dwIndex = temp_row.dwIndex;
 
1093
                    retval = SNMP_ERR_COMMITFAILED;
 
1094
                }
 
1095
                /*
 
1096
                 * Don't know yet, whether change in ifIndex creates new row or not 
 
1097
                 */
 
1098
                /*
 
1099
                 * else{ 
 
1100
                 */
 
1101
                /*
 
1102
                 * temp_row.dwType = 2; 
 
1103
                 */
 
1104
                /*
 
1105
                 * if(SetIpNetEntry(&temp_row) != NO_ERROR) 
 
1106
                 */
 
1107
                /*
 
1108
                 * retval = SNMP_ERR_COMMITFAILED; 
 
1109
                 */
 
1110
                /*
 
1111
                 * } 
 
1112
                 */
 
1113
            }
 
1114
            break;
 
1115
        case IPMEDIANETADDRESS:
 
1116
            temp_row = *arp_row;
 
1117
            arp_row->dwAddr = *((int *) var_val);
 
1118
            if (!create_flag) {
 
1119
                if (SetIpNetEntry(arp_row) != NO_ERROR) {
 
1120
                    arp_row->dwAddr = oldarp_row->dwAddr;
 
1121
                    retval = SNMP_ERR_COMMITFAILED;
 
1122
                } else {
 
1123
                    temp_row.dwType = 2;
 
1124
                    if (SetIpNetEntry(&temp_row) != NO_ERROR) {
 
1125
                        snmp_log(LOG_ERR,
 
1126
                                 "Failed in ACTION, while deleting old row \n");
 
1127
                        retval = SNMP_ERR_COMMITFAILED;
 
1128
                    }
 
1129
                }
 
1130
            }
 
1131
            break;
 
1132
        case IPMEDIATYPE:
 
1133
            arp_row->dwType = *((int *) var_val);
 
1134
            if (!create_flag) {
 
1135
                if (SetIpNetEntry(arp_row) != NO_ERROR)
 
1136
                    retval = SNMP_ERR_COMMITFAILED;
 
1137
            }
 
1138
            break;
 
1139
        case IPMEDIAPHYSADDRESS:
 
1140
            memcpy(arp_row->bPhysAddr, var_val, var_val_len);
 
1141
            arp_row->dwPhysAddrLen = var_val_len;
 
1142
            if (!create_flag) {
 
1143
                if (SetIpNetEntry(arp_row) != NO_ERROR)
 
1144
                    retval = SNMP_ERR_COMMITFAILED;
 
1145
            }
 
1146
            break;
 
1147
        default:
 
1148
            DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_arp\n",
 
1149
                        var + 1));
 
1150
            retval = SNMP_ERR_NOTWRITABLE;
 
1151
        }
 
1152
        return retval;
 
1153
    case UNDO:
 
1154
        /*
 
1155
         * Reverse the SET action and free resources 
 
1156
         */
 
1157
        if (oldarp_row != NULL) {
 
1158
            /*
 
1159
             * UNDO the changes done for existing entry. 
 
1160
             */
 
1161
            if (!create_flag) {
 
1162
                if ((status = SetIpNetEntry(oldarp_row)) != NO_ERROR) {
 
1163
                    snmp_log(LOG_ERR, "Error in case UNDO, status : %d\n",
 
1164
                             status);
 
1165
                    retval = SNMP_ERR_UNDOFAILED;
 
1166
                }
 
1167
            }
 
1168
 
 
1169
            if (oldarp_row->dwAddr != arp_row->dwAddr) {
 
1170
                arp_row->dwType = 2;    /*If row was added/created delete that row */
 
1171
 
 
1172
                if ((status = SetIpNetEntry(arp_row)) != NO_ERROR) {
 
1173
                    snmp_log(LOG_ERR,
 
1174
                             "Error while deleting added row, status : %d\n",
 
1175
                             status);
 
1176
                    retval = SNMP_ERR_UNDOFAILED;
 
1177
                }
 
1178
            }
 
1179
            free(oldarp_row);
 
1180
            oldarp_row = NULL;
 
1181
            free(arp_row);
 
1182
            arp_row = NULL;
 
1183
            return retval;
 
1184
        }
 
1185
        break;
 
1186
    case COMMIT:
 
1187
        /*
 
1188
         * if new entry and physical address specified, create new entry 
 
1189
         */
 
1190
        if (create_flag) {
 
1191
            if (arp_row->dwPhysAddrLen != 0) {
 
1192
                if ((status = CreateIpNetEntry(arp_row)) != NO_ERROR) {
 
1193
                    snmp_log(LOG_ERR,
 
1194
                             "Inside COMMIT: CreateIpNetEntry failed, status %d\n",
 
1195
                             status);
 
1196
                    retval = SNMP_ERR_COMMITFAILED;
 
1197
                }
 
1198
            } else {
 
1199
                /*
 
1200
                 * For new entry, physical address must be set. 
 
1201
                 */
 
1202
                snmp_log(LOG_ERR,
 
1203
                         "Can't create new entry without physical address\n");
 
1204
                retval = SNMP_ERR_WRONGVALUE;
 
1205
            }
 
1206
            /*
 
1207
             * unset the create_flag, so that CreateIpNetEntry called only once 
 
1208
             */
 
1209
            create_flag = 0;
 
1210
        }
 
1211
 
 
1212
    case FREE:
 
1213
        /*
 
1214
         * Free any resources allocated 
 
1215
         */
 
1216
        free(oldarp_row);
 
1217
        oldarp_row = NULL;
 
1218
        free(arp_row);
 
1219
        arp_row = NULL;
 
1220
        break;
 
1221
    }
 
1222
    return retval;
 
1223
}
 
1224
#endif                          /* WIN32 */