Can anybody correct this code that is used to get/set ARP entries and uses ioctl( )

Can anybody correct this code that is used to get/set ARP entries and uses ioctl( )

Post by jeniffe » Wed, 26 Apr 2006 10:31:52



This is a C program compiled on gcc compiler that tries to set a new
entry in the arp cache,get an entry and also delete an entry from it.I
have run this program but in the set function Set_Entry function a call

to ether_aton(a, n) is made but the value of sa_data is not being
updated.This is why I think tht i am getting the error of invalid
argument in ioctl func..Plzz help me out.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <netinet/if_ether.h>
#include <sys/ioctl.h>

#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h>
#else
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#endif

int main()
        {
        int i=Set_Entry();

        return 0;
        }

/*
void Del_Entry()
        {
int sd;

  struct arpreq      arpreq;
  struct sockaddr_in *sin;
  struct in_addr     ina;
  char   ip[] = "172.26.29.98";
  unsigned char hw_addr[]="0:a:f4:36:12:e1";

  int rc;

  sd = socket(AF_INET, SOCK_DGRAM, 0);
  if (sd < 0)
  {
    perror("socket() error\n");
    exit(1);
  }

  sin = (struct sockaddr_in *) &arpreq.arp_pa;
  memset(sin, 0, sizeof(struct sockaddr_in));
  sin->sin_family = AF_INET;
  ina.s_addr = inet_addr(ip);
  memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr));

  strcpy(arpreq.arp_dev, "eth0");
/*
  sin_h = (struct sockaddr_in *) &arpreq.arp_ha;
  memset(sin_h, 0, sizeof(struct sockaddr_in));
  sin_h->sin_family =AF_INET;
  ina_h.s_addr = inet_addr(ip);
  memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr));*/
 //arpreq.arp_flags=ATF_PERM;

//arpreq.arp_ha.sa_family=AF_INET;

  /*rc = ioctl(sd, SIOCSARP, &arpreq);

if (rc < 0)
  {
    perror("Entry not available in cache...\n");
  }
else
        {
        printf("\nentry has been successfully retreiveed");
  hw_addr = (unsigned char *) arpreq.arp_ha.sa_data;
  printf("HWAddr found : %x:%x:%x:%x:%x:%x\n", hw_addr[0],
       hw_addr[1], hw_addr[2], hw_addr[3], hw_addr[4], hw_addr[5]);
        }

        }

*/

int Set_Entry()
{
  int sd;
  struct arpreq      arpreq;
  struct sockaddr_in *sin;
  struct in_addr     ina;
  char   ip[] = "172.26.28.77";
  char eaddr[]="0:14:22:42:48:e6";//00-14-22-42-48-E6
  int rc;
  u_char *ea;
  sd = socket(AF_INET,SOCK_DGRAM,0);
  if (sd < 0)
  {
    perror("socket() error\n");
    exit(1);
  }
  sin = (struct sockaddr_in *) &arpreq.arp_pa;
  memset(sin, 0, sizeof(struct sockaddr_in));
  sin->sin_family=AF_INET;
  ina.s_addr = inet_addr(ip);
  memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr));
  ea =(char*)arpreq.arp_ha.sa_data;
 if(ether_aton(eaddr, ea))
        {
        printf("\nreturning 1");
        return (1);
        }
 printf("ea = %s",ea);

 arpreq.arp_flags=ATF_PERM;
 strcpy(arpreq.arp_dev, "eth0");

printf("sa_data = %s",arpreq.arp_ha.sa_data);

 rc = ioctl(sd, SIOCSARP, &arpreq);
  if (rc < 0)
  {
    perror("Entry not set...\n");
  }
else
    {
    printf("\nentry has been successfully set");
     }
return 0;
 }

int Get_Entry()
        {
int sd;

  struct arpreq      arpreq;
  struct sockaddr_in *sin;
  struct in_addr     ina;
  char   ip[] = "172.26.28.77";
  unsigned char      *hw_addr;

  int rc;

  sd = socket(AF_INET, SOCK_DGRAM, 0);
  if (sd < 0)
  {
    perror("socket() error\n");
    exit(1);
  }

  /* Try to find an entry in arp cache for the ip address specified */

  printf("Find arp entry for IP : %s\n", ip);

  sin = (struct sockaddr_in *) &arpreq.arp_pa;
  memset(sin, 0, sizeof(struct sockaddr_in));
  sin->sin_family = AF_INET;
  ina.s_addr = inet_addr(ip);
  memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr));

  strcpy(arpreq.arp_dev, "eth0");
  arpreq.arp_ha.sa_family = AF_UNSPEC;

  rc = ioctl(sd, SIOCGARP, &arpreq);

  if (rc < 0)
  {
    perror("Entry not available in cache...\n");
  }
else
        {
        printf("\nentry has been successfully retreived");
  hw_addr = (unsigned char *) arpreq.arp_ha.sa_data;
  printf("HWAddr found : %x:%x:%x:%x:%x:%x\n", hw_addr[0], hw_addr[1],
hw_addr[2], hw_addr[3], hw_addr[4], hw_addr[5]);
        }

return 0;

Quote:}

ether_aton(a, n)
        char *a;
        char *n;
{
        int i, o[6];

        i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
                                           &o[3], &o[4], &o[5]);

        printf("\n i=%d\n",i);

        printf("%x %x %x %x %x %x",o[0],o[1],o[2],o[3],o[4],o[5]);

        if (i != 6) {
                perror("arp: invalid Ethernet address");
                return (1);
                }
         for (i=0; i<6; i++)
                n[i]=o[i];
        printf("\n");
        for(i=0;i<6;i++)
                printf("%x ",n[i]);
        printf("\n");
        return (0);
             }

 
 
 

Can anybody correct this code that is used to get/set ARP entries and uses ioctl( )

Post by Floyd L. Davids » Wed, 26 Apr 2006 16:07:40



>This is a C program compiled on gcc compiler that tries to set a new
>entry in the arp cache,get an entry and also delete an entry from it.I
>have run this program but in the set function Set_Entry function a call

Your code is just loaded with problems.  It does not use the
facilities of ANSI/ISO Standard C, which suggests it dates back
prior to perhaps 1990 or so.

Instead of using the example you are, look up the code for /arp/
from any current Linux distribution.  You can, for example,
download net-tools-1.60.tar.bz2 from ftp.oss.cc.gatech.edu.
You'll find it on that server at,

 /pub/linux/distributions/slackware/slackware-10.2/source/n/tcpip/net-tools-1.60.tar.bz2

And turn your compiler warnings up as high as you can.  The
least you would want is a command line like this:

   gcc -W -Wall -O2 -o foo foo.c

There are actually several other warnings that can also be enabled
most of the time.  The point is to let the compiler help you write
better code.  For example, I test short programs with a "generic"
Makefile that uses this command to compile:

   gcc -ggdb  -O2 -std=c99 -pedantic -Wall -W -Wcast-align \
       -Wcast-qual  -Wmissing-prototypes -Wshadow \
       -Wnested-externs -Wstrict-prototypes -Waggregate-return \
       -Wpointer-arith   -c foo.c

--
Floyd L. Davidson            <http://www.apaflo.com/floyd_davidson>


 
 
 

1. code example for set a ARP entry (error, )

I try to write some code to set an ARP entry.

but the code at ioctl. alert a error: invalid argument.

WHY???

int setMac(char *dev, unsigned long ip, unsigned char *mac)
{
    struct sockaddr addr;
    struct sockaddr hw_addr;
    struct arpreq req;
    int sockfd, i;

    /* default Mac to zero, in case we return an error */
    memset(mac, '\0', 6);

    memset(&addr, '\0', sizeof(addr));
    addr.sa_family = AF_INET;
    memcpy(&addr.sa_data[2], &ip, 4);

    memset(&hw_addr, '\0', sizeof(hw_addr));
    /*hw_addr.sa_family = ARPHRD_ETHER;*/
    memcpy(hw_addr.sa_data, mac, 6);

    memset(&req, '\0', sizeof(req));
    memcpy(&req.arp_pa, &addr, sizeof(addr));
    memcpy(&req.arp_dev[0], dev, sizeof(req.arp_dev));
    memcpy(&req.arp_ha, &hw_addr, sizeof(hw_addr));

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("socket\n");
        return (-1);
    }

    /* try to get an ARP mapping (if available)*/
    if (ioctl(sockfd, SIOCSARP, (char *) &req) < 0)
    {
        printf("ioctl error:%s\n", strerror(errno));
        close(sockfd);
        return (-1);
    }

    close(sockfd);
    return 0;

2. Is anyone using wmppp?

3. Anybody has used ioctl

4. Heisenberg Uncertainty and PPP

5. Does anybody know correct syntax for using ~%put in shell script

6. An Ethernet Driver ???

7. use ioctl() to get arp entry

8. Lombard ethernet apparently works

9. Getting hme parameters using ioctl (not ndd)

10. Using ATAPI 6 "SET MAX EXT" Command and HDIO_DRIVE_CMD ioctl

11. Why I am getting error using sendto

12. I can not get ARP to work, even though /proc/net/arp is correct!

13. How to set From, using a script, using formmail?