对原始套接口感兴趣还在于它是构建 端口扫描,泛洪攻击,会话拦截 等一系列网络行为的基础。
原始套接口提供普通的TCP和UDP套接口不提供的以下3个能力:
1.进程 可以读与写ICMP,IGMP等分组。
2.进程可以读与写内核不处理其协议字段的IPv4数据报。
3.进程可以使用IP_HDRINCL 套接口选项自行构造IPv4头部。
下面的简单的tcp row socket 实现,在centos 4 中编译通过
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#define PCKT_LEN 8192
//can create separate header file
//ip header's structs
struct ipheader{
unsigned char iph_ihl:5,iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flag;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
//udp header's structure
struct udpheader{
unsigned short int udph_srcport;
unsigned short int udph_destport;
unsigned short int udph_len;
unsigned short int udph_chksum;
};
//check sum function
unsigned short check_sum(unsigned short *buf,int nwords){
unsigned long sum;
for(sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >>16);
return (unsigned short)(~sum);
}
int main(int argc,char *argv[]) {
int sockfd;
char buffer[PCKT_LEN];
struct ipheader *ip = (struct ipheader *)buffer;
struct udpheader *udp = (struct udpheader *)(buffer+sizeof(struct ipheader));
struct sockaddr_in sin,din;
int one = 1;
const int *val = &one;
memset(buffer,0,PCKT_LEN);
if(argc != 5){
printf("- Invalid parameters!!!/n");
printf("- Usage %s <source hostname/ip><source port> <target hostname/ip><target port>/n",argv[0]);
exit(-1);
}
sockfd = socket(PF_INET,SOCK_RAW,IPPROTO_UDP);
if(sockfd < 0) {
perror("socket() error");
exit(-1);
} else
printf("socket() - Using sock_raw socket and udp protocol is OK./n");
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
sin.sin_addr.s_addr = inet_addr(argv[1]);
sin.sin_addr.s_addr = inet_addr(argv[3]);
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader);
ip->iph_ident = htons(54321);
ip->iph_ttl = 64;
ip->iph_protocol = 17; //udp
ip->iph_sourceip = inet_addr(argv[1]);
ip->iph_destip = inet_addr(argv[3]);
udp->udph_srcport = htons(atoi(argv[2]));
udp->udph_destport = htons(atoi(argv[4]));
udp->udph_len = htons(sizeof(struct udpheader));
ip->iph_chksum = check_sum((unsigned short *)buffer,sizeof(struct ipheader) + sizeof(struct udpheader));
if(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one)) < 0) {
perror("setsockopt() error");
exit(-1);
} else
printf("setsockopt() is ok./n");
printf("Trying ..../n");
printf("Using raw socket and udp protocol/n");
printf("Using source ip: %s port: %u,Target ip: %s port: %u./n",argv[1],atoi(argv[2]),argv[3],atoi(argv[4]));
int count;
for(count = 1;count <= 20; count++){
if(sendto(sockfd,buffer,ip->iph_len,0,(struct sockaddr *)&sin,sizeof(sin)) < 0) {
perror("sendto() error");
exit(-1);
} else {
printf("Count #%u - sendto() is OK./n",count);
sleep(2);
}
}
close(sockfd);
return 0;
}