1/* Tests for name switch cache daemon (nscd) door wrapper. */ 2 3#include "config.h" 4 5#include <assert.h> 6#include <ctype.h> 7#include <door.h> 8#include <fcntl.h> 9#include <inttypes.h> 10#include <nss_dbdefs.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <strings.h> 14#include <unistd.h> 15#include <sys/mman.h> 16 17#if defined(SOLARIS_NSCD_DOOR_SYSTEM_VOLATILE) 18#define DOOR_FILE "/system/volatile/name_service_door" 19#else 20#define DOOR_FILE "/var/run/name_service_door" 21#endif 22 23#define HEADER(file, test_name) \ 24 fprintf(file, "---------------------------------------------------------\n" \ 25 "%s\n" \ 26 "---------------------------------------------------------\n", \ 27 test_name); 28 29 30static long x0; 31 32/* It's possible that the system allocated a new memory for rbuf. 33 Unmap it if it is the case. */ 34static int handle_rbuf(door_arg_t *params, void *buf) 35{ 36 if (params->rbuf != buf) { 37 if (munmap(params->rbuf, params->rsize) != 0) { 38 perror("munmap"); 39 return EINVAL; 40 } 41 } 42 43 return 0; 44} 45 46__attribute__((noinline)) 47static int test_app_small_request(int did) 48{ 49 /* Set call parameters. */ 50 size_t buf_size = sizeof(uint32_t); 51 char *buf = malloc(buf_size); 52 assert(buf != NULL); 53 54 nss_pheader_t *header = (nss_pheader_t *) buf; 55 header->nsc_callnumber = x0 + NSCD_GETENT; 56 57 door_arg_t params; 58 params.data_ptr = buf; 59 params.data_size = buf_size; 60 params.desc_ptr = NULL; 61 params.desc_num = 0; 62 params.rbuf = buf; 63 params.rsize = buf_size; 64 65 /* Make the call. */ 66 if (door_call(did, ¶ms) != 0) { 67 return errno; 68 } 69 70 return handle_rbuf(¶ms, buf); 71} 72 73__attribute__((noinline)) 74static int test_app_uninitialized_request(int did) 75{ 76 /* Set call parameters. */ 77 size_t buf_size = sizeof(nss_pheader_t) + sizeof(nss_dbd_t); 78 char *buf = malloc(buf_size); 79 assert(buf != NULL); 80 81 nss_pheader_t *header = (nss_pheader_t *) buf; 82 header->nsc_callnumber = x0 + NSCD_GETENT; 83 header->dbd_off = x0 + sizeof(nss_pheader_t); 84 header->dbd_len = x0 + sizeof(nss_dbd_t); 85 nss_dbd_t *dbd = (nss_dbd_t *) (buf + sizeof(nss_pheader_t)); 86 dbd->flags = x0; 87 dbd->o_name = x0 + 100; 88 dbd->o_config_name = x0 + 100; 89 dbd->o_default_config = x0 + 100; 90 header->key_off = x0 + sizeof(nss_pheader_t) + sizeof(nss_dbd_t); 91 header->key_len = x0 + 1; // one byte past the end of 'buf' 92 header->pbufsiz = x0 + 10000000; 93 94 door_arg_t params; 95 params.data_ptr = buf; 96 params.data_size = buf_size; 97 params.desc_ptr = NULL; 98 params.desc_num = 0; 99 params.rbuf = buf; 100 params.rsize = buf_size; 101 102 /* Make the call. */ 103 if (door_call(did, ¶ms) != 0) { 104 return errno; 105 } 106 107 /* Check definedness of response attributes ... */ 108 int x = 0; 109 if (header->p_status != NSS_SUCCESS) x = -1; else x = -2; 110 if (header->p_herrno != 0) x = -2; else x = -3; 111 if (header->key_off != 0) x = -4; else x = -5; 112 if (header->key_len != 0) x = -6; else x = -7; 113 if (header->data_off != 0) x = -8; else x = -9; 114 if (header->data_len != 0) x = -10; else x = -11; 115 /* ... and now one which is not defined. */ 116 if (header->reserved1 != 0) x = -12; else x = -13; 117 118 handle_rbuf(¶ms, buf); 119 return x; 120} 121 122__attribute__((noinline)) 123static int test_app_proto_icmp(int did) 124{ 125 door_arg_t params; 126 char buf[16384]; 127 128 /* Set call parameters. */ 129 nss_pheader_t *header = (nss_pheader_t *) buf; 130 header->nsc_callnumber = NSCD_SEARCH; 131 header->p_ruid = getuid(); 132 header->p_euid = geteuid(); 133 header->p_version = NSCD_HEADER_REV; 134 header->p_status = 0; 135 header->p_errno = 0; 136 header->p_herrno = 0; 137 header->libpriv = 0; 138 header->nss_dbop = NSS_DBOP_PROTOCOLS_BYNAME; 139 140 size_t name_len = strlen(NSS_DBNAM_PROTOCOLS); 141 size_t default_config_len = strlen(NSS_FILES_ONLY); 142 header->dbd_off = sizeof(nss_pheader_t); 143 header->dbd_len = sizeof(nss_dbd_t) + name_len + 1 + default_config_len + 1; 144 nss_dbd_t *dbd = (nss_dbd_t *) (buf + sizeof(nss_pheader_t)); 145 dbd->o_name = sizeof(nss_dbd_t); 146 dbd->o_config_name = 0; 147 dbd->o_default_config = dbd->o_name + name_len + 1; 148 dbd->flags = 0; 149 strcpy(buf + header->dbd_off + dbd->o_name, NSS_DBNAM_PROTOCOLS); 150 strcpy(buf + header->dbd_off + dbd->o_default_config, 151 NSS_DEFCONF_PROTOCOLS); 152 153 name_len = strlen("icmp"); 154 header->key_off = header->dbd_off + ROUND_UP(header->dbd_len, sizeof(nssuint_t)); 155 header->key_len = name_len + 1; 156 strcpy(buf + header->key_off, "icmp"); 157 158 header->data_off = header->key_off + ROUND_UP(header->key_len, sizeof(nssuint_t)); 159 header->data_len = 0; 160 header->pbufsiz = header->data_off + header->data_len; 161 162 params.data_ptr = buf; 163 params.data_size = header->pbufsiz; 164 params.desc_ptr = NULL; 165 params.desc_num = 0; 166 params.rbuf = buf; 167 params.rsize = sizeof(buf); 168 169 /* Sanity checks on the nss_pheader_t header. */ 170 assert(header->p_version == NSCD_HEADER_REV); 171 assert(header->dbd_off == sizeof(nss_pheader_t)); 172 assert((params.data_size & 3) == 0); 173 assert((header->dbd_off & 3) == 0); 174 assert((header->key_off & 3) == 0); 175 assert((header->data_off & 3) == 0); 176 assert(header->data_off == params.data_size); 177 nssuint_t l1 = header->key_off - header-> dbd_off; 178 assert(l1 >= header->dbd_len); 179 nssuint_t l2 = header->data_off - header->key_off; 180 assert(l2 >= header->key_len); 181 assert(sizeof(nss_pheader_t) + l1 + l2 == header->data_off); 182 assert(header->data_off + header->data_len == header->pbufsiz); 183 184 /* Make the call. */ 185 if (door_call(did, ¶ms) != 0) { 186 return errno; 187 } 188 189 /* Print response attributes. */ 190 HEADER(stdout, "app_proto_icmp"); 191 printf("status=%u\n", header->p_status); 192 printf("errno=%u\n", header->p_errno); 193 printf("herrno=%u\n", header->p_herrno); 194 printf("bufsiz=%" PRIu64 "\n", header->pbufsiz); 195 printf("dbd_off=%" PRIu64 " dbd_len=%" PRIu64 "\n", 196 header->dbd_off, header->dbd_len); 197 printf("key_off=%" PRIu64 " key_len=%" PRIu64 "\n", 198 header->key_off, header->key_len); 199 printf("data_off=%" PRIu64 " data_len=%" PRIu64 "\n", 200 header->data_off, header->data_len); 201 printf("ext_off=%" PRIu64 " ext_len=%" PRIu64 "\n", 202 header->ext_off, header->ext_len); 203 printf("key=%s\n", buf + header->key_off); 204 205 /* Parse response proto data. */ 206 char *p = buf + header->data_off; 207 char *limit = p + header->data_len; 208 209 while ((p < limit) && isspace(*p)) 210 p++; 211 char *name_start = p; 212 while ((p < limit) && !isspace(*p)) 213 p++; // skip over the name 214 name_len = p - name_start; 215 216 while ((p < limit) && isspace(*p)) 217 p++; 218 char *number_start = p; 219 do { 220 p++; // skip over the proto number 221 } while ((p < limit) && !isspace(*p)); 222 size_t number_len = p - number_start; 223 224 while ((p < limit) && isspace(*p)) 225 p++; 226 char *aliases_start = p; 227 while ((p < limit) && !isspace(*p)) 228 p++; // skip over the aliases 229 size_t aliases_len = p - aliases_start; 230 231 printf("data: name=%.*s number=%.*s aliases=%.*s\n", 232 (int) name_len, name_start, (int) number_len, number_start, 233 (int) aliases_len, aliases_start); 234 235 return handle_rbuf(¶ms, buf); 236} 237 238int main(int argc, const char *argv[]) 239{ 240 /* Uninitialised, but we know px[0] is 0x0. */ 241 long *px = malloc(sizeof(long)); 242 x0 = px[0]; 243 244 int did = open(DOOR_FILE, O_RDONLY); 245 if (did < 0) { 246 perror("open " DOOR_FILE); 247 fprintf(stderr, "Make sure the name service switch daemon (nscd) " 248 "is running.\n"); 249 return 1; 250 } 251 252 struct door_info info; 253 if (door_info(did, &info) != 0) { 254 perror("door_info " DOOR_FILE); 255 close(did); 256 return 1; 257 } 258 259 HEADER(stderr, "app_small_request"); 260 test_app_small_request(did); 261 262 HEADER(stderr, "app_uninitialized_request"); 263 test_app_uninitialized_request(did); 264 265 HEADER(stderr, "app_proto_icmp"); 266 test_app_proto_icmp(did); 267 268 close(did); 269 270 return 0; 271} 272 273