是否有限制多少字符可以通过UDP / SNMP来送?(Is there a limit how ma

2019-09-29 22:54发布

我试图通过UDP / SNMP服务器从发送一个字符串到客户端。 但是,如果我复制一个字符串,长度为86到PDU packet->value_value一切工作正常,我让客户端上的字符串。 如果我只添加一个字符更多的字符串,长度是现在87 ,该数据包不能传递到客户端。 包大小正确提高。 是否有限制多少个字符,可以送? 我的包比1500更小。

这段代码显示了如何复制字符串到packet->value_value

value_value = "asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd as";
printf("String length: %d\n",strlen(value_value)); // 86 OK, 87or greater NOK
packet->value_length = strlen(value_value);
packet->value_value = malloc(packet->value_length);
strcpy(packet->value_value, value_value);

对于一些信息,这里用约分组长度一些更详细的信息的终端输出

与串长度输出86

src/agent.c:69:parse_request(): Input length=43
src/agent.c:116:perform_snmp_request(): OID is: 1.3.6.1.2.1.1.1.0
String length: 86
src/mibservice.c:90:snmpget(): packet->value_type=04
src/mibservice.c:91:snmpget(): packet->value_length=56
src/mibservice.c:93:snmpget(): packet->value_value=61
...
src/mibservice.c:93:snmpget(): packet->value_value=73
src/mibservice.c:95:snmpget(): Before packet->length=41
src/mibservice.c:97:snmpget(): After packet->length=127
src/mibservice.c:99:snmpget(): Before packet->pdu_length=28
src/mibservice.c:101:snmpget(): After packet->pdu_length=114
src/mibservice.c:103:snmpget(): Before packet->variablebindings_length=14
src/mibservice.c:105:snmpget(): After packet->variablebindings_length=100
src/mibservice.c:107:snmpget(): Before packet->varbind_length=12
src/mibservice.c:109:snmpget(): After packet->varbind_length=98
src/agent.c:96:create_response(): Output length=129

与串长度输出87

src/agent.c:69:parse_request(): Input length=43
src/agent.c:116:perform_snmp_request(): OID is: 1.3.6.1.2.1.1.1.0
String length: 87
src/mibservice.c:90:snmpget(): packet->value_type=04
src/mibservice.c:91:snmpget(): packet->value_length=57
src/mibservice.c:93:snmpget(): packet->value_value=61
...
src/mibservice.c:93:snmpget(): packet->value_value=64
src/mibservice.c:95:snmpget(): Before packet->length=41
src/mibservice.c:97:snmpget(): After packet->length=128
src/mibservice.c:99:snmpget(): Before packet->pdu_length=28
src/mibservice.c:101:snmpget(): After packet->pdu_length=115
src/mibservice.c:103:snmpget(): Before packet->variablebindings_length=14
src/mibservice.c:105:snmpget(): After packet->variablebindings_length=101
src/mibservice.c:107:snmpget(): Before packet->varbind_length=12
src/mibservice.c:109:snmpget(): After packet->varbind_length=99
src/agent.c:96:create_response(): Output length=130

更新这里是我的问题可运行的例子。 包out_buf_0代表一个有效的SNMP包,可以通过UDP发送。 分组out_buf_1是像相同的分组out_buf_0并在后面加上一个字符更0x64 。 此外,我提出因为附加字符的所有长度+ 1。 为什么out_buf_1不是一个有效的SNMP报文/为何不能透过UDP发送? 注意:SNMP请求,因为不能在终端显示request id从客户端不同于out_buf_0out_buf_1 ,看看在Wireshark来查看请求/响应。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MESSAGE_MAX_LEN  1500 /* MTU, IEEE Std 802.3TM-2015 */
#define PORT 161 /* RFC 1157 */

int out_buf_0_len = 129; /* 0x7f + 2 */
char out_buf_0[] = {
0x30, /* SNMP Packet start */
0x7f, /* SNMP Packet length */
0x02, 0x01, 0x00, /* Version */
0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, /* Community*/
0xa2, /* GetResponsePDU */
0x72, /* GetResponsePDU Length */
0x02, 0x04, 0x2c, 0x80, 0x7e, 0x2f, /* Request id */
0x02, 0x01, 0x00, /*Error status */
0x02, 0x01, 0x00, /*Error index */
0x30, /* Varbind list start */
0x64, /* Varbind list length*/
0x30, /* Varbind value start */
0x62, /* Varbind value length */
0x06, 0x08, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, /* OID */
0x04,  /* Value start, type octet-string*/
0x56, /* Value length */
0x61, 0x73, 0x64, 0x20, 0x61, /* Value */
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73 };

int out_buf_1_len = 130; /* 0x80 + 2 */
char out_buf_1[] = {
0x30, /* SNMP Packet start */
0x80, /* SNMP Packet length */
0x02, 0x01, 0x00, /* Version */
0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, /* Community*/
0xa2, /* GetResponsePDU */
0x73, /* GetResponsePDU Length */
0x02, 0x04, 0x2c, 0x80, 0x7e, 0x2f, /* Request id */
0x02, 0x01, 0x00, /*Error status */
0x02, 0x01, 0x00, /*Error index */
0x30, /* Varbind list start */
0x65, /* Varbind list length*/
0x30, /* Varbind value start */
0x63, /* Varbind value length */
0x06, 0x08, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, /* OID */
0x04,  /* Value start, type octet-string*/
0x57, /* Value length */
0x61, 0x73, 0x64, 0x20, 0x61, /* Value */
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64 };

int my_socket;
struct sockaddr_in remote_addr;
int socket_create()
{
    printf("Create socket\n");
    struct sockaddr_in socket_addr;
    if ((my_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("Cannot create socket. Exit.\n");
        return -1;
    }
    memset((char *)&socket_addr, 0, sizeof(socket_addr));
    socket_addr.sin_family = AF_INET;
    socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    socket_addr.sin_port = htons(PORT);
    if (bind(my_socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
    {
        printf("Bind failed. Exit.\n");
        return - 1;
    }
    printf("Listen on: %s:%d\n", inet_ntoa(socket_addr.sin_addr), PORT);
    return 0;
}

socklen_t addr_len = sizeof(remote_addr);
void socket_listen(char *in_buf)
{
    int  recv_len; /* Bytes received */
    int  nbyt; /* Bytes count */
    char *out_buf[MESSAGE_MAX_LEN];
    int  out_len = 0;

    for (;;) { /* Receive snmp message from snmp manager */
        recv_len = recvfrom(my_socket, in_buf, MESSAGE_MAX_LEN, 0, (struct sockaddr *)&remote_addr, &addr_len);
        if (recv_len > 0)
            if (sendto(my_socket, out_buf_1, out_buf_1_len, 0, (struct sockaddr *)&remote_addr, addr_len) < 0)
                printf("Cannot send data to destination.\n");
    }
}

/* Disable SNMP on local machine. # systemctl stop snmpd 
 * Execute main(): gcc <filename>.c && ./a.out
 * Run SNMP Request: $ snmpget -v 1 -c public 0.0.0.0:161 1.3.6.1.2.1.1.1.0
 */
char in_buf[MESSAGE_MAX_LEN];
int main(int argc, char **argv)
{
    if (socket_create() == -1)
        exit(2);
    socket_listen(in_buf);
}

整个帧的长度,包括我的SNMPv1的分组out_buf_0是1368个比特, out_buf_1应该1376个比特。

Answer 1:

正如有人在评论指针移出,strcpy的是邪恶的,不应该被用于任何东西。 你的malloc实际分配的数组比你原来的数组较小,因为你没有考虑到尾随空。 当您使用的strcpy你写过去的尾部空分配的数组的结尾。

既然你不包括相关的数据包结构,我不知道是如何被使用,但如果在此之后的任何代码需要C语言的零终止字符串如预期它可能将无法正常工作的代码。



Answer 2:

SNMP报文长度0x80是错的,看这里

0x80的的ASN.1长度字段是错误的。 解码器看到你的包的前两个字节是0x80的的0x30,并确定从0x80的,应该有以下没有更多的字节。 尽管如此,仍然有多个字节,所以它是一个无效的编码,并进一步无效SNMP消息。 在这里0x80的并不意味着128个字节的内容为你打算,这意味着你的长度字段为0x80的&〜0x80的== 0个字节以下这八位字节长。 相反,0x81表示将意味着你的长度字段为0×81&〜0x80的== 1以下八位组,那下面0x80的八位组将表明128内容长度。

这就是SNMP报文应该怎么样子,

char out_buf_1[] = {
0x30, /* SNMP Packet start */
0x81, 0x80, /* SNMP Packet length */
0x02, 0x01, 0x00, /* Version */
0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, /* Community*/
0xa2, /* GetResponsePDU */
0x73, /* GetResponsePDU Length */
0x02, 0x04, 0x2c, 0x80, 0x7e, 0x2f, /* Request id */
0x02, 0x01, 0x00, /*Error status */
0x02, 0x01, 0x00, /*Error index */
0x30, /* Varbind list start */
0x65, /* Varbind list length*/
0x30, /* Varbind value start */
0x63, /* Varbind value length */
0x06, 0x08, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, /* OID */
0x04,  /* Value start, type octet-string*/
0x57, /* Value length */
0x61, 0x73, 0x64, 0x20, 0x61, /* Value */
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64, 0x20, 0x61, 0x73, 0x64, 0x20, 0x61,
0x73, 0x64 };


文章来源: Is there a limit how many character can be send over udp/snmp?
标签: c snmp