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) 2001 by Sun Microsystems, Inc.
  24  * All rights reserved.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <stdlib.h>
  30 #include <jni.h>
  31 #include <dhcp_inittab.h>
  32 #include <dhcp_symbol.h>
  33 #include <exception.h>
  34 #include <com_sun_dhcpmgr_bridge_Bridge.h>
  35 #include <dhcp_svc_private.h>
  36 
  37 #include "class_cache.h"
  38 
  39 /*
  40  * Retrieve a list of DHCP options from the dhcp inittab.
  41  */
  42 /*ARGSUSED*/
  43 JNIEXPORT jobjectArray JNICALL
  44 Java_com_sun_dhcpmgr_bridge_Bridge_getInittabOptions(
  45     JNIEnv *env,
  46     jobject obj,
  47     jbyte jcategory) {
  48 
  49         jclass opt_class;
  50         jmethodID opt_cons;
  51         jobjectArray jlist = NULL;
  52         jobject jobj;
  53         jstring jname;
  54         jshort jcode;
  55         jbyte jtype;
  56         jint jgran;
  57         jint jmax;
  58 
  59         uchar_t category;
  60         dhcp_symbol_t *entryptr;
  61         dhcp_symbol_t *list;
  62         dhcp_symbol_t internal;
  63         size_t num;
  64         int i;
  65 
  66         /* Make sure we have the classes & methods we need */
  67         opt_class = find_class(env, OPT_CLASS);
  68         if (opt_class == NULL) {
  69                 /* exception thrown */
  70                 return (NULL);
  71         }
  72         opt_cons = get_methodID(env, opt_class, OPT_CONS);
  73         if (opt_cons == NULL) {
  74                 /* exception thrown */
  75                 return (NULL);
  76         }
  77 
  78         /* Translate the dhcpmgr category to the inittab category */
  79         if (jcategory == DSYM_STANDARD) {
  80                 category = ITAB_CAT_STANDARD | ITAB_CAT_INTERNAL |
  81                     ITAB_CAT_FIELD;
  82         } else {
  83                 category = jcategory;
  84         }
  85 
  86         /* Get the list of options */
  87         list = inittab_load(category, ITAB_CONS_MANAGER, &num);
  88         if (list == NULL) {
  89                 return (NULL);
  90         }
  91 
  92         /* Construct the array */
  93         jlist = (*env)->NewObjectArray(env, num, opt_class, NULL);
  94         if (jlist == NULL) {
  95                 /* exception thrown */
  96                 free(list);
  97                 return (NULL);
  98         }
  99 
 100         /* For each option, create an object and add it to the array */
 101         for (i = 0; i < num; ++i) {
 102 
 103                 /* Verify the entry. Use the internal if necessary. */
 104                 if (inittab_verify(&list[i], &internal) == ITAB_FAILURE) {
 105                         entryptr = &internal;
 106                 } else {
 107                         entryptr = &list[i];
 108                 }
 109 
 110                 jtype = entryptr->ds_type;
 111                 jname = (*env)->NewStringUTF(env, entryptr->ds_name);
 112                 if (jname == NULL) {
 113                         /* exception thrown */
 114                         break;
 115                 }
 116 
 117                 /* HACK. Since the codes for fields can overlap the     */
 118                 /* codes for STANDARD options, we will just set the     */
 119                 /* code to zero and ignore the need for these codes to  */
 120                 /* be unique. We do the same for internal but not       */
 121                 /* for the same reason. For internal we have no need    */
 122                 /* for the actual code and since we expect them to      */
 123                 /* change in the future, we'll just go ahead and        */
 124                 /* set them to zero too.                                */
 125                 if (entryptr->ds_category == DSYM_INTERNAL ||
 126                     entryptr->ds_category == DSYM_FIELD) {
 127                         jcode = (jshort)0;
 128                 } else {
 129                         jcode = entryptr->ds_code;
 130                 }
 131 
 132                 jmax = entryptr->ds_max;
 133                 jgran = entryptr->ds_gran;
 134 
 135                 /* Create an 'Option' */
 136                 jobj = (*env)->NewObject(env, opt_class, opt_cons, jname,
 137                     jcategory, NULL, jcode, jtype, jgran, jmax, NULL,
 138                     JNI_TRUE);
 139                 if (jobj == NULL) {
 140                         /* exception thrown */
 141                         break;
 142                 }
 143 
 144                 (*env)->SetObjectArrayElement(env, jlist, i, jobj);
 145                 if ((*env)->ExceptionOccurred(env) != NULL) {
 146                         break;
 147                 }
 148         }
 149 
 150         free(list);
 151 
 152         return (jlist);
 153 }