Subject: Re: Gratuitous ARP request or reply.

From: "Alexandre CASSEN" <[email-masked]>
Date: Tue, 26 Feb 2002 18:12:04 +0100

Hi Harish,

>I have a question reguarding IPv4 VRRP RFC.
>
>As per the RFC, whenever VRRP virtual router becomes
>master, it shall broadcast a gratuitous *ARP request*
>containing virtual router MAC address for each IP address
>associated with the virtual router.
>
>Is this a ARP request or ARP reply, or in other words, what
>is the operation type in ARP header? Is it ARP_REQUEST = 1
>or ARP_REPLY = 2

as an example :

/*
 * send a gratuitous ARP packet
 *
 * Arg 1: vsrv = the VRRP storing struct
 * Arg 2: addr = IP Address to use in the gratuitous ARP packet
 */
static int send_gratuitous_arp(vrrp_rt *vsrv, uint32_t addr)
{
  struct m_arphdr {
    unsigned short int ar_hrd;          /* Format of hardware address.  */
    unsigned short int ar_pro;          /* Format of protocol address.  */
    unsigned char ar_hln;               /* Length of hardware address.  */
    unsigned char ar_pln;               /* Length of protocol address.  */
    unsigned short int ar_op;           /* ARP opcode (command).  */
    /* Ethernet looks like this : This bit is variable sized however...  */
    unsigned char __ar_sha[ETH_ALEN];   /* Sender hardware address.  */
    unsigned char __ar_sip[4];          /* Sender IP address.  */
    unsigned char __ar_tha[ETH_ALEN];   /* Target hardware address.  */
    unsigned char __ar_tip[4];          /* Target IP address.  */
  };

  char buf[sizeof(struct m_arphdr) + ETHER_HDR_LEN];
  char buflen = sizeof(struct m_arphdr) + ETHER_HDR_LEN;
  struct ether_header *eth = (struct ether_header *)buf;
  struct m_arphdr *arph = (struct m_arphdr *)(buf + vrrp_dlt_len(vsrv));
  char  *hwaddr = vsrv->vif->hwaddr;
  int  hwlen = ETH_ALEN;

  /* hardcoded for ethernet */
  memset(eth->ether_dhost, 0xFF, ETH_ALEN);
  memcpy(eth->ether_shost, hwaddr, hwlen);
  eth->ether_type = htons(ETHERTYPE_ARP);

  /* build the arp payload */
  memset(arph, 0, sizeof(*arph));
  arph->ar_hrd = htons(ARPHRD_ETHER);
  arph->ar_pro = htons(ETHERTYPE_IP);
  arph->ar_hln = 6;
  arph->ar_pln = 4;
  arph->ar_op  = htons(ARPOP_REQUEST);
  memcpy(arph->__ar_sha, hwaddr, hwlen);
  addr = htonl(addr);
  memcpy(arph->__ar_sip, &addr, sizeof(addr));
  memcpy(arph->__ar_tip, &addr, sizeof(addr));
  return vrrp_send_pkt(vsrv, buf, buflen);
}

Hope it will help,
Alexandre