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 (c) 1999-2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <string.h> 30 #include <dhcp_svc_private.h> 31 #include <dhcp_svc_confkey.h> 32 #include <libinetutil.h> 33 #include <libintl.h> 34 #include <stdlib.h> 35 #include <ctype.h> 36 #include <malloc.h> 37 #include <netdb.h> 38 #include <arpa/inet.h> 39 #include <jni.h> 40 #include <com_sun_dhcpmgr_bridge_Bridge.h> 41 42 #include "exception.h" 43 #include "dd_misc.h" 44 #include "class_cache.h" 45 46 /* 47 * Create a dn_rec from a DhcpClientRecord. 48 */ 49 static dn_rec_t * 50 create_dnrec(JNIEnv *env, 51 jobject dhcpClientRecord) 52 { 53 jclass dcr_class; 54 55 dn_rec_t *dnrec = NULL; 56 char *str; 57 unsigned int cid_len; 58 59 /* Locate the class we need */ 60 dcr_class = find_class(env, DCR_CLASS); 61 if (dcr_class == NULL) { 62 /* exception thrown */ 63 return (NULL); 64 } 65 66 dnrec = malloc(sizeof (dn_rec_t)); 67 if (dnrec == NULL) { 68 throw_memory_exception(env); 69 return (NULL); 70 } 71 72 /* 73 * Get the cid and the cid_len. 74 */ 75 if (!dd_get_str_attr(env, dcr_class, DCR_GETCID, dhcpClientRecord, 76 &str)) { 77 /* exception thrown */ 78 free_dnrec(dnrec); 79 return (NULL); 80 } 81 cid_len = DN_MAX_CID_LEN; 82 if (hexascii_to_octet(str, strlen(str), dnrec->dn_cid, &cid_len) != 0) { 83 free(str); 84 free_dnrec(dnrec); 85 throw_memory_exception(env); 86 return (NULL); 87 } 88 dnrec->dn_cid_len = cid_len; 89 free(str); 90 91 /* 92 * Get the flags. 93 */ 94 if (!dd_get_str_attr(env, dcr_class, DCR_GETFLAG, dhcpClientRecord, 95 &str)) { 96 /* exception thrown */ 97 free_dnrec(dnrec); 98 return (NULL); 99 } 100 dnrec->dn_flags = atoi(str); 101 free(str); 102 103 /* 104 * Get the client IP. 105 */ 106 if (!dd_get_str_attr(env, dcr_class, DCR_GETCIP, dhcpClientRecord, 107 &str)) { 108 /* exception thrown */ 109 free_dnrec(dnrec); 110 return (NULL); 111 } 112 dnrec->dn_cip.s_addr = ntohl(inet_addr(str)); 113 free(str); 114 115 /* 116 * Get the server IP. 117 */ 118 if (!dd_get_str_attr(env, dcr_class, DCR_GETSIP, dhcpClientRecord, 119 &str)) { 120 /* exception thrown */ 121 free_dnrec(dnrec); 122 return (NULL); 123 } 124 dnrec->dn_sip.s_addr = ntohl(inet_addr(str)); 125 free(str); 126 127 /* 128 * Get the expiration. 129 */ 130 if (!dd_get_str_attr(env, dcr_class, DCR_GETEXP, dhcpClientRecord, 131 &str)) { 132 /* exception thrown */ 133 free_dnrec(dnrec); 134 return (NULL); 135 } 136 dnrec->dn_lease = atol(str); 137 free(str); 138 139 /* 140 * Get the signature. 141 */ 142 if (!dd_get_str_attr(env, dcr_class, DCR_GETSIG, dhcpClientRecord, 143 &str)) { 144 /* exception thrown */ 145 free_dnrec(dnrec); 146 return (NULL); 147 } 148 dnrec->dn_sig = atoll(str); 149 free(str); 150 151 /* 152 * Get the macro. 153 */ 154 if (!dd_get_str_attr(env, dcr_class, DCR_GETMAC, dhcpClientRecord, 155 &str)) { 156 /* exception thrown */ 157 free_dnrec(dnrec); 158 return (NULL); 159 } 160 (void) strlcpy(dnrec->dn_macro, str, sizeof (dnrec->dn_macro)); 161 free(str); 162 163 /* 164 * Get the comment. 165 */ 166 if (!dd_get_str_attr(env, dcr_class, DCR_GETCMT, dhcpClientRecord, 167 &str)) { 168 /* exception thrown */ 169 free_dnrec(dnrec); 170 return (NULL); 171 } 172 (void) strlcpy(dnrec->dn_comment, str, sizeof (dnrec->dn_comment)); 173 free(str); 174 175 return (dnrec); 176 } 177 178 /* 179 * Create a DhcpClientRecord from a dn_rec. 180 */ 181 static jobject 182 create_DhcpClientRecord( 183 JNIEnv *env, 184 dn_rec_t *dnrec) 185 { 186 jclass dcr_class; 187 jmethodID dcr_cons; 188 jobject dhcpClientRecord; 189 struct in_addr tmpaddr; 190 191 char ascii_cid[DN_MAX_CID_LEN * 2 + 1]; 192 char ascii_flags[2 + 1]; 193 char ascii_cip[IPADDR_MAX_CHAR + 1]; 194 char ascii_sip[IPADDR_MAX_CHAR + 1]; 195 char ascii_lease[ULONG_MAX_CHAR + 1]; 196 char ascii_sig[UINT64_MAX_CHAR + 1]; 197 char ascii_macro[DSVC_MAX_MACSYM_LEN + 1]; 198 char ascii_comment[DN_MAX_COMMENT_LEN + 1]; 199 200 uint_t cid_len; 201 int err; 202 203 /* Find the class */ 204 dcr_class = find_class(env, DCR_CLASS); 205 if (dcr_class == NULL) { 206 /* exception thrown */ 207 return (NULL); 208 } 209 210 /* Locate the constructor we need */ 211 dcr_cons = get_methodID(env, dcr_class, DCR_CONS); 212 if (dcr_cons == NULL) { 213 /* exception thrown */ 214 return (NULL); 215 } 216 217 cid_len = DN_MAX_CID_LEN * 2 + 1; 218 err = octet_to_hexascii(dnrec->dn_cid, dnrec->dn_cid_len, ascii_cid, 219 &cid_len); 220 if (err != 0) { 221 throw_bridge_exception(env, strerror(err)); 222 return (NULL); 223 } 224 ascii_cid[cid_len] = '\0'; 225 226 (void) sprintf(ascii_flags, "%02hu", dnrec->dn_flags); 227 228 tmpaddr.s_addr = htonl(dnrec->dn_cip.s_addr); 229 (void) strcpy(ascii_cip, inet_ntoa(tmpaddr)); 230 tmpaddr.s_addr = htonl(dnrec->dn_sip.s_addr); 231 (void) strcpy(ascii_sip, inet_ntoa(tmpaddr)); 232 233 (void) sprintf(ascii_lease, "%d", dnrec->dn_lease); 234 (void) sprintf(ascii_sig, "%lld", dnrec->dn_sig); 235 236 (void) strlcpy(ascii_macro, dnrec->dn_macro, sizeof (ascii_macro)); 237 (void) strlcpy(ascii_comment, dnrec->dn_comment, 238 sizeof (ascii_comment)); 239 240 dhcpClientRecord = (*env)->NewObject(env, dcr_class, dcr_cons, 241 (*env)->NewStringUTF(env, ascii_cid), 242 (*env)->NewStringUTF(env, ascii_flags), 243 (*env)->NewStringUTF(env, ascii_cip), 244 (*env)->NewStringUTF(env, ascii_sip), 245 (*env)->NewStringUTF(env, ascii_lease), 246 (*env)->NewStringUTF(env, ascii_macro), 247 (*env)->NewStringUTF(env, ascii_comment), 248 (*env)->NewStringUTF(env, ascii_sig)); 249 250 return (dhcpClientRecord); 251 } 252 253 /* 254 * Given a network name, find it's IP address. 255 */ 256 static boolean_t 257 getNetIPByName(const char *netname, char *netip) { 258 259 struct netent *ne; 260 ulong_t addr; 261 boolean_t result = B_FALSE; 262 263 if ((ne = getnetbyname(netname)) != NULL && 264 ne->n_addrtype == AF_INET) { 265 266 int i; 267 ulong_t tl; 268 int count; 269 270 for (i = 0, tl = (ulong_t)0xff000000, count = 0; 271 i < 4; i++, tl >>= 8) { 272 273 if ((ne->n_net & tl) == 0) 274 count += 8; 275 else 276 break; 277 } 278 279 addr = ne->n_net << count; 280 (void) sprintf(netip, "%ld.%ld.%ld.%ld", 281 ((addr & 0xff000000) >> 24), ((addr & 0x00ff0000) >> 16), 282 ((addr & 0x0000ff00) >> 8), (addr & 0x000000ff)); 283 284 result = B_TRUE; 285 } 286 287 return (result); 288 } 289 290 /* 291 * Create a Network object for a network IP address. 292 */ 293 static jobject 294 createNetwork( 295 JNIEnv *env, 296 const char *network) 297 { 298 jclass net_class; 299 jmethodID net_cons; 300 jobject net; 301 302 struct in_addr addr; 303 struct in_addr mask; 304 jstring jstr; 305 306 /* Locate the class and methods we need */ 307 net_class = find_class(env, NET_CLASS); 308 if (net_class == NULL) { 309 /* exception thrown */ 310 return (NULL); 311 } 312 net_cons = get_methodID(env, net_class, NET_CONS); 313 if (net_cons == NULL) { 314 /* exception thrown */ 315 return (NULL); 316 } 317 318 addr.s_addr = ntohl(inet_addr(network)); 319 get_netmask4(&addr, &mask); 320 321 jstr = (*env)->NewStringUTF(env, network); 322 if (jstr == NULL) { 323 /* exception thrown */ 324 return (NULL); 325 } 326 327 net = (*env)->NewObject(env, net_class, net_cons, jstr, mask.s_addr); 328 329 return (net); 330 } 331 332 333 /* 334 * Get the Network object for the network argument. 335 */ 336 /*ARGSUSED*/ 337 JNIEXPORT jobject JNICALL 338 Java_com_sun_dhcpmgr_bridge_Bridge_getNetwork( 339 JNIEnv *env, 340 jobject obj, 341 jstring jnet) 342 { 343 344 jobject netObj; 345 char *net; 346 347 char *netip = NULL; 348 char ascii_ip[IPADDR_MAX_CHAR + 1]; 349 350 /* Retrieve the net argument */ 351 if (!dd_jstring_to_UTF(env, jnet, &net)) { 352 /* exception thrown */ 353 return (NULL); 354 } 355 356 /* 357 * If net looks like an IP address, assume it is, 358 * otherwise go get its IP 359 */ 360 if (!isdigit(*net)) { 361 if (getNetIPByName(net, ascii_ip)) { 362 netip = ascii_ip; 363 } 364 } else { 365 netip = net; 366 } 367 368 /* If we could not find an IP for net, then return NULL object */ 369 if (netip == NULL) { 370 free(net); 371 return (NULL); 372 } 373 374 /* Create a Network object */ 375 netObj = createNetwork(env, netip); 376 if (netObj == NULL) { 377 /* exception thrown */ 378 free(net); 379 return (NULL); 380 } 381 382 /* free up resources */ 383 free(net); 384 385 /* return the object */ 386 return (netObj); 387 } 388 389 /* 390 * List the networks currently under DHCP management. Return as an array 391 * of Network objects including the subnet mask for each network. 392 */ 393 /*ARGSUSED*/ 394 JNIEXPORT jobjectArray JNICALL 395 Java_com_sun_dhcpmgr_bridge_Bridge_getNetworks( 396 JNIEnv *env, 397 jobject obj, 398 jobject jdatastore) 399 { 400 jclass net_class; 401 jobjectArray jlist = NULL; 402 jobject net; 403 uint32_t count; 404 char **list = NULL; 405 dsvc_datastore_t datastore; 406 int rcode; 407 int i; 408 409 /* Locate the class. */ 410 net_class = find_class(env, NET_CLASS); 411 if (net_class == NULL) { 412 /* exception thrown */ 413 return (NULL); 414 } 415 416 /* Create a dsvc_datastore_t using args and DHCP config settings */ 417 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 418 /* exception thrown */ 419 return (NULL); 420 } 421 422 /* Get the list of network tables */ 423 rcode = list_dd(&datastore, DSVC_DHCPNETWORK, &list, &count); 424 425 dd_free_datastore_t(&datastore); 426 427 if (rcode != DSVC_SUCCESS) { 428 throw_libdhcpsvc_exception(env, rcode); 429 return (NULL); 430 } 431 432 /* Construct the array */ 433 jlist = (*env)->NewObjectArray(env, count, net_class, NULL); 434 if (jlist == NULL) { 435 /* exception thrown */ 436 for (i = 0; i < count; i++) { 437 free(list[i]); 438 } 439 free(list); 440 return (NULL); 441 } 442 443 /* For each network, create an object and add it to the array */ 444 for (i = 0; i < count; i++) { 445 net = createNetwork(env, list[i]); 446 if (net == NULL) { 447 /* exception thrown */ 448 break; 449 } 450 451 (*env)->SetObjectArrayElement(env, jlist, i, net); 452 if ((*env)->ExceptionOccurred(env) != NULL) { 453 break; 454 } 455 } 456 457 /* 458 * Free the list now. 459 */ 460 for (i = 0; i < count; i++) { 461 free(list[i]); 462 } 463 free(list); 464 465 return (jlist); 466 } 467 468 /* 469 * Use the current datastore to create a network table in a new datastore. 470 */ 471 /*ARGSUSED*/ 472 JNIEXPORT void JNICALL 473 Java_com_sun_dhcpmgr_bridge_Bridge_cvtNetwork( 474 JNIEnv *env, 475 jobject obj, 476 jstring jnet, 477 jobject jdatastore) 478 { 479 dn_rec_t record; 480 dn_rec_list_t *recordList; 481 dn_rec_list_t *originalList = NULL; 482 uint32_t query; 483 uint32_t count = 0; 484 struct in_addr tmpaddr; 485 char ascii_cip[IPADDR_MAX_CHAR + 1]; 486 487 dsvc_handle_t curHandle; 488 dsvc_handle_t newHandle; 489 dsvc_datastore_t curDatastore; 490 dsvc_datastore_t newDatastore; 491 492 char *net; 493 int rcode; 494 int i; 495 496 /* Get the current data store configuration */ 497 if (!dd_get_conf_datastore_t(env, &curDatastore)) { 498 /* exception thrown */ 499 return; 500 } 501 502 /* Make a "new" dsvc_datastore_t */ 503 if (!dd_make_datastore_t(env, &newDatastore, jdatastore)) { 504 /* exception thrown */ 505 dd_free_datastore_t(&curDatastore); 506 return; 507 } 508 509 /* Retrieve the net argument */ 510 if (!dd_jstring_to_UTF(env, jnet, &net)) { 511 /* exception thrown */ 512 dd_free_datastore_t(&curDatastore); 513 dd_free_datastore_t(&newDatastore); 514 return; 515 } 516 517 /* Open the current network table */ 518 rcode = open_dd(&curHandle, &curDatastore, DSVC_DHCPNETWORK, net, 519 DSVC_READ); 520 521 dd_free_datastore_t(&curDatastore); 522 if (rcode != DSVC_SUCCESS) { 523 throw_open_dd_exception(env, rcode, net); 524 dd_free_datastore_t(&newDatastore); 525 free(net); 526 return; 527 } 528 529 /* Open the new network table */ 530 rcode = open_dd(&newHandle, &newDatastore, DSVC_DHCPNETWORK, net, 531 DSVC_CREATE | DSVC_READ | DSVC_WRITE); 532 533 dd_free_datastore_t(&newDatastore); 534 if (rcode != DSVC_SUCCESS) { 535 throw_open_dd_exception(env, rcode, net); 536 (void) close_dd(&curHandle); 537 free(net); 538 return; 539 } 540 free(net); 541 542 /* Get the records */ 543 DSVC_QINIT(query); 544 rcode = lookup_dd(curHandle, B_FALSE, query, -1, &record, 545 (void**)&recordList, &count); 546 547 (void) close_dd(&curHandle); 548 if (rcode != DSVC_SUCCESS) { 549 throw_libdhcpsvc_exception(env, rcode); 550 (void) close_dd(&newHandle); 551 return; 552 } 553 554 if (count != 0) { 555 originalList = recordList; 556 } 557 558 /* For each row, write client record to new table */ 559 for (i = 0; i < count; i++) { 560 /* Now add the record */ 561 rcode = add_dd_entry(newHandle, recordList->dnl_rec); 562 563 if (rcode != DSVC_SUCCESS) { 564 tmpaddr.s_addr = 565 htonl(recordList->dnl_rec->dn_cip.s_addr); 566 (void) strcpy(ascii_cip, inet_ntoa(tmpaddr)); 567 throw_add_dd_entry_exception(env, rcode, ascii_cip); 568 break; 569 } 570 571 recordList = recordList->dnl_next; 572 } 573 574 (void) close_dd(&newHandle); 575 576 if (originalList != NULL) { 577 free_dnrec_list(originalList); 578 } 579 } 580 581 /* 582 * Retrieve all of the records in a particular network table. Returns an 583 * array of DhcpClientRecord. 584 */ 585 /*ARGSUSED*/ 586 JNIEXPORT jobjectArray JNICALL 587 Java_com_sun_dhcpmgr_bridge_Bridge_loadNetwork( 588 JNIEnv *env, 589 jobject obj, 590 jstring jnet, 591 jobject jdatastore) 592 { 593 jclass dcr_class; 594 jobjectArray jlist = NULL; 595 jobject dhcpClientRecord; 596 int i; 597 598 dsvc_handle_t handle; 599 dsvc_datastore_t datastore; 600 601 dn_rec_t record; 602 dn_rec_list_t *recordList = NULL; 603 dn_rec_list_t *originalList = NULL; 604 uint32_t query; 605 uint32_t count = 0; 606 607 char *net; 608 int rcode; 609 610 /* Locate the class and constructor we need */ 611 dcr_class = find_class(env, DCR_CLASS); 612 if (dcr_class == NULL) { 613 /* exception thrown */ 614 return (NULL); 615 } 616 617 /* Create a dsvc_datastore_t using args and DHCP config settings */ 618 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 619 /* exception thrown */ 620 return (NULL); 621 } 622 623 /* Retrieve the net argument */ 624 if (!dd_jstring_to_UTF(env, jnet, &net)) { 625 /* exception thrown */ 626 dd_free_datastore_t(&datastore); 627 return (NULL); 628 } 629 630 rcode = open_dd(&handle, &datastore, DSVC_DHCPNETWORK, net, DSVC_READ); 631 632 dd_free_datastore_t(&datastore); 633 if (rcode != DSVC_SUCCESS) { 634 throw_open_dd_exception(env, rcode, net); 635 free(net); 636 return (NULL); 637 } 638 free(net); 639 640 /* Get the records */ 641 DSVC_QINIT(query); 642 rcode = lookup_dd(handle, B_FALSE, query, -1, &record, 643 (void**)&recordList, &count); 644 645 (void) close_dd(&handle); 646 if (rcode != DSVC_SUCCESS) { 647 throw_libdhcpsvc_exception(env, rcode); 648 return (NULL); 649 } 650 651 /* Save original pointer so we can free it correctly at end */ 652 originalList = recordList; 653 654 /* Construct the array */ 655 jlist = (*env)->NewObjectArray(env, count, dcr_class, NULL); 656 if (jlist == NULL) { 657 /* exception thrown */ 658 if (originalList != NULL) { 659 free_dnrec_list(originalList); 660 } 661 return (NULL); 662 } 663 664 /* For each client, create an object and add it to the array */ 665 for (i = 0; i < count; i++) { 666 dhcpClientRecord = create_DhcpClientRecord(env, 667 recordList->dnl_rec); 668 if (dhcpClientRecord == NULL) { 669 /* exception thrown */ 670 break; 671 } 672 recordList = recordList->dnl_next; 673 674 (*env)->SetObjectArrayElement(env, jlist, i, dhcpClientRecord); 675 if ((*env)->ExceptionOccurred(env) != NULL) { 676 break; 677 } 678 } 679 680 if (originalList != NULL) { 681 free_dnrec_list(originalList); 682 } 683 684 return (jlist); 685 } 686 687 /* 688 * Create a client record 689 */ 690 /*ARGSUSED*/ 691 JNIEXPORT void JNICALL 692 Java_com_sun_dhcpmgr_bridge_Bridge_createDhcpClientRecord( 693 JNIEnv *env, 694 jobject obj, 695 jobject jrec, 696 jstring jnet, 697 jobject jdatastore) 698 { 699 dsvc_handle_t handle; 700 dsvc_datastore_t datastore; 701 dn_rec_t *dnrec; 702 char *net; 703 int rcode; 704 705 struct in_addr tmpaddr; 706 char ascii_cip[IPADDR_MAX_CHAR + 1]; 707 708 /* Create a dsvc_datastore_t using args and DHCP config settings */ 709 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 710 /* exception thrown */ 711 return; 712 } 713 714 /* Retrieve the net argument */ 715 if (!dd_jstring_to_UTF(env, jnet, &net)) { 716 /* exception thrown */ 717 dd_free_datastore_t(&datastore); 718 return; 719 } 720 721 dnrec = create_dnrec(env, jrec); 722 if (dnrec == NULL) { 723 /* exception thrown */ 724 dd_free_datastore_t(&datastore); 725 free(net); 726 return; 727 } 728 729 rcode = open_dd(&handle, &datastore, DSVC_DHCPNETWORK, 730 net, DSVC_WRITE); 731 732 dd_free_datastore_t(&datastore); 733 if (rcode != DSVC_SUCCESS) { 734 throw_open_dd_exception(env, rcode, net); 735 free(net); 736 free_dnrec(dnrec); 737 return; 738 } 739 free(net); 740 741 /* Now add the record */ 742 rcode = add_dd_entry(handle, dnrec); 743 744 (void) close_dd(&handle); 745 if (rcode != DSVC_SUCCESS) { 746 tmpaddr.s_addr = htonl(dnrec->dn_cip.s_addr); 747 (void) strcpy(ascii_cip, inet_ntoa(tmpaddr)); 748 throw_add_dd_entry_exception(env, rcode, ascii_cip); 749 } 750 751 free_dnrec(dnrec); 752 753 } 754 755 /* 756 * Modify a client record. Supply both old and new record and table in 757 * which they're to be modified. 758 */ 759 /*ARGSUSED*/ 760 JNIEXPORT void JNICALL 761 Java_com_sun_dhcpmgr_bridge_Bridge_modifyDhcpClientRecord( 762 JNIEnv *env, 763 jobject obj, 764 jobject joldrec, 765 jobject jnewrec, 766 jstring jnet, 767 jobject jdatastore) 768 { 769 dsvc_handle_t handle; 770 dsvc_datastore_t datastore; 771 dn_rec_t *dnoldrec; 772 dn_rec_t *dnnewrec; 773 774 struct in_addr tmpaddr; 775 char old_ascii_cip[IPADDR_MAX_CHAR + 1]; 776 char new_ascii_cip[IPADDR_MAX_CHAR + 1]; 777 778 char *net; 779 int rcode; 780 781 /* Create a dsvc_datastore_t using args and DHCP config settings */ 782 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 783 /* exception thrown */ 784 return; 785 } 786 787 /* Retrieve the net argument */ 788 if (!dd_jstring_to_UTF(env, jnet, &net)) { 789 /* exception thrown */ 790 dd_free_datastore_t(&datastore); 791 return; 792 } 793 794 dnoldrec = create_dnrec(env, joldrec); 795 if (dnoldrec == NULL) { 796 /* exception thrown */ 797 dd_free_datastore_t(&datastore); 798 free(net); 799 return; 800 } 801 802 dnnewrec = create_dnrec(env, jnewrec); 803 if (dnnewrec == NULL) { 804 /* exception thrown */ 805 dd_free_datastore_t(&datastore); 806 free(net); 807 free_dnrec(dnoldrec); 808 return; 809 } 810 811 rcode = open_dd(&handle, &datastore, DSVC_DHCPNETWORK, 812 net, DSVC_WRITE); 813 814 dd_free_datastore_t(&datastore); 815 if (rcode != DSVC_SUCCESS) { 816 throw_open_dd_exception(env, rcode, net); 817 free(net); 818 free_dnrec(dnoldrec); 819 free_dnrec(dnnewrec); 820 return; 821 } 822 free(net); 823 824 /* Modify the record */ 825 rcode = modify_dd_entry(handle, dnoldrec, dnnewrec); 826 827 (void) close_dd(&handle); 828 if (rcode != DSVC_SUCCESS) { 829 tmpaddr.s_addr = htonl(dnoldrec->dn_cip.s_addr); 830 (void) strcpy(old_ascii_cip, inet_ntoa(tmpaddr)); 831 tmpaddr.s_addr = htonl(dnnewrec->dn_cip.s_addr); 832 (void) strcpy(new_ascii_cip, inet_ntoa(tmpaddr)); 833 throw_modify_dd_entry_exception(env, rcode, old_ascii_cip, 834 new_ascii_cip); 835 } 836 837 free_dnrec(dnnewrec); 838 free_dnrec(dnoldrec); 839 } 840 841 /* 842 * Delete a client record 843 */ 844 /*ARGSUSED*/ 845 JNIEXPORT void JNICALL 846 Java_com_sun_dhcpmgr_bridge_Bridge_deleteDhcpClientRecord( 847 JNIEnv *env, 848 jobject obj, 849 jobject jrec, 850 jstring jnet, 851 jobject jdatastore) 852 { 853 dsvc_handle_t handle; 854 dsvc_datastore_t datastore; 855 dn_rec_t *dnrec; 856 857 struct in_addr tmpaddr; 858 char ascii_cip[IPADDR_MAX_CHAR + 1]; 859 860 char *net; 861 int rcode; 862 863 /* Create a dsvc_datastore_t using args and DHCP config settings */ 864 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 865 /* exception thrown */ 866 return; 867 } 868 869 /* Retrieve the net argument */ 870 if (!dd_jstring_to_UTF(env, jnet, &net)) { 871 /* exception thrown */ 872 dd_free_datastore_t(&datastore); 873 return; 874 } 875 876 dnrec = create_dnrec(env, jrec); 877 if (dnrec == NULL) { 878 /* exception thrown */ 879 dd_free_datastore_t(&datastore); 880 free(net); 881 return; 882 } 883 884 rcode = open_dd(&handle, &datastore, DSVC_DHCPNETWORK, 885 net, DSVC_WRITE); 886 887 dd_free_datastore_t(&datastore); 888 if (rcode != DSVC_SUCCESS) { 889 throw_open_dd_exception(env, rcode, net); 890 free(net); 891 free_dnrec(dnrec); 892 return; 893 } 894 free(net); 895 896 /* Delete the record */ 897 rcode = delete_dd_entry(handle, dnrec); 898 899 (void) close_dd(&handle); 900 if (rcode != DSVC_SUCCESS) { 901 tmpaddr.s_addr = htonl(dnrec->dn_cip.s_addr); 902 (void) strcpy(ascii_cip, inet_ntoa(tmpaddr)); 903 throw_delete_dd_entry_exception(env, rcode, ascii_cip); 904 } 905 906 free_dnrec(dnrec); 907 } 908 909 /* 910 * Retrieve a client record 911 */ 912 /*ARGSUSED*/ 913 JNIEXPORT jobject JNICALL 914 Java_com_sun_dhcpmgr_bridge_Bridge_getDhcpClientRecord( 915 JNIEnv *env, 916 jobject obj, 917 jobject jrec, 918 jstring jnet, 919 jobject jdatastore) 920 { 921 jclass dcr_class; 922 jmethodID dcr_getcip; 923 jobject dhcpClientRecord = NULL; 924 jstring jaddr; 925 926 dsvc_handle_t handle; 927 dsvc_datastore_t datastore; 928 929 char *net; 930 char *addr; 931 int rcode; 932 933 dn_rec_t record; 934 dn_rec_list_t *recordList; 935 uint32_t query; 936 uint32_t count = 0; 937 938 /* Find the class and method we need */ 939 dcr_class = find_class(env, DCR_CLASS); 940 if (dcr_class == NULL) { 941 /* exception thrown */ 942 return (NULL); 943 } 944 945 /* Locate the method id we need */ 946 dcr_getcip = get_methodID(env, dcr_class, DCR_GETCIP); 947 if (dcr_getcip == NULL) { 948 /* exception thrown */ 949 return (NULL); 950 } 951 952 /* Get the address from the record */ 953 jaddr = (*env)->CallObjectMethod(env, jrec, dcr_getcip); 954 if (jaddr == NULL) { 955 /* exception thrown */ 956 return (NULL); 957 } 958 959 /* Create a dsvc_datastore_t using args and DHCP config settings */ 960 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 961 /* exception thrown */ 962 return (NULL); 963 } 964 965 /* Retrieve the net argument */ 966 if (!dd_jstring_to_UTF(env, jnet, &net)) { 967 /* exception thrown */ 968 dd_free_datastore_t(&datastore); 969 return (NULL); 970 } 971 972 /* Convert the address to a native string */ 973 if (!dd_jstring_to_UTF(env, jaddr, &addr)) { 974 /* exception thrown */ 975 throw_memory_exception(env); 976 dd_free_datastore_t(&datastore); 977 free(net); 978 return (NULL); 979 } 980 981 rcode = open_dd(&handle, &datastore, DSVC_DHCPNETWORK, net, DSVC_READ); 982 983 dd_free_datastore_t(&datastore); 984 if (rcode != DSVC_SUCCESS) { 985 throw_open_dd_exception(env, rcode, net); 986 free(addr); 987 free(net); 988 return (NULL); 989 } 990 free(net); 991 992 /* Get the record */ 993 DSVC_QINIT(query); 994 DSVC_QEQ(query, DN_QCIP); 995 record.dn_cip.s_addr = ntohl(inet_addr(addr)); 996 997 rcode = lookup_dd(handle, B_FALSE, query, 1, &record, 998 (void **)&recordList, &count); 999 1000 (void) close_dd(&handle); 1001 if (rcode == DSVC_SUCCESS) { 1002 if (count == 1) { 1003 dhcpClientRecord = create_DhcpClientRecord(env, 1004 recordList->dnl_rec); 1005 free_dnrec_list(recordList); 1006 } else { 1007 throw_noent_exception(env, addr); 1008 } 1009 } else { 1010 throw_libdhcpsvc_exception(env, rcode); 1011 } 1012 1013 free(addr); 1014 1015 1016 return (dhcpClientRecord); 1017 } 1018 1019 /* 1020 * Create a network table. 1021 */ 1022 /*ARGSUSED*/ 1023 JNIEXPORT void JNICALL 1024 Java_com_sun_dhcpmgr_bridge_Bridge_createDhcpNetwork( 1025 JNIEnv *env, 1026 jobject obj, 1027 jstring jnet, 1028 jobject jdatastore) 1029 { 1030 dsvc_handle_t handle; 1031 dsvc_datastore_t datastore; 1032 char *net; 1033 int rcode; 1034 1035 /* Create a dsvc_datastore_t using args and DHCP config settings */ 1036 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 1037 /* exception thrown */ 1038 return; 1039 } 1040 1041 /* Retrieve the net argument */ 1042 if (!dd_jstring_to_UTF(env, jnet, &net)) { 1043 /* exception thrown */ 1044 dd_free_datastore_t(&datastore); 1045 return; 1046 } 1047 1048 rcode = open_dd(&handle, &datastore, DSVC_DHCPNETWORK, net, 1049 DSVC_CREATE | DSVC_READ | DSVC_WRITE); 1050 1051 dd_free_datastore_t(&datastore); 1052 1053 /* 1054 * If open was successful, then close. Otherwise, if unsuccessful 1055 * opening table, then map error to exception. 1056 */ 1057 if (rcode == DSVC_SUCCESS) { 1058 (void) close_dd(&handle); 1059 } else { 1060 throw_open_dd_exception(env, rcode, net); 1061 } 1062 1063 free(net); 1064 } 1065 1066 /* 1067 * Delete a network table. 1068 */ 1069 /*ARGSUSED*/ 1070 JNIEXPORT void JNICALL 1071 Java_com_sun_dhcpmgr_bridge_Bridge_deleteDhcpNetwork( 1072 JNIEnv *env, 1073 jobject obj, 1074 jstring jnet, 1075 jobject jdatastore) 1076 { 1077 dsvc_datastore_t datastore; 1078 char *net; 1079 int rcode; 1080 1081 /* Create a dsvc_datastore_t using args and DHCP config settings */ 1082 if (!dd_make_datastore_t(env, &datastore, jdatastore)) { 1083 /* exception thrown */ 1084 return; 1085 } 1086 1087 /* Retrieve the net argument */ 1088 if (!dd_jstring_to_UTF(env, jnet, &net)) { 1089 /* exception thrown */ 1090 dd_free_datastore_t(&datastore); 1091 return; 1092 } 1093 1094 rcode = remove_dd(&datastore, DSVC_DHCPNETWORK, net); 1095 1096 dd_free_datastore_t(&datastore); 1097 if (rcode != DSVC_SUCCESS) { 1098 throw_remove_dd_exception(env, rcode, net); 1099 } 1100 1101 free(net); 1102 }