netsnmp_defaultrouter_entry * netsnmp_access_defaultrouter_entry_create(void) { int rc = 0; netsnmp_defaultrouter_entry *entry = SNMP_MALLOC_TYPEDEF(netsnmp_defaultrouter_entry); DEBUGMSGTL(("access:defaultrouter:entry", "create\n")); if(NULL == entry) return NULL; entry->oid_index.len = 1; entry->oid_index.oids = &entry->ns_dr_index; /* * set up defaults */ entry->dr_lifetime = IPDEFAULTROUTERLIFETIME_MAX; entry->dr_preference = IPDEFAULTROUTERPREFERENCE_MEDIUM; rc = netsnmp_arch_defaultrouter_entry_init(entry); if (SNMP_ERR_NOERROR != rc) { DEBUGMSGT(("access:defaultrouter:create","error %d in arch init\n")); netsnmp_access_defaultrouter_entry_free(entry); entry = NULL; } return entry; }
/** * extra context cleanup * */ void ipDefaultRouterTable_rowreq_ctx_cleanup(ipDefaultRouterTable_rowreq_ctx * rowreq_ctx) { DEBUGMSGTL(("verbose:ipDefaultRouterTable:ipDefaultRouterTable_rowreq_ctx_cleanup", "called\n")); netsnmp_assert(NULL != rowreq_ctx); /* * TODO:211:o: |-> Perform extra ipDefaultRouterTable rowreq cleanup. */ netsnmp_access_defaultrouter_entry_free(rowreq_ctx->data); rowreq_ctx->data = NULL; } /* ipDefaultRouterTable_rowreq_ctx_cleanup */
/** * add new entry */ static void _add_new_entry(netsnmp_defaultrouter_entry *defaultrouter_entry, netsnmp_container *container) { ipDefaultRouterTable_rowreq_ctx *rowreq_ctx; DEBUGMSGTL(("ipDefaultRouterTable:access", "creating new entry\n")); netsnmp_assert(NULL != defaultrouter_entry); netsnmp_assert(NULL != container); /* * allocate an row context and set the index(es) */ rowreq_ctx = ipDefaultRouterTable_allocate_rowreq_ctx(defaultrouter_entry, NULL); if ((NULL != rowreq_ctx) && (MFD_SUCCESS == ipDefaultRouterTable_indexes_set(rowreq_ctx, defaultrouter_entry->dr_addresstype, defaultrouter_entry->dr_address, defaultrouter_entry->dr_address_len, defaultrouter_entry->dr_if_index))) { if (CONTAINER_INSERT(container, rowreq_ctx) < 0) { DEBUGMSGTL(("ipAddressTable:access", "container insert failed for new entry\n")); ipDefaultRouterTable_release_rowreq_ctx(rowreq_ctx); return; } } else { if (NULL != rowreq_ctx) { snmp_log(LOG_ERR, "error setting index while loading " "ipDefaultRouterTable cache.\n"); ipDefaultRouterTable_release_rowreq_ctx(rowreq_ctx); } else { snmp_log(LOG_ERR, "memory allocation failed while loading " "ipDefaultRouterTable cache.\n"); netsnmp_access_defaultrouter_entry_free(defaultrouter_entry); } return; } }
/** * check entry for update */ static void _check_entry_for_updates (ipDefaultRouterTable_rowreq_ctx * rowreq_ctx, void **magic) { netsnmp_container *defaultrouter_container = magic[0]; netsnmp_container *to_delete = (netsnmp_container *) magic[1]; /* * check for matching entry using secondary index. */ netsnmp_defaultrouter_entry *defaultrouter_entry = CONTAINER_FIND (defaultrouter_container, rowreq_ctx->data); if (NULL == defaultrouter_entry) { DEBUGMSGTL (("ipDefaultRouterTable:access", "removing missing entry\n")); if (NULL == to_delete) { magic[1] = to_delete = netsnmp_container_find ("lifo"); if (NULL == to_delete) snmp_log (LOG_ERR, "couldn't create delete container\n"); } if (NULL != to_delete) CONTAINER_INSERT (to_delete, rowreq_ctx); } else { DEBUGMSGTL (("ipDefaultRouterTable:access", "updating existing entry\n")); /* * Check for changes & update */ netsnmp_access_defaultrouter_entry_update (rowreq_ctx->data, defaultrouter_entry); /* * remove entry from ifcontainer */ CONTAINER_REMOVE (defaultrouter_container, defaultrouter_entry); netsnmp_access_defaultrouter_entry_free (defaultrouter_entry); } }
/** * * @retval 0 no errors * @retval !0 errors */ static int _load_defaultrouter_from_sysctl(netsnmp_container *container, int family) { netsnmp_defaultrouter_entry *entry; struct rt_msghdr *rtm; struct sockaddr *dst_sa, *gw_sa; char *buf, *lim, *newbuf, *next; char address[NETSNMP_ACCESS_DEFAULTROUTER_BUF_SIZE + 1]; int mib[6]; size_t address_len, needed; int address_type, err, preference, st; netsnmp_assert(NULL != container); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = family; mib[4] = NET_RT_DUMP; mib[5] = 0; err = 0; buf = newbuf = NULL; if (family == AF_INET) { address_len = 4; address_type = INETADDRESSTYPE_IPV4; #ifdef NETSNMP_ENABLE_IPV6 } else if (family == AF_INET6) { address_len = 16; address_type = INETADDRESSTYPE_IPV6; #endif } else { err = EINVAL; goto out; } if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { err = errno; goto out; } /* Empty arp table. */ if (needed == 0) goto out; for (;;) { newbuf = realloc(buf, needed); if (newbuf == NULL) { err = ENOMEM; goto out; } buf = newbuf; st = sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &needed, NULL, 0); if (st == 0 || errno != ENOMEM) break; else needed += needed / 8; /* XXX: why 8? */ } if (st == -1) { err = errno; goto out; } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { #ifdef NETSNMP_ENABLE_IPV6 struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; #endif rtm = (struct rt_msghdr *)next; if (!(rtm->rtm_addrs & RTA_GATEWAY)) continue; dst_sa = (struct sockaddr*)(rtm + 1); #ifdef SA_SIZE gw_sa = (struct sockaddr*)(SA_SIZE(dst_sa) + (char*)dst_sa); #else gw_sa = (struct sockaddr*)(RT_ROUNDUP(dst_sa->sa_len) + (char*)dst_sa); #endif switch (family) { case AF_INET: if (((struct sockaddr_in*)dst_sa)->sin_addr.s_addr != INADDR_ANY) continue; memcpy(address, &((struct sockaddr_in*)gw_sa)->sin_addr.s_addr, address_len); break; #ifdef NETSNMP_ENABLE_IPV6 case AF_INET6: if (memcmp(((struct sockaddr_in6*)dst_sa)->sin6_addr.s6_addr, &in6addr_any, sizeof in6addr_any) != 0) continue; /* XXX: need to determine qualifying criteria for * default gateways in IPv6. */ memcpy(address, &((struct sockaddr_in6*)dst_sa)->sin6_addr.s6_addr, address_len); break; #endif default: break; } entry = netsnmp_access_defaultrouter_entry_create(); if (NULL == entry) { err = ENOMEM; break; } /* XXX: this is wrong (hardcoding the router preference to medium). */ preference = 0; entry->ns_dr_index = ++idx_offset; entry->dr_addresstype = address_type; entry->dr_address_len = address_len; memcpy(entry->dr_address, address, sizeof(address)); entry->dr_if_index = rtm->rtm_index; entry->dr_lifetime = rtm->rtm_rmx.rmx_expire; entry->dr_preference = preference; if (CONTAINER_INSERT(container, entry) < 0) { DEBUGMSGTL(("access:arp:container", "error with defaultrouter_entry: " "insert into container failed.\n")); netsnmp_access_defaultrouter_entry_free(entry); goto out; } } out: free(buf); return err; }
void _access_defaultrouter_entry_release(netsnmp_defaultrouter_entry * entry, void *context) { netsnmp_access_defaultrouter_entry_free(entry); }