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