Linux下使用原始套接字实现ping 功能

//获得某个网卡的IP地址

char*   GetIpAddress(const char* interfaceName)

{

register int fd, intrface;
  struct ifreq buf[MAXINTERFACES];   //#define MAXINTERFACES    12
  struct ifconf ifc;
  if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0)
  {
    ifc.ifc_len = sizeof buf;
    ifc.ifc_buf = (caddr_t) buf;
    if (!ioctl (fd, SIOCGIFCONF, (char *) &ifc))
    {
      intrface = ifc.ifc_len / sizeof (struct ifreq);
      while (intrface-- > 0)
      {
        if (0 != strcmp(buf[intrface].ifr_name, interfaceName))
          continue;   

//get the ip address of this net device
        if (!(ioctl (fd, SIOCGIFADDR, (char *) &buf[intrface])))
        {
          ::close(fd);
          return (inet_ntoa(((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr));
        }
        else
        {
          char str[256];
          sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name);
          perror (str);
        }
      }
    }

::close(fd);
  }
return "";

}

bool   IsValidIpAddress(const char* ipAddress)

{

struct sockaddr_in sin;

sin.sin_family = AF_INET;
  memset(&sin, 0, sizeof(sin));
  if (inet_pton(AF_INET, ipAddress, &sin.sin_addr) <= 0)
  {
    return false;
  }
  else
  {
    char strConvertedIP[MAX_IP_LENGTH];    //#define MAX_IP_LENGTH     30
    if (NULL != inet_ntop(AF_INET, &sin.sin_addr, strConvertedIP, MAX_IP_LENGTH) )
    {
      
      if(0 != strcmp(strConvertedIP, "0.0.0.0"))
      {
        return true;
      }
    }
    return false;
  }

}

bool    send_echo_req(int sock_fd,struct sockaddr_in *dstaddr)

{

char buf[100];
  size_t len = sizeof(struct icmp);
  struct icmp *icmp;
  socklen_t dstlen = sizeof(struct sockaddr_in);

bzero(buf, sizeof(buf));
  icmp = (struct icmp *)buf;
  icmp->icmp_type = ICMP_ECHO;
  icmp->icmp_code = 0;
  icmp->icmp_id = getpid();
  icmp->icmp_seq = 1;
  icmp->icmp_cksum = in_cksum((uint16_t *) icmp, sizeof(struct icmp));

if (sendto(sockfd, buf, len, 0, (struct sockaddr*)dstaddr, dstlen) == -1)
  {
    err_sys("sendto");
    return false;
  }
  return true;
}

bool     recv_echo_reply(int sock_fd)

{

char buf[100];
  ssize_t n;
  struct ip *ip;
  struct icmp *icmp;
 
  fd_set rfds;
  struct timeval tv;
  int retval;

FD_ZERO(&rfds);
  FD_SET(sockfd, &rfds);

tv.tv_sec = 5;
  tv.tv_usec = 0;

retval = select(sockfd+1, &rfds, NULL, NULL, &tv);

if (retval == -1)
  {
    perror("select()");
    return false;
  }
  else if (retval)
  {
    /* FD_ISSET(0, &rfds) will be true. */
    if ((n = read(sockfd, buf, sizeof(buf))) == -1)
    {
      err_sys("read");
      return false;
    }
    ip = (struct ip *)buf;
    if (ip->ip_p != IPPROTO_ICMP) {
      fprintf(stderr, "protocol error.\r\n");
      return false;
    }
    icmp = (struct icmp *)(buf + sizeof(struct ip));
    if (icmp->icmp_type == ICMP_ECHOREPLY) {
      if (icmp->icmp_id != getpid()) {
        fprintf(stderr, "not this process.\r\n");
        return false;
      } else {
        //printf("destination host is alive.\r\n");
        return true;
      }
    }
  }
  //printf("ping timeout.\n");
  return false;

}

uint16_t   in_cksum(uint16_t*  addr, int len)

{

int nleft = len;
  uint32_t sum = 0;
  uint16_t *w = addr;
  uint16_t answer = 0;

while (nleft > 1) {
    sum += *w++;
    nleft -= 2;
  }

if (nleft == 1) {
    *(unsigned char *)(&answer) = *(unsigned char *)w ;
    sum += answer;
  }

sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return(answer);

}

bool    Ping (char* dest)

{

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwswpd.html