커널 2.6.18 인 Linux에서 sendmsg()를 사용하여 설정된 TOS 값으로 UDP 패킷을 보내려고합니다. 그러나 '잘못된 인수'오류로 호출이 실패합니다. 부수적 인 데이터 부분을 비활성화하면 (조건 컴파일 플래그 USE_IP_TOS 참조) sendmsg()가 성공합니다. 코드와 출력은 다음 것은 :sendmsg()가 IP_TOS 보조 데이터와 함께 UDP 패킷을 보내는 동안 실패 함
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <net/if.h>
#define UDP_PORT 45897
int SendMsgWithIPTOS(int sockfd, unsigned char *pBuf, size_t bufLen, int tos)
{
unsigned int toIp;
struct sockaddr_in to_addr;
struct msghdr msg;
struct iovec iov[1];
unsigned char cmsg[ CMSG_SPACE(sizeof(int)) ];
struct cmsghdr *cmsgptr = NULL;
size_t sendBytes = 0;
toIp = 0x0a214401;
to_addr.sin_addr.s_addr = htonl(toIp);
to_addr.sin_family = AF_INET;
to_addr.sin_port = htons(UDP_PORT);
memset(&iov, 0, sizeof(iov));
memset(&cmsg, 0, sizeof(cmsg));
iov[0].iov_base = pBuf;
iov[0].iov_len = bufLen;
memset(&msg, 0, sizeof (struct msghdr));
msg.msg_name = &to_addr;
msg.msg_namelen = sizeof(to_addr);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
#ifndef USE_IP_TOS
msg.msg_control = NULL;
msg.msg_controllen = 0;
#else
msg.msg_control = cmsg;
msg.msg_controllen = sizeof(cmsg);
cmsgptr = CMSG_FIRSTHDR(&msg);
cmsgptr->cmsg_level = IPPROTO_IP;
cmsgptr->cmsg_type = IP_TOS;
cmsgptr->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsgptr), (unsigned char*)&tos, sizeof(int));
//*((int *) CMSG_DATA (cmsgptr)) = tos;
msg.msg_controllen = CMSG_SPACE(sizeof(int));
#endif
msg.msg_flags = 0;
if ((sendBytes = sendmsg(sockfd, &msg, 0)) == -1)
{
fprintf(stderr, "sendmsg() failed (%s) (%d)\n", strerror(errno), errno);
}
else
{
fprintf(stderr, "sent %d bytes \n", sendBytes);
}
return sendBytes;
}
int main()
{
int32_t sockfd, retCode;
struct sockaddr_in sockaddr;
socklen_t addrlen = sizeof(sockaddr);
unsigned char buf[1024] = { 0 };
size_t len = sizeof(buf);
int optval;
/* Create a UDP socket */
if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
fprintf(stderr, "socket failed (%s)\n", strerror(errno));
return sockfd;
}
/* Bind the socket to the given port */
memset(&sockaddr, 0, addrlen);
sockaddr.sin_addr.s_addr = INADDR_ANY;
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(UDP_PORT);
if ((retCode = bind(sockfd, (const struct sockaddr *)&sockaddr, addrlen)) < 0)
{
fprintf(stderr, "bind failed (%s)\n", strerror(errno));
close(sockfd);
return retCode;
}
#if 0 // set the DSCP value using setsockopt
/* Set the DSCP value to Expedited Forwarding (0x2e) */
optval = 0xb8;
if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, (void*)&optval, sizeof(optval)) < 0)
{
fprintf(stderr, "Failed to set DSCP value (%s)\n", strerror(errno));
close(sockfd);
return retCode;
}
else
{
socklen_t optlen = sizeof(optval);
fprintf(stderr, "DSCP value to set to %u\n", (optval >> 2));
optval = 0;
if (getsockopt(sockfd, IPPROTO_IP, IP_TOS, (void*)&optval, &optlen) < 0)
{
fprintf(stderr, "Failed to retrieve ip_tos value\n");
}
else
{
fprintf(stderr, "Retrieved dscp value %u optlen (%d)\n", (optval >> 2), optlen);
}
}
#endif
optval = 0xb8; // Expedited Forwarding
while (1)
{
retCode = SendMsgWithIPTOS(sockfd, buf, len, optval);
sleep(1);
}
return retCode;
}
Output:
-------
$
$ gcc -o ip_tos sockopt_test.c -Wall -DUSE_IP_TOS
$
$ ./ip_tos
sendmsg() failed (Invalid argument) (22)
sendmsg() failed (Invalid argument) (22)
$
$ gcc -o ip_tos sockopt_test.c -Wall
sockopt_test.c: In function ‘SendMsgWithIPTOS’:
sockopt_test.c:22: warning: unused variable ‘cmsgptr’
$
$ ./ip_tos
sent 1024 bytes
sent 1024 bytes
$
내가 테스트 목적을 위해 코드의 setsockopt를() 부분을 활성화/비활성화 시도 유의하시기 바랍니다. 하지만 그게 도움이되지 않습니다
내가 뭘 잘못하고 있는지 모르겠어. 코드를 사용하여 문제를 찾는 데 도움이되거나 문제를 디버깅하는 데 도움이되는 포인터를 제공해 주시면 대단히 감사하겠습니다.
감사 Raveendra
코드를 어떻게 변경 했습니까? 귀하의 답변을 수정하십시오. –
이 질문에 대한 답을 제공하지 않습니다. 충분한 [평판] (https://stackoverflow.com/help/whats-reputation)이 있으면 [모든 게시물에 주석 달기] (https://stackoverflow.com/help/privileges/comment) 할 수 있습니다. 대신, [질문자의 설명이 필요없는 답변을 제공하십시오] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can- i-do- 대신). - [리뷰에서] (리뷰/저품절 포스트/16968281) – Milap