1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdarg.h> 30 #include <dhcp_svc_private.h> 31 #include <dhcp_symbol.h> 32 #include <libintl.h> 33 #include <jni.h> 34 35 #include "dd_misc.h" 36 #include "exception.h" 37 38 /* 39 * Note: These must match exactly with the message ids defined in the 40 * bridge ResourceBundle.properties file. 41 */ 42 #define DSVC_EXISTS_EX "dsvc_exists_exception" 43 #define DSVC_ACCESS_EX "dsvc_access_exception" 44 #define DSVC_CREDENTIAL_EX "dsvc_credential_exception" 45 #define DSVC_NO_ENT_EX "dsvc_no_ent_exception" 46 #define DSVC_BUSY_EX "dsvc_busy_exception" 47 #define DSVC_INVALID_ARGS_EX "dsvc_invalid_args_exception" 48 #define DSVC_INTERNAL_EX "dsvc_internal_exception" 49 #define DSVC_UNAVAILABLE_EX "dsvc_unavailable_exception" 50 #define DSVC_COLLISION_EX "dsvc_collision_exception" 51 #define DSVC_UNSUPPORTED_EX "dsvc_unsupported_exception" 52 #define DSVC_NO_MEMORY_EX "dsvc_no_memory_exception" 53 #define DSVC_NO_RESOURCES_EX "dsvc_no_resources_exception" 54 #define DSVC_BAD_RESOURCE_EX "dsvc_bad_resource_exception" 55 #define DSVC_BAD_PATH_EX "dsvc_bad_path_exception" 56 #define DSVC_MOD_VERSION_EX "dsvc_mod_version_exception" 57 #define DSVC_MOD_ERR_EX "dsvc_mod_err_exception" 58 #define DSVC_MOD_LOAD_ERR_EX "dsvc_mod_load_err_exception" 59 #define DSVC_MOD_UNLOAD_ERR_EX "dsvc_mod_unload_err_exception" 60 #define DSVC_MOD_CFG_ERR_EX "dsvc_mod_cfg_err_exception" 61 #define DSVC_SYNCH_ERR_EX "dsvc_synch_err_exception" 62 #define DSVC_NO_LOCKMGR_EX "dsvc_no_lockmgr_exception" 63 #define DSVC_NO_LOCATION_EX "dsvc_no_location_exception" 64 #define DSVC_NO_TABLE_EX "dsvc_no_table_exception" 65 #define DSVC_TABLE_EXISTS_EX "dsvc_table_exists_exception" 66 #define DSVC_BAD_CONVER_EX "dsvc_bad_conver_exception" 67 #define DSVC_INTERNAL_ERROR "dsvc_internal_error" 68 69 #define DSYM_CODE_OUT_OF_RANGE_EX "dsym_code_out_of_range_exception" 70 #define DSYM_EXCEEDS_CLASS_SIZE_EX "dsym_exceeds_class_size_exception" 71 #define DSYM_EXCEEDS_MAX_CLASS_SIZE_EX "dsym_exceeds_max_class_size_exception" 72 #define DSYM_INTERNAL_EX "dsym_internal_exception" 73 #define DSYM_INVALID_CAT_EX "dsym_invalid_cat_exception" 74 #define DSYM_INVALID_TYPE_EX "dsym_invalid_type_exception" 75 #define DSYM_NO_MEMORY_EX "dsym_no_memory_exception" 76 #define DSYM_TOO_FEW_FIELDS_EX "dsym_too_few_fields_exception" 77 #define DSYM_SYNTAX_EX "dsym_syntax_exception" 78 #define DSYM_TOO_MANY_FIELDS_EX "dsym_too_many_fields_exception" 79 #define DSYM_VALUE_OUT_OF_RANGE_EX "dsym_value_out_of_range_exception" 80 81 static void 82 throw_exception(JNIEnv *env, const char *name, const char *msgid, 83 int nargs, ...) 84 { 85 va_list ap; 86 87 jclass class; 88 jmethodID mid; 89 jstring jmsgid = NULL; 90 jobjectArray jlist = NULL; 91 jthrowable throwObj; 92 93 va_start(ap, nargs); 94 95 class = (*env)->FindClass(env, name); 96 if (class == NULL) { 97 /* exception thrown */ 98 va_end(ap); 99 return; 100 } 101 102 mid = (*env)->GetMethodID(env, class, "<init>", 103 "(Ljava/lang/String;[Ljava/lang/Object;)V"); 104 if (mid == NULL) { 105 /* exception thrown */ 106 va_end(ap); 107 return; 108 } 109 110 if (msgid != NULL) { 111 jmsgid = dd_native_to_jstring(env, msgid); 112 if (jmsgid == NULL) { 113 /* exception thrown */ 114 va_end(ap); 115 return; 116 } 117 } 118 119 /* The arguments (if any) are arguments to the message */ 120 if (nargs != 0) { 121 122 jclass strclass; 123 int i; 124 strclass = (*env)->FindClass(env, "java/lang/String"); 125 if (strclass == NULL) { 126 /* exception thrown */ 127 va_end(ap); 128 return; 129 } 130 131 jlist = (*env)->NewObjectArray(env, nargs, strclass, NULL); 132 if (jlist == NULL) { 133 /* exception thrown */ 134 va_end(ap); 135 return; 136 } 137 138 for (i = 0; i < nargs; i++) { 139 jstring jarg; 140 char *arg; 141 142 if ((arg = va_arg(ap, char *)) == 0) { 143 break; 144 } 145 146 jarg = dd_native_to_jstring(env, arg); 147 if (jarg == NULL) { 148 /* exception thrown */ 149 break; 150 } 151 152 (*env)->SetObjectArrayElement(env, jlist, i, jarg); 153 if ((*env)->ExceptionOccurred(env) != NULL) { 154 break; 155 } 156 } 157 158 } 159 160 if ((*env)->ExceptionOccurred(env) == NULL) { 161 throwObj = (jthrowable)(*env)->NewObject(env, class, mid, 162 jmsgid, jlist); 163 if (throwObj == NULL) { 164 /* exception thrown */ 165 va_end(ap); 166 return; 167 } 168 169 /* finally! */ 170 (*env)->Throw(env, throwObj); 171 } 172 173 va_end(ap); 174 } 175 176 /* Throw an exception indicating record or file exists */ 177 static void 178 throw_exists_exception(JNIEnv *env, const char *obj) 179 { 180 throw_exception(env, 181 "com/sun/dhcpmgr/bridge/ExistsException", NULL, 1, obj); 182 } 183 184 /* Throw an exception indicating a table already exists */ 185 static void 186 throw_table_exists_exception(JNIEnv *env, const char *obj) 187 { 188 throw_exception(env, "com/sun/dhcpmgr/bridge/TableExistsException", 189 NULL, 1, obj); 190 } 191 192 /* Throw an exception indicating a table does not exist */ 193 static void 194 throw_notable_exception(JNIEnv *env, const char *obj) 195 { 196 throw_exception(env, 197 "com/sun/dhcpmgr/bridge/NoTableException", NULL, 1, obj); 198 } 199 200 /* Throw a generic bridge exception with a specified message */ 201 void 202 throw_bridge_exception(JNIEnv *env, const char *msgid) 203 { 204 throw_exception(env, 205 "com/sun/dhcpmgr/bridge/BridgeException", msgid, 0); 206 } 207 208 /* Throw an exception as a result of an remove_dd() error */ 209 void 210 throw_remove_dd_exception(JNIEnv *env, int rcode, const char *obj) 211 { 212 switch (rcode) { 213 case DSVC_NO_TABLE: 214 throw_notable_exception(env, obj); 215 break; 216 default: 217 throw_libdhcpsvc_exception(env, rcode); 218 } 219 } 220 221 /* Throw an exception as a result of an open_dd() error */ 222 void 223 throw_open_dd_exception(JNIEnv *env, int rcode, const char *obj) 224 { 225 switch (rcode) { 226 case DSVC_TABLE_EXISTS: 227 throw_table_exists_exception(env, obj); 228 break; 229 case DSVC_NO_TABLE: 230 throw_notable_exception(env, obj); 231 break; 232 default: 233 throw_libdhcpsvc_exception(env, rcode); 234 } 235 } 236 237 /* Throw an exception as a result of an add_dd_entry() error */ 238 void 239 throw_add_dd_entry_exception(JNIEnv *env, int rcode, const char *obj) 240 { 241 switch (rcode) { 242 case DSVC_EXISTS: 243 throw_exists_exception(env, obj); 244 break; 245 default: 246 throw_libdhcpsvc_exception(env, rcode); 247 } 248 } 249 250 /* Throw an exception as a result of an delete_dd_entry() error */ 251 void 252 throw_delete_dd_entry_exception(JNIEnv *env, int rcode, const char *obj) 253 { 254 switch (rcode) { 255 case DSVC_NOENT: 256 throw_noent_exception(env, obj); 257 break; 258 default: 259 throw_libdhcpsvc_exception(env, rcode); 260 } 261 } 262 263 /* Throw an exception as a result of an modify_dd_entry() error */ 264 void 265 throw_modify_dd_entry_exception(JNIEnv *env, int rcode, const char *orig, 266 const char *new) 267 { 268 switch (rcode) { 269 case DSVC_EXISTS: 270 throw_exists_exception(env, new); 271 break; 272 case DSVC_NOENT: 273 throw_noent_exception(env, orig); 274 break; 275 default: 276 throw_libdhcpsvc_exception(env, rcode); 277 } 278 } 279 280 /* Throw an out of memory exception */ 281 void 282 throw_memory_exception(JNIEnv *env) 283 { 284 throw_libdhcpsvc_exception(env, DSVC_NO_MEMORY); 285 } 286 287 /* Throw an exception indicating that there is no DHCP config file */ 288 void 289 throw_no_defaults_exception(JNIEnv *env) 290 { 291 throw_exception(env, 292 "com/sun/dhcpmgr/bridge/NoDefaultsException", NULL, 0); 293 } 294 295 /* Throw an exception indicating record or file does not exist */ 296 void 297 throw_noent_exception(JNIEnv *env, const char *obj) 298 { 299 throw_exception(env, 300 "com/sun/dhcpmgr/bridge/NoEntryException", NULL, 1, obj); 301 } 302 303 /* Throw an exception indicating an invalid resource */ 304 void 305 throw_invalid_resource_exception(JNIEnv *env, const char *obj) 306 { 307 throw_exception(env, "com/sun/dhcpmgr/bridge/InvalidRsrcException", 308 NULL, 1, obj); 309 } 310 311 /* Throw an exception indicating an invalid path */ 312 void 313 throw_invalid_path_exception(JNIEnv *env, const char *obj) 314 { 315 throw_exception(env, "com/sun/dhcpmgr/bridge/InvalidPathException", 316 NULL, 1, obj); 317 } 318 319 /* Throw an exception indicating that the service is not currently running */ 320 void 321 throw_not_running_exception(JNIEnv *env) 322 { 323 throw_exception(env, 324 "com/sun/dhcpmgr/bridge/NotRunningException", NULL, 0); 325 } 326 327 /* Throw exception for a libdhcpsvc error that requires no special treatment */ 328 void 329 throw_libdhcpsvc_exception(JNIEnv *env, int rcode) 330 { 331 const char *msgid; 332 333 switch (rcode) { 334 case DSVC_SUCCESS: 335 break; 336 case DSVC_EXISTS: 337 msgid = DSVC_EXISTS_EX; 338 break; 339 case DSVC_ACCESS: 340 msgid = DSVC_ACCESS_EX; 341 break; 342 case DSVC_NO_CRED: 343 msgid = DSVC_CREDENTIAL_EX; 344 break; 345 case DSVC_NOENT: 346 msgid = DSVC_NO_ENT_EX; 347 break; 348 case DSVC_BUSY: 349 msgid = DSVC_BUSY_EX; 350 break; 351 case DSVC_INVAL: 352 msgid = DSVC_INVALID_ARGS_EX; 353 break; 354 case DSVC_INTERNAL: 355 msgid = DSVC_INTERNAL_EX; 356 break; 357 case DSVC_UNAVAILABLE: 358 msgid = DSVC_UNAVAILABLE_EX; 359 break; 360 case DSVC_COLLISION: 361 msgid = DSVC_COLLISION_EX; 362 break; 363 case DSVC_UNSUPPORTED: 364 msgid = DSVC_UNSUPPORTED_EX; 365 break; 366 case DSVC_NO_MEMORY: 367 msgid = DSVC_NO_MEMORY_EX; 368 break; 369 case DSVC_NO_RESOURCES: 370 msgid = DSVC_NO_RESOURCES_EX; 371 break; 372 case DSVC_BAD_RESOURCE: 373 msgid = DSVC_BAD_RESOURCE_EX; 374 break; 375 case DSVC_BAD_PATH: 376 msgid = DSVC_BAD_PATH_EX; 377 break; 378 case DSVC_MODULE_VERSION: 379 msgid = DSVC_MOD_VERSION_EX; 380 break; 381 case DSVC_MODULE_ERR: 382 msgid = DSVC_MOD_ERR_EX; 383 break; 384 case DSVC_MODULE_LOAD_ERR: 385 msgid = DSVC_MOD_LOAD_ERR_EX; 386 break; 387 case DSVC_MODULE_UNLOAD_ERR: 388 msgid = DSVC_MOD_UNLOAD_ERR_EX; 389 break; 390 case DSVC_MODULE_CFG_ERR: 391 msgid = DSVC_MOD_CFG_ERR_EX; 392 break; 393 case DSVC_SYNCH_ERR: 394 msgid = DSVC_SYNCH_ERR_EX; 395 break; 396 case DSVC_NO_LOCKMGR: 397 msgid = DSVC_NO_LOCKMGR_EX; 398 break; 399 case DSVC_NO_LOCATION: 400 msgid = DSVC_NO_LOCATION_EX; 401 break; 402 case DSVC_BAD_CONVER: 403 msgid = DSVC_BAD_CONVER_EX; 404 break; 405 default: 406 msgid = DSVC_INTERNAL_ERROR; 407 } 408 409 throw_bridge_exception(env, msgid); 410 } 411 412 /* Determine whether an exception is a defaults file doesn't exist exception */ 413 boolean_t 414 is_no_defaults_exception(JNIEnv *env, jthrowable e) 415 { 416 jclass class; 417 boolean_t result = B_FALSE; 418 419 class = (*env)->FindClass(env, 420 "com/sun/dhcpmgr/bridge/NoDefaultsException"); 421 if (class != NULL) { 422 if ((*env)->IsInstanceOf(env, e, class) == JNI_TRUE && 423 e != NULL) { 424 result = B_TRUE; 425 } 426 } 427 428 return (result); 429 } 430 431 /* Throw a symbol parsing error */ 432 /* ARGSUSED [one day we should use the `key' argument in messages] */ 433 void 434 throw_dsym_parser_exception(JNIEnv *env, const char *key, char **fields, 435 int field, dsym_errcode_t rcode) 436 { 437 const char *dsym_exception = "com/sun/dhcpmgr/bridge/DsymException"; 438 439 char ascii_long_1[ULONG_MAX_CHAR + 1]; 440 char ascii_long_2[ULONG_MAX_CHAR + 1]; 441 ushort_t min; 442 ushort_t max; 443 444 switch (rcode) { 445 case DSYM_SUCCESS: 446 break; 447 case DSYM_SYNTAX_ERROR: 448 throw_exception(env, 449 dsym_exception, DSYM_SYNTAX_EX, 1, fields[field]); 450 break; 451 case DSYM_CODE_OUT_OF_RANGE: 452 (void) dsym_get_code_ranges(fields[DSYM_CAT_FIELD], 453 &min, &max, B_TRUE); 454 (void) sprintf(ascii_long_1, "%d", min); 455 (void) sprintf(ascii_long_2, "%d", max); 456 throw_exception(env, dsym_exception, DSYM_CODE_OUT_OF_RANGE_EX, 457 3, fields[DSYM_CAT_FIELD], ascii_long_1, ascii_long_2); 458 break; 459 case DSYM_VALUE_OUT_OF_RANGE: 460 throw_exception(env, dsym_exception, 461 DSYM_VALUE_OUT_OF_RANGE_EX, 1, fields[field]); 462 break; 463 case DSYM_INVALID_CAT: 464 throw_exception(env, dsym_exception, 465 DSYM_INVALID_CAT_EX, 1, fields[DSYM_CAT_FIELD]); 466 break; 467 case DSYM_INVALID_TYPE: 468 throw_exception(env, dsym_exception, 469 DSYM_INVALID_TYPE_EX, 1, fields[DSYM_TYPE_FIELD]); 470 break; 471 case DSYM_EXCEEDS_CLASS_SIZE: 472 (void) sprintf(ascii_long_1, "%d", DSYM_CLASS_SIZE); 473 throw_exception(env, dsym_exception, 474 DSYM_EXCEEDS_CLASS_SIZE_EX, 1, ascii_long_1); 475 break; 476 case DSYM_EXCEEDS_MAX_CLASS_SIZE: 477 (void) sprintf(ascii_long_1, "%d", DSYM_MAX_CLASS_SIZE); 478 throw_exception(env, dsym_exception, 479 DSYM_EXCEEDS_MAX_CLASS_SIZE_EX, 1, ascii_long_1); 480 break; 481 case DSYM_NO_MEMORY: 482 throw_exception(env, dsym_exception, DSYM_NO_MEMORY_EX, 0); 483 break; 484 default: 485 throw_exception(env, dsym_exception, DSYM_INTERNAL_EX, 0); 486 } 487 } 488 489 /* Throw a symbol init parsing error */ 490 void 491 throw_dsym_parser_init_exception(JNIEnv *env, const char *key, 492 dsym_errcode_t rcode) 493 { 494 const char *dsym_exception = "com/sun/dhcpmgr/bridge/DsymException"; 495 496 switch (rcode) { 497 case DSYM_SUCCESS: 498 break; 499 case DSYM_NULL_FIELD: 500 throw_exception(env, 501 dsym_exception, DSYM_TOO_FEW_FIELDS_EX, 1, key); 502 break; 503 case DSYM_TOO_MANY_FIELDS: 504 throw_exception(env, 505 dsym_exception, DSYM_TOO_MANY_FIELDS_EX, 1, key); 506 break; 507 case DSYM_NO_MEMORY: 508 throw_exception(env, dsym_exception, DSYM_NO_MEMORY_EX, 0); 509 break; 510 default: 511 throw_exception(env, dsym_exception, DSYM_INTERNAL_EX, 0); 512 } 513 } 514 515 /* Throw an exception indicating an error in wordexp */ 516 void 517 throw_wordexp_exception(JNIEnv *env, int code) 518 { 519 char buf[UINT64_MAX_CHAR + 1]; 520 521 (void) snprintf(buf, sizeof (buf), "%d", code); 522 throw_exception(env, "com/sun/dhcpmgr/bridge/WordexpException", 523 NULL, 1, buf); 524 }