| Summary: | kevent.data value incorrect for UDP sockets | ||
|---|---|---|---|
| Product: | Base System | Reporter: | knotwell <knotwell> |
| Component: | kern | Assignee: | kbyanc |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | Unspecified | ||
| Hardware: | Any | ||
| OS: | Any | ||
State Changed From-To: open->patched Fix committed to -current. Thanks! Responsible Changed From-To: freebsd-bugs->kbyanc I'll take this so I don't forget the MFC. State Changed From-To: patched->closed I feel it has gotten to late in the FreeBSD 4.x branch's life cycle to worry about MFC'ing this now. It is in FreeBSD 5.0 and later. |
When kevent returns a read event for a UDP socket, the data field (AKA the number of bytes to be read) is 16 bytes too long. NOTE: the problem exists in 4.3 release as well. How-To-Repeat: 1) Compile up the following discard server 2) Run nc -u 127.0.0.1 6060 3) Send data to netcat and watch the server's output It should be consistently off by sixteen bytes. NOTE: this may be a documentation bug and "the number of bytes in the socket buffer" needs to be explained further. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/event.h> /* loopback discardserver on port 6060 */ int main(void) { int queue,sock; struct sockaddr_in saddr; struct kevent evt; memset(&saddr,0,sizeof(struct sockaddr_in)); saddr.sin_family = AF_INET; saddr.sin_port = htons(6060); saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); memset(&evt,0,sizeof(struct kevent)); evt.filter = EVFILT_READ; evt.flags = EV_ADD; if(((queue = kqueue()) == -1) || ((evt.ident = (sock = socket(AF_INET,SOCK_DGRAM,0))) == -1) || (bind(sock,(struct sockaddr *)&saddr,sizeof saddr)) || (kevent(queue,&evt,1,NULL,0,NULL))) return(fprintf(stderr,"bad setup\n"),EXIT_FAILURE); while(1){ char *buf; if((kevent(queue,NULL,0,&evt,1,NULL) == -1) || (!evt.data)) break; if((buf = malloc(evt.data)) == NULL) continue; recv(sock,buf,evt.data,0); printf("size to read(%d) : data : %s\n",evt.data,buf); free(buf); } return(EXIT_SUCCESS); }