00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "config.h"
00010
00011 #include <ws2tcpip.h>
00012 #include <iphlpapi.h>
00013
00014 #include <errno.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017
00018 #include "dnet.h"
00019
00020 struct arp_handle {
00021 MIB_IPNETTABLE *iptable;
00022 };
00023
00024 arp_t *
00025 arp_open(void)
00026 {
00027 return (calloc(1, sizeof(arp_t)));
00028 }
00029
00030 int
00031 arp_add(arp_t *arp, const struct arp_entry *entry)
00032 {
00033 MIB_IPFORWARDROW ipfrow;
00034 MIB_IPNETROW iprow;
00035
00036 if (GetBestRoute(entry->arp_pa.addr_ip,
00037 IP_ADDR_ANY, &ipfrow) != NO_ERROR)
00038 return (-1);
00039
00040 iprow.dwIndex = ipfrow.dwForwardIfIndex;
00041 iprow.dwPhysAddrLen = ETH_ADDR_LEN;
00042 memcpy(iprow.bPhysAddr, &entry->arp_ha.addr_eth, ETH_ADDR_LEN);
00043 iprow.dwAddr = entry->arp_pa.addr_ip;
00044 iprow.dwType = 4;
00045
00046 if (CreateIpNetEntry(&iprow) != NO_ERROR)
00047 return (-1);
00048
00049 return (0);
00050 }
00051
00052 int
00053 arp_delete(arp_t *arp, const struct arp_entry *entry)
00054 {
00055 MIB_IPFORWARDROW ipfrow;
00056 MIB_IPNETROW iprow;
00057
00058 if (GetBestRoute(entry->arp_pa.addr_ip,
00059 IP_ADDR_ANY, &ipfrow) != NO_ERROR)
00060 return (-1);
00061
00062 memset(&iprow, 0, sizeof(iprow));
00063 iprow.dwIndex = ipfrow.dwForwardIfIndex;
00064 iprow.dwAddr = entry->arp_pa.addr_ip;
00065
00066 if (DeleteIpNetEntry(&iprow) != NO_ERROR) {
00067 errno = ENXIO;
00068 return (-1);
00069 }
00070 return (0);
00071 }
00072
00073 static int
00074 _arp_get_entry(const struct arp_entry *entry, void *arg)
00075 {
00076 struct arp_entry *e = (struct arp_entry *)arg;
00077
00078 if (addr_cmp(&entry->arp_pa, &e->arp_pa) == 0) {
00079 memcpy(&e->arp_ha, &entry->arp_ha, sizeof(e->arp_ha));
00080 return (1);
00081 }
00082 return (0);
00083 }
00084
00085 int
00086 arp_get(arp_t *arp, struct arp_entry *entry)
00087 {
00088 if (arp_loop(arp, _arp_get_entry, entry) != 1) {
00089 errno = ENXIO;
00090 SetLastError(ERROR_NO_DATA);
00091 return (-1);
00092 }
00093 return (0);
00094 }
00095
00096 int
00097 arp_loop(arp_t *arp, arp_handler callback, void *arg)
00098 {
00099 struct arp_entry entry;
00100 ULONG len;
00101 int i, ret;
00102
00103 for (len = sizeof(arp->iptable[0]); ; ) {
00104 if (arp->iptable)
00105 free(arp->iptable);
00106 arp->iptable = malloc(len);
00107 ret = GetIpNetTable(arp->iptable, &len, FALSE);
00108 if (ret == NO_ERROR)
00109 break;
00110 else if (ret != ERROR_INSUFFICIENT_BUFFER)
00111 return (-1);
00112 }
00113 entry.arp_pa.addr_type = ADDR_TYPE_IP;
00114 entry.arp_pa.addr_bits = IP_ADDR_BITS;
00115
00116 entry.arp_ha.addr_type = ADDR_TYPE_ETH;
00117 entry.arp_ha.addr_bits = ETH_ADDR_BITS;
00118
00119 for (i = 0; i < (int)arp->iptable->dwNumEntries; i++) {
00120 if (arp->iptable->table[i].dwPhysAddrLen != ETH_ADDR_LEN)
00121 continue;
00122 entry.arp_pa.addr_ip = arp->iptable->table[i].dwAddr;
00123 memcpy(&entry.arp_ha.addr_eth,
00124 arp->iptable->table[i].bPhysAddr, ETH_ADDR_LEN);
00125
00126 if ((ret = (*callback)(&entry, arg)) != 0)
00127 return (ret);
00128 }
00129 return (0);
00130 }
00131
00132 arp_t *
00133 arp_close(arp_t *arp)
00134 {
00135 if (arp != NULL) {
00136 if (arp->iptable != NULL)
00137 free(arp->iptable);
00138 free(arp);
00139 }
00140 return (NULL);
00141 }