对原始套接口感兴趣还在于它是构建 端口扫描,泛洪攻击,会话拦截 等一系列网络行为的基础。
原始套接口提供普通的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;
};
//tcp header's sturcts
struct tcpheader{
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum; unsigned char tcph_reserved:4,tcph_offset:4;
unsigned int tcp_res1:4,
tcph_hlen:4,
tcph_fin:1,
tcph_syn:1,
tcph_rst:1,
tcph_psh:1,
tcph_ack:1,
tcph_urg:1,
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};
//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 tcpheader *tcp = (struct tcpheader*)(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_TCP);
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 tcpheader);
ip->iph_ident = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = 6; //tcp
ip->iph_chksum = 0;
ip->iph_sourceip = inet_addr(argv[1]);
ip->iph_destip = inet_addr(argv[3]);
tcp->tcph_srcport = htons(atoi(argv[2]));
tcp->tcph_destport = htons(atoi(argv[4]));
tcp->tcph_seqnum = htonl(1);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0;
tcp->tcph_urgptr = 0;
ip->iph_chksum = check_sum((unsigned short *)buffer,(sizeof(struct ipheader) + sizeof(struct tcpheader)));
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]));
unsigned 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;
}