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 }