2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * forward declaration of our internal inittab_table[]. too bulky to put 2N/A * up front -- check the end of this file for its definition. 2N/A * Note: we have only an IPv4 version here. The inittab_verify() function is 2N/A * used by the DHCP server and manager. We'll need a new function if the 2N/A * server is extended to DHCPv6. 2N/A * the number of fields in the inittab and names for the fields. note that 2N/A * this order is meaningful to parse_entry(); other functions should just 2N/A * use them as indexes into the array returned from parse_entry(). 2N/A * the category_map_entry_t is used to map the inittab category codes to 2N/A * the dsym codes. the reason the codes are different is that the inittab 2N/A * needs to have the codes be ORable such that queries can retrieve more 2N/A * than one category at a time. this map is also used to map the inittab 2N/A * string representation of a category to its numerical code. 2N/A * inittab_load(): returns all inittab entries with the specified criteria 2N/A * input: uchar_t: the categories the consumer is interested in 2N/A * char: the consumer type of the caller 2N/A * size_t *: set to the number of entries returned 2N/A * output: dhcp_symbol_t *: an array of dynamically allocated entries 2N/A * on success, NULL upon failure 2N/A * inittab_getbyname(): returns an inittab entry with the specified criteria 2N/A * input: int: the categories the consumer is interested in 2N/A * char: the consumer type of the caller 2N/A * char *: the name of the inittab entry the consumer wants 2N/A * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure 2N/A * on success, NULL upon failure 2N/A * inittab_getbycode(): returns an inittab entry with the specified criteria 2N/A * input: uchar_t: the categories the consumer is interested in 2N/A * char: the consumer type of the caller 2N/A * uint16_t: the code of the inittab entry the consumer wants 2N/A * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure 2N/A * on success, NULL upon failure 2N/A * inittab_lookup(): returns inittab entries with the specified criteria 2N/A * input: uchar_t: the categories the consumer is interested in 2N/A * char: the consumer type of the caller 2N/A * const char *: the name of the entry the caller is interested 2N/A * in, or NULL if the caller doesn't care 2N/A * int32_t: the code the caller is interested in, or -1 if the 2N/A * caller doesn't care 2N/A * size_t *: set to the number of entries returned 2N/A * output: dhcp_symbol_t *: dynamically allocated dhcp_symbol structures 2N/A * on success, NULL upon failure 2N/A * make sure the string didn't overflow our buffer 2N/A * skip `pure comment' lines 2N/A * parse the entry out into fields. 2N/A * validate the values in the entries; skip if invalid. 2N/A * find out whether this entry of interest to our consumer, 2N/A * and if so, throw it onto the set of entries we'll return. 2N/A * check categories last since it's the most expensive check. 2N/A * looks like a match. allocate an entry and fill it in 2N/A * if we run out of memory, might as well return what we can 2N/A "allocating dhcp_symbol_t's");
2N/A * parse_entry(): parses an entry out into its constituent fields 2N/A * input: char *: the entry 2N/A * char **: an array of ITAB_FIELDS length which contains 2N/A * pointers into the entry on upon return 2N/A * output: boolean_t: B_TRUE on success, B_FALSE on failure 2N/A * due to a mistake made long ago, the first and second fields of 2N/A * each entry are not separated by a comma, but rather by 2N/A * whitespace -- have bufsplit() treat the two fields as one, then 2N/A * pull them apart afterwards. 2N/A * pull the first and second fields apart. this is complicated 2N/A * since the first field can contain embedded whitespace (so we 2N/A * must separate the two fields by the last span of whitespace). 2N/A * first, find the initial span of whitespace. if there isn't one, 2N/A * then the entry is malformed. 2N/A * find the last span of whitespace. 2N/A * NUL-terminate the first byte of the last span of whitespace, so 2N/A * that the first field doesn't have any residual trailing 2N/A * remove any whitespace from the fields. 2N/A * inittab_verify(): verifies that a given inittab entry matches an internal 2N/A * input: dhcp_symbol_t *: the inittab entry to verify 2N/A * dhcp_symbol_t *: if non-NULL, a place to store the internal 2N/A * inittab entry upon return 2N/A * output: int: ITAB_FAILURE, ITAB_SUCCESS, or ITAB_UNKNOWN 2N/A * get_hw_type(): interpret ",hwtype" in the input string, as part of a DUID. 2N/A * The hwtype string is optional, and must be 0-65535 if 2N/A * input: char **: pointer to string pointer 2N/A * int *: error return value 2N/A * output: int: hardware type, or -1 for empty, or -2 for error. 2N/A * get_mac_addr(): interpret ",macaddr" in the input string, as part of a DUID. 2N/A * The 'macaddr' may be a hex string (in any standard format), 2N/A * or the name of a physical interface. If an interface name 2N/A * is given, then the interface type is extracted as well. 2N/A * input: const char *: input string 2N/A * int *: error return value 2N/A * uint16_t *: hardware type output (network byte order) 2N/A * int: hardware type input; -1 for empty 2N/A * uchar_t *: output buffer for MAC address 2N/A * output: int: length of MAC address, or -1 for error 2N/A * Allow MAC addresses with separators matching regexp 2N/A * inittab_encode_e(): converts a string representation of a given datatype into 2N/A * binary; used for encoding ascii values into a form that 2N/A * can be put in DHCP packets to be sent on the wire. 2N/A * input: const dhcp_symbol_t *: the entry describing the value option 2N/A * const char *: the value to convert 2N/A * uint16_t *: set to the length of the binary data returned 2N/A * boolean_t: if false, return a full DHCP option 2N/A * int *: error return value 2N/A * output: uchar_t *: a dynamically allocated byte array with converted data 2N/A * Maximum (worst-case) encoded length is one byte more than 2N/A * the number of characters on input. 2N/A /* Worst case is ":::::" */ 2N/A * figure out the number of entries by counting the spaces 2N/A * in the value string 2N/A * if we're gonna return a complete option, then include the 2N/A * option length and code in the size of the packet we allocate 2N/A * Note that this encoder always presents the trailing 0-octet 2N/A * when dealing with a list. This means that you can't have 2N/A * non-fully-qualified members anywhere but at the end of a 2N/A * list (or as the only member of the list). 2N/A * Skip over whitespace that delimits list members. 2N/A * Just copy non-ASCII text directly to the 2N/A * output string. This simplifies the use of 2N/A * other ctype macros below, as, unlike the 2N/A * special isascii function, they don't handle 2N/A * Handle any of \D, \DD, or \DDD for 2N/A * User terminated \D or \DD 2N/A * with non-digit. An error, 2N/A * but we can assume he means 2N/A * to treat as \00D or \0DD. 2N/A /* Fall through and copy character */ 2N/A * End of component. Write the length 2N/A * prefix. If the component is zero 2N/A * length (i.e., ".."), the just omit 2N/A * Unescaped space; end of domain name 2N/A * Handle trailing escape sequence. If string ends 2N/A * with \, then assume user wants \ at end of encoded 2N/A * string. If it ends with \D or \DD, assume \00D or 2N/A * If user specified FQDN with trailing '.', then above 2N/A * will result in zero for the last component length. 2N/A * We're done, and optstart already points to the start 2N/A * of the next in list. Otherwise, we need to write a 2N/A * single zero byte to end the entry, if there are more 2N/A * entries that will be decoded. 2N/A /* Call libinetutil function to decode */ 2N/A "not compatible with option granularity");
2N/A * if just_payload is false, then we need to add the option 2N/A * code and length fields in. 2N/A /* LINTED: alignment */ 2N/A * get_dhcpopt_code(): converts a string representation of a given DHCP option 2N/A * into the DHCP option code. Returns -1 if the given DHCP 2N/A * option string wasn't found in dhcp_inittab(5). 2N/A * input: const char *: the DHCP option string to convert 2N/A * output: int: the DHCP option code on success and -1 on failure. 2N/A * validate_servervalue(): validate the DHCP option value received from the 2N/A * DHCP server. Only checks hostname related options. 2N/A * input: ushort_t: the DHCP option code of the value to be checked. 2N/A * const char *: the DHCP option value to check. 2N/A * output: boolean_t: B_TRUE on success and B_FALSE on failure. 2N/A /* Validate any hostname or domain name option value */ 2N/A * inittab_decode_e(): converts a binary representation of a given datatype into 2N/A * a string; used for decoding DHCP options in a packet off 2N/A * the wire into ascii 2N/A * input: dhcp_symbol_t *: the entry describing the payload option 2N/A * uchar_t *: the payload to convert 2N/A * uint16_t: the payload length (only used if just_payload is true) 2N/A * boolean_t: if false, payload is assumed to be a DHCP option 2N/A * int *: set to extended error code if error occurs. 2N/A * output: char *: a dynamically allocated string containing the converted data 2N/A * figure out the number of elements to convert. note that 2N/A * for ds_type NUMBER, the granularity is really 1 since the 2N/A * value of ds_gran is the number of bytes in the number. 2N/A * A valid, decoded RFC 1035 domain string or sequence of 2N/A * strings is always the same size as the encoded form, but we 2N/A * allow for RFC 1035 \DDD and \\ and \. escaping. 2N/A * Decoding stops at the end of the input or the first coding 2N/A * violation. Coding violations result in discarding the 2N/A * offending list entry entirely. Note that we ignore the 255 2N/A * character overall limit on domain names. 2N/A /* Upper two bits of length must be zero */ 2N/A * First, determine the type of DUID. We need at least two 2N/A * octets worth of data to grab the type code. Once we have 2N/A * that, the number of octets required for representation 2N/A * depends on the type. 2N/A "not compatible with option granularity");
2N/A * inittab_encode(): converts a string representation of a given datatype into 2N/A * binary; used for encoding ascii values into a form that 2N/A * can be put in DHCP packets to be sent on the wire. 2N/A * input: dhcp_symbol_t *: the entry describing the value option 2N/A * const char *: the value to convert 2N/A * uint16_t *: set to the length of the binary data returned 2N/A * boolean_t: if false, return a full DHCP option 2N/A * output: uchar_t *: a dynamically allocated byte array with converted data 2N/A * inittab_decode(): converts a binary representation of a given datatype into 2N/A * a string; used for decoding DHCP options in a packet off 2N/A * the wire into ascii 2N/A * input: dhcp_symbol_t *: the entry describing the payload option 2N/A * uchar_t *: the payload to convert 2N/A * uint16_t: the payload length (only used if just_payload is true) 2N/A * boolean_t: if false, payload is assumed to be a DHCP option 2N/A * output: char *: a dynamically allocated string containing the converted data 2N/A * inittab_msg(): prints diagnostic messages if INITTAB_DEBUG is set 2N/A * const char *: a printf-like format string 2N/A * ...: arguments to the format string 2N/A * check DHCP_INITTAB_DEBUG the first time in; thereafter, use 2N/A * the the cached result (stored in `action'). 2N/A /* FALLTHRU into INITTAB_MSG_OUTPUT */ 2N/A * decode_number(): decodes a sequence of numbers from binary into ascii; 2N/A * binary is coming off of the network, so it is in nbo 2N/A * input: uint8_t: the number of "granularity" numbers to decode 2N/A * uint8_t: the length of each number 2N/A * boolean_t: whether the numbers should be considered signed 2N/A * uint8_t: the number of numbers per granularity 2N/A * const uint8_t *: where to decode the numbers from 2N/A * char *: where to decode the numbers to 2N/A * output: boolean_t: true on successful conversion, false on failure 2N/A "not compatible with option granularity");
2N/A * encode_number(): encodes a sequence of numbers from ascii into binary; 2N/A * number will end up on the wire so it needs to be in nbo 2N/A * input: uint8_t: the number of "granularity" numbers to encode 2N/A * uint8_t: the length of each number 2N/A * boolean_t: whether the numbers should be considered signed 2N/A * uint8_t: the number of numbers per granularity 2N/A * const uint8_t *: where to encode the numbers from 2N/A * char *: where to encode the numbers to 2N/A * int *: set to extended error code if error occurs. 2N/A * output: boolean_t: true on successful conversion, false on failure 2N/A "not compatible with option granularity");
2N/A * totally obscure c factoid: it is legal to pass a 2N/A * string representing a negative number to strtoul(). 2N/A * in this case, strtoul() will return an unsigned 2N/A * long that if cast to a long, would represent the 2N/A * negative number. we take advantage of this to 2N/A * cut down on code here. 2N/A * inittab_type_to_size(): given an inittab entry, returns size of one entry of 2N/A * input: dhcp_symbol_t *: an entry of the given type 2N/A * output: uint8_t: the size in bytes of an entry of that type 2N/A * itabcode_to_dsymcode(): maps an inittab category code to its dsym 2N/A * input: uchar_t: the inittab category code 2N/A * output: dsym_category_t: the dsym category code 2N/A * category_to_code(): maps a category name to its numeric representation 2N/A * input: const char *: the category name 2N/A * output: uchar_t: its internal code (numeric representation) 2N/A * our internal table of DHCP option values, used by inittab_verify() 2N/A{ 0, 0,
"", 0, 0, 0 }