18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU BOOTP/DHCP server 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2004 Fabrice Bellard 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions: 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software. 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE. 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "helper.h" 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: only DHCP is supported */ 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NB_ADDR 16 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define START_ADDR 15 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define LEASE_TIME (24 * 3600) 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct { 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t allocated; 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t macaddr[6]; 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} BOOTPClient; 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BOOTPClient bootp_clients[NB_ADDR]; 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char *bootp_filename; 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define dprintf(fmt, ...) \ 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerif (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## __VA_ARGS__); fflush(dfd); } 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define dprintf(fmt, ...) 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BOOTPClient *get_new_addr(SockAddress* paddr, 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const uint8_t *macaddr) 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BOOTPClient *bc; 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i = 0; i < NB_ADDR; i++) { 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bc = &bootp_clients[i]; 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto found; 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project found: 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bc = &bootp_clients[i]; 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bc->allocated = 1; 68d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine sock_address_init_inet( paddr, 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project special_addr_ip | (i+START_ADDR), 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BOOTP_CLIENT ); 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return bc; 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BOOTPClient *request_addr(const ipaddr_t *paddr, 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const uint8_t *macaddr) 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t req_addr = ip_geth(*paddr); 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t spec_addr = special_addr_ip; 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner BOOTPClient *bc; 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (req_addr >= (spec_addr | START_ADDR) && 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req_addr < (spec_addr | (NB_ADDR + START_ADDR))) { 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bc = &bootp_clients[(req_addr & 0xff) - START_ADDR]; 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) { 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bc->allocated = 1; 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return bc; 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BOOTPClient *find_addr(SockAddress *paddr, const uint8_t *macaddr) 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BOOTPClient *bc; 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i = 0; i < NB_ADDR; i++) { 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!memcmp(macaddr, bootp_clients[i].macaddr, 6)) 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto found; 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project found: 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bc = &bootp_clients[i]; 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bc->allocated = 1; 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sock_address_init_inet( paddr, 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project special_addr_ip | (i + START_ADDR), 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BOOTP_CLIENT ); 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return bc; 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const ipaddr_t **preq_addr) 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const uint8_t *p, *p_end; 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int len, tag; 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *pmsg_type = 0; 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *preq_addr = NULL; 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p = bp->bp_vend; 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p_end = p + DHCP_OPT_LEN; 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (memcmp(p, rfc1533_cookie, 4) != 0) 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p += 4; 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (p < p_end) { 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tag = p[0]; 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tag == RFC1533_PAD) { 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p++; 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (tag == RFC1533_END) { 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p++; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (p >= p_end) 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = *p++; 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("dhcp: tag=%d len=%d\n", tag, len); 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(tag) { 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case RFC2132_MSG_TYPE: 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len >= 1) 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *pmsg_type = p[0]; 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case RFC2132_REQ_ADDR: 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len >= 4) 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *preq_addr = (const ipaddr_t *)p; 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project p += len; 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr) { 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *preq_addr = (const ipaddr_t*)&bp->bp_ciaddr; 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bootp_reply(const struct bootp_t *bp) 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner BOOTPClient *bc = NULL; 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *m; 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct bootp_t *rbp; 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SockAddress saddr, daddr; 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t dns_addr; 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const ipaddr_t *preq_addr; 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int dhcp_msg_type, val; 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint8_t *q; 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* extract exact DHCP msg type */ 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dhcp_decode(bp, &dhcp_msg_type, &preq_addr); 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type); 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (preq_addr) { 173d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine dprintf(" req_addr=%08x\n", ntohl(*(uint32_t*)preq_addr)); 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("\n"); 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dhcp_msg_type == 0) 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dhcp_msg_type != DHCPDISCOVER && 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dhcp_msg_type != DHCPREQUEST) 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX: this is a hack to get the client mac address */ 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(client_ethaddr, bp->bp_hwaddr, 6); 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((m = m_get()) == NULL) 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data += IF_MAXLINKHDR; 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rbp = (struct bootp_t *)m->m_data; 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data += sizeof(struct udpiphdr); 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(rbp, 0, sizeof(struct bootp_t)); 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dhcp_msg_type == DHCPDISCOVER) { 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (preq_addr) { 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bc = request_addr(preq_addr, client_ethaddr); 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bc) { 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_init_inet(&daddr, ip_geth(*preq_addr), BOOTP_CLIENT); 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!bc) { 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner new_addr: 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bc = get_new_addr(&daddr, client_ethaddr); 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!bc) { 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("no address left\n"); 2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(bc->macaddr, client_ethaddr, 6); 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (preq_addr) { 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bc = request_addr(preq_addr, client_ethaddr); 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bc) { 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_init_inet(&daddr, ip_geth(*preq_addr), BOOTP_CLIENT); 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(bc->macaddr, client_ethaddr, 6); 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_init_inet(&daddr, 0, BOOTP_CLIENT); 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bc = find_addr(&daddr, bp->bp_hwaddr); 2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!bc) { 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if never assigned, behaves as if it was already 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project assigned (windows fix because it remembers its address) */ 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto new_addr; 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sock_address_init_inet( &saddr, special_addr_ip | CTL_ALIAS, 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BOOTP_SERVER ); 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rbp->bp_op = BOOTP_REPLY; 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rbp->bp_xid = bp->bp_xid; 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rbp->bp_htype = 1; 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rbp->bp_hlen = 6; 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6); 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rbp->bp_yiaddr = htonl(sock_address_get_ip(&daddr)); /* Client IP address */ 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rbp->bp_siaddr = htonl(sock_address_get_ip(&saddr)); /* Server IP address */ 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = rbp->bp_vend; 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(q, rfc1533_cookie, 4); 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q += 4; 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bc) { 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t saddr_ip = htonl(sock_address_get_ip(&saddr)); 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("%s addr=%08x\n", 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (dhcp_msg_type == DHCPDISCOVER) ? "offered" : "ack'ed", 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_get_ip(&daddr)); 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dhcp_msg_type == DHCPDISCOVER) { 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = RFC2132_MSG_TYPE; 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = 1; 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = DHCPOFFER; 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else /* DHCPREQUEST */ { 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = RFC2132_MSG_TYPE; 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = 1; 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = DHCPACK; 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bootp_filename) 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s", 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bootp_filename); 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = RFC2132_SRV_ID; 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = 4; 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(q, &saddr_ip, 4); 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q += 4; 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = RFC1533_NETMASK; 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = 4; 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = 0xff; 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = 0xff; 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = 0xff; 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = 0x00; 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!slirp_restrict) { 2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = RFC1533_GATEWAY; 2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = 4; 2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(q, &saddr_ip, 4); 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q += 4; 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = RFC1533_DNS; 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = 4; 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dns_addr = htonl(special_addr_ip | CTL_DNS); 2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(q, &dns_addr, 4); 2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q += 4; 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = RFC2132_LEASE_TIME; 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = 4; 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = htonl(LEASE_TIME); 2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(q, &val, 4); 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q += 4; 2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (*slirp_hostname) { 2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = strlen(slirp_hostname); 2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = RFC1533_HOSTNAME; 2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = val; 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(q, slirp_hostname, val); 2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q += val; 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char nak_msg[] = "requested address not available"; 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("nak'ed addr=%08x\n", ip_geth(*preq_addr)); 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = RFC2132_MSG_TYPE; 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = 1; 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = DHCPNAK; 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = RFC2132_MESSAGE; 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = sizeof(nak_msg) - 1; 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(q, nak_msg, sizeof(nak_msg) - 1); 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q += sizeof(nak_msg) - 1; 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *q++ = RFC1533_END; 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_init_inet(&daddr, 0xffffffffu, BOOTP_CLIENT); 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len = sizeof(struct bootp_t) - 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sizeof(struct ip) - sizeof(struct udphdr); 3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_output2_(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bootp_input(struct mbuf *m) 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct bootp_t *bp = mtod(m, struct bootp_t *); 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (bp->bp_op == BOOTP_REQUEST) { 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bootp_reply(bp); 3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 331