原始套接字-自定義IP首部和TCP首部

 

  1 /* =====================================================================================
  2 *
  3 *       Filename:    raw.c
  4 *    Description:    使用原始套接字發送TCP協議,並外帶本身的數據。
  5 *
  6 * ====================================================================================*/
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #include <string.h>
 10 #include <sys/socket.h>
 11 #include <netinet/in.h>
 12 #include <netinet/ip.h>
 13 #include <netinet/tcp.h>
 14 #include <arpa/inet.h>
 15 #define DATA "hello"
 16 #define PACKET_SIZE sizeof(struct iphdr) + sizeof(struct tcphdr) + sizeof(DATA)
 17 
 18 /*---------------------------------------------------------
 19  Function Name : check_sum()
 20    Descrypthon : 校驗和計算,摘自UNP源碼
 21 ------------------------------------------------------------*/
 22 unsigned short check_sum(unsigned short *addr, int len)
 23 {
 24     int nleft = len;
 25     int sum = 0;
 26     unsigned short *w = addr;
 27     short answer = 0;
 28     while (nleft > 1)
 29     {
 30         sum += *w++;
 31         nleft -=2;
 32     }
 33     if (nleft == 1)
 34     {
 35         *(unsigned char *)(&answer) = *(unsigned char *)w;
 36         sum += answer;
 37     }
 38     sum = (sum >> 16) + (sum & 0xffff);
 39     sum += (sum >> 16);
 40     answer = ~sum;
 41     return answer;
 42 }
 43 
 44 /*---------------------------------------------------------
 45  Function Name : init_socket()
 46    Descrypthon : 初始化socket,使用原始套接字
 47    parameter   : P1 一個待初始化的原始套接字,P2 待初始化的目標地址結構,P3 目標地址,P4 目標端口
 48    return      : 返回一個原始套接字,在函數體內將目標地址結構進行初始
 49 ------------------------------------------------------------*/
 50 int init_socket(int sockfd, struct sockaddr_in *target,const char *dst_addr, const char *dst_port)
 51 {
 52     const int flag = 1;
 53     //目標協議簇
 54     target->sin_family = AF_INET;
 55     //目標端口
 56     target->sin_port = htons(atoi(dst_port));
 57 
 58     //將dst_addr中的ASCII-IP地址更新到target->sin_addr結構中
 59     if (inet_aton(dst_addr, &target->sin_addr) == 0)
 60     {
 61         perror("inet_aton fail\n");
 62         exit(-1);
 63     }
 64     //初始化原始套接字
 65     if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0)
 66     {
 67         perror("error");
 68         exit(-1);
 69     }
 70     //設置套接字×××
 71     if (setsockopt(sockfd,IPPROTO_IP, IP_HDRINCL, &flag, sizeof(flag)) < 0)
 72     {
 73         perror("setsockopt fail \n");
 74         exit(-1);
 75     }
 76     return sockfd;
 77 }
 78 
 79 /*---------------------------------------------------------------
 80  Function Name : buile_iphdr()
 81    Descrypthon : 構建IP頭部數據, 源地址使用僞隨機地址
 82 -----------------------------------------------------------------*/
 83 void buile_iphdr(struct sockaddr_in *target, char *buffer)
 84 {
 85     struct iphdr *ip = (struct iphdr *)(buffer);
 86     ip->version = 4;//版本
 87     ip->ihl = 5;//首部長度 5*4 = 20
 88     ip->tos = 0;//8位服務類型
 89     ip->tot_len = htons(PACKET_SIZE);//16位總長度
 90     ip->id = 0;//16位標識符
 91     ip->frag_off = 0;//3位標誌
 92     ip->ttl = 255;//生存時間
 93     ip->protocol = IPPROTO_TCP;//協議
 94     ip->check = check_sum((unsigned short *)ip, sizeof(struct iphdr) + sizeof(DATA));//16位首部校驗和
 95     ip->saddr = random();//源ip地址
 96     ip->daddr = target->sin_addr.s_addr;//目標ip地址
 97 }
 98 
 99 /*---------------------------------------------------------------
100  Function Name : buile_tcphdr()
101    Descrypthon : 構建TCP頭部信息,並加入一些本身的數據,而後進行
102                  校驗計算。
103 -----------------------------------------------------------------*/
104 void buile_tcphdr(struct sockaddr_in *target, const char *src_port, char *buffer)
105 {
106     struct tcphdr *tcp = (struct tcphdr *)(buffer);
107     tcp->source = htons(atoi(src_port));//16位源端口號
108     tcp->dest = target->sin_port;//16位目的端口號
109     tcp->seq = random();//32位序號
110     tcp->doff = 5;//
111     tcp->syn = 1;//同步序號
112     buffer += sizeof(struct tcphdr);
113     tcp->check = check_sum((unsigned short *)tcp, sizeof(struct tcphdr) + sizeof(DATA));//16位檢驗和
114     memcpy(buffer, DATA, sizeof(DATA));//將DATA中的數據拷貝sizeof(DATA)字節到buffer所指的地址中
115 }
116 int main(int argc, const char *argv[])
117 {
118     char *buffer;
119     char *buffer_head = NULL;
120     int sockfd = 0;
121     struct sockaddr_in *target;
122     if (argc != 4)
123     {
124         printf("usage: destination addresss, destination port, source port \n");
125         exit(-1);
126     }
127     const char *dst_addr = argv[1];
128     const char *dst_port = argv[2];
129     const char *src_port = argv[3];
130 
131     target = calloc(sizeof(struct sockaddr_in),1);
132     //calloc在動態分配完內存後,自動初始化該內存空間爲零,而malloc不初始化,裏邊數據是隨機的垃圾數據。
133     buffer = calloc(PACKET_SIZE, 1);
134     buffer_head = buffer;
135 
136     //初始化套接字
137     sockfd = init_socket(sockfd, target, dst_addr, dst_port);
138     //建立IP首部
139     buile_iphdr(target, buffer);
140     buffer += sizeof(struct iphdr);//指針下移
141     //建立TCP首部
142     buile_tcphdr(target, src_port, buffer);
143     //發送
144     sendto(sockfd, buffer_head, PACKET_SIZE, 0,(struct sockaddr *)target, sizeof(struct sockaddr_in));
145 
146     //下兩行是對calloc申請的釋放
147     free(buffer_head);
148     free(target);
149     return 0;
150 }
相關文章
相關標籤/搜索