SIOCGARP to display the entire ARP table. | Unix Linux Forums | Programming

  Unix/Linux Go Back    


Programming Post questions about C, C++, Java, SQL, and other programming languages here.

SIOCGARP to display the entire ARP table.

Programming


Closed Linux or Unix Question    
 
Thread Tools Search this Thread Display Modes
    #1  
Old Unix and Linux 08-25-2010
semash! semash! is offline
Registered User
 
Join Date: Aug 2009
Last Activity: 11 June 2012, 6:16 AM EDT
Posts: 47
Thanks: 0
Thanked 1 Time in 1 Post
SIOCGARP to display the entire ARP table.

Hello everybody,

I have a working code that displays an entry from a given IP address. but, how can i display the entire ARP table? like the option 'arp -a' of the standard linux program.

This is the code:
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <net/if.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if_arp.h>

char *mac_ntoa(unsigned char *ptr){
static char address[30];
sprintf(address, "%02X:%02X:%02X:%02X:%02X:%02X",
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
return(address);
}

int main(int argc, char* argv[]){
int s;

struct arpreq req;
struct hostent *hp;
struct sockaddr_in *sin;

char *host = argv[1];

bzero((caddr_t)&req, sizeof(req));

sin = (struct sockaddr_in *)&req.arp_pa;
sin->sin_family = AF_INET; /* Address Family: Internet */
sin->sin_addr.s_addr = inet_addr(host);

if(sin->sin_addr.s_addr ==-1){
if(!(hp = gethostbyname(host))){
fprintf(stderr, "arp: %s ", host);
herror((char *)NULL);
return(-1);
        }
bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, sizeof(sin->sin_addr));
}

if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("socket() failed.");
exit(-1);
        } /* Socket is opened.*/

strcpy(req.arp_dev, "eth0");

if(ioctl(s, SIOCGARP, (caddr_t)&req) <0){
if(errno == ENXIO){
printf("%s (%s) -- no entry.\n", host, inet_ntoa(sin->sin_addr));
exit(-1);
        } else {
perror("SIOCGARP");
exit(-1);
        }
}
close(s); /* Close the socket, we don't need it anymore. */

printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));

if(req.arp_flags & ATF_COM){
printf("%s ", mac_ntoa(req.arp_ha.sa_data));
        } else {
printf("incomplete");
}

if(req.arp_flags & ATF_PERM){
printf("ATF_PERM");
        }
if(req.arp_flags & ATF_PUBL){
printf("ATF_PUBL");
        }
if(req.arp_flags & ATF_USETRAILERS){
printf("ATF_USETRAILERS");
}

printf("\n");
return(0);
}

I've looked to /usr/src/linux/net/ipv4/arp.c code before posting and can't find anything that tells me how to do it.

Thanks in advance.
Sponsored Links
    #2  
Old Unix and Linux 08-25-2010
Corona688 Corona688 is online now Forum Staff  
Mead Rotor
 
Join Date: Aug 2005
Last Activity: 5 March 2015, 2:59 PM EST
Location: Saskatchewan
Posts: 20,363
Thanks: 872
Thanked 3,567 Times in 3,332 Posts
The "-a" flag in Linux just changes the output format. I think you're thinking of the windows arp command, where the "/a" flag displays the whole table.

In any case, according to the strace command, linux ARP doesn't use ioctls to get the ARP table -- it slurps it in from the special file /proc/net/arp all in one big read. Try cat /proc/net/arp.

Last edited by Corona688; 08-25-2010 at 01:49 PM..
Sponsored Links
    #3  
Old Unix and Linux 08-25-2010
semash! semash! is offline
Registered User
 
Join Date: Aug 2009
Last Activity: 11 June 2012, 6:16 AM EDT
Posts: 47
Thanks: 0
Thanked 1 Time in 1 Post
Hey Corona688,

Again, you were right, it sounds like a fair solution.

I can use sscanf() reading /proc/net/arp and get the same results as with 'arp -an'. While i was looking for a solution, i saw a program which did it with a complex function, reading from devices called '/dev/kmem' and '/dev/vmunix'. Never understood that.

Well, thank you, man!

Last edited by semash!; 08-25-2010 at 05:16 PM..
    #4  
Old Unix and Linux 08-25-2010
Corona688 Corona688 is online now Forum Staff  
Mead Rotor
 
Join Date: Aug 2005
Last Activity: 5 March 2015, 2:59 PM EST
Location: Saskatchewan
Posts: 20,363
Thanks: 872
Thanked 3,567 Times in 3,332 Posts
Quote:
Originally Posted by semash! View Post
While i was looking for a solution, i saw a program which did it with a complex function, reading from devices called '/dev/kmem' and 'dev/vmunix'. Never understood that.
Ew, that sounds very ugly indeed. It's reading raw data directly from kernel memory...
Sponsored Links
    #5  
Old Unix and Linux 08-25-2010
semash! semash! is offline
Registered User
 
Join Date: Aug 2009
Last Activity: 11 June 2012, 6:16 AM EDT
Posts: 47
Thanks: 0
Thanked 1 Time in 1 Post
Yeah... Here's part of the function i was talking about, just for sharing and general knowledge...

Code:
struct nlist nl[] = {
#define    X_ARPTAB    0
    { "_arptab" },
#define    X_ARPTAB_SIZE    1
    { "_arptab_size" },
#define    N_SYSMAP    2
    { "_Sysmap" },
#define    N_SYSSIZE    3
    { "_Syssize" },
    { "" },
};

static struct pte *Sysmap;

/*
 * Dump the entire arp table
 */
dump(kernel, mem)
    char *kernel, *mem;
{
    extern int h_errno;
    struct arptab *at;
    struct hostent *hp;
    int bynumber, mf, arptab_size, sz;
    char *host, *malloc();
    off_t lseek();

    if (nlist(kernel, nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) {
        fprintf(stderr, "arp: %s: bad namelist\n", kernel);
        exit(1);
    }
    mf = open(mem, O_RDONLY);
    if (mf < 0) {
        fprintf(stderr, "arp: cannot open %s\n", mem);
        exit(1);
    }
    if (kflag) {
        off_t off;

        Sysmap = (struct pte *)
           malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
        if (!Sysmap) {
            fputs("arp: can't get memory for Sysmap.\n", stderr);
            exit(1);
        }
        off = nl[N_SYSMAP].n_value & ~KERNBASE;
        (void)lseek(mf, off, L_SET);
        (void)read(mf, (char *)Sysmap,
            (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
    }
    klseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, L_SET);
    read(mf, &arptab_size, sizeof arptab_size);
    if (arptab_size <= 0 || arptab_size > 1000) {
        fprintf(stderr, "arp: %s: namelist wrong\n", kernel);
        exit(1);
    }
    sz = arptab_size * sizeof (struct arptab);
    at = (struct arptab *)malloc((u_int)sz);
    if (at == NULL) {
        fputs("arp: can't get memory for arptab.\n", stderr);
        exit(1);
    }
    klseek(mf, (long)nl[X_ARPTAB].n_value, L_SET);
    if (read(mf, (char *)at, sz) != sz) {
        perror("arp: error reading arptab");
        exit(1);
    }
    close(mf);
    for (bynumber = 0; arptab_size-- > 0; at++) {
        if (at->at_iaddr.s_addr == 0 || at->at_flags == 0)
            continue;
        if (bynumber == 0)
            hp = gethostbyaddr((caddr_t)&at->at_iaddr,
                sizeof at->at_iaddr, AF_INET);
        else
            hp = 0;
        if (hp)
            host = hp->h_name;
        else {
            host = "?";
            if (h_errno == TRY_AGAIN)
                bynumber = 1;
        }
        printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr));
        if (at->at_flags & ATF_COM)
            ether_print(at->at_enaddr);
        else
            printf("(incomplete)");
        if (at->at_flags & ATF_PERM)
            printf(" permanent");
        if (at->at_flags & ATF_PUBL)
            printf(" published");
        if (at->at_flags & ATF_USETRAILERS)
            printf(" trailers");
        printf("\n");
    }
}



/*
 * Seek into the kernel for a value.
 */
klseek(fd, base, off)
    int fd, off;
    off_t base;
{
    off_t lseek();

    if (kflag) {    /* get kernel pte */
        base &= ~KERNBASE;
        base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
    }
    (void)lseek(fd, base, off);
}

Unix or Linux Image

You see? It's incomprehensible.
Sponsored Links
Closed Linux or Unix Question

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Unix or Linux Image More UNIX and Linux Forum Topics You Might Find Helpful
Thread Thread Starter Forum Replies Last Post
How to send html file in a mail not as an attachment but it should display in the mail in table for mani_isha UNIX for Dummies Questions & Answers 0 03-30-2010 04:37 AM
Display the contents of a table. gokulj Web Programming 3 10-06-2009 10:10 AM
Check the record count in table (table in oracle) kamineni Shell Programming and Scripting 1 12-29-2008 06:32 AM
Check the record count in table (table in oracle) kamineni Shell Programming and Scripting 1 12-15-2008 08:31 AM



All times are GMT -4. The time now is 04:14 PM.