我在C中实现原始套接字。我有两个程序(比如服务器和客户端)。客户端正在向服务器发送信息,然后服务器正在发送ACK。客户端已发送信息,服务器已成功接收。现在服务器正在发回ACK。现在,Client已成功解析以太网头。我收到IP地址时遇到问题。
1. What should be the type of arguments of the function CreateIPHeader()?
2. How to print IP addresses in ParseIPHeader()?
3. What should be the data type of value returned by ParseIPHeader, if I want just the IP addresses?
struct iphdr *CreateIPHeader(char *src_ip,char *dst_ip)
{
struct iphdr *ip_header;
ip_header=malloc(sizeof(struct iphdr));
//OTHER FIELDS OF IP HEADER
ip_header->saddr = inet_ntoa(*((struct in_addr *)(src_ip)));
ip_header->daddr = inet_ntoa(*((struct in_addr *)(dst_ip)));
ip_header->check=ComputeChecksum((unsigned char *)ip_header,ip_header->ihl*4);
printf("\nip to be sent = %s",ip_header->saddr); //printing correct IP
printf("\nip to be rcvd = %s",ip_header->daddr);
return(ip_header);
}
char* ParseIPHeader(unsigned char *packet,int len)
{
struct iphdr *ip_header,*ret_ip;
unsigned char *out;
struct ethhdr *ethernet_header;
out=malloc(2048);
memset(out, 0, 2048);
ethernet_header=(struct ethhdr *) out;
ret_ip=(struct iphdr *) (out + sizeof(struct ethhdr));
if(ntohs(ethernet_header->h_proto)==ETH_P_IP)
{
if(len>=(sizeof(struct ethhdr)+sizeof(struct iphdr)))
{
ip_header=(struct iphdr*)(packet+sizeof(struct ethhdr));
ret_ip->saddr = ip_header->daddr;
ret_ip->daddr = ip_header->saddr;
printf("daddr SENT = %s",ret_ip->daddr); //how to print them?
printf("saddr SENT = %s",ret_ip->saddr);
}
else
printf("IP packet does not have full header\n");
}
else
{
//not an IP packet
}
return out;
}
int main()
{
unsigned char in[2048];
int len;
char *rcv_ip;
Struct iphdr *ip_header;
memset(in,0,2048);
len=recvfrom(raw,in,2048,0,(struct sockaddr *)&packet_info,&packet_info_size);
rcv_ip=ParseIPHeader(in,len); /*I want this function to return me the ip addresses which I would use in the next line.*/
ip_header =CreateIPHeader(rcv_ip+5,rcv_ip);
memset(in,0,2048);
memcpy(in+sizeof(struct ethhdr),ip_header,ip_header->ihl*4);
sendrawpacket(raw,in,pkt_len);
free(ip_header);
return 0;
}
任何帮助将不胜感激。 谢谢:)
答案 0 :(得分:0)
而不是:
printf("\nDest Addr %s \n",inet_ntoa(*((struct in_addr *)&((ip_header->daddr)))));
printf("\nSource Addr %s \n",inet_ntoa(*((struct in_addr *)&(ip_header->saddr))));
也许:
printf("\nDest Addr %s \n",inet_ntoa(ip_header->daddr));
printf("\nSource Addr %s \n",inet_ntoa(ip_header->saddr));
答案 1 :(得分:0)
如果确实printf
导致你出现了段错误而不是其他东西,那么可能是:
struct in_addr dest;
dest.s_addr = ip_header->daddr;
printf("\nDest Addr %s \n", inet_ntoa(dest));
这是因为(假设您使用的是struct iphdr *ip_header
)ip_header->daddr
类型为__u32
而inet_ntoa
需要struct in_addr
。
答案 2 :(得分:0)
有几件事情有误。
CreateIPHeader
您将inet_ntoa()
与inet_aton()
混淆。创建IP标头时,您希望使用
ip_header->saddr
inet_aton(src_ip, (struct in_addr *) &ip_header->saddr)
请注意,s_addr
中的d_addr
和struct iphdr
属于__u32
类型,而非char
数组。因此,当您进行此更改时,printf
中的CreateIPHeader
语句将会中断。
main
你的printf
工作的原因是问题#1。收到后,您拨打CreateIPHeader
来创建一个不正确的struct iphdr
(见上文),现在错误地将C字符串分配给saddr
和daddr
。之后,abc
指向此错误的标头;您的printf
神奇地工作,因为abc->saddr
和abc->daddr
实际上是 C字符串。
您只覆盖了packet_buffer的iphdr
部分(您的memcpy
声明)。您还必须更改h_dest
中的h_src
和struct ethhdr
值。
您确实无需将IP地址转换为C字符串,然后将其转换回IP地址。
此外,您还没有释放ip_header
。
一般来说,你可以这样做:
int main()
{
unsigned char in[2048];
unsigned char out[2048];
int len;
memset(in, 0, 2048);
memset(out, 0, 2048);
len = recvfrom(raw, in, 2048, 0,
(struct sockaddr *) &packet_info, &packet_info_size);
struct ethhdr *in_eth = (struct ethhdr *) in;
if (ntohs(ethernet_header->h_proto) == ETH_P_IP &&
len >= sizeof(struct ethhdr) + sizeof(struct iphdr) {
struct iphdr *in_ip = (struct iphdr*) (in + sizeof(struct ethhdr));
/* create outbound packet, starting with eth header */
struct ethhdr *out_eth = (struct ethhdr *) out;
/* ... set h_dest and h_src */
struct iphdr *out_ip = (struct iphdr *) (out + sizeof(struct ethhdr));
out_ip->saddr = in_ip->daddr;
out_ip->daddr = in_ip->saddr;
/* calculate the IPv4 checksum, packet len etc */
sendrawpacket(raw, out, pkt_len);
}
return 0;
};
不保证没有错误。刚刚在浏览器中写了它。