| |
| /* |
| * Note: this file originally auto-generated by mib2c using |
| * : mib2c.access_functions.conf,v 1.3 2003/05/31 00:11:57 hardaker Exp $ |
| */ |
| |
| #include <net-snmp/net-snmp-config.h> |
| #include <net-snmp/net-snmp-includes.h> |
| #include <net-snmp/agent/net-snmp-agent-includes.h> |
| #include "netSnmpHostsTable_access.h" |
| #include "netSnmpHostsTable_enums.h" |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| |
| #define MAX_HOSTS_LINE 4096 |
| |
| /* XXX: make .conf token */ |
| #define HOSTS_FILE "/etc/hosts" |
| |
| typedef struct my_loop_info_s { |
| FILE *filep; |
| in_addr_t theaddr; |
| char line[MAX_HOSTS_LINE]; |
| char hostname[64]; |
| int lineno; |
| char *current_ptr; |
| } my_loop_info; |
| |
| typedef struct my_data_info_s { |
| in_addr_t theaddr; |
| in_addr_t theoldaddr; |
| char hostname[64]; |
| int lineno; |
| } my_data_info; |
| |
| /** NOTE: |
| * - these get_ routines MUST return data that will not be freed (ie, |
| * use static variables or persistent data). It will be copied, if |
| * needed, immediately after the get_ routine has been called. |
| * - these SET routines must copy the incoming data and can not take |
| * ownership of the memory passed in by the val pointer. |
| */ |
| |
| |
| /** returns the first data point within the netSnmpHostsTable table data. |
| |
| Set the my_loop_context variable to the first data point structure |
| of your choice (from which you can find the next one). This could |
| be anything from the first node in a linked list, to an integer |
| pointer containing the beginning of an array variable. |
| |
| Set the my_data_context variable to something to be returned to |
| you later that will provide you with the data to return in a given |
| row. This could be the same pointer as what my_loop_context is |
| set to, or something different. |
| |
| The put_index_data variable contains a list of snmp variable |
| bindings, one for each index in your table. Set the values of |
| each appropriately according to the data matching the first row |
| and return the put_index_data variable at the end of the function. |
| */ |
| netsnmp_variable_list * |
| netSnmpHostsTable_get_first_data_point(void **my_loop_context, |
| void **my_data_context, |
| netsnmp_variable_list * |
| put_index_data, |
| netsnmp_iterator_info *mydata) |
| { |
| my_loop_info *loopctx; |
| |
| loopctx = SNMP_MALLOC_TYPEDEF(my_loop_info); |
| |
| if (!loopctx) |
| return NULL; /*XXX log err */ |
| |
| loopctx->filep = fopen("/etc/hosts","r"); |
| |
| if (!loopctx->filep) { |
| free(loopctx); |
| return NULL; |
| } |
| |
| /* at this point, we need to get the first name and address from |
| the file. But since our get_next_data_point function does |
| this, we'll use it instead of duplicating code */ |
| *my_loop_context = loopctx; |
| |
| return netSnmpHostsTable_get_next_data_point(my_loop_context, |
| my_data_context, |
| put_index_data, |
| mydata); |
| } |
| |
| /** functionally the same as netSnmpHostsTable_get_first_data_point, but |
| my_loop_context has already been set to a previous value and should |
| be updated to the next in the list. For example, if it was a |
| linked list, you might want to cast it to your local data type and |
| then return my_loop_context->next. The my_data_context pointer |
| should be set to something you need later and the indexes in |
| put_index_data updated again. */ |
| netsnmp_variable_list * |
| netSnmpHostsTable_get_next_data_point(void **my_loop_context, |
| void **my_data_context, |
| netsnmp_variable_list * |
| put_index_data, |
| netsnmp_iterator_info *mydata) |
| { |
| my_loop_info *loopctx = *my_loop_context; |
| char tmpstring[64]; |
| |
| if (!loopctx) |
| return NULL; |
| |
| while(loopctx->filep) { |
| if (!loopctx->current_ptr) { |
| if (!fgets(loopctx->line, sizeof(loopctx->line), loopctx->filep)) { |
| /* we're done */ |
| fclose(loopctx->filep); |
| loopctx->filep = NULL; |
| return NULL; |
| } |
| loopctx->lineno++; |
| loopctx->current_ptr = loopctx->line; |
| loopctx->current_ptr = skip_white(loopctx->current_ptr); |
| |
| if (loopctx->current_ptr == NULL || *loopctx->current_ptr == '#') { |
| loopctx->current_ptr = NULL; |
| continue; |
| } |
| |
| loopctx->current_ptr = |
| copy_nword(loopctx->current_ptr, tmpstring, sizeof(tmpstring)); |
| loopctx->theaddr = inet_addr(tmpstring); |
| |
| if (!loopctx->current_ptr) |
| continue; |
| } |
| |
| loopctx->current_ptr = |
| copy_nword(loopctx->current_ptr, loopctx->hostname, sizeof(loopctx->hostname)); |
| |
| snmp_set_var_value(put_index_data, (u_char *) loopctx->hostname, |
| strlen(loopctx->hostname)); |
| return put_index_data; |
| } |
| |
| /* we're out of data */ |
| *my_loop_context = NULL; |
| return NULL; |
| } |
| |
| void * |
| netSnmpHostsTable_context_convert_function(void *loop_context, |
| netsnmp_iterator_info *iinfo) |
| { |
| my_loop_info *loopctx = loop_context; |
| my_data_info *datactx = SNMP_MALLOC_TYPEDEF(my_data_info); |
| if (!datactx) |
| return NULL; |
| datactx->theoldaddr = datactx->theaddr = loopctx->theaddr; |
| datactx->lineno = loopctx->lineno; |
| strcpy(datactx->hostname, loopctx->hostname); |
| return datactx; |
| } |
| |
| /** Create a data_context for non-existent rows that SETs are performed on. |
| * return a void * pointer which will be passed to subsequent get_XXX |
| * and set_XXX functions for data retrieval and modification during |
| * this SET request. |
| * |
| * The indexs are encoded (in order) into the index_data pointer if it |
| * would be helpful to use that information. |
| */ |
| void * |
| netSnmpHostsTable_create_data_context(netsnmp_variable_list * index_data) |
| { |
| my_data_info *datactx = SNMP_MALLOC_TYPEDEF(my_data_info); |
| |
| if (!datactx) |
| return NULL; |
| strlcpy(datactx->hostname, (const char *) index_data->val.string, |
| sizeof(datactx->hostname)); |
| return datactx; |
| } |
| |
| void |
| netSnmpHostsTable_data_free(void *data, netsnmp_iterator_info *iinfo) |
| { |
| free(data); |
| } |
| |
| void |
| netSnmpHostsTable_loop_free(void *loopctx, netsnmp_iterator_info *iinfo) |
| { |
| free(loopctx); |
| } |
| |
| /** If the implemented set_* functions don't operate directly on the |
| real-live data (which is actually recommended), then this function |
| can be used to take a given my_data_context pointer and "commit" it |
| to whereever the modified data needs to be put back to. For |
| example, if this was a routing table you could publish the modified |
| routes back into the kernel at this point. |
| |
| rowStatus will be set to 1 if new, 0 if not or -1 if it should |
| be deleted. |
| |
| If you free the data yourself, make sure to *my_data_context = NULL */ |
| int |
| netSnmpHostsTable_commit_row(void **my_data_context, int new_or_del) |
| { |
| /** Add any necessary commit code here */ |
| FILE *in, *out; |
| char line[MAX_HOSTS_LINE], line2[MAX_HOSTS_LINE]; |
| char myaddr[64], *cp; |
| my_data_info *datactx = *my_data_context; |
| size_t line2_sz; |
| int foundit = 0; |
| |
| if (datactx->theaddr == datactx->theoldaddr && new_or_del != -1) |
| return SNMP_ERR_NOERROR; /* no change in the value */ |
| |
| if ((out = fopen(HOSTS_FILE ".snmp", "w")) == NULL) |
| return SNMP_ERR_COMMITFAILED; |
| |
| if ((in = fopen(HOSTS_FILE, "r")) == NULL) |
| return SNMP_ERR_COMMITFAILED; |
| |
| while(fgets(line, sizeof(line), in)) { |
| copy_nword(line,myaddr,sizeof(myaddr)); |
| if (inet_addr(myaddr) == datactx->theaddr && new_or_del != -1) { |
| foundit = 1; |
| /* right line to append to */ |
| line[strlen(line)-1] = '\0'; /* nuke the new line */ |
| fprintf(out, "%s %s\n", line, datactx->hostname); |
| } else if (inet_addr(myaddr) == datactx->theoldaddr) { |
| /* find and remove the name from the current line */ |
| int count = 0; |
| cp = copy_nword(line, line2, sizeof(line2)); /* pass the addr */ |
| if (strlen(line2) > sizeof(line2)-2) { |
| errorit: |
| fclose(in); |
| fclose(out); |
| unlink(HOSTS_FILE ".snmp"); |
| return SNMP_ERR_RESOURCEUNAVAILABLE; |
| } |
| line2_sz = strlen(line2); |
| line2[line2_sz++] = '\t'; |
| while(cp) { |
| cp = copy_nword(cp, &line2[line2_sz], sizeof(line2)-line2_sz); |
| if (strcmp(&line2[line2_sz], datactx->hostname) == 0) { |
| /* a match, so don't add it to line2 (which means |
| don't update the write line2_sz index */ |
| } else { |
| if (strlen(line2) > sizeof(line2)-2) { |
| goto errorit; |
| } |
| line2_sz = strlen(line2); |
| line2[line2_sz++] = ' '; |
| count++; |
| } |
| } |
| if (count) { |
| /* at least one name was still present on the line, so |
| save it to the new file */ |
| line2[line2_sz] = '\0'; |
| fprintf(out, "%s\n", line2); |
| } |
| } else { |
| fputs(line, out); |
| } |
| } |
| |
| if (!foundit && new_or_del != -1) { |
| /* couldn't add it to an existing line, so append a new one */ |
| fprintf(out, "%d.%d.%d.%d\t%s\n", |
| (0x000000ff & datactx->theaddr), |
| (0x0000ff00 & datactx->theaddr) >> 8, |
| (0x00ff0000 & datactx->theaddr) >> 16, |
| (0xff000000 & datactx->theaddr) >> 24, |
| datactx->hostname); |
| } |
| fclose(out); /* close out first to minimize race condition */ |
| fclose(in); |
| /* |
| * race condition here - someone else could open the file after |
| * we close it but before we can rename it. |
| */ |
| if (!rename(HOSTS_FILE ".snmp", HOSTS_FILE)) |
| return SNMP_ERR_COMMITFAILED; |
| |
| /* |
| * return no errors. And there shouldn't be any!!! Ever!!! You |
| * should have checked the values long before this. |
| */ |
| return SNMP_ERR_NOERROR; |
| } |
| |
| |
| /* |
| * User-defined data access functions (per column) for data in table |
| * netSnmpHostsTable |
| */ |
| |
| |
| long * |
| get_netSnmpHostAddressType(void *data_context, size_t * ret_len) |
| { |
| static long ret = NETSNMPHOSTADDRESSTYPE_IPV4; |
| *ret_len = sizeof(ret); |
| return &ret; |
| } |
| |
| int |
| set_netSnmpHostAddressType(void *data_context, long *val, size_t val_len) |
| { |
| return SNMP_ERR_NOERROR; /* always ipv4 */ |
| } |
| |
| char * |
| get_netSnmpHostAddress(void *data_context, size_t * ret_len) |
| { |
| my_data_info *datainfo = data_context; |
| *ret_len = sizeof(in_addr_t); /* XXX: make sure it's 4 */ |
| return (char *) &datainfo->theaddr; |
| } |
| |
| int |
| set_netSnmpHostAddress(void *data_context, char *val, size_t val_len) |
| { |
| my_data_info *datainfo = data_context; |
| memcpy(&datainfo->theaddr, val, val_len); |
| return SNMP_ERR_NOERROR; |
| } |
| |
| long * |
| get_netSnmpHostStorage(void *data_context, size_t * ret_len) |
| { |
| static long ret = ST_NONVOLATILE; |
| *ret_len = sizeof(ret); |
| return &ret; |
| } |
| |
| int |
| set_netSnmpHostStorage(void *data_context, long *val, size_t val_len) |
| { |
| return SNMP_ERR_NOERROR; |
| } |
| |
| long * |
| get_netSnmpHostRowStatus(void *data_context, size_t * ret_len) |
| { |
| static long ret = RS_ACTIVE; |
| *ret_len = sizeof(ret); |
| return &ret; |
| } |
| |
| int |
| set_netSnmpHostRowStatus(void *data_context, long *val, size_t val_len) |
| { |
| /* XXX */ |
| return SNMP_ERR_NOERROR; |
| } |