Date: Sat, 28 Feb 1998 13:36:14 PST From: Bill Fenner <fenner@parc.xerox.com> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: kern/5877: sb_cc counts control data as well as data data Message-ID: <199802282136.NAA04591@fenestro.parc.xerox.com>
index | next in thread | raw e-mail
>Number: 5877
>Category: kern
>Synopsis: sb_cc counts control data as well as data data
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Feb 28 13:40:00 PST 1998
>Last-Modified:
>Originator: Bill Fenner
>Organization:
Xerox
>Release: FreeBSD 3.0-CURRENT i386
>Environment:
BSD since the beginning of time (well, 4.2 =)
>Description:
A socket's sb_cc field includes the length of control data (like the
source address, for PR_ADDR protocols, and any control info like if
SO_TIMESTAMP, IP_RECVIF, etc. are set).
Problems with this include:
- FIONREAD just returns sb_cc, but not all these bytes are readable
- This count is used to determine the high/low water marks on the
socket.
Advantages are:
- sb_cc is really the length of the attached mbufs, so it's simple
to compute.
>How-To-Repeat:
Adel Abushaev <adel@ksu.ru> reported the problem and included this pair of
test programs.
/* client.c */
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void main()
{
int sockfd;
struct sockaddr_in servaddr_in;
char buffer[512];
memset(&servaddr_in, 0, sizeof(struct sockaddr_in));
servaddr_in.sin_family = AF_INET;
servaddr_in.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr_in.sin_port = htons(4000);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd <= 0)
{
perror("socket"); return;
}
sendto(sockfd, buffer, 512, 0, (struct sockaddr *)&servaddr_in,
sizeof(struct sockaddr_in));
close(sockfd);
}
/* server.c */
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#ifdef SOLARIS
#include <sys/filio.h>
#endif
void main()
{
int sockfd;
struct sockaddr_in myaddr_in, peeraddr_in;
unsigned addrlen;
char buffer[512];
struct timeval tim;
int optval;
fd_set fdsread, fdswrite, fdsexcept;
memset(&myaddr_in, 0, sizeof(struct sockaddr_in));
memset(&peeraddr_in, 0, sizeof(struct sockaddr_in));
myaddr_in.sin_family = AF_INET;
myaddr_in.sin_addr.s_addr = INADDR_ANY;
myaddr_in.sin_port = htons(4000);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd <= 0)
{
perror("socket"); return;
}
if (bind(sockfd, (struct sockaddr *)&myaddr_in, sizeof(struct sockaddr_in))
< 0)
{
perror("bind"); return;
}
FD_ZERO(&fdsread); FD_ZERO(&fdswrite); FD_ZERO(&fdsexcept);
FD_SET(sockfd, &fdsread);
tim.tv_sec=60; tim.tv_usec=0;
select(sockfd+1, &fdsread, &fdswrite, &fdsexcept, &tim);
if (FD_ISSET(sockfd, &fdsread))
{
ioctl(sockfd, FIONREAD, &optval); printf("ioctl: %d\n",optval);
optval=recvfrom(sockfd, buffer, 512, 0, (struct sockaddr *)&peeraddr_in,
&addrlen); printf("recv: %d\n",optval);
ioctl(sockfd, FIONREAD, &optval); printf("ioctl: %d\n",optval);
}
close(sockfd);
}
>Fix:
Make sb_cc reflect the number of data bytes in the socket buffer,
instead of the amount of data+control. This may be as simple as
fixing sballoc() and sbfree() in sys/socketvar.h to only count
MT_HEADER, MT_DATA, MT_OOBDATA mbufs, or may be much more involved.
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802282136.NAA04591>
