linux 原始套接字 绑定网卡,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)

{

int sockfd;

struct sockaddr_in dstaddr;

bool ret;

char*  ipAddr;

ipAddr = GetIPAddress(m_wirelessNetworkDevice);

if(!IsValidIPAddress(ipAddr.toUtf8().constData()))

return false;

if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)   //ICMP协议,原始套接字类型

{

err_sys("socket");

return false;

}

bzero(&dstaddr, sizeof(dstaddr));

dstaddr.sin_family = AF_INET;

dstaddr.sin_port = htons(0);

//printf("dest is %s\n",dest);

if (inet_pton(AF_INET, dest, &dstaddr.sin_addr) <= 0)

{

err_sys("inet_pton");

::close(sockfd);

return false;

}

ret = send_echo_req(sockfd, &dstaddr);

if (!ret)

{

::close(sockfd);

return false;

}

ret = recv_echo_reply(sockfd);

if (ret)

{

::close(sockfd);

return true;

}

else

{

::close(sockfd);

return false;

}

}

以上是Linux下的代码。0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值