int __udp_sendto(char *data, int len, struct sockaddr_in *server, struct sockaddr_in *local) { ip_route_t rt; if (__arp_lookup((ip_addr_t *)&server->sin_addr, &rt) < 0) { diag_printf("%s: Can't find address of server\n", __FUNCTION__); return -1; } else { __udp_send(data, len, &rt, ntohs(server->sin_port), ntohs(local->sin_port)); return 0; } }
// send BOOTP REQUEST or DHCP DISCOVER static void bootp_start(void) { int txSize; bootp_header_t b; // send out a BOOTP request or DHCP DISCOVER prep_bootp_request(&b); // basic BOOTP request #ifdef CYGSEM_REDBOOT_NETWORKING_DHCP debug_printf("DHCP send: DISCOVER\n"); NewDhcpState(DHCP_WAITING_FOR_OFFER); txSize = prep_dhcp_discover(&b); // make it into DHCP DISCOVER #else debug_printf("BOOTP send: REQUEST\n"); txSize = sizeof(b); #endif __udp_send((char *)&b, txSize, (ip_route_t*)&broadcast, IPPORT_BOOTPS, IPPORT_BOOTPC); }
// Handler for received BOOTP/DHCP packets static void bootp_handler(udp_socket_t *skt, char *buf, int len, ip_route_t *src_route, word src_port) { bootp_header_t *b; #ifdef CYGSEM_REDBOOT_NETWORKING_DHCP int txSize; int type; bootp_header_t txpkt; unsigned expected = 0; #endif b = (bootp_header_t *) buf; // only accept BOOTP REPLY responses if (b->bp_op != BOOTREPLY) return; // must be sent to me if (memcmp(b->bp_chaddr, __local_enet_addr, b->bp_hlen)) return; // verify XID if (b->bp_xid != xid) return; #if !defined(CYGSEM_REDBOOT_NETWORKING_DHCP) // simple BOOTP - this is all there is! debug_printf("BOOTP recv: REPLY\n"); if (dhcpState != DHCP_DONE) { save_packet(b, len); parseConfig(b, len); NewDhcpState(DHCP_DONE); } #else // DHCP support is enabled... // Check to see that it's a DHCP packet with a DHCP type field type = -1; if (!memcmp(b->bp_vend, dhcpCookie, sizeof dhcpCookie)) { unsigned char *p = b->bp_vend + 4; while (p < (unsigned char *)b + len) { if (*p == TAG_DHCP_MESS_TYPE) { type = p[2]; break; } p += p[1] + 2; } } if (type == -1) { // apparently we have a BOOTP (but not not DHCP) server debug_printf("DHCP recv: BOOTP-REPLY -- falling back to BOOTP mode\n"); if (dhcpState != DHCP_DONE) { save_packet(b, len); parseConfig(b, len); NewDhcpState(DHCP_DONE); } return; } // it's a real DHCP packet debug_printf("DHCP recv: %s [%d]\n", dhcpTypeString[type], type); switch (dhcpState) { case DHCP_WAITING_FOR_OFFER: if (type == (expected = DHCP_MESS_TYPE_OFFER)) { prep_bootp_request(&txpkt); txSize = prep_dhcp_request(&txpkt, b); debug_printf("DHCP send: REQUEST\n"); NewDhcpState(DHCP_WAITING_FOR_ACK); __udp_send((char *)&txpkt, txSize, (ip_route_t *)&broadcast, IPPORT_BOOTPS, IPPORT_BOOTPC); return; } break; case DHCP_WAITING_FOR_ACK: if (type == (expected = DHCP_MESS_TYPE_ACK)) { save_packet(b, len); parseConfig(b, len); NewDhcpState(DHCP_DONE); return; } break; default: debug_printf("DHCP packet ignored\n"); return; } if (type == DHCP_MESS_TYPE_NAK && dhcpState != DHCP_DONE) { NewDhcpState(DHCP_FAILED); return; } debug_printf("DHCP packet ignored -- expected %d[%s]\n", expected, dhcpTypeString[expected]); #endif }