Linux下用C++写了ping的源代码,期间遇到段错误,百思不得其解。用了几条printf测试输出,终于找到了根源所在, 原来是memcpy(packet, icmp , icmplen);的时候icmplen的值不对,照成了内存访问越界。
#include<iostream>
#include<string.h>
#include<errno.h>
#include<signal.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdio.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<netdb.h>
#include<netinet/in_systm.h>
#include<netinet/ip.h>
#include<netinet/ip_icmp.h>
#include<sys/types.h>
#define ICMPHEAD 8
#define MAXICMPLEN 200
//typedef unsigned int socklen_t;
using namespace std;
class RawSock
{
public:
int sock;
int error;
RawSock(int protocol =0);
virtual ~RawSock();
int send(const void* msg, int msglen, struct sockaddr* addr, unsigned int len);
int send(const void* msg, int msglen, char *addr);
int receive(void *buf, int buflen, sockaddr *from, socklen_t *len);
int Error() { return error; }
};
class ICMP : public RawSock
{
public:
struct icmp *packet;
int max_len;
int length;
uint16_t checksum(uint16_t *addr, int len);
ICMP();
ICMP(int len);
~ICMP();
int send_icmp(char *to, void *buf, int len);
int recv_icmp(sockaddr *from);
void setCode(int c) { packet->icmp_code =c; }
void setId(int i) { packet->icmp_id =i; }
void setSeq(int s) { packet->icmp_seq = s; }
void setType(int t) { packet->icmp_type = t; }
};
RawSock:: RawSock(int protocol )
{
sock = socket(AF_INET, SOCK_RAW, protocol);
setuid(getuid());
if( sock == -1 ) error = 1;
else error = 0;
}
RawSock:: ~RawSock()
{
close(sock);
}
int RawSock:: send(const void* msg, int msglen, struct sockaddr* to, unsigned int len)
{
if (error )
return -1;
int length = sendto(sock, msg, msglen, 0, (const struct sockaddr *)to, len);
if( length == -1)
{
error = 2;
return -1;
}
return length;
}
int RawSock:: send(const void* msg, int msglen, char *hostname)
{
sockaddr_in sin;
if(error)
return -1;
if(hostname)
{
hostent *hostnm = gethostbyname(hostname);
if( hostnm == (struct hostent *)0)
{
return -1;
}
sin.sin_addr = *((struct in_addr *)hostnm->h_addr);
}
else
return -1;
sin.sin_family = AF_INET;
return send(msg, msglen, (sockaddr *)&sin, sizeof(sin));
}
int RawSock::receive(void *buf, int buflen, sockaddr* from, socklen_t *len)
{
if(error) return -1;
while(1)
{
int length =recvfrom(sock, buf, buflen, 0, from, len);
if(length == -1)
if( error == EINTR ) continue;
else {
error = 3;
return -1;
}
return length;
}
}
/********************
* ICMP 瀹炵幇
*
*
* ********************/
ICMP::ICMP() : RawSock(IPPROTO_ICMP)
{
max_len = MAXICMPLEN;
packet = (struct icmp *)new char [max_len];
packet->icmp_code = 0;
packet->icmp_id = 0;
packet->icmp_seq = 0;
packet->icmp_type = ICMP_ECHO;
}
ICMP::ICMP(int len) : RawSock(IPPROTO_ICMP)
{
max_len = len;
packet = (struct icmp *) new char [max_len];
packet->icmp_code = 0;
packet->icmp_id = 0;
packet->icmp_seq = 0;
packet->icmp_type = ICMP_ECHO;
}
ICMP::~ICMP()
{
delete [] (char *)packet;
}