xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sadm/dhcpmgr/lib/network.c (revision 0:68f95e015346)
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 *
create_dnrec(JNIEnv * env,jobject dhcpClientRecord)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
create_DhcpClientRecord(JNIEnv * env,dn_rec_t * dnrec)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
getNetIPByName(const char * netname,char * netip)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
createNetwork(JNIEnv * env,const char * network)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
Java_com_sun_dhcpmgr_bridge_Bridge_getNetwork(JNIEnv * env,jobject obj,jstring jnet)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
Java_com_sun_dhcpmgr_bridge_Bridge_getNetworks(JNIEnv * env,jobject obj,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_cvtNetwork(JNIEnv * env,jobject obj,jstring jnet,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_loadNetwork(JNIEnv * env,jobject obj,jstring jnet,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_createDhcpClientRecord(JNIEnv * env,jobject obj,jobject jrec,jstring jnet,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_modifyDhcpClientRecord(JNIEnv * env,jobject obj,jobject joldrec,jobject jnewrec,jstring jnet,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_deleteDhcpClientRecord(JNIEnv * env,jobject obj,jobject jrec,jstring jnet,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_getDhcpClientRecord(JNIEnv * env,jobject obj,jobject jrec,jstring jnet,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_createDhcpNetwork(JNIEnv * env,jobject obj,jstring jnet,jobject jdatastore)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
Java_com_sun_dhcpmgr_bridge_Bridge_deleteDhcpNetwork(JNIEnv * env,jobject obj,jstring jnet,jobject jdatastore)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 }
1103