13 static void parse_dhcp_options(void *, int, uint8_t);
15 static void subnet_mask(void *data
, int opt_len
)
19 IPInfo
.netmask
= *(uint32_t *)data
;
22 static void router(void *data
, int opt_len
)
26 IPInfo
.gateway
= *(uint32_t *)data
;
29 static void dns_servers(void *data
, int opt_len
)
31 int num
= opt_len
>> 2;
34 if (num
> DNS_MAX_SERVERS
)
35 num
= DNS_MAX_SERVERS
;
37 for (i
= 0; i
< num
; i
++) {
38 dns_server
[i
] = *(uint32_t *)data
;
44 * if you find you got no corret DNS server, you can add
45 * it here manually. BUT be carefull the DNS_MAX_SERVERS
47 if (i
< DNS_MAX_SERVERS
) {
48 dns_server
[i
++] = your_master_dns_server
;
49 dns_server
[i
++] = your_second_dns_server
;
54 static void local_domain(void *data
, int opt_len
)
56 char *p
= (char *)data
+ opt_len
;
57 char *ld
= LocalDomain
;
60 *p
= '\0'; /* Zero-terminate option */
61 dns_mangle(&ld
, data
);
62 *p
= end
; /* Restore ending byte */
65 static void vendor_encaps(void *data
, int opt_len
)
67 /* Only recongnize PXELINUX options */
68 parse_dhcp_options(data
, opt_len
, 208);
71 static void option_overload(void *data
, int opt_len
)
75 over_load
= *(uint8_t *)data
;
79 static void server(void *data
, int opt_len
)
89 ip
= *(uint32_t *)data
;
94 static void client_identifier(void *data
, int opt_len
)
96 if (opt_len
> MAC_MAX
|| opt_len
< 2 ||
97 MAC_len
!= (opt_len
>> 8) ||
98 *(uint8_t *)data
!= MAC_type
)
102 MAC_len
= opt_len
& 0xff;
103 memcpy(MAC
, data
+1, opt_len
);
107 static void bootfile_name(void *data
, int opt_len
)
109 strncpy(boot_file
, data
, opt_len
);
110 boot_file
[opt_len
] = 0;
113 static void uuid_client_identifier(void *data
, int opt_len
)
115 int type
= *(uint8_t *)data
;
116 if (opt_len
!= 17 || type
!= 0 || have_uuid
)
121 memcpy(uuid
, data
+1, 16);
125 static void pxelinux_configfile(void *data
, int opt_len
)
128 strncpy(ConfigName
, data
, opt_len
);
129 ConfigName
[opt_len
] = 0;
132 static void pxelinux_pathprefix(void *data
, int opt_len
)
135 strncpy(path_prefix
, data
, opt_len
);
136 path_prefix
[opt_len
] = 0;
139 static void pxelinux_reboottime(void *data
, int opt_len
)
141 if ((opt_len
&& 0xff) != 4)
144 RebootTime
= ntohl(*(uint32_t *)data
);
145 DHCPMagic
|= 8; /* Got reboot time */
149 struct dhcp_options
{
151 void (*fun
) (void *, int);
154 static struct dhcp_options dhcp_opts
[] = {
160 {52, option_overload
},
162 {61, client_identifier
},
164 {97, uuid_client_identifier
},
165 {209, pxelinux_configfile
},
166 {210, pxelinux_pathprefix
},
167 {211, pxelinux_reboottime
}
171 * Parse a sequence of DHCP options, pointed to by _option_;
172 * -- some DHCP servers leave option fields unterminated
173 * in violation of the spec.
175 * filter contains the minimum value for the option to recognize
176 * -- this is used to restrict parsing to PXELINUX-specific options only.
178 static void parse_dhcp_options(void *option
, int size
, uint8_t opt_filter
)
182 int opt_entries
= sizeof(dhcp_opts
) / sizeof(dhcp_opts
[0]);
185 struct dhcp_options
*opt
;
197 /* Anything else will have a lenght filed */
198 opt_len
= *p
++; /* c <- option lenght */
199 size
= size
- opt_len
- 1;
202 if (opt_num
< opt_filter
) { /* Is the option value valid */
203 option
+= opt_len
; /* Try next */
208 for (i
= 0; i
< opt_entries
; i
++) {
209 if (opt_num
== opt
->opt_num
) {
210 opt
->fun(p
, opt_len
);
224 * Parse a DHCP packet. This includes dealing with "overloaded"
225 * option fields (see RFC 2132, section 9.3)
227 * This should fill in the following global variables, if the
228 * information is present:
230 * MyIP - client IP address
231 * server_ip - boot server IP address
232 * net_mask - network mask
233 * gate_way - default gateway router IP
234 * boot_file - boot file name
235 * DNSServers - DNS server IPs
236 * LocalDomain - Local domain name
237 * MAC_len, MAC - Client identifier, if MAC_len == 0
239 * This assumes the DHCP packet is in "trackbuf".
242 void parse_dhcp(int pkt_len
)
244 struct bootp_t
*dhcp
= (struct bootp_t
*)trackbuf
;
247 IPInfo
.ipv4
= 4; /* This is IPv4 only for now... */
250 if (ip_ok(dhcp
->yip
))
251 IPInfo
.myip
= dhcp
->yip
;
253 if (ip_ok(dhcp
->sip
))
254 IPInfo
.serverip
= dhcp
->sip
;
256 opt_len
= (char *)dhcp
+ pkt_len
- (char *)&dhcp
->options
;
257 if (opt_len
&& (dhcp
->option_magic
== BOOTP_OPTION_MAGIC
))
258 parse_dhcp_options(&dhcp
->options
, opt_len
, 0);
261 parse_dhcp_options(&dhcp
->bootfile
, 128, 0);
262 else if (dhcp
->bootfile
[0])
263 strcpy(boot_file
, dhcp
->bootfile
);
266 parse_dhcp_options(dhcp
->sname
, 64, 0);