简体   繁体   中英

Add arp entry Linux

Read the question carefully in order to propose a solution, please

I need to add permanent arp entry in Linux somehow.

The problem is: if I add an entry via shell, or via sockets, it always gets flag 0x6 . Even if I use the code posted downhere, where I specify the flag, it remains the same, 0x6.

I found this information about 0x6 flag:

Notice the ARP flag of "0x6". The ASIC ARP entry with flag 0x6 is MAC-cache related entry. It is caused by arp lookup failure when installing the session. The session will try to use the source MAC address of incoming packet, but it is not necessary for using this mac address. We can get the MAC address when the reply packet arrives by sending an ARP packet to the source host.

So anytime I add any arp entry, then I ping the same ip address, it always results in ARP request broadcast .

The question is, is there a way how to add a permanent ARP entry with proper flag? So I add an entry, and in case of any comunication afterwards, there wont be any ARP broadcast?

Btw, to get into what I am up to: I am sending a broadcast(L3) from PC1 containing PC1's IP and MAC, PC2 gets the packet and add addresses them into ARP table and establish TCP session, but always first run ARP broadcast.

via shell:

#!/bin/sh
arp -s $1 $2 2>/dev/null

via sockets:

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);
} /* End of mac_ntoa */

int mac_aton(char *addr, unsigned char *ptr){
    int i, v[6];
    if((i = sscanf(addr, "%x:%x:%x:%x:%x:%x", &v[0], &v[1], &v[2], &v[3],
            &v[4], &v[5])) !=6){

        fprintf(stderr, "arp: invalid Ethernet address '%s'\n", addr);
        return(1);
    } /* End of If*/

    for(i = 0; i < 6; i++){
        ptr[i] = v[i];
    } /* End of For */

    return(0);
}

int main(int argc, char* argv[]){
    if(argc < 3 || argc > 4){
        fprintf(stderr,"usage: %s <ip_addr> <hw_addr> [temp|pub|perm|trail]\n",
            argv[0]);
        fprintf(stderr, "default: temp.\n");
        exit(-1);
    } /* End of If */

    int s, flags;
    char *host = argv[1];

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

    bzero((caddr_t)&req, sizeof(req)); /* caddr_t is not really needed. */

    sin = (struct sockaddr_in *)&req.arp_pa;
    sin->sin_family = AF_INET;
    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);
        } /* End of If */
        bcopy((char *)hp->h_addr,
            (char *)&sin->sin_addr, sizeof(sin->sin_addr));
    } /* End of If */

    if(mac_aton(argv[2], req.arp_ha.sa_data)){ /* If address is valid... */
        return(-1);
    }

    argc -=2;
    argv +=2;

    flags = ATF_PERM | ATF_COM;

    while(argc-- > 0){
        if(!(strncmp(argv[0], "temp", 4))){
            flags &= ~ATF_PERM;
        } else if(!(strncmp(argv[0], "pub", 3))){
            flags |= ATF_PUBL;
        } else if(!(strncmp(argv[0], "trail", 5))){
            flags |= ATF_USETRAILERS;
        } else if(!(strncmp(argv[0], "dontpub", 7))){ /* Not working yet */
            flags |= ATF_DONTPUB;
        } else if(!(strncmp(argv[0], "perm", 4))){
            flags = ATF_PERM;
        } else {
            flags &= ~ATF_PERM;
        } /* End of Else*/
    argv++;
    }/* End of While */

    req.arp_flags = flags; /* Finally, asign the flags to the structure */
    strcpy(req.arp_dev, "eth0"); /* Asign the device.  */

    if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
        perror("socket() failed.");
        exit(-1);
    } /* End of If */

    if(ioctl(s, SIOCSARP, (caddr_t)&req) <0){ /* caddr_t not really needed. */
        perror(host);
        exit(-1);
    } /* End of If */

    printf("ARP cache entry successfully added.\n");
    close(s);
    return(0);
}

0x06 flag value means the entry is complete and permanent. So I guess your shell script is good enough to add a static arp entry. Here is the relevant flag values -

#define ATF_COM 0x02        /* completed entry (ha valid)   */
#define ATF_PERM    0x04        /* permanent entry      */

The definition of flag 0x06 that you posted is not related to the linux kernel.

The reason you're seeing an arp request may be due to problems in your topology or IP addressing. Can you post those details? Or you could post the packet trace where PC2 does an arp request even when it has a static arp entry.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM