Fam Zheng (2):

slirp: Add sanity check for str option length
   slirp: Implement RFC2132 TFTP server name
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEM/p7ZGGVAfjOnI+X4/ZanpVg20wFAlvM054ACgkQ4/ZanpVg
 20zDghAA251oTzggsGn3VOXE6SCSFdFcyvZNtJE7ytDN/4hKlTonorpJcK0sQGtR
 FV1t7TTLHzNESNpbpyMKOw685BXQ6HTDgaeriyA1Iz5I23/CNdE1aG9go4MumEtO
 HSNrnschjbnzjmxed1OEQ/EiEGMWQpuQR6I0d5jOTArJfTgm8dm5ggUjvIDQMoNF
 7mEaxvdqxtxaXO9/7v6elrfYN7pLs/d6Zk4nJ44jo2BqCizrBkX+IRqnSHq55Zhp
 WeZeEC9DeQfzo2AzFjSiHiYFdxT7aQCEw8IHSl+rS1VFzigeL7DTqUkqSoA64pKv
 /jo9Eiy08wk3Ipz8WEAbchwK7WJpEOIlt/8o7Svl0arC6aiN1c/uRER1OjEn9j1L
 K4kKMOh6whwKh3dKuv7oYfG1pJcUrl/OnVFcCZOhr7DGYPjObk3yS7Ykr0wx8Qib
 aOn4THlfgC+yYFsjulKKGMZvfK8qxxI7vrTRoPEnUP0HgMPYjkvx0gs5QJe4b+Dz
 a6dBa4aqEaGw8297nE/pNV0wVVSzTaKg0dTK3DmceGY0dhHavMMROWg5zfNbnJ+Y
 r3mXjirhQwKWup72A42njZ2Mnt+KHjLzbOta25ItOatxlxN16jODslNPxdbcmKHh
 fsWUwBBmqoK4ecuO7isuRyLi0sgbTQX4qSx3iv0EfdZAQRbCbuo=
 =h1hQ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging

Fam Zheng (2):
  slirp: Add sanity check for str option length
  slirp: Implement RFC2132 TFTP server name

# gpg: Signature made Sun 21 Oct 2018 20:29:34 BST
# gpg:                using RSA key E3F65A9E9560DB4C
# gpg: Good signature from "Samuel Thibault <samuel.thibault@aquilenet.fr>"
# gpg:                 aka "Samuel Thibault <sthibault@debian.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@gnu.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@inria.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@labri.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@ens-lyon.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 900C B024 B679 31D4 0F82  304B D017 8C76 7D06 9EE6
#      Subkey fingerprint: 33FA 7B64 6195 01F8 CE9C  8F97 E3F6 5A9E 9560 DB4C

* remotes/thibault/tags/samuel-thibault:
  slirp: Implement RFC2132 TFTP server name
  slirp: Add sanity check for str option length

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-10-23 16:05:00 +01:00
commit 9b29b44e8e
8 changed files with 69 additions and 14 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 *vnameserver, const char *vnameserver6,
const char *smb_export, const char *vsmbserver, const char *smb_export, const char *vsmbserver,
const char **dnssearch, const char *vdomainname, const char **dnssearch, const char *vdomainname,
const char *tftp_server_name,
Error **errp) Error **errp)
{ {
/* default settings according to historic slirp */ /* default settings according to historic slirp */
@ -350,6 +351,20 @@ static int net_slirp_init(NetClientState *peer, const char *model,
return -1; return -1;
} }
if (vdomainname && strlen(vdomainname) > 255) {
error_setg(errp, "'domainname' parameter cannot exceed 255 bytes");
return -1;
}
if (vhostname && strlen(vhostname) > 255) {
error_setg(errp, "'vhostname' parameter cannot exceed 255 bytes");
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); nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
@ -361,7 +376,8 @@ static int net_slirp_init(NetClientState *peer, const char *model,
s->slirp = slirp_init(restricted, ipv4, net, mask, host, s->slirp = slirp_init(restricted, ipv4, net, mask, host,
ipv6, ip6_prefix, vprefix6_len, ip6_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); dns, ip6_dns, dnssearch, vdomainname, s);
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
@ -898,7 +914,8 @@ int net_init_slirp(const Netdev *netdev, const char *name,
user->ipv6_host, user->hostname, user->tftp, user->ipv6_host, user->hostname, user->tftp,
user->bootfile, user->dhcpstart, user->bootfile, user->dhcpstart,
user->dns, user->ipv6_dns, user->smb, 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) { while (slirp_configs) {
config = slirp_configs; config = slirp_configs;

View File

@ -174,6 +174,8 @@
# #
# @guestfwd: forward guest TCP connections # @guestfwd: forward guest TCP connections
# #
# @tftp-server-name: RFC2132 "TFTP server name" string (Since 3.1)
#
# Since: 1.2 # Since: 1.2
## ##
{ 'struct': 'NetdevUserOptions', { 'struct': 'NetdevUserOptions',
@ -198,7 +200,8 @@
'*smb': 'str', '*smb': 'str',
'*smbserver': 'str', '*smbserver': 'str',
'*hostfwd': ['String'], '*hostfwd': ['String'],
'*guestfwd': ['String'] } } '*guestfwd': ['String'],
'*tftp-server-name': 'str' } }
## ##
# @NetdevTapOptions: # @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" " [,ipv6[=on|off]][,ipv6-net=addr[/int]][,ipv6-host=addr]\n"
" [,restrict=on|off][,hostname=host][,dhcpstart=addr]\n" " [,restrict=on|off][,hostname=host][,dhcpstart=addr]\n"
" [,dns=addr][,ipv6-dns=addr][,dnssearch=domain][,domainname=domain]\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 #ifndef _WIN32
"[,smb=dir[,smbserver=addr]]\n" "[,smb=dir[,smbserver=addr]]\n"
#endif #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 The TFTP client on the guest must be configured in binary mode (use the command
@code{bin} of the Unix TFTP client). @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} @item bootfile=@var{file}
When using the user mode network stack, broadcast @var{file} as the BOOTP 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 filename. In conjunction with @option{tftp}, this can be used to network boot

View File

@ -159,6 +159,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
struct in_addr preq_addr; struct in_addr preq_addr;
int dhcp_msg_type, val; int dhcp_msg_type, val;
uint8_t *q; uint8_t *q;
uint8_t *end;
uint8_t client_ethaddr[ETH_ALEN]; uint8_t client_ethaddr[ETH_ALEN];
/* extract exact DHCP msg type */ /* extract exact DHCP msg type */
@ -240,6 +241,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
q = rbp->bp_vend; q = rbp->bp_vend;
end = (uint8_t *)&rbp[1];
memcpy(q, rfc1533_cookie, 4); memcpy(q, rfc1533_cookie, 4);
q += 4; q += 4;
@ -292,24 +294,46 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
if (*slirp->client_hostname) { if (*slirp->client_hostname) {
val = strlen(slirp->client_hostname); val = strlen(slirp->client_hostname);
*q++ = RFC1533_HOSTNAME; if (q + val + 2 >= end) {
*q++ = val; g_warning("DHCP packet size exceeded, "
memcpy(q, slirp->client_hostname, val); "omitting host name option.");
q += val; } else {
*q++ = RFC1533_HOSTNAME;
*q++ = val;
memcpy(q, slirp->client_hostname, val);
q += val;
}
} }
if (slirp->vdomainname) { if (slirp->vdomainname) {
val = strlen(slirp->vdomainname); val = strlen(slirp->vdomainname);
*q++ = RFC1533_DOMAINNAME; if (q + val + 2 >= end) {
*q++ = val; g_warning("DHCP packet size exceeded, "
memcpy(q, slirp->vdomainname, val); "omitting domain name option.");
q += val; } else {
*q++ = RFC1533_DOMAINNAME;
*q++ = val;
memcpy(q, slirp->vdomainname, val);
q += val;
}
}
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) { if (slirp->vdnssearch) {
size_t spaceleft = sizeof(rbp->bp_vend) - (q - rbp->bp_vend);
val = slirp->vdnssearch_len; val = slirp->vdnssearch_len;
if (val + 1 > spaceleft) { if (q + val >= end) {
g_warning("DHCP packet size exceeded, " g_warning("DHCP packet size exceeded, "
"omitting domain-search option."); "omitting domain-search option.");
} else { } else {
@ -331,6 +355,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
memcpy(q, nak_msg, sizeof(nak_msg) - 1); memcpy(q, nak_msg, sizeof(nak_msg) - 1);
q += sizeof(nak_msg) - 1; q += sizeof(nak_msg) - 1;
} }
assert(q < end);
*q = RFC1533_END; *q = RFC1533_END;
daddr.sin_addr.s_addr = 0xffffffffu; daddr.sin_addr.s_addr = 0xffffffffu;

View File

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

View File

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

View File

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