diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libdhcputil | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libdhcputil')
22 files changed, 3652 insertions, 0 deletions
diff --git a/usr/src/lib/libdhcputil/Makefile b/usr/src/lib/libdhcputil/Makefile new file mode 100644 index 0000000000..eebf93f7df --- /dev/null +++ b/usr/src/lib/libdhcputil/Makefile @@ -0,0 +1,74 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include $(SRC)/lib/Makefile.lib + +LOCHDRS = dhcp_inittab.h dhcp_symbol.h dhcpmsg.h +COMHDRS = dhcp_impl.h dhcp_symbol_common.h +HDRS = $(LOCHDRS) $(COMHDRS) +LOCHDRDIR = common +COMHDRDIR = $(SRC)/common/net/dhcp +HDRDIR = $(LOCHDRDIR) +SUBDIRS = $(MACH) +POFILE = libdhcputil.po +MSGFILES = common/dhcpmsg.c +XGETFLAGS = -a -x libdhcputil.xcl + +# Override HDRSRCS so check only local headers +HDRSRCS = $(LOCHDRS:%=$(HDRDIR)/%) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install: spec .WAIT $(SUBDIRS) + +lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) + +$(ROOTHDRDIR)/%: $(COMHDRDIR)/% + $(INS.file) + +check: $(CHECKHDRS) + +$(POFILE): pofile_MSGFILES + +_msg: $(MSGDOMAINPOFILE) + +spec $(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/Makefile.msg.targ +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/libdhcputil/Makefile.com b/usr/src/lib/libdhcputil/Makefile.com new file mode 100644 index 0000000000..c6e3f163e4 --- /dev/null +++ b/usr/src/lib/libdhcputil/Makefile.com @@ -0,0 +1,64 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +LIBRARY = libdhcputil.a +VERS = .1 +LOCOBJS = dhcp_inittab.o dhcp_symbol.o dhcpmsg.o +COMDIR = $(SRC)/common/net/dhcp +COMOBJS = scan.o +OBJECTS = $(LOCOBJS) $(COMOBJS) + +include ../../Makefile.lib + +# install this library in the root filesystem +include ../../Makefile.rootfs + +LIBS = $(DYNLIB) $(LINTLIB) + +LDLIBS += -lc -lnsl -lgen -linetutil +SRCS = $(LOCOBJS:%.o=$(SRCDIR)/%.c) $(COMOBJS:%.o=$(COMDIR)/%.c) +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) + +SRCDIR = ../common +MAPDIR = ../spec/$(TRANSMACH) +SPECMAPFILE = $(MAPDIR)/mapfile + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -I$(COMDIR) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +pics/%.o: $(COMDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +include ../../Makefile.targ diff --git a/usr/src/lib/libdhcputil/README.inittab b/usr/src/lib/libdhcputil/README.inittab new file mode 100644 index 0000000000..b6ec2763e6 --- /dev/null +++ b/usr/src/lib/libdhcputil/README.inittab @@ -0,0 +1,294 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +Copyright (c) 2001 by Sun Microsystems, Inc. +All rights reserved. + +Inittab Purpose, Goals, and Functionality +Peter Memishian +ident "%Z%%M% %I% %E% SMI" + +PROBLEM STATEMENT +================= + +Currently, each DHCP-related utility that needs to handle DHCP options +uses ad-hoc methods for learning and using them, ranging from using +hard-coded internal tables to providing published (but distinct) +configuration files describing these options. + +Originally, when only the DHCP server needed to be concerned with DHCP +options, not having a standard API for managing and parsing DHCP +options was understandable. Now, with four consumers of DHCP options +in core Solaris (in.dhcpd, dhcpinfo, snoop, and dhcpmgr), the +situation has spiraled out of control. In addition to the obvious +maintenance headache caused by the redundant code, it has also become +a burden to our customers, who already have to cope with multiple +places where DHCP option information is stored (dhcptags(4), +dhcptab(4)). + +The inittab API is designed to reduce the confusion, both for the +customer and the application developer. Its goal is to provide a +single configuration for applications to receive their DHCP option +knowledge from and general routines for encoding and decoding DHCP +options. + +INITTAB +======= + +The inittab file contains information regarding the syntax and (to +some degree) the semantics of DHCP options. It is primarily a +read-only file (like /etc/termcap) and should not need to be changed +by users. Experienced sysadmins may need to update this file to add +new DHCP options, but this should be rare. + +The inittab file consists of inittab records, each being one line long +and describing a particular option. The format is based heavily on +the format for defining symbols in dhcptab(4). Each line has the +following syntax: + + option_name category, code, type, granularity, maximum, consumers + +where: + + `option_name' is user-interpretable name of the option (for use with + dhcpinfo(1M) for instance). This field should at least be per- + category unique and ideally should be unique across all categories. + Of particular note is that options names in the STANDARD, SITE, and + VENDOR spaces should not overlap, or the behavior is undefined. + + `category' is one of STANDARD, SITE, VENDOR, FIELD, or INTERNAL and + identifies the namespace in which the option falls. + + `code' is the code of this option when it is sent over the + wire. (note: in most cases, `code' uniquely identifies the + option, without a category. however, in the case of internal + categories like FIELD or INTERNAL, `code' may be used for + other purposes and thus may not be globally unique). This field + should be per-category unique and the STANDARD and SITE fields + should not have overlapping code fields or the behavior is + undefined. + + `type' describes the payload associated with this option. Valid + types are IP, ASCII, OCTET, NUMBER, BOOL, UNUMBER8, UNUMBER16, + UNUMBER32, SNUMBER8, SNUMBER16, and SNUMBER32. For numbers, + a preceding `U' or `S' indicates whether the number is unsigned + or signed, and the trailing number indicates the number of bits + in the number. + + `granularity' describes how many units of `type' payload make + up a whole value for this option. In the case of `NUMBER', + granularity describes the number of bytes in the number. Note + that `NUMBER' is preserved for compatibility, but the more + descriptive [SU]NUMBER{8,16,32,64} types should preferred. + + `maximum' describes how many whole values are allowed for this + option. 0 indicates an infinite number. + + `consumers' describe which programs make use of this information. + (`i' for dhcpinfo, `s' for snoop, `d' for in.dhcpd, and + `m' for dhcpmgr). + +A sample entry would be + + StaticRt STANDARD, 33, IP, 2, 0, isdm + +which describes an option named `StaticRt', that is in the STANDARD +category (i.e., defined by the DHCP standard), and is option code +33, which is of type `IP Address', consisting of a potentially +infinite number of pairs of IP addresses. Lastly, the consumers of +option are dhcpinfo, snoop, in.dhcpd and dhcpmgr. + +Comments in the inittab file begin with `#', and end with a newline. +Comments need not start at the beginning of a line. Lines cannot be +continued (with `\' for instance). + +The inittab file becomes the authoritative source for all DHCP options +for all DHCP option consumers, with the following exceptions and notes: + + o The DHCP agent and DHCP server both have their core protocol- + related functionality hardcoded into them, so changes to the + inittab file do not generally affect their inner workings. + + o A program can specify which entries it wants from the inittab. + This means that some DHCP options will never be used by some + programs, even if they are listed as a `consumer' of the given + option. An example of this is that the DHCP server never + requests any fields with the VENDOR category. (VENDOR information + for the DHCP server comes from dhcptab(4) instead). + + o In general, changing provided information in a released inittab + file is ill-advised. Adding new entries should be the extent + of the modifications that are performed. + + o The inittab C API also provides functions which allow programs + to verify that a given entry in the inittab file is correct + (which it does by consulting a compiled-in database of current + options). In general, this functionality is only used where + absolutely necessary, since it nullifies some of the advantages + of having an inittab. + + o Where a symbol is defined both in the inittab and in dhcptab(4), + inittab is authoritative. EXTEND symbol definitions in + dhcptab(4) will be deprecated in a future release of Solaris. + +C-LEVEL API +=========== + +Each inittab entry describes a specific DHCP option and is defined as +a dhcp_symbol_t (as defined in usr/src/lib/libdhcputil/common/dhcp_symbol.h). + +In general, it is expected that inittab entries are acquired via +inittab_load(), inittab_getbyname(), or inittab_getbycode() and passed +as needed to the remaining inittab_XXX functions. If consumers need +to convert the inittab entries into a different format, then the +fields inside the inittab entry may be read directly. Some inittab +functions return dynamically allocated parameters; all such parameters +can be freed with free(3c). + +To get an inittab entry, one of the following API's must be used: + + dhcp_symbol_t * + inittab_load(uchar_t categories, char consumer, size_t *n_entries); + + dhcp_symbol_t * + inittab_getbyname(uchar_t categories, char consumer, const char *name); + + dhcp_symbol_t * + inittab_getbycode(uchar_t categories, char consumer, unsigned int code); + +where the `categories' parameter consists of the following values OR'd +together: + + #define ITAB_CAT_STANDARD 0x01 + #define ITAB_CAT_FIELD 0x02 + #define ITAB_CAT_INTERNAL 0x04 + #define ITAB_CAT_VENDOR 0x08 + #define ITAB_CAT_SITE 0x10 + +and the `consumer' field consists of one of the following: + + #define ITAB_CONS_INFO 'i' + #define ITAB_CONS_SERVER 'd' + #define ITAB_CONS_SNOOP 's' + #define ITAB_CONS_MANAGER 'm' + +inittab_load() creates and returns an array of dhcp_symbol_t's made +up of all the entries of the specified categories that are available +to the provided consumer. Note that there is no specified order to +the entries returned. The array is dynamically allocated, and the +number of items in the array is returned in the `n_entries' parameter. + +inittab_getbyname()/inittab_getbycode() return an dhcp_symbol_t +matching the given name or code for the provided category and the +provided consumer. The dhcp_symbol_t is dynamically allocated. + +Some inittab consumers may need to make sure that a given inittab +entry has not been corrupted in the inittab file. For those cases, +inittab_verify() can be used to validate an inittab_entry against an +internal table compiled into the inittab API: + + int + inittab_verify(dhcp_symbol_t *inittab_ent, + dhcp_symbol_t *internal_ent); + +where `inittab_ent' is an dhcp_symbol_t previously returned from +inittab_load() or inittab_getbyX(). inittab_verify() returns +ITAB_SUCCESS if `inittab_ent' is verified to be correct, ITAB_FAILURE +if `inittab_ent' is incorrect, and ITAB_UNKNOWN if inittab_verify() +doesn't know. If `internal_ent' is non-NULL, it is filled in with the +value of the option known internally to the inittab API. Entries are +verified using the `ds_category' and `ds_code' fields from the +dhcp_symbol_t. For ITAB_SUCCESS to be returned, the entry passed in +and the internal entry both must have the same ds_gran, ds_max, and +ds_type values. + +To perform encoding and decoding of DHCP options, the following +routines are provided: + + uchar_t * + inittab_encode(dhcp_symbol_t *inittab_ent, const char *data, + uint16_t *lengthp, boolean_t just_payload); + + const char * + inittab_decode(dhcp_symbol_t *inittab_ent, uchar_t *data, + uint16_t length, boolean_t just_payload); + +Both of these routines take an `inittab_ent' that was previously +returned from inittab_load() or inittab_getbyX(). + +For inittab_encode(), `data' is an ASCII string to encode, and a +pointer to a dynamically allocated byte-array representing the encoded +option is returned. The size of the resulting data returned is stored +in `lengthp'. Note that if the `just_payload' option is set, then +only the payload of the option is returned (i.e., the option code and +option length is left off the returned data). To encode multiple +items of a given type, separate the items by spaces, such as +"109.108.21.1 148.232.2.1". Octal data should be of the form "0xNN" +where NN is a hexadecimal digit representing the byte. + +For inittab_decode(), `data' is a byte-array representing an encoded +option, which is `length' bytes long. A pointer to a dynamically +allocated string representing the option's value in ASCII is returned. +Note that if the `data' byte-array consists of just the payload of the +option, then the `just_payload' option should be set. + +In addition, the following routines return extended error information +for reporting parsing errors: + + uchar_t * + inittab_encode_e(dhcp_symbol_t *inittab_ent, const char *data, + uint16_t *lengthp, boolean_t just_payload, int *eerrno); + + const char * + inittab_decode_e(dhcp_symbol_t *inittab_ent, uchar_t *data, + uint16_t length, boolean_t just_payload, int *eerrno); + + +The extended codes: + +/* + * DHCP Extended error codes + */ +#define ITAB_SYNTAX_ERROR (-1) +#define ITAB_BAD_IPADDR (-2) +#define ITAB_BAD_STRING (-3) +#define ITAB_BAD_OCTET (-4) +#define ITAB_BAD_NUMBER (-5) +#define ITAB_BAD_BOOLEAN (-6) +#define ITAB_NOT_ENOUGH_IP (-7) +#define ITAB_BAD_GRAN (-8) + + +ENVIRONMENT VARIABLES +===================== + +In order to aid in debugging inittab-related problems, two environment +variables, DHCP_INITTAB_DEBUG, and DHCP_INITTAB_PATH, can be set +before starting a program which uses the inittab API. + +If DHCP_INITTAB_DEBUG is an exported environment variable, then the +inittab API will print useful diagnostic messages handy in tracking +down problems in the inittab file. If DHCP_INITTAB_PATH is an +exported environment variable, then its value is used as the location +of the inittab file, instead of /etc/dhcp/inittab. + +-- +Peter Memishian, Internet Engineering, Solaris Software (meem@east.sun.com) diff --git a/usr/src/lib/libdhcputil/common/dhcp_inittab.c b/usr/src/lib/libdhcputil/common/dhcp_inittab.c new file mode 100644 index 0000000000..4adca5a652 --- /dev/null +++ b/usr/src/lib/libdhcputil/common/dhcp_inittab.c @@ -0,0 +1,1223 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <stdarg.h> +#include <limits.h> +#include <ctype.h> +#include <libgen.h> +#include <sys/isa_defs.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/sysmacros.h> +#include <libinetutil.h> + +#include "dhcp_symbol.h" +#include "dhcp_inittab.h" + +static uint64_t dhcp_htonll(uint64_t); +static uint64_t dhcp_ntohll(uint64_t); +static void inittab_msg(const char *, ...); +static uchar_t category_to_code(const char *); +static boolean_t encode_number(uint8_t, uint8_t, boolean_t, uint8_t, + const char *, uint8_t *, int *); +static boolean_t decode_number(uint8_t, uint8_t, boolean_t, uint8_t, + const uint8_t *, char *, int *); +static dhcp_symbol_t *inittab_lookup(uchar_t, char, const char *, int32_t, + size_t *); +static dsym_category_t itabcode_to_dsymcode(uchar_t); +static boolean_t parse_entry(char *, char **); + +/* + * forward declaration of our internal inittab_table[]. too bulky to put + * up front -- check the end of this file for its definition. + */ +static dhcp_symbol_t inittab_table[]; + +/* + * the number of fields in the inittab and names for the fields. note that + * this order is meaningful to parse_entry(); other functions should just + * use them as indexes into the array returned from parse_entry(). + */ +#define ITAB_FIELDS 7 +enum { ITAB_NAME, ITAB_CODE, ITAB_TYPE, ITAB_GRAN, ITAB_MAX, ITAB_CONS, + ITAB_CAT }; + +/* + * the category_map_entry_t is used to map the inittab category codes to + * the dsym codes. the reason the codes are different is that the inittab + * needs to have the codes be ORable such that queries can retrieve more + * than one category at a time. this map is also used to map the inittab + * string representation of a category to its numerical code. + */ +typedef struct category_map_entry { + dsym_category_t cme_dsymcode; + char *cme_name; + uchar_t cme_itabcode; +} category_map_entry_t; + +static category_map_entry_t category_map[] = { + { DSYM_STANDARD, "STANDARD", ITAB_CAT_STANDARD }, + { DSYM_FIELD, "FIELD", ITAB_CAT_FIELD }, + { DSYM_INTERNAL, "INTERNAL", ITAB_CAT_INTERNAL }, + { DSYM_VENDOR, "VENDOR", ITAB_CAT_VENDOR }, + { DSYM_SITE, "SITE", ITAB_CAT_SITE } +}; + +/* + * inittab_load(): returns all inittab entries with the specified criteria + * + * input: uchar_t: the categories the consumer is interested in + * char: the consumer type of the caller + * size_t *: set to the number of entries returned + * output: dhcp_symbol_t *: an array of dynamically allocated entries + * on success, NULL upon failure + */ +dhcp_symbol_t * +inittab_load(uchar_t categories, char consumer, size_t *n_entries) +{ + return (inittab_lookup(categories, consumer, NULL, -1, n_entries)); +} + +/* + * inittab_getbyname(): returns an inittab entry with the specified criteria + * + * input: int: the categories the consumer is interested in + * char: the consumer type of the caller + * char *: the name of the inittab entry the consumer wants + * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure + * on success, NULL upon failure + */ +dhcp_symbol_t * +inittab_getbyname(uchar_t categories, char consumer, const char *name) +{ + return (inittab_lookup(categories, consumer, name, -1, NULL)); +} + +/* + * inittab_getbycode(): returns an inittab entry with the specified criteria + * + * input: uchar_t: the categories the consumer is interested in + * char: the consumer type of the caller + * uint16_t: the code of the inittab entry the consumer wants + * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure + * on success, NULL upon failure + */ +dhcp_symbol_t * +inittab_getbycode(uchar_t categories, char consumer, uint16_t code) +{ + return (inittab_lookup(categories, consumer, NULL, code, NULL)); +} + +/* + * inittab_lookup(): returns inittab entries with the specified criteria + * + * input: uchar_t: the categories the consumer is interested in + * char: the consumer type of the caller + * const char *: the name of the entry the caller is interested + * in, or NULL if the caller doesn't care + * int32_t: the code the caller is interested in, or -1 if the + * caller doesn't care + * size_t *: set to the number of entries returned + * output: dhcp_symbol_t *: dynamically allocated dhcp_symbol structures + * on success, NULL upon failure + */ +static dhcp_symbol_t * +inittab_lookup(uchar_t categories, char consumer, const char *name, + int32_t code, size_t *n_entriesp) +{ + FILE *inittab_fp; + dhcp_symbol_t *new_entries, *entries = NULL; + dhcp_symbol_t entry; + char buffer[ITAB_MAX_LINE_LEN]; + char *fields[ITAB_FIELDS]; + unsigned long line = 0; + size_t i, n_entries = 0; + char *inittab_path; + uchar_t category_code; + dsym_cdtype_t type; + + inittab_path = getenv("DHCP_INITTAB_PATH"); + if (inittab_path == NULL) + inittab_path = ITAB_INITTAB_PATH; + + inittab_fp = fopen(inittab_path, "r"); + if (inittab_fp == NULL) { + inittab_msg("inittab_lookup: fopen: %s: %s", + ITAB_INITTAB_PATH, strerror(errno)); + return (NULL); + } + + (void) bufsplit(",\n", 0, NULL); + while (fgets(buffer, sizeof (buffer), inittab_fp) != NULL) { + + line++; + + /* + * make sure the string didn't overflow our buffer + */ + if (strchr(buffer, '\n') == NULL) { + inittab_msg("inittab_lookup: line %li: too long, " + "skipping", line); + continue; + } + + /* + * skip `pure comment' lines + */ + for (i = 0; buffer[i] != '\0'; i++) + if (isspace(buffer[i]) == 0) + break; + + if (buffer[i] == ITAB_COMMENT_CHAR || buffer[i] == '\0') + continue; + + /* + * parse the entry out into fields. + */ + if (parse_entry(buffer, fields) == B_FALSE) { + inittab_msg("inittab_lookup: line %li: syntax error, " + "skipping", line); + continue; + } + + /* + * validate the values in the entries; skip if invalid. + */ + if (atoi(fields[ITAB_GRAN]) > ITAB_GRAN_MAX) { + inittab_msg("inittab_lookup: line %li: granularity `%s'" + " out of range, skipping", line, fields[ITAB_GRAN]); + continue; + } + + if (atoi(fields[ITAB_MAX]) > ITAB_MAX_MAX) { + inittab_msg("inittab_lookup: line %li: maximum `%s' " + "out of range, skipping", line, fields[ITAB_MAX]); + continue; + } + + if (dsym_get_type_id(fields[ITAB_TYPE], &type, B_FALSE) != + DSYM_SUCCESS) { + inittab_msg("inittab_lookup: line %li: type `%s' " + "is invalid, skipping", line, fields[ITAB_TYPE]); + continue; + } + + /* + * find out whether this entry of interest to our consumer, + * and if so, throw it onto the set of entries we'll return. + * check categories last since it's the most expensive check. + */ + if (strchr(fields[ITAB_CONS], consumer) == NULL) + continue; + + if (code != -1 && atoi(fields[ITAB_CODE]) != code) + continue; + + if (name != NULL && strcasecmp(fields[ITAB_NAME], name) != 0) + continue; + + category_code = category_to_code(fields[ITAB_CAT]); + if ((category_code & categories) == 0) + continue; + + /* + * looks like a match. allocate an entry and fill it in + */ + new_entries = realloc(entries, (n_entries + 1) * + sizeof (dhcp_symbol_t)); + + /* + * if we run out of memory, might as well return what we can + */ + if (new_entries == NULL) { + inittab_msg("inittab_lookup: ran out of memory " + "allocating dhcp_symbol_t's"); + break; + } + + entry.ds_max = atoi(fields[ITAB_MAX]); + entry.ds_code = atoi(fields[ITAB_CODE]); + entry.ds_type = type; + entry.ds_gran = atoi(fields[ITAB_GRAN]); + entry.ds_category = itabcode_to_dsymcode(category_code); + entry.ds_classes.dc_cnt = 0; + entry.ds_classes.dc_names = NULL; + (void) strlcpy(entry.ds_name, fields[ITAB_NAME], + sizeof (entry.ds_name)); + + entries = new_entries; + entries[n_entries++] = entry; + } + + if (ferror(inittab_fp) != 0) { + inittab_msg("inittab_lookup: error on inittab stream"); + clearerr(inittab_fp); + } + + (void) fclose(inittab_fp); + + if (n_entriesp != NULL) + *n_entriesp = n_entries; + + return (entries); +} + +/* + * parse_entry(): parses an entry out into its constituent fields + * + * input: char *: the entry + * char **: an array of ITAB_FIELDS length which contains + * pointers into the entry on upon return + * output: boolean_t: B_TRUE on success, B_FALSE on failure + */ +static boolean_t +parse_entry(char *entry, char **fields) +{ + char *category, *spacep; + size_t n_fields, i; + + /* + * due to a mistake made long ago, the first and second fields of + * each entry are not separated by a comma, but rather by + * whitespace -- have bufsplit() treat the two fields as one, then + * pull them apart afterwards. + */ + n_fields = bufsplit(entry, ITAB_FIELDS - 1, fields); + if (n_fields != (ITAB_FIELDS - 1)) + return (B_FALSE); + + /* + * pull the first and second fields apart. this is complicated + * since the first field can contain embedded whitespace (so we + * must separate the two fields by the last span of whitespace). + * + * first, find the initial span of whitespace. if there isn't one, + * then the entry is malformed. + */ + category = strpbrk(fields[ITAB_NAME], " \t"); + if (category == NULL) + return (B_FALSE); + + /* + * find the last span of whitespace. + */ + do { + while (isspace(*category)) + category++; + + spacep = strpbrk(category, " \t"); + if (spacep != NULL) + category = spacep; + } while (spacep != NULL); + + /* + * NUL-terminate the first byte of the last span of whitespace, so + * that the first field doesn't have any residual trailing + * whitespace. + */ + spacep = category - 1; + while (isspace(*spacep)) + spacep--; + + if (spacep <= fields[0]) + return (B_FALSE); + + *++spacep = '\0'; + + /* + * remove any whitespace from the fields. + */ + for (i = 0; i < n_fields; i++) { + while (isspace(*fields[i])) + fields[i]++; + } + fields[ITAB_CAT] = category; + + return (B_TRUE); +} + +/* + * inittab_verify(): verifies that a given inittab entry matches an internal + * definition + * + * input: dhcp_symbol_t *: the inittab entry to verify + * dhcp_symbol_t *: if non-NULL, a place to store the internal + * inittab entry upon return + * output: int: ITAB_FAILURE, ITAB_SUCCESS, or ITAB_UNKNOWN + */ +int +inittab_verify(dhcp_symbol_t *inittab_ent, dhcp_symbol_t *internal_ent) +{ + unsigned int i; + + for (i = 0; inittab_table[i].ds_name[0] != '\0'; i++) { + + if (inittab_ent->ds_category != inittab_table[i].ds_category) + continue; + + if (inittab_ent->ds_code == inittab_table[i].ds_code) { + if (internal_ent != NULL) + *internal_ent = inittab_table[i]; + + if (inittab_table[i].ds_type != inittab_ent->ds_type || + inittab_table[i].ds_gran != inittab_ent->ds_gran || + inittab_table[i].ds_max != inittab_ent->ds_max) + return (ITAB_FAILURE); + + return (ITAB_SUCCESS); + } + } + + return (ITAB_UNKNOWN); +} + +/* + * inittab_encode_e(): converts a string representation of a given datatype into + * binary; used for encoding ascii values into a form that + * can be put in DHCP packets to be sent on the wire. + * + * input: dhcp_symbol_t *: the entry describing the value option + * const char *: the value to convert + * uint16_t *: set to the length of the binary data returned + * boolean_t: if false, return a full DHCP option + * output: uchar_t *: a dynamically allocated byte array with converted data + */ +uchar_t * +inittab_encode_e(dhcp_symbol_t *ie, const char *value, uint16_t *lengthp, + boolean_t just_payload, int *ierrnop) +{ + uint16_t length = 0; + uchar_t n_entries = 0; + const char *valuep; + char *currp; + uchar_t *result = NULL; + unsigned int i; + uint8_t type_size = inittab_type_to_size(ie); + boolean_t is_signed; + uint_t vallen, reslen; + + *ierrnop = 0; + if (type_size == 0) { + *ierrnop = ITAB_SYNTAX_ERROR; + return (NULL); + } + + if (ie->ds_type == DSYM_ASCII) + n_entries = strlen(value); /* no NUL */ + else if (ie->ds_type == DSYM_OCTET) { + vallen = strlen(value); + n_entries = vallen / 2; + n_entries += vallen % 2; + } else { + /* + * figure out the number of entries by counting the spaces + * in the value string + */ + for (valuep = value; valuep++ != NULL; n_entries++) + valuep = strchr(valuep, ' '); + } + + /* + * if we're gonna return a complete option, then include the + * option length and code in the size of the packet we allocate + */ + if (just_payload == B_FALSE) + length += 2; + + length += n_entries * type_size; + if (length > 0) + result = malloc(length); + + switch (ie->ds_type) { + + case DSYM_ASCII: + + if (result == NULL) { + *ierrnop = ITAB_NOMEM; + return (NULL); + } + + if (strlen(value) > length) { + free(result); + *ierrnop = ITAB_BAD_STRING; + return (NULL); + } + + (void) memcpy(result, value, length); + break; + + case DSYM_OCTET: + + if (result == NULL) { + *ierrnop = ITAB_BAD_OCTET; + return (NULL); + } + + reslen = length; + /* Call libinetutil function to decode */ + if (hexascii_to_octet(value, vallen, result, &reslen) != 0) { + free(result); + *ierrnop = ITAB_BAD_OCTET; + return (NULL); + } + break; + + case DSYM_IP: + + if (result == NULL) { + *ierrnop = ITAB_BAD_IPADDR; + return (NULL); + } + if (n_entries % ie->ds_gran != 0) { + *ierrnop = ITAB_BAD_GRAN; + inittab_msg("inittab_encode: number of entries " + "not compatible with option granularity"); + free(result); + return (NULL); + } + + for (valuep = value, i = 0; i < n_entries; i++, valuep++) { + + currp = strchr(valuep, ' '); + if (currp != NULL) + *currp = '\0'; + if (inet_pton(AF_INET, valuep, + &result[i * sizeof (ipaddr_t)]) != 1) { + *ierrnop = ITAB_BAD_IPADDR; + inittab_msg("inittab_encode: bogus ip address"); + free(result); + return (NULL); + } + + valuep = currp; + if (valuep == NULL) { + if (i < (n_entries - 1)) { + *ierrnop = ITAB_NOT_ENOUGH_IP; + inittab_msg("inittab_encode: too few " + "ip addresses"); + free(result); + return (NULL); + } + break; + } + } + break; + + case DSYM_NUMBER: /* FALLTHRU */ + case DSYM_UNUMBER8: /* FALLTHRU */ + case DSYM_SNUMBER8: /* FALLTHRU */ + case DSYM_UNUMBER16: /* FALLTHRU */ + case DSYM_SNUMBER16: /* FALLTHRU */ + case DSYM_UNUMBER32: /* FALLTHRU */ + case DSYM_SNUMBER32: /* FALLTHRU */ + case DSYM_UNUMBER64: /* FALLTHRU */ + case DSYM_SNUMBER64: + + if (result == NULL) { + *ierrnop = ITAB_BAD_NUMBER; + return (NULL); + } + + is_signed = (ie->ds_type == DSYM_SNUMBER64 || + ie->ds_type == DSYM_SNUMBER32 || + ie->ds_type == DSYM_SNUMBER16 || + ie->ds_type == DSYM_SNUMBER8); + + if (encode_number(n_entries, type_size, is_signed, 0, value, + result, ierrnop) == B_FALSE) { + free(result); + return (NULL); + } + break; + + default: + if (ie->ds_type == DSYM_BOOL) + *ierrnop = ITAB_BAD_BOOLEAN; + else + *ierrnop = ITAB_SYNTAX_ERROR; + + inittab_msg("inittab_encode: unsupported type `%d'", + ie->ds_type); + + free(result); + return (NULL); + } + + /* + * if just_payload is false, then we need to slide the option + * code and length fields in. (length includes them in its + * count, so we have to subtract 2) + */ + if (just_payload == B_FALSE) { + (void) memmove(result + 2, result, length - 2); + result[0] = ie->ds_code; + result[1] = length - 2; + } + + if (lengthp != NULL) + *lengthp = length; + + return (result); +} + +/* + * inittab_decode_e(): converts a binary representation of a given datatype into + * a string; used for decoding DHCP options in a packet off + * the wire into ascii + * + * input: dhcp_symbol_t *: the entry describing the payload option + * uchar_t *: the payload to convert + * uint16_t: the payload length (only used if just_payload is true) + * boolean_t: if false, payload is assumed to be a DHCP option + * int *: set to extended error code if error occurs. + * output: char *: a dynamically allocated string containing the converted data + */ +char * +inittab_decode_e(dhcp_symbol_t *ie, uchar_t *payload, uint16_t length, + boolean_t just_payload, int *ierrnop) +{ + char *resultp, *end, *result = NULL; + char *currp; + uchar_t n_entries; + struct in_addr in_addr; + uint8_t type_size = inittab_type_to_size(ie); + boolean_t is_signed; + + *ierrnop = 0; + if (type_size == 0) { + *ierrnop = ITAB_SYNTAX_ERROR; + return (NULL); + } + + if (just_payload == B_FALSE) { + length = payload[1]; + payload += 2; + } + + /* + * figure out the number of elements to convert. note that + * for ds_type NUMBER, the granularity is really 1 since the + * value of ds_gran is the number of bytes in the number. + */ + if (ie->ds_type == DSYM_NUMBER) + n_entries = MIN(ie->ds_max, length / type_size); + else + n_entries = MIN(ie->ds_max * ie->ds_gran, length / type_size); + + if (n_entries == 0) + n_entries = length / type_size; + + if ((length % type_size) != 0) { + inittab_msg("inittab_decode: length of string not compatible " + "with option type `%i'", ie->ds_type); + *ierrnop = ITAB_BAD_STRING; + return (NULL); + } + + switch (ie->ds_type) { + + case DSYM_ASCII: + + result = malloc(n_entries + 1); + if (result == NULL) { + *ierrnop = ITAB_NOMEM; + return (NULL); + } + + (void) memcpy(result, payload, n_entries); + result[n_entries] = '\0'; + break; + + case DSYM_OCTET: + + result = malloc(n_entries * (sizeof ("0xNN") + 1)); + if (result == NULL) { + *ierrnop = ITAB_NOMEM; + return (NULL); + } + + for (resultp = result; n_entries != 0; n_entries--) { + currp = resultp; + resultp += sprintf(resultp, "0x%02X ", *payload++); + if (currp == resultp) { + free(result); + *ierrnop = ITAB_BAD_OCTET; + return (NULL); + } + } + + resultp[-1] = '\0'; + break; + + case DSYM_IP: + + if ((length / sizeof (ipaddr_t)) % ie->ds_gran != 0) { + *ierrnop = ITAB_BAD_GRAN; + inittab_msg("inittab_decode: number of entries " + "not compatible with option granularity"); + return (NULL); + } + + result = malloc(n_entries * (sizeof ("aaa.bbb.ccc.ddd") + 1)); + end = &result[n_entries * (sizeof ("aaa.bbb.ccc.ddd") + 1)]; + if (result == NULL) { + *ierrnop = ITAB_NOMEM; + return (NULL); + } + + for (resultp = result; n_entries != 0; n_entries--) { + (void) memcpy(&in_addr.s_addr, payload, + sizeof (ipaddr_t)); + currp = resultp; + resultp += snprintf(resultp, end - resultp, "%s ", + inet_ntoa(in_addr)); + if (currp == resultp) { + free(result); + *ierrnop = ITAB_BAD_IPADDR; + return (NULL); + } + payload += sizeof (ipaddr_t); + } + + resultp[-1] = '\0'; + break; + + case DSYM_NUMBER: /* FALLTHRU */ + case DSYM_UNUMBER8: /* FALLTHRU */ + case DSYM_SNUMBER8: /* FALLTHRU */ + case DSYM_UNUMBER16: /* FALLTHRU */ + case DSYM_SNUMBER16: /* FALLTHRU */ + case DSYM_UNUMBER32: /* FALLTHRU */ + case DSYM_SNUMBER32: /* FALLTHRU */ + case DSYM_UNUMBER64: /* FALLTHRU */ + case DSYM_SNUMBER64: + + is_signed = (ie->ds_type == DSYM_SNUMBER64 || + ie->ds_type == DSYM_SNUMBER32 || + ie->ds_type == DSYM_SNUMBER16 || + ie->ds_type == DSYM_SNUMBER8); + + result = malloc(n_entries * ITAB_MAX_NUMBER_LEN); + if (result == NULL) { + *ierrnop = ITAB_NOMEM; + return (NULL); + } + + if (decode_number(n_entries, type_size, is_signed, ie->ds_gran, + payload, result, ierrnop) == B_FALSE) { + free(result); + return (NULL); + } + break; + + default: + inittab_msg("inittab_decode: unsupported type `%d'", + ie->ds_type); + break; + } + + return (result); +} + +/* + * inittab_encode(): converts a string representation of a given datatype into + * binary; used for encoding ascii values into a form that + * can be put in DHCP packets to be sent on the wire. + * + * input: dhcp_symbol_t *: the entry describing the value option + * const char *: the value to convert + * uint16_t *: set to the length of the binary data returned + * boolean_t: if false, return a full DHCP option + * output: uchar_t *: a dynamically allocated byte array with converted data + */ +uchar_t * +inittab_encode(dhcp_symbol_t *ie, const char *value, uint16_t *lengthp, + boolean_t just_payload) +{ + int ierrno; + + return (inittab_encode_e(ie, value, lengthp, just_payload, &ierrno)); +} + +/* + * inittab_decode(): converts a binary representation of a given datatype into + * a string; used for decoding DHCP options in a packet off + * the wire into ascii + * + * input: dhcp_symbol_t *: the entry describing the payload option + * uchar_t *: the payload to convert + * uint16_t: the payload length (only used if just_payload is true) + * boolean_t: if false, payload is assumed to be a DHCP option + * output: char *: a dynamically allocated string containing the converted data + */ +char * +inittab_decode(dhcp_symbol_t *ie, uchar_t *payload, uint16_t length, + boolean_t just_payload) +{ + int ierrno; + + return (inittab_decode_e(ie, payload, length, just_payload, &ierrno)); +} + +/* + * inittab_msg(): prints diagnostic messages if INITTAB_DEBUG is set + * + * const char *: a printf-like format string + * ...: arguments to the format string + * output: void + */ +/*PRINTFLIKE1*/ +static void +inittab_msg(const char *fmt, ...) +{ + enum { INITTAB_MSG_CHECK, INITTAB_MSG_RETURN, INITTAB_MSG_OUTPUT }; + + va_list ap; + char buf[512]; + static int action = INITTAB_MSG_CHECK; + + /* + * check DHCP_INITTAB_DEBUG the first time in; thereafter, use + * the the cached result (stored in `action'). + */ + switch (action) { + + case INITTAB_MSG_CHECK: + + if (getenv("DHCP_INITTAB_DEBUG") == NULL) { + action = INITTAB_MSG_RETURN; + return; + } + + action = INITTAB_MSG_OUTPUT; + + /* FALLTHRU into INITTAB_MSG_OUTPUT */ + + case INITTAB_MSG_OUTPUT: + + va_start(ap, fmt); + + (void) snprintf(buf, sizeof (buf), "inittab: %s\n", fmt); + (void) vfprintf(stderr, buf, ap); + + va_end(ap); + break; + + case INITTAB_MSG_RETURN: + + return; + } +} + +/* + * decode_number(): decodes a sequence of numbers from binary into ascii; + * binary is coming off of the network, so it is in nbo + * + * input: uint8_t: the number of "granularity" numbers to decode + * uint8_t: the length of each number + * boolean_t: whether the numbers should be considered signed + * uint8_t: the number of numbers per granularity + * const uint8_t *: where to decode the numbers from + * char *: where to decode the numbers to + * output: boolean_t: true on successful conversion, false on failure + */ +static boolean_t +decode_number(uint8_t n_entries, uint8_t size, boolean_t is_signed, + uint8_t granularity, const uint8_t *from, char *to, int *ierrnop) +{ + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + + if (granularity != 0) { + if ((granularity % n_entries) != 0) { + inittab_msg("decode_number: number of entries " + "not compatible with option granularity"); + *ierrnop = ITAB_BAD_GRAN; + return (B_FALSE); + } + } + + for (; n_entries != 0; n_entries--, from += size) { + + switch (size) { + + case 1: + to += sprintf(to, is_signed ? "%d " : "%u ", *from); + break; + + case 2: + (void) memcpy(&uint16, from, 2); + to += sprintf(to, is_signed ? "%hd " : "%hu ", + ntohs(uint16)); + break; + + case 4: + (void) memcpy(&uint32, from, 4); + to += sprintf(to, is_signed ? "%ld " : "%lu ", + ntohl(uint32)); + break; + + case 8: + (void) memcpy(&uint64, from, 8); + to += sprintf(to, is_signed ? "%lld " : "%llu ", + dhcp_ntohll(uint64)); + break; + + default: + *ierrnop = ITAB_BAD_NUMBER; + inittab_msg("decode_number: unknown integer size `%d'", + size); + return (B_FALSE); + } + } + + to[-1] = '\0'; + return (B_TRUE); +} + +/* + * encode_number(): encodes a sequence of numbers from ascii into binary; + * number will end up on the wire so it needs to be in nbo + * + * input: uint8_t: the number of "granularity" numbers to encode + * uint8_t: the length of each number + * boolean_t: whether the numbers should be considered signed + * uint8_t: the number of numbers per granularity + * const uint8_t *: where to encode the numbers from + * char *: where to encode the numbers to + * int *: set to extended error code if error occurs. + * output: boolean_t: true on successful conversion, false on failure + */ +static boolean_t /* ARGSUSED */ +encode_number(uint8_t n_entries, uint8_t size, boolean_t is_signed, + uint8_t granularity, const char *from, uint8_t *to, int *ierrnop) +{ + uint8_t i; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + char *endptr; + + if (granularity != 0) { + if ((granularity % n_entries) != 0) { + *ierrnop = ITAB_BAD_GRAN; + inittab_msg("encode_number: number of entries " + "not compatible with option granularity"); + return (B_FALSE); + } + } + + for (i = 0; i < n_entries; i++, from++) { + + /* + * totally obscure c factoid: it is legal to pass a + * string representing a negative number to strtoul(). + * in this case, strtoul() will return an unsigned + * long that if cast to a long, would represent the + * negative number. we take advantage of this to + * cut down on code here. + */ + + errno = 0; + switch (size) { + + case 1: + to[i] = strtoul(from, &endptr, 0); + if (errno != 0 || from == endptr) { + goto error; + } + break; + + case 2: + uint16 = htons(strtoul(from, &endptr, 0)); + if (errno != 0 || from == endptr) { + goto error; + } + (void) memcpy(to + (i * 2), &uint16, 2); + break; + + case 4: + uint32 = htonl(strtoul(from, &endptr, 0)); + if (errno != 0 || from == endptr) { + goto error; + } + (void) memcpy(to + (i * 4), &uint32, 4); + break; + + case 8: + uint64 = dhcp_htonll(strtoull(from, &endptr, 0)); + if (errno != 0 || from == endptr) { + goto error; + } + (void) memcpy(to + (i * 8), &uint64, 8); + break; + + default: + inittab_msg("encode_number: unsupported integer " + "size `%d'", size); + return (B_FALSE); + } + + from = strchr(from, ' '); + if (from == NULL) + break; + } + + return (B_TRUE); + +error: + *ierrnop = ITAB_BAD_NUMBER; + inittab_msg("encode_number: cannot convert to integer"); + return (B_FALSE); +} + +/* + * inittab_type_to_size(): given an inittab entry, returns size of one entry of + * its type + * + * input: dhcp_symbol_t *: an entry of the given type + * output: uint8_t: the size in bytes of an entry of that type + */ +uint8_t +inittab_type_to_size(dhcp_symbol_t *ie) +{ + switch (ie->ds_type) { + + case DSYM_ASCII: + case DSYM_OCTET: + case DSYM_SNUMBER8: + case DSYM_UNUMBER8: + + return (1); + + case DSYM_SNUMBER16: + case DSYM_UNUMBER16: + + return (2); + + case DSYM_SNUMBER32: + case DSYM_UNUMBER32: + case DSYM_IP: + + return (4); + + case DSYM_SNUMBER64: + case DSYM_UNUMBER64: + + return (8); + + case DSYM_NUMBER: + + return (ie->ds_gran); + } + + return (0); +} + +/* + * itabcode_to_dsymcode(): maps an inittab category code to its dsym + * representation + * + * input: uchar_t: the inittab category code + * output: dsym_category_t: the dsym category code + */ +static dsym_category_t +itabcode_to_dsymcode(uchar_t itabcode) +{ + + unsigned int i; + + for (i = 0; i < ITAB_CAT_COUNT; i++) + if (category_map[i].cme_itabcode == itabcode) + return (category_map[i].cme_dsymcode); + + return (DSYM_BAD_CAT); +} + +/* + * category_to_code(): maps a category name to its numeric representation + * + * input: const char *: the category name + * output: uchar_t: its internal code (numeric representation) + */ +static uchar_t +category_to_code(const char *category) +{ + unsigned int i; + + for (i = 0; i < ITAB_CAT_COUNT; i++) + if (strcasecmp(category_map[i].cme_name, category) == 0) + return (category_map[i].cme_itabcode); + + return (0); +} + +/* + * dhcp_htonll(): converts a 64-bit number from host to network byte order + * + * input: uint64_t: the number to convert + * output: uint64_t: its value in network byte order + */ +static uint64_t +dhcp_htonll(uint64_t uint64_hbo) +{ + return (dhcp_ntohll(uint64_hbo)); +} + +/* + * dhcp_ntohll(): converts a 64-bit number from network to host byte order + * + * input: uint64_t: the number to convert + * output: uint64_t: its value in host byte order + */ +static uint64_t +dhcp_ntohll(uint64_t uint64_nbo) +{ +#ifdef _LITTLE_ENDIAN + return ((uint64_t)ntohl(uint64_nbo & 0xffffffff) << 32 | + ntohl(uint64_nbo >> 32)); +#else + return (uint64_nbo); +#endif +} + +/* + * our internal table of DHCP option values, used by inittab_verify() + */ +static dhcp_symbol_t inittab_table[] = +{ +{ DSYM_INTERNAL, 1024, "Hostname", DSYM_BOOL, 0, 0 }, +{ DSYM_INTERNAL, 1025, "LeaseNeg", DSYM_BOOL, 0, 0 }, +{ DSYM_INTERNAL, 1026, "EchoVC", DSYM_BOOL, 0, 0 }, +{ DSYM_INTERNAL, 1027, "BootPath", DSYM_ASCII, 1, 128 }, +{ DSYM_FIELD, 0, "Opcode", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_FIELD, 1, "Htype", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_FIELD, 2, "HLen", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_FIELD, 3, "Hops", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_FIELD, 4, "Xid", DSYM_UNUMBER32, 1, 1 }, +{ DSYM_FIELD, 8, "Secs", DSYM_UNUMBER16, 1, 1 }, +{ DSYM_FIELD, 10, "Flags", DSYM_OCTET, 1, 2 }, +{ DSYM_FIELD, 12, "Ciaddr", DSYM_IP, 1, 1 }, +{ DSYM_FIELD, 16, "Yiaddr", DSYM_IP, 1, 1 }, +{ DSYM_FIELD, 20, "BootSrvA", DSYM_IP, 1, 1 }, +{ DSYM_FIELD, 24, "Giaddr", DSYM_IP, 1, 1 }, +{ DSYM_FIELD, 28, "Chaddr", DSYM_OCTET, 1, 16 }, +{ DSYM_FIELD, 44, "BootSrvN", DSYM_ASCII, 1, 64 }, +{ DSYM_FIELD, 108, "BootFile", DSYM_ASCII, 1, 128 }, +{ DSYM_FIELD, 236, "Magic", DSYM_OCTET, 1, 4 }, +{ DSYM_FIELD, 240, "Options", DSYM_OCTET, 1, 60 }, +{ DSYM_STANDARD, 1, "Subnet", DSYM_IP, 1, 1 }, +{ DSYM_STANDARD, 2, "UTCoffst", DSYM_SNUMBER32, 1, 1 }, +{ DSYM_STANDARD, 3, "Router", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 4, "Timeserv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 5, "IEN116ns", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 6, "DNSserv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 7, "Logserv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 8, "Cookie", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 9, "Lprserv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 10, "Impress", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 11, "Resource", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 12, "Hostname", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 13, "Bootsize", DSYM_UNUMBER16, 1, 1 }, +{ DSYM_STANDARD, 14, "Dumpfile", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 15, "DNSdmain", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 16, "Swapserv", DSYM_IP, 1, 1 }, +{ DSYM_STANDARD, 17, "Rootpath", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 18, "ExtendP", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 19, "IpFwdF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 20, "NLrouteF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 21, "PFilter", DSYM_IP, 2, 0 }, +{ DSYM_STANDARD, 22, "MaxIpSiz", DSYM_UNUMBER16, 1, 1 }, +{ DSYM_STANDARD, 23, "IpTTL", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 24, "PathTO", DSYM_UNUMBER32, 1, 1 }, +{ DSYM_STANDARD, 25, "PathTbl", DSYM_UNUMBER16, 1, 0 }, +{ DSYM_STANDARD, 26, "MTU", DSYM_UNUMBER16, 1, 1 }, +{ DSYM_STANDARD, 27, "SameMtuF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 28, "Broadcst", DSYM_IP, 1, 1 }, +{ DSYM_STANDARD, 29, "MaskDscF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 30, "MaskSupF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 31, "RDiscvyF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 32, "RSolictS", DSYM_IP, 1, 1 }, +{ DSYM_STANDARD, 33, "StaticRt", DSYM_IP, 2, 0 }, +{ DSYM_STANDARD, 34, "TrailerF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 35, "ArpTimeO", DSYM_UNUMBER32, 1, 1 }, +{ DSYM_STANDARD, 36, "EthEncap", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 37, "TcpTTL", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 38, "TcpKaInt", DSYM_UNUMBER32, 1, 1 }, +{ DSYM_STANDARD, 39, "TcpKaGbF", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 40, "NISdmain", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 41, "NISservs", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 42, "NTPservs", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 43, "Vendor", DSYM_OCTET, 1, 0 }, +{ DSYM_STANDARD, 44, "NetBNms", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 45, "NetBDsts", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 46, "NetBNdT", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 47, "NetBScop", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 48, "XFontSrv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 49, "XDispMgr", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 50, "ReqIP", DSYM_IP, 1, 1 }, +{ DSYM_STANDARD, 51, "LeaseTim", DSYM_UNUMBER32, 1, 1 }, +{ DSYM_STANDARD, 52, "OptOvrld", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 53, "DHCPType", DSYM_UNUMBER8, 1, 1 }, +{ DSYM_STANDARD, 54, "ServerID", DSYM_IP, 1, 1 }, +{ DSYM_STANDARD, 55, "ReqList", DSYM_OCTET, 1, 0 }, +{ DSYM_STANDARD, 56, "Message", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 57, "DHCP_MTU", DSYM_UNUMBER16, 1, 1 }, +{ DSYM_STANDARD, 58, "T1Time", DSYM_UNUMBER32, 1, 1 }, +{ DSYM_STANDARD, 59, "T2Time", DSYM_UNUMBER32, 1, 1 }, +{ DSYM_STANDARD, 60, "ClassID", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 61, "ClientID", DSYM_OCTET, 1, 0 }, +{ DSYM_STANDARD, 62, "NW_dmain", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 63, "NWIPOpts", DSYM_OCTET, 1, 128 }, +{ DSYM_STANDARD, 64, "NIS+dom", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 65, "NIS+serv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 66, "TFTPsrvN", DSYM_ASCII, 1, 64 }, +{ DSYM_STANDARD, 67, "OptBootF", DSYM_ASCII, 1, 128 }, +{ DSYM_STANDARD, 68, "MblIPAgt", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 69, "SMTPserv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 70, "POP3serv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 71, "NNTPserv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 72, "WWWservs", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 73, "Fingersv", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 74, "IRCservs", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 75, "STservs", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 76, "STDAservs", DSYM_IP, 1, 0 }, +{ DSYM_STANDARD, 77, "UserClas", DSYM_ASCII, 1, 0 }, +{ DSYM_STANDARD, 78, "SLP_DA", DSYM_OCTET, 1, 0 }, +{ DSYM_STANDARD, 79, "SLP_SS", DSYM_OCTET, 1, 0 }, +{ DSYM_STANDARD, 82, "AgentOpt", DSYM_OCTET, 1, 0 }, +{ DSYM_STANDARD, 89, "FQDN", DSYM_OCTET, 1, 0 }, +{ 0, 0, "", 0, 0, 0 } +}; diff --git a/usr/src/lib/libdhcputil/common/dhcp_inittab.h b/usr/src/lib/libdhcputil/common/dhcp_inittab.h new file mode 100644 index 0000000000..ed70ad20b4 --- /dev/null +++ b/usr/src/lib/libdhcputil/common/dhcp_inittab.h @@ -0,0 +1,117 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999-2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _DHCP_INITTAB_H +#define _DHCP_INITTAB_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <dhcp_symbol.h> +#include <limits.h> + +/* + * dhcp_inittab.[ch] make up the interface to the inittab file, which + * is a table of all known DHCP options. please see `README.inittab' + * for more background on the inittab api, and dhcp_inittab.c for details + * on how to use the exported functions. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * On-disk inittab attributes and limits. + */ +#define ITAB_INITTAB_PATH "/etc/dhcp/inittab" +#define ITAB_MAX_LINE_LEN 8192 /* bytes */ +#define ITAB_MAX_NUMBER_LEN 30 /* digits */ +#define ITAB_COMMENT_CHAR '#' +#define ITAB_CODE_MAX UCHAR_MAX /* for now */ +#define ITAB_GRAN_MAX UCHAR_MAX +#define ITAB_MAX_MAX UCHAR_MAX + +/* + * Return values from the inittab API. + */ +#define ITAB_FAILURE 0 +#define ITAB_SUCCESS 1 +#define ITAB_UNKNOWN 2 + +/* + * Categories to pass to inittab functions; note that these may be + * bitwise-OR'd to request more than one. Note that these should + * not be used otherwise. + */ +#define ITAB_CAT_STANDARD 0x01 +#define ITAB_CAT_FIELD 0x02 +#define ITAB_CAT_INTERNAL 0x04 +#define ITAB_CAT_VENDOR 0x08 +#define ITAB_CAT_SITE 0x10 +#define ITAB_CAT_COUNT 5 + +/* + * Consumer which is using the inittab functions. + */ +#define ITAB_CONS_INFO 'i' +#define ITAB_CONS_SERVER 'd' +#define ITAB_CONS_SNOOP 's' +#define ITAB_CONS_MANAGER 'm' +#define ITAB_CONS_COUNT (sizeof ("idsm") - 1) + +/* + * Extended error codes, for use with inittab_{en,de}code_e(). + */ +#define ITAB_SYNTAX_ERROR (-1) +#define ITAB_BAD_IPADDR (-2) +#define ITAB_BAD_STRING (-3) +#define ITAB_BAD_OCTET (-4) +#define ITAB_BAD_NUMBER (-5) +#define ITAB_BAD_BOOLEAN (-6) +#define ITAB_NOT_ENOUGH_IP (-7) +#define ITAB_BAD_GRAN (-8) +#define ITAB_NOMEM (-9) + +extern uint8_t inittab_type_to_size(dhcp_symbol_t *); +extern int inittab_verify(dhcp_symbol_t *, dhcp_symbol_t *); +extern dhcp_symbol_t *inittab_load(uchar_t, char, size_t *); +extern dhcp_symbol_t *inittab_getbyname(uchar_t, char, const char *); +extern dhcp_symbol_t *inittab_getbycode(uchar_t, char, uint16_t); +extern uchar_t *inittab_encode(dhcp_symbol_t *, const char *, + uint16_t *, boolean_t); +extern uchar_t *inittab_encode_e(dhcp_symbol_t *, const char *, + uint16_t *, boolean_t, int *); +extern char *inittab_decode(dhcp_symbol_t *, uchar_t *, + uint16_t, boolean_t); +extern char *inittab_decode_e(dhcp_symbol_t *, uchar_t *, + uint16_t, boolean_t, int *); + +#ifdef __cplusplus +} +#endif + +#endif /* _DHCP_INITTAB_H */ diff --git a/usr/src/lib/libdhcputil/common/dhcp_symbol.c b/usr/src/lib/libdhcputil/common/dhcp_symbol.c new file mode 100644 index 0000000000..d02d3461a7 --- /dev/null +++ b/usr/src/lib/libdhcputil/common/dhcp_symbol.c @@ -0,0 +1,884 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdlib.h> +#include <ctype.h> +#include <strings.h> +#include <limits.h> +#include <errno.h> +#include <dhcp_impl.h> + +#include "dhcp_symbol.h" + +/* + * The following structure and table are used to define the attributes + * of a DHCP symbol category. + */ +typedef struct dsym_cat { + char *dc_string; /* string value for the category */ + int dc_minlen; /* min. chars of dc_string to match */ + dsym_category_t dc_id; /* numerical value for the category */ + boolean_t dc_dhcptab; /* valid for dhcptab use? */ + ushort_t dc_min; /* minimum valid code */ + ushort_t dc_max; /* maximum valid code */ +} dsym_cat_t; + +static dsym_cat_t cats[DSYM_CATEGORY_NUM] = { + { "Extend", 6, DSYM_EXTEND, B_TRUE, DHCP_LAST_STD + 1, + DHCP_SITE_OPT - 1 }, + { "Vendor=", 6, DSYM_VENDOR, B_TRUE, DHCP_FIRST_OPT, + DHCP_LAST_OPT }, + { "Site", 4, DSYM_SITE, B_TRUE, DHCP_SITE_OPT, DHCP_LAST_OPT }, + { "Standard", 8, DSYM_STANDARD, B_FALSE, DHCP_FIRST_OPT, + DHCP_LAST_STD }, + { "Field", 5, DSYM_FIELD, B_FALSE, CD_PACKET_START, + CD_PACKET_END }, + { "Internal", 8, DSYM_INTERNAL, B_FALSE, CD_INTRNL_START, + CD_INTRNL_END } +}; + +/* + * The following structure and table are used to define the attributes + * of a DHCP symbol type. + */ +typedef struct dsym_type { + char *dt_string; /* string value for the type */ + dsym_cdtype_t dt_id; /* numerical value for the type */ + boolean_t dt_dhcptab; /* valid for dhcptab use? */ +} dsym_type_t; + +static dsym_type_t types[DSYM_CDTYPE_NUM] = { + { "ASCII", DSYM_ASCII, B_TRUE }, + { "OCTET", DSYM_OCTET, B_TRUE }, + { "IP", DSYM_IP, B_TRUE }, + { "NUMBER", DSYM_NUMBER, B_TRUE }, + { "BOOL", DSYM_BOOL, B_TRUE }, + { "INCLUDE", DSYM_INCLUDE, B_FALSE }, + { "UNUMBER8", DSYM_UNUMBER8, B_TRUE }, + { "UNUMBER16", DSYM_UNUMBER16, B_TRUE }, + { "UNUMBER32", DSYM_UNUMBER32, B_TRUE }, + { "UNUMBER64", DSYM_UNUMBER64, B_TRUE }, + { "SNUMBER8", DSYM_SNUMBER8, B_TRUE }, + { "SNUMBER16", DSYM_SNUMBER16, B_TRUE }, + { "SNUMBER32", DSYM_SNUMBER32, B_TRUE }, + { "SNUMBER64", DSYM_SNUMBER64, B_TRUE } +}; + +/* + * symbol delimiters and constants + */ +#define DSYM_CLASS_DEL " \t\n" +#define DSYM_FIELD_DEL "," +#define DSYM_VENDOR_DEL '=' +#define DSYM_QUOTE '"' + +/* + * dsym_trim(): trims all whitespace from either side of a string + * + * input: char **: a pointer to a string to trim of whitespace. + * output: none + */ +static void +dsym_trim(char **str) +{ + + char *tmpstr = *str; + + /* + * Trim all whitespace from the front of the string. + */ + while (*tmpstr != '\0' && isspace(*tmpstr)) { + tmpstr++; + } + + /* + * Move the str pointer to first non-whitespace char. + */ + *str = tmpstr; + + /* + * Check case where the string is nothing but whitespace. + */ + if (*tmpstr == '\0') { + + /* + * Trim all whitespace from the end of the string. + */ + tmpstr = *str + strlen(*str) - 1; + while (tmpstr >= *str && isspace(*tmpstr)) { + tmpstr--; + } + + /* + * terminate after last non-whitespace char. + */ + *(tmpstr+1) = '\0'; + } +} + +/* + * dsym_get_token(): strtok_r() like routine, except consecutive delimiters + * result in an empty string + * + * note: original string is modified + * + * input: char *: string in which to search for tokens + * char *: list of possible token delimiter characters + * char **: location for next call to routine + * boolean_t: should delimiters be ignored if within quoted string? + * output: char *: token, or NULL if no more tokens + */ +static char * +dsym_get_token(char *str, char *dels, char **lasts, boolean_t quote_support) +{ + + char *ptr = str; + char *del; + boolean_t found = B_FALSE; + boolean_t in_quote = B_FALSE; + + /* + * If incoming string has no tokens return a NULL + * pointer to signify no more tokens. + */ + if (*ptr == '\0') { + return (NULL); + } + + /* + * Loop until either a token has been identified or until end + * of string has been reached. + */ + while (!found && *ptr != '\0') { + + /* + * If pointer currently lies within a quoted string, + * then do not check for the delimiter. + */ + if (!in_quote) { + for (del = dels; !found && *del != '\0'; del++) { + if (*del == *ptr) { + *ptr++ = '\0'; + found = B_TRUE; + } + } + } + + /* + * If the pointer is pointing at a delimiter, then + * check to see if it points to at a quote and update + * the state appropriately. + */ + if (!found) { + if (quote_support && *ptr == DSYM_QUOTE) { + in_quote = !in_quote; + } + ptr++; + } + } + + *lasts = ptr; + + return (str); +} + +/* + * dsym_get_long(): given a numeric string, returns its long value + * + * input: const char *: the numeric string + * long *: the return location for the long value + * output: DSYM_SUCCESS, DSYM_VALUE_OUT_OF_RANGE or DSYM_SYNTAX_ERROR + */ +static dsym_errcode_t +dsym_get_long(const char *str, long *val) +{ + + int ret = DSYM_SUCCESS; + int i; + + for (i = 0; str[i] != '\0'; i++) { + if (!isdigit(str[i])) { + return (DSYM_SYNTAX_ERROR); + } + } + + errno = 0; + *val = strtol(str, NULL, 10); + if (errno != 0) { + ret = DSYM_VALUE_OUT_OF_RANGE; + } + + return (ret); +} + +/* + * dsym_free_classes(): frees the classes allocated by dsym_parse_classes() + * + * input: dhcp_classes_t *: pointer to structure containing classes to free + * output: none + */ +void +dsym_free_classes(dhcp_classes_t *classes) +{ + + int i; + + if (classes->dc_names == NULL) { + return; + } + + for (i = 0; i < classes->dc_cnt; i++) { + free(classes->dc_names[i]); + } + + free(classes->dc_names); + classes->dc_names = NULL; + classes->dc_cnt = 0; +} + +/* + * dsym_parse_classes(): given a "Vendor" class string, builds and returns + * the list of vendor classes + * + * input: char *: the "Vendor" class string + * dhcp_classes_t *: pointer to the classes structure + * output: DSYM_SUCCESS, DSYM_INVALID_CAT, DSYM_EXCEEDS_MAX_CLASS_SIZE, + * DSYM_EXCEEDS_CLASS_SIZE, DSYM_SYNTAX_ERROR, or DSYM_NO_MEMORY + */ +static dsym_errcode_t +dsym_parse_classes(char *ptr, dhcp_classes_t *classes_ret) +{ + + char **classes = NULL; + char *cp; + int len; + int ret = DSYM_SUCCESS; + int i; + + while (*ptr != '\0') { + if (*ptr == DSYM_VENDOR_DEL) { + ptr++; + break; + } + ptr++; + } + + if (*ptr == '\0') { + return (DSYM_INVALID_CAT); + } + + if (strlen(ptr) > DSYM_MAX_CLASS_SIZE) { + return (DSYM_EXCEEDS_MAX_CLASS_SIZE); + } + + dsym_trim(&ptr); + classes_ret->dc_cnt = 0; + for (i = 0; ret == DSYM_SUCCESS; i++) { + cp = dsym_get_token(ptr, DSYM_CLASS_DEL, &ptr, B_TRUE); + if (cp == NULL) { + break; + } + + len = strlen(cp); + + if (len == 0) { + continue; + } else if (len > DSYM_CLASS_SIZE) { + ret = DSYM_EXCEEDS_CLASS_SIZE; + continue; + } + + if (cp[0] == DSYM_QUOTE && cp[len-1] != DSYM_QUOTE) { + ret = DSYM_SYNTAX_ERROR; + continue; + } + + /* Strip off the quotes */ + if (cp[0] == DSYM_QUOTE) { + cp[len-1] = '\0'; + cp++; + } + + classes = realloc(classes_ret->dc_names, + (sizeof (char **)) * (classes_ret->dc_cnt + 1)); + if (classes == NULL || + (classes[classes_ret->dc_cnt] = strdup(cp)) + == NULL) { + ret = DSYM_NO_MEMORY; + continue; + } + classes_ret->dc_names = classes; + classes_ret->dc_cnt++; + } + + if (ret != DSYM_SUCCESS) { + dsym_free_classes(classes_ret); + } + + return (ret); +} + +/* + * dsym_get_cat_by_name(): given a category field, returns the pointer to its + * entry in the internal category table. + * + * input: const char *: the category name + * dsym_cat_t *: the return location for the pointer to the table entry + * boolean_t: case-sensitive name compare + * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT + */ +static dsym_errcode_t +dsym_get_cat_by_name(const char *cat, dsym_cat_t **entry, boolean_t cs) +{ + + dsym_cat_t *entryp = NULL; + int ret = DSYM_SUCCESS; + int cnt = sizeof (cats) / sizeof (dsym_cat_t); + int result; + int len; + int i; + + for (i = 0; i < cnt; i++) { + + len = cats[i].dc_minlen; + if (cs) { + result = strncmp(cat, cats[i].dc_string, len); + } else { + result = strncasecmp(cat, cats[i].dc_string, len); + } + + if (result == 0) { + entryp = &cats[i]; + break; + } + } + + if (entryp != NULL) { + /* + * Special code required for the Vendor category, because we + * allow whitespace between the keyword and the delimiter. + * If there is no delimiter, then this is an illegal category. + */ + const char *ptr = cat + entryp->dc_minlen; + if (entryp->dc_id == DSYM_VENDOR) { + while (*ptr != '\0' && isspace(*ptr)) { + ptr++; + } + if (*ptr != DSYM_VENDOR_DEL) { + ret = DSYM_INVALID_CAT; + } + } else { + if (*ptr != '\0') { + ret = DSYM_INVALID_CAT; + } + } + } else { + ret = DSYM_INVALID_CAT; + } + + if (ret == DSYM_SUCCESS) { + *entry = entryp; + } + + return (ret); +} + +/* + * dsym_parse_cat(): given a category field, returns the category value + * Note: The category must be a valid dhcptab category. + * + * input: const char *: a category field + * dsym_category_t *: the return location for the category value + * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT + */ +static dsym_errcode_t +dsym_parse_cat(const char *field, dsym_category_t *cat) +{ + + dsym_cat_t *entry; + int ret; + + ret = dsym_get_cat_by_name(field, &entry, B_TRUE); + if (ret == DSYM_SUCCESS) { + /* + * Since this routine is meant to be used to parse dhcptab + * symbol definitions, only a subset of the DHCP categories + * are valid in this context. + */ + if (entry->dc_dhcptab) { + *cat = entry->dc_id; + } else { + ret = DSYM_INVALID_CAT; + } + } + + return (ret); +} + +/* + * dsym_parse_intrange(): given a DHCP integer field, returns the value + * + * input: const char *: a DHCP code field + * int *: the return location for the value + * int: the minimum valid value + * int: the maximum valid value + * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, or DSYM_VALUE_OUT_OF_RANGE + */ +static dsym_errcode_t +dsym_parse_intrange(const char *field, int *intval, int min, int max) +{ + + int ret; + long longval; + + ret = dsym_get_long(field, &longval); + if (ret == DSYM_SUCCESS) { + if (longval < min || longval > max) { + ret = DSYM_VALUE_OUT_OF_RANGE; + } else { + *intval = (int)longval; + } + } + return (ret); +} + +/* + * dsym_validate_code(): given a symbol category and code, validates + * that the code is valid for the category + * + * input: dsym_category_t: the symbol category + * uint16_t: the symbol code + * output: DSYM_SUCCESS, DSYM_INVALID_CAT or DSYM_CODE_OUT_OF_RANGE + */ +static dsym_errcode_t +dsym_validate_code(dsym_category_t cat, ushort_t code) +{ + + int cnt = sizeof (cats) / sizeof (dsym_cat_t); + int i; + + /* + * Find the category entry from the internal table. + */ + for (i = 0; i < cnt; i++) { + dsym_cat_t *entry; + if (cat == cats[i].dc_id) { + entry = &cats[i]; + if (code < entry->dc_min || code > entry->dc_max) { + return (DSYM_CODE_OUT_OF_RANGE); + } + return (DSYM_SUCCESS); + } + } + + return (DSYM_INVALID_CAT); +} + +/* + * dsym_validate_granularity(): given a symbol type, validates + * that the granularity is valid for the type + * + * input: dsym_cdtype_t: the symbol type + * uchar_t: the symbol granularity + * output: DSYM_SUCCESS or DSYM_VALUE_OUT_OF_RANGE + */ +static dsym_errcode_t +dsym_validate_granularity(dsym_cdtype_t type, uchar_t gran) +{ + /* + * We only need to check for a 0 with non-boolean types, as + * anything else is already validated by the ranges passed to + * dsym_parse_intrange() in dsym_parse_field(). + */ + if (gran == 0 && type != DSYM_BOOL) { + return (DSYM_VALUE_OUT_OF_RANGE); + } + return (DSYM_SUCCESS); +} + +/* + * dsym_get_type_by_name(): given a type field, returns the pointer to its + * entry in the internal type table. + * + * input: const char *: the type name + * dsym_type_t *: the return location for the pointer to the table entry + * boolean_t: case-sensitive name compare + * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE + */ +static dsym_errcode_t +dsym_get_type_by_name(const char *type, dsym_type_t **entry, boolean_t cs) +{ + int cnt = sizeof (types) / sizeof (dsym_type_t); + int result; + int i; + + for (i = 0; i < cnt; i++) { + + if (cs) { + result = strcmp(type, types[i].dt_string); + } else { + result = strcasecmp(type, types[i].dt_string); + } + + if (result == 0) { + *entry = &types[i]; + return (DSYM_SUCCESS); + } + } + + return (DSYM_INVALID_TYPE); +} + +/* + * dsym_parse_type(): given a DHCP type string, returns the type id + * + * input: char *: a DHCP type string + * dsym_cdtype_t *: the return location for the type id + * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE + */ +static dsym_errcode_t +dsym_parse_type(char *field, dsym_cdtype_t *type) +{ + + dsym_type_t *entry; + int ret; + + ret = dsym_get_type_by_name(field, &entry, B_TRUE); + if (ret == DSYM_SUCCESS) { + /* + * Since this routine is meant to be used to parse dhcptab + * symbol definitions, only a subset of the DHCP type + * are valid in this context. + */ + if (entry->dt_dhcptab) { + *type = entry->dt_id; + } else { + ret = DSYM_INVALID_TYPE; + } + } + + return (ret); +} + +/* + * dsym_free_fields(): frees an array of fields allocated by + * dsym_init_parser(). + * + * input: char **: array of fields to free + * output: none + */ +void +dsym_free_fields(char **fields) +{ + int i; + if (fields != NULL) { + for (i = 0; i < DSYM_NUM_FIELDS; i++) { + free(fields[i]); + } + free(fields); + } +} + +/* + * dsym_close_parser(): free up all resources associated with the parser + * + * input: char **: the fields allocated by dsym_init_parser() + * dhcp_symbol_t *: the structure populated by dsym_init_parser() + * output: none + */ +void +dsym_close_parser(char **fields, dhcp_symbol_t *sym) +{ + dsym_free_fields(fields); + dsym_free_classes(&sym->ds_classes); +} + +/* + * dsym_init_parser(): initializes the structures used to parse a symbol + * value. + * + * input: const char *: the symbol name + * const char *: the symbol value in dhcptab format + * char ***: the return location for the symbol fields + * dhcp_symbol_t *: the structure which eventually will + * be the repository for the parsed symbol data + * output: int: DSYM_SUCCESS, DYSM_NO_MEMORY, DSYM_NULL_FIELD or + * DSYM_TOO_MANY_FIELDS + */ +dsym_errcode_t +dsym_init_parser(const char *name, const char *value, char ***fields_ret, + dhcp_symbol_t *sym) +{ + + int ret = DSYM_SUCCESS; + char *cp; + char *next; + char *field; + char **fields; + int i; + + /* + * Initialize the symbol structure. + */ + sym->ds_category = 0; + sym->ds_code = 0; + (void) strlcpy(sym->ds_name, name, DSYM_MAX_SYM_LEN); + sym->ds_type = 0; + sym->ds_gran = 0; + sym->ds_max = 0; + sym->ds_classes.dc_names = NULL; + sym->ds_classes.dc_cnt = 0; + + if ((cp = strdup(value)) == NULL || + (fields = calloc(DSYM_NUM_FIELDS, sizeof (char *))) == NULL) { + ret = DSYM_NO_MEMORY; + } + + next = cp; + for (i = 0; ret == DSYM_SUCCESS && i < DSYM_NUM_FIELDS; i++) { + + field = dsym_get_token(next, DSYM_FIELD_DEL, &next, + B_FALSE); + + if (field == NULL) { + ret = DSYM_NULL_FIELD; + continue; + } + + dsym_trim(&field); + + if (strlen(field) == 0) { + ret = DSYM_NULL_FIELD; + continue; + } + + if ((fields[i] = strdup(field)) == NULL) { + ret = DSYM_NO_MEMORY; + continue; + } + } + + if (ret == DSYM_SUCCESS && + dsym_get_token(next, DSYM_FIELD_DEL, &next, B_FALSE) != NULL) { + ret = DSYM_TOO_MANY_FIELDS; + } + + if (ret != DSYM_SUCCESS) { + dsym_free_fields(fields); + } else { + *fields_ret = fields; + } + + free(cp); + return (ret); +} + +/* + * dsym_parse_field(): parses the specified symbol field. + * + * input: int: the field number to be parsed. + * char **: symbol fields initialized by dsym_init_parser() + * dhcp_symbol_t *: the structure which will be the repository + * for the parsed field + * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, DSYM_CODE_OUT_OF_RANGE, + * DSYM_INVALID_CAT, DSYM_INVALID_TYPE, DSYM_EXCEEDS_CLASS_SIZE, + * DSYM_EXCEEDS_MAX_CLASS_SIZE, DSYM_NO_MEMORY, + * DSYM_INVALID_FIELD_NUM, DSYM_VALUE_OUT_OF_RANGE + */ +dsym_errcode_t +dsym_parse_field(int field_num, char **fields, dhcp_symbol_t *sym) +{ + + int ret = DSYM_SUCCESS; + int intval; + + switch (field_num) { + + case DSYM_CAT_FIELD: + ret = dsym_parse_cat(fields[field_num], &sym->ds_category); + if (ret == DSYM_SUCCESS && sym->ds_category == DSYM_VENDOR) { + ret = dsym_parse_classes(fields[field_num], + &sym->ds_classes); + } + break; + + case DSYM_CODE_FIELD: + ret = dsym_parse_intrange(fields[field_num], &intval, 0, + USHRT_MAX); + if (ret == DSYM_SUCCESS) { + sym->ds_code = (ushort_t)intval; + ret = dsym_validate_code(sym->ds_category, + sym->ds_code); + } + break; + + case DSYM_TYPE_FIELD: + ret = dsym_parse_type(fields[field_num], &sym->ds_type); + break; + + case DSYM_GRAN_FIELD: + ret = dsym_parse_intrange(fields[field_num], &intval, 0, + UCHAR_MAX); + if (ret == DSYM_SUCCESS) { + sym->ds_gran = (uchar_t)intval; + ret = dsym_validate_granularity(sym->ds_type, + sym->ds_gran); + } + break; + + case DSYM_MAX_FIELD: + ret = dsym_parse_intrange(fields[field_num], &intval, 0, + UCHAR_MAX); + if (ret == DSYM_SUCCESS) { + sym->ds_max = (uchar_t)intval; + } + break; + default: + ret = DSYM_INVALID_FIELD_NUM; + } + + return (ret); +} + +/* + * dsym_parser(): parses a DHCP symbol value + * + * input: char **: symbol fields initialized by dsym_init_parser() + * dhcp_symbol_t *: the structure which will be the repository + * for the parsed field + * int *: last field processed + * boolean_t: parse all fields even though errors occur? + * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, DSYM_CODE_OUT_OF_RANGE, + * DSYM_INVALID_CAT, DSYM_INVALID_TYPE, DSYM_EXCEEDS_CLASS_SIZE, + * DSYM_EXCEEDS_MAX_CLASS_SIZE, DSYM_NO_MEMORY + * DSYM_INVALID_FIELD_NUM, DSYM_VALUE_OUT_OF_RANGE + */ +dsym_errcode_t +dsym_parser(char **fields, dhcp_symbol_t *sym, int *lastField, + boolean_t bestEffort) +{ + + int ret = DSYM_SUCCESS; + int tret = DSYM_SUCCESS; + int i; + + *lastField = -1; + for (i = DSYM_FIRST_FIELD; + tret == DSYM_SUCCESS && i < DSYM_NUM_FIELDS; i++) { + + tret = dsym_parse_field(i, fields, sym); + if (tret != DSYM_SUCCESS) { + if (ret == DSYM_SUCCESS) { + ret = tret; + } + if (bestEffort) { + *lastField = i; + tret = DSYM_SUCCESS; + } + } + } + + if (*lastField == -1) { + *lastField = i - 1; + } + + return (ret); +} + +/* + * dsym_get_cat_id(): given a category string, return the associated id. + * + * input: const char *: the category name + * dsym_category_t *: the return location for the id + * boolean_t: case-sensitive name compare + * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT + */ +dsym_errcode_t +dsym_get_cat_id(const char *cat, dsym_category_t *id, boolean_t cs) +{ + + dsym_cat_t *entry; + int ret; + + ret = dsym_get_cat_by_name(cat, &entry, cs); + if (ret == DSYM_SUCCESS) { + *id = entry->dc_id; + } + + return (ret); +} + +/* + * dsym_get_code_ranges(): given a category field, returns its valid code + * ranges. + * + * input: const char *: the category name + * ushort *: return location for the minimum code value. + * ushort *: return location for the maximum code value. + * boolean_t: case-sensitive name compare + * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT + */ +dsym_errcode_t +dsym_get_code_ranges(const char *cat, ushort_t *min, ushort_t *max, + boolean_t cs) +{ + + dsym_cat_t *entry; + int ret; + + ret = dsym_get_cat_by_name(cat, &entry, cs); + if (ret == DSYM_SUCCESS) { + *min = entry->dc_min; + *max = entry->dc_max; + } + + return (ret); +} + +/* + * dsym_get_type_id(): given a type string, return the associated type id. + * + * input: const char *: the type name + * dsym_cdtype_t *: the return location for the id + * boolean_t: case-sensitive name compare + * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE + */ +dsym_errcode_t +dsym_get_type_id(const char *type, dsym_cdtype_t *id, boolean_t cs) +{ + + dsym_type_t *entry; + int ret; + + ret = dsym_get_type_by_name(type, &entry, cs); + if (ret == DSYM_SUCCESS) { + *id = entry->dt_id; + } + + return (ret); +} diff --git a/usr/src/lib/libdhcputil/common/dhcp_symbol.h b/usr/src/lib/libdhcputil/common/dhcp_symbol.h new file mode 100644 index 0000000000..fcfd65c20f --- /dev/null +++ b/usr/src/lib/libdhcputil/common/dhcp_symbol.h @@ -0,0 +1,131 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _DHCP_SYMBOL_H +#define _DHCP_SYMBOL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file, along with <dhcp_symbol_common.h>, contains the DHCP symbol + * constants and the definitions for the external interfaces to the parsing + * logic (contained in dhcp_symbol.c) for symbol definitions. These + * definitions can and should be used by all consumers of DHCP symbols. + */ + +#include <sys/types.h> +#include <dhcp_svc_private.h> +#include <dhcp_symbol_common.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Vendor class length (and implicitly, the number of classes) + */ +#define DSYM_CLASS_SIZE DSVC_MAX_MACSYM_LEN /* Single class max */ +#define DSYM_MAX_CLASS_SIZE (DSYM_CLASS_SIZE * 10) /* At least 10 */ + +/* + * Maximum symbol length is defined by the libdhcpsvc. + */ +#define DSYM_MAX_SYM_LEN DSVC_MAX_MACSYM_LEN + +/* + * symbol parsing error codes + */ +typedef enum { + DSYM_SUCCESS, + DSYM_SYNTAX_ERROR, + DSYM_NULL_FIELD, + DSYM_TOO_MANY_FIELDS, + DSYM_CODE_OUT_OF_RANGE, + DSYM_VALUE_OUT_OF_RANGE, + DSYM_INVALID_CAT, + DSYM_INVALID_TYPE, + DSYM_EXCEEDS_CLASS_SIZE, + DSYM_EXCEEDS_MAX_CLASS_SIZE, + DSYM_NO_MEMORY, + DSYM_INVALID_FIELD_NUM +} dsym_errcode_t; + +/* + * symbol fields + */ +#define DSYM_CAT_FIELD 0 +#define DSYM_CODE_FIELD 1 +#define DSYM_TYPE_FIELD 2 +#define DSYM_GRAN_FIELD 3 +#define DSYM_MAX_FIELD 4 +#define DSYM_NUM_FIELDS 5 +#define DSYM_FIRST_FIELD DSYM_CAT_FIELD + +/* + * This structure is used by the dhcp_symbol_t structure below + * when the option being defined is a vendor option. In which case, + * this structure contains the client classes for which the option + * applies. + */ +typedef struct dhcp_classes { + char **dc_names; + uint8_t dc_cnt; +} dhcp_classes_t; + +/* + * This structure is used to define a DHCP symbol. The structure is + * used by both the inittab parsing routines and by the dhcptab parsing + * routines to define a symbol definition in either of those tables. + */ +typedef struct dhcp_symbol { + dsym_category_t ds_category; /* category */ + ushort_t ds_code; /* option code */ + char ds_name[DSYM_MAX_SYM_LEN + 1]; /* option name */ + dsym_cdtype_t ds_type; /* type of parm */ + uchar_t ds_gran; /* granularity */ + uchar_t ds_max; /* maximum number */ + dhcp_classes_t ds_classes; /* client classes */ +} dhcp_symbol_t; + +extern void dsym_free_fields(char **); +extern void dsym_free_classes(dhcp_classes_t *); +extern void dsym_close_parser(char **, dhcp_symbol_t *); +extern dsym_errcode_t dsym_init_parser(const char *, const char *, char ***, + dhcp_symbol_t *); +extern dsym_errcode_t dsym_parse_field(int, char **, dhcp_symbol_t *); +extern dsym_errcode_t dsym_parser(char **, dhcp_symbol_t *, int *, boolean_t); +extern dsym_errcode_t dsym_get_cat_id(const char *, dsym_category_t *, + boolean_t); +extern dsym_errcode_t dsym_get_code_ranges(const char *cat, ushort_t *, + ushort_t *, boolean_t); +extern dsym_errcode_t dsym_get_type_id(const char *, dsym_cdtype_t *, + boolean_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _DHCP_SYMBOL_H */ diff --git a/usr/src/lib/libdhcputil/common/dhcpmsg.c b/usr/src/lib/libdhcputil/common/dhcpmsg.c new file mode 100644 index 0000000000..5329af5fbf --- /dev/null +++ b/usr/src/lib/libdhcputil/common/dhcpmsg.c @@ -0,0 +1,216 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdarg.h> +#include <errno.h> +#include <stdio.h> +#include <syslog.h> +#include <libintl.h> +#include <string.h> +#include <limits.h> + +#include "dhcpmsg.h" + +static boolean_t is_daemon = B_FALSE; +static boolean_t is_verbose = B_FALSE; +static char program[PATH_MAX] = "<unknown>"; +static int debug_level; + +static const char *err_to_string(int); +static int err_to_syslog(int); + +/* + * dhcpmsg(): logs a message to the console or to syslog + * + * input: int: the level to log the message at + * const char *: a printf-like format string + * ...: arguments to the format string + * output: void + */ + +/*PRINTFLIKE2*/ +void +dhcpmsg(int errlevel, const char *fmt, ...) +{ + va_list ap; + char buf[512]; + char *errmsg; + + if ((errlevel == MSG_DEBUG2 && (debug_level < 2)) || + (errlevel == MSG_DEBUG && (debug_level < 1)) || + (errlevel == MSG_VERBOSE && !is_verbose)) + return; + + va_start(ap, fmt); + + /* + * either log to stderr, or log to syslog. print out unix + * error message if errlevel is MSG_ERR and errno is set + */ + + if (is_daemon) { + (void) snprintf(buf, sizeof (buf), (errlevel == MSG_ERR && + errno != 0) ? "%s: %%m\n" : "%s\n", gettext(fmt)); + (void) vsyslog(err_to_syslog(errlevel), buf, ap); + } else { + errmsg = strerror(errno); + if (errmsg == NULL) + errmsg = dgettext(TEXT_DOMAIN, "<unknown error>"); + + (void) snprintf(buf, sizeof (buf), (errlevel == MSG_ERR && + errno != 0) ? "%s: %s: %s: %s\n" : "%s: %s: %s\n", program, + dgettext(TEXT_DOMAIN, err_to_string(errlevel)), + gettext(fmt), errmsg); + + (void) vfprintf(stderr, buf, ap); + } + + va_end(ap); +} + +/* + * dhcpmsg_init(): opens and initializes the DHCP messaging facility + * + * input: const char *: the name of the executable + * boolean_t: whether the executable is a daemon + * boolean_t: whether the executable is running "verbosely" + * int: the debugging level the executable is being run at + * output: void + */ + +void +dhcpmsg_init(const char *program_name, boolean_t daemon, boolean_t verbose, + int level) +{ + (void) strlcpy(program, program_name, sizeof (program)); + + debug_level = level; + is_verbose = verbose; + + if (daemon) { + is_daemon = B_TRUE; + (void) openlog(program, LOG_PID, LOG_DAEMON); + if (is_verbose) { + syslog(err_to_syslog(MSG_VERBOSE), "%s", + dgettext(TEXT_DOMAIN, "Daemon started")); + } + } +} + +/* + * dhcpmsg_fini(): closes the DHCP messaging facility. + * + * input: void + * output: void + */ + +void +dhcpmsg_fini(void) +{ + if (is_daemon) { + if (is_verbose) { + syslog(err_to_syslog(MSG_VERBOSE), "%s", + dgettext(TEXT_DOMAIN, "Daemon terminated")); + } + closelog(); + } +} + +/* + * err_to_syslog(): converts a dhcpmsg log level into a syslog log level + * + * input: int: the dhcpmsg log level + * output: int: the syslog log level + */ + +static int +err_to_syslog(int errlevel) +{ + switch (errlevel) { + + case MSG_DEBUG: + case MSG_DEBUG2: + return (LOG_DEBUG); + + case MSG_ERROR: + case MSG_ERR: + return (LOG_ERR); + + case MSG_WARNING: + return (LOG_WARNING); + + case MSG_NOTICE: + return (LOG_NOTICE); + + case MSG_CRIT: + return (LOG_CRIT); + + case MSG_VERBOSE: + case MSG_INFO: + return (LOG_INFO); + } + + return (LOG_INFO); +} + +/* + * err_to_string(): converts a log level into a string + * + * input: int: the log level + * output: const char *: the stringified log level + */ + +static const char * +err_to_string(int errlevel) +{ + switch (errlevel) { + + case MSG_DEBUG: + case MSG_DEBUG2: + return ("debug"); + + case MSG_ERR: + case MSG_ERROR: + return ("error"); + + case MSG_WARNING: + return ("warning"); + + case MSG_NOTICE: + return ("notice"); + + case MSG_CRIT: + return ("CRITICAL"); + + case MSG_VERBOSE: + case MSG_INFO: + return ("info"); + } + + return ("<unknown>"); +} diff --git a/usr/src/lib/libdhcputil/common/dhcpmsg.h b/usr/src/lib/libdhcputil/common/dhcpmsg.h new file mode 100644 index 0000000000..822359cd46 --- /dev/null +++ b/usr/src/lib/libdhcputil/common/dhcpmsg.h @@ -0,0 +1,74 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _DHCPMSG_H +#define _DHCPMSG_H + +#pragma ident "%W% %E% SMI" + +#include <sys/types.h> +#include <stdarg.h> +#include <syslog.h> +#include <errno.h> /* since consumers may want to 0 errno */ + +/* + * dhcpmsg.[ch] comprise the interface used to log messages, either to + * syslog(3C), or to the screen, depending on the debug level. see + * dhcpmsg.c for documentation on how to use the exported functions. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * the syslog levels, while useful, do not provide enough flexibility + * to do everything we want. consequently, we introduce another set + * of levels, which map to a syslog level, but also potentially add + * additional behavior. + */ + +enum { + MSG_DEBUG, /* LOG_DEBUG, only if debug_level is 1 */ + MSG_DEBUG2, /* LOG_DEBUG, only if debug_level is 1 or 2 */ + MSG_INFO, /* LOG_INFO */ + MSG_VERBOSE, /* LOG_INFO, only if is_verbose is true */ + MSG_NOTICE, /* LOG_NOTICE */ + MSG_WARNING, /* LOG_WARNING */ + MSG_ERR, /* LOG_ERR, use errno if nonzero */ + MSG_ERROR, /* LOG_ERR */ + MSG_CRIT /* LOG_CRIT */ +}; + +extern void dhcpmsg(int, const char *, ...); +extern void dhcpmsg_init(const char *, boolean_t, boolean_t, int); +extern void dhcpmsg_fini(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _DHCPMSG_H */ diff --git a/usr/src/lib/libdhcputil/common/llib-ldhcputil b/usr/src/lib/libdhcputil/common/llib-ldhcputil new file mode 100644 index 0000000000..799c396a38 --- /dev/null +++ b/usr/src/lib/libdhcputil/common/llib-ldhcputil @@ -0,0 +1,35 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +#include <dhcp_symbol.h> +#include <dhcp_inittab.h> +#include <dhcpmsg.h> +#include <dhcp_impl.h> diff --git a/usr/src/lib/libdhcputil/i386/Makefile b/usr/src/lib/libdhcputil/i386/Makefile new file mode 100644 index 0000000000..f800c19b30 --- /dev/null +++ b/usr/src/lib/libdhcputil/i386/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1999-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%Z%%M% %I% %E% SMI" +# +# lib/libdhcputil/i386/Makefile + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libdhcputil/libdhcputil.xcl b/usr/src/lib/libdhcputil/libdhcputil.xcl new file mode 100644 index 0000000000..f70fae37d1 --- /dev/null +++ b/usr/src/lib/libdhcputil/libdhcputil.xcl @@ -0,0 +1,25 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +msgid "%s: %%m\n" +msgid "%s\n" +msgid "%s: %s: %s: %s\n" +msgid "%s: %s: %s\n" diff --git a/usr/src/lib/libdhcputil/req.flg b/usr/src/lib/libdhcputil/req.flg new file mode 100644 index 0000000000..d7246ea4b0 --- /dev/null +++ b/usr/src/lib/libdhcputil/req.flg @@ -0,0 +1,30 @@ +#!/bin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +find_files "s.*" usr/src/common/net/dhcp diff --git a/usr/src/lib/libdhcputil/sparc/Makefile b/usr/src/lib/libdhcputil/sparc/Makefile new file mode 100644 index 0000000000..b83201c1d5 --- /dev/null +++ b/usr/src/lib/libdhcputil/sparc/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1999-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%Z%%M% %I% %E% SMI" +# +# lib/libdhcputil/sparc/Makefile + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libdhcputil/spec/Makefile b/usr/src/lib/libdhcputil/spec/Makefile new file mode 100644 index 0000000000..ad76aff4a5 --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/Makefile @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1999-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%W% %E% SMI" +# +# lib/libdhcputil/spec/Makefile + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/libdhcputil/spec/Makefile.targ b/usr/src/lib/libdhcputil/spec/Makefile.targ new file mode 100644 index 0000000000..d0cbd76ba4 --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/Makefile.targ @@ -0,0 +1,33 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1999-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%W% %E% SMI" +# +# lib/libdhcputil/spec/Makefile.targ + +LIBRARY = libdhcputil.a +VERS = .1 +OBJECTS = dhcputil.o +SPECCPP = -I../.. -I$(SRC)/common/net/dhcp diff --git a/usr/src/lib/libdhcputil/spec/amd64/Makefile b/usr/src/lib/libdhcputil/spec/amd64/Makefile new file mode 100644 index 0000000000..4ee7613aaf --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/amd64/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +all clean clobber install lint: + @echo "Nothing to $@ on amd64" diff --git a/usr/src/lib/libdhcputil/spec/dhcputil.spec b/usr/src/lib/libdhcputil/spec/dhcputil.spec new file mode 100644 index 0000000000..eaaed806b3 --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/dhcputil.spec @@ -0,0 +1,178 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +#ident "%Z%%M% %I% %E% SMI" +# +# lib/libdhcpagent/spec/dhcputil.spec + +function dhcpmsg +include <dhcpmsg.h> +declaration void dhcpmsg(int level, const char *format, ...) +version SUNWprivate_1.1 +end + +function dhcpmsg_init +include <dhcpmsg.h> +declaration void dhcpmsg_init(const char *program_name, boolean_t \ + is_daemon, boolean_t is_verbose, int debugging_level) +version SUNWprivate_1.1 +end + +function dhcpmsg_fini +include <dhcpmsg.h> +declaration void dhcpmsg_fini(void) +version SUNWprivate_1.1 +end + +function inittab_load +include <dhcp_inittab.h> +declaration dhcp_symbol_t *inittab_load(uchar_t categories, char \ + consumer, size_t *n_entries) +version SUNWprivate_1.1 +end + +function inittab_getbyname +include <dhcp_inittab.h> +declaration dhcp_symbol_t *inittab_getbyname(uchar_t categories, \ + char consumer, const char *name) +version SUNWprivate_1.1 +end + +function inittab_getbycode +include <dhcp_inittab.h> +declaration dhcp_symbol_t *inittab_getbycode(uchar_t categories, \ + char consumer, uint16_t code) +version SUNWprivate_1.1 +end + +function inittab_verify +include <dhcp_inittab.h> +declaration int inittab_verify(dhcp_symbol_t *inittab_entry, \ + dhcp_symbol_t *internal_entry) +version SUNWprivate_1.1 +end + +function inittab_encode +include <dhcp_inittab.h> +declaration uchar_t *inittab_encode(dhcp_symbol_t *inittab_entry, \ + const char *value, uint16_t *lengthp, boolean_t \ + just_payload) +version SUNWprivate_1.1 +end + +function inittab_decode +include <dhcp_inittab.h> +declaration char *inittab_decode(dhcp_symbol_t *inittab_entry, \ + uchar_t *payload, uint16_t length, boolean_t \ + just_payload) +version SUNWprivate_1.1 +end + +function inittab_encode_e +include <dhcp_inittab.h> +declaration uchar_t *inittab_encode_e(dhcp_symbol_t *inittab_entry, \ + const char *value, uint16_t *lengthp, boolean_t \ + just_payload, int *ierrnop) +version SUNWprivate_1.1 +end + +function inittab_decode_e +include <dhcp_inittab.h> +declaration char *inittab_decode_e(dhcp_symbol_t *inittab_entry, \ + uchar_t *payload, uint16_t length, boolean_t \ + just_payload, int *ierrno) +version SUNWprivate_1.1 +end + +function inittab_type_to_size +include <dhcp_inittab.h> +declaration uint8_t inittab_type_to_size(dhcp_symbol_t *inittab_entry) +version SUNWprivate_1.1 +end + +function dsym_close_parser +include <dhcp_symbol.h> +declaration void dsym_close_parser(char **fields, dhcp_symbol_t *sym) +version SUNWprivate_1.1 +end + +function dsym_free_classes +include <dhcp_symbol.h> +declaration void dsym_free_classes(dhcp_classes_t *classes) +version SUNWprivate_1.1 +end + +function dsym_free_fields +include <dhcp_symbol.h> +declaration void dsym_free_fields(char **fields) +version SUNWprivate_1.1 +end + +function dsym_init_parser +include <dhcp_symbol.h> +declaration dsym_errcode_t dsym_init_parser(const char * name, \ + const char *value, char ***fields_ret, dhcp_symbol_t *sym) +version SUNWprivate_1.1 +end + +function dsym_parse_field +include <dhcp_symbol.h> +declaration dsym_errcode_t dsym_parse_field(int field_num, \ + char **fields, dhcp_symbol_t *sym) +version SUNWprivate_1.1 +end + +function dsym_parser +include <dhcp_symbol.h> +declaration dsym_errcode_t dsym_parser(char **fields, dhcp_symbol_t *sym, \ + int *lastField, boolean_t bestEffort) +version SUNWprivate_1.1 +end + +function dsym_get_cat_id +include <dhcp_symbol.h> +declaration dsym_errcode_t dsym_get_cat_id(const char *cat, \ + dsym_category_t *id, boolean_t cs) +version SUNWprivate_1.1 +end + +function dsym_get_code_ranges +include <dhcp_symbol.h> +declaration dsym_errcode_t dsym_get_code_ranges(const char *cat, \ + ushort_t *min, ushort_t *max, boolean_t cs) +version SUNWprivate_1.1 +end + +function dsym_get_type_id +include <dhcp_symbol.h> +declaration dsym_errcode_t dsym_get_type_id(const char *type, \ + dsym_cdtype_t *id, boolean_t cs) +version SUNWprivate_1.1 +end + +function dhcp_options_scan +include <dhcp_impl.h> +declaration int dhcp_options_scan(PKT_LIST *pl, boolean_t scan_vendor) +version SUNWprivate_1.2 +end diff --git a/usr/src/lib/libdhcputil/spec/i386/Makefile b/usr/src/lib/libdhcputil/spec/i386/Makefile new file mode 100644 index 0000000000..6ad76c1208 --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/i386/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1999-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%W% %E% SMI" +# +# lib/libdhcputil/spec/i386/Makefile + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libdhcputil/spec/sparc/Makefile b/usr/src/lib/libdhcputil/spec/sparc/Makefile new file mode 100644 index 0000000000..4aba178c6f --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/sparc/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1999-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%W% %E% SMI" +# +# lib/libdhcputil/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libdhcputil/spec/sparcv9/Makefile b/usr/src/lib/libdhcputil/spec/sparcv9/Makefile new file mode 100644 index 0000000000..86fdf91c6b --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/sparcv9/Makefile @@ -0,0 +1,33 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1999-2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%W% %E% SMI" +# +# lib/libdhcputil/spec/sparcv9/Makefile + +.KEEP_STATE: + +all clean clobber install lint: + @echo "Nothing to $@ on sparcv9" diff --git a/usr/src/lib/libdhcputil/spec/versions b/usr/src/lib/libdhcputil/spec/versions new file mode 100644 index 0000000000..05e8e3e9ca --- /dev/null +++ b/usr/src/lib/libdhcputil/spec/versions @@ -0,0 +1,43 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# ident "%Z%%M% %I% %E% SMI" +# + +sparc { + SUNWprivate_1.2: {SUNWprivate_1.1}; + SUNWprivate_1.1; +} +sparcv9 { + SUNWprivate_1.2: {SUNWprivate_1.1}; + SUNWprivate_1.1; +} +i386 { + SUNWprivate_1.2: {SUNWprivate_1.1}; + SUNWprivate_1.1; +} +amd64 { + SUNWprivate_1.2: {SUNWprivate_1.1}; + SUNWprivate_1.1; +} |