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 }