xref: /netbsd-src/tests/net/inpcb/broadcast_bind.c (revision eedb766f768f680d2141fa76dc9464cc9ad7c3c3)
1 /* $NetBSD: broadcast_bind.c,v 1.2 2022/11/17 08:42:06 ozaki-r Exp $ */
2 /* $OpenBSD: broadcast_bind.c,v 1.2 2015/12/02 20:45:00 mpi Exp $ */
3 
4 /*
5  * Copyright (c) 2015 Vincent Gross <vgross@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <err.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include <arpa/inet.h>
28 
29 #include <sys/socket.h>
30 
31 #include <netinet/in.h>
32 
33 
34 static int
test_bind(char * paddr,struct in_addr * addr,u_int16_t port,int type,int expected_errno)35 test_bind(char *paddr, struct in_addr *addr, u_int16_t port, int type,
36     int expected_errno)
37 {
38 	int s, rc;
39 	struct sockaddr_in sin;
40 
41 	memset(&sin, 0, sizeof(sin));
42 	sin.sin_family = AF_INET;
43 	sin.sin_len = sizeof(sin);
44 	sin.sin_port = htons(port);
45 	memcpy(&sin.sin_addr, addr, sizeof(*addr));
46 
47 	s = socket(PF_INET, type, 0);
48 	if (s < 0) {
49 		warn("socket(PF_INET, %d, 0)", type);
50 		return (1);
51 	}
52 
53 	rc = bind(s, (struct sockaddr *)&sin, sin.sin_len);
54 	if ((rc == 0 && expected_errno == 0) ||
55 	    (rc != 0 && expected_errno == errno)) {
56 		close(s);
57 		return (0);
58 	}
59 
60 	warn("bind(%s,%d) (type %d) expected %d, got %d", paddr, port, type,
61 	    expected_errno, errno);
62 	close(s);
63 
64 	return (1);
65 }
66 
67 int
main(int argc,char * argv[])68 main(int argc, char *argv[])
69 {
70 	int rc;
71 	struct in_addr uc_addr, err_addr, bc_addr;
72 	int port = 30000;
73 
74 	if (argc != 4)
75 		errx(1, "needs 2 arguments: <unicast> <error> <broadcast>");
76 
77 	rc = inet_pton(AF_INET, argv[1], &uc_addr);
78 	if (rc != 1) {
79 		if (rc)
80 			err(1, "inet_pton(unicast)");
81 		else
82 			errx(1, "inet_pton(unicast): error parsing %s",
83 			    argv[1]);
84 	}
85 	rc = inet_pton(AF_INET, argv[2], &err_addr);
86 	if (rc != 1) {
87 		if (rc)
88 			err(1, "inet_pton(error)");
89 		else
90 			errx(1, "inet_pton(error): error parsing %s", argv[2]);
91 	}
92 	rc = inet_pton(AF_INET, argv[3], &bc_addr);
93 	if (rc != 1) {
94 		if (rc)
95 			err(1, "inet_pton(broadcast)");
96 		else
97 			errx(1, "inet_pton(broadcast): error parsing %s",
98 			    argv[3]);
99 	}
100 
101 	rc = 0;
102 	rc |= test_bind(argv[1], &uc_addr, port, SOCK_STREAM, 0);
103 	rc |= test_bind(argv[2], &err_addr, port, SOCK_STREAM, EADDRNOTAVAIL);
104 #ifdef __NetBSD__
105 	rc |= test_bind(argv[3], &bc_addr, port, SOCK_STREAM, 0);
106 #else
107 	rc |= test_bind(argv[3], &bc_addr, port, SOCK_STREAM, EADDRNOTAVAIL);
108 #endif
109 
110 	rc |= test_bind(argv[2], &err_addr, port, SOCK_STREAM, EADDRNOTAVAIL);
111 	rc |= test_bind(argv[3], &bc_addr, port, SOCK_DGRAM, 0);
112 
113 	return (rc);
114 }
115