我想通過UDP/SNMP從服務器發送一個字符串到客戶端。但是,如果我複製一個長度爲86
的字符串到pdu packet->value_value
一切正常,我得到客戶端的字符串。如果我只向字符串添加更多字符,則長度現在爲87
,數據包無法傳遞給客戶端。數據包大小正確提升。是否有限制可以發送多少個字符?我的包是小於1500是否有限制可以通過udp/snmp發送多少個字符?
這段代碼顯示瞭如何將字符串複製到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_0
和out_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比特。
? 'malloc(packet-> value_length + 1);'在''strcpy'之前爲'NUL'終結符加1。或者'packet-> value_length = strlen(value_value)+ 1;'而不是。 –
@WeatherVane問題是一樣的,如果我添加+1值長度是錯誤的。 – Sam
您的程序會超出內存分配並導致UB。 –