misc/181092: Invoke the function sendmsg be hung.
jell
jelllove at 126.com
Tue Aug 6 14:30:00 UTC 2013
>Number: 181092
>Category: misc
>Synopsis: Invoke the function sendmsg be hung.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Aug 06 14:30:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator: jell
>Release: FreeBSD-9.1-RELEASE-i386
>Organization:
jell
>Environment:
FreeBSD jell 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243826: Tue Dec 4 06:55:39 UTC 2012 root at obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
>Description:
I wrote a simple tools to create a INET6 RAW socket, and try to invoke the function "sendmsg" to send a message.
And I found when the message size is 9210, the function "sendmsg" will be hung.
>How-To-Repeat:
1. Compile my test code(in attachment)
2. config a ipv6 address like "5555::6/64"
3. Run my test tools as "./test 5555::7 9210"
4. The process "test" will be hung.
>Fix:
Patch attached with submission follows:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void set_addr(struct sockaddr *pAddr, int domain, char *pAddress, unsigned short port)
{
struct sockaddr_in *sin4 = NULL;
struct sockaddr_in6 *sin6 = NULL;
if (domain == AF_INET) {
struct sockaddr_in *sin4 = (struct sockaddr_in *)pAddr;
memset(sin4, 0, sizeof(struct sockaddr_in));
sin4->sin_family = AF_INET;
sin4->sin_port = htons(port);
if (pAddress == NULL) {
sin4->sin_addr.s_addr = htonl(INADDR_ANY);
}
else {
sin4->sin_addr.s_addr = inet_addr(pAddress);
}
}
else {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)pAddr;
memset(sin6, 0, sizeof(struct sockaddr_in6));
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
if (pAddress == NULL) {
sin6->sin6_addr = in6addr_any;
}
else {
inet_pton(AF_INET6, pAddress, &sin6->sin6_addr);
}
}
}
void usage()
{
printf("usage:\n\t test ipv6_address send_size\ne.g.\n\ttest 2000:56::56 9183");
exit(0);
}
int main(int argc, char* argv[])
{
int buffer_size = 9183;
int s = -1;
char *pTmpBuffer = NULL;
int nRet = 0;
struct sockaddr_in6 sin6;
char *pAddress;
static struct msghdr smsghdr;
struct iovec iov[2];
static char *scmsg = 0;
struct cmsghdr *scmsgp = 0;
int ip6optlen = 0;
int hoplimit = 200;
if (argc >= 3) {
pAddress = argv[1];/* get the IP address */
buffer_size = atoi(argv[2]); /* get the send buffer size */
if (buffer_size <= 0) {
usage();
}
}
else {
usage();
}
s = socket(AF_INET6, SOCK_RAW, 3);
if (s < 0) {
perror("create socket error\n");
exit(-1);
}
pTmpBuffer = (char *)malloc(buffer_size);
if (pTmpBuffer == NULL) {
perror("malloc failed:");
exit(-1);
}
memset(pTmpBuffer, 0, buffer_size);
memset(&smsghdr, 0, sizeof(smsghdr));
set_addr((struct sockaddr *)&sin6, AF_INET6, pAddress, 0);
smsghdr.msg_name = (char *)&sin6;
smsghdr.msg_namelen = sizeof(sin6);
ip6optlen = CMSG_SPACE(sizeof(int));
scmsg = (char *)malloc(ip6optlen);
smsghdr.msg_control = (caddr_t)scmsg;
smsghdr.msg_controllen = ip6optlen;
scmsgp = (struct cmsghdr *)scmsg;
scmsgp->cmsg_len = CMSG_LEN(sizeof(int));
scmsgp->cmsg_level = IPPROTO_IPV6;
scmsgp->cmsg_type = IPV6_HOPLIMIT;
*(int *)(CMSG_DATA(scmsgp)) = hoplimit;
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
memset(&iov, 0, sizeof(iov));
iov[0].iov_base = (char *)pTmpBuffer;
iov[0].iov_len = buffer_size;
smsghdr.msg_iov = iov;
smsghdr.msg_iovlen = 1;
nRet = sendmsg(s, &smsghdr, 0);
free(pTmpBuffer);
if (nRet < 0) {
perror("sendmsg failed:");
exit(-1);
}
printf("success send size: %d bytes\n", nRet);
return 0;
}
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list