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

« back to all changes in this revision

Viewing changes to agent/mibgroup/examples/netSnmpHostsTable_access.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
/*
 
3
 * Note: this file originally auto-generated by mib2c using
 
4
 *        : mib2c.access_functions.conf,v 1.3 2003/05/31 00:11:57 hardaker Exp $
 
5
 */
 
6
 
 
7
#include <net-snmp/net-snmp-config.h>
 
8
#include <net-snmp/net-snmp-includes.h>
 
9
#include <net-snmp/agent/net-snmp-agent-includes.h>
 
10
#include "netSnmpHostsTable_access.h"
 
11
#include "netSnmpHostsTable_enums.h"
 
12
#include <netinet/in.h>
 
13
#include <arpa/inet.h>
 
14
#include <stdio.h>
 
15
#include <unistd.h>
 
16
 
 
17
#define MAX_HOSTS_LINE 4096
 
18
 
 
19
/* XXX: make .conf token */
 
20
#define HOSTS_FILE "/etc/hosts"
 
21
 
 
22
typedef struct my_loop_info_s {
 
23
   FILE *filep;
 
24
   in_addr_t theaddr;
 
25
   char line[MAX_HOSTS_LINE];
 
26
   char hostname[64];
 
27
   int lineno;
 
28
   char *current_ptr;
 
29
} my_loop_info;
 
30
 
 
31
typedef struct my_data_info_s {
 
32
   in_addr_t theaddr;
 
33
   in_addr_t theoldaddr;
 
34
   char hostname[64];
 
35
   int lineno;
 
36
} my_data_info;   
 
37
 
 
38
/** NOTE:
 
39
 * - these get_ routines MUST return data that will not be freed (ie,
 
40
 *   use static variables or persistent data).  It will be copied, if
 
41
 *   needed, immediately after the get_ routine has been called.
 
42
 * - these SET routines must copy the incoming data and can not take
 
43
 *   ownership of the memory passed in by the val pointer.
 
44
 */
 
45
 
 
46
 
 
47
/** returns the first data point within the netSnmpHostsTable table data.
 
48
 
 
49
    Set the my_loop_context variable to the first data point structure
 
50
    of your choice (from which you can find the next one).  This could
 
51
    be anything from the first node in a linked list, to an integer
 
52
    pointer containing the beginning of an array variable.
 
53
 
 
54
    Set the my_data_context variable to something to be returned to
 
55
    you later that will provide you with the data to return in a given
 
56
    row.  This could be the same pointer as what my_loop_context is
 
57
    set to, or something different.
 
58
 
 
59
    The put_index_data variable contains a list of snmp variable
 
60
    bindings, one for each index in your table.  Set the values of
 
61
    each appropriately according to the data matching the first row
 
62
    and return the put_index_data variable at the end of the function.
 
63
*/
 
64
netsnmp_variable_list *
 
65
netSnmpHostsTable_get_first_data_point(void **my_loop_context,
 
66
                                       void **my_data_context,
 
67
                                       netsnmp_variable_list *
 
68
                                       put_index_data,
 
69
                                       netsnmp_iterator_info *mydata)
 
70
{
 
71
    my_loop_info *loopctx;
 
72
 
 
73
    loopctx = SNMP_MALLOC_TYPEDEF(my_loop_info);
 
74
 
 
75
    if (!loopctx)
 
76
        return NULL; /*XXX log err */
 
77
 
 
78
    loopctx->filep = fopen("/etc/hosts","r");
 
79
 
 
80
    if (!loopctx->filep) {
 
81
        free(loopctx);
 
82
        return NULL;
 
83
    }
 
84
 
 
85
    /* at this point, we need to get the first name and address from
 
86
       the file.  But since our get_next_data_point function does
 
87
       this, we'll use it instead of duplicating code */
 
88
    *my_loop_context = loopctx;
 
89
 
 
90
    return netSnmpHostsTable_get_next_data_point(my_loop_context,
 
91
                                                 my_data_context,
 
92
                                                 put_index_data,
 
93
                                                 mydata);
 
94
}
 
95
 
 
96
/** functionally the same as netSnmpHostsTable_get_first_data_point, but
 
97
   my_loop_context has already been set to a previous value and should
 
98
   be updated to the next in the list.  For example, if it was a
 
99
   linked list, you might want to cast it to your local data type and
 
100
   then return my_loop_context->next.  The my_data_context pointer
 
101
   should be set to something you need later and the indexes in
 
102
   put_index_data updated again. */
 
103
netsnmp_variable_list *
 
104
netSnmpHostsTable_get_next_data_point(void **my_loop_context,
 
105
                                      void **my_data_context,
 
106
                                      netsnmp_variable_list *
 
107
                                      put_index_data,
 
108
                                      netsnmp_iterator_info *mydata)
 
109
{
 
110
    my_loop_info *loopctx = *my_loop_context;
 
111
    char tmpstring[64];
 
112
 
 
113
    if (!loopctx)
 
114
        return NULL;
 
115
 
 
116
    while(loopctx->filep) {
 
117
        if (!loopctx->current_ptr) {
 
118
            if (!fgets(loopctx->line, sizeof(loopctx->line), loopctx->filep)) {
 
119
                /* we're done */
 
120
                fclose(loopctx->filep);
 
121
                loopctx->filep = NULL;
 
122
                return NULL;
 
123
            }
 
124
            loopctx->lineno++;
 
125
            loopctx->current_ptr = loopctx->line;
 
126
            loopctx->current_ptr = skip_white(loopctx->current_ptr);
 
127
 
 
128
            if (loopctx->current_ptr == NULL || *loopctx->current_ptr == '#') {
 
129
                loopctx->current_ptr = NULL;
 
130
                continue;
 
131
            }
 
132
 
 
133
            loopctx->current_ptr =
 
134
                copy_nword(loopctx->current_ptr, tmpstring, sizeof(tmpstring));
 
135
            loopctx->theaddr = inet_addr(tmpstring);
 
136
 
 
137
            if (!loopctx->current_ptr)
 
138
                continue;
 
139
        }
 
140
 
 
141
        loopctx->current_ptr =
 
142
            copy_nword(loopctx->current_ptr, loopctx->hostname, sizeof(loopctx->hostname));
 
143
        
 
144
        snmp_set_var_value(put_index_data, (u_char *) loopctx->hostname,
 
145
                           strlen(loopctx->hostname));
 
146
        return put_index_data;
 
147
    }
 
148
    
 
149
    /* we're out of data */
 
150
    *my_loop_context = NULL;
 
151
    return NULL;
 
152
}
 
153
 
 
154
void *
 
155
netSnmpHostsTable_context_convert_function(void *loop_context,
 
156
                                           netsnmp_iterator_info *iinfo)
 
157
{
 
158
    my_loop_info *loopctx = loop_context;
 
159
    my_data_info *datactx = SNMP_MALLOC_TYPEDEF(my_data_info);
 
160
    if (!datactx)
 
161
        return NULL;
 
162
    datactx->theoldaddr = datactx->theaddr = loopctx->theaddr;
 
163
    datactx->lineno = loopctx->lineno;
 
164
    strcpy(datactx->hostname, loopctx->hostname);
 
165
    return datactx;
 
166
}
 
167
 
 
168
/** Create a data_context for non-existent rows that SETs are performed on.
 
169
 *  return a void * pointer which will be passed to subsequent get_XXX
 
170
 *  and set_XXX functions for data retrival and modification during
 
171
 *  this SET request.
 
172
 *
 
173
 *  The indexs are encoded (in order) into the index_data pointer if it
 
174
 *  would be helpful to use that information.
 
175
 */
 
176
void           *
 
177
netSnmpHostsTable_create_data_context(netsnmp_variable_list * index_data)
 
178
{
 
179
    my_data_info *datactx = SNMP_MALLOC_TYPEDEF(my_data_info);
 
180
    if (!datactx)
 
181
        return NULL;
 
182
    strncpy(datactx->hostname, index_data->val.string,
 
183
            strlen(index_data->val.string));
 
184
    return datactx;
 
185
}
 
186
 
 
187
void
 
188
netSnmpHostsTable_data_free(void *data, netsnmp_iterator_info *iinfo)
 
189
{
 
190
    free(data);
 
191
}
 
192
 
 
193
void
 
194
netSnmpHostsTable_loop_free(void *loopctx, netsnmp_iterator_info *iinfo)
 
195
{
 
196
    free(loopctx);
 
197
}
 
198
 
 
199
/** If the implemented set_* functions don't operate directly on the
 
200
   real-live data (which is actually recommended), then this function
 
201
   can be used to take a given my_data_context pointer and "commit" it
 
202
   to whereever the modified data needs to be put back to.  For
 
203
   example, if this was a routing table you could publish the modified
 
204
   routes back into the kernel at this point.
 
205
 
 
206
   rowStatus will be set to 1 if new, 0 if not or -1 if it should
 
207
   be deleted.
 
208
 
 
209
   If you free the data yourself, make sure to *my_data_context = NULL */
 
210
int
 
211
netSnmpHostsTable_commit_row(void **my_data_context, int new_or_del)
 
212
{
 
213
    /** Add any necessary commit code here */
 
214
    FILE *in, *out;
 
215
    char line[MAX_HOSTS_LINE], line2[MAX_HOSTS_LINE];
 
216
    char myaddr[64], *cp;
 
217
    my_data_info *datactx = *my_data_context;
 
218
    size_t line2_sz;
 
219
    int foundit = 0;
 
220
 
 
221
    if (datactx->theaddr == datactx->theoldaddr && new_or_del != -1)
 
222
        return SNMP_ERR_NOERROR; /* no change in the value */
 
223
 
 
224
    if ((out = fopen(HOSTS_FILE ".snmp", "w")) == NULL)
 
225
        return SNMP_ERR_COMMITFAILED;
 
226
    
 
227
    if ((in = fopen(HOSTS_FILE, "r")) == NULL)
 
228
        return SNMP_ERR_COMMITFAILED;
 
229
 
 
230
    while(fgets(line, sizeof(line), in)) {
 
231
        copy_nword(line,myaddr,sizeof(myaddr));
 
232
        if (inet_addr(myaddr) == datactx->theaddr && new_or_del != -1) {
 
233
            foundit = 1;
 
234
            /* right line to append to */
 
235
            line[strlen(line)-1] = '\0'; /* nuke the new line */
 
236
            fprintf(out, "%s %s\n", line, datactx->hostname);
 
237
        } else if (inet_addr(myaddr) == datactx->theoldaddr) {
 
238
            /* find and remove the name from the current line */
 
239
            int count = 0;
 
240
            cp = copy_nword(line, line2, sizeof(line2)); /* pass the addr */
 
241
            if (strlen(line2) > sizeof(line2)-2) {
 
242
              errorit:
 
243
                fclose(in);
 
244
                fclose(out);
 
245
                unlink(HOSTS_FILE ".snmp");
 
246
                return SNMP_ERR_RESOURCEUNAVAILABLE;
 
247
            }
 
248
            line2_sz = strlen(line2);
 
249
            line2[line2_sz++] = '\t';
 
250
            while(cp) {
 
251
                cp = copy_nword(cp, &line2[line2_sz], sizeof(line2)-line2_sz);
 
252
                if (strcmp(&line2[line2_sz], datactx->hostname) == 0) {
 
253
                    /* a match, so don't add it to line2 (which means
 
254
                       don't update the write line2_sz index */
 
255
                } else {
 
256
                    if (strlen(line2) > sizeof(line2)-2) {
 
257
                        goto errorit;
 
258
                    }
 
259
                    line2_sz = strlen(line2);
 
260
                    line2[line2_sz++] = ' ';
 
261
                    count++;
 
262
                }
 
263
            }
 
264
            if (count) {
 
265
                /* at least one name was still present on the line, so
 
266
                   save it to the new file */
 
267
                line2[line2_sz] = '\0';
 
268
                fprintf(out, "%s\n", line2);
 
269
            }
 
270
        } else {
 
271
            fputs(line, out);
 
272
        }
 
273
    }
 
274
 
 
275
    if (!foundit && new_or_del != -1) {
 
276
        /* couldn't add it to an existing line, so append a new one */
 
277
        fprintf(out, "%d.%d.%d.%d\t%s\n",
 
278
                (0x000000ff & datactx->theaddr),
 
279
                (0x0000ff00 & datactx->theaddr) >> 8,
 
280
                (0x00ff0000 & datactx->theaddr) >> 16,
 
281
                (0xff000000 & datactx->theaddr) >> 24,
 
282
                datactx->hostname);
 
283
    }
 
284
    fclose(out); /* close out first to minimize race condition */
 
285
    fclose(in);
 
286
    /*
 
287
     * race condition here - someone else could open the file after
 
288
     *  we close it but before we can rename it.
 
289
     */
 
290
    if (!rename(HOSTS_FILE ".snmp", HOSTS_FILE))
 
291
        return SNMP_ERR_COMMITFAILED;
 
292
        
 
293
    /*
 
294
     * return no errors.  And there shouldn't be any!!!  Ever!!!  You
 
295
     * should have checked the values long before this. 
 
296
     */
 
297
    return SNMP_ERR_NOERROR;
 
298
}
 
299
 
 
300
 
 
301
/*
 
302
 * User-defined data access functions (per column) for data in table
 
303
 * netSnmpHostsTable
 
304
 */
 
305
 
 
306
 
 
307
long           *
 
308
get_netSnmpHostAddressType(void *data_context, size_t * ret_len)
 
309
{
 
310
    static long ret = NETSNMPHOSTADDRESSTYPE_IPV4;
 
311
    *ret_len = sizeof(ret);
 
312
    return &ret;
 
313
}
 
314
 
 
315
int
 
316
set_netSnmpHostAddressType(void *data_context, long *val, size_t val_len)
 
317
{
 
318
    return SNMP_ERR_NOERROR; /* always ipv4 */
 
319
}
 
320
 
 
321
char           *
 
322
get_netSnmpHostAddress(void *data_context, size_t * ret_len)
 
323
{
 
324
    my_data_info *datainfo = data_context;
 
325
    *ret_len = sizeof(in_addr_t);  /* XXX: make sure it's 4 */
 
326
    return (char *) &datainfo->theaddr;
 
327
}
 
328
 
 
329
int
 
330
set_netSnmpHostAddress(void *data_context, char *val, size_t val_len)
 
331
{
 
332
    my_data_info *datainfo = data_context;
 
333
    memcpy(&datainfo->theaddr, val, val_len);
 
334
    return SNMP_ERR_NOERROR;
 
335
}
 
336
 
 
337
long           *
 
338
get_netSnmpHostStorage(void *data_context, size_t * ret_len)
 
339
{
 
340
    static long ret = ST_NONVOLATILE;
 
341
    *ret_len = sizeof(ret);
 
342
    return &ret;
 
343
}
 
344
 
 
345
int
 
346
set_netSnmpHostStorage(void *data_context, long *val, size_t val_len)
 
347
{
 
348
    return SNMP_ERR_NOERROR;
 
349
}
 
350
 
 
351
long           *
 
352
get_netSnmpHostRowStatus(void *data_context, size_t * ret_len)
 
353
{
 
354
    static long ret = RS_ACTIVE;
 
355
    *ret_len = sizeof(ret);
 
356
    return &ret;
 
357
}
 
358
 
 
359
int
 
360
set_netSnmpHostRowStatus(void *data_context, long *val, size_t val_len)
 
361
{
 
362
    /* XXX */
 
363
    return SNMP_ERR_NOERROR;
 
364
}