NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/54435: reading TCP urgent data with MSG_OOB doesn't clear poll(2) status
The following reply was made to PR kern/54435; it has been noted by GNATS.
From: Valery Ushakov <uwe%stderr.spb.ru@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/54435: reading TCP urgent data with MSG_OOB doesn't clear
poll(2) status
Date: Sun, 4 Aug 2019 02:36:37 +0300
Updated test, so that we are on the same page.
/* oobrecv.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int usage(void);
int getsocket(void);
void oobtest(int);
int pollsock(int);
bool oobinline = false;
bool oobsync = false;
bool delay = false;
int
usage(void)
{
fprintf(stderr, "usage: oobrecv [oob | inline | sync | delay | sleep] ...\n");
fprintf(stderr, "default is: %s%s%s\n",
oobinline ? "inline" : "oob",
oobsync ? " sync" : "",
delay ? " delay" : "");
return EXIT_FAILURE;
}
int
main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; ++i) {
if (strcasecmp(argv[i], "oob") == 0)
oobinline = false;
else if (strcasecmp(argv[i], "inline") == 0)
oobinline = true;
else if (strcasecmp(argv[i], "delay") == 0
|| strcasecmp(argv[i], "sleep") == 0)
delay = true;
else if (strcasecmp(argv[i], "sync") == 0)
oobsync = true;
else
return usage();
}
oobtest(getsocket());
return 0;
}
int
getsocket(void)
{
int s;
int status;
s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0)
err(EXIT_FAILURE, "socket");
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
#if !defined(__linux__) && !defined(__sun__)
sin.sin_len = sizeof(sin);
#endif
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sin.sin_port = htons(12345);
if (oobinline) {
int one = 1;
status = setsockopt(s, SOL_SOCKET, SO_OOBINLINE,
(char *)&one, sizeof(one));
if (status < 0)
err(EXIT_FAILURE, "SO_OOBINLINE");
}
status = connect(s, (struct sockaddr *)&sin, sizeof(sin));
if (status < 0)
err(EXIT_FAILURE, "connect");
return s;
}
void
oobtest(int s)
{
char buf[128];
int status;
printf("reading urgent data with %s",
oobinline ? "SO_OOBINLINE" : "MSG_OOB");
if (oobsync)
printf(" with SIOCATMARK");
if (delay)
printf(" after delay");
printf("\n");
if (delay)
sleep(1);
for (;;) {
int revents = pollsock(s);
if (revents == 0)
continue;
if (revents & POLLNVAL) {
errno = EBADF;
err(EXIT_FAILURE, "poll");
}
if (revents & POLLERR) {
int sockerr;
socklen_t optlen = (socklen_t)sizeof(sockerr);
status = getsockopt(s, SOL_SOCKET, SO_ERROR,
(char *)&sockerr, &optlen);
if (status < 0)
err(EXIT_FAILURE, "SO_ERROR");
errno = sockerr;
err(EXIT_FAILURE, NULL);
}
ssize_t nread;
if (oobsync && (revents & (POLLPRI | POLLRDBAND))) {
for (;;) {
int atmark;
status = ioctl(s, SIOCATMARK, &atmark);
if (status < 0)
err(EXIT_FAILURE, "SIOCATMARK");
if (atmark) {
printf("<at mark>\n");
break;
}
nread = recv(s, buf, sizeof(buf), 0);
if (nread < 0)
err(EXIT_FAILURE, "recv");
printf("recv() = %zd (reading to mark)\n", nread);
fwrite(buf, 1, nread, stdout);
printf("\n");
}
}
int flags = 0;
if (!oobinline && (revents & (POLLPRI | POLLRDBAND)))
flags |= MSG_OOB;
retry:
nread = recv(s, buf, sizeof(buf), flags);
if (nread < 0) {
if (flags & MSG_OOB) {
flags &= ~MSG_OOB;
printf("recv(MSG_OOB) failed, retrying\n");
goto retry;
}
else {
err(EXIT_FAILURE, "recv%s",
flags & MSG_OOB ? "(MSG_OOB)" : "");
}
}
printf("recv(%s) = %zd\n",
flags & MSG_OOB ? "MSG_OOB" : "",
nread);
if (nread == 0)
return;
fwrite(buf, 1, nread, stdout);
printf("\n");
}
}
int
pollsock(int s)
{
struct pollfd fds[1];
fds[0].fd = s;
fds[0].events = POLLIN | POLLPRI | POLLRDBAND;
fds[0].revents = 0;
int nready = poll(fds, 1, -1);
if (nready < 0)
err(EXIT_FAILURE, "poll");
if (nready == 0)
return 0;
int revents = fds[0].revents;
printf("poll: revents = 0x%x", revents);
if (fds[0].revents != 0) {
printf(":");
if (revents & POLLNVAL) printf(" NVAL");
if (revents & POLLERR) printf(" ERR");
if (revents & POLLHUP) printf(" HUP");
if (revents & POLLIN) printf(" IN");
if (revents & POLLPRI) printf(" PRI");
if (revents & POLLRDNORM) printf(" RDNORM");
if (revents & POLLRDBAND) printf(" RDBAND");
}
printf("\n");
return revents;
}
Home |
Main Index |
Thread Index |
Old Index