slirp: Implement RFC2132 TFTP server name

This new usernet option can be used to add data for option 66 (tftp
server name) in the BOOTP reply, which is useful in PXE based automatic
OS install such as OpenBSD.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Tested-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
This commit is contained in:
Fam Zheng 2018-09-14 15:26:16 +08:00 committed by Samuel Thibault
parent 6e157a0339
commit 0fca92b907
8 changed files with 38 additions and 4 deletions

View File

@ -150,6 +150,7 @@ static int net_slirp_init(NetClientState *peer, const char *model,
const char *vnameserver, const char *vnameserver6,
const char *smb_export, const char *vsmbserver,
const char **dnssearch, const char *vdomainname,
const char *tftp_server_name,
Error **errp)
{
/* default settings according to historic slirp */
@ -360,6 +361,11 @@ static int net_slirp_init(NetClientState *peer, const char *model,
return -1;
}
if (tftp_server_name && strlen(tftp_server_name) > 255) {
error_setg(errp, "'tftp-server-name' parameter cannot exceed 255 bytes");
return -1;
}
nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
snprintf(nc->info_str, sizeof(nc->info_str),
@ -370,7 +376,8 @@ static int net_slirp_init(NetClientState *peer, const char *model,
s->slirp = slirp_init(restricted, ipv4, net, mask, host,
ipv6, ip6_prefix, vprefix6_len, ip6_host,
vhostname, tftp_export, bootfile, dhcp,
vhostname, tftp_server_name,
tftp_export, bootfile, dhcp,
dns, ip6_dns, dnssearch, vdomainname, s);
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
@ -907,7 +914,8 @@ int net_init_slirp(const Netdev *netdev, const char *name,
user->ipv6_host, user->hostname, user->tftp,
user->bootfile, user->dhcpstart,
user->dns, user->ipv6_dns, user->smb,
user->smbserver, dnssearch, user->domainname, errp);
user->smbserver, dnssearch, user->domainname,
user->tftp_server_name, errp);
while (slirp_configs) {
config = slirp_configs;

View File

@ -174,6 +174,8 @@
#
# @guestfwd: forward guest TCP connections
#
# @tftp-server-name: RFC2132 "TFTP server name" string (Since 3.1)
#
# Since: 1.2
##
{ 'struct': 'NetdevUserOptions',
@ -198,7 +200,8 @@
'*smb': 'str',
'*smbserver': 'str',
'*hostfwd': ['String'],
'*guestfwd': ['String'] } }
'*guestfwd': ['String'],
'*tftp-server-name': 'str' } }
##
# @NetdevTapOptions:

View File

@ -1823,7 +1823,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
" [,ipv6[=on|off]][,ipv6-net=addr[/int]][,ipv6-host=addr]\n"
" [,restrict=on|off][,hostname=host][,dhcpstart=addr]\n"
" [,dns=addr][,ipv6-dns=addr][,dnssearch=domain][,domainname=domain]\n"
" [,tftp=dir][,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
" [,tftp=dir][,tftp-server-name=name][,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
#ifndef _WIN32
"[,smb=dir[,smbserver=addr]]\n"
#endif
@ -2060,6 +2060,11 @@ server. The files in @var{dir} will be exposed as the root of a TFTP server.
The TFTP client on the guest must be configured in binary mode (use the command
@code{bin} of the Unix TFTP client).
@item tftp-server-name=@var{name}
In BOOTP reply, broadcast @var{name} as the "TFTP server name" (RFC2132 option
66). This can be used to advise the guest to load boot files or configurations
from a different server than the host address.
@item bootfile=@var{file}
When using the user mode network stack, broadcast @var{file} as the BOOTP
filename. In conjunction with @option{tftp}, this can be used to network boot

View File

@ -318,6 +318,19 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
}
}
if (slirp->tftp_server_name) {
val = strlen(slirp->tftp_server_name);
if (q + val + 2 >= end) {
g_warning("DHCP packet size exceeded, "
"omitting tftp-server-name option.");
} else {
*q++ = RFC2132_TFTP_SERVER_NAME;
*q++ = val;
memcpy(q, slirp->tftp_server_name, val);
q += val;
}
}
if (slirp->vdnssearch) {
val = slirp->vdnssearch_len;
if (q + val >= end) {

View File

@ -70,6 +70,7 @@
#define RFC2132_MAX_SIZE 57
#define RFC2132_RENEWAL_TIME 58
#define RFC2132_REBIND_TIME 59
#define RFC2132_TFTP_SERVER_NAME 66
#define DHCPDISCOVER 1
#define DHCPOFFER 2

View File

@ -13,6 +13,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
bool in6_enabled,
struct in6_addr vprefix_addr6, uint8_t vprefix_len,
struct in6_addr vhost6, const char *vhostname,
const char *tftp_server_name,
const char *tftp_path, const char *bootfile,
struct in_addr vdhcp_start, struct in_addr vnameserver,
struct in6_addr vnameserver6, const char **vdnssearch,

View File

@ -283,6 +283,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
bool in6_enabled,
struct in6_addr vprefix_addr6, uint8_t vprefix_len,
struct in6_addr vhost6, const char *vhostname,
const char *tftp_server_name,
const char *tftp_path, const char *bootfile,
struct in_addr vdhcp_start, struct in_addr vnameserver,
struct in6_addr vnameserver6, const char **vdnssearch,
@ -321,6 +322,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
slirp->vdhcp_startaddr = vdhcp_start;
slirp->vnameserver_addr = vnameserver;
slirp->vnameserver_addr6 = vnameserver6;
slirp->tftp_server_name = g_strdup(tftp_server_name);
if (vdnssearch) {
translate_dnssearch(slirp, vdnssearch);

View File

@ -212,6 +212,7 @@ struct Slirp {
/* tftp states */
char *tftp_prefix;
struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
char *tftp_server_name;
ArpTable arp_table;
NdpTable ndp_table;