如何收到发往本机的UDP包,要IP完整格式,包括IP头,我用SOCK_RAW但是不行,只能收到数据,不能得到IP头,请教高手,谢谢!

解决方案 »

  1.   

    use winpcap,these are some code:typedef struct _ETH_HEADER
    {
        __u8   h_dest[6];
        __u8   h_source[6];
        __u16  h_proto;
    }ETH_HEADER;
    typedef struct _IP_HEADER
    {
    __u8            h_lenver;//4位首部长度+4位IP版本号
        __u8            tos;//8位服务类型TOS
        __u16           tot_len;//16位总长度(字节)
        __u16           id;//16位标识
        __u16           frag_off;//3位标志位
        __u8            ttl;//8位生存时间 TTL
        __u8            protocol;//8位协议 (TCP, UDP 或其他)
        __u16           check;//16位IP首部校验和
        __u32           saddr;//32位源IP地址
        __u32           daddr;//32位目的IP地址
    }IP_HEADER;
    typedef struct _TCP_HEADER
    {
        __u16           source;//16位源端口
        __u16           dest;//16位目的端口
        __u32           seq;//32位序列号
        __u32           ack_seq;//32位确认号
    __u8 th_lenres;//4位首部长度/6位保留字
    __u8 th_flag;//6位标志位
        __u16           window;//16位窗口大小
        __u16           check;//16位校验和
        __u16           urg_ptr;//16位紧急数据偏移量
    }TCP_HEADER;
    //for more details you can consult winpcap example "testApp.exe"
    char *pChar;
    struct bpf_hdr *hdr;
    char *buf=(char*)lpPacket->Buffer;//lpPacket point for packet that you receivedUINT off=0;hdr=(struct bpf_hdr *)(buf+off);
    off+=hdr->bh_hdrlen;
    pChar =(char*)(buf+off); // pChar中指向的才是报文数据。
    //////////////////////////////////////////////////////
    ETHER_PACKET   *pEthPkt = (ETHER_PACKET *) lpPacket->Buffer;
    ETH_HEADER     *pEthHdr = (ETH_HEADER *) pChar;
    IP_HEADER      *pIpHdr = (IP_HEADER *) (pChar+sizeof(ETH_HEADER));
    int             i_IPH_Size = 20;//pIpHdr->ihl * 4;
    TCP_HEADER     *pTcpHdr = (TCP_HEADER *) ((char *) pIpHdr + i_IPH_Size);
    int             i_TCPH_Size = 20;//pTcpHdr->doff * 4;
    ------------------------------------------------------------------------
    int DecodeIPHeader(WSABUF *wsabuf, unsigned int srcip, unsigned short srcport,
            unsigned int destip, unsigned short destport)
    {
        BYTE          *hdr = (BYTE *)wsabuf->buf,
                      *nexthdr = NULL;
        unsigned short shortval;
        SOCKADDR_IN    srcaddr,
                       destaddr;
        
        unsigned short ip_version,
                       ip_hdr_len,
                       ip_tos,
                       ip_total_len,
                       ip_id,
                       ip_flags,
                       ip_ttl,
                       ip_frag_offset,
                       ip_proto,
                       ip_hdr_chksum,
                       ip_src_port,
                       ip_dest_port;
        unsigned int   ip_src,
                       ip_dest;
        BOOL           bPrint = TRUE;
        ip_version = HI_WORD(*hdr);
        ip_hdr_len = LO_WORD(*hdr) * 4;
        nexthdr = (BYTE *)(wsabuf->buf + ip_hdr_len);
        hdr++;    ip_tos = *hdr;
        hdr++;    memcpy(&shortval, hdr, 2);
        ip_total_len = ntohs(shortval);
        hdr += 2;    memcpy(&shortval, hdr, 2);
        ip_id = ntohs(shortval);
        hdr += 2;    ip_flags = ((*hdr) >> 5);    memcpy(&shortval, hdr, 2);
        ip_frag_offset = ((ntohs(shortval)) & 0x1FFF);
        hdr+=2;    ip_ttl = *hdr;
        hdr++;    ip_proto = *hdr;
        hdr++;    memcpy(&shortval, hdr, 2);
        ip_hdr_chksum = ntohs(shortval);
        hdr += 2;    memcpy(&srcaddr.sin_addr.s_addr, hdr, 4);
        ip_src = ntohl(srcaddr.sin_addr.s_addr);
        hdr += 4;    memcpy(&destaddr.sin_addr.s_addr, hdr, 4);
        ip_dest = ntohl(destaddr.sin_addr.s_addr);
        hdr += 4;
        //
        // If packet is UDP, TCP, or IGMP read ahead and
        //  get the port values.
        //
        if (((ip_proto == 2) ||
             (ip_proto == 6) ||
             (ip_proto == 17)))
        {
            memcpy(&ip_src_port, nexthdr, 2);
            ip_src_port = ntohs(ip_src_port);
            memcpy(&ip_dest_port, nexthdr+2, 2);
            ip_dest_port = ntohs(ip_dest_port);//        if ((srcip == ip_src) ||
    //            (srcport == ip_src_port) ||
    //            (destip == ip_dest) ||
    //            (destport == ip_dest_port))
    //        {
    //            bPrint = TRUE;
    //        }
    //        else
    //        {
    //            bPrint = FALSE;
    //        }
    }
    if (srcip == ip_src || destip == ip_dest || srcip == 0 || destip == 0)
    {
    bPrint = TRUE;
    }
    else
    {
    bPrint = FALSE;
    }    // Print IP Hdr
        //
        if (bPrint)
        {
            printf("IP HEADER\n");
            printf("   IP Version: %-10d  |  IP Header Len: %2d bytes   |   IP TOS: %X%X (hex)\n",
                ip_version, ip_hdr_len, HI_WORD(ip_tos), LO_WORD(ip_tos));
            printf(" IP Total Len: %-05d bytes | Identification: 0x%08X | IP Flags: %X  (hex)\n",
                ip_total_len, ip_id, ip_flags);
            printf("  Frag Offset: 0x%08X  |            TTL: %-10d | Protocol: %-10s \n",
                ip_frag_offset, ip_ttl, szProto[ip_proto]);
            printf(" Hdr Checksum: 0x%08X\n", ip_hdr_chksum);
            printf("     Src Addr: %-15s\n", inet_ntoa(srcaddr.sin_addr));
            printf("    Dest Addr: %-15s\n", inet_ntoa(destaddr.sin_addr));
        }
        else
            return ip_hdr_len; if (!bPrint)
    return ip_hdr_len;    switch (ip_proto)
        {
            case 2:        // IGMP
                DecodeIGMPHeader(wsabuf, ip_hdr_len);
                break;
            case 6:        // TCP
                DecodeTCPHeader(wsabuf, ip_hdr_len);
                break;
            case 17:       // UDP
                DecodeUDPHeader(wsabuf, ip_hdr_len);
                break;
            default:
                printf("   No decoder installed for protocol\n");
                break;
        }
        printf("\n");    return ip_hdr_len;
    }
      

  2.   

    谢谢 JennyVenus(),但我不要解码的程序,需要
    不用WINPCAP,直接用RAW_SOCK的话如何得到UDP的包
      

  3.   

    You need to call bind in your receiving
    application, just like a normal UDP application.there is some code:
    Sender code:
    //
    #include <winsock2.h>
    #include <stdlib.h>
    #include <stdio.h>
    int main(int argc, char* argv[])
    {
        WSADATA wsa;
        int sock;
        struct sockaddr_in sockaddress;
        struct sockaddr_in toaddress;    if ( WSAStartup(  MAKEWORD( 2, 2 ), &wsa ) != 0 )
        {
            printf("WSAStartup() failed\n");
            return -1;
        }    sock = socket( AF_INET, SOCK_DGRAM, 0 );
        sockaddress.sin_family = AF_INET;
        sockaddress.sin_port = htons(6000);
        sockaddress.sin_addr.s_addr = inet_addr("192.168.1.21"); // local ip    if ( bind( sock, (struct sockaddr*)&sockaddress, sizeof(sockaddress) )
    == -1 )
        {
            printf("bind() failed\n");
            return -1;
        }    toaddress.sin_family = AF_INET;
        toaddress.sin_port = htons(7000);
        toaddress.sin_addr.s_addr = inet_addr("192.168.1.23"); // remote ip    for(;;)
        {
            sendto(
                sock,
                "Test",
                4,
                0,
                (struct sockaddr*)&toaddress,
                sizeof(toaddress) );
            Sleep(500);
        } return 0;
    }Receiver code:#include <winsock2.h>
    #include <ws2tcpip.h>
    #include <mstcpip.h>
    #include <stdlib.h>
    #include <stdio.h>
    int main(int argc, char* argv[])
    {
        int sock = -1;
        int sockOption;
        DWORD dwBytesReturned;
        struct sockaddr_in sockAddress;
        WSADATA wsa;    if ( WSAStartup( MAKEWORD( 2, 2 ), &wsa ) != 0 )
        {
            printf("WSAStartup() failed\n");
            return -1;
        }    sock = socket( AF_INET , SOCK_RAW,  0 ) ;
        if ( sock <= 0 )
        {
            printf("socket() failed\n");
            return -1;
        }    sockOption = 1000;
        if ( setsockopt(
                sock,
                SOL_SOCKET,
                SO_RCVTIMEO,
                (const char *)&sockOption,
                sizeof(sockOption) ) == -1 )
        {
            printf("SO_RCVTIMEO failed\n");
            closesocket( sock );
            return -1;
        }    sockOption = 1;
        if ( setsockopt(
                sock,
                IPPROTO_IP,
                IP_HDRINCL,
                (const char *)&sockOption,
                sizeof(sockOption) ) == -1 )
            return false;    sockAddress.sin_family = AF_INET;
        sockAddress.sin_port = htons(0);
        sockAddress.sin_addr.s_addr = inet_addr("192.168.1.23"); // local ip
        if (bind( sock, (const struct sockaddr*)&sockAddress,
    sizeof(sockAddress)) == -1)
        {
            printf("bind() failed\n");
            closesocket( sock );
            return -1;
        }    sockOption = RCVALL_ON;
        if( WSAIoctl(
                sock,
                SIO_RCVALL,
                &sockOption,
                sizeof(sockOption),
                NULL,
                0,
                &dwBytesReturned,
                NULL,
                NULL ) == SOCKET_ERROR )
        {
            printf("SIO_RECVALL failed = %d\n", WSAGetLastError() );
            closesocket( sock ) ;
            return -1;
        }    printf( "Waiting for packets...\n" );
        for(;;)
        {
            char buffer[64000];
            int recvd;
            recvd = recvfrom( sock, buffer, sizeof(buffer), 0, NULL, NULL );
            printf( "Packet recvd: %d bytes (err=%d)\n", recvd,
    WSAGetLastError() );
        }    closesocket( sock );    WSACleanup();    return 0;
    }