1 /*- 2 * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved. 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions 5 * are met: 6 * 1. Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * 2. Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * 12 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 13 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 16 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22 * SUCH DAMAGE. 23 */ 24 25 #include <sys/cdefs.h> 26 __FBSDID("$FreeBSD$"); 27 28 #include <stdbool.h> 29 #include <stdio.h> 30 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <sys/un.h> 35 36 #include <atf-c.h> 37 /* Helper functions*/ 38 39 /* 40 * Create two devd events. The easiest way I know of, that requires no special 41 * hardware, is to create md(4) devices. 42 */ 43 static void 44 create_two_events(void) 45 { 46 FILE *create_stdout; 47 FILE *destroy_stdout; 48 char mdname[80]; 49 char destroy_cmd[80]; 50 char *error; 51 52 create_stdout = popen("mdconfig -a -s 64 -t null", "r"); 53 ATF_REQUIRE(create_stdout != NULL); 54 error = fgets(mdname, sizeof(mdname), create_stdout); 55 ATF_REQUIRE(error != NULL); 56 /* We only expect one line of output */ 57 ATF_REQUIRE_EQ(0, pclose(create_stdout)); 58 59 snprintf(destroy_cmd, nitems(destroy_cmd), "mdconfig -d -u %s", mdname); 60 destroy_stdout = popen(destroy_cmd, "r"); 61 ATF_REQUIRE(destroy_stdout != NULL); 62 /* We expect no output */ 63 ATF_REQUIRE_EQ(0, pclose(destroy_stdout)); 64 } 65 66 /* 67 * Test Cases 68 */ 69 70 /* 71 * Open a client connection to devd, create some events, and test that they can 72 * be read _whole_ and _one_at_a_time_ from the socket 73 */ 74 ATF_TC_WITHOUT_HEAD(seqpacket); 75 ATF_TC_BODY(seqpacket, tc) 76 { 77 int s; 78 int error; 79 struct sockaddr_un devd_addr; 80 bool got_create_event = false; 81 bool got_destroy_event = false; 82 const char create_pat[] = 83 "!system=DEVFS subsystem=CDEV type=CREATE cdev=md"; 84 const char destroy_pat[] = 85 "!system=DEVFS subsystem=CDEV type=DESTROY cdev=md"; 86 87 memset(&devd_addr, 0, sizeof(devd_addr)); 88 devd_addr.sun_family = PF_LOCAL; 89 strlcpy(devd_addr.sun_path, "/var/run/devd.seqpacket.pipe", 90 sizeof(devd_addr.sun_path)); 91 92 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 93 ATF_REQUIRE(s >= 0); 94 error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr)); 95 ATF_REQUIRE_EQ(0, error); 96 97 create_two_events(); 98 99 /* 100 * Loop until both events are detected on _different_ reads 101 * There may be extra events due to unrelated system activity 102 * If we never get both events, then the test will timeout. 103 */ 104 while (!(got_create_event && got_destroy_event)) { 105 int cmp; 106 ssize_t len; 107 char event[1024]; 108 109 /* Read 1 less than sizeof(event) to allow space for NULL */ 110 len = recv(s, event, sizeof(event) - 1, MSG_WAITALL); 111 ATF_REQUIRE(len != -1); 112 /* NULL terminate the result */ 113 event[len] = '\0'; 114 printf("%s", event); 115 cmp = strncmp(event, create_pat, sizeof(create_pat) - 1); 116 if (cmp == 0) 117 got_create_event = true; 118 119 cmp = strncmp(event, destroy_pat, sizeof(destroy_pat) - 1); 120 if (cmp == 0) 121 got_destroy_event = true; 122 } 123 124 close(s); 125 } 126 127 /* 128 * Open a client connection to devd using the stream socket, create some 129 * events, and test that they can be read in any number of reads. 130 */ 131 ATF_TC_WITHOUT_HEAD(stream); 132 ATF_TC_BODY(stream, tc) 133 { 134 int s; 135 int error; 136 struct sockaddr_un devd_addr; 137 bool got_create_event = false; 138 bool got_destroy_event = false; 139 const char create_pat[] = 140 "!system=DEVFS subsystem=CDEV type=CREATE cdev=md"; 141 const char destroy_pat[] = 142 "!system=DEVFS subsystem=CDEV type=DESTROY cdev=md"; 143 ssize_t len = 0; 144 145 memset(&devd_addr, 0, sizeof(devd_addr)); 146 devd_addr.sun_family = PF_LOCAL; 147 strlcpy(devd_addr.sun_path, "/var/run/devd.pipe", 148 sizeof(devd_addr.sun_path)); 149 150 s = socket(PF_LOCAL, SOCK_STREAM, 0); 151 ATF_REQUIRE(s >= 0); 152 error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr)); 153 ATF_REQUIRE_EQ(0, error); 154 155 create_two_events(); 156 157 /* 158 * Loop until both events are detected on _different_ reads 159 * There may be extra events due to unrelated system activity 160 * If we never get both events, then the test will timeout. 161 */ 162 while (!(got_create_event && got_destroy_event)) { 163 char event[1024]; 164 ssize_t newlen; 165 char *create_pos, *destroy_pos; 166 167 /* Read 1 less than sizeof(event) to allow space for NULL */ 168 newlen = read(s, &event[len], sizeof(event) - len - 1); 169 ATF_REQUIRE(newlen != -1); 170 len += newlen; 171 /* NULL terminate the result */ 172 event[newlen] = '\0'; 173 printf("%s", event); 174 175 create_pos = strstr(event, create_pat); 176 if (create_pos != NULL) 177 got_create_event = true; 178 179 destroy_pos = strstr(event, destroy_pat); 180 if (destroy_pos != NULL) 181 got_destroy_event = true; 182 } 183 184 close(s); 185 } 186 187 /* 188 * Main. 189 */ 190 191 ATF_TP_ADD_TCS(tp) 192 { 193 ATF_TP_ADD_TC(tp, seqpacket); 194 ATF_TP_ADD_TC(tp, stream); 195 196 return (atf_no_error()); 197 } 198 199