这是 Linux 套接字中的一个错误吗?在 RAW udp 套接字中接收额外的 IP 标头

问题描述 投票:0回答:2

我用UDP协议创建了一个RAW套接字,发送了一个由UDP标头和数据组成的数据包,PP中一切正常,数据包是正确的。

我还在另一个程序中创建了相同的套接字,它接受了我发送的数据,但也接受了 IP 标头。为何如此?为什么没有写到任何地方?

也就是说,我们发送DATA+UDP,并从同一个套接字接收DATA+UDP+IP。

第二个接收数据的程序只有在指针上加20(即IP头的大小)才能工作。

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <linux/udp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <sys/types.h>
#include <sys/socket.h>
#define __USE_XOPEN2K
#include <netdb.h>

#define AF_INETv4 0x02
#define AF_INETv6 0x0A

int main(int argc, char **argv)
{
    int m_socket = socket(AF_INETv4, SOCK_RAW, IPPROTO_UDP);

    struct sockaddr_in bnd;
    bnd.sin_family = AF_INET;
    bnd.sin_port = htons(55555);
    bnd.sin_addr.s_addr = inet_addr("127.0.0.1");

    bind(m_socket, &bnd, sizeof(bnd));
    perror("bind: ");

    struct iovec iov;

    char buffer[1500 - 14 - 20] = {0};
    iov.iov_base = &buffer;
    iov.iov_len  = sizeof(buffer);
    struct udphdr *udp = iov.iov_base;
    udp->source = htons(55555);
    udp->dest   = htons(22222);
    udp->len    = htons(8);
    udp->check = 0;

    struct  msghdr  msg = {0};

    msg.msg_flags = 0;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    struct sockaddr_in in;
    in.sin_family = AF_INETv4;
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    in.sin_port = htons(22222);

    msg.msg_name = &in;
    msg.msg_namelen = sizeof(struct sockaddr_in);

    for(int i = 0; i < 10; i++)
    {
        sendmsg(m_socket, &msg, 0);
        perror("");
    }

    return 0;
}
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <linux/udp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <sys/types.h>
#include <sys/socket.h>
#define __USE_XOPEN2K
#include <netdb.h>

#define AF_INETv4 0x02
#define AF_INETv6 0x0A

int main(int argc, char **argv)
{
    int m_socket = socket(AF_INETv4, SOCK_RAW, IPPROTO_UDP);

    struct sockaddr_in bnd;
    bnd.sin_family = AF_INET;
    bnd.sin_port = htons(22222);
    bnd.sin_addr.s_addr = inet_addr("127.0.0.1");

    bind(m_socket, &bnd, sizeof(bnd));
    perror("bind: ");

    struct iovec iov;

    char buffer[1500 - 14 - 20] = {0};
    iov.iov_base = &buffer;
    iov.iov_len  = sizeof(buffer);

    struct  msghdr  msg = {0};

    msg.msg_flags = 0;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    struct sockaddr_in in;
    in.sin_family = AF_INETv4;
    in.sin_addr.s_addr = 0;
    in.sin_port = 0;

    msg.msg_name = &in;
    msg.msg_namelen = sizeof(struct sockaddr_in);

    for(int i = 0; i < 10; i++)
    {
        recvmsg(m_socket, &msg, MSG_ZEROCOPY);
        perror("");

        struct udphdr *udp = (uint8_t*)iov.iov_base + 20;
        uint16_t src = htons(udp->source );
        uint16_t dst = htons(udp->dest);
        uint16_t len = htons(udp->len);
        uint16_t chk = htons(udp->check);

        fprintf(stderr, "src: %hu dst: %hu len: %hu chk: %hu\n", src, dst, len, chk);
    }

    return 0;
}
c linux sockets
2个回答
2
投票

您正在发送您自己构建的额外标头。 如果您的套接字是 AF_INETv4,则无需编写 IP 标头。 这让操作系统知道它是一个 IP 套接字,并为您添加标头。


-5
投票

这篇文章解释了一切https://habr.com/ru/articles/183316/

© www.soinside.com 2019 - 2024. All rights reserved.