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