/* * 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 #include #include #include "netSnmpHostsTable_access.h" #include "netSnmpHostsTable_enums.h" #include #include #include #include #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) { fclose(out); 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; }