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