Changeset 22101 in vbox for trunk/src/VBox
- Timestamp:
- Aug 8, 2009 6:22:29 AM (15 years ago)
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/bootp.c
r22027 r22101 27 27 28 28 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; 29 29 static void bootp_reply(PNATState pData, struct mbuf *m0, int off, uint16_t flags); 30 31 static uint8_t *dhcp_find_option(uint8_t *vend, uint8_t tag) 32 { 33 uint8_t *q = vend; 34 uint8_t len; 35 /*@todo magic validation */ 36 q += 4; /*magic*/ 37 while(*q != RFC1533_END) 38 { 39 if (*q == RFC1533_PAD) 40 continue; 41 if (*q == tag) 42 return q; 43 q++; 44 len = *q; 45 q += 1 + len; 46 } 47 return NULL; 48 } 49 static BOOTPClient *alloc_addr(PNATState pData) 50 { 51 int i; 52 for (i = 0; i < NB_ADDR; i++) 53 { 54 if (!bootp_clients[i].allocated) 55 { 56 BOOTPClient *bc; 57 58 bc = &bootp_clients[i]; 59 memset(bc, 0, sizeof(BOOTPClient)); 60 bc->allocated = 1; 61 bc->number = i; 62 return bc; 63 } 64 } 65 return NULL; 66 } 30 67 static BOOTPClient *get_new_addr(PNATState pData, struct in_addr *paddr) 31 68 { 32 int i; 33 69 BOOTPClient *bc; 70 bc = alloc_addr(pData); 71 if (bc == NULL) 72 return NULL; 73 paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (bc->number + START_ADDR)); 74 bc->addr.s_addr = paddr->s_addr; 75 return bc; 76 return NULL; 77 } 78 79 static int release_addr(PNATState pData, struct in_addr *paddr) 80 { 81 unsigned i; 34 82 for (i = 0; i < NB_ADDR; i++) 35 83 { 36 if (!bootp_clients[i].allocated) 37 { 38 BOOTPClient *bc; 39 40 bc = &bootp_clients[i]; 41 bc->allocated = 1; 42 paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); 43 bc->addr.s_addr = paddr->s_addr; 44 return bc; 45 } 46 } 47 return NULL; 48 } 49 50 static int release_addr(PNATState pData, struct in_addr *paddr) 51 { 52 unsigned i; 53 54 i = ntohl(paddr->s_addr) - START_ADDR - ntohl(special_addr.s_addr); 55 if (i >= NB_ADDR) 56 return 0; 57 58 memset(bootp_clients[i].macaddr, '\0', 6); 59 bootp_clients[i].allocated = 0; 60 return 1; 61 } 62 84 if (paddr->s_addr == bootp_clients[i].addr.s_addr) 85 { 86 memset(&bootp_clients[i], 0, sizeof(BOOTPClient)); 87 return 1; 88 } 89 } 90 return 0; 91 } 92 93 /* 94 * from RFC 2131 4.3.1 95 * Field DHCPOFFER DHCPACK DHCPNAK 96 * ----- --------- ------- ------- 97 * 'op' BOOTREPLY BOOTREPLY BOOTREPLY 98 * 'htype' (From "Assigned Numbers" RFC) 99 * 'hlen' (Hardware address length in octets) 100 * 'hops' 0 0 0 101 * 'xid' 'xid' from client 'xid' from client 'xid' from client 102 * DHCPDISCOVER DHCPREQUEST DHCPREQUEST 103 * message message message 104 * 'secs' 0 0 0 105 * 'ciaddr' 0 'ciaddr' from 0 106 * DHCPREQUEST or 0 107 * 'yiaddr' IP address offered IP address 0 108 * to client assigned to client 109 * 'siaddr' IP address of next IP address of next 0 110 * bootstrap server bootstrap server 111 * 'flags' 'flags' from 'flags' from 'flags' from 112 * client DHCPDISCOVER client DHCPREQUEST client DHCPREQUEST 113 * message message message 114 * 'giaddr' 'giaddr' from 'giaddr' from 'giaddr' from 115 * client DHCPDISCOVER client DHCPREQUEST client DHCPREQUEST 116 * message message message 117 * 'chaddr' 'chaddr' from 'chaddr' from 'chaddr' from 118 * client DHCPDISCOVER client DHCPREQUEST client DHCPREQUEST 119 * message message message 120 * 'sname' Server host name Server host name (unused) 121 * or options or options 122 * 'file' Client boot file Client boot file (unused) 123 * name or options name or options 124 * 'options' options options 125 * 126 * Option DHCPOFFER DHCPACK DHCPNAK 127 * ------ --------- ------- ------- 128 * Requested IP address MUST NOT MUST NOT MUST NOT 129 * IP address lease time MUST MUST (DHCPREQUEST) MUST NOT 130 * MUST NOT (DHCPINFORM) 131 * Use 'file'/'sname' fields MAY MAY MUST NOT 132 * DHCP message type DHCPOFFER DHCPACK DHCPNAK 133 * Parameter request list MUST NOT MUST NOT MUST NOT 134 * Message SHOULD SHOULD SHOULD 135 * Client identifier MUST NOT MUST NOT MAY 136 * Vendor class identifier MAY MAY MAY 137 * Server identifier MUST MUST MUST 138 * Maximum message size MUST NOT MUST NOT MUST NOT 139 * All others MAY MAY MUST NOT 140 */ 63 141 static BOOTPClient *find_addr(PNATState pData, struct in_addr *paddr, const uint8_t *macaddr) 64 142 { … … 80 158 } 81 159 82 static void dhcp_decode(const uint8_t *buf, int size, 83 int *pmsg_type, struct in_addr *req_ip) 84 { 85 const uint8_t *p, *p_end; 86 int len, tag; 87 88 *pmsg_type = 0; 89 90 p = buf; 91 p_end = buf + size; 92 if (size < 5) 93 return; 94 if (memcmp(p, rfc1533_cookie, 4) != 0) 95 return; 96 p += 4; 97 while (p < p_end) 98 { 99 tag = p[0]; 100 if (tag == RFC1533_PAD) 101 p++; 102 else if (tag == RFC1533_END) 103 break; 104 else 105 { 106 p++; 107 if (p >= p_end) 108 break; 109 len = *p++; 110 Log(("dhcp: tag=0x%02x len=%d\n", tag, len)); 111 112 switch(tag) 113 { 114 case RFC2132_REQ_ADDR: 115 if (len >= 4) 116 *req_ip = *(struct in_addr*)p; 117 break; 118 case RFC2132_MSG_TYPE: 119 if (len >= 1) 120 *pmsg_type = p[0]; 121 break; 122 default: 123 break; 124 } 125 p += len; 126 } 127 } 128 } 129 130 static void bootp_reply(PNATState pData, struct mbuf *m0) 131 { 132 BOOTPClient *bc; 133 struct mbuf *m; /* XXX: @todo vasily - it'd be better to reuse this mbuf here */ 134 struct bootp_t *bp = mtod(m0, struct bootp_t *); 160 static struct mbuf *dhcp_create_msg(PNATState pData, struct bootp_t *bp, struct mbuf *m, uint8_t type) 161 { 162 struct bootp_t *rbp; 135 163 struct ethhdr *eh; 136 struct bootp_t *rbp;137 struct sockaddr_in saddr, daddr;138 int dhcp_msg_type, val;139 164 uint8_t *q; 140 struct in_addr requested_ip; /* the requested IP in DHCPREQUEST */ 141 int send_nak = 0; 165 166 rbp = mtod(m, struct bootp_t *); 167 memset(rbp, 0, sizeof(struct bootp_t)); 168 eh = mtod(m, struct ethhdr *); 169 memcpy(eh->h_source, bp->bp_hwaddr, ETH_ALEN); /* XXX: if_encap just swap source with dest*/ 170 m->m_data += if_maxlinkhdr; /*reserve ether header */ 171 rbp = mtod(m, struct bootp_t *); 172 rbp->bp_op = BOOTP_REPLY; 173 rbp->bp_xid = bp->bp_xid; /* see table 3 of rfc2131*/ 174 rbp->flags = bp->flags; 175 rbp->bp_giaddr.s_addr = bp->bp_giaddr.s_addr; 176 #if 0 /*check flags*/ 177 saddr.sin_port = htons(BOOTP_SERVER); 178 daddr.sin_port = htons(BOOTP_CLIENT); 179 #endif 180 rbp->bp_htype = 1; 181 rbp->bp_hlen = 6; 182 memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6); 183 184 memcpy(rbp->bp_vend, rfc1533_cookie, 4); /* cookie */ 185 q = rbp->bp_vend; 186 q += 4; 187 *q++ = RFC2132_MSG_TYPE; 188 *q++ = 1; 189 *q++ = type; 190 191 return m; 192 } 193 194 static int dhcp_do_ack_offer(PNATState pData, struct mbuf *m, BOOTPClient *bc, int is_from_request) 195 { 196 int off = 0; 197 struct bootp_t *rbp = NULL; 198 uint8_t *q; 199 struct in_addr saddr; 200 int val; 201 202 struct dns_entry *de = NULL; 203 struct dns_domain_entry *dd = NULL; 204 int added = 0; 205 uint8_t *q_dns_header = NULL; 206 uint32_t lease_time = htonl(LEASE_TIME); 207 uint32_t netmask = htonl(pData->netmask); 208 209 rbp = mtod(m, struct bootp_t *); 210 q = &rbp->bp_vend[0]; 211 q += 7; /* !cookie rfc 2132 + TYPE*/ 212 213 /*DHCP Offer specific*/ 214 if ( tftp_prefix 215 && RTDirExists(tftp_prefix) 216 && bootp_filename) 217 RTStrPrintf((char*)rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename); 218 219 Log(("NAT: DHCP: bp_file:%s\n", &rbp->bp_file)); 220 /* Address/port of the DHCP server. */ 221 rbp->bp_yiaddr = bc->addr; /* Client IP address */ 222 Log(("NAT: DHCP: bp_yiaddr:%R[IP4]\n", &rbp->bp_yiaddr)); 223 rbp->bp_siaddr = pData->tftp_server; /* Next Server IP address, i.e. TFTP */ 224 Log(("NAT: DHCP: bp_siaddr:%R[IP4]\n", &rbp->bp_siaddr)); 225 if (is_from_request) 226 { 227 rbp->bp_ciaddr.s_addr = bc->addr.s_addr; /* Client IP address */ 228 } 229 #ifndef VBOX_WITH_NAT_SERVICE 230 saddr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); 231 #else 232 saddr.s_addr = special_addr.s_addr; 233 #endif 234 Log(("NAT: DHCP: s_addr:%R[IP4]\n", &saddr)); 142 235 143 236 #define FILL_BOOTP_EXT(q, tag, len, pvalue) \ … … 159 252 }while(0) 160 253 254 255 256 FILL_BOOTP_EXT(q, RFC1533_NETMASK, 4, &netmask); 257 FILL_BOOTP_EXT(q, RFC1533_GATEWAY, 4, &saddr); 258 259 if (pData->use_dns_proxy) 260 { 261 uint32_t addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); 262 FILL_BOOTP_EXT(q, RFC1533_DNS, 4, &addr); 263 goto skip_dns_servers; 264 } 265 266 if (!TAILQ_EMPTY(&pData->dns_list_head)) 267 { 268 de = TAILQ_LAST(&pData->dns_list_head, dns_list_head); 269 q_dns_header = q; 270 FILL_BOOTP_EXT(q, RFC1533_DNS, 4, &de->de_addr.s_addr); 271 } 272 273 TAILQ_FOREACH_REVERSE(de, &pData->dns_list_head, dns_list_head, de_list) 274 { 275 if (TAILQ_LAST(&pData->dns_list_head, dns_list_head) == de) 276 continue; /* first value with head we've ingected before */ 277 FILL_BOOTP_APP(q_dns_header, q, RFC1533_DNS, 4, &de->de_addr.s_addr); 278 } 279 280 skip_dns_servers: 281 if (LIST_EMPTY(&pData->dns_domain_list_head)) 282 { 283 /* Microsoft dhcp client doen't like domain-less dhcp and trimmed packets*/ 284 /* dhcpcd client very sad if no domain name is passed */ 285 FILL_BOOTP_EXT(q, RFC1533_DOMAINNAME, 1, " "); 286 } 287 if (pData->fPassDomain) 288 { 289 LIST_FOREACH(dd, &pData->dns_domain_list_head, dd_list) 290 { 291 292 if (dd->dd_pszDomain == NULL) 293 continue; 294 /* never meet valid separator here in RFC1533*/ 295 if (added != 0) 296 FILL_BOOTP_EXT(q, RFC1533_DOMAINNAME, 1, ","); 297 else 298 added = 1; 299 val = (int)strlen(dd->dd_pszDomain); 300 FILL_BOOTP_EXT(q, RFC1533_DOMAINNAME, val, dd->dd_pszDomain); 301 } 302 } 303 304 FILL_BOOTP_EXT(q, RFC2132_LEASE_TIME, 4, &lease_time); 305 306 if (*slirp_hostname) 307 { 308 val = (int)strlen(slirp_hostname); 309 FILL_BOOTP_EXT(q, RFC1533_HOSTNAME, val, slirp_hostname); 310 } 311 return q - rbp->bp_vend; /*return offset */ 312 } 313 314 static int dhcp_send_nack(PNATState pData, struct bootp_t *bp, BOOTPClient *bc, struct mbuf *m) 315 { 316 struct bootp_t *rbp; 317 uint8_t *q = NULL; 318 rbp = mtod(m, struct bootp_t *); 319 320 dhcp_create_msg(pData, bp, m, DHCPNAK); 321 322 return 7; 323 } 324 static int dhcp_send_ack(PNATState pData, struct bootp_t *bp, BOOTPClient *bc, struct mbuf *m, int is_from_request) 325 { 326 struct bootp_t *rbp; 327 int off = 0; /* boot_reply will fill general options and add END before sending response*/ 328 329 dhcp_create_msg(pData, bp, m, DHCPACK); 330 off = dhcp_do_ack_offer(pData, m, bc, is_from_request); 331 return off; 332 } 333 static int dhcp_send_offer(PNATState pData, struct bootp_t *bp, BOOTPClient *bc, struct mbuf *m) 334 { 335 struct bootp_t *rbp; 336 int off = 0; /* boot_reply will fill general options and add END before sending response*/ 337 338 dhcp_create_msg(pData, bp, m, DHCPOFFER); 339 off = dhcp_do_ack_offer(pData, m, bc, 0); 340 return off; 341 } 342 343 /** 344 * decoding client messages RFC2131 (4.3.6) 345 * --------------------------------------------------------------------- 346 * | |INIT-REBOOT |SELECTING |RENEWING |REBINDING | 347 * --------------------------------------------------------------------- 348 * |broad/unicast |broadcast |broadcast |unicast |broadcast | 349 * |server-ip |MUST NOT |MUST |MUST NOT |MUST NOT | 350 * |requested-ip |MUST |MUST |MUST NOT |MUST NOT | 351 * |ciaddr |zero |zero |IP address |IP address| 352 * --------------------------------------------------------------------- 353 * 354 */ 355 enum DHCP_REQUEST_STATES{INIT_REBOOT, SELECTING, RENEWING, REBINDING, NONE}; 356 static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, const uint8_t *buf, int size, struct mbuf *m) 357 { 358 BOOTPClient *bc; 359 struct in_addr daddr; 360 int off; 361 uint8_t *opt; 362 uint8_t *req_ip; 363 uint8_t *server_ip; 364 enum DHCP_REQUEST_STATES dhcp_stat = NONE; 365 /*need to understand which type of request we get */ 366 req_ip = dhcp_find_option(&bp->bp_vend[0], RFC2132_REQ_ADDR); 367 server_ip = dhcp_find_option(&bp->bp_vend[0], RFC2132_SRV_ID); 368 369 bc = find_addr(pData, &daddr, bp->bp_hwaddr); 370 if (!bc) 371 { 372 LogRel(("NAT: DHCP no IP address left\n")); 373 Log(("no address left\n")); 374 return -1; 375 } 376 LogRel(("NAT: flags:%x sec:%x\n", bp->flags, bp->bp_secs)); 377 if (server_ip != NULL) 378 { 379 /*selecting*/ 380 dhcp_stat = SELECTING; 381 Assert((bp->bp_ciaddr.s_addr == INADDR_ANY)); 382 Assert((*(uint32_t *)(req_ip + 2) == bc->addr.s_addr)); /*the same address as in offer*/ 383 Assert((bp->bp_xid == bc->xid)); 384 } 385 else 386 { 387 if (req_ip != NULL) 388 { 389 /* init-reboot */ 390 dhcp_stat = INIT_REBOOT; 391 } 392 else 393 { 394 if (bp->flags & DHCP_FLAGS_B) 395 dhcp_stat = RENEWING; 396 else 397 dhcp_stat = REBINDING; /*??rebinding??*/ 398 } 399 } 400 /*?? renewing ??*/ 401 if(dhcp_stat == RENEWING){ 402 Assert(( server_ip == NULL 403 && req_ip == NULL 404 && bp->bp_ciaddr.s_addr != INADDR_ANY)); 405 if (bc != NULL) 406 { 407 Assert((bc->addr.s_addr == bp->bp_ciaddr.s_addr)); 408 /*if it already here well just do ack, we aren't aware of dhcp time expiration*/ 409 } 410 else 411 { 412 if ((bp->bp_ciaddr.s_addr & pData->netmask) != special_addr.s_addr) 413 { 414 off = dhcp_send_nack(pData, bp, bc, m); 415 return off; 416 } 417 bc = alloc_addr(pData); 418 if (bc == NULL) 419 { 420 LogRel(("NAT: can't alloc address. RENEW has been silently ignored\n")); 421 return -1; 422 } 423 Assert((bp->bp_hlen == ETH_ALEN)); 424 memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen); 425 bc->addr.s_addr = bp->bp_ciaddr.s_addr; /* @todo change releasing */ 426 } 427 } 428 Assert((dhcp_stat != NONE)); 429 off = dhcp_send_ack(pData, bp, bc, m, 1);/*@todo when need send NACK */ 430 return off; 431 } 432 433 static int dhcp_decode_discover(PNATState pData, struct bootp_t *bp, const uint8_t *buf, int size, int flag, struct mbuf *m) 434 { 435 BOOTPClient *bc; 436 struct in_addr daddr; 437 int off; 438 /* flag == 1 discover */ 439 if (flag == 1) 440 { 441 bc = find_addr(pData, &daddr, bp->bp_hwaddr); 442 if (!bc) 443 { 444 bc = get_new_addr(pData, &daddr); 445 if (!bc) 446 { 447 LogRel(("NAT: DHCP no IP address left\n")); 448 Log(("no address left\n")); 449 return -1; 450 } 451 memcpy(bc->macaddr, bp->bp_hwaddr, 6); 452 } 453 bc->xid = bp->bp_xid; 454 /*bc isn't NULL */ 455 off = dhcp_send_offer(pData, bp, bc, m); 456 return off; 457 } 458 else 459 { 460 /* flag == 0 inform */ 461 bc = find_addr(pData, &daddr, bp->bp_hwaddr); 462 if (bc == NULL) 463 { 464 LogRel(("NAT: DHCP Inform was ignored no boot client was found\n")); 465 return -1; 466 } 467 off = dhcp_send_ack(pData, bp, bc, m, 0); 468 return off; 469 } 470 return -1; 471 } 472 473 static int dhcp_decode_release(PNATState pData, struct bootp_t *bp, const uint8_t *buf, int size, int flag) 474 { 475 return -1; 476 } 477 /** 478 * fields for discovering t 479 * Field DHCPDISCOVER DHCPREQUEST DHCPDECLINE, 480 * DHCPINFORM DHCPRELEASE 481 * ----- ------------ ----------- ----------- 482 * 'op' BOOTREQUEST BOOTREQUEST BOOTREQUEST 483 * 'htype' (From "Assigned Numbers" RFC) 484 * 'hlen' (Hardware address length in octets) 485 * 'hops' 0 0 0 486 * 'xid' selected by client 'xid' from server selected by 487 * DHCPOFFER message client 488 * 'secs' 0 or seconds since 0 or seconds since 0 489 * DHCP process started DHCP process started 490 * 'flags' Set 'BROADCAST' Set 'BROADCAST' 0 491 * flag if client flag if client 492 * requires broadcast requires broadcast 493 * reply reply 494 * 'ciaddr' 0 (DHCPDISCOVER) 0 or client's 0 (DHCPDECLINE) 495 * client's network address client's network 496 * network address (BOUND/RENEW/REBIND) address 497 * (DHCPINFORM) (DHCPRELEASE) 498 * 'yiaddr' 0 0 0 499 * 'siaddr' 0 0 0 500 * 'giaddr' 0 0 0 501 * 'chaddr' client's hardware client's hardware client's hardware 502 * address address address 503 * 'sname' options, if options, if (unused) 504 * indicated in indicated in 505 * 'sname/file' 'sname/file' 506 * option; otherwise option; otherwise 507 * unused unused 508 * 'file' options, if options, if (unused) 509 * indicated in indicated in 510 * 'sname/file' 'sname/file' 511 * option; otherwise option; otherwise 512 * unused unused 513 * 'options' options options (unused) 514 * Requested IP address MAY MUST (in MUST 515 * (DISCOVER) SELECTING or (DHCPDECLINE), 516 * MUST NOT INIT-REBOOT) MUST NOT 517 * (INFORM) MUST NOT (in (DHCPRELEASE) 518 * BOUND or 519 * RENEWING) 520 * IP address lease time MAY MAY MUST NOT 521 * (DISCOVER) 522 * MUST NOT 523 * (INFORM) 524 * Use 'file'/'sname' fields MAY MAY MAY 525 * DHCP message type DHCPDISCOVER/ DHCPREQUEST DHCPDECLINE/ 526 * DHCPINFORM DHCPRELEASE 527 * Client identifier MAY MAY MAY 528 * Vendor class identifier MAY MAY MUST NOT 529 * Server identifier MUST NOT MUST (after MUST 530 * SELECTING) 531 * MUST NOT (after 532 * INIT-REBOOT, 533 * BOUND, RENEWING 534 * or REBINDING) 535 * Parameter request list MAY MAY MUST NOT 536 * Maximum message size MAY MAY MUST NOT 537 * Message SHOULD NOT SHOULD NOT SHOULD 538 * Site-specific MAY MAY MUST NOT 539 * All others MAY MAY MUST NOT 540 * 541 */ 542 static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf, int size) 543 { 544 const uint8_t *p, *p_end; 545 int rc; 546 int pmsg_type; 547 struct in_addr req_ip; 548 int flag = 0; 549 int len, tag; 550 struct mbuf *m = NULL; 551 552 pmsg_type = 0; 553 554 p = buf; 555 p_end = buf + size; 556 if (size < 5) 557 return; 558 if (memcmp(p, rfc1533_cookie, 4) != 0) 559 return; 560 p = dhcp_find_option(bp->bp_vend, RFC2132_MSG_TYPE); 561 Assert(p); 562 if (p == NULL) 563 return; 564 if ((m = m_get(pData)) == NULL) 565 { 566 LogRel(("NAT: can't alocate memory for response!\n")); 567 return; 568 } 569 switch(*(p+2)) 570 { 571 case DHCPDISCOVER: 572 flag = 1; 573 /**/ 574 case DHCPINFORM: 575 rc = dhcp_decode_discover(pData, bp, buf, size, flag, m); 576 Assert(rc > 0); 577 goto reply; 578 break; 579 case DHCPREQUEST: 580 rc = dhcp_decode_request(pData, bp, buf, size, m); 581 Assert(rc > 0); 582 goto reply; 583 break; 584 case DHCPRELEASE: 585 flag = 1; 586 #if 0 587 case DHCPDECLINE: 588 #endif 589 rc = dhcp_decode_release(pData, bp, buf, size, flag); 590 Assert(rc > 0); 591 goto reply; 592 break; 593 default: 594 AssertMsgFailed(("unsupported DHCP message type")); 595 } 596 return; 597 reply: 598 Assert(m); 599 if (rc < 0) 600 { 601 /*silently ignore*/ 602 m_free(pData, m); 603 return; 604 } 605 bootp_reply(pData, m, rc, bp->flags); 606 return; 607 } 608 609 static void bootp_reply(PNATState pData, struct mbuf *m, int off, uint16_t flags) 610 { 611 #if 0 612 BOOTPClient *bc; 613 struct mbuf *m; /* XXX: @todo vasily - it'd be better to reuse this mbuf here */ 614 struct bootp_t *bp = mtod(m0, struct bootp_t *); 615 struct bootp_t *rbp; 616 struct sockaddr_in saddr, daddr; 617 int dhcp_msg_type, val; 618 uint8_t *q; 619 struct in_addr requested_ip; /* the requested IP in DHCPREQUEST */ 620 int send_nak = 0; 621 161 622 /* extract exact DHCP msg type */ 162 623 requested_ip.s_addr = 0xffffffff; 163 dhcp_decode(bp ->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type, &requested_ip);624 dhcp_decode(bp, bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type, &requested_ip); 164 625 Log(("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type)); 165 626 … … 181 642 return; 182 643 183 if ((m = m_get(pData)) == NULL)184 return;185 eh = mtod(m, struct ethhdr *);186 memcpy(eh->h_source, bp->bp_hwaddr, ETH_ALEN); /* XXX: if_encap just swap source with dest*/187 m->m_data += if_maxlinkhdr; /*reserve ether header */188 rbp = mtod(m, struct bootp_t *);189 memset(rbp, 0, sizeof(struct bootp_t));190 644 191 645 if (dhcp_msg_type == DHCPDISCOVER) 192 646 { 193 647 /* Do not allocate a new lease for clients that forgot that they had a lease. */ 194 bc = find_addr(pData, &daddr.sin_addr, bp->bp_hwaddr);195 if (!bc)196 {197 new_addr:198 bc = get_new_addr(pData, &daddr.sin_addr);199 if (!bc)200 {201 LogRel(("NAT: DHCP no IP address left\n"));202 Log(("no address left\n"));203 return;204 }205 memcpy(bc->macaddr, bp->bp_hwaddr, 6);206 }207 }208 else209 {210 bc = find_addr(pData, &daddr.sin_addr, bp->bp_hwaddr);211 if (!bc)212 {213 /* if never assigned, behaves as if it was already214 assigned (windows fix because it remembers its address) */215 goto new_addr;216 }217 }218 219 if ( tftp_prefix220 && RTDirExists(tftp_prefix)221 && bootp_filename)222 RTStrPrintf((char*)rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename);223 224 Log(("NAT: DHCP: bp_file:%s\n", &rbp->bp_file));225 /* Address/port of the DHCP server. */226 #ifndef VBOX_WITH_NAT_SERVICE227 saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);228 #else229 saddr.sin_addr.s_addr = special_addr.s_addr;230 #endif231 Log(("NAT: DHCP: s_addr:%R[IP4]\n", &saddr.sin_addr));232 233 saddr.sin_port = htons(BOOTP_SERVER);234 235 daddr.sin_port = htons(BOOTP_CLIENT);236 237 rbp->bp_op = BOOTP_REPLY;238 rbp->bp_xid = bp->bp_xid;239 rbp->bp_htype = 1;240 rbp->bp_hlen = 6;241 memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);242 243 rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */244 Log(("NAT: DHCP: bp_yiaddr:%R[IP4]\n", &rbp->bp_yiaddr));245 rbp->bp_siaddr = pData->tftp_server; /* Next Server IP address, i.e. TFTP */246 Log(("NAT: DHCP: bp_siaddr:%R[IP4]\n", &rbp->bp_siaddr));247 248 q = rbp->bp_vend;249 memcpy(q, rfc1533_cookie, 4);250 q += 4;251 252 if (dhcp_msg_type == DHCPDISCOVER)253 {254 *q++ = RFC2132_MSG_TYPE;255 *q++ = 1;256 *q++ = DHCPOFFER;257 648 } 258 649 else if (dhcp_msg_type == DHCPREQUEST) … … 285 676 ( dhcp_msg_type == DHCPDISCOVER 286 677 || dhcp_msg_type == DHCPREQUEST)) 287 { 288 struct dns_entry *de = NULL; 289 struct dns_domain_entry *dd = NULL; 290 int added = 0; 291 uint8_t *q_dns_header = NULL; 292 uint32_t lease_time = htonl(LEASE_TIME); 293 uint32_t netmask = htonl(pData->netmask); 294 295 FILL_BOOTP_EXT(q, RFC1533_NETMASK, 4, &netmask); 296 FILL_BOOTP_EXT(q, RFC1533_GATEWAY, 4, &saddr.sin_addr); 297 298 if (pData->use_dns_proxy) 299 { 300 uint32_t addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); 301 FILL_BOOTP_EXT(q, RFC1533_DNS, 4, &addr); 302 goto skip_dns_servers; 303 } 304 305 if (!TAILQ_EMPTY(&pData->dns_list_head)) 306 { 307 de = TAILQ_LAST(&pData->dns_list_head, dns_list_head); 308 q_dns_header = q; 309 FILL_BOOTP_EXT(q, RFC1533_DNS, 4, &de->de_addr.s_addr); 310 } 311 312 TAILQ_FOREACH_REVERSE(de, &pData->dns_list_head, dns_list_head, de_list) 313 { 314 if (TAILQ_LAST(&pData->dns_list_head, dns_list_head) == de) 315 continue; /* first value with head we've ingected before */ 316 FILL_BOOTP_APP(q_dns_header, q, RFC1533_DNS, 4, &de->de_addr.s_addr); 317 } 318 319 skip_dns_servers: 320 if (LIST_EMPTY(&pData->dns_domain_list_head)) 321 { 322 /* Microsoft dhcp client doen't like domain-less dhcp and trimmed packets*/ 323 /* dhcpcd client very sad if no domain name is passed */ 324 FILL_BOOTP_EXT(q, RFC1533_DOMAINNAME, 1, " "); 325 } 326 if (pData->fPassDomain) 327 { 328 LIST_FOREACH(dd, &pData->dns_domain_list_head, dd_list) 329 { 330 331 if (dd->dd_pszDomain == NULL) 332 continue; 333 /* never meet valid separator here in RFC1533*/ 334 if (added != 0) 335 FILL_BOOTP_EXT(q, RFC1533_DOMAINNAME, 1, ","); 336 else 337 added = 1; 338 val = (int)strlen(dd->dd_pszDomain); 339 FILL_BOOTP_EXT(q, RFC1533_DOMAINNAME, val, dd->dd_pszDomain); 340 } 341 } 342 343 FILL_BOOTP_EXT(q, RFC2132_LEASE_TIME, 4, &lease_time); 344 345 if (*slirp_hostname) 346 { 347 val = (int)strlen(slirp_hostname); 348 FILL_BOOTP_EXT(q, RFC1533_HOSTNAME, val, slirp_hostname); 349 } 350 } 351 *q++ = RFC1533_END; 678 #endif 679 struct sockaddr_in saddr, daddr; 680 struct bootp_t *rbp = NULL; 681 uint8_t *q = NULL; 682 int nack; 683 rbp = mtod(m, struct bootp_t *); 684 Assert((m)); 685 Assert((rbp)); 686 q = rbp->bp_vend; 687 nack = (q[6] == DHCPNAK); 688 q += off; 689 690 #ifndef VBOX_WITH_NAT_SERVICE 691 saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); 692 #else 693 saddr.sin_addr.s_addr = special_addr.s_addr; 694 #endif 695 696 FILL_BOOTP_EXT(q, RFC2132_SRV_ID, 4, &saddr.sin_addr); 697 698 699 *q++ = RFC1533_END; /*end of message */ 700 352 701 353 702 m->m_len = sizeof(struct bootp_t) … … 356 705 m->m_data += sizeof(struct udphdr) 357 706 + sizeof(struct ip); 358 /* Reply to the broadcast address, as some clients perform paranoid checks. */ 359 daddr.sin_addr.s_addr = INADDR_BROADCAST; 707 if ((flags & DHCP_FLAGS_B) || nack != 0) 708 daddr.sin_addr.s_addr = INADDR_BROADCAST; 709 else 710 daddr.sin_addr.s_addr = rbp->bp_yiaddr.s_addr; /*unicast requested by client*/ 711 saddr.sin_port = htons(BOOTP_SERVER); 712 daddr.sin_port = htons(BOOTP_CLIENT); 360 713 udp_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); 361 714 } … … 366 719 367 720 if (bp->bp_op == BOOTP_REQUEST) 368 bootp_reply(pData, m); 369 } 721 { 722 dhcp_decode(pData, bp, bp->bp_vend, DHCP_OPT_LEN); 723 } 724 } -
trunk/src/VBox/Devices/Network/slirp/bootp.h
r16214 r22101 74 74 #define DHCPNAK 6 75 75 #define DHCPRELEASE 7 76 #define DHCPINFORM 8 76 77 77 78 #define RFC1533_VENDOR_MAJOR 0 … … 103 104 uint32_t bp_xid; 104 105 uint16_t bp_secs; 105 uint16_t unused;106 uint16_t flags; 106 107 struct in_addr bp_ciaddr; 107 108 struct in_addr bp_yiaddr; … … 113 114 uint8_t bp_vend[DHCP_OPT_LEN]; 114 115 }; 115 116 #define DHCP_FLAGS_B (1<<15) 116 117 struct bootp_ext 117 118 { -
trunk/src/VBox/Devices/Network/slirp/slirp_state.h
r22024 r22101 38 38 typedef struct 39 39 { 40 uint32_t xid; 40 41 bool allocated; 41 42 uint8_t macaddr[6]; 42 43 struct in_addr addr; 44 int number; 43 45 } BOOTPClient; 44 46
Note:
See TracChangeset
for help on using the changeset viewer.