青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

不會飛的鳥

2010年12月10日 ... 不鳥他們!!! 我要用自己開發(fā)的分布式文件系統(tǒng)、分布式調(diào)度系統(tǒng)、分布式檢索系統(tǒng), 做自己的搜索引擎!!!大魚有大志!!! ---楊書童

linux sock_raw原始套接字編程

sock_raw原始套接字編程可以接收到本機網(wǎng)卡上的數(shù)據(jù)幀或者數(shù)據(jù)包,對與監(jiān)聽網(wǎng)絡的流量和分析是很有作用的.一共可以有3種方式創(chuàng)建這種socket
 
1.socket(AF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)發(fā)送接收ip數(shù)據(jù)包
2.socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))發(fā)送接收以太網(wǎng)數(shù)據(jù)幀
3.socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))過時了,不要用啊
 
理解一下SOCK_RAW的原理, 比如網(wǎng)卡收到了一個 14+20+8+100+4 的udp的以太網(wǎng)數(shù)據(jù)幀.
 
首先,網(wǎng)卡對該數(shù)據(jù)幀進行硬過濾(根據(jù)網(wǎng)卡的模式不同會有不同的動作,如果設置了promisc混雜模式的話,則不做任何過濾直接交給下一層輸入例程,否則非本機mac或者廣播mac會被直接丟棄).按照上面的例子,如果成功的話,會進入ip輸入例程.但是在進入ip輸入例程之前,系統(tǒng)會檢查系統(tǒng)中是否有通過socket(AF_PACKET, SOCK_RAW, ..)創(chuàng)建的套接字.如果有的話并且協(xié)議相符,在這個例子中就是需要ETH_P_IP或者ETH_P_ALL類型.系統(tǒng)就給每個這樣的socket接收緩沖區(qū)發(fā)送一個數(shù)據(jù)幀拷貝.然后進入下一步.
 
其次,進入了ip輸入例程(ip層會對該數(shù)據(jù)包進行軟過濾,就是檢查校驗或者丟棄非本機ip或者廣播ip的數(shù)據(jù)包等,具體要參考源代碼),例子中就是如果成功的話會進入udp輸入例程.但是在交給udp輸入例程之前,系統(tǒng)會檢查系統(tǒng)中是否有通過socket(AF_INET, SOCK_RAW, ..)創(chuàng)建的套接字.如果有的話并且協(xié)議相符,在這個例子中就是需要IPPROTO_UDP類型.系統(tǒng)就給每個這樣的socket接收緩沖區(qū)發(fā)送一個數(shù)據(jù)幀拷貝.然后進入下一步.
 
最后,進入udp輸入例程 ...
 
ps:如果校驗和出錯的話,內(nèi)核會直接丟棄該數(shù)據(jù)包的.而不會拷貝給sock_raw的套接字,因為校驗和都出錯了,數(shù)據(jù)肯定有問題的包括所有信息都沒有意義了.
 
進一步分析他們的能力.
1. socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
能:該套接字可以接收協(xié)議類型為(tcp udp icmp等)發(fā)往本機的ip數(shù)據(jù)包,從上面看的就是20+8+100.
不能:不能收到非發(fā)往本地ip的數(shù)據(jù)包(ip軟過濾會丟棄這些不是發(fā)往本機ip的數(shù)據(jù)包).
不能:不能收到從本機發(fā)送出去的數(shù)據(jù)包.
發(fā)送的話需要自己組織tcp udp icmp等頭部.可以setsockopt來自己包裝ip頭部
這種套接字用來寫個ping程序比較適合
     
2. socket(PF_PACKET, SOCK_RAW, htons(x)); 
這個套接字比較強大,創(chuàng)建這種套接字可以監(jiān)聽網(wǎng)卡上的所有數(shù)據(jù)幀.從上面看就是20+20+8+100.最后一個以太網(wǎng)crc從來都不算進來的,因為內(nèi)核已經(jīng)判斷過了,對程序來說沒有任何意義了.
能: 接收發(fā)往本地mac的數(shù)據(jù)幀
能: 接收從本機發(fā)送出去的數(shù)據(jù)幀(第3個參數(shù)需要設置為ETH_P_ALL)
能: 接收非發(fā)往本地mac的數(shù)據(jù)幀(網(wǎng)卡需要設置為promisc混雜模式)
協(xié)議類型一共有四個
ETH_P_IP  0x800      只接收發(fā)往本機mac的ip類型的數(shù)據(jù)幀
ETH_P_ARP 0x806      只接受發(fā)往本機mac的arp類型的數(shù)據(jù)幀
ETH_P_ARP 0x8035     只接受發(fā)往本機mac的rarp類型的數(shù)據(jù)幀
ETH_P_ALL 0x3        接收發(fā)往本機mac的所有類型ip arp rarp的數(shù)據(jù)幀, 接收從本機發(fā)出的所有類型的數(shù)據(jù)幀.(混雜模式打開的情況下,會接收到非發(fā)往本地mac的數(shù)據(jù)幀)
 
發(fā)送的時候需要自己組織整個以太網(wǎng)數(shù)據(jù)幀.所有相關的地址使用struct sockaddr_ll 而不是struct sockaddr_in(因為協(xié)議簇是PF_PACKET不是AF_INET了),比如發(fā)送給某個機器,對方的地址需要使用struct sockaddr_ll.
 
這種socket大小通吃,強悍
下面是一段相關的代碼:
 

     ...
    int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    struct sockaddr_ll sll;
    memset( &sll, 0, sizeof(sll) );
    sll.sll_family = AF_PACKET;
    struct ifreq ifstruct;
    strcpy(ifstruct.ifr_name, "eth0");
    ioctl(sockfd, SIOCGIFINDEX, &ifstruct);
    sll.sll_ifindex = ifstruct.ifr_ifindex;
    sll.sll_protocol = htons(ETH_P_ALL);
    if(bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1 ) {
       perror("bind()");
    ...

 

int set_promisc(char *interface, int fd) {
        struct ifreq ifr;
        strcpy(ifr.ifr_name, interface);
        if(ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
                perror("iotcl()");
                return -1;
        }
        ifr.ifr_flags |= IFF_PROMISC;
        if(ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
                perror("iotcl()");
                return -1;
        }
        return 0;
}
 
int unset_promisc(char *interface, int fd) {
        struct ifreq ifr;
        strcpy(ifr.ifr_name, interface);
        if(ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
                perror("iotcl()");
                return -1;
        }
        ifr.ifr_flags &= ~IFF_PROMISC;
        if(ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
                perror("iotcl()");
                return -1;
        }
        return 0;
}

 

3. socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))這個最好不要用,反正我不用...
 
總結使用方法: 1.只想收到發(fā)往本機某種協(xié)議的ip數(shù)據(jù)包的話用第一種就足夠了
            2. 更多的詳細的內(nèi)容請使用第二種.包括ETH_P_ALL參數(shù)和混雜模式都可以使它的能力不斷的加強.
ps:很多自己的想法.虛擬機測試環(huán)境.有錯歡迎指出交流
qq:110024218
 
 
我寫的ping
 

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
 
#include "unistd.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "netinet/ip.h"
#include "netinet/ip_icmp.h"
#include "netdb.h"
#include "errno.h"
#include "arpa/inet.h"
#include "signal.h"
#include "sys/time.h"
 
extern int errno;
 
int sockfd;
struct sockaddr_in addr; //peer addr
char straddr[128]; //peer addr ip(char*)
char sendbuf[2048];
char recvbuf[2048];
int sendnum;
int recvnum;
int datalen = 30;
 
 
unsigned short my_cksum(unsigned short *data, int len) {
        int result = 0;
        for(int i=0; i<len/2; i++) {
                result += *data;
                data++;
        }
        while(result >> 16)result = (result&0xffff) + (result>>16);
        return ~result;
}
void tv_sub(struct timeval* recvtime, const struct timeval* sendtime) {
        int sec = recvtime->tv_sec - sendtime->tv_sec;
        int usec = recvtime->tv_usec - sendtime->tv_usec;
        if(usec >= 0) {
                recvtime->tv_sec = sec;
                recvtime->tv_usec = usec;
        } else {
                recvtime->tv_sec = sec-1;
                recvtime->tv_usec = -usec;
        }
}
 
void send_icmp() {
        struct icmp* icmp = (struct icmp*)sendbuf;
        icmp->icmp_type = ICMP_ECHO;
        icmp->icmp_code = 0;
        icmp->icmp_cksum = 0;
        icmp->icmp_id = getpid(); //needn't use htons() call, because peer networking kernel didn't handle this data and won't make different meanings(bigdian litteldian)
        icmp->icmp_seq = ++sendnum; //needn'
t use hotns() call too.
        gettimeofday((struct timeval*)icmp->icmp_data, NULL);
        int len = 8+datalen;
        icmp->icmp_cksum = my_cksum((unsigned short*)icmp, len);
        int retval = sendto(sockfd, sendbuf, len, 0, (struct sockaddr*)&addr, sizeof(addr));
        if(retval == -1){
                perror("sendto()");
                exit(-1);
        } else {
// printf("send icmp request to %s(%d) bytes\n", straddr, len);
        }
}
void recv_icmp() {
        struct timeval *sendtime;
        struct timeval recvtime;
 
        for(;;) {
                int n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, 0, 0);
                if(n == -1) {
                        if(errno == EINTR)continue;
                        else {
                                perror("recvfrom()");
                                exit(-1);
                        }
                } else {
                        gettimeofday(&recvtime, NULL);
                        struct ip *ip = (struct ip*)recvbuf;
                        if(ip->ip_src.s_addr != addr.sin_addr.s_addr) {
// printf("ip_src is not : %s\n", straddr);
                                continue;
                        }
                        struct icmp *icmp = (struct icmp*)(recvbuf + ((ip->ip_hl)<<2));
                        if(icmp->icmp_id != getpid()) {
// printf("icmp_id is not :%d\n", getpid());
                                continue;
                        }
                        recvnum++;
                        sendtime = (struct timeval*)icmp->icmp_data;
                        tv_sub(&recvtime, sendtime);
                        printf("imcp echo from %s(%dbytes)\tttl=%d\tseq=%d\ttime=%d.%06d s\n", straddr, n, ip->ip_ttl, icmp->icmp_seq, recvtime.tv_sec, recvtime.tv_usec);
                }
        }
}
void catch_sigalrm(int signum) {
        send_icmp();
        alarm(1);
}
void catch_sigint(int signum) {
        printf("\nPing statics:send %d packets, recv %d packets, %d%% lost...\n", sendnum, recvnum, (int)((float)(sendnum-recvnum)/sendnum)*100);
        exit(0);
}
 
int main(int argc, char **argv) {
        if(argc != 2) {
                printf("please use format: ping hostname\n");
                exit(-1);
        }
 
        sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
        if(sockfd == -1) {
                perror("socket()");
                return -1;
        }
 
/*
        int sendbufsize = 180;
        socklen_t sendbufsizelen = sizeof(sendbufsize);
        if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sendbufsize, sendbufsizelen) == -1)perror("setsockopt()");
        int recvbufsize;
        socklen_t recvbufsizelen;
        if(getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvbufsize, &recvbufsizelen) == -1)perror("getsockopt()");
*/
 
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        int retval = inet_pton(AF_INET, argv[1], &addr.sin_addr);
        if(retval == -1 || retval == 0) {
                struct hostent* host = gethostbyname(argv[1]);
                if(host == NULL) {
                        fprintf(stderr, "gethostbyname(%s):%s\n", argv[1], strerror(errno));
                        exit(-1);
                }
/*
                if(host->h_name != NULL)printf("hostent.h_name:%s\n", host->h_name);
                if(host->h_aliases != NULL && *(host->h_aliases) != NULL)printf("hostent.h_aliases:%s\n", *(host->h_aliases));
                printf("hostent.h_addrtype:%d\n", host->h_addrtype);
                printf("hostent.h_length:%d\n", host->h_length);
*/
                if(host->h_addr_list != NULL && *(host->h_addr_list) != NULL) {
                        strncpy((char*)&addr.sin_addr, *(host->h_addr_list), 4);
                        inet_ntop(AF_INET, *(host->h_addr_list), straddr, sizeof(straddr));
                }
                printf("Ping address:%s(%s)\n\n", host->h_name, straddr);
        } else {
                strcpy(straddr, argv[1]);
                printf("Ping address:%s(%s)\n\n", straddr, straddr);
        }
 
        struct sigaction sa1;
        memset(&sa1, 0, sizeof(sa1));
        sa1.sa_handler = catch_sigalrm;
        sigemptyset(&sa1.sa_mask);
        sa1.sa_flags = 0;
        if(sigaction(SIGALRM, &sa1, NULL) == -1)perror("sigaction()");
        struct sigaction sa2;
        memset(&sa2, 0, sizeof(sa2));
        sa2.sa_handler = catch_sigint;
        sigemptyset(&sa2.sa_mask);
        sa2.sa_flags = 0;
        if(sigaction(SIGINT, &sa2, NULL) == -1)perror("sigaction()");
 
        alarm(1);
        recv_icmp();
 
        return 0;
}

posted on 2011-06-27 09:16 不會飛的鳥 閱讀(697) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            午夜在线视频观看日韩17c| 欧美一区二区三区在线看| 久久综合激情| 亚洲精品一区二区三区四区高清| 亚洲国产一区二区在线| 欧美顶级艳妇交换群宴| 欧美一级久久| 欧美激情视频网站| 久久激情五月激情| 欧美另类videos死尸| 久久精品视频导航| 欧美日韩国产在线播放| 久久免费国产| 国产精品第一区| 欧美高清视频在线播放| 国产精品永久在线| 亚洲精品国精品久久99热一| 好吊色欧美一区二区三区视频| 亚洲精品国产精品乱码不99按摩| 韩国精品主播一区二区在线观看| 99这里有精品| 亚洲精品久久嫩草网站秘色 | 欧美日韩午夜在线| 久热精品在线| 国产日韩欧美在线看| 亚洲美女诱惑| 亚洲精品1区2区| 久久er99精品| 欧美在现视频| 国产精品久久久久91| 亚洲国产日韩综合一区| 伊人久久婷婷| 久久精品国内一区二区三区| 欧美在线播放一区二区| 国产精品国产亚洲精品看不卡15| 亚洲欧洲日本专区| 亚洲日韩中文字幕在线播放| 久久久国产一区二区| 久久九九免费视频| 国产午夜精品全部视频在线播放| 中文网丁香综合网| 亚洲一区视频| 国产精品久久久久久久久久久久久久 | 亚洲激情一区二区| 亚洲国产婷婷| 免费欧美电影| 亚洲大胆女人| 亚洲国产裸拍裸体视频在线观看乱了中文 | 欧美激情一二区| 激情五月婷婷综合| 久久www免费人成看片高清| 久久国产一二区| 国内在线观看一区二区三区| 欧美在线首页| 蜜臀av国产精品久久久久| 亚洲二区视频| 欧美理论在线| 亚洲一区二区三区午夜| 性色av香蕉一区二区| 国产欧美日韩一区二区三区在线| 午夜在线精品| 久久在线免费观看视频| 亚洲国产精品久久久久秋霞蜜臀 | 久久久精品国产99久久精品芒果| 国产一区导航| 老司机凹凸av亚洲导航| 亚洲国产裸拍裸体视频在线观看乱了| 亚洲欧洲在线免费| 欧美偷拍另类| 欧美亚洲一区二区在线| 男男成人高潮片免费网站| 91久久嫩草影院一区二区| 欧美日韩成人一区| 亚洲专区一二三| 免费成人av在线| 一区二区三区高清视频在线观看| 国产精品视频观看| 久久久在线视频| 日韩一级网站| 久久人人爽人人爽| 99re这里只有精品6| 国产精品欧美久久| 久久久噜噜噜久久中文字免| 亚洲精品麻豆| 久久深夜福利免费观看| 夜夜嗨av一区二区三区四区| 国产视频欧美视频| 欧美激情一区二区三区| 欧美一级一区| 亚洲免费大片| 美女国产一区| 亚洲欧美日本国产有色| 亚洲大胆美女视频| 国产精品日韩在线一区| 欧美a级片网站| 亚洲欧美久久久久一区二区三区| 欧美mv日韩mv国产网站| 亚洲欧美日韩一区在线| 亚洲人成绝费网站色www| 国产区日韩欧美| 欧美日韩免费观看一区三区| 久久精品国产免费看久久精品| 99pao成人国产永久免费视频| 久久免费精品视频| 亚洲女优在线| 99热在这里有精品免费| 黄色成人av| 国产精品尤物福利片在线观看| 欧美激情综合亚洲一二区| 久久精品亚洲| 亚洲欧美日韩综合aⅴ视频| 亚洲精品一区二区三区蜜桃久| 美女国产精品| 久久欧美中文字幕| 久久国产精品久久久久久电车| 中文av一区二区| 亚洲精品视频免费| 亚洲高清免费视频| 狠狠88综合久久久久综合网| 欧美资源在线| 亚洲影院免费| 一区二区三区日韩在线观看| 亚洲精品1区| 欧美韩日一区| 欧美成人蜜桃| 欧美v亚洲v综合ⅴ国产v| 久久综合电影一区| 久久久噜噜噜久久中文字幕色伊伊| 午夜精品亚洲| 亚洲伊人一本大道中文字幕| 这里只有精品电影| 亚洲无限av看| 亚洲欧美电影院| 亚洲欧美电影在线观看| 亚洲专区在线| 午夜精品在线| 久久aⅴ乱码一区二区三区| 亚欧成人精品| 久久精品视频导航| 老牛嫩草一区二区三区日本| 久久婷婷麻豆| 久久综合亚州| 欧美电影免费观看| 亚洲国产一区二区三区青草影视 | 亚洲电影网站| 亚洲国产精品欧美一二99| 亚洲国产欧美久久| 亚洲理论电影网| 夜夜嗨av一区二区三区中文字幕| 99精品国产在热久久下载| 在线亚洲免费视频| 亚洲欧美日韩久久精品| 久久精品国亚洲| 美玉足脚交一区二区三区图片| 欧美va亚洲va国产综合| 亚洲精品三级| 亚洲免费在线| 久久精品免费看| 久色成人在线| 欧美色视频在线| 国产精品视频一二三| 激情成人av| 日韩视频在线一区二区三区| 亚洲尤物视频网| 久久亚洲风情| 亚洲伦理精品| 西瓜成人精品人成网站| 久久综合一区| 国产精品成av人在线视午夜片| 国产一区二区三区日韩| 亚洲精品欧美专区| 西西裸体人体做爰大胆久久久| 六月天综合网| 一区二区欧美亚洲| 欧美在线视频a| 欧美看片网站| 国色天香一区二区| 国产精品99久久久久久白浆小说| 欧美在线资源| 亚洲日本乱码在线观看| 欧美一区二区三区视频| 欧美激情精品| 国内精品视频在线观看| 99综合电影在线视频| 久久久噜噜噜久久中文字幕色伊伊| 最新精品在线| 久久久久久久久久久成人| 欧美手机在线视频| 亚洲国产一二三| 欧美中文日韩| 99re66热这里只有精品3直播 | 久久久久久久精| 99视频精品全国免费| 久久偷看各类wc女厕嘘嘘偷窃| 国产精品久久久久久影院8一贰佰| 亚洲大胆在线| 久久精品91久久香蕉加勒比| 99精品视频免费| 欧美成人69av| 在线观看欧美日韩国产|