#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/iso88025.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <nlist.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
static int get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr);
static int search(u_long addr);
static int get(char *host);
static struct sockaddr_inarp *getaddr(char *host);
static void print_entry(struct sockaddr_dl *sdl, struct sockaddr_inarp *s_in, struct rt_msghdr *rtm);
static char *rifname;
static int nflag = 0;
int main(int argc, char* argv[])
{
get("192.168.254.128");
return 0;
}
static int
get(char *host)
{
struct sockaddr_inarp *addr;
addr = getaddr(host);
if (addr == NULL)
return (1);
if (0 == search(addr->sin_addr.s_addr)) {
printf("%s (%s) -- no entry",
host, inet_ntoa(addr->sin_addr));
if (rifname)
printf(" on %s", rifname);
printf("\n");
return (1);
}
return (0);
}
static struct sockaddr_inarp *
getaddr(char *host)
{
struct hostent *hp;
static struct sockaddr_inarp reply;
bzero(&reply, sizeof(reply));
reply.sin_len = sizeof(reply);
reply.sin_family = AF_INET;
reply.sin_addr.s_addr = inet_addr(host);
if (reply.sin_addr.s_addr == INADDR_NONE) {
if (!(hp = gethostbyname(host))) {
warnx("%s: %s", host, hstrerror(h_errno));
return (NULL);
}
bcopy((char *)hp->h_addr, (char *)&reply.sin_addr,
sizeof reply.sin_addr);
}
return (&reply);
}
static int
search(u_long addr)
{
int mib[6];
size_t needed;
char *lim, *buf, *newbuf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin2;
struct sockaddr_dl *sdl;
char ifname[IF_NAMESIZE];
int st, found_entry = 0;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if (needed == 0) /* empty table */
return 0;
buf = NULL;
for (;;) {
newbuf = realloc(buf, needed);
if (newbuf == NULL) {
if (buf != NULL)
free(buf);
errx(1, "could not reallocate memory");
}
buf = newbuf;
st = sysctl(mib, 6, buf, &needed, NULL, 0);
if (st == 0 || errno != ENOMEM)
break;
needed += needed / 8;
}
if (st == -1)
err(1, "actual retrieval of routing table");
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
sin2 = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
if (rifname && if_indextoname(sdl->sdl_index, ifname) &&
strcmp(ifname, rifname))
continue;
if (addr) {
if (addr != sin2->sin_addr.s_addr)
continue;
found_entry = 1;
}
print_entry(sdl, sin2, rtm);
}
free(buf);
return (found_entry);
}
/*
* Display an arp entry
*/
static void
print_entry(struct sockaddr_dl *sdl, struct sockaddr_inarp *addr, struct rt_msghdr *rtm)
{
const char *host;
struct hostent *hp;
struct iso88025_sockaddr_dl_data *trld;
char ifname[IF_NAMESIZE];
int seg;
if (nflag == 0)
hp = gethostbyaddr((caddr_t)&(addr->sin_addr),
sizeof addr->sin_addr, AF_INET);
else
hp = 0;
if (hp)
host = hp->h_name;
else {
host = "?";
if (h_errno == TRY_AGAIN)
nflag = 1;
}
printf("%s (%s) at ", host, inet_ntoa(addr->sin_addr));
if (sdl->sdl_alen) {
if ((sdl->sdl_type == IFT_ETHER ||
sdl->sdl_type == IFT_L2VLAN) &&
sdl->sdl_alen == ETHER_ADDR_LEN)
printf("%s", ether_ntoa((struct ether_addr *)LLADDR(sdl)));
else {
int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
printf("%s", link_ntoa(sdl) + n);
}
} else
printf("(incomplete)");
if (if_indextoname(sdl->sdl_index, ifname) != NULL)
printf(" on %s", ifname);
if (rtm->rtm_rmx.rmx_expire == 0)
printf(" permanent");
if (addr->sin_other & SIN_PROXY)
printf(" published (proxy only)");
if (rtm->rtm_addrs & RTA_NETMASK) {
addr = (struct sockaddr_inarp *)
(SA_SIZE(sdl) + (char *)sdl);
if (addr->sin_addr.s_addr == 0xffffffff)
printf(" published");
if (addr->sin_len != 8)
printf("(weird)");
}
switch(sdl->sdl_type) {
case IFT_ETHER:
printf(" [ethernet]");
break;
case IFT_ISO88025:
printf(" [token-ring]");
trld = SDL_ISO88025(sdl);
if (trld->trld_rcf != 0) {
printf(" rt=%x", ntohs(trld->trld_rcf));
for (seg = 0; seg < ((TR_RCF_RIFLEN(trld->trld_rcf) - 2 ) / 2); seg++)
printf(":%x", ntohs(*(trld->trld_route[seg])));
}
break;
case IFT_FDDI:
printf(" [fddi]");
break;
case IFT_ATM:
printf(" [atm]");
break;
case IFT_L2VLAN:
printf(" [vlan]");
break;
case IFT_IEEE1394:
printf(" [firewire]");
break;
default:
break;
}
printf("\n");
}
FreeBSD: разрешение MAC адресов
или может я вообще не туда пошёл?
функция arpresolve не подходит, т.к. она kernel-mode
Код:
получает MAC адрес из кеша ОС. выдрано из исходников тулзы arp. ещё не разбирался, но помоему там можно кой-чё повыбрасывать. и ещё я там лишних хедеров мог понаписывать