xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sadm/dhcpmgr/lib/service.c (revision 11590:38f29d9bce75)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*11590SMark.Haywood@Sun.COM  * Common Development and Distribution License (the "License").
6*11590SMark.Haywood@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11590SMark.Haywood@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <wordexp.h>
270Sstevel@tonic-gate #include <string.h>
280Sstevel@tonic-gate #include <malloc.h>
290Sstevel@tonic-gate #include <sys/signal.h>
300Sstevel@tonic-gate #include <libintl.h>
310Sstevel@tonic-gate #include <arpa/inet.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <dhcp_svc_private.h>
340Sstevel@tonic-gate #include <dhcp_svc_confkey.h>
350Sstevel@tonic-gate #include <jni.h>
360Sstevel@tonic-gate #include <libscf.h>
370Sstevel@tonic-gate #include <com_sun_dhcpmgr_bridge_Bridge.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include "exception.h"
400Sstevel@tonic-gate #include "dd_misc.h"
410Sstevel@tonic-gate #include "class_cache.h"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #define	DHCP_SERVER_INST	"svc:/network/dhcp-server:default"
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #define	DHCPD_FNAME	"in.dhcpd"
460Sstevel@tonic-gate #define	CONFOPT_MODE	0644
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate  * Gets called when the library is loaded.
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate /*ARGSUSED*/
520Sstevel@tonic-gate JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM * jvm,void * reserved)530Sstevel@tonic-gate JNI_OnLoad(
540Sstevel@tonic-gate     JavaVM *jvm,
550Sstevel@tonic-gate     void *reserved)
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	JNIEnv *env;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	if ((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_2)) {
600Sstevel@tonic-gate 		return (JNI_ERR);
610Sstevel@tonic-gate 	}
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	init_class_cache();
640Sstevel@tonic-gate 	return (JNI_VERSION_1_2);
650Sstevel@tonic-gate }
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate  * Determine whether an upgrade of the datastore is necessary.
690Sstevel@tonic-gate  */
700Sstevel@tonic-gate /*ARGSUSED*/
710Sstevel@tonic-gate JNIEXPORT jboolean JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_isVersionCurrent(JNIEnv * env,jobject obj)720Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_isVersionCurrent(
730Sstevel@tonic-gate     JNIEnv *env,
740Sstevel@tonic-gate     jobject obj)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate 	dsvc_datastore_t datastore;
770Sstevel@tonic-gate 	int cfgVersion;
780Sstevel@tonic-gate 	int curVersion;
790Sstevel@tonic-gate 	int rcode;
800Sstevel@tonic-gate 	jboolean result = JNI_FALSE;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	/* Get the data store configuration */
830Sstevel@tonic-gate 	if (dd_get_conf_datastore_t(env, &datastore)) {
840Sstevel@tonic-gate 		cfgVersion = datastore.d_conver;
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 		datastore.d_conver = DSVC_CUR_CONVER;
870Sstevel@tonic-gate 		free(datastore.d_location);
880Sstevel@tonic-gate 		datastore.d_location = NULL;
890Sstevel@tonic-gate 		rcode = status_dd(&datastore);
900Sstevel@tonic-gate 		if (rcode != DSVC_SUCCESS) {
910Sstevel@tonic-gate 			throw_libdhcpsvc_exception(env, rcode);
920Sstevel@tonic-gate 		} else {
930Sstevel@tonic-gate 			curVersion = datastore.d_conver;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 			if (curVersion == cfgVersion) {
960Sstevel@tonic-gate 				result = JNI_TRUE;
970Sstevel@tonic-gate 			}
980Sstevel@tonic-gate 		}
990Sstevel@tonic-gate 		dd_free_datastore_t(&datastore);
1000Sstevel@tonic-gate 	}
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	return (result);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /*
1060Sstevel@tonic-gate  * Retrieve the data store object for the specified resource.
1070Sstevel@tonic-gate  */
1080Sstevel@tonic-gate /*ARGSUSED*/
1090Sstevel@tonic-gate JNIEXPORT jobject JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_getDataStore(JNIEnv * env,jobject obj,jstring jresource)1100Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_getDataStore(
1110Sstevel@tonic-gate     JNIEnv *env,
1120Sstevel@tonic-gate     jobject obj,
1130Sstevel@tonic-gate     jstring jresource)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	jclass ds_class;
1160Sstevel@tonic-gate 	jmethodID ds_cons;
1170Sstevel@tonic-gate 	jobject dsObject;
1180Sstevel@tonic-gate 	jboolean avail;
1190Sstevel@tonic-gate 	jint version;
1200Sstevel@tonic-gate 	dsvc_datastore_t datastore;
1210Sstevel@tonic-gate 	char *resource;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	/* Make sure we have the classes & methods we need */
1240Sstevel@tonic-gate 	ds_class = find_class(env, DS_CLASS);
1250Sstevel@tonic-gate 	if (ds_class == NULL) {
1260Sstevel@tonic-gate 		/* exception thrown */
1270Sstevel@tonic-gate 		return (NULL);
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate 	ds_cons = get_methodID(env, ds_class, DS_CONS);
1300Sstevel@tonic-gate 	if (ds_cons == NULL) {
1310Sstevel@tonic-gate 		/* exception thrown */
1320Sstevel@tonic-gate 		return (NULL);
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	/* Retrieve the resource argument */
1360Sstevel@tonic-gate 	if (!dd_jstring_to_UTF(env, jresource, &resource)) {
1370Sstevel@tonic-gate 		/* exception thrown */
1380Sstevel@tonic-gate 		return (NULL);
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	datastore.d_conver = DSVC_CUR_CONVER;
1420Sstevel@tonic-gate 	datastore.d_resource = resource;
1430Sstevel@tonic-gate 	datastore.d_location = NULL;
1440Sstevel@tonic-gate 	avail = JNI_FALSE;
1450Sstevel@tonic-gate 	if (status_dd(&datastore) == DSVC_SUCCESS) {
1460Sstevel@tonic-gate 		avail = JNI_TRUE;
1470Sstevel@tonic-gate 		version = datastore.d_conver;
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	dsObject = (*env)->NewObject(env, ds_class, ds_cons,
151*11590SMark.Haywood@Sun.COM 	    jresource, version, avail);
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	free(resource);
1540Sstevel@tonic-gate 	return (dsObject);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate /*
1580Sstevel@tonic-gate  * Retrieve the list of data stores available for DHCP.  Returns an array of
1590Sstevel@tonic-gate  * DHCP datastore names.
1600Sstevel@tonic-gate  */
1610Sstevel@tonic-gate /*ARGSUSED*/
1620Sstevel@tonic-gate JNIEXPORT jobjectArray JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_getDataStores(JNIEnv * env,jobject obj)1630Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_getDataStores(
1640Sstevel@tonic-gate     JNIEnv *env,
1650Sstevel@tonic-gate     jobject obj)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate 	jclass ds_class;
1680Sstevel@tonic-gate 	jmethodID ds_cons;
1690Sstevel@tonic-gate 	jobjectArray jlist = NULL;
1700Sstevel@tonic-gate 	jobject jobj;
1710Sstevel@tonic-gate 	jstring jstr;
1720Sstevel@tonic-gate 	jboolean avail;
1730Sstevel@tonic-gate 	jint version;
1740Sstevel@tonic-gate 	char **list;
1750Sstevel@tonic-gate 	dsvc_datastore_t datastore;
1760Sstevel@tonic-gate 	int i, len;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	/* Make sure we have the classes & methods we need */
1790Sstevel@tonic-gate 	ds_class = find_class(env, DS_CLASS);
1800Sstevel@tonic-gate 	if (ds_class == NULL) {
1810Sstevel@tonic-gate 		/* exception thrown */
1820Sstevel@tonic-gate 		return (NULL);
1830Sstevel@tonic-gate 	}
1840Sstevel@tonic-gate 	ds_cons = get_methodID(env, ds_class, DS_CONS);
1850Sstevel@tonic-gate 	if (ds_cons == NULL) {
1860Sstevel@tonic-gate 		/* exception thrown */
1870Sstevel@tonic-gate 		return (NULL);
1880Sstevel@tonic-gate 	}
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	/* Get the list */
1910Sstevel@tonic-gate 	list = dd_data_stores(env);
1920Sstevel@tonic-gate 	if ((*env)->ExceptionOccurred(env) != NULL) {
1930Sstevel@tonic-gate 		return (NULL);
1940Sstevel@tonic-gate 	}
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	/* Compute the length of the array, store in len */
1970Sstevel@tonic-gate 	ARRAY_LENGTH(list, len);
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	/* Construct the array */
2000Sstevel@tonic-gate 	jlist = (*env)->NewObjectArray(env, len, ds_class, NULL);
2010Sstevel@tonic-gate 	if (jlist == NULL) {
2020Sstevel@tonic-gate 		/* exception thrown */
2030Sstevel@tonic-gate 		dd_free_data_stores(list);
2040Sstevel@tonic-gate 		return (NULL);
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/* For each store, create an object and add it to the array */
2080Sstevel@tonic-gate 	for (i = 0; i < len; ++i) {
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 		jstr = (*env)->NewStringUTF(env, list[i]);
2110Sstevel@tonic-gate 		if (jstr == NULL) {
2120Sstevel@tonic-gate 			/* exception thrown */
2130Sstevel@tonic-gate 			break;
2140Sstevel@tonic-gate 		}
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 		datastore.d_conver = DSVC_CUR_CONVER;
2170Sstevel@tonic-gate 		datastore.d_resource = list[i];
2180Sstevel@tonic-gate 		datastore.d_location = NULL;
2190Sstevel@tonic-gate 		avail = JNI_FALSE;
2200Sstevel@tonic-gate 		if (status_dd(&datastore) == DSVC_SUCCESS) {
2210Sstevel@tonic-gate 			avail = JNI_TRUE;
2220Sstevel@tonic-gate 			version = datastore.d_conver;
2230Sstevel@tonic-gate 		}
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 		jobj = (*env)->NewObject(env, ds_class, ds_cons,
226*11590SMark.Haywood@Sun.COM 		    jstr, version, avail);
2270Sstevel@tonic-gate 		if (jobj == NULL) {
2280Sstevel@tonic-gate 			/* exception thrown */
2290Sstevel@tonic-gate 			break;
2300Sstevel@tonic-gate 		}
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 		(*env)->SetObjectArrayElement(env, jlist, i, jobj);
2330Sstevel@tonic-gate 		if ((*env)->ExceptionOccurred(env) != NULL) {
2340Sstevel@tonic-gate 			break;
2350Sstevel@tonic-gate 		}
2360Sstevel@tonic-gate 	}
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	dd_free_data_stores(list);
2390Sstevel@tonic-gate 	return (jlist);
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate /*
2430Sstevel@tonic-gate  * Read the config file for DHCP and return its contents as a DhcpdOptions
2440Sstevel@tonic-gate  * object.
2450Sstevel@tonic-gate  */
2460Sstevel@tonic-gate /*ARGSUSED*/
2470Sstevel@tonic-gate JNIEXPORT jobject JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_readDefaults(JNIEnv * env,jobject obj)2480Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_readDefaults(
2490Sstevel@tonic-gate     JNIEnv *env,
2500Sstevel@tonic-gate     jobject obj)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate 	jclass cfg_class;
2530Sstevel@tonic-gate 	jmethodID cfg_cons;
2540Sstevel@tonic-gate 	jmethodID cfg_set;
255*11590SMark.Haywood@Sun.COM 	jobject cfgobj = NULL;
2560Sstevel@tonic-gate 	dhcp_confopt_t *cfgs, *tcfgs;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	/* Make sure we have the classes & methods we need */
2590Sstevel@tonic-gate 	cfg_class = find_class(env, CFG_CLASS);
2600Sstevel@tonic-gate 	if (cfg_class == NULL) {
2610Sstevel@tonic-gate 		/* exception thrown */
2620Sstevel@tonic-gate 		return (NULL);
2630Sstevel@tonic-gate 	}
2640Sstevel@tonic-gate 	cfg_cons = get_methodID(env, cfg_class, CFG_CONS);
2650Sstevel@tonic-gate 	if (cfg_cons == NULL) {
2660Sstevel@tonic-gate 		/* exception thrown */
2670Sstevel@tonic-gate 		return (NULL);
2680Sstevel@tonic-gate 	}
2690Sstevel@tonic-gate 	cfg_set = get_methodID(env, cfg_class, CFG_SET);
2700Sstevel@tonic-gate 	if (cfg_set == NULL) {
2710Sstevel@tonic-gate 		/* exception thrown */
2720Sstevel@tonic-gate 		return (NULL);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	/* Get the data */
2760Sstevel@tonic-gate 	if (read_dsvc_conf(&cfgs) != 0) {
2770Sstevel@tonic-gate 		throw_bridge_exception(env, strerror(errno));
2780Sstevel@tonic-gate 	} else {
2790Sstevel@tonic-gate 		/* Construct returned options object */
2800Sstevel@tonic-gate 		cfgobj = (*env)->NewObject(env, cfg_class, cfg_cons);
2810Sstevel@tonic-gate 		if (cfgobj == NULL) {
2820Sstevel@tonic-gate 			/* exception thrown */
2830Sstevel@tonic-gate 			free_dsvc_conf(cfgs);
2840Sstevel@tonic-gate 			return (NULL);
2850Sstevel@tonic-gate 		}
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		/* Load the option settings into the options object */
2880Sstevel@tonic-gate 		tcfgs = cfgs;
2890Sstevel@tonic-gate 		for (;;) {
2900Sstevel@tonic-gate 			if (cfgs->co_type == DHCP_COMMENT) {
2910Sstevel@tonic-gate 				(*env)->CallVoidMethod(env, cfgobj, cfg_set,
2920Sstevel@tonic-gate 				    (*env)->NewStringUTF(env, cfgs->co_key),
2930Sstevel@tonic-gate 				    (*env)->NewStringUTF(env, ""), JNI_TRUE);
2940Sstevel@tonic-gate 			} else {
2950Sstevel@tonic-gate 				if (cfgs->co_key == NULL) {
2960Sstevel@tonic-gate 					break;
2970Sstevel@tonic-gate 				}
2980Sstevel@tonic-gate 				(*env)->CallVoidMethod(env, cfgobj, cfg_set,
2990Sstevel@tonic-gate 				    (*env)->NewStringUTF(env, cfgs->co_key),
3000Sstevel@tonic-gate 				    (*env)->NewStringUTF(env, cfgs->co_value),
3010Sstevel@tonic-gate 				    JNI_FALSE);
3020Sstevel@tonic-gate 			}
3030Sstevel@tonic-gate 			if ((*env)->ExceptionOccurred(env) != NULL) {
3040Sstevel@tonic-gate 				free_dsvc_conf(tcfgs);
3050Sstevel@tonic-gate 				return (NULL);
3060Sstevel@tonic-gate 			}
3070Sstevel@tonic-gate 			++cfgs;
3080Sstevel@tonic-gate 		}
3090Sstevel@tonic-gate 		free_dsvc_conf(tcfgs);
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 	return (cfgobj);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate /*
3150Sstevel@tonic-gate  * Write the DHCP config file.  Takes a DhcpdOptions object as input
3160Sstevel@tonic-gate  */
3170Sstevel@tonic-gate /*ARGSUSED*/
3180Sstevel@tonic-gate JNIEXPORT void JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_writeDefaults(JNIEnv * env,jobject obj,jobject jcfgs)3190Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_writeDefaults(
3200Sstevel@tonic-gate     JNIEnv *env,
3210Sstevel@tonic-gate     jobject obj,
3220Sstevel@tonic-gate     jobject jcfgs)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate 	jclass cfg_class;
3250Sstevel@tonic-gate 	jmethodID cfg_getall;
3260Sstevel@tonic-gate 	jclass res_class;
3270Sstevel@tonic-gate 	jmethodID res_getkey;
3280Sstevel@tonic-gate 	jmethodID res_getval;
3290Sstevel@tonic-gate 	jmethodID res_iscom;
3300Sstevel@tonic-gate 	jobjectArray resArray;
3310Sstevel@tonic-gate 	jsize reslen;
3320Sstevel@tonic-gate 	jobject jobj, resobj;
3330Sstevel@tonic-gate 	dhcp_confopt_t *cfgs;
3340Sstevel@tonic-gate 	int i;
3350Sstevel@tonic-gate 	jboolean comment;
3360Sstevel@tonic-gate 	const char *tmpstr;
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	/* Make sure we can get at the classes we need */
3390Sstevel@tonic-gate 	cfg_class = find_class(env, CFG_CLASS);
3400Sstevel@tonic-gate 	if (cfg_class == NULL) {
3410Sstevel@tonic-gate 		/* exception thrown */
3420Sstevel@tonic-gate 		return;
3430Sstevel@tonic-gate 	}
3440Sstevel@tonic-gate 	cfg_getall = get_methodID(env, cfg_class, CFG_GETALL);
3450Sstevel@tonic-gate 	if (cfg_getall == NULL) {
3460Sstevel@tonic-gate 		/* exception thrown */
3470Sstevel@tonic-gate 		return;
3480Sstevel@tonic-gate 	}
3490Sstevel@tonic-gate 	res_class = find_class(env, RES_CLASS);
3500Sstevel@tonic-gate 	if (res_class == NULL) {
3510Sstevel@tonic-gate 		/* exception thrown */
3520Sstevel@tonic-gate 		return;
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 	res_getkey = get_methodID(env, res_class, RES_GETKEY);
3550Sstevel@tonic-gate 	res_getval = get_methodID(env, res_class, RES_GETVAL);
3560Sstevel@tonic-gate 	res_iscom = get_methodID(env, res_class, RES_ISCOM);
3570Sstevel@tonic-gate 	if (res_getkey == NULL || res_getval == NULL || res_iscom == NULL) {
3580Sstevel@tonic-gate 		/* exception thrown */
3590Sstevel@tonic-gate 		return;
3600Sstevel@tonic-gate 	}
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	/* Get the resource array from the config object */
3630Sstevel@tonic-gate 	resArray = (*env)->CallObjectMethod(env, jcfgs, cfg_getall);
3640Sstevel@tonic-gate 	if ((*env)->ExceptionOccurred(env) != NULL) {
3650Sstevel@tonic-gate 		return;
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate 	reslen = (*env)->GetArrayLength(env, resArray);
3680Sstevel@tonic-gate 	/* Allocate array to convert into; extra zero'd item to signal end */
3690Sstevel@tonic-gate 	cfgs = calloc(reslen+1, sizeof (dhcp_confopt_t));
3700Sstevel@tonic-gate 	if (cfgs == NULL) {
3710Sstevel@tonic-gate 		throw_memory_exception(env);
3720Sstevel@tonic-gate 		return;
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	/* Now copy data into local array */
3760Sstevel@tonic-gate 	for (i = 0; i < reslen; ++i) {
3770Sstevel@tonic-gate 		jobj = (*env)->GetObjectArrayElement(env, resArray, i);
3780Sstevel@tonic-gate 		if (jobj == NULL) {
3790Sstevel@tonic-gate 			/* exception thrown */
3800Sstevel@tonic-gate 			free_dsvc_conf(cfgs);
3810Sstevel@tonic-gate 			return;
3820Sstevel@tonic-gate 		}
3830Sstevel@tonic-gate 		/* Set record type */
3840Sstevel@tonic-gate 		comment = (*env)->CallBooleanMethod(env, jobj, res_iscom);
3850Sstevel@tonic-gate 		if ((*env)->ExceptionOccurred(env) != NULL) {
3860Sstevel@tonic-gate 			return;
3870Sstevel@tonic-gate 		}
3880Sstevel@tonic-gate 		if (comment == JNI_TRUE) {
3890Sstevel@tonic-gate 			cfgs[i].co_type = DHCP_COMMENT;
3900Sstevel@tonic-gate 		} else {
3910Sstevel@tonic-gate 			cfgs[i].co_type = DHCP_KEY;
3920Sstevel@tonic-gate 		}
3930Sstevel@tonic-gate 		/*
3940Sstevel@tonic-gate 		 * Get the key from the object, convert to a char *,
3950Sstevel@tonic-gate 		 * and then duplicate into the cfgs array so that
3960Sstevel@tonic-gate 		 * free_dsvc_conf can be used correctly.
3970Sstevel@tonic-gate 		 * Do the same thing for the value.
3980Sstevel@tonic-gate 		 */
3990Sstevel@tonic-gate 		resobj = (*env)->CallObjectMethod(env, jobj, res_getkey);
4000Sstevel@tonic-gate 		tmpstr = (*env)->GetStringUTFChars(env, resobj, NULL);
4010Sstevel@tonic-gate 		if (tmpstr == NULL) {
4020Sstevel@tonic-gate 			/* exception thrown */
4030Sstevel@tonic-gate 			free_dsvc_conf(cfgs);
4040Sstevel@tonic-gate 			throw_bridge_exception(env,
405*11590SMark.Haywood@Sun.COM 			    gettext("Error converting key"));
4060Sstevel@tonic-gate 			return;
4070Sstevel@tonic-gate 		}
4080Sstevel@tonic-gate 		cfgs[i].co_key = strdup(tmpstr);
4090Sstevel@tonic-gate 		(*env)->ReleaseStringUTFChars(env, resobj, tmpstr);
4100Sstevel@tonic-gate 		if (cfgs[i].co_key == NULL) {
4110Sstevel@tonic-gate 			/* Out of memory, fail */
4120Sstevel@tonic-gate 			free_dsvc_conf(cfgs);
4130Sstevel@tonic-gate 			throw_memory_exception(env);
4140Sstevel@tonic-gate 			return;
4150Sstevel@tonic-gate 		}
4160Sstevel@tonic-gate 		resobj = (*env)->CallObjectMethod(env, jobj, res_getval);
4170Sstevel@tonic-gate 		tmpstr = (*env)->GetStringUTFChars(env, resobj, NULL);
4180Sstevel@tonic-gate 		if (tmpstr == NULL) {
4190Sstevel@tonic-gate 			free_dsvc_conf(cfgs);
4200Sstevel@tonic-gate 			throw_bridge_exception(env,
421*11590SMark.Haywood@Sun.COM 			    gettext("Error converting value"));
4220Sstevel@tonic-gate 			return;
4230Sstevel@tonic-gate 		}
4240Sstevel@tonic-gate 		cfgs[i].co_value = strdup(tmpstr);
4250Sstevel@tonic-gate 		(*env)->ReleaseStringUTFChars(env, resobj, tmpstr);
4260Sstevel@tonic-gate 		if (cfgs[i].co_value == NULL) {
4270Sstevel@tonic-gate 			/* Out of memory, fail */
4280Sstevel@tonic-gate 			free_dsvc_conf(cfgs);
4290Sstevel@tonic-gate 			throw_memory_exception(env);
4300Sstevel@tonic-gate 			return;
4310Sstevel@tonic-gate 		}
4320Sstevel@tonic-gate 	}
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	/* Now write the new data */
4350Sstevel@tonic-gate 	if (write_dsvc_conf(cfgs, CONFOPT_MODE) != 0) {
4360Sstevel@tonic-gate 		throw_bridge_exception(env, strerror(errno));
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 	free_dsvc_conf(cfgs);
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate /*
4420Sstevel@tonic-gate  * Remove the DHCP config file
4430Sstevel@tonic-gate  */
4440Sstevel@tonic-gate /*ARGSUSED*/
4450Sstevel@tonic-gate JNIEXPORT void JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_removeDefaults(JNIEnv * env,jobject obj)4460Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_removeDefaults(
4470Sstevel@tonic-gate     JNIEnv *env,
4480Sstevel@tonic-gate     jobject obj)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate 	if (delete_dsvc_conf() != 0) {
4510Sstevel@tonic-gate 		throw_bridge_exception(env, strerror(errno));
4520Sstevel@tonic-gate 	}
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate /*
4560Sstevel@tonic-gate  * Start up the daemon.
4570Sstevel@tonic-gate  */
4580Sstevel@tonic-gate /*ARGSUSED*/
4590Sstevel@tonic-gate JNIEXPORT void JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_startup(JNIEnv * env,jobject obj)4600Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_startup(
4610Sstevel@tonic-gate     JNIEnv *env,
4620Sstevel@tonic-gate     jobject obj)
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate 	char *s;
4650Sstevel@tonic-gate 	int ret;
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	/*
4680Sstevel@tonic-gate 	 * We first get the current state of the server according to
4690Sstevel@tonic-gate 	 * svc.startd; if it's "disabled", we can just enable it.
4700Sstevel@tonic-gate 	 * In any other case, we want to send a refresh so that
4710Sstevel@tonic-gate 	 * dependencies are re-evaluated, which will be the case if the
4720Sstevel@tonic-gate 	 * service was marked enabled by the profile, yet the
4730Sstevel@tonic-gate 	 * config file didn't exist to allow it to run.
4740Sstevel@tonic-gate 	 */
4750Sstevel@tonic-gate 	if ((s = smf_get_state(DHCP_SERVER_INST)) != NULL) {
4760Sstevel@tonic-gate 		if (strcmp(SCF_STATE_STRING_DISABLED, s) == 0)
4770Sstevel@tonic-gate 			ret = smf_enable_instance(DHCP_SERVER_INST, 0);
4780Sstevel@tonic-gate 		else
4790Sstevel@tonic-gate 			ret = smf_refresh_instance(DHCP_SERVER_INST);
4800Sstevel@tonic-gate 		free(s);
4810Sstevel@tonic-gate 		if (ret == 0)
4820Sstevel@tonic-gate 			return;
4830Sstevel@tonic-gate 	}
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	/* Something wasn't right, return exception with error from smf */
4860Sstevel@tonic-gate 	throw_bridge_exception(env, scf_strerror(scf_error()));
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate /*
4900Sstevel@tonic-gate  * Shut down the daemon.
4910Sstevel@tonic-gate  */
4920Sstevel@tonic-gate /*ARGSUSED*/
4930Sstevel@tonic-gate JNIEXPORT void JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_shutdown(JNIEnv * env,jobject obj)4940Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_shutdown(
4950Sstevel@tonic-gate     JNIEnv *env,
4960Sstevel@tonic-gate     jobject obj)
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate 	if (smf_disable_instance(DHCP_SERVER_INST, 0) != 0) {
4990Sstevel@tonic-gate 		throw_bridge_exception(env, scf_strerror(scf_error()));
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate /*
5040Sstevel@tonic-gate  * Tell the daemon to re-read the dhcptab.
5050Sstevel@tonic-gate  */
5060Sstevel@tonic-gate /*ARGSUSED*/
5070Sstevel@tonic-gate JNIEXPORT void JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_reload(JNIEnv * env,jobject obj)5080Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_reload(
5090Sstevel@tonic-gate     JNIEnv *env,
5100Sstevel@tonic-gate     jobject obj)
5110Sstevel@tonic-gate {
5120Sstevel@tonic-gate 	int err;
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	if ((err = dd_signal(DHCPD_FNAME, SIGHUP)) != 0) {
5150Sstevel@tonic-gate 		if (err == -1) {
5160Sstevel@tonic-gate 			/* dd_signal couldn't find in.dhcpd running */
5170Sstevel@tonic-gate 			throw_not_running_exception(env);
5180Sstevel@tonic-gate 		} else {
5190Sstevel@tonic-gate 			throw_bridge_exception(env, strerror(err));
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate /*
5250Sstevel@tonic-gate  * Make the resource location.
5260Sstevel@tonic-gate  */
5270Sstevel@tonic-gate /*ARGSUSED*/
5280Sstevel@tonic-gate JNIEXPORT void JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_makeLocation(JNIEnv * env,jobject obj,jobject jdatastore)5290Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_makeLocation(
5300Sstevel@tonic-gate     JNIEnv *env,
5310Sstevel@tonic-gate     jobject obj,
5320Sstevel@tonic-gate     jobject jdatastore)
5330Sstevel@tonic-gate {
5340Sstevel@tonic-gate 	dsvc_datastore_t datastore;
5350Sstevel@tonic-gate 	int rcode;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	/* Create a dsvc_datastore_t using args and DHCP config file */
5380Sstevel@tonic-gate 	if (!dd_make_datastore_t(env, &datastore, jdatastore)) {
5390Sstevel@tonic-gate 		/* exception thrown */
5400Sstevel@tonic-gate 		return;
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	/* If the location does not already exist, go create it. */
5440Sstevel@tonic-gate 	if (status_dd(&datastore) != DSVC_SUCCESS) {
545*11590SMark.Haywood@Sun.COM 		rcode = mklocation_dd(&datastore);
546*11590SMark.Haywood@Sun.COM 		if (rcode != DSVC_SUCCESS) {
547*11590SMark.Haywood@Sun.COM 			throw_libdhcpsvc_exception(env, rcode);
548*11590SMark.Haywood@Sun.COM 		}
5490Sstevel@tonic-gate 	}
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	dd_free_datastore_t(&datastore);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate /*
5550Sstevel@tonic-gate  * Check if the server is running; returns true if so, false if not.
5560Sstevel@tonic-gate  */
5570Sstevel@tonic-gate /*ARGSUSED*/
5580Sstevel@tonic-gate JNIEXPORT jboolean JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_isServerRunning(JNIEnv * env,jobject obj)5590Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_isServerRunning(
5600Sstevel@tonic-gate     JNIEnv *env,
5610Sstevel@tonic-gate     jobject obj)
5620Sstevel@tonic-gate {
5630Sstevel@tonic-gate 	if (dd_getpid(DAEMON_FNAME) != (pid_t)-1) {
5640Sstevel@tonic-gate 		return (JNI_TRUE);
5650Sstevel@tonic-gate 	} else {
5660Sstevel@tonic-gate 		return (JNI_FALSE);
5670Sstevel@tonic-gate 	}
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate /*
5710Sstevel@tonic-gate  * Retrieve the list of interfaces on the system which are candidates for
5720Sstevel@tonic-gate  * use by the DHCP daemon.  Returns an array of IPInterface objects.
5730Sstevel@tonic-gate  */
5740Sstevel@tonic-gate /*ARGSUSED*/
5750Sstevel@tonic-gate JNIEXPORT jobjectArray JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_getInterfaces(JNIEnv * env,jobject obj)5760Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_getInterfaces(
5770Sstevel@tonic-gate     JNIEnv *env,
5780Sstevel@tonic-gate     jobject obj)
5790Sstevel@tonic-gate {
5800Sstevel@tonic-gate 	jclass ipif_class;
5810Sstevel@tonic-gate 	jmethodID ipif_cons;
5820Sstevel@tonic-gate 	jobjectArray jlist = NULL;
5830Sstevel@tonic-gate 	jobject jobj;
5840Sstevel@tonic-gate 	jsize len;
5850Sstevel@tonic-gate 	struct ip_interface **list;
5860Sstevel@tonic-gate 	int i;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	/* Locate the class and constructor we need */
5890Sstevel@tonic-gate 	ipif_class = find_class(env, IPIF_CLASS);
5900Sstevel@tonic-gate 	if (ipif_class == NULL) {
5910Sstevel@tonic-gate 		/* exception thrown */
5920Sstevel@tonic-gate 		return (NULL);
5930Sstevel@tonic-gate 	}
5940Sstevel@tonic-gate 	ipif_cons = get_methodID(env, ipif_class, IPIF_CONS);
5950Sstevel@tonic-gate 	if (ipif_cons == NULL) {
5960Sstevel@tonic-gate 		return (NULL);
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	/* Retrieve interface list */
6000Sstevel@tonic-gate 	list = dd_get_interfaces();
6010Sstevel@tonic-gate 	if (list == NULL) {
6020Sstevel@tonic-gate 		throw_bridge_exception(env,
603*11590SMark.Haywood@Sun.COM 		    gettext("Error in dd_get_interfaces"));
6040Sstevel@tonic-gate 		return (NULL);
6050Sstevel@tonic-gate 	}
6060Sstevel@tonic-gate 	/* Compute length of list */
6070Sstevel@tonic-gate 	ARRAY_LENGTH(list, len);
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	/* Construct the array */
6100Sstevel@tonic-gate 	jlist = (*env)->NewObjectArray(env, len, ipif_class, NULL);
6110Sstevel@tonic-gate 	if (jlist == NULL) {
6120Sstevel@tonic-gate 		/* exception thrown */
6130Sstevel@tonic-gate 		for (i = 0; i < len; i++) {
6140Sstevel@tonic-gate 			free(list[i]);
6150Sstevel@tonic-gate 		}
6160Sstevel@tonic-gate 		free(list);
6170Sstevel@tonic-gate 		return (NULL);
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	/* For each interface, construct an object and add to the array */
6210Sstevel@tonic-gate 	for (i = 0; i < len; ++i) {
6220Sstevel@tonic-gate 		jobj = (*env)->NewObject(env, ipif_class, ipif_cons,
6230Sstevel@tonic-gate 		    (*env)->NewStringUTF(env, list[i]->name),
6240Sstevel@tonic-gate 		    (*env)->NewStringUTF(env, inet_ntoa(list[i]->addr)),
6250Sstevel@tonic-gate 		    (*env)->NewStringUTF(env, inet_ntoa(list[i]->mask)));
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 		if (jobj == NULL) {
6280Sstevel@tonic-gate 			/* exception thrown */
6290Sstevel@tonic-gate 			break;
6300Sstevel@tonic-gate 		}
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 		(*env)->SetObjectArrayElement(env, jlist, i, jobj);
6330Sstevel@tonic-gate 		if ((*env)->ExceptionOccurred(env) != NULL) {
6340Sstevel@tonic-gate 			break;
6350Sstevel@tonic-gate 		}
6360Sstevel@tonic-gate 	}
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
6390Sstevel@tonic-gate 		free(list[i]);
6400Sstevel@tonic-gate 	}
6410Sstevel@tonic-gate 	free(list);
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 	return (jlist);
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate /*
6470Sstevel@tonic-gate  * Parse a line into arguments.
6480Sstevel@tonic-gate  */
6490Sstevel@tonic-gate /*ARGSUSED*/
6500Sstevel@tonic-gate JNIEXPORT jobjectArray JNICALL
Java_com_sun_dhcpmgr_bridge_Bridge_getArguments(JNIEnv * env,jobject obj,jstring jline)6510Sstevel@tonic-gate Java_com_sun_dhcpmgr_bridge_Bridge_getArguments(
6520Sstevel@tonic-gate     JNIEnv *env,
6530Sstevel@tonic-gate     jobject obj,
6540Sstevel@tonic-gate     jstring jline)
6550Sstevel@tonic-gate {
6560Sstevel@tonic-gate 	wordexp_t exp;
6570Sstevel@tonic-gate 	int flags = WRDE_NOCMD;
6580Sstevel@tonic-gate 	char *line;
6590Sstevel@tonic-gate 	jclass str_class;
6600Sstevel@tonic-gate 	jobjectArray jlist = NULL;
6610Sstevel@tonic-gate 	jstring jarg;
6620Sstevel@tonic-gate 	int i, ret;
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	/* Go ahead and get the class for a String class */
6650Sstevel@tonic-gate 	str_class = (*env)->GetObjectClass(env, jline);
6660Sstevel@tonic-gate 	if (str_class == NULL) {
6670Sstevel@tonic-gate 		/* exception thrown */
6680Sstevel@tonic-gate 		return (NULL);
6690Sstevel@tonic-gate 	}
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	/* Retrieve the line argument */
6720Sstevel@tonic-gate 	if (jline != NULL &&
6730Sstevel@tonic-gate 	    (line = dd_jstring_to_native(env, jline)) == NULL) {
6740Sstevel@tonic-gate 		/* exception thrown */
6750Sstevel@tonic-gate 		return (NULL);
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 	/* Retrieve argument list */
6790Sstevel@tonic-gate 	ret = wordexp(line, &exp, flags);
6800Sstevel@tonic-gate 	free(line);
6810Sstevel@tonic-gate 	if (ret != 0) {
6820Sstevel@tonic-gate 		throw_wordexp_exception(env, ret);
6830Sstevel@tonic-gate 		/* Free memory for the one error case where it's allocated */
6840Sstevel@tonic-gate 		if (ret == WRDE_NOSPACE)
6850Sstevel@tonic-gate 			wordfree(&exp);
6860Sstevel@tonic-gate 		return (NULL);
6870Sstevel@tonic-gate 	}
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	/* Construct the array */
6900Sstevel@tonic-gate 	jlist = (*env)->NewObjectArray(env, exp.we_wordc, str_class, NULL);
6910Sstevel@tonic-gate 	if (jlist == NULL) {
6920Sstevel@tonic-gate 		/* exception thrown */
6930Sstevel@tonic-gate 		wordfree(&exp);
6940Sstevel@tonic-gate 		return (NULL);
6950Sstevel@tonic-gate 	}
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 	/* For each argument, create an object and add it to the array */
6980Sstevel@tonic-gate 	for (i = 0; i < exp.we_wordc; i++) {
6990Sstevel@tonic-gate 		jarg = dd_native_to_jstring(env, exp.we_wordv[i]);
7000Sstevel@tonic-gate 		if (jarg == NULL) {
7010Sstevel@tonic-gate 			/* exception thrown */
7020Sstevel@tonic-gate 			break;
7030Sstevel@tonic-gate 		}
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 		(*env)->SetObjectArrayElement(env, jlist, i, jarg);
7060Sstevel@tonic-gate 		if ((*env)->ExceptionOccurred(env) != NULL) {
7070Sstevel@tonic-gate 			break;
7080Sstevel@tonic-gate 		}
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 	wordfree(&exp);
7120Sstevel@tonic-gate 	return (jlist);
7130Sstevel@tonic-gate }
714