gpt4 book ai didi

c - 启动时端口错误(recvfrom)

转载 作者:太空宇宙 更新时间:2023-11-04 11:05:08 27 4
gpt4 key购买 nike

我在编写小型 DNS 服务器并将其 strip 化到最低限度时偶然发现了一个奇怪的行为。该程序应在 127.0.0.1:1337 上监听 DNS 查询并以拒绝回复。我通过发出 dig @localhost -p 1337 foo.bar. 来测试它的行为如果第48行被注释掉//char bout[bufferSize]; // <-- WTF它就像魅力一样。

程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

static int SOCKET;


void bindSocket(){
int s = socket (AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
fprintf (stderr, "Could not create socket\n");
exit (EXIT_FAILURE);
}

struct sockaddr_in address;
memset((char *)&address, 0, sizeof(address));

inet_aton("127.0.0.1", &address.sin_addr);
address.sin_family = AF_INET;
address.sin_port = htons(1337);

int rc = bind ( s, (struct sockaddr *) &address, sizeof (address) );
if (rc < 0) {
fprintf (stderr, "Could not bind Socket\n %s \n", strerror(errno));
exit (EXIT_FAILURE);
}
SOCKET = s;
}

void decline(uint16_t err, char *bin, struct sockaddr *to){
char bout[12];
memset((bout + 4), 0, 8);
memcpy(bout, bin, 4);
bout[2] = (bout[2] | 0x80) & 0xFE;
bout[3] = (bout[3] | err ) & 0x7F;
sendto( SOCKET, bout, 12, 0, to, sizeof(struct sockaddr) );
}

void hereBeDragons(){
size_t bufferSize = 512;
char bin[bufferSize];
char bout[bufferSize]; // <-- WTF
struct sockaddr sender;
socklen_t len;
while(1){
memset(bin, 0, bufferSize);
int n = recvfrom( SOCKET, bin, bufferSize, 0, &sender, &len );
if (n < 0) continue;
puts("receved a query");

/* Strictly decline all invalid queries */
decline( 2, bin, &sender);
}
}

int main(){
bindSocket();
hereBeDragons();
return EXIT_FAILURE;
}

程序输出:

received a query

挖掘输出:

; <<>> DiG 9.9.5-3-Ubuntu <<>> @localhost -p 1337 foo.bar.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 37520
;; flags: qr ad; QUERY: 0, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; Query time: 1 msec
;; SERVER: 127.0.0.1#1337(127.0.0.1)
;; WHEN: Fri Aug 29 21:37:46 CEST 2014
;; MSG SIZE rcvd: 12

这只是一个缩减示例,在实际代码中,bout 用于构造对传入查询的有效响应。但是当我把它留在里面时,会出现以下问题:

Wireshark packet capture

程序将答案发送到错误的端口,5 秒后重试,程序发送到正确的端口。

我做错了什么?

最佳答案

这是一个非常微妙的错误。

必须初始化套接字地址长度参数,recvfrom() 的第六个参数。它必须设置为指示在第五个参数中传递的地址缓冲区的长度。当 recvfrom() 返回时,长度会更新以反射(reflect)写入其中的网络地址结构的实际大小。

在调用 recvfrom() 之前,添加:

len=sizeof(sender);

这在 recvfrom(2) man page 中有解释:

The argument addrlen is a value-result argument, which the caller should initialize before the call to the size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address

关于c - 启动时端口错误(recvfrom),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25575477/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com