| | 205 | int DhcpConstructRequest(char* buf) |
| | 206 | { |
| | 207 | int offset, length; |
| | 208 | struct DhcpPacket* dhcpPacket; |
| | 209 | struct DhcpOption* options; |
| | 210 | BYTE optionsWanted[7]={1, 28, 2, 3, 15, 6, 12}; |
| | 211 | DWORD netAddress; |
| | 212 | |
| | 213 | offset=DhcpConstructHeaders(buf); |
| | 214 | |
| | 215 | dhcpPacket=(struct DhcpPacket*)(buf+offset); |
| | 216 | memset(dhcpPacket, 0, sizeof(struct DhcpPacket)); |
| | 217 | |
| | 218 | dhcpPacket->op=DHCP_BOOT_REQUEST; |
| | 219 | dhcpPacket->hType=1; |
| | 220 | dhcpPacket->hLen=6; |
| | 221 | dhcpPacket->flags=HostToNetShort(0x8000); |
| | 222 | dhcpPacket->xId=HostToNetLong(0xDEADBEEF); |
| | 223 | |
| | 224 | memcpy(dhcpPacket->clientHw, sourceAddr, 6); |
| | 225 | dhcpPacket->cookie=HostToNetLong(0x63825363); |
| | 226 | |
| | 227 | options=(struct DhcpOption*)(buf+offset+sizeof(struct DhcpPacket)); |
| | 228 | |
| | 229 | /* DHCP message type. */ |
| | 230 | options->code=53; |
| | 231 | options->len=1; |
| | 232 | options->data[0]=3; |
| | 233 | |
| | 234 | length=offset+sizeof(struct DhcpPacket)+sizeof(struct DhcpOption); |
| | 235 | |
| | 236 | netAddress=HostToNetLong(address); |
| | 237 | |
| | 238 | options=(struct DhcpOption*)(buf+length); |
| | 239 | options->code=50; |
| | 240 | options->len=4; |
| | 241 | memcpy(options->data, &netAddress, 4); |
| | 242 | |
| | 243 | length+=sizeof(struct DhcpOption)+3; |
| | 244 | |
| | 245 | options=(struct DhcpOption*)(buf+length); |
| | 246 | options->code=54; |
| | 247 | options->len=4; |
| | 248 | memcpy(options->data, &serverIp, 4); |
| | 249 | |
| | 250 | length+=sizeof(struct DhcpOption)+3; |
| | 251 | |
| | 252 | /* End option */ |
| | 253 | buf[length]=0xFF; |
| | 254 | length++; |
| | 255 | |
| | 256 | /* Padding */ |
| | 257 | memset(buf+length, 0, 344-length); |
| | 258 | |
| | 259 | length=344; |
| | 260 | |
| | 261 | DhcpFinishPacket(buf, length); |
| | 262 | |
| | 263 | return length; |
| | 264 | } |
| | 265 | |
| | 266 | int DhcpPacketCheck(char* buf) |
| | 267 | { |
| | 268 | struct EthHeader* ethHeader=(struct EthHeader*)buf; |
| | 269 | struct IpHeader* ipHeader; |
| | 270 | struct UdpHeader* udpHeader; |
| | 271 | |
| | 272 | if (HostToNetShort(ethHeader->ethType) != ETH_TYPE_IP) |
| | 273 | return 0; |
| | 274 | |
| | 275 | #if 0 |
| | 276 | printf("%X:%X:%X:%X:%X:%X\n", ethHeader->dest[0], ethHeader->dest[1], ethHeader->dest[2], |
| | 277 | ethHeader->dest[3], ethHeader->dest[4], ethHeader->dest[5]); |
| | 278 | |
| | 279 | /* Should be addressed only to us. */ |
| | 280 | if (memcmp(sourceAddr, ethHeader->dest, 6)) |
| | 281 | return 0; |
| | 282 | #endif |
| | 283 | |
| | 284 | ipHeader=(struct IpHeader*)(buf+sizeof(struct EthHeader)); |
| | 285 | |
| | 286 | /* TODO: Checksum */ |
| | 287 | |
| | 288 | if (ipHeader->protocol != PROTOCOL_RAW_UDP) |
| | 289 | return 0; |
| | 290 | |
| | 291 | udpHeader=(struct UdpHeader*)(buf+sizeof(struct EthHeader)+sizeof(struct IpHeader)); |
| | 292 | |
| | 293 | if (HostToNetShort(udpHeader->destPort) != 68) |
| | 294 | return 0; |
| | 295 | |
| | 296 | /* TODO: Checksum */ |
| | 297 | |
| | 298 | return 1; |
| | 299 | } |
| | 300 | |
| | 301 | int DhcpParseOffer(char* buf) |
| | 302 | { |
| | 303 | struct DhcpPacket* dhcpPacket=(struct DhcpPacket*)(buf+sizeof(struct EthHeader)+sizeof(struct IpHeader)+sizeof(struct UdpHeader)); |
| | 304 | struct DhcpOption* dhcpOption=(struct DhcpOption*)((char*)dhcpPacket+sizeof(struct DhcpPacket)); |
| | 305 | char* option=(char*)dhcpOption; |
| | 306 | |
| | 307 | address=NetToHostLong(dhcpPacket->yourIp); |
| | 308 | |
| | 309 | while (dhcpOption->code != 0xFF) |
| | 310 | { |
| | 311 | if (dhcpOption->code == 54) |
| | 312 | { |
| | 313 | memcpy(&serverIp, dhcpOption->data, 4); |
| | 314 | break; |
| | 315 | } |
| | 316 | |
| | 317 | option+=sizeof(struct DhcpOption)+dhcpOption->len-1; |
| | 318 | dhcpOption=(struct DhcpOption*)option; |
| | 319 | } |
| | 320 | |
| | 321 | return 0; |
| | 322 | } |
| | 323 | |