linux udp发送错误,sendto()“无效参数”错误在Linux上的原始udp套接字

我试图用原始套接字发送udp数据包。对于IPv4,一切正常,但我无法突破IPv6套接字的问题,其中sendto()始终表示无效参数。最初我在考虑IPv6的强制校验和,但IPV6_CHECKSUM选项应该解决这个问题,所以我现在没有选择。sendto()“无效参数”错误在Linux上的原始udp套接字

我使用inaddr_any作为addr_from,并且使用addr_to的一些ipv6地址与同一个端口。我通过send_ip工具来源查看,它手动计算校验和并发送带有原始/原始套接字的数据包,但我希望linux根据基于策略的路由规则自动形成具有必要源地址的IP数据包。

有没有人有任何想法这个问题的根源是什么?或者使用raw/ipproto_udp套接字的任何工作示例?

在此先感谢!

PS:请忽略所有线程的东西

发送代码:

typedef struct thread_data {

char msg[BUFFER_LENGTH];

struct sockaddr_in6 addr_to;

struct sockaddr_in6 addr_from;

} thread_data;

void create_packet(const thread_data* data, void** packet, size_t* size) {

size_t msg_len = strlen(data->msg), udp_len = sizeof(struct udphdr);

struct udphdr udp = {0};

udp.source = data->addr_from.sin6_port;

udp.dest = data->addr_to.sin6_port;

udp.len = htons(udp_len + msg_len);

udp.check = 0;

*packet = malloc(udp_len + msg_len);

if(!(*packet)) {

ERROR("malloc failed");

}

memcpy(*packet, &udp, sizeof(struct udphdr));

memcpy((*packet) + udp_len, data->msg, msg_len);

*size = udp_len + msg_len;

}

void client_thread(void* args) {

thread_data* data = (thread_data*)args;

int sock = -1;

if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)) < 0) {

ERROR("failed to create socket");

}

int val = 2; //I tried to play with this value, but with no luck

if(setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val)) < 0) {

ERROR("setsockopt failed");

}

ssize_t res = sendto(sock, packet, size, 0, (struct sockaddr*)&(data->addr_to), sizeof(data->addr_to));

if (res < 0) {

ERROR("sendto failed");

}

}

2013-12-16

Alex

+0

你用什么作为你的IPv6地址'addr_from'和'addr_to'? –

+0

对于我在6addr_any和addr_to中使用的addr_from,我使用了一些可从主机访问的有效IPv6地址。 addr_to和addr_from的端口号相同。 –

+0

你使用什么作为你的IPv6地址'addr_to'? –

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UDP是一种无连的传输协议,它不保证数据包的可靠性和顺序性。而ICMP是一种网络协议,它主要用于网络故障排查、错误报告和路由器之间的通信。在使用UDP协议时,我们可以使用原始发送收ICMP消息。 在Linux系统中,我们可以使用socket()函数来创建一个原始,指定协议族为AF_INET(IPv4)或AF_INET6(IPv6),协议类型为SOCK_RAW,协议号为IPPROTO_ICMP。然后我们可以使用sendto()函数来发送UDP数据包,并使用recvfrom()函数来收ICMP消息。 以下是一个简单的示例代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #define BUFSIZE 1024 int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in addr; char buffer[BUFSIZE]; // 创建原始 sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sockfd < 0) { perror("socket"); exit(EXIT_FAILURE); } // 设置地址结构体 memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 发送UDP数据包 strcpy(buffer, "Hello, UDP!"); if (sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("sendto"); exit(EXIT_FAILURE); } // 收ICMP消息 if (recvfrom(sockfd, buffer, BUFSIZE, 0, NULL, NULL) < 0) { perror("recvfrom"); exit(EXIT_FAILURE); } struct iphdr *iph = (struct iphdr *)buffer; struct icmphdr *icmph = (struct icmphdr *)(buffer + (iph->ihl * 4)); printf("Received ICMP packet from %s\n", inet_ntoa(addr.sin_addr)); printf("Type: %d\n", icmph->type); printf("Code: %d\n", icmph->code); close(sockfd); return 0; } ``` 在上面的示例代码中,我们创建了一个原始,并指定协议为ICMP。然后我们使用sendto()函数发送了一个UDP数据包,目标地址为127.0.0.1。着,我们使用recvfrom()函数收ICMP消息,并解析出其中的类型和代码。 需要注意的是,使用原始需要具有管理员权限。此外,使用原始需要特殊的权限,因此需要小心使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值