├── .gitignore ├── dhcp.pcap ├── dhcpdiscover.raw ├── dhcprequest.raw ├── Makefile ├── logging.h ├── args.h ├── config.sh ├── README.md ├── launch_server.sh ├── dhcp.h ├── dhcpserver.h ├── bindings.h ├── args.c ├── bindings.c ├── options.h ├── options.c ├── dhcpserver.c ├── queue.h └── rfc2132.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | -------------------------------------------------------------------------------- /dhcp.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crossbowerbt/dhcpserver/HEAD/dhcp.pcap -------------------------------------------------------------------------------- /dhcpdiscover.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crossbowerbt/dhcpserver/HEAD/dhcpdiscover.raw -------------------------------------------------------------------------------- /dhcprequest.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crossbowerbt/dhcpserver/HEAD/dhcprequest.raw -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -ggdb 3 | OBJS = args.o bindings.o dhcpserver.o options.o 4 | 5 | .c.o: 6 | $(CC) -c -o $@ $< $(CFLAGS) 7 | 8 | dhcpserver: $(OBJS) 9 | $(CC) -o $@ $^ $(CFLAGS) 10 | 11 | clean: 12 | rm -f $(OBJS) dhcpserver 13 | -------------------------------------------------------------------------------- /logging.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * Logging macros 5 | */ 6 | 7 | #define log_info(str, ...) do { \ 8 | printf((str), __VA_ARGS__); \ 9 | printf("\n"); \ 10 | } while(0); 11 | 12 | 13 | #define log_error(str, ...) do { \ 14 | fprintf(stderr, (str), __VA_ARGS__); \ 15 | fprintf(stderr, "\n"); \ 16 | } while(0); 17 | -------------------------------------------------------------------------------- /args.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "dhcpserver.h" 5 | 6 | #define NAME "dhcpserver" 7 | #define VERSION "v. 0.1" 8 | 9 | #define USAGE_TXT \ 10 | NAME " - " VERSION "\n" \ 11 | "usage: [-a first,last] [-d device] [-o opt,value]\n" \ 12 | " [-p time] [-s mac,ip] server_address\n" 13 | 14 | /* 15 | * Usage description: 16 | * -a: specify the pool of free addresses to allocate 17 | * -d: network device name to use 18 | * -o: specify a DHCP option for the pool 19 | * -p: time in the pending state (in seconds) 20 | * -s: specify a static binding 21 | */ 22 | 23 | /* Prototypes */ 24 | 25 | void usage(char *msg, int exit_status); 26 | void parse_args(int argc, char *argv[], address_pool *pool); 27 | -------------------------------------------------------------------------------- /config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | INTERFACE='eth0' 4 | 5 | # get IP address (of the DHCP server) cofigured on the specified interface 6 | IP_ADDRESS=`ifconfig $INTERFACE | awk '/inet /{ print $2 }'` 7 | 8 | # get network mask 9 | NETWORK_MASK=`ifconfig $INTERFACE | awk '/netmask /{ print $4 }'` 10 | 11 | # get default gateway router 12 | DEFAULT_GATEWAY=`route -n | grep $INTERFACE | awk '/UG/{print $2}'` 13 | 14 | # user defined pool of addresses 15 | POOL_START='192.168.1.50' 16 | POOL_END='192.168.1.99' 17 | 18 | # default duration of the lease (in seconds) 19 | DEFAULT_LEASE_TIME='1800' 20 | 21 | # max acceptable lease time requested by a client (in seconds) 22 | MAX_LEASE_TIME='3600' 23 | 24 | # how long to consider an offered address in the pending state (in seconds) 25 | PENDING_TIME='30' 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DHCP Server 2 | ========== 3 | 4 | A stand-alone DHCP server, implemented as an attempt to better grasp the chaos which is the current descendant of the good ol' BOOTP. 5 | 6 | Implemented in pure C, no dependencies. Still in beta :) 7 | 8 | Usage 9 | ----- 10 | 11 | You can either launch the binary file directly, specifying all the required options, or use the launch_server.sh script, that also includes the configuration. 12 | 13 | Configuration 14 | ------------- 15 | 16 | Portability was one of the objectives I had in mind while writing the code. 17 | 18 | Since system and library calls used to retrieve informations (such as MAC addresses, IP addresses and other network-related stuff) differ greatly between *linux, *bsd and other unix-like systems, I decided to "outsource" them into a shell script. 19 | 20 | The launch_server.sh contains all the configuration the server requires to run. Give a look at it, and you will understand how to use the program and how to configure it... 21 | 22 | License 23 | ------- 24 | 25 | Copyright 2014 - Emanuele Acri 26 | 27 | Offer me a coffee license: use the code as you wish, but offer me a coffee :) 28 | 29 | 30 | -------------------------------------------------------------------------------- /launch_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # interface to use 4 | interface='wlp3s0' 5 | 6 | # server ip configs 7 | server_id=`ifconfig $interface | grep 'inet[^6]' | awk '{print $2}'` 8 | netmask=`ifconfig $interface | grep 'netmask' | awk '{print $4}'` 9 | gateway=`route -n | grep $interface | grep UG | awk '{ print $2}'` 10 | broadcast=`ifconfig $interface | grep 'broadcast' | awk '{print $6}'` 11 | 12 | # address pool 13 | first='192.168.1.20' 14 | last='192.168.1.25' 15 | 16 | # DHCP options (timers, in seconds) 17 | pending_time=30 18 | lease_time=3600 19 | renewal_time=1800 20 | rebinding_time=3000 21 | 22 | # other DHCP options 23 | dns_server='208.67.222.222' 24 | domain='mynet.org' 25 | 26 | ./dhcpserver \ 27 | -o ROUTER,$gateway \ 28 | -o SUBNET_MASK,$netmask \ 29 | -o IP_ADDRESS_LEASE_TIME,$lease_time \ 30 | -o RENEWAL_T1_TIME_VALUE,$renewal_time \ 31 | -o REBINDING_T2_TIME_VALUE,$rebinding_time \ 32 | -o BROADCAST_ADDRESS,$broadcast \ 33 | -o DOMAIN_NAME,$domain \ 34 | -o DOMAIN_NAME_SERVER,$dns_server \ 35 | -a $first,$last \ 36 | -p $pending_time \ 37 | -d $interface \ 38 | $server_id 39 | -------------------------------------------------------------------------------- /dhcp.h: -------------------------------------------------------------------------------- 1 | #ifndef DHCP_H 2 | #define DHCP_H 3 | 4 | #include 5 | 6 | enum ports { 7 | BOOTPS = 67, 8 | BOOTPC = 68 9 | }; 10 | 11 | enum op_types { 12 | BOOTREQUEST = 1, 13 | BOOTREPLY = 2, 14 | }; 15 | 16 | enum hardware_address_types { 17 | ETHERNET = 0x01, 18 | ETHERNET_LEN = 0x06, 19 | }; 20 | 21 | /* DHCP message */ 22 | 23 | enum { 24 | DHCP_HEADER_SIZE = 236 // without size of options 25 | }; 26 | 27 | struct dhcp_message { 28 | uint8_t op; // message op code, message type 29 | uint8_t htype; // hardware address type 30 | uint8_t hlen; // hardware address length 31 | uint8_t hops; // incremented by relay agents 32 | 33 | uint32_t xid; // transaction ID 34 | 35 | uint16_t secs; // seconds since address acquisition or renewal 36 | uint16_t flags; // flags 37 | 38 | uint32_t ciaddr; // client IP address 39 | uint32_t yiaddr; // 'your' client IP address 40 | uint32_t siaddr; // IP address of the next server to use in bootstrap 41 | uint32_t giaddr; // relay agent IP address 42 | 43 | uint8_t chaddr[16]; // client hardware address 44 | 45 | uint8_t sname[64]; // server host name 46 | 47 | uint8_t file[128]; // boot file name 48 | 49 | uint8_t options[312]; // optional parameters field 50 | }; 51 | 52 | typedef struct dhcp_message dhcp_message; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /dhcpserver.h: -------------------------------------------------------------------------------- 1 | #ifndef DHCPSERVER_H 2 | #define DHCPSERVER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "queue.h" 8 | #include "dhcp.h" 9 | #include "options.h" 10 | #include "bindings.h" 11 | 12 | /* 13 | * Global association pool. 14 | * 15 | * The (static or dynamic) associations tables of the DHCP server, 16 | * are maintained in this global structure. 17 | * 18 | * Note: all the IP addresses are in host order, 19 | * to allow an easy manipulation. 20 | */ 21 | 22 | struct address_pool { 23 | uint32_t server_id; // this server id (IP address) 24 | uint32_t netmask; // network mask 25 | uint32_t gateway; // network gateway 26 | 27 | char device[16]; // network device to use 28 | 29 | pool_indexes indexes; // used to delimitate a pool of available addresses 30 | 31 | time_t lease_time; // default lease time 32 | time_t pending_time; // duration of a binding in the pending state 33 | 34 | dhcp_option_list options; // options for this pool, see queue 35 | 36 | binding_list bindings; // associated addresses, see queue(3) 37 | }; 38 | 39 | typedef struct address_pool address_pool; 40 | 41 | /* 42 | * Internal representation of a DHCP message, 43 | * with options parsed into a list... 44 | */ 45 | 46 | struct dhcp_msg { 47 | dhcp_message hdr; 48 | dhcp_option_list opts; 49 | }; 50 | 51 | typedef struct dhcp_msg dhcp_msg; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /bindings.h: -------------------------------------------------------------------------------- 1 | #ifndef BINDINGS_H 2 | #define BINDINGS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "queue.h" 8 | #include "options.h" 9 | 10 | /* 11 | * Header to manage the database of address bindings. 12 | */ 13 | 14 | // static association or dynamic 15 | enum { 16 | DYNAMIC = 0, 17 | STATIC = 1, 18 | STATIC_OR_DYNAMIC = 2 19 | }; 20 | 21 | // binding status 22 | enum { 23 | EMPTY = 0, 24 | ASSOCIATED, 25 | PENDING, 26 | EXPIRED, 27 | RELEASED 28 | }; 29 | 30 | /* 31 | * IP address used to delimitate an address pool. 32 | */ 33 | 34 | struct pool_indexes { 35 | uint32_t first; // first address of the pool 36 | uint32_t last; // last address of the pool 37 | uint32_t current; // current available address 38 | }; 39 | 40 | typedef struct pool_indexes pool_indexes; 41 | 42 | /* 43 | * The bindings are organized as a double linked list 44 | * using the standard queue(3) library 45 | */ 46 | 47 | struct address_binding { 48 | uint32_t address; // address 49 | uint8_t cident_len; // client identifier len 50 | uint8_t cident[256]; // client identifier 51 | 52 | time_t binding_time; // time of binding 53 | time_t lease_time; // duration of lease 54 | 55 | int status; // binding status 56 | int is_static; // check if it is a static binding 57 | 58 | LIST_ENTRY(address_binding) pointers; // list pointers, see queue(3) 59 | }; 60 | 61 | typedef struct address_binding address_binding; 62 | 63 | typedef LIST_HEAD(binding_list_, address_binding) BINDING_LIST_HEAD; 64 | typedef struct binding_list_ binding_list; 65 | 66 | /* 67 | * Prototypes 68 | */ 69 | 70 | void init_binding_list (binding_list *list); 71 | 72 | address_binding *add_binding (binding_list *list, uint32_t address, uint8_t *cident, uint8_t cident_len, int is_static); 73 | void remove_binding (address_binding *binding); 74 | 75 | void update_bindings_statuses (binding_list *list); 76 | 77 | address_binding *search_binding (binding_list *list, uint8_t *cident, uint8_t cident_len, int is_static, int status); 78 | address_binding *new_dynamic_binding (binding_list *list, pool_indexes *indexes, uint32_t address, uint8_t *cident, uint8_t cident_len); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /args.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "args.h" 11 | #include "options.h" 12 | 13 | void usage(char *msg, int exit_status) 14 | { 15 | fprintf(exit_status == 0 ? stdout : stderr, 16 | "%s", USAGE_TXT); 17 | 18 | if (msg) { 19 | fprintf(exit_status == 0 ? stdout : stderr, 20 | "\n%s\n", msg); 21 | } 22 | 23 | exit(exit_status); 24 | } 25 | 26 | void parse_args(int argc, char *argv[], address_pool *pool) 27 | { 28 | int c; 29 | 30 | opterr = 0; 31 | 32 | while ((c = getopt (argc, argv, "a:d:o:p:s:")) != -1) 33 | switch (c) { 34 | 35 | case 'a': // parse IP address pool 36 | { 37 | char *opt = strdup(optarg); 38 | char *sfirst = opt; 39 | char *slast = strchr(opt, ','); 40 | 41 | if (slast == NULL) 42 | usage("error: comma not present in option -a.", 1); 43 | *slast = '\0'; 44 | slast++; 45 | 46 | uint32_t *first, *last; 47 | 48 | if (parse_ip(sfirst, (void **)&first) != 4) 49 | usage("error: invalid first ip in address pool.", 1); 50 | 51 | if (parse_ip(slast, (void **)&last) != 4) 52 | usage("error: invalid last ip in address pool.", 1); 53 | 54 | pool->indexes.first = *first; 55 | pool->indexes.last = *last; 56 | pool->indexes.current = *first; 57 | 58 | free(first); 59 | free(last); 60 | free(opt); 61 | 62 | break; 63 | } 64 | 65 | case 'd': // network device to use 66 | { 67 | strncpy(pool->device, optarg, sizeof(pool->device)); 68 | break; 69 | } 70 | 71 | case 'o': // parse dhcp option 72 | { 73 | uint8_t id; 74 | 75 | char *opt = strdup(optarg); 76 | char *name = opt; 77 | char *value = strchr(opt, ','); 78 | 79 | if (value == NULL) 80 | usage("error: comma not present in option -o.", 1); 81 | *value = '\0'; 82 | value++; 83 | 84 | dhcp_option *option = calloc(1, sizeof(*option)); 85 | 86 | if((id = parse_option(option, name, value)) == 0) { 87 | char msg[128]; 88 | snprintf(msg, sizeof(msg), 89 | "error: invalid dhcp option specified: %s,%s", 90 | name, value); 91 | usage(msg, 1); 92 | } 93 | 94 | append_option(&pool->options, option); 95 | 96 | if(option->id == IP_ADDRESS_LEASE_TIME) 97 | pool->lease_time = ntohl(*((uint32_t *)option->data)); 98 | 99 | free(option); 100 | free(opt); 101 | break; 102 | } 103 | 104 | case 'p': // parse pending time 105 | { 106 | time_t *t; 107 | 108 | if(parse_long(optarg, (void **)&t) != 4) 109 | usage("error: invalid pending time.", 1); 110 | 111 | pool->pending_time = *t; 112 | free(t); 113 | break; 114 | } 115 | 116 | case 's': // static binding 117 | { 118 | char *opt = strdup(optarg); 119 | char *shw = opt; 120 | char *sip = strchr(opt, ','); 121 | 122 | if (sip == NULL) 123 | usage("error: comma not present in option -s.", 1); 124 | *sip = '\0'; 125 | sip++; 126 | 127 | uint32_t *ip; 128 | uint8_t *hw; 129 | 130 | if (parse_mac(shw, (void **)&hw) != 6) 131 | usage("error: invalid mac address in static binding.", 1); 132 | 133 | if (parse_ip(sip, (void **)&ip) != 4) 134 | usage("error: invalid ip in static binding.", 1); 135 | 136 | add_binding(&pool->bindings, *ip, hw, 6, 1); 137 | 138 | free(ip); 139 | free(hw); 140 | free(opt); 141 | break; 142 | } 143 | 144 | case '?': 145 | default: 146 | usage(NULL, 1); 147 | } 148 | 149 | if(optind >= argc) 150 | usage("error: server address not provided.", 1); 151 | 152 | uint32_t *ip; 153 | 154 | if (parse_ip(argv[optind], (void **)&ip) != 4) 155 | usage("error: invalid server address.", 1); 156 | 157 | pool->server_id = *ip; 158 | 159 | free(ip); 160 | } 161 | -------------------------------------------------------------------------------- /bindings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "queue.h" 8 | #include "bindings.h" 9 | 10 | /* 11 | * Initialize the binding list. 12 | */ 13 | 14 | void 15 | init_binding_list (binding_list *list) 16 | { 17 | LIST_INIT(list); 18 | } 19 | 20 | /* 21 | * Create a new binding 22 | * 23 | * The binding is added to the binding list, 24 | * and a pointer to the binding is returned for further manipulations. 25 | */ 26 | 27 | address_binding * 28 | add_binding (binding_list *list, uint32_t address, 29 | uint8_t *cident, uint8_t cident_len, int is_static) 30 | { 31 | // fill binding 32 | 33 | address_binding *binding = calloc(1, sizeof(*binding)); 34 | 35 | binding->address = address; 36 | binding->cident_len = cident_len; 37 | memcpy(binding->cident, cident, cident_len); 38 | 39 | binding->is_static = is_static; 40 | 41 | // add to binding list 42 | 43 | LIST_INSERT_HEAD(list, binding, pointers); 44 | 45 | return binding; 46 | } 47 | 48 | /* 49 | * Updated bindings status, i.e. set to EXPIRED the status of the 50 | * expired bindings. 51 | */ 52 | 53 | void 54 | update_bindings_statuses (binding_list *list) 55 | { 56 | address_binding *binding, *binding_temp; 57 | 58 | LIST_FOREACH_SAFE(binding, list, pointers, binding_temp) { 59 | if(binding->binding_time + binding->lease_time < time(NULL)) { 60 | binding->status = EXPIRED; 61 | } 62 | } 63 | } 64 | 65 | /* 66 | * Search a static or dynamic binding having the given client identifier. 67 | * 68 | * If the is_static option is true a static binding will be searched, 69 | * otherwise a dynamic one. If status is not zero, an binding with that 70 | * status will be searched. 71 | */ 72 | 73 | address_binding * 74 | search_binding (binding_list *list, uint8_t *cident, uint8_t cident_len, 75 | int is_static, int status) 76 | { 77 | address_binding *binding, *binding_temp; 78 | 79 | LIST_FOREACH_SAFE(binding, list, pointers, binding_temp) { 80 | 81 | if((binding->is_static == is_static || is_static == STATIC_OR_DYNAMIC) && 82 | binding->cident_len == cident_len && 83 | memcmp(binding->cident, cident, cident_len) == 0) { 84 | 85 | if(status == 0) 86 | return binding; 87 | else if(status == binding->status) 88 | return binding; 89 | } 90 | } 91 | 92 | return NULL; 93 | } 94 | 95 | /* 96 | * Get an available free address 97 | * 98 | * If a zero address is returned, no more address are available. 99 | */ 100 | 101 | static uint32_t 102 | take_free_address (pool_indexes *indexes) 103 | { 104 | if(indexes->current <= indexes->last) { 105 | 106 | uint32_t address = indexes->current; 107 | indexes->current = htonl(ntohl(indexes->current) + 1); 108 | return address; 109 | 110 | } else 111 | return 0; 112 | } 113 | 114 | /* 115 | * Create a new dynamic binding or reuse an expired one. 116 | * 117 | * An attemp will be made to assign to the client the requested IP address 118 | * contained in the address option. An address equals to zero means that no 119 | * specific address has been requested. 120 | * 121 | * If the dynamic pool of addresses is full a NULL pointer will be returned. 122 | */ 123 | 124 | address_binding * 125 | new_dynamic_binding (binding_list *list, pool_indexes *indexes, uint32_t address, 126 | uint8_t *cident, uint8_t cident_len) 127 | { 128 | address_binding *binding, *binding_temp; 129 | address_binding *found_binding = NULL; 130 | 131 | if (address != 0) { 132 | 133 | LIST_FOREACH_SAFE(binding, list, pointers, binding_temp) { 134 | // search a previous binding using the requested IP address 135 | 136 | if(binding->address == address) { 137 | found_binding = binding; 138 | break; 139 | } 140 | } 141 | } 142 | 143 | if(found_binding != NULL && 144 | !found_binding->is_static && 145 | found_binding->status != PENDING && 146 | found_binding->status != ASSOCIATED) { 147 | 148 | // the requested IP address is available (reuse an expired association) 149 | return found_binding; 150 | 151 | } else { 152 | 153 | /* the requested IP address is already in use, or no address has been 154 | requested, or the address requested has never been allocated 155 | (we do not support this last case and just return the next 156 | available address!). */ 157 | 158 | uint32_t address = take_free_address(indexes); 159 | 160 | if(address != 0) 161 | return add_binding(list, address, cident, cident_len, 0); 162 | 163 | else { // search any previously assigned address which is expired 164 | 165 | LIST_FOREACH_SAFE(binding, list, pointers, binding_temp) { 166 | if(!binding->is_static && 167 | found_binding->status != PENDING && 168 | found_binding->status != ASSOCIATED) 169 | return binding; 170 | } 171 | 172 | // if executions reach here no more addresses are available 173 | return NULL; 174 | } 175 | } 176 | 177 | // execution should not reach here... 178 | return NULL; 179 | } 180 | -------------------------------------------------------------------------------- /options.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTIONS_H 2 | #define OPTIONS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "queue.h" 8 | 9 | /* 10 | * Code ID of DHCP and BOOTP options 11 | * as defined in RFC 2132 12 | */ 13 | 14 | enum dhcp_msg_type { 15 | DHCP_DISCOVER = 1, 16 | DHCP_OFFER = 2, 17 | DHCP_REQUEST = 3, 18 | DHCP_DECLINE = 4, 19 | DHCP_ACK = 5, 20 | DHCP_NAK = 6, 21 | DHCP_RELEASE = 7, 22 | DHCP_INFORM = 8, 23 | }; 24 | 25 | enum { 26 | 27 | /* RFC 1497 Vendor Extensions */ 28 | 29 | PAD = 0, 30 | END = 255, 31 | 32 | SUBNET_MASK = 1, 33 | TIME_OFFSET = 2, 34 | ROUTER = 3, 35 | TIME_SERVER = 4, 36 | NAME_SERVER = 5, 37 | DOMAIN_NAME_SERVER = 6, 38 | LOG_SERVER = 7, 39 | COOKIE_SERVER = 8, 40 | LPR_SERVER = 9, 41 | IMPRESS_SERVER = 10, 42 | RESOURCE_LOCATION_SERVER = 11, 43 | HOST_NAME = 12, 44 | BOOT_FILE_SIZE = 13, 45 | MERIT_DUMP_FILE = 14, 46 | DOMAIN_NAME = 15, 47 | SWAP_SERVER = 16, 48 | ROOT_PATH = 17, 49 | EXTENSIONS_PATH = 18, 50 | 51 | /* IP Layer Parameters per Host */ 52 | 53 | IP_FORWARDING = 19, 54 | NON_LOCAL_SOURCE_ROUTING = 20, 55 | POLICY_FILTER = 21, 56 | MAXIMUM_DATAGRAM_REASSEMBLY_SIZE = 22, 57 | DEFAULT_IP_TIME_TO_LIVE = 23, 58 | PATH_MTU_AGING_TIMEOUT = 24, 59 | PATH_MTU_PLATEAU_TABLE = 25, 60 | 61 | /* IP Layer Parameters per Interface */ 62 | 63 | INTERFACE_MTU = 26, 64 | ALL_SUBNETS_ARE_LOCAL = 27, 65 | BROADCAST_ADDRESS = 28, 66 | PERFORM_MASK_DISCOVERY = 29, 67 | MASK_SUPPLIER = 30, 68 | PERFORM_ROUTER_DISCOVERY = 31, 69 | ROUTER_SOLICITATION_ADDRESS = 32, 70 | STATIC_ROUTE = 33, 71 | 72 | /* Link Layer Parameters per Interface */ 73 | 74 | TRAILER_ENCAPSULATION = 34, 75 | ARP_CACHE_TIMEOUT = 35, 76 | ETHERNET_ENCAPSULATION = 36, 77 | 78 | /* TCP Parameters */ 79 | 80 | TCP_DEFAULT_TTL = 37, 81 | TCP_KEEPALIVE_INTERVAL = 38, 82 | TCP_KEEPALIVE_GARBAGE = 39, 83 | 84 | /* Application and Service Parameters */ 85 | 86 | NETWORK_INFORMATION_SERVICE_DOMAIN = 40, 87 | NETWORK_INFORMATION_SERVERS = 41, 88 | NETWORK_TIME_PROTOCOL_SERVERS = 42, 89 | VENDOR_SPECIFIC_INFORMATION = 43, 90 | NETBIOS_OVER_TCP_IP_NAME_SERVER = 44, 91 | NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER = 4, 92 | NETBIOS_OVER_TCP_IP_NODE_TYPE = 46, 93 | NETBIOS_OVER_TCP_IP_SCOPE = 47, 94 | X_WINDOW_SYSTEM_FONT_SERVER = 48, 95 | X_WINDOW_SYSTEM_DISPLAY_MANAGER = 49, 96 | NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN = 64, 97 | NETWORK_INFORMATION_SERVICE_PLUS_SERVERS = 65, 98 | MOBILE_IP_HOME_AGENT = 68, 99 | SMTP_SERVER = 69, 100 | POP3_SERVER = 70, 101 | NNTP_SERVER = 71, 102 | DEFAULT_WWW_SERVER = 72, 103 | DEFAULT_FINGER_SERVER = 73, 104 | DEFAULT_IRC_SERVER = 74, 105 | STREETTALK_SERVER = 75, 106 | STREETTALK_DIRECTORY_ASSISTANCE_SERVER = 76, 107 | 108 | /* DHCP Extensions */ 109 | 110 | REQUESTED_IP_ADDRESS = 50, 111 | IP_ADDRESS_LEASE_TIME = 51, 112 | OPTION_OVERLOAD = 52, 113 | TFTP_SERVER_NAME = 66, 114 | BOOTFILE_NAME = 67, 115 | DHCP_MESSAGE_TYPE = 53, 116 | SERVER_IDENTIFIER = 54, 117 | PARAMETER_REQUEST_LIST = 55, 118 | MESSAGE = 56, 119 | MAXIMUM_DHCP_MESSAGE_SIZE = 57, 120 | RENEWAL_T1_TIME_VALUE = 58, 121 | REBINDING_T2_TIME_VALUE = 59, 122 | VENDOR_CLASS_IDENTIFIER = 60, 123 | CLIENT_IDENTIFIER = 61 124 | 125 | }; 126 | 127 | struct dhcp_option { 128 | uint8_t id; // option id 129 | uint8_t len; // option length 130 | uint8_t data[256]; // option data 131 | 132 | TAILQ_ENTRY(dhcp_option) pointers; // pointers, see queue(3) 133 | }; 134 | 135 | typedef struct dhcp_option dhcp_option; 136 | 137 | typedef TAILQ_HEAD(dhcp_option_list_, dhcp_option) DHCP_OPTION_LIST; 138 | typedef struct dhcp_option_list_ dhcp_option_list; 139 | 140 | /* Value parsing functions: 141 | * 142 | * Parse the string pointed by s, and allocate the 143 | * pointer p to contain the parsed data. 144 | * 145 | * On success return the size of the parsed data, 146 | * on error return zero. 147 | */ 148 | 149 | int parse_byte (char *s, void **p); 150 | int parse_byte_list (char *s, void **p); 151 | int parse_short (char *s, void **p); 152 | int parse_short_list (char *s, void **p); 153 | int parse_long (char *s, void **p); 154 | int parse_string (char *s, void **p); 155 | int parse_ip (char *s, void **p); 156 | int parse_ip_list (char *s, void **p); 157 | int parse_mac (char *s, void **p); 158 | 159 | /* Other prototypes */ 160 | 161 | void init_option_list (dhcp_option_list *list); 162 | uint8_t parse_option (dhcp_option *option, char *name, char *value); 163 | dhcp_option * search_option (dhcp_option_list *list, uint8_t id); 164 | void print_options (dhcp_option_list *list); 165 | void append_option (dhcp_option_list *list, dhcp_option *opt); 166 | int parse_options_to_list (dhcp_option_list *list, dhcp_option *opts, size_t len); 167 | size_t serialize_option_list (dhcp_option_list *list, uint8_t *buf, size_t len); 168 | void delete_option_list (dhcp_option_list *list); 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /options.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "queue.h" 17 | #include "options.h" 18 | #include "logging.h" 19 | 20 | const uint8_t option_magic[4] = { 0x63, 0x82, 0x53, 0x63 }; 21 | 22 | /* 23 | * Mapping table between DHCP options and 24 | * functions that parse their value. 25 | */ 26 | 27 | static struct { 28 | 29 | char *name; 30 | int (*f) (char *, void **); 31 | 32 | } dhcp_option_info [256] = { 33 | 34 | [PAD] { "PAD", NULL }, 35 | [END] { "END", NULL }, 36 | [SUBNET_MASK] { "SUBNET_MASK", parse_ip }, 37 | [TIME_OFFSET] { "TIME_OFFSET", parse_long }, 38 | [ROUTER] { "ROUTER", parse_ip_list }, 39 | [TIME_SERVER] { "TIME_SERVER", parse_ip_list }, 40 | [NAME_SERVER] { "NAME_SERVER", parse_ip_list }, 41 | [DOMAIN_NAME_SERVER] { "DOMAIN_NAME_SERVER", parse_ip_list }, 42 | [LOG_SERVER] { "LOG_SERVER", parse_ip_list }, 43 | [COOKIE_SERVER] { "COOKIE_SERVER", parse_ip_list }, 44 | [LPR_SERVER] { "LPR_SERVER", parse_ip_list }, 45 | [IMPRESS_SERVER] { "IMPRESS_SERVER", parse_ip_list }, 46 | [RESOURCE_LOCATION_SERVER] { "RESOURCE_LOCATION_SERVER", parse_ip_list }, 47 | [HOST_NAME] { "HOST_NAME", parse_string }, 48 | [BOOT_FILE_SIZE] { "BOOT_FILE_SIZE", parse_short }, 49 | [MERIT_DUMP_FILE] { "MERIT_DUMP_FILE", parse_string }, 50 | [DOMAIN_NAME] { "DOMAIN_NAME", parse_string }, 51 | [SWAP_SERVER] { "SWAP_SERVER", parse_ip }, 52 | [ROOT_PATH] { "ROOT_PATH", parse_string }, 53 | [EXTENSIONS_PATH] { "EXTENSIONS_PATH", parse_string }, 54 | [IP_FORWARDING] { "IP_FORWARDING", parse_byte }, 55 | [NON_LOCAL_SOURCE_ROUTING] { "NON_LOCAL_SOURCE_ROUTING", parse_byte }, 56 | [POLICY_FILTER] { "POLICY_FILTER", parse_ip_list }, 57 | [MAXIMUM_DATAGRAM_REASSEMBLY_SIZE] { "MAXIMUM_DATAGRAM_REASSEMBLY_SIZE", parse_short }, 58 | [DEFAULT_IP_TIME_TO_LIVE] { "DEFAULT_IP_TIME_TO_LIVE", parse_byte }, 59 | [PATH_MTU_AGING_TIMEOUT] { "PATH_MTU_AGING_TIMEOUT", parse_long }, 60 | [PATH_MTU_PLATEAU_TABLE] { "PATH_MTU_PLATEAU_TABLE", parse_short_list }, 61 | [INTERFACE_MTU] { "INTERFACE_MTU", parse_short }, 62 | [ALL_SUBNETS_ARE_LOCAL] { "ALL_SUBNETS_ARE_LOCAL", parse_byte }, 63 | [BROADCAST_ADDRESS] { "BROADCAST_ADDRESS", parse_ip }, 64 | [PERFORM_MASK_DISCOVERY] { "PERFORM_MASK_DISCOVERY", parse_byte }, 65 | [MASK_SUPPLIER] { "MASK_SUPPLIER", parse_byte }, 66 | [PERFORM_ROUTER_DISCOVERY] { "PERFORM_ROUTER_DISCOVERY", parse_byte }, 67 | [ROUTER_SOLICITATION_ADDRESS] { "ROUTER_SOLICITATION_ADDRESS", parse_ip }, 68 | [STATIC_ROUTE] { "STATIC_ROUTE", parse_ip_list }, 69 | [TRAILER_ENCAPSULATION] { "TRAILER_ENCAPSULATION", parse_byte }, 70 | [ARP_CACHE_TIMEOUT] { "ARP_CACHE_TIMEOUT", parse_long }, 71 | [ETHERNET_ENCAPSULATION] { "ETHERNET_ENCAPSULATION", parse_byte }, 72 | [TCP_DEFAULT_TTL] { "TCP_DEFAULT_TTL", parse_byte }, 73 | [TCP_KEEPALIVE_INTERVAL] { "TCP_KEEPALIVE_INTERVAL", parse_long }, 74 | [TCP_KEEPALIVE_GARBAGE] { "TCP_KEEPALIVE_GARBAGE", parse_byte }, 75 | [NETWORK_INFORMATION_SERVICE_DOMAIN] { "NETWORK_INFORMATION_SERVICE_DOMAIN", parse_string }, 76 | [NETWORK_INFORMATION_SERVERS] { "NETWORK_INFORMATION_SERVERS", parse_ip_list }, 77 | [NETWORK_TIME_PROTOCOL_SERVERS] { "NETWORK_TIME_PROTOCOL_SERVERS", parse_ip_list }, 78 | [VENDOR_SPECIFIC_INFORMATION] { "VENDOR_SPECIFIC_INFORMATION", parse_byte_list }, 79 | [NETBIOS_OVER_TCP_IP_NAME_SERVER] { "NETBIOS_OVER_TCP_IP_NAME_SERVER", parse_ip_list }, 80 | [NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER] { "NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER", parse_ip_list }, 81 | [NETBIOS_OVER_TCP_IP_NODE_TYPE] { "NETBIOS_OVER_TCP_IP_NODE_TYPE", parse_byte }, 82 | [NETBIOS_OVER_TCP_IP_SCOPE] { "NETBIOS_OVER_TCP_IP_SCOPE", parse_string }, 83 | [X_WINDOW_SYSTEM_FONT_SERVER] { "X_WINDOW_SYSTEM_FONT_SERVER", parse_ip_list }, 84 | [X_WINDOW_SYSTEM_DISPLAY_MANAGER] { "X_WINDOW_SYSTEM_DISPLAY_MANAGER", parse_ip_list }, 85 | [NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN] { "NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN", parse_string }, 86 | [NETWORK_INFORMATION_SERVICE_PLUS_SERVERS] { "NETWORK_INFORMATION_SERVICE_PLUS_SERVERS", parse_ip_list }, 87 | [MOBILE_IP_HOME_AGENT] { "MOBILE_IP_HOME_AGENT", parse_ip_list }, 88 | [SMTP_SERVER] { "SMTP_SERVER", parse_ip_list }, 89 | [POP3_SERVER] { "POP3_SERVER", parse_ip_list }, 90 | [NNTP_SERVER] { "NNTP_SERVER", parse_ip_list }, 91 | [DEFAULT_WWW_SERVER] { "DEFAULT_WWW_SERVER", parse_ip_list }, 92 | [DEFAULT_FINGER_SERVER] { "DEFAULT_FINGER_SERVER", parse_ip_list }, 93 | [DEFAULT_IRC_SERVER] { "DEFAULT_IRC_SERVER", parse_ip_list }, 94 | [STREETTALK_SERVER] { "STREETTALK_SERVER", parse_ip_list }, 95 | [STREETTALK_DIRECTORY_ASSISTANCE_SERVER] { "STREETTALK_DIRECTORY_ASSISTANCE_SERVER", parse_ip_list }, 96 | [REQUESTED_IP_ADDRESS] { "REQUESTED_IP_ADDRESS", NULL }, 97 | [IP_ADDRESS_LEASE_TIME] { "IP_ADDRESS_LEASE_TIME", parse_long }, 98 | [OPTION_OVERLOAD] { "OPTION_OVERLOAD", parse_byte }, 99 | [TFTP_SERVER_NAME] { "TFTP_SERVER_NAME", parse_string }, 100 | [BOOTFILE_NAME] { "BOOTFILE_NAME", parse_string }, 101 | [DHCP_MESSAGE_TYPE] { "DHCP_MESSAGE_TYPE", NULL }, 102 | [SERVER_IDENTIFIER] { "SERVER_IDENTIFIER", parse_ip }, 103 | [PARAMETER_REQUEST_LIST] { "PARAMETER_REQUEST_LIST", NULL }, 104 | [MESSAGE] { "MESSAGE", NULL }, 105 | [MAXIMUM_DHCP_MESSAGE_SIZE] { "MAXIMUM_DHCP_MESSAGE_SIZE", NULL }, 106 | [RENEWAL_T1_TIME_VALUE] { "RENEWAL_T1_TIME_VALUE", parse_long }, 107 | [REBINDING_T2_TIME_VALUE] { "REBINDING_T2_TIME_VALUE", parse_long }, 108 | [VENDOR_CLASS_IDENTIFIER] { "VENDOR_CLASS_IDENTIFIER", NULL }, 109 | [CLIENT_IDENTIFIER] { "CLIENT_IDENTIFIER", NULL }, 110 | 111 | }; 112 | 113 | /* Value parsing functions */ 114 | 115 | int 116 | parse_byte (char *s, void **p) 117 | { 118 | *p = malloc(sizeof(uint8_t)); 119 | uint8_t n = ((uint8_t) strtol(s, NULL, 0)); 120 | memcpy(*p, &n, sizeof(n)); 121 | 122 | return sizeof(uint8_t); 123 | } 124 | 125 | int 126 | parse_byte_list (char *s, void **p) 127 | { 128 | *p = malloc(strlen(s) * sizeof(uint8_t)); // slightly over the strictly requested size 129 | 130 | int count = 0; 131 | 132 | char *s2 = strdup(s); 133 | char *s3 = strtok(s2, ", "); 134 | 135 | while(s3 != NULL) { 136 | 137 | uint8_t n = ((uint8_t) strtol(s3, NULL, 0)); 138 | 139 | memcpy(((uint8_t *) *p) + count, &n, sizeof(uint8_t)); 140 | 141 | count += sizeof(uint8_t); 142 | s3 = strtok(NULL, " "); 143 | } 144 | 145 | free(s2); 146 | 147 | return count; 148 | } 149 | 150 | int 151 | parse_short (char *s, void **p) 152 | { 153 | *p = malloc(sizeof(uint16_t)); 154 | uint16_t n = ((uint16_t) strtol(s, NULL, 0)); 155 | memcpy(*p, &n, sizeof(n)); 156 | 157 | return sizeof(uint16_t); 158 | } 159 | 160 | int 161 | parse_short_list (char *s, void **p) 162 | { 163 | *p = malloc(strlen(s) * sizeof(uint16_t)); // slightly over the strictly requested size 164 | 165 | int count = 0; 166 | 167 | char *s2 = strdup(s); 168 | char *s3 = strtok(s2, ", "); 169 | 170 | while(s3 != NULL) { 171 | 172 | uint16_t n = ((uint16_t) strtol(s3, NULL, 0)); 173 | 174 | memcpy(((uint8_t *) *p) + count, &n, sizeof(uint16_t)); 175 | 176 | count += sizeof(uint16_t); 177 | s3 = strtok(NULL, " "); 178 | } 179 | 180 | free(s2); 181 | 182 | return count; 183 | } 184 | 185 | int 186 | parse_long (char *s, void **p) 187 | { 188 | *p = malloc(sizeof(uint32_t)); 189 | uint32_t n = strtol(s, NULL, 0); 190 | memcpy(*p, &n, sizeof(n)); 191 | 192 | return sizeof(uint32_t); 193 | } 194 | 195 | int 196 | parse_string (char *s, void **p) 197 | { 198 | *p = strdup(s); 199 | 200 | return strlen(s); 201 | } 202 | 203 | int 204 | parse_ip (char *s, void **p) 205 | { 206 | struct sockaddr_in ip; 207 | 208 | *p = malloc(sizeof(uint32_t)); 209 | 210 | if (inet_aton(s, &ip.sin_addr) == 0) { // error: invalid IP address 211 | free(*p); 212 | return 0; 213 | } 214 | 215 | memcpy(*p, &ip.sin_addr, sizeof(uint32_t)); 216 | 217 | return sizeof(uint32_t); 218 | } 219 | 220 | int 221 | parse_ip_list (char *s, void **p) 222 | { 223 | *p = malloc(strlen(s) * sizeof(uint32_t) / 4); // slightly over the strictly required size 224 | 225 | int count = 0; 226 | 227 | char *s2 = strdup(s); 228 | char *s3 = strtok(s2, ", "); 229 | 230 | while(s3 != NULL) { 231 | struct sockaddr_in ip; 232 | 233 | if (inet_aton(s3, &ip.sin_addr) == 0) { // error: invalid IP address 234 | free(*p); 235 | return 0; 236 | } 237 | 238 | memcpy(((uint8_t *) *p) + count, &ip.sin_addr, sizeof(uint32_t)); 239 | 240 | count += sizeof(uint32_t); 241 | s3 = strtok(NULL, " "); 242 | } 243 | 244 | free(s2); 245 | 246 | return count; 247 | } 248 | 249 | int 250 | parse_mac (char *s, void **p) 251 | { 252 | *p = malloc(6); 253 | int i; 254 | 255 | if (strlen(s) != 17 || 256 | s[2] != ':' || s[5] != ':' || s[8] != ':' || s[11] != ':' || s[14] != ':') { 257 | free(*p); 258 | return 0; // error: invalid MAC address 259 | } 260 | 261 | if (!isxdigit(s[0]) || !isxdigit(s[1]) || !isxdigit(s[3]) || !isxdigit(s[4]) || 262 | !isxdigit(s[6]) || !isxdigit(s[7]) || !isxdigit(s[9]) || !isxdigit(s[10]) || 263 | !isxdigit(s[12]) || !isxdigit(s[13]) || !isxdigit(s[15]) || !isxdigit(s[16])) { 264 | free(*p); 265 | return 0; // error: invalid MAC address 266 | } 267 | 268 | for (i = 0; i < 6; i++) { 269 | long b = strtol(s+(3*i), NULL, 16); 270 | ((uint8_t *) *p)[i] = (uint8_t) b; 271 | } 272 | 273 | return 6; 274 | } 275 | 276 | /* Option-related functions */ 277 | 278 | /* 279 | * Given the name of the option and its value as strings, 280 | * fill the dhcp_option structure pointed by opt. 281 | * 282 | * On success return the parsed option id, 283 | * otherwise return zero. 284 | */ 285 | uint8_t 286 | parse_option (dhcp_option *opt, char *name, char *value) 287 | { 288 | int (*f) (char *, void **); 289 | int id; 290 | 291 | uint8_t len; 292 | uint8_t *p; 293 | 294 | for (id = 0; id < 256; id++) { // search the option by name 295 | if (dhcp_option_info[id].name && 296 | strcmp(dhcp_option_info[id].name, name) == 0) break; 297 | } 298 | 299 | if (id == 256) { // not found 300 | log_error("Unsupported DHCP option '%s'", name); 301 | return 0; 302 | } 303 | 304 | f = dhcp_option_info[id].f; 305 | 306 | if (f == NULL) { // no parsing function available 307 | log_error("Unsupported DHCP option '%s'", name); 308 | return 0; 309 | } 310 | 311 | len = f(value, (void **)&p); // parse the value 312 | 313 | if(len == 0) // error parsing the value 314 | return 0; 315 | 316 | // structure filling 317 | opt->id = id; 318 | opt->len = len; 319 | memcpy(opt->data, p, len); 320 | 321 | free(p); 322 | 323 | return opt->id; 324 | } 325 | 326 | /* 327 | * Initialize an option list. 328 | */ 329 | 330 | void 331 | init_option_list (dhcp_option_list *list) 332 | { 333 | TAILQ_INIT(list); 334 | } 335 | 336 | /* 337 | * Given a list of options search an option having 338 | * the passed option id, and returns a pointer to it. 339 | * 340 | * If the option is not present the function returns NULL. 341 | */ 342 | 343 | dhcp_option * 344 | search_option (dhcp_option_list *list, uint8_t id) 345 | { 346 | dhcp_option *opt, *opt_temp; 347 | 348 | TAILQ_FOREACH_SAFE(opt, list, pointers, opt_temp) { 349 | 350 | if(opt->id == id) 351 | return opt; 352 | 353 | } 354 | 355 | return NULL; 356 | } 357 | 358 | /* 359 | * Print options in list. 360 | */ 361 | 362 | void 363 | print_options (dhcp_option_list *list) 364 | { 365 | dhcp_option *opt, *opt_temp; 366 | int i=0; 367 | 368 | TAILQ_FOREACH_SAFE(opt, list, pointers, opt_temp) { 369 | 370 | printf("options[%d]=%d (%s)\n", i++, opt->id, 371 | dhcp_option_info[opt->id].name); 372 | 373 | } 374 | } 375 | 376 | 377 | /* 378 | * Append the provided option to the list. 379 | * 380 | * Always allocate new memory, that must be freed later... 381 | */ 382 | 383 | void 384 | append_option (dhcp_option_list *list, dhcp_option *opt) 385 | { 386 | dhcp_option *nopt = calloc(1, sizeof(*nopt)); 387 | memcpy(nopt, opt, 2 + opt->len); 388 | 389 | TAILQ_INSERT_TAIL(list, nopt, pointers); 390 | } 391 | 392 | /* 393 | * Parse the options contained in a DHCP message into a list. 394 | * 395 | * Return 1 on success, 0 if the options are malformed. 396 | */ 397 | 398 | int 399 | parse_options_to_list (dhcp_option_list *list, dhcp_option *opts, size_t len) 400 | { 401 | dhcp_option *opt, *end; 402 | 403 | opt = opts; 404 | end = (dhcp_option *)(((uint8_t *)opts) + len); 405 | 406 | if (len < 4 || 407 | memcmp(opt, option_magic, sizeof(option_magic)) != 0) 408 | return 0; 409 | 410 | opt = (dhcp_option *)(((uint8_t *) opt) + 4); 411 | 412 | while (opt < end && 413 | opt->id != END) { // TODO: check also valid option sizes 414 | 415 | if ((dhcp_option *)(((uint8_t *) opt) + 2 + opt->len) >= end) 416 | return 0; // the len field is too long 417 | 418 | append_option(list, opt); 419 | 420 | opt = (dhcp_option *)(((uint8_t *) opt) + 2 + opt->len); 421 | } 422 | 423 | if (opt < end && opt->id == END) 424 | return 1; 425 | 426 | return 0; 427 | } 428 | 429 | /* 430 | * Serialize a list of options, to be inserted directly inside 431 | * the options section of a DHCP message. 432 | * 433 | * Return 0 on error, the total serialized len on success. 434 | */ 435 | 436 | size_t 437 | serialize_option_list (dhcp_option_list *list, uint8_t *buf, size_t len) 438 | { 439 | uint8_t *p = buf; 440 | 441 | if (len < 4) 442 | return 0; 443 | 444 | memcpy(p, option_magic, sizeof(option_magic)); 445 | p += 4; len -= 4; 446 | 447 | dhcp_option *opt, *opt_temp; 448 | 449 | TAILQ_FOREACH_SAFE(opt, list, pointers, opt_temp) { 450 | 451 | if (len <= 2 + opt->len) 452 | return 0; 453 | 454 | memcpy(p, opt, 2 + opt->len); 455 | p += 2 + opt->len; 456 | len -= 2 + opt->len; 457 | 458 | } 459 | 460 | if (len < 1) 461 | return 0; 462 | 463 | *p = END; 464 | 465 | p++; len--; 466 | 467 | return p - buf; 468 | } 469 | 470 | /* 471 | * Delete an option list and deallocate its memory. 472 | * Deallocate even the list elements. 473 | */ 474 | 475 | void 476 | delete_option_list (dhcp_option_list *list) 477 | { 478 | dhcp_option *opt = TAILQ_FIRST(list); 479 | dhcp_option *tmp; 480 | 481 | while (opt != NULL) { 482 | tmp = TAILQ_NEXT(opt, pointers); 483 | free(opt); 484 | opt = tmp; 485 | } 486 | 487 | TAILQ_INIT(list); 488 | } 489 | -------------------------------------------------------------------------------- /dhcpserver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "dhcpserver.h" 22 | #include "bindings.h" 23 | #include "args.h" 24 | #include "dhcp.h" 25 | #include "options.h" 26 | #include "logging.h" 27 | 28 | /* 29 | * Global pool 30 | */ 31 | 32 | address_pool pool; 33 | 34 | /* 35 | * Helper functions 36 | */ 37 | 38 | char * 39 | str_ip (uint32_t ip) 40 | { 41 | struct in_addr addr; 42 | memcpy(&addr, &ip, sizeof(ip)); 43 | return inet_ntoa(addr); 44 | } 45 | 46 | char * 47 | str_mac (uint8_t *mac) 48 | { 49 | static char str[128]; 50 | 51 | sprintf(str, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", 52 | mac[0], mac[1], mac[2], 53 | mac[3], mac[4], mac[5]); 54 | 55 | return str; 56 | } 57 | 58 | char * 59 | str_status (int status) 60 | { 61 | switch(status) { 62 | case EMPTY: 63 | return "empty"; 64 | case PENDING: 65 | return "pending"; 66 | case ASSOCIATED: 67 | return "associated"; 68 | case RELEASED: 69 | return "released"; 70 | case EXPIRED: 71 | return "expired"; 72 | default: 73 | return NULL; 74 | } 75 | } 76 | 77 | /* 78 | * Network related routines 79 | */ 80 | 81 | void 82 | add_arp_entry (int s, uint8_t *mac, uint32_t ip) 83 | { 84 | struct arpreq ar; 85 | struct sockaddr_in *sock; 86 | 87 | memset(&ar, 0, sizeof(ar)); 88 | 89 | /* add a proxy ARP entry for given pair */ 90 | 91 | sock = (struct sockaddr_in *) &ar.arp_pa; 92 | sock->sin_family = AF_INET; 93 | sock->sin_addr.s_addr = ip; 94 | 95 | memcpy(ar.arp_ha.sa_data, mac, 6); 96 | ar.arp_flags = ATF_COM; //(ATF_PUBL | ATF_COM); 97 | 98 | strncpy(ar.arp_dev, pool.device, sizeof(ar.arp_dev)); 99 | 100 | if (ioctl(s, SIOCSARP, (char *) &ar) < 0) { 101 | perror("error adding entry to arp table"); 102 | }; 103 | } 104 | 105 | void 106 | delete_arp_entry (int s, uint8_t *mac, uint32_t ip) 107 | { 108 | struct arpreq ar; 109 | struct sockaddr_in *sock; 110 | 111 | memset(&ar, 0, sizeof(ar)); 112 | 113 | sock = (struct sockaddr_in *) &ar.arp_pa; 114 | sock->sin_family = AF_INET; 115 | sock->sin_addr.s_addr = ip; 116 | 117 | strncpy(ar.arp_dev, pool.device, sizeof(ar.arp_dev)); 118 | 119 | if(ioctl(s, SIOCGARP, (char *) &ar) < 0) { 120 | if (errno != ENXIO) { 121 | perror("error getting arp entry"); 122 | return; 123 | } 124 | }; 125 | 126 | if(ip == 0 || memcmp(mac, ar.arp_ha.sa_data, 6) == 0) { 127 | if(ioctl(s, SIOCDARP, (char *) &ar) < 0) { 128 | perror("error removing arp table entry"); 129 | } 130 | } 131 | } 132 | 133 | int 134 | send_dhcp_reply (int s, struct sockaddr_in *client_sock, dhcp_msg *reply) 135 | { 136 | size_t len, ret; 137 | 138 | len = serialize_option_list(&reply->opts, reply->hdr.options, 139 | sizeof(reply->hdr) - DHCP_HEADER_SIZE); 140 | 141 | len += DHCP_HEADER_SIZE; 142 | 143 | client_sock->sin_addr.s_addr = reply->hdr.yiaddr; // use the address assigned by us 144 | 145 | if(reply->hdr.yiaddr != 0) { 146 | add_arp_entry(s, reply->hdr.chaddr, reply->hdr.yiaddr); 147 | } 148 | 149 | if ((ret = sendto(s, reply, len, 0, (struct sockaddr *)client_sock, sizeof(*client_sock))) < 0) { 150 | perror("sendto failed"); 151 | return -1; 152 | } 153 | 154 | return ret; 155 | } 156 | 157 | /* 158 | * Message handling routines. 159 | */ 160 | 161 | uint8_t 162 | expand_request (dhcp_msg *request, size_t len) 163 | { 164 | init_option_list(&request->opts); 165 | 166 | if (request->hdr.hlen < 1 || request->hdr.hlen > 16) 167 | return 0; 168 | 169 | if(parse_options_to_list(&request->opts, (dhcp_option *)request->hdr.options, 170 | len - DHCP_HEADER_SIZE) == 0) 171 | return 0; 172 | 173 | dhcp_option *type_opt = search_option(&request->opts, DHCP_MESSAGE_TYPE); 174 | 175 | if (type_opt == NULL) 176 | return 0; 177 | 178 | uint8_t type = type_opt->data[0]; 179 | 180 | return type; 181 | } 182 | 183 | int 184 | init_reply (dhcp_msg *request, dhcp_msg *reply) 185 | { 186 | memset(&reply->hdr, 0, sizeof(reply->hdr)); 187 | 188 | init_option_list(&reply->opts); 189 | 190 | reply->hdr.op = BOOTREPLY; 191 | 192 | reply->hdr.htype = request->hdr.htype; 193 | reply->hdr.hlen = request->hdr.hlen; 194 | 195 | reply->hdr.xid = request->hdr.xid; 196 | reply->hdr.flags = request->hdr.flags; 197 | 198 | reply->hdr.giaddr = request->hdr.giaddr; 199 | 200 | memcpy(reply->hdr.chaddr, request->hdr.chaddr, request->hdr.hlen); 201 | 202 | return 1; 203 | } 204 | 205 | void 206 | fill_requested_dhcp_options (dhcp_option *requested_opts, dhcp_option_list *reply_opts) 207 | { 208 | uint8_t len = requested_opts->len; 209 | uint8_t *id = requested_opts->data; 210 | 211 | int i; 212 | for (i = 0; i < len; i++) { 213 | 214 | if(id[i] != 0) { 215 | dhcp_option *opt = search_option(&pool.options, id[i]); 216 | 217 | if(opt != NULL) 218 | append_option(reply_opts, opt); 219 | } 220 | 221 | } 222 | } 223 | 224 | int 225 | fill_dhcp_reply (dhcp_msg *request, dhcp_msg *reply, 226 | address_binding *binding, uint8_t type) 227 | { 228 | static dhcp_option type_opt, server_id_opt; 229 | 230 | type_opt.id = DHCP_MESSAGE_TYPE; 231 | type_opt.len = 1; 232 | type_opt.data[0] = type; 233 | append_option(&reply->opts, &type_opt); 234 | 235 | server_id_opt.id = SERVER_IDENTIFIER; 236 | server_id_opt.len = 4; 237 | memcpy(server_id_opt.data, &pool.server_id, sizeof(pool.server_id)); 238 | append_option(&reply->opts, &server_id_opt); 239 | 240 | if(binding != NULL) { 241 | reply->hdr.yiaddr = binding->address; 242 | } 243 | 244 | if (type != DHCP_NAK) { 245 | dhcp_option *requested_opts = search_option(&request->opts, PARAMETER_REQUEST_LIST); 246 | 247 | if (requested_opts) 248 | fill_requested_dhcp_options(requested_opts, &reply->opts); 249 | } 250 | 251 | return type; 252 | } 253 | 254 | int 255 | serve_dhcp_discover (dhcp_msg *request, dhcp_msg *reply) 256 | { 257 | address_binding *binding = search_binding(&pool.bindings, request->hdr.chaddr, 258 | request->hdr.hlen, STATIC, EMPTY); 259 | 260 | if (binding) { // a static binding has been configured for this client 261 | 262 | log_info("Offer %s to %s (static), %s status %sexpired", 263 | str_ip(binding->address), str_mac(request->hdr.chaddr), 264 | str_status(binding->status), 265 | binding->binding_time + binding->lease_time < time(NULL) ? "" : "not "); 266 | 267 | if (binding->binding_time + binding->lease_time < time(NULL)) { 268 | binding->status = PENDING; 269 | binding->binding_time = time(NULL); 270 | binding->lease_time = pool.pending_time; 271 | } 272 | 273 | return fill_dhcp_reply(request, reply, binding, DHCP_OFFER); 274 | 275 | } 276 | 277 | else { // use dynamic pool 278 | 279 | /* If an address is available, the new address 280 | SHOULD be chosen as follows: */ 281 | 282 | binding = search_binding(&pool.bindings, request->hdr.chaddr, 283 | request->hdr.hlen, DYNAMIC, EMPTY); 284 | 285 | if (binding) { 286 | 287 | /* The client's current address as recorded in the client's current 288 | binding, ELSE */ 289 | 290 | /* The client's previous address as recorded in the client's (now 291 | expired or released) binding, if that address is in the server's 292 | pool of available addresses and not already allocated, ELSE */ 293 | 294 | log_info("Offer %s to %s, %s status %sexpired", 295 | str_ip(binding->address), str_mac(request->hdr.chaddr), 296 | str_status(binding->status), 297 | binding->binding_time + binding->lease_time < time(NULL) ? "" : "not "); 298 | 299 | if (binding->binding_time + binding->lease_time < time(NULL)) { 300 | binding->status = PENDING; 301 | binding->binding_time = time(NULL); 302 | binding->lease_time = pool.pending_time; 303 | } 304 | 305 | return fill_dhcp_reply(request, reply, binding, DHCP_OFFER); 306 | 307 | } else { 308 | 309 | /* The address requested in the 'Requested IP Address' option, if that 310 | address is valid and not already allocated, ELSE */ 311 | 312 | /* A new address allocated from the server's pool of available 313 | addresses; the address is selected based on the subnet from which 314 | the message was received (if 'giaddr' is 0) or on the address of 315 | the relay agent that forwarded the message ('giaddr' when not 0). */ 316 | 317 | // TODO: extract requested IP address 318 | uint32_t address = 0; 319 | dhcp_option *address_opt = 320 | search_option(&request->opts, REQUESTED_IP_ADDRESS); 321 | 322 | if(address_opt != NULL) 323 | memcpy(&address, address_opt->data, sizeof(address)); 324 | 325 | binding = new_dynamic_binding(&pool.bindings, &pool.indexes, address, 326 | request->hdr.chaddr, request->hdr.hlen); 327 | 328 | if (binding == NULL) { 329 | log_info("Can not offer an address to %s, no address available.", 330 | str_mac(request->hdr.chaddr)); 331 | 332 | return 0; 333 | } 334 | 335 | log_info("Offer %s to %s, %s status %sexpired", 336 | str_ip(binding->address), str_mac(request->hdr.chaddr), 337 | str_status(binding->status), 338 | binding->binding_time + binding->lease_time < time(NULL) ? "" : "not "); 339 | 340 | if (binding->binding_time + binding->lease_time < time(NULL)) { 341 | binding->status = PENDING; 342 | binding->binding_time = time(NULL); 343 | binding->lease_time = pool.pending_time; 344 | } 345 | 346 | return fill_dhcp_reply(request, reply, binding, DHCP_OFFER); 347 | } 348 | 349 | } 350 | 351 | // should NOT reach here... 352 | } 353 | 354 | int 355 | serve_dhcp_request (dhcp_msg *request, dhcp_msg *reply) 356 | { 357 | address_binding *binding = search_binding(&pool.bindings, request->hdr.chaddr, 358 | request->hdr.hlen, STATIC_OR_DYNAMIC, PENDING); 359 | 360 | uint32_t server_id = 0; 361 | dhcp_option *server_id_opt = search_option(&request->opts, SERVER_IDENTIFIER); 362 | 363 | if(server_id_opt != NULL) 364 | memcpy(&server_id, server_id_opt->data, sizeof(server_id)); 365 | 366 | if (server_id == pool.server_id) { // this request is an answer to our offer 367 | 368 | if (binding != NULL) { 369 | 370 | log_info("Ack %s to %s, associated", 371 | str_ip(binding->address), str_mac(request->hdr.chaddr)); 372 | 373 | binding->status = ASSOCIATED; 374 | binding->lease_time = pool.lease_time; 375 | 376 | return fill_dhcp_reply(request, reply, binding, DHCP_ACK); 377 | 378 | } else { 379 | 380 | log_info("Nak to %s, not associated", 381 | str_mac(request->hdr.chaddr)); 382 | 383 | return fill_dhcp_reply(request, reply, NULL, DHCP_NAK); 384 | } 385 | 386 | } else if (server_id != 0) { // answer to the offer of another server 387 | 388 | log_info("Clearing %s of %s, accepted another server offer", 389 | str_ip(binding->address), str_mac(request->hdr.chaddr)); 390 | 391 | binding->status = EMPTY; 392 | binding->lease_time = 0; 393 | 394 | return 0; 395 | 396 | } 397 | 398 | // malformed request... 399 | return 0; 400 | } 401 | 402 | int 403 | serve_dhcp_decline (dhcp_msg *request, dhcp_msg *reply) 404 | { 405 | address_binding *binding = search_binding(&pool.bindings, request->hdr.chaddr, 406 | request->hdr.hlen, STATIC_OR_DYNAMIC, PENDING); 407 | 408 | if(binding != NULL) { 409 | log_info("Declined %s by %s", 410 | str_ip(binding->address), str_mac(request->hdr.chaddr)); 411 | 412 | binding->status = EMPTY; 413 | } 414 | 415 | return 0; 416 | } 417 | 418 | int 419 | serve_dhcp_release (dhcp_msg *request, dhcp_msg *reply) 420 | { 421 | address_binding *binding = search_binding(&pool.bindings, request->hdr.chaddr, 422 | request->hdr.hlen, STATIC_OR_DYNAMIC, ASSOCIATED); 423 | 424 | if(binding != NULL) { 425 | log_info("Released %s by %s", 426 | str_mac(request->hdr.chaddr), str_ip(binding->address)); 427 | 428 | binding->status = RELEASED; 429 | } 430 | 431 | return 0; 432 | } 433 | 434 | int 435 | serve_dhcp_inform (dhcp_msg *request, dhcp_msg *reply) 436 | { 437 | log_info("Info to %s", str_mac(request->hdr.chaddr)); 438 | 439 | return fill_dhcp_reply(request, reply, NULL, DHCP_ACK); 440 | } 441 | 442 | /* 443 | * Dispatch client DHCP messages to the correct handling routines 444 | */ 445 | 446 | void 447 | message_dispatcher (int s, struct sockaddr_in server_sock) 448 | { 449 | 450 | while (1) { 451 | struct sockaddr_in client_sock; 452 | socklen_t slen = sizeof(client_sock); 453 | size_t len; 454 | 455 | dhcp_msg request; 456 | dhcp_msg reply; 457 | 458 | uint8_t type; 459 | 460 | if((len = recvfrom(s, &request.hdr, sizeof(request.hdr), 0, (struct sockaddr *)&client_sock, &slen)) < DHCP_HEADER_SIZE + 5) { 461 | continue; // TODO: check the magic number 300 462 | } 463 | 464 | if(request.hdr.op != BOOTREQUEST) 465 | continue; 466 | 467 | if((type = expand_request(&request, len)) == 0) { 468 | log_error("%s.%u: invalid request received\n", 469 | inet_ntoa(client_sock.sin_addr), ntohs(client_sock.sin_port)); 470 | continue; 471 | } 472 | 473 | init_reply(&request, &reply); 474 | 475 | switch (type) { 476 | 477 | case DHCP_DISCOVER: 478 | type = serve_dhcp_discover(&request, &reply); 479 | break; 480 | 481 | case DHCP_REQUEST: 482 | type = serve_dhcp_request(&request, &reply); 483 | break; 484 | 485 | case DHCP_DECLINE: 486 | type = serve_dhcp_decline(&request, &reply); 487 | break; 488 | 489 | case DHCP_RELEASE: 490 | type = serve_dhcp_release(&request, &reply); 491 | break; 492 | 493 | case DHCP_INFORM: 494 | type = serve_dhcp_inform(&request, &reply); 495 | break; 496 | 497 | default: 498 | printf("%s.%u: request with invalid DHCP message type option\n", 499 | inet_ntoa(client_sock.sin_addr), ntohs(client_sock.sin_port)); 500 | break; 501 | 502 | } 503 | 504 | if(type != 0) 505 | send_dhcp_reply(s, &client_sock, &reply); 506 | 507 | delete_option_list(&request.opts); 508 | delete_option_list(&reply.opts); 509 | 510 | } 511 | 512 | } 513 | 514 | int 515 | main (int argc, char *argv[]) 516 | { 517 | int s; 518 | struct protoent *pp; 519 | struct servent *ss; 520 | struct sockaddr_in server_sock; 521 | 522 | /* Initialize global pool */ 523 | 524 | memset(&pool, 0, sizeof(pool)); 525 | 526 | init_binding_list(&pool.bindings); 527 | init_option_list(&pool.options); 528 | 529 | /* Load configuration */ 530 | 531 | parse_args(argc, argv, &pool); 532 | 533 | /* Set up server */ 534 | 535 | if ((ss = getservbyname("bootps", "udp")) == 0) { 536 | fprintf(stderr, "server: getservbyname() error\n"); 537 | exit(1); 538 | } 539 | 540 | if ((pp = getprotobyname("udp")) == 0) { 541 | fprintf(stderr, "server: getprotobyname() error\n"); 542 | exit(1); 543 | } 544 | 545 | if ((s = socket(AF_INET, SOCK_DGRAM, pp->p_proto)) == -1) { 546 | perror("server: socket() error"); 547 | exit(1); 548 | } 549 | 550 | server_sock.sin_family = AF_INET; 551 | server_sock.sin_addr.s_addr = htonl(INADDR_ANY); 552 | server_sock.sin_port = ss->s_port; 553 | 554 | if (bind(s, (struct sockaddr *) &server_sock, sizeof(server_sock)) == -1) { 555 | perror("server: bind()"); 556 | close(s); 557 | exit(1); 558 | } 559 | 560 | printf("dhcp server: listening on %d\n", ntohs(server_sock.sin_port)); 561 | 562 | /* Message processing loop */ 563 | 564 | message_dispatcher(s, server_sock); 565 | 566 | close(s); 567 | 568 | return 0; 569 | } 570 | -------------------------------------------------------------------------------- /queue.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: queue.h,v 1.44 2016/09/09 20:31:46 millert Exp $ */ 2 | /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ 3 | 4 | /* 5 | * Copyright (c) 1991, 1993 6 | * The Regents of the University of California. All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the University nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | * 32 | * @(#)queue.h 8.5 (Berkeley) 8/20/94 33 | */ 34 | 35 | #ifndef _SYS_QUEUE_H_ 36 | #define _SYS_QUEUE_H_ 37 | 38 | #define NULL ((void *)0) 39 | 40 | /* 41 | * This file defines five types of data structures: singly-linked lists, 42 | * lists, simple queues, tail queues and XOR simple queues. 43 | * 44 | * 45 | * A singly-linked list is headed by a single forward pointer. The elements 46 | * are singly linked for minimum space and pointer manipulation overhead at 47 | * the expense of O(n) removal for arbitrary elements. New elements can be 48 | * added to the list after an existing element or at the head of the list. 49 | * Elements being removed from the head of the list should use the explicit 50 | * macro for this purpose for optimum efficiency. A singly-linked list may 51 | * only be traversed in the forward direction. Singly-linked lists are ideal 52 | * for applications with large datasets and few or no removals or for 53 | * implementing a LIFO queue. 54 | * 55 | * A list is headed by a single forward pointer (or an array of forward 56 | * pointers for a hash table header). The elements are doubly linked 57 | * so that an arbitrary element can be removed without a need to 58 | * traverse the list. New elements can be added to the list before 59 | * or after an existing element or at the head of the list. A list 60 | * may only be traversed in the forward direction. 61 | * 62 | * A simple queue is headed by a pair of pointers, one to the head of the 63 | * list and the other to the tail of the list. The elements are singly 64 | * linked to save space, so elements can only be removed from the 65 | * head of the list. New elements can be added to the list before or after 66 | * an existing element, at the head of the list, or at the end of the 67 | * list. A simple queue may only be traversed in the forward direction. 68 | * 69 | * A tail queue is headed by a pair of pointers, one to the head of the 70 | * list and the other to the tail of the list. The elements are doubly 71 | * linked so that an arbitrary element can be removed without a need to 72 | * traverse the list. New elements can be added to the list before or 73 | * after an existing element, at the head of the list, or at the end of 74 | * the list. A tail queue may be traversed in either direction. 75 | * 76 | * An XOR simple queue is used in the same way as a regular simple queue. 77 | * The difference is that the head structure also includes a "cookie" that 78 | * is XOR'd with the queue pointer (first, last or next) to generate the 79 | * real pointer value. 80 | * 81 | * For details on the use of these macros, see the queue(3) manual page. 82 | */ 83 | 84 | #if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) 85 | #define _Q_INVALIDATE(a) (a) = ((void *)-1) 86 | #else 87 | #define _Q_INVALIDATE(a) 88 | #endif 89 | 90 | /* 91 | * Singly-linked List definitions. 92 | */ 93 | #define SLIST_HEAD(name, type) \ 94 | struct name { \ 95 | struct type *slh_first; /* first element */ \ 96 | } 97 | 98 | #define SLIST_HEAD_INITIALIZER(head) \ 99 | { NULL } 100 | 101 | #define SLIST_ENTRY(type) \ 102 | struct { \ 103 | struct type *sle_next; /* next element */ \ 104 | } 105 | 106 | /* 107 | * Singly-linked List access methods. 108 | */ 109 | #define SLIST_FIRST(head) ((head)->slh_first) 110 | #define SLIST_END(head) NULL 111 | #define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) 112 | #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) 113 | 114 | #define SLIST_FOREACH(var, head, field) \ 115 | for((var) = SLIST_FIRST(head); \ 116 | (var) != SLIST_END(head); \ 117 | (var) = SLIST_NEXT(var, field)) 118 | 119 | #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ 120 | for ((var) = SLIST_FIRST(head); \ 121 | (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ 122 | (var) = (tvar)) 123 | 124 | /* 125 | * Singly-linked List functions. 126 | */ 127 | #define SLIST_INIT(head) { \ 128 | SLIST_FIRST(head) = SLIST_END(head); \ 129 | } 130 | 131 | #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ 132 | (elm)->field.sle_next = (slistelm)->field.sle_next; \ 133 | (slistelm)->field.sle_next = (elm); \ 134 | } while (0) 135 | 136 | #define SLIST_INSERT_HEAD(head, elm, field) do { \ 137 | (elm)->field.sle_next = (head)->slh_first; \ 138 | (head)->slh_first = (elm); \ 139 | } while (0) 140 | 141 | #define SLIST_REMOVE_AFTER(elm, field) do { \ 142 | (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ 143 | } while (0) 144 | 145 | #define SLIST_REMOVE_HEAD(head, field) do { \ 146 | (head)->slh_first = (head)->slh_first->field.sle_next; \ 147 | } while (0) 148 | 149 | #define SLIST_REMOVE(head, elm, type, field) do { \ 150 | if ((head)->slh_first == (elm)) { \ 151 | SLIST_REMOVE_HEAD((head), field); \ 152 | } else { \ 153 | struct type *curelm = (head)->slh_first; \ 154 | \ 155 | while (curelm->field.sle_next != (elm)) \ 156 | curelm = curelm->field.sle_next; \ 157 | curelm->field.sle_next = \ 158 | curelm->field.sle_next->field.sle_next; \ 159 | } \ 160 | _Q_INVALIDATE((elm)->field.sle_next); \ 161 | } while (0) 162 | 163 | /* 164 | * List definitions. 165 | */ 166 | #define LIST_HEAD(name, type) \ 167 | struct name { \ 168 | struct type *lh_first; /* first element */ \ 169 | } 170 | 171 | #define LIST_HEAD_INITIALIZER(head) \ 172 | { NULL } 173 | 174 | #define LIST_ENTRY(type) \ 175 | struct { \ 176 | struct type *le_next; /* next element */ \ 177 | struct type **le_prev; /* address of previous next element */ \ 178 | } 179 | 180 | /* 181 | * List access methods. 182 | */ 183 | #define LIST_FIRST(head) ((head)->lh_first) 184 | #define LIST_END(head) NULL 185 | #define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) 186 | #define LIST_NEXT(elm, field) ((elm)->field.le_next) 187 | 188 | #define LIST_FOREACH(var, head, field) \ 189 | for((var) = LIST_FIRST(head); \ 190 | (var)!= LIST_END(head); \ 191 | (var) = LIST_NEXT(var, field)) 192 | 193 | #define LIST_FOREACH_SAFE(var, head, field, tvar) \ 194 | for ((var) = LIST_FIRST(head); \ 195 | (var) && ((tvar) = LIST_NEXT(var, field), 1); \ 196 | (var) = (tvar)) 197 | 198 | /* 199 | * List functions. 200 | */ 201 | #define LIST_INIT(head) do { \ 202 | LIST_FIRST(head) = LIST_END(head); \ 203 | } while (0) 204 | 205 | #define LIST_INSERT_AFTER(listelm, elm, field) do { \ 206 | if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ 207 | (listelm)->field.le_next->field.le_prev = \ 208 | &(elm)->field.le_next; \ 209 | (listelm)->field.le_next = (elm); \ 210 | (elm)->field.le_prev = &(listelm)->field.le_next; \ 211 | } while (0) 212 | 213 | #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ 214 | (elm)->field.le_prev = (listelm)->field.le_prev; \ 215 | (elm)->field.le_next = (listelm); \ 216 | *(listelm)->field.le_prev = (elm); \ 217 | (listelm)->field.le_prev = &(elm)->field.le_next; \ 218 | } while (0) 219 | 220 | #define LIST_INSERT_HEAD(head, elm, field) do { \ 221 | if (((elm)->field.le_next = (head)->lh_first) != NULL) \ 222 | (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ 223 | (head)->lh_first = (elm); \ 224 | (elm)->field.le_prev = &(head)->lh_first; \ 225 | } while (0) 226 | 227 | #define LIST_REMOVE(elm, field) do { \ 228 | if ((elm)->field.le_next != NULL) \ 229 | (elm)->field.le_next->field.le_prev = \ 230 | (elm)->field.le_prev; \ 231 | *(elm)->field.le_prev = (elm)->field.le_next; \ 232 | _Q_INVALIDATE((elm)->field.le_prev); \ 233 | _Q_INVALIDATE((elm)->field.le_next); \ 234 | } while (0) 235 | 236 | #define LIST_REPLACE(elm, elm2, field) do { \ 237 | if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ 238 | (elm2)->field.le_next->field.le_prev = \ 239 | &(elm2)->field.le_next; \ 240 | (elm2)->field.le_prev = (elm)->field.le_prev; \ 241 | *(elm2)->field.le_prev = (elm2); \ 242 | _Q_INVALIDATE((elm)->field.le_prev); \ 243 | _Q_INVALIDATE((elm)->field.le_next); \ 244 | } while (0) 245 | 246 | /* 247 | * Simple queue definitions. 248 | */ 249 | #define SIMPLEQ_HEAD(name, type) \ 250 | struct name { \ 251 | struct type *sqh_first; /* first element */ \ 252 | struct type **sqh_last; /* addr of last next element */ \ 253 | } 254 | 255 | #define SIMPLEQ_HEAD_INITIALIZER(head) \ 256 | { NULL, &(head).sqh_first } 257 | 258 | #define SIMPLEQ_ENTRY(type) \ 259 | struct { \ 260 | struct type *sqe_next; /* next element */ \ 261 | } 262 | 263 | /* 264 | * Simple queue access methods. 265 | */ 266 | #define SIMPLEQ_FIRST(head) ((head)->sqh_first) 267 | #define SIMPLEQ_END(head) NULL 268 | #define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) 269 | #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) 270 | 271 | #define SIMPLEQ_FOREACH(var, head, field) \ 272 | for((var) = SIMPLEQ_FIRST(head); \ 273 | (var) != SIMPLEQ_END(head); \ 274 | (var) = SIMPLEQ_NEXT(var, field)) 275 | 276 | #define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ 277 | for ((var) = SIMPLEQ_FIRST(head); \ 278 | (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ 279 | (var) = (tvar)) 280 | 281 | /* 282 | * Simple queue functions. 283 | */ 284 | #define SIMPLEQ_INIT(head) do { \ 285 | (head)->sqh_first = NULL; \ 286 | (head)->sqh_last = &(head)->sqh_first; \ 287 | } while (0) 288 | 289 | #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ 290 | if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ 291 | (head)->sqh_last = &(elm)->field.sqe_next; \ 292 | (head)->sqh_first = (elm); \ 293 | } while (0) 294 | 295 | #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ 296 | (elm)->field.sqe_next = NULL; \ 297 | *(head)->sqh_last = (elm); \ 298 | (head)->sqh_last = &(elm)->field.sqe_next; \ 299 | } while (0) 300 | 301 | #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 302 | if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ 303 | (head)->sqh_last = &(elm)->field.sqe_next; \ 304 | (listelm)->field.sqe_next = (elm); \ 305 | } while (0) 306 | 307 | #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ 308 | if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ 309 | (head)->sqh_last = &(head)->sqh_first; \ 310 | } while (0) 311 | 312 | #define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ 313 | if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ 314 | == NULL) \ 315 | (head)->sqh_last = &(elm)->field.sqe_next; \ 316 | } while (0) 317 | 318 | #define SIMPLEQ_CONCAT(head1, head2) do { \ 319 | if (!SIMPLEQ_EMPTY((head2))) { \ 320 | *(head1)->sqh_last = (head2)->sqh_first; \ 321 | (head1)->sqh_last = (head2)->sqh_last; \ 322 | SIMPLEQ_INIT((head2)); \ 323 | } \ 324 | } while (0) 325 | 326 | /* 327 | * XOR Simple queue definitions. 328 | */ 329 | #define XSIMPLEQ_HEAD(name, type) \ 330 | struct name { \ 331 | struct type *sqx_first; /* first element */ \ 332 | struct type **sqx_last; /* addr of last next element */ \ 333 | unsigned long sqx_cookie; \ 334 | } 335 | 336 | #define XSIMPLEQ_ENTRY(type) \ 337 | struct { \ 338 | struct type *sqx_next; /* next element */ \ 339 | } 340 | 341 | /* 342 | * XOR Simple queue access methods. 343 | */ 344 | #define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ 345 | (unsigned long)(ptr))) 346 | #define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) 347 | #define XSIMPLEQ_END(head) NULL 348 | #define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) 349 | #define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) 350 | 351 | 352 | #define XSIMPLEQ_FOREACH(var, head, field) \ 353 | for ((var) = XSIMPLEQ_FIRST(head); \ 354 | (var) != XSIMPLEQ_END(head); \ 355 | (var) = XSIMPLEQ_NEXT(head, var, field)) 356 | 357 | #define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ 358 | for ((var) = XSIMPLEQ_FIRST(head); \ 359 | (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ 360 | (var) = (tvar)) 361 | 362 | /* 363 | * XOR Simple queue functions. 364 | */ 365 | #define XSIMPLEQ_INIT(head) do { \ 366 | arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ 367 | (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ 368 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ 369 | } while (0) 370 | 371 | #define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ 372 | if (((elm)->field.sqx_next = (head)->sqx_first) == \ 373 | XSIMPLEQ_XOR(head, NULL)) \ 374 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ 375 | (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ 376 | } while (0) 377 | 378 | #define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ 379 | (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ 380 | *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ 381 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ 382 | } while (0) 383 | 384 | #define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 385 | if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ 386 | XSIMPLEQ_XOR(head, NULL)) \ 387 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ 388 | (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ 389 | } while (0) 390 | 391 | #define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ 392 | if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ 393 | (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ 394 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ 395 | } while (0) 396 | 397 | #define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ 398 | if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ 399 | (elm)->field.sqx_next)->field.sqx_next) \ 400 | == XSIMPLEQ_XOR(head, NULL)) \ 401 | (head)->sqx_last = \ 402 | XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ 403 | } while (0) 404 | 405 | 406 | /* 407 | * Tail queue definitions. 408 | */ 409 | #define TAILQ_HEAD(name, type) \ 410 | struct name { \ 411 | struct type *tqh_first; /* first element */ \ 412 | struct type **tqh_last; /* addr of last next element */ \ 413 | } 414 | 415 | #define TAILQ_HEAD_INITIALIZER(head) \ 416 | { NULL, &(head).tqh_first } 417 | 418 | #define TAILQ_ENTRY(type) \ 419 | struct { \ 420 | struct type *tqe_next; /* next element */ \ 421 | struct type **tqe_prev; /* address of previous next element */ \ 422 | } 423 | 424 | /* 425 | * Tail queue access methods. 426 | */ 427 | #define TAILQ_FIRST(head) ((head)->tqh_first) 428 | #define TAILQ_END(head) NULL 429 | #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 430 | #define TAILQ_LAST(head, headname) \ 431 | (*(((struct headname *)((head)->tqh_last))->tqh_last)) 432 | /* XXX */ 433 | #define TAILQ_PREV(elm, headname, field) \ 434 | (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) 435 | #define TAILQ_EMPTY(head) \ 436 | (TAILQ_FIRST(head) == TAILQ_END(head)) 437 | 438 | #define TAILQ_FOREACH(var, head, field) \ 439 | for((var) = TAILQ_FIRST(head); \ 440 | (var) != TAILQ_END(head); \ 441 | (var) = TAILQ_NEXT(var, field)) 442 | 443 | #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ 444 | for ((var) = TAILQ_FIRST(head); \ 445 | (var) != TAILQ_END(head) && \ 446 | ((tvar) = TAILQ_NEXT(var, field), 1); \ 447 | (var) = (tvar)) 448 | 449 | 450 | #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ 451 | for((var) = TAILQ_LAST(head, headname); \ 452 | (var) != TAILQ_END(head); \ 453 | (var) = TAILQ_PREV(var, headname, field)) 454 | 455 | #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ 456 | for ((var) = TAILQ_LAST(head, headname); \ 457 | (var) != TAILQ_END(head) && \ 458 | ((tvar) = TAILQ_PREV(var, headname, field), 1); \ 459 | (var) = (tvar)) 460 | 461 | /* 462 | * Tail queue functions. 463 | */ 464 | #define TAILQ_INIT(head) do { \ 465 | (head)->tqh_first = NULL; \ 466 | (head)->tqh_last = &(head)->tqh_first; \ 467 | } while (0) 468 | 469 | #define TAILQ_INSERT_HEAD(head, elm, field) do { \ 470 | if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ 471 | (head)->tqh_first->field.tqe_prev = \ 472 | &(elm)->field.tqe_next; \ 473 | else \ 474 | (head)->tqh_last = &(elm)->field.tqe_next; \ 475 | (head)->tqh_first = (elm); \ 476 | (elm)->field.tqe_prev = &(head)->tqh_first; \ 477 | } while (0) 478 | 479 | #define TAILQ_INSERT_TAIL(head, elm, field) do { \ 480 | (elm)->field.tqe_next = NULL; \ 481 | (elm)->field.tqe_prev = (head)->tqh_last; \ 482 | *(head)->tqh_last = (elm); \ 483 | (head)->tqh_last = &(elm)->field.tqe_next; \ 484 | } while (0) 485 | 486 | #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ 487 | if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ 488 | (elm)->field.tqe_next->field.tqe_prev = \ 489 | &(elm)->field.tqe_next; \ 490 | else \ 491 | (head)->tqh_last = &(elm)->field.tqe_next; \ 492 | (listelm)->field.tqe_next = (elm); \ 493 | (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ 494 | } while (0) 495 | 496 | #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ 497 | (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ 498 | (elm)->field.tqe_next = (listelm); \ 499 | *(listelm)->field.tqe_prev = (elm); \ 500 | (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ 501 | } while (0) 502 | 503 | #define TAILQ_REMOVE(head, elm, field) do { \ 504 | if (((elm)->field.tqe_next) != NULL) \ 505 | (elm)->field.tqe_next->field.tqe_prev = \ 506 | (elm)->field.tqe_prev; \ 507 | else \ 508 | (head)->tqh_last = (elm)->field.tqe_prev; \ 509 | *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ 510 | _Q_INVALIDATE((elm)->field.tqe_prev); \ 511 | _Q_INVALIDATE((elm)->field.tqe_next); \ 512 | } while (0) 513 | 514 | #define TAILQ_REPLACE(head, elm, elm2, field) do { \ 515 | if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ 516 | (elm2)->field.tqe_next->field.tqe_prev = \ 517 | &(elm2)->field.tqe_next; \ 518 | else \ 519 | (head)->tqh_last = &(elm2)->field.tqe_next; \ 520 | (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ 521 | *(elm2)->field.tqe_prev = (elm2); \ 522 | _Q_INVALIDATE((elm)->field.tqe_prev); \ 523 | _Q_INVALIDATE((elm)->field.tqe_next); \ 524 | } while (0) 525 | 526 | #define TAILQ_CONCAT(head1, head2, field) do { \ 527 | if (!TAILQ_EMPTY(head2)) { \ 528 | *(head1)->tqh_last = (head2)->tqh_first; \ 529 | (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ 530 | (head1)->tqh_last = (head2)->tqh_last; \ 531 | TAILQ_INIT((head2)); \ 532 | } \ 533 | } while (0) 534 | 535 | #endif /* !_SYS_QUEUE_H_ */ 536 | -------------------------------------------------------------------------------- /rfc2132.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Network Working Group S. Alexander 8 | Request for Comments: 2132 Silicon Graphics, Inc. 9 | Obsoletes: 1533 R. Droms 10 | Category: Standards Track Bucknell University 11 | March 1997 12 | 13 | DHCP Options and BOOTP Vendor Extensions 14 | 15 | Status of this memo 16 | 17 | This document specifies an Internet standards track protocol for the 18 | Internet community, and requests discussion and suggestions for 19 | improvements. Please refer to the current edition of the "Internet 20 | Official Protocol Standards" (STD 1) for the standardization state 21 | and status of this protocol. Distribution of this memo is unlimited. 22 | 23 | Abstract 24 | 25 | The Dynamic Host Configuration Protocol (DHCP) [1] provides a 26 | framework for passing configuration information to hosts on a TCP/IP 27 | network. Configuration parameters and other control information are 28 | carried in tagged data items that are stored in the 'options' field 29 | of the DHCP message. The data items themselves are also called 30 | "options." 31 | 32 | This document specifies the current set of DHCP options. Future 33 | options will be specified in separate RFCs. The current list of 34 | valid options is also available in ftp://ftp.isi.edu/in- 35 | notes/iana/assignments [22]. 36 | 37 | All of the vendor information extensions defined in RFC 1497 [2] may 38 | be used as DHCP options. The definitions given in RFC 1497 are 39 | included in this document, which supersedes RFC 1497. All of the 40 | DHCP options defined in this document, except for those specific to 41 | DHCP as defined in section 9, may be used as BOOTP vendor information 42 | extensions. 43 | 44 | Table of Contents 45 | 46 | 1. Introduction .............................................. 2 47 | 2. BOOTP Extension/DHCP Option Field Format .................. 4 48 | 3. RFC 1497 Vendor Extensions ................................ 5 49 | 4. IP Layer Parameters per Host .............................. 11 50 | 5. IP Layer Parameters per Interface ........................ 13 51 | 6. Link Layer Parameters per Interface ....................... 16 52 | 7. TCP Parameters ............................................ 17 53 | 8. Application and Service Parameters ........................ 18 54 | 9. DHCP Extensions ........................................... 25 55 | 56 | 57 | 58 | Alexander & Droms Standards Track [Page 1] 59 | 60 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 61 | 62 | 63 | 10. Defining new extensions ................................... 31 64 | 11. Acknowledgements .......................................... 31 65 | 12. References ................................................ 32 66 | 13. Security Considerations ................................... 33 67 | 14. Authors' Addresses ........................................ 34 68 | 69 | 1. Introduction 70 | 71 | This document specifies options for use with both the Dynamic Host 72 | Configuration Protocol and the Bootstrap Protocol. 73 | 74 | The full description of DHCP packet formats may be found in the DHCP 75 | specification document [1], and the full description of BOOTP packet 76 | formats may be found in the BOOTP specification document [3]. This 77 | document defines the format of information in the last field of DHCP 78 | packets ('options') and of BOOTP packets ('vend'). The remainder of 79 | this section defines a generalized use of this area for giving 80 | information useful to a wide class of machines, operating systems and 81 | configurations. Sites with a single DHCP or BOOTP server that is 82 | shared among heterogeneous clients may choose to define other, site- 83 | specific formats for the use of the 'options' field. 84 | 85 | Section 2 of this memo describes the formats of DHCP options and 86 | BOOTP vendor extensions. Section 3 describes options defined in 87 | previous documents for use with BOOTP (all may also be used with 88 | DHCP). Sections 4-8 define new options intended for use with both 89 | DHCP and BOOTP. Section 9 defines options used only in DHCP. 90 | 91 | References further describing most of the options defined in sections 92 | 2-6 can be found in section 12. The use of the options defined in 93 | section 9 is described in the DHCP specification [1]. 94 | 95 | Information on registering new options is contained in section 10. 96 | 97 | This document updates the definition of DHCP/BOOTP options that 98 | appears in RFC1533. The classing mechanism has been extended to 99 | include vendor classes as described in section 8.4 and 9.13. The new 100 | procedure for defining new DHCP/BOOTP options in described in section 101 | 10. Several new options, including NIS+ domain and servers, Mobile 102 | IP home agent, SMTP server, TFTP server and Bootfile server, have 103 | been added. Text giving definitions used throughout the document has 104 | been added in section 1.1. Text emphasizing the need for uniqueness 105 | of client-identifiers has been added to section 9.14. 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | Alexander & Droms Standards Track [Page 2] 115 | 116 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 117 | 118 | 119 | 1.1 Requirements 120 | 121 | Throughout this document, the words that are used to define the 122 | significance of particular requirements are capitalized. These words 123 | are: 124 | 125 | o "MUST" 126 | 127 | This word or the adjective "REQUIRED" means that the item is an 128 | absolute requirement of this specification. 129 | 130 | o "MUST NOT" 131 | 132 | This phrase means that the item is an absolute prohibition of 133 | this specification. 134 | 135 | o "SHOULD" 136 | 137 | This word or the adjective "RECOMMENDED" means that there may 138 | exist valid reasons in particular circumstances to ignore this 139 | item, but the full implications should be understood and the case 140 | carefully weighed before choosing a different course. 141 | 142 | o "SHOULD NOT" 143 | 144 | This phrase means that there may exist valid reasons in 145 | particular circumstances when the listed behavior is acceptable 146 | or even useful, but the full implications should be understood 147 | and the case carefully weighed before implementing any behavior 148 | described with this label. 149 | 150 | o "MAY" 151 | 152 | This word or the adjective "OPTIONAL" means that this item is 153 | truly optional. One vendor may choose to include the item 154 | because a particular marketplace requires it or because it 155 | enhances the product, for example; another vendor may omit the 156 | same item. 157 | 158 | 1.2 Terminology 159 | 160 | This document uses the following terms: 161 | 162 | o "DHCP client" 163 | 164 | A DHCP client or "client" is an Internet host using DHCP to 165 | obtain configuration parameters such as a network address. 166 | 167 | 168 | 169 | 170 | Alexander & Droms Standards Track [Page 3] 171 | 172 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 173 | 174 | 175 | o "DHCP server" 176 | 177 | A DHCP server of "server"is an Internet host that returns 178 | configuration parameters to DHCP clients. 179 | 180 | o "binding" 181 | 182 | A binding is a collection of configuration parameters, including 183 | at least an IP address, associated with or "bound to" a DHCP 184 | client. Bindings are managed by DHCP servers. 185 | 186 | 2. BOOTP Extension/DHCP Option Field Format 187 | 188 | 189 | DHCP options have the same format as the BOOTP 'vendor extensions' 190 | defined in RFC 1497 [2]. Options may be fixed length or variable 191 | length. All options begin with a tag octet, which uniquely 192 | identifies the option. Fixed-length options without data consist of 193 | only a tag octet. Only options 0 and 255 are fixed length. All 194 | other options are variable-length with a length octet following the 195 | tag octet. The value of the length octet does not include the two 196 | octets specifying the tag and length. The length octet is followed 197 | by "length" octets of data. Options containing NVT ASCII data SHOULD 198 | NOT include a trailing NULL; however, the receiver of such options 199 | MUST be prepared to delete trailing nulls if they exist. The 200 | receiver MUST NOT require that a trailing null be included in the 201 | data. In the case of some variable-length options the length field 202 | is a constant but must still be specified. 203 | 204 | Any options defined subsequent to this document MUST contain a length 205 | octet even if the length is fixed or zero. 206 | 207 | All multi-octet quantities are in network byte-order. 208 | 209 | When used with BOOTP, the first four octets of the vendor information 210 | field have been assigned to the "magic cookie" (as suggested in RFC 211 | 951). This field identifies the mode in which the succeeding data is 212 | to be interpreted. The value of the magic cookie is the 4 octet 213 | dotted decimal 99.130.83.99 (or hexadecimal number 63.82.53.63) in 214 | network byte order. 215 | 216 | All of the "vendor extensions" defined in RFC 1497 are also DHCP 217 | options. 218 | 219 | Option codes 128 to 254 (decimal) are reserved for site-specific 220 | options. 221 | 222 | 223 | 224 | 225 | 226 | Alexander & Droms Standards Track [Page 4] 227 | 228 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 229 | 230 | 231 | Except for the options in section 9, all options may be used with 232 | either DHCP or BOOTP. 233 | 234 | Many of these options have their default values specified in other 235 | documents. In particular, RFC 1122 [4] specifies default values for 236 | most IP and TCP configuration parameters. 237 | 238 | Many options supply one or more 32-bit IP address. Use of IP 239 | addresses rather than fully-qualified Domain Names (FQDNs) may make 240 | future renumbering of IP hosts more difficult. Use of these 241 | addresses is discouraged at sites that may require renumbering. 242 | 243 | 3. RFC 1497 Vendor Extensions 244 | 245 | This section lists the vendor extensions as defined in RFC 1497. 246 | They are defined here for completeness. 247 | 248 | 3.1. Pad Option 249 | 250 | The pad option can be used to cause subsequent fields to align on 251 | word boundaries. 252 | 253 | The code for the pad option is 0, and its length is 1 octet. 254 | 255 | Code 256 | +-----+ 257 | | 0 | 258 | +-----+ 259 | 260 | 3.2. End Option 261 | 262 | The end option marks the end of valid information in the vendor 263 | field. Subsequent octets should be filled with pad options. 264 | 265 | The code for the end option is 255, and its length is 1 octet. 266 | 267 | Code 268 | +-----+ 269 | | 255 | 270 | +-----+ 271 | 272 | 3.3. Subnet Mask 273 | 274 | The subnet mask option specifies the client's subnet mask as per RFC 275 | 950 [5]. 276 | 277 | If both the subnet mask and the router option are specified in a DHCP 278 | reply, the subnet mask option MUST be first. 279 | 280 | 281 | 282 | Alexander & Droms Standards Track [Page 5] 283 | 284 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 285 | 286 | 287 | The code for the subnet mask option is 1, and its length is 4 octets. 288 | 289 | Code Len Subnet Mask 290 | +-----+-----+-----+-----+-----+-----+ 291 | | 1 | 4 | m1 | m2 | m3 | m4 | 292 | +-----+-----+-----+-----+-----+-----+ 293 | 294 | 3.4. Time Offset 295 | 296 | The time offset field specifies the offset of the client's subnet in 297 | seconds from Coordinated Universal Time (UTC). The offset is 298 | expressed as a two's complement 32-bit integer. A positive offset 299 | indicates a location east of the zero meridian and a negative offset 300 | indicates a location west of the zero meridian. 301 | 302 | The code for the time offset option is 2, and its length is 4 octets. 303 | 304 | Code Len Time Offset 305 | +-----+-----+-----+-----+-----+-----+ 306 | | 2 | 4 | n1 | n2 | n3 | n4 | 307 | +-----+-----+-----+-----+-----+-----+ 308 | 309 | 3.5. Router Option 310 | 311 | The router option specifies a list of IP addresses for routers on the 312 | client's subnet. Routers SHOULD be listed in order of preference. 313 | 314 | The code for the router option is 3. The minimum length for the 315 | router option is 4 octets, and the length MUST always be a multiple 316 | of 4. 317 | 318 | Code Len Address 1 Address 2 319 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 320 | | 3 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 321 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 322 | 323 | 3.6. Time Server Option 324 | 325 | The time server option specifies a list of RFC 868 [6] time servers 326 | available to the client. Servers SHOULD be listed in order of 327 | preference. 328 | 329 | The code for the time server option is 4. The minimum length for 330 | this option is 4 octets, and the length MUST always be a multiple of 331 | 4. 332 | 333 | 334 | 335 | 336 | 337 | 338 | Alexander & Droms Standards Track [Page 6] 339 | 340 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 341 | 342 | 343 | Code Len Address 1 Address 2 344 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 345 | | 4 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 346 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 347 | 348 | 3.7. Name Server Option 349 | 350 | The name server option specifies a list of IEN 116 [7] name servers 351 | available to the client. Servers SHOULD be listed in order of 352 | preference. 353 | 354 | The code for the name server option is 5. The minimum length for 355 | this option is 4 octets, and the length MUST always be a multiple of 356 | 4. 357 | 358 | Code Len Address 1 Address 2 359 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 360 | | 5 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 361 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 362 | 363 | 3.8. Domain Name Server Option 364 | 365 | The domain name server option specifies a list of Domain Name System 366 | (STD 13, RFC 1035 [8]) name servers available to the client. Servers 367 | SHOULD be listed in order of preference. 368 | 369 | The code for the domain name server option is 6. The minimum length 370 | for this option is 4 octets, and the length MUST always be a multiple 371 | of 4. 372 | 373 | Code Len Address 1 Address 2 374 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 375 | | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 376 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 377 | 378 | 3.9. Log Server Option 379 | 380 | The log server option specifies a list of MIT-LCS UDP log servers 381 | available to the client. Servers SHOULD be listed in order of 382 | preference. 383 | 384 | The code for the log server option is 7. The minimum length for this 385 | option is 4 octets, and the length MUST always be a multiple of 4. 386 | 387 | Code Len Address 1 Address 2 388 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 389 | | 7 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 390 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 391 | 392 | 393 | 394 | Alexander & Droms Standards Track [Page 7] 395 | 396 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 397 | 398 | 399 | 3.10. Cookie Server Option 400 | 401 | The cookie server option specifies a list of RFC 865 [9] cookie 402 | servers available to the client. Servers SHOULD be listed in order 403 | of preference. 404 | 405 | The code for the log server option is 8. The minimum length for this 406 | option is 4 octets, and the length MUST always be a multiple of 4. 407 | 408 | Code Len Address 1 Address 2 409 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 410 | | 8 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 411 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 412 | 413 | 3.11. LPR Server Option 414 | 415 | The LPR server option specifies a list of RFC 1179 [10] line printer 416 | servers available to the client. Servers SHOULD be listed in order 417 | of preference. 418 | 419 | The code for the LPR server option is 9. The minimum length for this 420 | option is 4 octets, and the length MUST always be a multiple of 4. 421 | 422 | Code Len Address 1 Address 2 423 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 424 | | 9 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 425 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 426 | 427 | 3.12. Impress Server Option 428 | 429 | The Impress server option specifies a list of Imagen Impress servers 430 | available to the client. Servers SHOULD be listed in order of 431 | preference. 432 | 433 | The code for the Impress server option is 10. The minimum length for 434 | this option is 4 octets, and the length MUST always be a multiple of 435 | 4. 436 | 437 | Code Len Address 1 Address 2 438 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 439 | | 10 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 440 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 441 | 442 | 3.13. Resource Location Server Option 443 | 444 | This option specifies a list of RFC 887 [11] Resource Location 445 | servers available to the client. Servers SHOULD be listed in order 446 | of preference. 447 | 448 | 449 | 450 | Alexander & Droms Standards Track [Page 8] 451 | 452 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 453 | 454 | 455 | The code for this option is 11. The minimum length for this option 456 | is 4 octets, and the length MUST always be a multiple of 4. 457 | 458 | Code Len Address 1 Address 2 459 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 460 | | 11 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 461 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 462 | 463 | 3.14. Host Name Option 464 | 465 | This option specifies the name of the client. The name may or may 466 | not be qualified with the local domain name (see section 3.17 for the 467 | preferred way to retrieve the domain name). See RFC 1035 for 468 | character set restrictions. 469 | 470 | The code for this option is 12, and its minimum length is 1. 471 | 472 | Code Len Host Name 473 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 474 | | 12 | n | h1 | h2 | h3 | h4 | h5 | h6 | ... 475 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 476 | 477 | 3.15. Boot File Size Option 478 | 479 | This option specifies the length in 512-octet blocks of the default 480 | boot image for the client. The file length is specified as an 481 | unsigned 16-bit integer. 482 | 483 | The code for this option is 13, and its length is 2. 484 | 485 | Code Len File Size 486 | +-----+-----+-----+-----+ 487 | | 13 | 2 | l1 | l2 | 488 | +-----+-----+-----+-----+ 489 | 490 | 3.16. Merit Dump File 491 | 492 | This option specifies the path-name of a file to which the client's 493 | core image should be dumped in the event the client crashes. The 494 | path is formatted as a character string consisting of characters from 495 | the NVT ASCII character set. 496 | 497 | The code for this option is 14. Its minimum length is 1. 498 | 499 | Code Len Dump File Pathname 500 | +-----+-----+-----+-----+-----+-----+--- 501 | | 14 | n | n1 | n2 | n3 | n4 | ... 502 | +-----+-----+-----+-----+-----+-----+--- 503 | 504 | 505 | 506 | Alexander & Droms Standards Track [Page 9] 507 | 508 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 509 | 510 | 511 | 3.17. Domain Name 512 | 513 | This option specifies the domain name that client should use when 514 | resolving hostnames via the Domain Name System. 515 | 516 | The code for this option is 15. Its minimum length is 1. 517 | 518 | Code Len Domain Name 519 | +-----+-----+-----+-----+-----+-----+-- 520 | | 15 | n | d1 | d2 | d3 | d4 | ... 521 | +-----+-----+-----+-----+-----+-----+-- 522 | 523 | 3.18. Swap Server 524 | 525 | This specifies the IP address of the client's swap server. 526 | 527 | The code for this option is 16 and its length is 4. 528 | 529 | Code Len Swap Server Address 530 | +-----+-----+-----+-----+-----+-----+ 531 | | 16 | n | a1 | a2 | a3 | a4 | 532 | +-----+-----+-----+-----+-----+-----+ 533 | 534 | 3.19. Root Path 535 | 536 | This option specifies the path-name that contains the client's root 537 | disk. The path is formatted as a character string consisting of 538 | characters from the NVT ASCII character set. 539 | 540 | The code for this option is 17. Its minimum length is 1. 541 | 542 | Code Len Root Disk Pathname 543 | +-----+-----+-----+-----+-----+-----+--- 544 | | 17 | n | n1 | n2 | n3 | n4 | ... 545 | +-----+-----+-----+-----+-----+-----+--- 546 | 547 | 3.20. Extensions Path 548 | 549 | A string to specify a file, retrievable via TFTP, which contains 550 | information which can be interpreted in the same way as the 64-octet 551 | vendor-extension field within the BOOTP response, with the following 552 | exceptions: 553 | 554 | - the length of the file is unconstrained; 555 | - all references to Tag 18 (i.e., instances of the 556 | BOOTP Extensions Path field) within the file are 557 | ignored. 558 | 559 | 560 | 561 | 562 | Alexander & Droms Standards Track [Page 10] 563 | 564 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 565 | 566 | 567 | The code for this option is 18. Its minimum length is 1. 568 | 569 | Code Len Extensions Pathname 570 | +-----+-----+-----+-----+-----+-----+--- 571 | | 18 | n | n1 | n2 | n3 | n4 | ... 572 | +-----+-----+-----+-----+-----+-----+--- 573 | 574 | 4. IP Layer Parameters per Host 575 | 576 | This section details the options that affect the operation of the IP 577 | layer on a per-host basis. 578 | 579 | 4.1. IP Forwarding Enable/Disable Option 580 | 581 | This option specifies whether the client should configure its IP 582 | layer for packet forwarding. A value of 0 means disable IP 583 | forwarding, and a value of 1 means enable IP forwarding. 584 | 585 | The code for this option is 19, and its length is 1. 586 | 587 | Code Len Value 588 | +-----+-----+-----+ 589 | | 19 | 1 | 0/1 | 590 | +-----+-----+-----+ 591 | 592 | 4.2. Non-Local Source Routing Enable/Disable Option 593 | 594 | This option specifies whether the client should configure its IP 595 | layer to allow forwarding of datagrams with non-local source routes 596 | (see Section 3.3.5 of [4] for a discussion of this topic). A value 597 | of 0 means disallow forwarding of such datagrams, and a value of 1 598 | means allow forwarding. 599 | 600 | The code for this option is 20, and its length is 1. 601 | 602 | Code Len Value 603 | +-----+-----+-----+ 604 | | 20 | 1 | 0/1 | 605 | +-----+-----+-----+ 606 | 607 | 4.3. Policy Filter Option 608 | 609 | This option specifies policy filters for non-local source routing. 610 | The filters consist of a list of IP addresses and masks which specify 611 | destination/mask pairs with which to filter incoming source routes. 612 | 613 | Any source routed datagram whose next-hop address does not match one 614 | of the filters should be discarded by the client. 615 | 616 | 617 | 618 | Alexander & Droms Standards Track [Page 11] 619 | 620 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 621 | 622 | 623 | See [4] for further information. 624 | 625 | The code for this option is 21. The minimum length of this option is 626 | 8, and the length MUST be a multiple of 8. 627 | 628 | Code Len Address 1 Mask 1 629 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 630 | | 21 | n | a1 | a2 | a3 | a4 | m1 | m2 | m3 | m4 | 631 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 632 | Address 2 Mask 2 633 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 634 | | a1 | a2 | a3 | a4 | m1 | m2 | m3 | m4 | ... 635 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 636 | 637 | 4.4. Maximum Datagram Reassembly Size 638 | 639 | This option specifies the maximum size datagram that the client 640 | should be prepared to reassemble. The size is specified as a 16-bit 641 | unsigned integer. The minimum value legal value is 576. 642 | 643 | The code for this option is 22, and its length is 2. 644 | 645 | Code Len Size 646 | +-----+-----+-----+-----+ 647 | | 22 | 2 | s1 | s2 | 648 | +-----+-----+-----+-----+ 649 | 650 | 4.5. Default IP Time-to-live 651 | 652 | This option specifies the default time-to-live that the client should 653 | use on outgoing datagrams. The TTL is specified as an octet with a 654 | value between 1 and 255. 655 | 656 | The code for this option is 23, and its length is 1. 657 | 658 | Code Len TTL 659 | +-----+-----+-----+ 660 | | 23 | 1 | ttl | 661 | +-----+-----+-----+ 662 | 663 | 4.6. Path MTU Aging Timeout Option 664 | 665 | This option specifies the timeout (in seconds) to use when aging Path 666 | MTU values discovered by the mechanism defined in RFC 1191 [12]. The 667 | timeout is specified as a 32-bit unsigned integer. 668 | 669 | The code for this option is 24, and its length is 4. 670 | 671 | 672 | 673 | 674 | Alexander & Droms Standards Track [Page 12] 675 | 676 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 677 | 678 | 679 | Code Len Timeout 680 | +-----+-----+-----+-----+-----+-----+ 681 | | 24 | 4 | t1 | t2 | t3 | t4 | 682 | +-----+-----+-----+-----+-----+-----+ 683 | 684 | 4.7. Path MTU Plateau Table Option 685 | 686 | This option specifies a table of MTU sizes to use when performing 687 | Path MTU Discovery as defined in RFC 1191. The table is formatted as 688 | a list of 16-bit unsigned integers, ordered from smallest to largest. 689 | The minimum MTU value cannot be smaller than 68. 690 | 691 | The code for this option is 25. Its minimum length is 2, and the 692 | length MUST be a multiple of 2. 693 | 694 | Code Len Size 1 Size 2 695 | +-----+-----+-----+-----+-----+-----+--- 696 | | 25 | n | s1 | s2 | s1 | s2 | ... 697 | +-----+-----+-----+-----+-----+-----+--- 698 | 699 | 5. IP Layer Parameters per Interface 700 | 701 | This section details the options that affect the operation of the IP 702 | layer on a per-interface basis. It is expected that a client can 703 | issue multiple requests, one per interface, in order to configure 704 | interfaces with their specific parameters. 705 | 706 | 5.1. Interface MTU Option 707 | 708 | This option specifies the MTU to use on this interface. The MTU is 709 | specified as a 16-bit unsigned integer. The minimum legal value for 710 | the MTU is 68. 711 | 712 | The code for this option is 26, and its length is 2. 713 | 714 | Code Len MTU 715 | +-----+-----+-----+-----+ 716 | | 26 | 2 | m1 | m2 | 717 | +-----+-----+-----+-----+ 718 | 719 | 5.2. All Subnets are Local Option 720 | 721 | This option specifies whether or not the client may assume that all 722 | subnets of the IP network to which the client is connected use the 723 | same MTU as the subnet of that network to which the client is 724 | directly connected. A value of 1 indicates that all subnets share 725 | the same MTU. A value of 0 means that the client should assume that 726 | some subnets of the directly connected network may have smaller MTUs. 727 | 728 | 729 | 730 | Alexander & Droms Standards Track [Page 13] 731 | 732 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 733 | 734 | 735 | The code for this option is 27, and its length is 1. 736 | 737 | Code Len Value 738 | +-----+-----+-----+ 739 | | 27 | 1 | 0/1 | 740 | +-----+-----+-----+ 741 | 742 | 5.3. Broadcast Address Option 743 | 744 | This option specifies the broadcast address in use on the client's 745 | subnet. Legal values for broadcast addresses are specified in 746 | section 3.2.1.3 of [4]. 747 | 748 | The code for this option is 28, and its length is 4. 749 | 750 | Code Len Broadcast Address 751 | +-----+-----+-----+-----+-----+-----+ 752 | | 28 | 4 | b1 | b2 | b3 | b4 | 753 | +-----+-----+-----+-----+-----+-----+ 754 | 755 | 5.4. Perform Mask Discovery Option 756 | 757 | This option specifies whether or not the client should perform subnet 758 | mask discovery using ICMP. A value of 0 indicates that the client 759 | should not perform mask discovery. A value of 1 means that the 760 | client should perform mask discovery. 761 | 762 | The code for this option is 29, and its length is 1. 763 | 764 | Code Len Value 765 | +-----+-----+-----+ 766 | | 29 | 1 | 0/1 | 767 | +-----+-----+-----+ 768 | 769 | 5.5. Mask Supplier Option 770 | 771 | This option specifies whether or not the client should respond to 772 | subnet mask requests using ICMP. A value of 0 indicates that the 773 | client should not respond. A value of 1 means that the client should 774 | respond. 775 | 776 | The code for this option is 30, and its length is 1. 777 | 778 | Code Len Value 779 | +-----+-----+-----+ 780 | | 30 | 1 | 0/1 | 781 | +-----+-----+-----+ 782 | 783 | 784 | 785 | 786 | Alexander & Droms Standards Track [Page 14] 787 | 788 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 789 | 790 | 791 | 5.6. Perform Router Discovery Option 792 | 793 | This option specifies whether or not the client should solicit 794 | routers using the Router Discovery mechanism defined in RFC 1256 795 | [13]. A value of 0 indicates that the client should not perform 796 | router discovery. A value of 1 means that the client should perform 797 | router discovery. 798 | 799 | The code for this option is 31, and its length is 1. 800 | 801 | Code Len Value 802 | +-----+-----+-----+ 803 | | 31 | 1 | 0/1 | 804 | +-----+-----+-----+ 805 | 806 | 5.7. Router Solicitation Address Option 807 | 808 | This option specifies the address to which the client should transmit 809 | router solicitation requests. 810 | 811 | The code for this option is 32, and its length is 4. 812 | 813 | Code Len Address 814 | +-----+-----+-----+-----+-----+-----+ 815 | | 32 | 4 | a1 | a2 | a3 | a4 | 816 | +-----+-----+-----+-----+-----+-----+ 817 | 818 | 5.8. Static Route Option 819 | 820 | This option specifies a list of static routes that the client should 821 | install in its routing cache. If multiple routes to the same 822 | destination are specified, they are listed in descending order of 823 | priority. 824 | 825 | The routes consist of a list of IP address pairs. The first address 826 | is the destination address, and the second address is the router for 827 | the destination. 828 | 829 | The default route (0.0.0.0) is an illegal destination for a static 830 | route. See section 3.5 for information about the router option. 831 | 832 | The code for this option is 33. The minimum length of this option is 833 | 8, and the length MUST be a multiple of 8. 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | Alexander & Droms Standards Track [Page 15] 843 | 844 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 845 | 846 | 847 | Code Len Destination 1 Router 1 848 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 849 | | 33 | n | d1 | d2 | d3 | d4 | r1 | r2 | r3 | r4 | 850 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 851 | Destination 2 Router 2 852 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 853 | | d1 | d2 | d3 | d4 | r1 | r2 | r3 | r4 | ... 854 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 855 | 856 | 6. Link Layer Parameters per Interface 857 | 858 | This section lists the options that affect the operation of the data 859 | link layer on a per-interface basis. 860 | 861 | 6.1. Trailer Encapsulation Option 862 | 863 | This option specifies whether or not the client should negotiate the 864 | use of trailers (RFC 893 [14]) when using the ARP protocol. A value 865 | of 0 indicates that the client should not attempt to use trailers. A 866 | value of 1 means that the client should attempt to use trailers. 867 | 868 | The code for this option is 34, and its length is 1. 869 | 870 | Code Len Value 871 | +-----+-----+-----+ 872 | | 34 | 1 | 0/1 | 873 | +-----+-----+-----+ 874 | 875 | 6.2. ARP Cache Timeout Option 876 | 877 | This option specifies the timeout in seconds for ARP cache entries. 878 | The time is specified as a 32-bit unsigned integer. 879 | 880 | The code for this option is 35, and its length is 4. 881 | 882 | Code Len Time 883 | +-----+-----+-----+-----+-----+-----+ 884 | | 35 | 4 | t1 | t2 | t3 | t4 | 885 | +-----+-----+-----+-----+-----+-----+ 886 | 887 | 6.3. Ethernet Encapsulation Option 888 | 889 | This option specifies whether or not the client should use Ethernet 890 | Version 2 (RFC 894 [15]) or IEEE 802.3 (RFC 1042 [16]) encapsulation 891 | if the interface is an Ethernet. A value of 0 indicates that the 892 | client should use RFC 894 encapsulation. A value of 1 means that the 893 | client should use RFC 1042 encapsulation. 894 | 895 | 896 | 897 | 898 | Alexander & Droms Standards Track [Page 16] 899 | 900 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 901 | 902 | 903 | The code for this option is 36, and its length is 1. 904 | 905 | Code Len Value 906 | +-----+-----+-----+ 907 | | 36 | 1 | 0/1 | 908 | +-----+-----+-----+ 909 | 910 | 7. TCP Parameters 911 | 912 | This section lists the options that affect the operation of the TCP 913 | layer on a per-interface basis. 914 | 915 | 7.1. TCP Default TTL Option 916 | 917 | This option specifies the default TTL that the client should use when 918 | sending TCP segments. The value is represented as an 8-bit unsigned 919 | integer. The minimum value is 1. 920 | 921 | The code for this option is 37, and its length is 1. 922 | 923 | Code Len TTL 924 | +-----+-----+-----+ 925 | | 37 | 1 | n | 926 | +-----+-----+-----+ 927 | 928 | 7.2. TCP Keepalive Interval Option 929 | 930 | This option specifies the interval (in seconds) that the client TCP 931 | should wait before sending a keepalive message on a TCP connection. 932 | The time is specified as a 32-bit unsigned integer. A value of zero 933 | indicates that the client should not generate keepalive messages on 934 | connections unless specifically requested by an application. 935 | 936 | The code for this option is 38, and its length is 4. 937 | 938 | Code Len Time 939 | +-----+-----+-----+-----+-----+-----+ 940 | | 38 | 4 | t1 | t2 | t3 | t4 | 941 | +-----+-----+-----+-----+-----+-----+ 942 | 943 | 7.3. TCP Keepalive Garbage Option 944 | 945 | This option specifies the whether or not the client should send TCP 946 | keepalive messages with a octet of garbage for compatibility with 947 | older implementations. A value of 0 indicates that a garbage octet 948 | should not be sent. A value of 1 indicates that a garbage octet 949 | should be sent. 950 | 951 | 952 | 953 | 954 | Alexander & Droms Standards Track [Page 17] 955 | 956 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 957 | 958 | 959 | The code for this option is 39, and its length is 1. 960 | 961 | Code Len Value 962 | +-----+-----+-----+ 963 | | 39 | 1 | 0/1 | 964 | +-----+-----+-----+ 965 | 966 | 8. Application and Service Parameters 967 | 968 | This section details some miscellaneous options used to configure 969 | miscellaneous applications and services. 970 | 971 | 8.1. Network Information Service Domain Option 972 | 973 | This option specifies the name of the client's NIS [17] domain. The 974 | domain is formatted as a character string consisting of characters 975 | from the NVT ASCII character set. 976 | 977 | The code for this option is 40. Its minimum length is 1. 978 | 979 | Code Len NIS Domain Name 980 | +-----+-----+-----+-----+-----+-----+--- 981 | | 40 | n | n1 | n2 | n3 | n4 | ... 982 | +-----+-----+-----+-----+-----+-----+--- 983 | 984 | 8.2. Network Information Servers Option 985 | 986 | This option specifies a list of IP addresses indicating NIS servers 987 | available to the client. Servers SHOULD be listed in order of 988 | preference. 989 | 990 | The code for this option is 41. Its minimum length is 4, and the 991 | length MUST be a multiple of 4. 992 | 993 | Code Len Address 1 Address 2 994 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 995 | | 41 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 996 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 997 | 998 | 8.3. Network Time Protocol Servers Option 999 | 1000 | This option specifies a list of IP addresses indicating NTP [18] 1001 | servers available to the client. Servers SHOULD be listed in order 1002 | of preference. 1003 | 1004 | The code for this option is 42. Its minimum length is 4, and the 1005 | length MUST be a multiple of 4. 1006 | 1007 | 1008 | 1009 | 1010 | Alexander & Droms Standards Track [Page 18] 1011 | 1012 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1013 | 1014 | 1015 | Code Len Address 1 Address 2 1016 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1017 | | 42 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1018 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1019 | 1020 | 8.4. Vendor Specific Information 1021 | 1022 | This option is used by clients and servers to exchange vendor- 1023 | specific information. The information is an opaque object of n 1024 | octets, presumably interpreted by vendor-specific code on the clients 1025 | and servers. The definition of this information is vendor specific. 1026 | The vendor is indicated in the vendor class identifier option. 1027 | Servers not equipped to interpret the vendor-specific information 1028 | sent by a client MUST ignore it (although it may be reported). 1029 | Clients which do not receive desired vendor-specific information 1030 | SHOULD make an attempt to operate without it, although they may do so 1031 | (and announce they are doing so) in a degraded mode. 1032 | 1033 | If a vendor potentially encodes more than one item of information in 1034 | this option, then the vendor SHOULD encode the option using 1035 | "Encapsulated vendor-specific options" as described below: 1036 | 1037 | The Encapsulated vendor-specific options field SHOULD be encoded as a 1038 | sequence of code/length/value fields of identical syntax to the DHCP 1039 | options field with the following exceptions: 1040 | 1041 | 1) There SHOULD NOT be a "magic cookie" field in the encapsulated 1042 | vendor-specific extensions field. 1043 | 1044 | 2) Codes other than 0 or 255 MAY be redefined by the vendor within 1045 | the encapsulated vendor-specific extensions field, but SHOULD 1046 | conform to the tag-length-value syntax defined in section 2. 1047 | 1048 | 3) Code 255 (END), if present, signifies the end of the 1049 | encapsulated vendor extensions, not the end of the vendor 1050 | extensions field. If no code 255 is present, then the end of 1051 | the enclosing vendor-specific information field is taken as the 1052 | end of the encapsulated vendor-specific extensions field. 1053 | 1054 | The code for this option is 43 and its minimum length is 1. 1055 | 1056 | Code Len Vendor-specific information 1057 | +-----+-----+-----+-----+--- 1058 | | 43 | n | i1 | i2 | ... 1059 | +-----+-----+-----+-----+--- 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | Alexander & Droms Standards Track [Page 19] 1067 | 1068 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1069 | 1070 | 1071 | When encapsulated vendor-specific extensions are used, the 1072 | information bytes 1-n have the following format: 1073 | 1074 | Code Len Data item Code Len Data item Code 1075 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 1076 | | T1 | n | d1 | d2 | ... | T2 | n | D1 | D2 | ... | ... | 1077 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 1078 | 1079 | 8.5. NetBIOS over TCP/IP Name Server Option 1080 | 1081 | The NetBIOS name server (NBNS) option specifies a list of RFC 1082 | 1001/1002 [19] [20] NBNS name servers listed in order of preference. 1083 | 1084 | The code for this option is 44. The minimum length of the option is 1085 | 4 octets, and the length must always be a multiple of 4. 1086 | 1087 | Code Len Address 1 Address 2 1088 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- 1089 | | 44 | n | a1 | a2 | a3 | a4 | b1 | b2 | b3 | b4 | ... 1090 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- 1091 | 1092 | 8.6. NetBIOS over TCP/IP Datagram Distribution Server Option 1093 | 1094 | The NetBIOS datagram distribution server (NBDD) option specifies a 1095 | list of RFC 1001/1002 NBDD servers listed in order of preference. The 1096 | code for this option is 45. The minimum length of the option is 4 1097 | octets, and the length must always be a multiple of 4. 1098 | 1099 | Code Len Address 1 Address 2 1100 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- 1101 | | 45 | n | a1 | a2 | a3 | a4 | b1 | b2 | b3 | b4 | ... 1102 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- 1103 | 1104 | 8.7. NetBIOS over TCP/IP Node Type Option 1105 | 1106 | The NetBIOS node type option allows NetBIOS over TCP/IP clients which 1107 | are configurable to be configured as described in RFC 1001/1002. The 1108 | value is specified as a single octet which identifies the client type 1109 | as follows: 1110 | 1111 | Value Node Type 1112 | ----- --------- 1113 | 0x1 B-node 1114 | 0x2 P-node 1115 | 0x4 M-node 1116 | 0x8 H-node 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | Alexander & Droms Standards Track [Page 20] 1123 | 1124 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1125 | 1126 | 1127 | In the above chart, the notation '0x' indicates a number in base-16 1128 | (hexadecimal). 1129 | 1130 | The code for this option is 46. The length of this option is always 1131 | 1. 1132 | 1133 | Code Len Node Type 1134 | +-----+-----+-----------+ 1135 | | 46 | 1 | see above | 1136 | +-----+-----+-----------+ 1137 | 1138 | 8.8. NetBIOS over TCP/IP Scope Option 1139 | 1140 | The NetBIOS scope option specifies the NetBIOS over TCP/IP scope 1141 | parameter for the client as specified in RFC 1001/1002. See [19], 1142 | [20], and [8] for character-set restrictions. 1143 | 1144 | The code for this option is 47. The minimum length of this option is 1145 | 1. 1146 | 1147 | Code Len NetBIOS Scope 1148 | +-----+-----+-----+-----+-----+-----+---- 1149 | | 47 | n | s1 | s2 | s3 | s4 | ... 1150 | +-----+-----+-----+-----+-----+-----+---- 1151 | 1152 | 8.9. X Window System Font Server Option 1153 | 1154 | This option specifies a list of X Window System [21] Font servers 1155 | available to the client. Servers SHOULD be listed in order of 1156 | preference. 1157 | 1158 | The code for this option is 48. The minimum length of this option is 1159 | 4 octets, and the length MUST be a multiple of 4. 1160 | 1161 | Code Len Address 1 Address 2 1162 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 1163 | | 48 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1164 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 1165 | 1166 | 8.10. X Window System Display Manager Option 1167 | 1168 | This option specifies a list of IP addresses of systems that are 1169 | running the X Window System Display Manager and are available to the 1170 | client. 1171 | 1172 | Addresses SHOULD be listed in order of preference. 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | Alexander & Droms Standards Track [Page 21] 1179 | 1180 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1181 | 1182 | 1183 | The code for the this option is 49. The minimum length of this option 1184 | is 4, and the length MUST be a multiple of 4. 1185 | 1186 | Code Len Address 1 Address 2 1187 | 1188 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 1189 | | 49 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1190 | +-----+-----+-----+-----+-----+-----+-----+-----+--- 1191 | 1192 | 8.11. Network Information Service+ Domain Option 1193 | 1194 | This option specifies the name of the client's NIS+ [17] domain. The 1195 | domain is formatted as a character string consisting of characters 1196 | from the NVT ASCII character set. 1197 | 1198 | The code for this option is 64. Its minimum length is 1. 1199 | 1200 | Code Len NIS Client Domain Name 1201 | +-----+-----+-----+-----+-----+-----+--- 1202 | | 64 | n | n1 | n2 | n3 | n4 | ... 1203 | +-----+-----+-----+-----+-----+-----+--- 1204 | 1205 | 8.12. Network Information Service+ Servers Option 1206 | 1207 | This option specifies a list of IP addresses indicating NIS+ servers 1208 | available to the client. Servers SHOULD be listed in order of 1209 | preference. 1210 | 1211 | The code for this option is 65. Its minimum length is 4, and the 1212 | length MUST be a multiple of 4. 1213 | 1214 | Code Len Address 1 Address 2 1215 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1216 | | 65 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1217 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1218 | 1219 | 8.13. Mobile IP Home Agent option 1220 | 1221 | This option specifies a list of IP addresses indicating mobile IP 1222 | home agents available to the client. Agents SHOULD be listed in 1223 | order of preference. 1224 | 1225 | The code for this option is 68. Its minimum length is 0 (indicating 1226 | no home agents are available) and the length MUST be a multiple of 4. 1227 | It is expected that the usual length will be four octets, containing 1228 | a single home agent's address. 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | Alexander & Droms Standards Track [Page 22] 1235 | 1236 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1237 | 1238 | 1239 | Code Len Home Agent Addresses (zero or more) 1240 | +-----+-----+-----+-----+-----+-----+-- 1241 | | 68 | n | a1 | a2 | a3 | a4 | ... 1242 | +-----+-----+-----+-----+-----+-----+-- 1243 | 1244 | 8.14. Simple Mail Transport Protocol (SMTP) Server Option 1245 | 1246 | The SMTP server option specifies a list of SMTP servers available to 1247 | the client. Servers SHOULD be listed in order of preference. 1248 | 1249 | The code for the SMTP server option is 69. The minimum length for 1250 | this option is 4 octets, and the length MUST always be a multiple of 1251 | 4. 1252 | 1253 | Code Len Address 1 Address 2 1254 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1255 | | 69 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1256 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1257 | 1258 | 8.15. Post Office Protocol (POP3) Server Option 1259 | 1260 | The POP3 server option specifies a list of POP3 available to the 1261 | client. Servers SHOULD be listed in order of preference. 1262 | 1263 | The code for the POP3 server option is 70. The minimum length for 1264 | this option is 4 octets, and the length MUST always be a multiple of 1265 | 4. 1266 | 1267 | Code Len Address 1 Address 2 1268 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1269 | | 70 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1270 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1271 | 1272 | 8.16. Network News Transport Protocol (NNTP) Server Option 1273 | 1274 | The NNTP server option specifies a list of NNTP available to the 1275 | client. Servers SHOULD be listed in order of preference. 1276 | 1277 | The code for the NNTP server option is 71. The minimum length for 1278 | this option is 4 octets, and the length MUST always be a multiple of 1279 | 4. 1280 | 1281 | Code Len Address 1 Address 2 1282 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1283 | | 71 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1284 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | Alexander & Droms Standards Track [Page 23] 1291 | 1292 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1293 | 1294 | 1295 | 8.17. Default World Wide Web (WWW) Server Option 1296 | 1297 | The WWW server option specifies a list of WWW available to the 1298 | client. Servers SHOULD be listed in order of preference. 1299 | 1300 | The code for the WWW server option is 72. The minimum length for 1301 | this option is 4 octets, and the length MUST always be a multiple of 1302 | 4. 1303 | 1304 | Code Len Address 1 Address 2 1305 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1306 | | 72 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1307 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1308 | 1309 | 8.18. Default Finger Server Option 1310 | 1311 | The Finger server option specifies a list of Finger available to the 1312 | client. Servers SHOULD be listed in order of preference. 1313 | 1314 | The code for the Finger server option is 73. The minimum length for 1315 | this option is 4 octets, and the length MUST always be a multiple of 1316 | 4. 1317 | 1318 | Code Len Address 1 Address 2 1319 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1320 | | 73 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1321 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1322 | 1323 | 8.19. Default Internet Relay Chat (IRC) Server Option 1324 | 1325 | The IRC server option specifies a list of IRC available to the 1326 | client. Servers SHOULD be listed in order of preference. 1327 | 1328 | The code for the IRC server option is 74. The minimum length for 1329 | this option is 4 octets, and the length MUST always be a multiple of 1330 | 4. 1331 | 1332 | Code Len Address 1 Address 2 1333 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1334 | | 74 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1335 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1336 | 1337 | 8.20. StreetTalk Server Option 1338 | 1339 | The StreetTalk server option specifies a list of StreetTalk servers 1340 | available to the client. Servers SHOULD be listed in order of 1341 | preference. 1342 | 1343 | 1344 | 1345 | 1346 | Alexander & Droms Standards Track [Page 24] 1347 | 1348 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1349 | 1350 | 1351 | The code for the StreetTalk server option is 75. The minimum length 1352 | for this option is 4 octets, and the length MUST always be a multiple 1353 | of 4. 1354 | 1355 | Code Len Address 1 Address 2 1356 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1357 | | 75 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1358 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1359 | 1360 | 8.21. StreetTalk Directory Assistance (STDA) Server Option 1361 | 1362 | The StreetTalk Directory Assistance (STDA) server option specifies a 1363 | list of STDA servers available to the client. Servers SHOULD be 1364 | listed in order of preference. 1365 | 1366 | The code for the StreetTalk Directory Assistance server option is 76. 1367 | The minimum length for this option is 4 octets, and the length MUST 1368 | always be a multiple of 4. 1369 | 1370 | Code Len Address 1 Address 2 1371 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1372 | | 76 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... 1373 | +-----+-----+-----+-----+-----+-----+-----+-----+-- 1374 | 1375 | 9. DHCP Extensions 1376 | 1377 | This section details the options that are specific to DHCP. 1378 | 1379 | 9.1. Requested IP Address 1380 | 1381 | This option is used in a client request (DHCPDISCOVER) to allow the 1382 | client to request that a particular IP address be assigned. 1383 | 1384 | The code for this option is 50, and its length is 4. 1385 | 1386 | Code Len Address 1387 | +-----+-----+-----+-----+-----+-----+ 1388 | | 50 | 4 | a1 | a2 | a3 | a4 | 1389 | +-----+-----+-----+-----+-----+-----+ 1390 | 1391 | 9.2. IP Address Lease Time 1392 | 1393 | This option is used in a client request (DHCPDISCOVER or DHCPREQUEST) 1394 | to allow the client to request a lease time for the IP address. In a 1395 | server reply (DHCPOFFER), a DHCP server uses this option to specify 1396 | the lease time it is willing to offer. 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | Alexander & Droms Standards Track [Page 25] 1403 | 1404 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1405 | 1406 | 1407 | The time is in units of seconds, and is specified as a 32-bit 1408 | unsigned integer. 1409 | 1410 | The code for this option is 51, and its length is 4. 1411 | 1412 | Code Len Lease Time 1413 | +-----+-----+-----+-----+-----+-----+ 1414 | | 51 | 4 | t1 | t2 | t3 | t4 | 1415 | +-----+-----+-----+-----+-----+-----+ 1416 | 1417 | 9.3. Option Overload 1418 | 1419 | This option is used to indicate that the DHCP 'sname' or 'file' 1420 | fields are being overloaded by using them to carry DHCP options. A 1421 | DHCP server inserts this option if the returned parameters will 1422 | exceed the usual space allotted for options. 1423 | 1424 | If this option is present, the client interprets the specified 1425 | additional fields after it concludes interpretation of the standard 1426 | option fields. 1427 | 1428 | The code for this option is 52, and its length is 1. Legal values 1429 | for this option are: 1430 | 1431 | Value Meaning 1432 | ----- -------- 1433 | 1 the 'file' field is used to hold options 1434 | 2 the 'sname' field is used to hold options 1435 | 3 both fields are used to hold options 1436 | 1437 | Code Len Value 1438 | +-----+-----+-----+ 1439 | | 52 | 1 |1/2/3| 1440 | +-----+-----+-----+ 1441 | 1442 | 9.4 TFTP server name 1443 | 1444 | This option is used to identify a TFTP server when the 'sname' field 1445 | in the DHCP header has been used for DHCP options. 1446 | 1447 | The code for this option is 66, and its minimum length is 1. 1448 | 1449 | Code Len TFTP server 1450 | +-----+-----+-----+-----+-----+--- 1451 | | 66 | n | c1 | c2 | c3 | ... 1452 | +-----+-----+-----+-----+-----+--- 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | Alexander & Droms Standards Track [Page 26] 1459 | 1460 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1461 | 1462 | 1463 | 9.5 Bootfile name 1464 | 1465 | This option is used to identify a bootfile when the 'file' field in 1466 | the DHCP header has been used for DHCP options. 1467 | 1468 | The code for this option is 67, and its minimum length is 1. 1469 | 1470 | Code Len Bootfile name 1471 | +-----+-----+-----+-----+-----+--- 1472 | | 67 | n | c1 | c2 | c3 | ... 1473 | +-----+-----+-----+-----+-----+--- 1474 | 1475 | 9.6. DHCP Message Type 1476 | 1477 | This option is used to convey the type of the DHCP message. The code 1478 | for this option is 53, and its length is 1. Legal values for this 1479 | option are: 1480 | 1481 | Value Message Type 1482 | ----- ------------ 1483 | 1 DHCPDISCOVER 1484 | 2 DHCPOFFER 1485 | 3 DHCPREQUEST 1486 | 4 DHCPDECLINE 1487 | 5 DHCPACK 1488 | 6 DHCPNAK 1489 | 7 DHCPRELEASE 1490 | 8 DHCPINFORM 1491 | 1492 | Code Len Type 1493 | +-----+-----+-----+ 1494 | | 53 | 1 | 1-9 | 1495 | +-----+-----+-----+ 1496 | 1497 | 9.7. Server Identifier 1498 | 1499 | This option is used in DHCPOFFER and DHCPREQUEST messages, and may 1500 | optionally be included in the DHCPACK and DHCPNAK messages. DHCP 1501 | servers include this option in the DHCPOFFER in order to allow the 1502 | client to distinguish between lease offers. DHCP clients use the 1503 | contents of the 'server identifier' field as the destination address 1504 | for any DHCP messages unicast to the DHCP server. DHCP clients also 1505 | indicate which of several lease offers is being accepted by including 1506 | this option in a DHCPREQUEST message. 1507 | 1508 | The identifier is the IP address of the selected server. 1509 | 1510 | The code for this option is 54, and its length is 4. 1511 | 1512 | 1513 | 1514 | Alexander & Droms Standards Track [Page 27] 1515 | 1516 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1517 | 1518 | 1519 | Code Len Address 1520 | +-----+-----+-----+-----+-----+-----+ 1521 | | 54 | 4 | a1 | a2 | a3 | a4 | 1522 | +-----+-----+-----+-----+-----+-----+ 1523 | 1524 | 9.8. Parameter Request List 1525 | 1526 | This option is used by a DHCP client to request values for specified 1527 | configuration parameters. The list of requested parameters is 1528 | specified as n octets, where each octet is a valid DHCP option code 1529 | as defined in this document. 1530 | 1531 | The client MAY list the options in order of preference. The DHCP 1532 | server is not required to return the options in the requested order, 1533 | but MUST try to insert the requested options in the order requested 1534 | by the client. 1535 | 1536 | The code for this option is 55. Its minimum length is 1. 1537 | 1538 | Code Len Option Codes 1539 | +-----+-----+-----+-----+--- 1540 | | 55 | n | c1 | c2 | ... 1541 | +-----+-----+-----+-----+--- 1542 | 1543 | 9.9. Message 1544 | 1545 | This option is used by a DHCP server to provide an error message to a 1546 | DHCP client in a DHCPNAK message in the event of a failure. A client 1547 | may use this option in a DHCPDECLINE message to indicate the why the 1548 | client declined the offered parameters. The message consists of n 1549 | octets of NVT ASCII text, which the client may display on an 1550 | available output device. 1551 | 1552 | The code for this option is 56 and its minimum length is 1. 1553 | 1554 | Code Len Text 1555 | +-----+-----+-----+-----+--- 1556 | | 56 | n | c1 | c2 | ... 1557 | +-----+-----+-----+-----+--- 1558 | 1559 | 9.10. Maximum DHCP Message Size 1560 | 1561 | This option specifies the maximum length DHCP message that it is 1562 | willing to accept. The length is specified as an unsigned 16-bit 1563 | integer. A client may use the maximum DHCP message size option in 1564 | DHCPDISCOVER or DHCPREQUEST messages, but should not use the option 1565 | in DHCPDECLINE messages. 1566 | 1567 | 1568 | 1569 | 1570 | Alexander & Droms Standards Track [Page 28] 1571 | 1572 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1573 | 1574 | 1575 | The code for this option is 57, and its length is 2. The minimum 1576 | legal value is 576 octets. 1577 | 1578 | Code Len Length 1579 | +-----+-----+-----+-----+ 1580 | | 57 | 2 | l1 | l2 | 1581 | +-----+-----+-----+-----+ 1582 | 1583 | 9.11. Renewal (T1) Time Value 1584 | 1585 | This option specifies the time interval from address assignment until 1586 | the client transitions to the RENEWING state. 1587 | 1588 | The value is in units of seconds, and is specified as a 32-bit 1589 | unsigned integer. 1590 | 1591 | The code for this option is 58, and its length is 4. 1592 | 1593 | Code Len T1 Interval 1594 | +-----+-----+-----+-----+-----+-----+ 1595 | | 58 | 4 | t1 | t2 | t3 | t4 | 1596 | +-----+-----+-----+-----+-----+-----+ 1597 | 1598 | 9.12. Rebinding (T2) Time Value 1599 | 1600 | This option specifies the time interval from address assignment until 1601 | the client transitions to the REBINDING state. 1602 | 1603 | The value is in units of seconds, and is specified as a 32-bit 1604 | unsigned integer. 1605 | 1606 | The code for this option is 59, and its length is 4. 1607 | 1608 | Code Len T2 Interval 1609 | +-----+-----+-----+-----+-----+-----+ 1610 | | 59 | 4 | t1 | t2 | t3 | t4 | 1611 | +-----+-----+-----+-----+-----+-----+ 1612 | 1613 | 9.13. Vendor class identifier 1614 | 1615 | This option is used by DHCP clients to optionally identify the vendor 1616 | type and configuration of a DHCP client. The information is a string 1617 | of n octets, interpreted by servers. Vendors may choose to define 1618 | specific vendor class identifiers to convey particular configuration 1619 | or other identification information about a client. For example, the 1620 | identifier may encode the client's hardware configuration. Servers 1621 | not equipped to interpret the class-specific information sent by a 1622 | client MUST ignore it (although it may be reported). Servers that 1623 | 1624 | 1625 | 1626 | Alexander & Droms Standards Track [Page 29] 1627 | 1628 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1629 | 1630 | 1631 | respond SHOULD only use option 43 to return the vendor-specific 1632 | information to the client. 1633 | 1634 | The code for this option is 60, and its minimum length is 1. 1635 | 1636 | Code Len Vendor class Identifier 1637 | +-----+-----+-----+-----+--- 1638 | | 60 | n | i1 | i2 | ... 1639 | +-----+-----+-----+-----+--- 1640 | 1641 | 9.14. Client-identifier 1642 | 1643 | This option is used by DHCP clients to specify their unique 1644 | identifier. DHCP servers use this value to index their database of 1645 | address bindings. This value is expected to be unique for all 1646 | clients in an administrative domain. 1647 | 1648 | Identifiers SHOULD be treated as opaque objects by DHCP servers. 1649 | 1650 | The client identifier MAY consist of type-value pairs similar to the 1651 | 'htype'/'chaddr' fields defined in [3]. For instance, it MAY consist 1652 | of a hardware type and hardware address. In this case the type field 1653 | SHOULD be one of the ARP hardware types defined in STD2 [22]. A 1654 | hardware type of 0 (zero) should be used when the value field 1655 | contains an identifier other than a hardware address (e.g. a fully 1656 | qualified domain name). 1657 | 1658 | For correct identification of clients, each client's client- 1659 | identifier MUST be unique among the client-identifiers used on the 1660 | subnet to which the client is attached. Vendors and system 1661 | administrators are responsible for choosing client-identifiers that 1662 | meet this requirement for uniqueness. 1663 | 1664 | The code for this option is 61, and its minimum length is 2. 1665 | 1666 | Code Len Type Client-Identifier 1667 | +-----+-----+-----+-----+-----+--- 1668 | | 61 | n | t1 | i1 | i2 | ... 1669 | +-----+-----+-----+-----+-----+--- 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 | 1679 | 1680 | 1681 | 1682 | Alexander & Droms Standards Track [Page 30] 1683 | 1684 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1685 | 1686 | 1687 | 10. Defining new extensions 1688 | 1689 | The author of a new DHCP option will follow these steps to obtain 1690 | acceptance of the option as a part of the DHCP Internet Standard: 1691 | 1692 | 1. The author devises the new option. 1693 | 2. The author requests a number for the new option from IANA by 1694 | contacting: 1695 | Internet Assigned Numbers Authority (IANA) 1696 | USC/Information Sciences Institute 1697 | 4676 Admiralty Way 1698 | Marina del Rey, California 90292-6695 1699 | 1700 | or by email as: iana@iana.org 1701 | 1702 | 3. The author documents the new option, using the newly obtained 1703 | option number, as an Internet Draft. 1704 | 4. The author submits the Internet Draft for review through the IETF 1705 | standards process as defined in "Internet Official Protocol 1706 | Standards" (STD 1). The new option will be submitted for eventual 1707 | acceptance as an Internet Standard. 1708 | 5. The new option progresses through the IETF standards process; the 1709 | new option will be reviewed by the Dynamic Host Configuration 1710 | Working Group (if that group still exists), or as an Internet 1711 | Draft not submitted by an IETF working group. 1712 | 6. If the new option fails to gain acceptance as an Internet 1713 | Standard, the assigned option number will be returned to IANA for 1714 | reassignment. 1715 | 1716 | This procedure for defining new extensions will ensure that: 1717 | 1718 | * allocation of new option numbers is coordinated from a single 1719 | authority, 1720 | * new options are reviewed for technical correctness and 1721 | appropriateness, and 1722 | * documentation for new options is complete and published. 1723 | 1724 | 11. Acknowledgements 1725 | 1726 | The author thanks the many (and too numerous to mention!) members of 1727 | the DHC WG for their tireless and ongoing efforts in the development 1728 | of DHCP and this document. 1729 | 1730 | The efforts of J Allard, Mike Carney, Dave Lapp, Fred Lien and John 1731 | Mendonca in organizing DHCP interoperability testing sessions are 1732 | gratefully acknowledged. 1733 | 1734 | 1735 | 1736 | 1737 | 1738 | Alexander & Droms Standards Track [Page 31] 1739 | 1740 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1741 | 1742 | 1743 | The development of this document was supported in part by grants from 1744 | the Corporation for National Research Initiatives (CNRI), Bucknell 1745 | University and Sun Microsystems. 1746 | 1747 | 12. References 1748 | 1749 | [1] Droms, R., "Dynamic Host Configuration Protocol", RFC 2131, 1750 | Bucknell University, March 1997. 1751 | 1752 | [2] Reynolds, J., "BOOTP Vendor Information Extensions", RFC 1497, 1753 | USC/Information Sciences Institute, August 1993. 1754 | 1755 | [3] Croft, W., and J. Gilmore, "Bootstrap Protocol", RFC 951, 1756 | Stanford University and Sun Microsystems, September 1985. 1757 | 1758 | [4] Braden, R., Editor, "Requirements for Internet Hosts - 1759 | Communication Layers", STD 3, RFC 1122, USC/Information Sciences 1760 | Institute, October 1989. 1761 | 1762 | [5] Mogul, J., and J. Postel, "Internet Standard Subnetting 1763 | Procedure", STD 5, RFC 950, USC/Information Sciences Institute, 1764 | August 1985. 1765 | 1766 | [6] Postel, J., and K. Harrenstien, "Time Protocol", STD 26, RFC 1767 | 868, USC/Information Sciences Institute, SRI, May 1983. 1768 | 1769 | [7] Postel, J., "Name Server", IEN 116, USC/Information Sciences 1770 | Institute, August 1979. 1771 | 1772 | [8] Mockapetris, P., "Domain Names - Implementation and 1773 | Specification", STD 13, RFC 1035, USC/Information Sciences 1774 | Institute, November 1987. 1775 | 1776 | [9] Postel, J., "Quote of the Day Protocol", STD 23, RFC 865, 1777 | USC/Information Sciences Institute, May 1983. 1778 | 1779 | [10] McLaughlin, L., "Line Printer Daemon Protocol", RFC 1179, The 1780 | Wollongong Group, August 1990. 1781 | 1782 | [11] Accetta, M., "Resource Location Protocol", RFC 887, CMU, 1783 | December 1983. 1784 | 1785 | [12] Mogul, J. and S. Deering, "Path MTU Discovery", RFC 1191, 1786 | DECWRL, Stanford University, November 1990. 1787 | 1788 | [13] Deering, S., "ICMP Router Discovery Messages", RFC 1256, 1789 | Xerox PARC, September 1991. 1790 | 1791 | 1792 | 1793 | 1794 | Alexander & Droms Standards Track [Page 32] 1795 | 1796 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1797 | 1798 | 1799 | [14] Leffler, S. and M. Karels, "Trailer Encapsulations", RFC 893, 1800 | U. C. Berkeley, April 1984. 1801 | 1802 | [15] Hornig, C., "Standard for the Transmission of IP Datagrams over 1803 | Ethernet Networks", RFC 894, Symbolics, April 1984. 1804 | 1805 | [16] Postel, J. and J. Reynolds, "Standard for the Transmission of 1806 | IP Datagrams Over IEEE 802 Networks", RFC 1042, USC/Information 1807 | Sciences Institute, February 1988. 1808 | 1809 | [17] Sun Microsystems, "System and Network Administration", March 1810 | 1990. 1811 | 1812 | [18] Mills, D., "Internet Time Synchronization: The Network Time 1813 | Protocol", RFC 1305, UDEL, March 1992. 1814 | 1815 | [19] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service 1816 | on a TCP/UDP transport: Concepts and Methods", STD 19, RFC 1001, 1817 | March 1987. 1818 | 1819 | [20] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service 1820 | on a TCP/UDP transport: Detailed Specifications", STD 19, RFC 1821 | 1002, March 1987. 1822 | 1823 | [21] Scheifler, R., "FYI On the X Window System", FYI 6, RFC 1198, 1824 | MIT Laboratory for Computer Science, January 1991. 1825 | 1826 | [22] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700, 1827 | USC/Information Sciences Institute, July 1992. 1828 | 1829 | 13. Security Considerations 1830 | 1831 | Security issues are not discussed in this memo. 1832 | 1833 | 1834 | 1835 | 1836 | 1837 | 1838 | 1839 | 1840 | 1841 | 1842 | 1843 | 1844 | 1845 | 1846 | 1847 | 1848 | 1849 | 1850 | Alexander & Droms Standards Track [Page 33] 1851 | 1852 | RFC 2132 DHCP Options and BOOTP Vendor Extensions March 1997 1853 | 1854 | 1855 | 14. Authors' Addresses 1856 | 1857 | Steve Alexander 1858 | Silicon Graphics, Inc. 1859 | 2011 N. Shoreline Boulevard 1860 | Mailstop 510 1861 | Mountain View, CA 94043-1389 1862 | 1863 | Phone: (415) 933-6172 1864 | EMail: sca@engr.sgi.com 1865 | 1866 | 1867 | Ralph Droms 1868 | Bucknell University 1869 | Lewisburg, PA 17837 1870 | 1871 | Phone: (717) 524-1145 1872 | EMail: droms@bucknell.edu 1873 | 1874 | 1875 | 1876 | 1877 | 1878 | 1879 | 1880 | 1881 | 1882 | 1883 | 1884 | 1885 | 1886 | 1887 | 1888 | 1889 | 1890 | 1891 | 1892 | 1893 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 | 1900 | 1901 | 1902 | 1903 | 1904 | 1905 | 1906 | Alexander & Droms Standards Track [Page 34] 1907 | 1908 | --------------------------------------------------------------------------------