Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

FreeBSD: разрешение MAC адресов

355
17 февраля 2007 года
<SCORP>
786 / / 21.10.2006
здравствуйте. собссно, сабж. как это можно написать? в смысле на С. нашёл функцию типа arpresolve. но ей надо ifnet -- укзатель на интерфейс. список этих интерфейсов хранится в списке, который можно перебирать макросами TAILQ_... самая главная проблема -- не могу понять, как получить голову этого списка, чтобы его как-то перебирать!
или может я вообще не туда пошёл?
355
18 февраля 2007 года
<SCORP>
786 / / 21.10.2006
функция arpresolve не подходит, т.к. она kernel-mode
355
18 февраля 2007 года
<SCORP>
786 / / 21.10.2006
Код:
#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");

}


получает MAC адрес из кеша ОС. выдрано из исходников тулзы arp. ещё не разбирался, но помоему там можно кой-чё повыбрасывать. и ещё я там лишних хедеров мог понаписывать
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог