读书人

原始套接字兑现

发布时间: 2013-02-17 10:44:46 作者: rapoo

原始套接字实现

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#ifdef WIN32#include <Winsock2.h>#include <ws2ipdef.h>#include <WS2tcpip.h>#else#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <unistd.h>#include <arpa/inet.h>#endif#ifdef WIN32#pragma comment(lib,"ws2_32.lib")#else#define SOCKET_ERROR -1typedef int BOOL;#endif#define  DEFAULT_PORT 10089typedef struct ip_head{ union {  unsigned char Version;  unsigned char HeadLen; };unsigned char ServiceType; unsigned short TotalLen; unsigned short Identifier; union {  unsigned short Flags; unsigned short FragOffset; }; unsigned char TimeToLive; unsigned char Protocol; unsigned short HeadChecksum; unsigned int SourceAddr; unsigned int DestinAddr; }IP_HEADER;/* * TCP header. * Per RFC 793, September, 1981. */typedef struct tcp_head {u_short th_sport;               /* source port */u_short th_dport;               /* destination port */unsigned int th_seq;                 /* sequence number */unsigned int th_ack;                 /* acknowledgement number */unsigned char th_lenres;u_char  th_flags;u_short th_win;                 /* window */u_short th_sum;                 /* checksum */u_short th_urp;                 /* urgent pointer */}TCP_HEADER;//tcp伪报头typedef struct psd_hdr{unsigned long saddr;unsigned long daddr;char mbz;char ptcl; //协议类型unsigned short tcpl;  //tcp长度}PSD_HEADER;typedef struct udp_head{unsigned short uh_sport;unsigned short uh_dport;unsigned short uh_len;unsigned short uh_sum;}UDP_HEADER;struct tcpiphdr{ip_head ipHead;tcp_head tcpHead;};void InitSocket(){#ifdef WIN32WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2, 2); int err = WSAStartup(wVersionRequested, &wsaData); if(err != 0){printf("windows socket DLL initiates faild\n");exit(-1);}#endif}int GetErrNo(){#ifdef WIN32return WSAGetLastError();#elsereturn errno;#endif}const char* GetErrStr(int errnum){#ifdef WIN32return "请查看msdn帮助文档或定义winerror.h";#elsereturn strerror(errnum);#endif}//设置虚拟IP地址void SetVirtualIp(int fd, const char* userIp){bool flag = true;if(setsockopt(fd,IPPROTO_IP,IP_HDRINCL,(char *) &flag,sizeof(flag))==SOCKET_ERROR){printf("windows socket DLL initiates faild\n");exit(-1);}}unsigned short CheckSum(unsigned short *buffer, int size){unsigned long cksum = 0;while(size > 0){cksum += *buffer;size -= sizeof(unsigned short );}if (size){cksum += *(unsigned short*)buffer;}cksum = (cksum >> 16) + (cksum & 0xffff);cksum += (cksum >> 16);return (unsigned short )(~cksum);}void WriteTcpPkg(const char* sourceIp, const char* destIp, unsigned int destPort,  char* szBuffer ){int iTotalSize = sizeof(ip_head) + sizeof(tcp_head);int iIpVersion = 4;int iIpSize = sizeof(ip_head)/sizeof(unsigned long);ip_head ipHead;tcp_head tcpHead;psd_hdr psdHead;ipHead.Version = (iIpVersion << 4) | iIpSize;//ipHead.ServiceType = 0;ipHead.TotalLen = htons(iTotalSize);ipHead.Identifier = 1;ipHead.FragOffset = 0;ipHead.TimeToLive = 128;ipHead.Protocol = IPPROTO_TCP;ipHead.HeadChecksum = 0;ipHead.SourceAddr =inet_addr(sourceIp);ipHead.DestinAddr = inet_addr(destIp);tcpHead.th_sport = htons(DEFAULT_PORT);tcpHead.th_dport = htons(destPort);tcpHead.th_seq = htonl(0x12345678);tcpHead.th_ack = 0;tcpHead.th_lenres = (sizeof(tcp_head)/4 << 4 | 0);tcpHead.th_flags = 2;  //标志位探测  2是syntcpHead.th_win = htons(512);tcpHead.th_urp = 0;tcpHead.th_sum = 0;psdHead.saddr = ipHead.SourceAddr;psdHead.daddr = ipHead.DestinAddr;psdHead.mbz = 0;psdHead.ptcl = IPPROTO_TCP;psdHead.tcpl = htons(sizeof(tcp_head));//计算校验和memcpy(szBuffer, &psdHead, sizeof(psdHead)); memcpy(szBuffer + sizeof(psdHead), &tcpHead, sizeof(tcpHead)); tcpHead.th_sum = CheckSum( (unsigned short*)szBuffer, sizeof(psdHead) + sizeof(tcpHead));memcpy(szBuffer, &ipHead, sizeof(ipHead));memcpy(szBuffer + sizeof(ipHead), &tcpHead, sizeof(tcpHead));memset(szBuffer + sizeof(ipHead) + sizeof(tcpHead), 0, sizeof(int)); ipHead.HeadChecksum = CheckSum((unsigned short*)szBuffer, sizeof(ipHead) + sizeof(tcpHead));memcpy(szBuffer, &ipHead, sizeof(ipHead));}void MyConnectTcp(sockaddr_in &servaddr){int fd = socket(AF_INET, SOCK_DGRAM, 0);int r = connect(fd, (struct sockaddr*)&servaddr, sizeof(servaddr));int ret = sendto(fd, "hello", 5, 0, (struct sockaddr*)&servaddr, sizeof(servaddr));struct sockaddr_in clientaddr;socklen_t size = sizeof(clientaddr);char szBuf[1024];ret = recvfrom(fd, szBuf, 1024, 0,(struct sockaddr*)&clientaddr, &size);}int main(int argc, char** argv){if(argc < 5){printf("usage : tm_client servIp servPort data userIp\n");exit(-1);}char servIp[64], userIp[64], workfId[16];int port = atoi(argv[2]);strcpy(servIp, argv[1]);strcpy(workfId, argv[3]);strcpy(userIp, argv[4]);struct sockaddr_in servaddr;InitSocket();//创建原始套接字,需要有超级用户的权限int fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);if( fd == SOCKET_ERROR){printf("%s\n", GetErrStr(GetErrNo()));printf("socket函数执行失败\n");return 1;}//Header is included with data. 报文将由自己组装,以数据的形式进行发送BOOL flag = true;if(setsockopt(fd,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR){printf("%d", GetErrNo());printf("set socket IP_HDRINCL faild\n");exit(-1);}//设置超时int nTimeOver = 1000;if(setsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&nTimeOver,sizeof(nTimeOver))==SOCKET_ERROR){printf("%d", GetErrNo());printf("set socket SO_SNDTIMEO faild\n");exit(-1);}servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr(servIp);servaddr.sin_port = htons(port);char szDataBuf[1024];memset(szDataBuf, 0, sizeof(szDataBuf));int ipsize = sizeof(ip_head), tcpsize = sizeof(tcp_head);int iTotalSize = sizeof(ip_head) + sizeof(tcp_head);WriteTcpPkg(userIp, servIp, port, szDataBuf);//此处在XP系统下会返回错误码WSAEINTR,表示通过WSACancelBlockingCall函数中断了,xp sp2及以上版本都会遇到这个问题if(sendto(fd, szDataBuf, iTotalSize, 0, (struct sockaddr*)&servaddr, sizeof(servaddr)) == SOCKET_ERROR){printf("sendto message faild, errno = %d\n", GetErrNo());exit(-1);}struct sockaddr_in cliaddr;socklen_t cliLen = sizeof(cliaddr);if( recvfrom(fd,szDataBuf, sizeof(iTotalSize), 0, (struct sockaddr*)&cliaddr, &cliLen) < 0){printf("recvfrom message faild\n");exit(-1);}#ifdef WIN32closesocket(fd);WSACleanup();#else  close(fd);#endifreturn 0;}

读书人网 >互联网

热点推荐