1.server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
/* ip首部长度 */
#define IP_HEADER_LEN sizeof(struct ip)
/* tcp首部长度 */
#define TCP_HEADER_LEN sizeof(struct tcphdr)
/* ip首部 + tcp首部长度 */
#define IP_TCP_HEADER_LEN IP_HEADER_LEN + TCP_HEADER_LEN
/* 接收数据缓冲大小 */
#define BUFFER_SIZE 1024
/* ip首部 + tcp首部 + 数据缓冲区大小 */
#define IP_TCP_BUFF_SIZE IP_TCP_HEADER_LEN + BUFFER_SIZE
void err_exit(const char *err_msg)
{
perror(err_msg);
exit(1);
}
/* 原始套接字接收 */
void raw_socket_recv()
{
struct ip *ip_header;
struct tcphdr *tcp_header;
int sock_raw_fd, ret_len;
char buf[IP_TCP_BUFF_SIZE];
if ((sock_raw_fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
err_exit("socket()");
/* 接收数据 */
while (1)
{
bzero(buf, IP_TCP_BUFF_SIZE);
ret_len = recv(sock_raw_fd, buf, IP_TCP_BUFF_SIZE, 0);
if (ret_len > 0)
{
/* 取出ip首部 */
ip_header = (struct ip *)buf;
/* 取出tcp首部 */
tcp_header = (struct tcphdr *)(buf + IP_HEADER_LEN);
if (ntohs(tcp_header->th_sport) != 14692) {
printf("=======================================\n");
printf("from ip:%s\n", inet_ntoa(ip_header->ip_src));
printf("from port:%d\n", ntohs(tcp_header->th_sport));
/* 取出数据 */
printf("get data:%s\n", buf + IP_TCP_HEADER_LEN);
}
}
}
close(sock_raw_fd);
}
int main(void)
{
/* 原始套接字接收 */
raw_socket_recv();
return 0;
}
2.client(1)
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <pthread.h>
#define errorlog(msg) do{ \
printf(msg); \
exit(1); \
}while(0)
/* 缓冲大小*/
#define BUFSIZE 1024
/*版本信息*/
#define IPVERSION 4
/* 原始套接字 */
int sockfd;
/* 程序活动标志 */
/*目的端口信息*/
#define DEST_PORT 8101
/*源端口信息*/
#define SRC_PORT 5566
/*send buffer */
char sendbuf[BUFSIZE] = {0};
char Data[] = "forever love for you!!";
struct ip{
unsigned int hl:4;
unsigned int version:4;
unsigned char tos;
unsigned short total_len;
unsigned short id;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
};
struct tcphdr{
unsigned short sport;
unsigned short dport;
unsigned int seq;
unsigned int ack;
u_char th_x2:4, /* (unused) */
th_off:4;
unsigned char flag;
unsigned short win;
unsigned short sum;
unsigned short urp;
};
struct pseudohdr
{
unsigned int saddr;
unsigned int daddr;
char zero;
char protocol;
unsigned short length;
};
/* CRC16校验 */
unsigned short inline
checksum (unsigned short *buffer, unsigned short size)
{
unsigned long cksum = 0;
while(size>1){
cksum += *buffer++;
size -= sizeof(unsigned short);
}
if(size){
cksum += *(unsigned char *)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return((unsigned short )(~cksum));
}
/* 发送SYN包函数
* 填写IP头部,TCP头部
* TCP伪头部仅用于校验和的计算
*/
void
init_header(struct ip *ip, struct tcphdr *tcp, struct pseudohdr *pseudoheader,struct sockaddr_in *dest, char *src)
{
int len = sizeof(struct ip) + sizeof(struct tcphdr) + strlen(Data);
// IP头部数据初始化
ip->hl = 5;
ip->version = IPVERSION;
ip->tos = 0;
ip->total_len = htons(len);
ip->id = 0;
ip->frag_and_flags = 0;
ip->ttl = 255;
ip->proto = IPPROTO_TCP;
ip->checksum = 0;
ip->sourceIP = inet_addr(src);
ip->destIP = dest->sin_addr.s_addr;
// TCP头部数据初始化
tcp->sport = htons( SRC_PORT );
tcp->dport = htons(DEST_PORT);
// tcp->seq = htonl( rand()%90000000 + 2345 );
// tcp->ack = 0;
tcp->th_off = sizeof(struct tcphdr) / 4;
tcp->flag = 0x02;
tcp->win = 4096;
tcp->sum = 0;
// tcp->urp = 0;
// //TCP伪头部
// pseudoheader->zero = 0;
// pseudoheader->protocol = IPPROTO_TCP;
// pseudoheader->length = htons(sizeof(struct tcphdr));
// pseudoheader->daddr = dest->sin_addr.s_addr;
// pseudoheader->saddr = inet_addr(src);
//// srand((unsigned) time(NULL));
}
/*********************************************************************************************************
** 函数名称: send_data
** 功能描述:
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
API 函数
*********************************************************************************************************/
void send_data(int fd, char *client, struct sockaddr_in *server)
{
// int i = 0;
int bufsize;
int send_len = 0;
bufsize = sizeof(struct ip) + sizeof(struct tcphdr) + strlen(Data) + 1;
// for(i = 0; i < 50; i++){
memset(sendbuf, 0, sizeof(sendbuf));
struct ip *iphdr;
// iphdr = (struct ip *)malloc(sizeof(struct ip ));
struct tcphdr *tcph;
// tcph = (struct tcphdr *)malloc(sizeof(struct tcphdr));
struct pseudohdr tcpv;
iphdr = (struct ip *)sendbuf;
tcph = (struct tcphdr *)(sendbuf + 20);
init_header(iphdr, tcph, &tcpv, server, client);
// memset(sendbuf,0,BUFSIZE);
// memcpy(sendbuf,iphdr,sizeof(struct ip ));
// memcpy(sendbuf + sizeof(struct ip ), tcph, sizeof(struct tcphdr));
memcpy(sendbuf + sizeof(struct ip ) + sizeof(struct tcphdr), Data, strlen(Data) + 1);
/*伪首部校验和*/
// memcpy(sendbuf, &tcpv, sizeof(tcpv));
// memcpy(sendbuf + sizeof(tcpv), tcph, sizeof(struct tcphdr));
// memcpy(sendbuf + sizeof(tcpv) + sizeof(tcph), Data, sizeof(Data));
// tcph->sum = checksum((unsigned short *)sendbuf, sizeof(sendbuf));
send_len = sendto(fd, sendbuf, bufsize, 0, (struct sockaddr *)server, sizeof(struct sockaddr_in));
if(send_len < 0){
printf("sendto error\n");
exit(1);
}
// free(iphdr);
// free(tcph);
// sleep(1);
// }
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 主函数
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int main (int argc, char **argv)
{
int sockfd;
int flag = 1;
// int timeout=1000;
struct sockaddr_in serveraddr;
char *srcaddr;
if(argc < 3){
errorlog("argument too less\n");
}
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if(sockfd <0){
errorlog("fail to socket\n");
}
bzero(&serveraddr, sizeof(serveraddr)); /*clear serveraddr*/
/*server fill*/
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(DEST_PORT);
serveraddr.sin_addr.s_addr = inet_addr(argv[2]);
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (void *)&flag, sizeof(flag)); /*ipheader change*/
// setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));/*timeout manage*/
/*client fill*/
srcaddr = argv[1];
send_data(sockfd, srcaddr, &serveraddr);
close(sockfd);
return (0);
}
3.client(2)(转)
/**
2 * @file ip_tcp_send.c
3 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
/* ip首部长度 */
#define IP_HEADER_LEN sizeof(struct ip)
/* tcp首部长度 */
#define TCP_HEADER_LEN sizeof(struct tcphdr)
/* ip首部 + tcp首部长度 */
#define IP_TCP_HEADER_LEN IP_HEADER_LEN + TCP_HEADER_LEN
void err_exit(const char *err_msg)
{
perror(err_msg);
exit(1);
}
/* 填充ip首部 */
struct ip *fill_ip_header(const char *src_ip, const char *dst_ip, int ip_packet_len)
{
struct ip *ip_header;
ip_header = (struct ip *)malloc(IP_HEADER_LEN);
ip_header->ip_v = IPVERSION;
ip_header->ip_hl = sizeof(struct ip) / 4; /* 这里注意,ip首部长度是指占多个32位的数量,4字节=32位,所以除以4 */
ip_header->ip_tos = 0;
ip_header->ip_len = htons(ip_packet_len); /* 整个IP数据报长度,包括普通数据 */
ip_header->ip_id = 0; /* 让内核自己填充标识位 */
ip_header->ip_off = 0;
ip_header->ip_ttl = MAXTTL;
ip_header->ip_p = IPPROTO_TCP; /* ip包封装的协议类型 */
ip_header->ip_sum = 0; /* 让内核自己计算校验和 */
ip_header->ip_src.s_addr = inet_addr(src_ip); /* 源IP地址 */
ip_header->ip_dst.s_addr = inet_addr(dst_ip); /* 目标IP地址 */
return ip_header;
}
/* 填充tcp首部 */
struct tcphdr *fill_tcp_header(int src_port, int dst_port)
{
struct tcphdr *tcp_header;
tcp_header = (struct tcphdr *)malloc(TCP_HEADER_LEN);
tcp_header->th_sport = htons(src_port);
tcp_header->th_dport = htons(dst_port);
/* 同IP首部一样,这里是占32位的字节多少个 */
tcp_header->th_off = sizeof(struct tcphdr) / 4;
/* 发起连接 */
tcp_header->th_flags = TH_SYN;
tcp_header->th_win = 4096;
tcp_header->th_sum = 0;
return tcp_header;
}
/* 发送ip_tcp报文 */
void ip_tcp_send(const char *src_ip, int src_port, const char *dst_ip, int dst_port, const char *data)
{
struct ip *ip_header;
struct tcphdr *tcp_header;
struct sockaddr_in dst_addr;
socklen_t sock_addrlen = sizeof(struct sockaddr_in);
int data_len = strlen(data);
int ip_packet_len = IP_TCP_HEADER_LEN + data_len;
char buf[ip_packet_len];
int sockfd, ret_len, on = 1;
bzero(&dst_addr, sock_addrlen);
dst_addr.sin_family = PF_INET;
dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
dst_addr.sin_port = htons(dst_port);
/* 创建tcp原始套接字 */
if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
err_exit("socket()");
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1)
err_exit("setsockopt()");
ip_header = fill_ip_header(src_ip, dst_ip, ip_packet_len);
tcp_header = fill_tcp_header(src_port, dst_port);
bzero(buf, ip_packet_len);
memcpy(buf, ip_header, IP_HEADER_LEN);
memcpy(buf + IP_HEADER_LEN, tcp_header, TCP_HEADER_LEN);
memcpy(buf + IP_TCP_HEADER_LEN, data, data_len);
/* 发送报文 */
ret_len = sendto(sockfd, buf, ip_packet_len, 0, (struct sockaddr *)&dst_addr, sock_addrlen);
if (ret_len > 0)
printf("sendto() ok!!!\n");
else printf("sendto() failed\n");
close(sockfd);
free(ip_header);
free(tcp_header);
}
int main(int argc, const char *argv[])
{
if (argc != 6)
{
printf("usage:%s src_ip src_port dst_ip dst_port data\n", argv[0]);
exit(1);
}
/* 发送ip_tcp报文 */
ip_tcp_send(argv[1], atoi(argv[2]), argv[3], atoi(argv[4]), argv[5]);
return 0;
}