设为首页 加入收藏

TOP

Linux下使用原始套接字实现ping 功能(一)
2014-11-24 07:46:16 来源: 作者: 【 】 浏览:5
Tags: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 timeva l 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

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android与Ubuntu下的可执行文件互.. 下一篇Ubuntu 10.10 64Bit下编译Android..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C++ Lambda表达式保 (2025-12-26 05:49:45)
·C++ Lambda表达式的 (2025-12-26 05:49:42)
·深入浅出 C++ Lambda (2025-12-26 05:49:40)
·C语言指针从入门到基 (2025-12-26 05:21:36)
·【C语言指针初阶】C (2025-12-26 05:21:33)