-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@733 c046a42c-6fe2-441c-8c8c-71466251a162
- Loading branch information
bellard
committed
Apr 22, 2004
1 parent
7c1f25b
commit f0cbd3e
Showing
37 changed files
with
12,057 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
/* | ||
* QEMU BOOTP/DHCP server | ||
* | ||
* Copyright (c) 2004 Fabrice Bellard | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
#include <slirp.h> | ||
|
||
/* XXX: only DHCP is supported */ | ||
|
||
#define NB_ADDR 16 | ||
|
||
#define START_ADDR 15 | ||
|
||
#define LEASE_TIME (24 * 3600) | ||
|
||
typedef struct { | ||
uint8_t allocated; | ||
} BOOTPClient; | ||
|
||
BOOTPClient bootp_clients[NB_ADDR]; | ||
|
||
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; | ||
|
||
#ifdef DEBUG | ||
#define dprintf(fmt, args...) \ | ||
if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); } | ||
#else | ||
#define dprintf(fmt, args...) | ||
#endif | ||
|
||
static BOOTPClient *get_new_addr(struct in_addr *paddr) | ||
{ | ||
BOOTPClient *bc; | ||
int i; | ||
|
||
for(i = 0; i < NB_ADDR; i++) { | ||
if (!bootp_clients[i].allocated) | ||
goto found; | ||
} | ||
return NULL; | ||
found: | ||
bc = &bootp_clients[i]; | ||
bc->allocated = 1; | ||
paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); | ||
return bc; | ||
} | ||
|
||
static void dhcp_decode(const uint8_t *buf, int size, | ||
int *pmsg_type) | ||
{ | ||
const uint8_t *p, *p_end; | ||
int len, tag; | ||
|
||
*pmsg_type = 0; | ||
|
||
p = buf; | ||
p_end = buf + size; | ||
if (size < 5) | ||
return; | ||
if (memcmp(p, rfc1533_cookie, 4) != 0) | ||
return; | ||
p += 4; | ||
while (p < p_end) { | ||
tag = p[0]; | ||
if (tag == RFC1533_PAD) { | ||
p++; | ||
} else if (tag == RFC1533_END) { | ||
break; | ||
} else { | ||
p++; | ||
if (p >= p_end) | ||
break; | ||
len = *p++; | ||
dprintf("dhcp: tag=0x%02x len=%d\n", tag, len); | ||
|
||
switch(tag) { | ||
case RFC2132_MSG_TYPE: | ||
if (len >= 1) | ||
*pmsg_type = p[0]; | ||
break; | ||
default: | ||
break; | ||
} | ||
p += len; | ||
} | ||
} | ||
} | ||
|
||
static void bootp_reply(struct bootp_t *bp) | ||
{ | ||
BOOTPClient *bc; | ||
struct mbuf *m; | ||
struct bootp_t *rbp; | ||
struct sockaddr_in saddr, daddr; | ||
struct in_addr dns_addr; | ||
int dhcp_msg_type, val; | ||
uint8_t *q; | ||
|
||
/* extract exact DHCP msg type */ | ||
dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type); | ||
dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type); | ||
|
||
if (dhcp_msg_type != DHCPDISCOVER && | ||
dhcp_msg_type != DHCPREQUEST) | ||
return; | ||
/* XXX: this is a hack to get the client mac address */ | ||
memcpy(client_ethaddr, bp->bp_hwaddr, 6); | ||
|
||
if ((m = m_get()) == NULL) | ||
return; | ||
m->m_data += if_maxlinkhdr; | ||
rbp = (struct bootp_t *)m->m_data; | ||
m->m_data += sizeof(struct udpiphdr); | ||
memset(rbp, 0, sizeof(struct bootp_t)); | ||
|
||
bc = get_new_addr(&daddr.sin_addr); | ||
if (!bc) { | ||
dprintf("no address left\n"); | ||
return; | ||
} | ||
dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr)); | ||
|
||
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); | ||
saddr.sin_port = htons(BOOTP_SERVER); | ||
|
||
daddr.sin_port = htons(BOOTP_CLIENT); | ||
|
||
rbp->bp_op = BOOTP_REPLY; | ||
rbp->bp_xid = bp->bp_xid; | ||
rbp->bp_htype = 1; | ||
rbp->bp_hlen = 6; | ||
memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6); | ||
|
||
rbp->bp_yiaddr = daddr.sin_addr; /* IP address */ | ||
|
||
q = rbp->bp_vend; | ||
memcpy(q, rfc1533_cookie, 4); | ||
q += 4; | ||
|
||
if (dhcp_msg_type == DHCPDISCOVER) { | ||
*q++ = RFC2132_MSG_TYPE; | ||
*q++ = 1; | ||
*q++ = DHCPOFFER; | ||
} else if (dhcp_msg_type == DHCPREQUEST) { | ||
*q++ = RFC2132_MSG_TYPE; | ||
*q++ = 1; | ||
*q++ = DHCPACK; | ||
} | ||
|
||
if (dhcp_msg_type == DHCPDISCOVER || | ||
dhcp_msg_type == DHCPREQUEST) { | ||
*q++ = RFC2132_SRV_ID; | ||
*q++ = 4; | ||
memcpy(q, &saddr.sin_addr, 4); | ||
q += 4; | ||
|
||
*q++ = RFC1533_NETMASK; | ||
*q++ = 4; | ||
*q++ = 0xff; | ||
*q++ = 0xff; | ||
*q++ = 0xff; | ||
*q++ = 0x00; | ||
|
||
*q++ = RFC1533_GATEWAY; | ||
*q++ = 4; | ||
memcpy(q, &saddr.sin_addr, 4); | ||
q += 4; | ||
|
||
*q++ = RFC1533_DNS; | ||
*q++ = 4; | ||
dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); | ||
memcpy(q, &dns_addr, 4); | ||
q += 4; | ||
|
||
*q++ = RFC2132_LEASE_TIME; | ||
*q++ = 4; | ||
val = htonl(LEASE_TIME); | ||
memcpy(q, &val, 4); | ||
q += 4; | ||
} | ||
*q++ = RFC1533_END; | ||
|
||
m->m_len = sizeof(struct bootp_t); | ||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); | ||
} | ||
|
||
void bootp_input(struct mbuf *m) | ||
{ | ||
struct bootp_t *bp = (struct bootp_t *)m->m_data; | ||
|
||
if (bp->bp_op == BOOTP_REQUEST) { | ||
bootp_reply(bp); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* bootp/dhcp defines */ | ||
|
||
#define BOOTP_SERVER 67 | ||
#define BOOTP_CLIENT 68 | ||
|
||
#define BOOTP_REQUEST 1 | ||
#define BOOTP_REPLY 2 | ||
|
||
#define RFC1533_COOKIE 99, 130, 83, 99 | ||
#define RFC1533_PAD 0 | ||
#define RFC1533_NETMASK 1 | ||
#define RFC1533_TIMEOFFSET 2 | ||
#define RFC1533_GATEWAY 3 | ||
#define RFC1533_TIMESERVER 4 | ||
#define RFC1533_IEN116NS 5 | ||
#define RFC1533_DNS 6 | ||
#define RFC1533_LOGSERVER 7 | ||
#define RFC1533_COOKIESERVER 8 | ||
#define RFC1533_LPRSERVER 9 | ||
#define RFC1533_IMPRESSSERVER 10 | ||
#define RFC1533_RESOURCESERVER 11 | ||
#define RFC1533_HOSTNAME 12 | ||
#define RFC1533_BOOTFILESIZE 13 | ||
#define RFC1533_MERITDUMPFILE 14 | ||
#define RFC1533_DOMAINNAME 15 | ||
#define RFC1533_SWAPSERVER 16 | ||
#define RFC1533_ROOTPATH 17 | ||
#define RFC1533_EXTENSIONPATH 18 | ||
#define RFC1533_IPFORWARDING 19 | ||
#define RFC1533_IPSOURCEROUTING 20 | ||
#define RFC1533_IPPOLICYFILTER 21 | ||
#define RFC1533_IPMAXREASSEMBLY 22 | ||
#define RFC1533_IPTTL 23 | ||
#define RFC1533_IPMTU 24 | ||
#define RFC1533_IPMTUPLATEAU 25 | ||
#define RFC1533_INTMTU 26 | ||
#define RFC1533_INTLOCALSUBNETS 27 | ||
#define RFC1533_INTBROADCAST 28 | ||
#define RFC1533_INTICMPDISCOVER 29 | ||
#define RFC1533_INTICMPRESPOND 30 | ||
#define RFC1533_INTROUTEDISCOVER 31 | ||
#define RFC1533_INTROUTESOLICIT 32 | ||
#define RFC1533_INTSTATICROUTES 33 | ||
#define RFC1533_LLTRAILERENCAP 34 | ||
#define RFC1533_LLARPCACHETMO 35 | ||
#define RFC1533_LLETHERNETENCAP 36 | ||
#define RFC1533_TCPTTL 37 | ||
#define RFC1533_TCPKEEPALIVETMO 38 | ||
#define RFC1533_TCPKEEPALIVEGB 39 | ||
#define RFC1533_NISDOMAIN 40 | ||
#define RFC1533_NISSERVER 41 | ||
#define RFC1533_NTPSERVER 42 | ||
#define RFC1533_VENDOR 43 | ||
#define RFC1533_NBNS 44 | ||
#define RFC1533_NBDD 45 | ||
#define RFC1533_NBNT 46 | ||
#define RFC1533_NBSCOPE 47 | ||
#define RFC1533_XFS 48 | ||
#define RFC1533_XDM 49 | ||
|
||
#define RFC2132_REQ_ADDR 50 | ||
#define RFC2132_LEASE_TIME 51 | ||
#define RFC2132_MSG_TYPE 53 | ||
#define RFC2132_SRV_ID 54 | ||
#define RFC2132_PARAM_LIST 55 | ||
#define RFC2132_MAX_SIZE 57 | ||
#define RFC2132_RENEWAL_TIME 58 | ||
#define RFC2132_REBIND_TIME 59 | ||
|
||
#define DHCPDISCOVER 1 | ||
#define DHCPOFFER 2 | ||
#define DHCPREQUEST 3 | ||
#define DHCPACK 5 | ||
|
||
#define RFC1533_VENDOR_MAJOR 0 | ||
#define RFC1533_VENDOR_MINOR 0 | ||
|
||
#define RFC1533_VENDOR_MAGIC 128 | ||
#define RFC1533_VENDOR_ADDPARM 129 | ||
#define RFC1533_VENDOR_ETHDEV 130 | ||
#define RFC1533_VENDOR_HOWTO 132 | ||
#define RFC1533_VENDOR_MNUOPTS 160 | ||
#define RFC1533_VENDOR_SELECTION 176 | ||
#define RFC1533_VENDOR_MOTD 184 | ||
#define RFC1533_VENDOR_NUMOFMOTD 8 | ||
#define RFC1533_VENDOR_IMG 192 | ||
#define RFC1533_VENDOR_NUMOFIMG 16 | ||
|
||
#define RFC1533_END 255 | ||
#define BOOTP_VENDOR_LEN 64 | ||
#define DHCP_OPT_LEN 312 | ||
|
||
struct bootp_t { | ||
struct ip ip; | ||
struct udphdr udp; | ||
uint8_t bp_op; | ||
uint8_t bp_htype; | ||
uint8_t bp_hlen; | ||
uint8_t bp_hops; | ||
unsigned long bp_xid; | ||
unsigned short bp_secs; | ||
unsigned short unused; | ||
struct in_addr bp_ciaddr; | ||
struct in_addr bp_yiaddr; | ||
struct in_addr bp_siaddr; | ||
struct in_addr bp_giaddr; | ||
uint8_t bp_hwaddr[16]; | ||
uint8_t bp_sname[64]; | ||
uint8_t bp_file[128]; | ||
uint8_t bp_vend[DHCP_OPT_LEN]; | ||
}; | ||
|
||
void bootp_input(struct mbuf *m); |
Oops, something went wrong.