slirp updates

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCgAGBQJW+bs1AAoJEOPlHOj7ay8dZd4P/1LapRGCErASZGdNWxVGxhTR
 jgM1eR7K2vjb2d4+nw5QVdI1jVnO2/hodbrIZVd0lxZtzyWzPSaa7Izc9Exl82is
 Zxqo4gvocDqNH2/9jEkruq5BtocCLTe3d2MJFqqr8kAaGD64qRATDO5ImItKKHZZ
 IDmKK4f/MpJTx1rGCcxqIjTH3eX+trrg78WH4ZMJQYS+s3+BiE1M1Wlj1xja6uji
 rSmXXOmF8VrO5VrafYXmAFnwftPLNoSRMoXYzB5MUAwQ8uHizrj6hbViUCOeo/y8
 1X9A/oOA4X0XiOWSIq/9FKGc8/tI0znCw1FN+axyyTvtqQ/NHgtDeibi6pM1IfV2
 sSsMveEX4y87UrTt+8U3ub3sSCXbkX56MUw+6xGrfSyrTgwr5QVJi9f9Ozsz2oBW
 rea4joPTXuu2TkXKMJIqF/Tsin+0eJ8wJIxIONISSi+QijyQGcxXyPsghvflTP28
 LIZJFdYeQjqm8vFpm1l3jXISrS9DoFIzRek+alJc+K4VQjONwrmuGTBxS82+oXiL
 c68YN5B48U5vO+XJNtlni7lJFtAx/ap54yWuPAvsUT4FXkaNA/gpeziVe7EXgiZ5
 oQfkOLkwNvEm7ej3ZY/Tti+3LRVFFd9yo339D5priFExccAS6V5qD547ISqsjCqY
 tq+vuAiwhfws/4kbr5Ao
 =+TFR
 -----END PGP SIGNATURE-----

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

slirp updates

# gpg: Signature made Tue 29 Mar 2016 00:16:05 BST using RSA key ID FB6B2F1D
# gpg: Good signature from "Samuel Thibault <samuel.thibault@gnu.org>"
# gpg:                 aka "Samuel Thibault <sthibault@debian.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: 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: F632 74CD C630 0873 CB3D  29D9 E3E5 1CE8 FB6B 2F1D

* remotes/thibault/tags/samuel-thibault:
  Rework ipv6 options
  Use C99 flexible array instead of 1-byte trailing array
  Avoid embedding struct mbuf in other structures
  slirp: send icmp6 errors when UDP send failed
  slirp: Fix memory leak on small incoming ipv4 packet

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-03-29 18:25:27 +01:00
commit 5b8e6b4cc2
11 changed files with 67 additions and 57 deletions

View File

@ -829,10 +829,10 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
net_init_slirp_configs(user->guestfwd, 0); net_init_slirp_configs(user->guestfwd, 0);
ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet, ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet,
user->host, user->ip6_prefix, user->ip6_prefixlen, user->host, user->ipv6_prefix, user->ipv6_prefixlen,
user->ip6_host, user->hostname, user->tftp, user->ipv6_host, user->hostname, user->tftp,
user->bootfile, user->dhcpstart, user->bootfile, user->dhcpstart,
user->dns, user->ip6_dns, user->smb, user->dns, user->ipv6_dns, user->smb,
user->smbserver, dnssearch); user->smbserver, dnssearch);
while (slirp_configs) { while (slirp_configs) {

View File

@ -2427,7 +2427,10 @@
# #
# @ip: #optional legacy parameter, use net= instead # @ip: #optional legacy parameter, use net= instead
# #
# @net: #optional IP address and optional netmask # @net: #optional IP network address that the guest will see, in the
# form addr[/netmask] The netmask is optional, and can be
# either in the form a.b.c.d or as a number of valid top-most
# bits. Default is 10.0.2.0/24.
# #
# @host: #optional guest-visible address of the host # @host: #optional guest-visible address of the host
# #
@ -2443,13 +2446,17 @@
# @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option
# to the guest # to the guest
# #
# @ip6-prefix: #optional IPv6 network prefix (default is fec0::) (since 2.6) # @ipv6-prefix: #optional IPv6 network prefix (default is fec0::) (since
# 2.6). The network prefix is given in the usual
# hexadecimal IPv6 address notation.
# #
# @ip6-prefixlen: #optional IPv6 network prefix length (default is 64) (since 2.6) # @ipv6-prefixlen: #optional IPv6 network prefix length (default is 64)
# (since 2.6)
# #
# @ip6-host: #optional guest-visible IPv6 address of the host (since 2.6) # @ipv6-host: #optional guest-visible IPv6 address of the host (since 2.6)
# #
# @ip6-dns: #optional guest-visible IPv6 address of the virtual nameserver (since 2.6) # @ipv6-dns: #optional guest-visible IPv6 address of the virtual
# nameserver (since 2.6)
# #
# @smb: #optional root directory of the built-in SMB server # @smb: #optional root directory of the built-in SMB server
# #
@ -2474,10 +2481,10 @@
'*dhcpstart': 'str', '*dhcpstart': 'str',
'*dns': 'str', '*dns': 'str',
'*dnssearch': ['String'], '*dnssearch': ['String'],
'*ip6-prefix': 'str', '*ipv6-prefix': 'str',
'*ip6-prefixlen': 'int', '*ipv6-prefixlen': 'int',
'*ip6-host': 'str', '*ipv6-host': 'str',
'*ip6-dns': 'str', '*ipv6-dns': 'str',
'*smb': 'str', '*smb': 'str',
'*smbserver': 'str', '*smbserver': 'str',
'*hostfwd': ['String'], '*hostfwd': ['String'],

View File

@ -1551,9 +1551,9 @@ DEF("smb", HAS_ARG, QEMU_OPTION_smb, "", QEMU_ARCH_ALL)
DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
#ifdef CONFIG_SLIRP #ifdef CONFIG_SLIRP
"-netdev user,id=str[,net=addr[/mask]][,host=addr][,ip6-net=addr[/int]]\n" "-netdev user,id=str[,net=addr[/mask]][,host=addr][,ipv6-net=addr[/int]]\n"
" [,ip6-host=addr][,restrict=on|off][,hostname=host][,dhcpstart=addr]\n" " [,ipv6-host=addr][,restrict=on|off][,hostname=host][,dhcpstart=addr]\n"
" [,dns=addr][,ip6-dns=addr][,dnssearch=domain][,tftp=dir]\n" " [,dns=addr][,ipv6-dns=addr][,dnssearch=domain][,tftp=dir]\n"
" [,bootfile=f][,hostfwd=rule][,guestfwd=rule]" " [,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
#ifndef _WIN32 #ifndef _WIN32
"[,smb=dir[,smbserver=addr]]\n" "[,smb=dir[,smbserver=addr]]\n"
@ -1710,11 +1710,13 @@ either in the form a.b.c.d or as number of valid top-most bits. Default is
Specify the guest-visible address of the host. Default is the 2nd IP in the Specify the guest-visible address of the host. Default is the 2nd IP in the
guest network, i.e. x.x.x.2. guest network, i.e. x.x.x.2.
@item ip6-net=@var{addr}[/@var{int}] @item ipv6-net=@var{addr}[/@var{int}]
Set IPv6 network address the guest will see. Optionally specify the prefix Set IPv6 network address the guest will see (default is fec0::/64). The
size, as number of valid top-most bits. Default is fec0::/64. network prefix is given in the usual hexadecimal IPv6 address
notation. The prefix size is optional, and is given as the number of
valid top-most bits (default is 64).
@item ip6-host=@var{addr} @item ipv6-host=@var{addr}
Specify the guest-visible IPv6 address of the host. Default is the 2nd IPv6 in Specify the guest-visible IPv6 address of the host. Default is the 2nd IPv6 in
the guest network, i.e. xxxx::2. the guest network, i.e. xxxx::2.
@ -1735,7 +1737,7 @@ Specify the guest-visible address of the virtual nameserver. The address must
be different from the host address. Default is the 3rd IP in the guest network, be different from the host address. Default is the 3rd IP in the guest network,
i.e. x.x.x.3. i.e. x.x.x.3.
@item ip6-dns=@var{addr} @item ipv6-dns=@var{addr}
Specify the guest-visible address of the IPv6 virtual nameserver. The address Specify the guest-visible address of the IPv6 virtual nameserver. The address
must be different from the host address. Default is the 3rd IP in the guest must be different from the host address. Default is the 3rd IP in the guest
network, i.e. xxxx::3. network, i.e. xxxx::3.

View File

@ -28,9 +28,9 @@ ifs_remque(struct mbuf *ifm)
void void
if_init(Slirp *slirp) if_init(Slirp *slirp)
{ {
slirp->if_fastq.ifq_next = slirp->if_fastq.ifq_prev = &slirp->if_fastq; slirp->if_fastq.qh_link = slirp->if_fastq.qh_rlink = &slirp->if_fastq;
slirp->if_batchq.ifq_next = slirp->if_batchq.ifq_prev = &slirp->if_batchq; slirp->if_batchq.qh_link = slirp->if_batchq.qh_rlink = &slirp->if_batchq;
slirp->next_m = &slirp->if_batchq; slirp->next_m = (struct mbuf *) &slirp->if_batchq;
} }
/* /*
@ -74,7 +74,8 @@ if_output(struct socket *so, struct mbuf *ifm)
* We mustn't put this packet back on the fastq (or we'll send it out of order) * We mustn't put this packet back on the fastq (or we'll send it out of order)
* XXX add cache here? * XXX add cache here?
*/ */
for (ifq = slirp->if_batchq.ifq_prev; ifq != &slirp->if_batchq; for (ifq = (struct mbuf *) slirp->if_batchq.qh_rlink;
(struct quehead *) ifq != &slirp->if_batchq;
ifq = ifq->ifq_prev) { ifq = ifq->ifq_prev) {
if (so == ifq->ifq_so) { if (so == ifq->ifq_so) {
/* A match! */ /* A match! */
@ -86,7 +87,7 @@ if_output(struct socket *so, struct mbuf *ifm)
/* No match, check which queue to put it on */ /* No match, check which queue to put it on */
if (so && (so->so_iptos & IPTOS_LOWDELAY)) { if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
ifq = slirp->if_fastq.ifq_prev; ifq = (struct mbuf *) slirp->if_fastq.qh_rlink;
on_fastq = 1; on_fastq = 1;
/* /*
* Check if this packet is a part of the last * Check if this packet is a part of the last
@ -98,9 +99,9 @@ if_output(struct socket *so, struct mbuf *ifm)
goto diddit; goto diddit;
} }
} else { } else {
ifq = slirp->if_batchq.ifq_prev; ifq = (struct mbuf *) slirp->if_batchq.qh_rlink;
/* Set next_m if the queue was empty so far */ /* Set next_m if the queue was empty so far */
if (slirp->next_m == &slirp->if_batchq) { if ((struct quehead *) slirp->next_m == &slirp->if_batchq) {
slirp->next_m = ifm; slirp->next_m = ifm;
} }
} }
@ -166,10 +167,10 @@ void if_start(Slirp *slirp)
} }
slirp->if_start_busy = true; slirp->if_start_busy = true;
if (slirp->if_fastq.ifq_next != &slirp->if_fastq) { if (slirp->if_fastq.qh_link != &slirp->if_fastq) {
ifm_next = slirp->if_fastq.ifq_next; ifm_next = (struct mbuf *) slirp->if_fastq.qh_link;
next_from_batchq = false; next_from_batchq = false;
} else if (slirp->next_m != &slirp->if_batchq) { } else if ((struct quehead *) slirp->next_m != &slirp->if_batchq) {
/* Nothing on fastq, pick up from batchq via next_m */ /* Nothing on fastq, pick up from batchq via next_m */
ifm_next = slirp->next_m; ifm_next = slirp->next_m;
next_from_batchq = true; next_from_batchq = true;
@ -182,12 +183,12 @@ void if_start(Slirp *slirp)
from_batchq = next_from_batchq; from_batchq = next_from_batchq;
ifm_next = ifm->ifq_next; ifm_next = ifm->ifq_next;
if (ifm_next == &slirp->if_fastq) { if ((struct quehead *) ifm_next == &slirp->if_fastq) {
/* No more packets in fastq, switch to batchq */ /* No more packets in fastq, switch to batchq */
ifm_next = slirp->next_m; ifm_next = slirp->next_m;
next_from_batchq = true; next_from_batchq = true;
} }
if (ifm_next == &slirp->if_batchq) { if ((struct quehead *) ifm_next == &slirp->if_batchq) {
/* end of batchq */ /* end of batchq */
ifm_next = NULL; ifm_next = NULL;
} }
@ -218,7 +219,7 @@ void if_start(Slirp *slirp)
/* Next packet in fastq is from the same session */ /* Next packet in fastq is from the same session */
ifm_next = next; ifm_next = next;
next_from_batchq = false; next_from_batchq = false;
} else if (slirp->next_m == &slirp->if_batchq) { } else if ((struct quehead *) slirp->next_m == &slirp->if_batchq) {
/* Set next_m and ifm_next if the session packet is now the /* Set next_m and ifm_next if the session packet is now the
* only one on batchq */ * only one on batchq */
slirp->next_m = ifm_next = next; slirp->next_m = ifm_next = next;

View File

@ -85,7 +85,7 @@ ip_input(struct mbuf *m)
DEBUG_ARG("m_len = %d", m->m_len); DEBUG_ARG("m_len = %d", m->m_len);
if (m->m_len < sizeof (struct ip)) { if (m->m_len < sizeof (struct ip)) {
return; goto bad;
} }
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);

View File

@ -29,16 +29,16 @@
void void
m_init(Slirp *slirp) m_init(Slirp *slirp)
{ {
slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist; slirp->m_freelist.qh_link = slirp->m_freelist.qh_rlink = &slirp->m_freelist;
slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist; slirp->m_usedlist.qh_link = slirp->m_usedlist.qh_rlink = &slirp->m_usedlist;
} }
void m_cleanup(Slirp *slirp) void m_cleanup(Slirp *slirp)
{ {
struct mbuf *m, *next; struct mbuf *m, *next;
m = slirp->m_usedlist.m_next; m = (struct mbuf *) slirp->m_usedlist.qh_link;
while (m != &slirp->m_usedlist) { while ((struct quehead *) m != &slirp->m_usedlist) {
next = m->m_next; next = m->m_next;
if (m->m_flags & M_EXT) { if (m->m_flags & M_EXT) {
free(m->m_ext); free(m->m_ext);
@ -46,8 +46,8 @@ void m_cleanup(Slirp *slirp)
free(m); free(m);
m = next; m = next;
} }
m = slirp->m_freelist.m_next; m = (struct mbuf *) slirp->m_freelist.qh_link;
while (m != &slirp->m_freelist) { while ((struct quehead *) m != &slirp->m_freelist) {
next = m->m_next; next = m->m_next;
free(m); free(m);
m = next; m = next;
@ -70,7 +70,7 @@ m_get(Slirp *slirp)
DEBUG_CALL("m_get"); DEBUG_CALL("m_get");
if (slirp->m_freelist.m_next == &slirp->m_freelist) { if (slirp->m_freelist.qh_link == &slirp->m_freelist) {
m = (struct mbuf *)malloc(SLIRP_MSIZE); m = (struct mbuf *)malloc(SLIRP_MSIZE);
if (m == NULL) goto end_error; if (m == NULL) goto end_error;
slirp->mbuf_alloced++; slirp->mbuf_alloced++;
@ -78,7 +78,7 @@ m_get(Slirp *slirp)
flags = M_DOFREE; flags = M_DOFREE;
m->slirp = slirp; m->slirp = slirp;
} else { } else {
m = slirp->m_freelist.m_next; m = (struct mbuf *) slirp->m_freelist.qh_link;
remque(m); remque(m);
} }
@ -225,7 +225,8 @@ dtom(Slirp *slirp, void *dat)
DEBUG_ARG("dat = %p", dat); DEBUG_ARG("dat = %p", dat);
/* bug corrected for M_EXT buffers */ /* bug corrected for M_EXT buffers */
for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist; for (m = (struct mbuf *) slirp->m_usedlist.qh_link;
(struct quehead *) m != &slirp->m_usedlist;
m = m->m_next) { m = m->m_next) {
if (m->m_flags & M_EXT) { if (m->m_flags & M_EXT) {
if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )

View File

@ -81,11 +81,9 @@ struct mbuf {
Slirp *slirp; Slirp *slirp;
bool resolution_requested; bool resolution_requested;
uint64_t expiration_date; uint64_t expiration_date;
char *m_ext;
/* start of dynamic buffer area, must be last element */ /* start of dynamic buffer area, must be last element */
union { char m_dat[];
char m_dat[1]; /* ANSI don't like 0 sized arrays */
char *m_ext;
};
}; };
#define ifq_prev m_prev #define ifq_prev m_prev

View File

@ -17,11 +17,6 @@
int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR; int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
#endif #endif
struct quehead {
struct quehead *qh_link;
struct quehead *qh_rlink;
};
inline void inline void
insque(void *a, void *b) insque(void *a, void *b)
{ {

View File

@ -45,6 +45,11 @@ struct emu_t {
struct emu_t *next; struct emu_t *next;
}; };
struct slirp_quehead {
struct slirp_quehead *qh_link;
struct slirp_quehead *qh_rlink;
};
void slirp_insque(void *, void *); void slirp_insque(void *, void *);
void slirp_remque(void *); void slirp_remque(void *);
int add_exec(struct ex_list **, int, char *, struct in_addr, int); int add_exec(struct ex_list **, int, char *, struct in_addr, int);

View File

@ -82,6 +82,7 @@ void free(void *ptr);
have different prototypes. */ have different prototypes. */
#define insque slirp_insque #define insque slirp_insque
#define remque slirp_remque #define remque slirp_remque
#define quehead slirp_quehead
#ifdef HAVE_SYS_STROPTS_H #ifdef HAVE_SYS_STROPTS_H
#include <sys/stropts.h> #include <sys/stropts.h>
@ -197,12 +198,13 @@ struct Slirp {
struct ex_list *exec_list; struct ex_list *exec_list;
/* mbuf states */ /* mbuf states */
struct mbuf m_freelist, m_usedlist; struct quehead m_freelist;
struct quehead m_usedlist;
int mbuf_alloced; int mbuf_alloced;
/* if states */ /* if states */
struct mbuf if_fastq; /* fast queue (for interactive data) */ struct quehead if_fastq; /* fast queue (for interactive data) */
struct mbuf if_batchq; /* queue for non-interactive data */ struct quehead if_batchq; /* queue for non-interactive data */
struct mbuf *next_m; /* pointer to next mbuf to output */ struct mbuf *next_m; /* pointer to next mbuf to output */
bool if_start_busy; /* avoid if_start recursion */ bool if_start_busy; /* avoid if_start recursion */

View File

@ -113,8 +113,7 @@ void udp6_input(struct mbuf *m)
m->m_data -= iphlen; m->m_data -= iphlen;
*ip = save_ip; *ip = save_ip;
DEBUG_MISC((dfd, "udp tx errno = %d-%s\n", errno, strerror(errno))); DEBUG_MISC((dfd, "udp tx errno = %d-%s\n", errno, strerror(errno)));
/* TODO: ICMPv6 error */ icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
/*icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));*/
goto bad; goto bad;
} }