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