source: src/router/udhcpc/options.c @ 12611

Last change on this file since 12611 was 12611, checked in by BrainSlayer, 4 years ago

dont use it at the moment, untested

File size: 5.0 KB
Line 
1/*
2 * options.c -- DHCP server option packet tools
3 * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
4 */
5
6#include <stdlib.h>
7#include <string.h>
8
9#include "common.h"
10#include "dhcpd.h"
11#include "options.h"
12#include "files.h"
13
14
15/* supported options are easily added here */
16struct dhcp_option dhcp_options[] = {
17        /* name[10]     flags                                   code */
18        {"subnet",      OPTION_IP | OPTION_REQ,                 0x01},
19        {"timezone",    OPTION_S32,                             0x02},
20        {"router",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x03},
21        {"timesvr",     OPTION_IP | OPTION_LIST,                0x04},
22        {"namesvr",     OPTION_IP | OPTION_LIST,                0x05},
23        {"dns",         OPTION_IP | OPTION_LIST | OPTION_REQ,   0x06},
24        {"logsvr",      OPTION_IP | OPTION_LIST,                0x07},
25        {"cookiesvr",   OPTION_IP | OPTION_LIST,                0x08},
26        {"lprsvr",      OPTION_IP | OPTION_LIST,                0x09},
27        {"hostname",    OPTION_STRING | OPTION_REQ,             0x0c},
28        {"bootsize",    OPTION_U16,                             0x0d},
29        {"domain",      OPTION_STRING | OPTION_REQ,             0x0f},
30        {"swapsvr",     OPTION_IP,                              0x10},
31        {"rootpath",    OPTION_STRING,                          0x11},
32        {"ipttl",       OPTION_U8,                              0x17},
33        {"mtu",         OPTION_U16,                             0x1a},
34        {"broadcast",   OPTION_IP | OPTION_REQ,                 0x1c},
35//      {"static_routes",OPTION_IP_PAIR | OPTION_LIST,          0x21},
36        {"nisdomain",   OPTION_STRING | OPTION_REQ,             0x28},
37        {"nissrv",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x29},
38        {"ntpsrv",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x2a},
39        {"wins",        OPTION_IP | OPTION_LIST,                0x2c},
40        {"requestip",   OPTION_IP,                              0x32},
41        {"lease",       OPTION_U32,                             0x33},
42        {"dhcptype",    OPTION_U8,                              0x35},
43        {"serverid",    OPTION_IP,                              0x36},
44        {"message",     OPTION_STRING,                          0x38},
45        {"vendorclass", OPTION_STRING,                          0x3C},
46        {"clientid",    OPTION_STRING,                          0x3D},
47        {"tftp",        OPTION_STRING,                          0x42},
48        {"bootfile",    OPTION_STRING,                          0x43},
49        {"userclass",   OPTION_STRING,                          0x4D},
50//      {"search",      OPTION_STR1035 | OPTION_LIST,           0x77},
51        {"cidrroute",   OPTION_U8 | OPTION_LIST | OPTION_REQ,   0x79},
52        {"wpad",        OPTION_STRING,                          0xfc},
53        {"",            0x00,                           0x00}
54};
55
56/* Lengths of the different option types */
57int option_lengths[] = {
58        [OPTION_IP] =           4,
59        [OPTION_IP_PAIR] =      8,
60        [OPTION_BOOLEAN] =      1,
61        [OPTION_STRING] =       1,
62        [OPTION_STR1035] =      1,
63        [OPTION_U8] =           1,
64        [OPTION_U16] =          2,
65        [OPTION_S16] =          2,
66        [OPTION_U32] =          4,
67        [OPTION_S32] =          4
68};
69
70
71/* get an option with bounds checking (warning, not aligned). */
72uint8_t *get_option(struct dhcpMessage *packet, int code)
73{
74        int i, length;
75        uint8_t *optionptr;
76        int over = 0, done = 0, curr = OPTION_FIELD;
77
78        optionptr = packet->options;
79        i = 0;
80        length = 308;
81        while (!done) {
82                if (i >= length) {
83                        LOG(LOG_WARNING, "bogus packet, option fields too long.");
84                        return NULL;
85                }
86                if (optionptr[i + OPT_CODE] == code) {
87                        if (i + 1 + optionptr[i + OPT_LEN] >= length) {
88                                LOG(LOG_WARNING, "bogus packet, option fields too long.");
89                                return NULL;
90                        }
91                        return optionptr + i + 2;
92                }
93                switch (optionptr[i + OPT_CODE]) {
94                case DHCP_PADDING:
95                        i++;
96                        break;
97                case DHCP_OPTION_OVER:
98                        if (i + 1 + optionptr[i + OPT_LEN] >= length) {
99                                LOG(LOG_WARNING, "bogus packet, option fields too long.");
100                                return NULL;
101                        }
102                        over = optionptr[i + 3];
103                        i += optionptr[OPT_LEN] + 2;
104                        break;
105                case DHCP_END:
106                        if (curr == OPTION_FIELD && over & FILE_FIELD) {
107                                optionptr = packet->file;
108                                i = 0;
109                                length = 128;
110                                curr = FILE_FIELD;
111                        } else if (curr == FILE_FIELD && over & SNAME_FIELD) {
112                                optionptr = packet->sname;
113                                i = 0;
114                                length = 64;
115                                curr = SNAME_FIELD;
116                        } else done = 1;
117                        break;
118                default:
119                        i += optionptr[OPT_LEN + i] + 2;
120                }
121        }
122//      fprintf(stderr,"option 0x%X not found\n",code);
123        return NULL;
124}
125
126
127/* return the position of the 'end' option (no bounds checking) */
128int end_option(uint8_t *optionptr)
129{
130        int i = 0;
131
132        while (optionptr[i] != DHCP_END) {
133                if (optionptr[i] == DHCP_PADDING) i++;
134                else i += optionptr[i + OPT_LEN] + 2;
135        }
136        return i;
137}
138
139
140/* add an option string to the options (an option string contains an option code,
141 * length, then data) */
142int add_option_string(uint8_t *optionptr, uint8_t *string)
143{
144        int end = end_option(optionptr);
145
146        /* end position + string length + option code/length + end option */
147        if (end + string[OPT_LEN] + 2 + 1 >= 308) {
148                LOG(LOG_ERR, "Option 0x%02x did not fit into the packet!", string[OPT_CODE]);
149                return 0;
150        }
151        DEBUG(LOG_INFO, "adding option 0x%02x", string[OPT_CODE]);
152        memcpy(optionptr + end, string, string[OPT_LEN] + 2);
153        optionptr[end + string[OPT_LEN] + 2] = DHCP_END;
154        return string[OPT_LEN] + 2;
155}
156
157
158/* add a one to four byte option to a packet */
159int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data)
160{
161        struct dhcp_option *dh;
162
163        for (dh=dhcp_options; dh->code; dh++) {
164                if (dh->code == code) {
165                        uint8_t option[6], len;
166                       
167                        option[OPT_CODE] = code;
168                        len = option_lengths[dh->flags & TYPE_MASK];
169                        option[OPT_LEN] = len;
170                        if (__BYTE_ORDER == __BIG_ENDIAN)
171                                data <<= 8 * (4 - len);
172                        /* This memcpy is for broken processors which can't
173                         * handle a simple unaligned 32-bit assignment */
174                        memcpy(&option[OPT_DATA], &data, 4);
175                        return add_option_string(optionptr, option);
176                }
177        }
178
179        DEBUG(LOG_ERR, "Could not add option 0x%02x", code);
180        return 0;
181}
182
Note: See TracBrowser for help on using the repository browser.