rawsocket发送数据包代码
时间: 2023-07-02 14:22:27 浏览: 110
以下是一个使用 raw socket 发送数据包的示例代码,其中包括了构造 IP 和 TCP 报文、计算校验和等操作:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SRC_IP "192.168.1.100"
#define DST_IP "192.168.1.1"
#define SRC_PORT 1234
#define DST_PORT 80
#define DATA "Hello, world!"
struct pseudo_header {
uint32_t src_addr;
uint32_t dst_addr;
uint8_t zero;
uint8_t protocol;
uint16_t len;
};
uint16_t checksum(uint16_t *buf, int len) {
uint32_t sum = 0;
while (len > 1) {
sum += *buf++;
len -= 2;
}
if (len == 1) {
sum += *(uint8_t *)buf;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
int main() {
int sockfd;
struct sockaddr_in dst_addr;
char packet[4096];
struct iphdr *ip_hdr;
struct tcphdr *tcp_hdr;
struct pseudo_header phdr;
int packet_len;
// 创建 raw socket
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (sockfd < 0) {
perror("socket");
exit(1);
}
// 构造目的地址结构体
memset(&dst_addr, 0, sizeof(dst_addr));
dst_addr.sin_family = AF_INET;
dst_addr.sin_port = htons(DST_PORT);
dst_addr.sin_addr.s_addr = inet_addr(DST_IP);
// 构造 TCP 报文
tcp_hdr = (struct tcphdr *)(packet + sizeof(struct iphdr));
memset(tcp_hdr, 0, sizeof(struct tcphdr));
tcp_hdr->source = htons(SRC_PORT);
tcp_hdr->dest = htons(DST_PORT);
tcp_hdr->seq = htonl(1);
tcp_hdr->ack_seq = 0;
tcp_hdr->doff = 5;
tcp_hdr->syn = 1;
tcp_hdr->window = htons(65535);
tcp_hdr->check = 0;
// 构造 IP 报文
ip_hdr = (struct iphdr *)packet;
memset(ip_hdr, 0, sizeof(struct iphdr));
ip_hdr->version = 4;
ip_hdr->ihl = 5;
ip_hdr->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
ip_hdr->id = htons(0x1234);
ip_hdr->ttl = 255;
ip_hdr->protocol = IPPROTO_TCP;
ip_hdr->saddr = inet_addr(SRC_IP);
ip_hdr->daddr = inet_addr(DST_IP);
ip_hdr->check = 0;
// 计算 TCP 校验和
phdr.src_addr = ip_hdr->saddr;
phdr.dst_addr = ip_hdr->daddr;
phdr.zero = 0;
phdr.protocol = IPPROTO_TCP;
phdr.len = htons(sizeof(struct tcphdr));
memcpy(&packet[sizeof(struct iphdr) + sizeof(struct tcphdr)], &phdr, sizeof(struct pseudo_header));
memcpy(&packet[sizeof(struct iphdr) + sizeof(struct tcphdr) + sizeof(struct pseudo_header)], tcp_hdr, sizeof(struct tcphdr));
tcp_hdr->check = checksum((uint16_t *)&packet[sizeof(struct iphdr) + sizeof(struct tcphdr)], sizeof(struct tcphdr) + sizeof(struct pseudo_header));
// 计算 IP 校验和
ip_hdr->check = checksum((uint16_t *)ip_hdr, sizeof(struct iphdr));
// 发送数据包
packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
if (sendto(sockfd, packet, packet_len, 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)) < 0) {
perror("sendto");
exit(1);
}
close(sockfd);
return 0;
}
```
需要注意的是,在实际使用中需要根据具体的情况修改源地址、目的地址、端口号、数据等字段,同时需要根据具体的操作系统和网络环境进行调整。
阅读全文