1/* 2 * Copyright (c) 2006 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <unistd.h> 30#include <stdlib.h> 31#include <stdio.h> 32#include <stdbool.h> 33#include <errno.h> 34#include <string.h> 35 36// add additional headers needed here. 37 38#include "../libmicro.h" 39#include <membership.h> 40#include <pwd.h> 41#include <uuid/uuid.h> 42 43#if DEBUG 44# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) 45#else 46# define debug(fmt, args...) 47#endif 48 49 50// Correct use case 51// 52// mbr_check_service_membership -E -L -S -W -B 200 -C 10 -r 100 -s "SACL" -u user_prefix 53// 54// libMicro default benchmark run options are "-E -C 200 -L -S -W" 55// 56// -B is batch size: loop iteration per each benchmark run. Needs to match # of 57// real lookups. This is total number of lookups to issue. 58// -C is min sample number: how many benchmark needs to run to get proper sample 59// 1 is mimumum, but you get at least 3 benchmark run 60// samples. Do not set to zero. Default is 200 for most 61// runs in libMicro. 62// -r is the number of total records. 63// -s is SACL string: ie. "ssh" 64// -u user_prefix that preceeds the user number 65 66typedef struct { 67 uuid_t *uuid_list; 68} tsd_t; 69 70// the number of record lookup to issue is covered by standard option optB 71static int optRecords = 100; // the number of total records 72static int optSACL = 0; // option SACL specified? 73 74static char **sacl = NULL; 75static char *default_sacl[] = { "com.apple.access_dsproxy", 76 "com.apple.access_screensharing", 77 "com.apple.access_ssh", 78 ""}; 79static int numSACL = 3; // number of SACLs 80 81 82// This will use local users (local_test_*) 83static char *default_uprefix = "local_test_"; 84 85int 86benchmark_init() 87{ 88 debug("benchmark_init"); 89 (void) sprintf(lm_optstr, "r:s:u:"); 90 91 lm_tsdsize = sizeof(tsd_t); 92 lm_defB = 100; 93 94 (void) sprintf(lm_usage, 95 "\n ------- mbr_check_service_membership specific options (default: *)\n" 96 " [-r total number of records (100*)]\n" 97 " [-s SACL]\n" 98 " [-u user_prefix]\n" 99 "\n" ); 100 return (0); 101} 102 103/* 104 * This is where you parse your lower-case arguments. 105 */ 106int 107benchmark_optswitch(int opt, char *optarg) 108{ 109 debug("benchmark_optswitch"); 110 111 switch (opt) { 112 case 'r': // total number of records. default is 100 113 optRecords = atoi(optarg); 114 debug("optRecords = %d\n", optRecords); 115 break; 116 117 case 's': // SACL 118 if (optSACL) { 119 printf("SACL already specified. Skipping"); 120 break; 121 } 122 sacl = malloc(2 * sizeof(char *)); 123 if (!sacl) { 124 printf("Error: no memory available for strdup\n"); 125 return -1; 126 } 127 sacl[0] = strdup(optarg); 128 sacl[1] = ""; 129 optSACL = 1; 130 numSACL = 1; 131 132 break; 133 134 case 'u': 135 default_uprefix = strdup(optarg); 136 debug("default_uprefix = %s\n", default_uprefix); 137 break; 138 139 default: 140 return -1; 141 } 142 143 return 0; 144} 145 146 147int 148benchmark_initrun() 149{ 150 int i; 151 debug("benchmark_initrun"); 152 153 if (!sacl) { 154 sacl = default_sacl; 155 } 156 157 for (i=0; strcmp(sacl[i], "") && i <= numSACL; i++) { 158 debug("SACL = %s", sacl[i]); 159 } 160 161 return (0); 162} 163 164// Initialize all structures that will be used in benchmark() 165// 1. make local or network node for OD query 166// 2. create user key 167int 168benchmark_initworker(void *tsd) 169{ 170 int i; 171 tsd_t *ts = (tsd_t *)tsd; 172 char *uprefix = default_uprefix; // local user is default 173 char username[30] = ""; 174 struct passwd *info = NULL; 175 176 debug("benchmark_initworker"); 177 178 // create an array of usernames to use in benchmark before their use 179 // realtime generation in benchmark effects performance measurements 180 181 ts->uuid_list = calloc(optRecords, sizeof(uuid_t)); 182 183 for (i = 0; i < optRecords; i++) { 184 185 sprintf(username, "%s%d", uprefix, i+1); 186 info = getpwnam(username); 187 if (!info) { 188 debug ("error converting username %s to uuid", username); 189 exit (1); 190 } 191 192 (void) mbr_uid_to_uuid(info->pw_uid, ts->uuid_list[i]); 193 194#if DEBUG 195 char buf[30]; 196 uid_t uid; 197 int id_type; 198 uuid_unparse(ts->uuid_list[i], buf); 199 mbr_uuid_to_id(ts->uuid_list[i], &uid, &id_type); 200 debug ("username (%s), uid %d, uuid %s, back to uid %d", username, info->pw_uid, buf, uid); 201#endif 202 } 203 204 // if batch size (one benchmark run) is less than the number records, adjust 205 // it to match the number record lookups in one batch run 206 if (optRecords < lm_optB) { 207 lm_optB = optRecords; 208 debug("Reducing batch size to %d to match the record #\n", lm_optB); 209 } 210 211 debug("benchmark_initworker"); 212 return (0); 213} 214 215int 216benchmark(void *tsd, result_t *res) 217{ 218 tsd_t *ts = (tsd_t *)tsd; 219 int i; 220 int err; 221 int isMember=0; 222 char *sacl_chosen; 223 224#ifdef DEBUG 225 uid_t uid; 226 int id_type; 227#endif 228 229 res->re_errors = 0; 230 231 debug("in to benchmark - optB = %i", lm_optB); 232 for (i = 0; i < lm_optB; i++) { 233 234 sacl_chosen = sacl[random() % numSACL]; 235 err = mbr_check_service_membership(ts->uuid_list[i], sacl_chosen, &isMember); 236 237#ifdef DEBUG 238 mbr_uuid_to_id(ts->uuid_list[i], &uid, &id_type); 239 debug ("loop %d: uid %d is %s a member of %s", i, uid, (isMember) ? "" : "not", sacl_chosen); 240#endif 241 242 if (err) { 243 debug("error: %s", strerror(err)); 244 res->re_errors++; 245 } 246 } 247 res->re_count = i; 248 249 return (0); 250} 251 252 253// We need to release all the structures we allocated in benchmark_initworker() 254int 255benchmark_finiworker(void *tsd) 256{ 257 tsd_t *ts = (tsd_t *)tsd; 258 debug("benchmark_result: deallocating structures"); 259 260 free(ts->uuid_list); 261 262 return (0); 263} 264 265int 266benchmark_finirun(void *tsd) 267{ 268 if (optSACL) 269 free(sacl); 270 271 return 0; 272} 273 274char * 275benchmark_result() 276{ 277 static char result = '\0'; 278 debug("benchmark_result"); 279 return (&result); 280} 281 282