1/*	$OpenBSD: rcvtimeo.c,v 1.6 2021/12/13 16:56:50 deraadt Exp $	*/
2
3/*	Written by Michael Shalayeff, 2002, Public Domain */
4
5#include <sys/socket.h>
6
7#include <netinet/in.h>
8
9#include <signal.h>
10#include <unistd.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <errno.h>
15#include <err.h>
16
17volatile int back;
18
19static void
20sigalarm(int sig, siginfo_t *sip, void *scp)
21{
22	if (!back)
23		_exit(1);
24}
25
26int
27main(int argc, char *argv[])
28{
29	struct sockaddr_in sin;
30	struct sigaction sa;
31	struct timeval tv;
32	u_char buf[16];
33	int s;
34
35	sa.sa_sigaction = &sigalarm;
36	sa.sa_flags = SA_SIGINFO;
37	sigemptyset(&sa.sa_mask);
38	sigaction(SIGALRM, &sa, NULL);
39
40	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
41		err(1, "socket");
42
43	memset(&sin, 0, sizeof(sin));
44	sin.sin_len = sizeof(sin);
45	sin.sin_family = AF_INET;
46	sin.sin_port = htons(30000);	/* XXX assuming nothing is there */
47	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
48	if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
49		err(1, "bind");
50
51	tv.tv_sec = 1;
52	tv.tv_usec = 0;
53	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
54		err(1, "setsockopt1");
55
56	back = 0;
57	alarm(2);
58	errno = 0;
59	if (recv(s, buf, sizeof(buf), 0) < 0 && errno != EAGAIN)
60		err(1, "recv1");
61	back = 1;
62
63	tv.tv_sec = 0;
64	tv.tv_usec = 1;
65	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
66		err(1, "setsockopt2");
67
68	back = 0;
69	alarm(2);
70	errno = 0;
71	if (recv(s, buf, sizeof(buf), 0) < 0 && errno != EAGAIN)
72		err(1, "recv2");
73	back = 1;
74
75	exit (0);
76}
77