Message ID | 20181121220647.18844-30-marcandre.lureau@redhat.com |
---|---|
State | New |
Headers | show |
Series | slirp: make it again a standalone project | expand |
Hi On Thu, Nov 22, 2018 at 2:38 AM Marc-André Lureau <marcandre.lureau@redhat.com> wrote: > > Introduce utility header/object, and replace remaining qemu functions > with SLIRP helpers. > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> self-nack, not only this patch deserves to be split, but it also introduces regression. > --- > slirp/ip.h | 14 +-- > slirp/ip6.h | 5 +- > slirp/ip6_icmp.h | 16 ++-- > slirp/libslirp.h | 12 ++- > slirp/qtailq.h | 218 ++++++++++++++++++++++++++++++++++++++++++++ > slirp/slirp.h | 12 +-- > slirp/util.h | 148 ++++++++++++++++++++++++++++++ > slirp/arp_table.c | 1 - > slirp/bootp.c | 1 - > slirp/cksum.c | 1 - > slirp/dhcpv6.c | 2 - > slirp/dnssearch.c | 1 - > slirp/if.c | 2 - > slirp/ip6_icmp.c | 4 - > slirp/ip6_input.c | 1 - > slirp/ip6_output.c | 2 - > slirp/ip_icmp.c | 7 +- > slirp/ip_input.c | 1 - > slirp/ip_output.c | 1 - > slirp/mbuf.c | 1 - > slirp/misc.c | 21 ++--- > slirp/ncsi.c | 1 - > slirp/ndp_table.c | 2 - > slirp/sbuf.c | 2 - > slirp/slirp.c | 7 -- > slirp/socket.c | 18 ++-- > slirp/tcp_input.c | 1 - > slirp/tcp_output.c | 1 - > slirp/tcp_subr.c | 13 ++- > slirp/tcp_timer.c | 1 - > slirp/tftp.c | 7 +- > slirp/udp.c | 7 +- > slirp/udp6.c | 2 - > slirp/util.c | 176 +++++++++++++++++++++++++++++++++++ > slirp/Makefile.objs | 1 + > 35 files changed, 609 insertions(+), 101 deletions(-) > create mode 100644 slirp/qtailq.h > create mode 100644 slirp/util.h > create mode 100644 slirp/util.c > > diff --git a/slirp/ip.h b/slirp/ip.h > index 243b6c8b24..cd6ddf2bb7 100644 > --- a/slirp/ip.h > +++ b/slirp/ip.h > @@ -89,7 +89,7 @@ struct ip { > uint8_t ip_p; /* protocol */ > uint16_t ip_sum; /* checksum */ > struct in_addr ip_src,ip_dst; /* source and dest address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > #define IP_MAXPACKET 65535 /* maximum packet size */ > > @@ -151,7 +151,7 @@ struct ip_timestamp { > n_long ipt_time; > } ipt_ta[1]; > } ipt_timestamp; > -} QEMU_PACKED; > +} SLIRP_PACKED; > > /* flag bits for ipt_flg */ > #define IPOPT_TS_TSONLY 0 /* timestamps only */ > @@ -181,11 +181,11 @@ struct ip_timestamp { > struct mbuf_ptr { > struct mbuf *mptr; > uint32_t dummy; > -} QEMU_PACKED; > +} SLIRP_PACKED; > #else > struct mbuf_ptr { > struct mbuf *mptr; > -} QEMU_PACKED; > +} SLIRP_PACKED; > #endif > struct qlink { > void *next, *prev; > @@ -201,7 +201,7 @@ struct ipovly { > uint16_t ih_len; /* protocol length */ > struct in_addr ih_src; /* source internet address */ > struct in_addr ih_dst; /* destination internet address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > /* > * Ip reassembly queue structure. Each fragment > @@ -217,7 +217,7 @@ struct ipq { > uint8_t ipq_p; /* protocol of this fragment */ > uint16_t ipq_id; /* sequence id for reassembly */ > struct in_addr ipq_src,ipq_dst; > -} QEMU_PACKED; > +} SLIRP_PACKED; > > /* > * Ip header, when holding a fragment. > @@ -227,7 +227,7 @@ struct ipq { > struct ipasfrag { > struct qlink ipf_link; > struct ip ipf_ip; > -} QEMU_PACKED; > +} SLIRP_PACKED; > > #define ipf_off ipf_ip.ip_off > #define ipf_tos ipf_ip.ip_tos > diff --git a/slirp/ip6.h b/slirp/ip6.h > index 14e9c78735..e0a13dec1c 100644 > --- a/slirp/ip6.h > +++ b/slirp/ip6.h > @@ -7,7 +7,6 @@ > #define SLIRP_IP6_H > > #include <glib.h> > -#include "net/eth.h" > > #define ALLNODES_MULTICAST { .s6_addr = \ > { 0xff, 0x02, 0x00, 0x00,\ > @@ -133,7 +132,7 @@ struct ip6 { > uint8_t ip_nh; /* next header */ > uint8_t ip_hl; /* hop limit */ > struct in6_addr ip_src, ip_dst; /* source and dest address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > /* > * IPv6 pseudo-header used by upper-layer protocols > @@ -145,7 +144,7 @@ struct ip6_pseudohdr { > uint16_t ih_zero_hi; /* zero */ > uint8_t ih_zero_lo; /* zero */ > uint8_t ih_nh; /* next header */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > > #endif > diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h > index 32b0914055..1f09b485e3 100644 > --- a/slirp/ip6_icmp.h > +++ b/slirp/ip6_icmp.h > @@ -48,12 +48,12 @@ struct ndp_ra { /* Router Advertisement Message */ > uint16_t lifetime; /* Router Lifetime */ > uint32_t reach_time; /* Reachable Time */ > uint32_t retrans_time; /* Retrans Timer */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > struct ndp_ns { /* Neighbor Solicitation Message */ > uint32_t reserved; > struct in6_addr target; /* Target Address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > struct ndp_na { /* Neighbor Advertisement Message */ > #if G_BYTE_ORDER == G_BIG_ENDIAN > @@ -72,13 +72,13 @@ struct ndp_na { /* Neighbor Advertisement Message */ > reserved_lo:24; > #endif > struct in6_addr target; /* Target Address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > struct ndp_redirect { > uint32_t reserved; > struct in6_addr target; /* Target Address */ > struct in6_addr dest; /* Destination Address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > /* > * Structure of an icmpv6 header. > @@ -103,7 +103,7 @@ struct icmp6 { > #define icmp6_nns icmp6_body.ndp_ns > #define icmp6_nna icmp6_body.ndp_na > #define icmp6_redirect icmp6_body.ndp_redirect > -} QEMU_PACKED; > +} SLIRP_PACKED; > > #define ICMP6_MINLEN 4 > #define ICMP6_ERROR_MINLEN 8 > @@ -134,16 +134,16 @@ struct ndpopt { > uint32_t pref_lt; /* Preferred Lifetime */ > uint32_t reserved2; > struct in6_addr prefix; > - } QEMU_PACKED prefixinfo; > + } SLIRP_PACKED prefixinfo; > #define ndpopt_prefixinfo ndpopt_body.prefixinfo > struct rdnss { > uint16_t reserved; > uint32_t lifetime; > struct in6_addr addr; > - } QEMU_PACKED rdnss; > + } SLIRP_PACKED rdnss; > #define ndpopt_rdnss ndpopt_body.rdnss > } ndpopt_body; > -} QEMU_PACKED; > +} SLIRP_PACKED; > > /* NDP options type */ > #define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */ > diff --git a/slirp/libslirp.h b/slirp/libslirp.h > index f2d71bd1f6..2c90738f89 100644 > --- a/slirp/libslirp.h > +++ b/slirp/libslirp.h > @@ -1,7 +1,17 @@ > #ifndef LIBSLIRP_H > #define LIBSLIRP_H > > -#include "qemu-common.h" > +#include <glib.h> > +#include <stdint.h> > +#include <stdbool.h> > + > +#ifdef _WIN32 > +#include <winsock2.h> > +#include <in6addr.h> > +#else > +#include <netinet/in.h> > +#include <arpa/inet.h> > +#endif > > typedef struct Slirp Slirp; > > diff --git a/slirp/qtailq.h b/slirp/qtailq.h > new file mode 100644 > index 0000000000..7c1d73a5bd > --- /dev/null > +++ b/slirp/qtailq.h > @@ -0,0 +1,218 @@ > +/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */ > + > +/* > + * slirp version: Copy from QEMU, removed all but tail queues. > + */ > + > +/* > + * Copyright (c) 1991, 1993 > + * The Regents of the University of California. All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. Neither the name of the University nor the names of its contributors > + * may be used to endorse or promote products derived from this software > + * without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * @(#)queue.h 8.5 (Berkeley) 8/20/94 > + */ > + > +#ifndef QTAILQ_H > +#define QTAILQ_H > + > +/* > + * A tail queue is headed by a pair of pointers, one to the head of the > + * list and the other to the tail of the list. The elements are doubly > + * linked so that an arbitrary element can be removed without a need to > + * traverse the list. New elements can be added to the list before or > + * after an existing element, at the head of the list, or at the end of > + * the list. A tail queue may be traversed in either direction. > + */ > + > +#define Q_TAILQ_HEAD(name, type, qual) \ > + struct name { \ > + qual type *tqh_first; /* first element */ \ > + qual type *qual *tqh_last; /* addr of last next element */ \ > + } > +#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type, ) > + > +#define QTAILQ_HEAD_INITIALIZER(head) \ > + { \ > + NULL, &(head).tqh_first \ > + } > + > +#define Q_TAILQ_ENTRY(type, qual) \ > + struct { \ > + qual type *tqe_next; /* next element */ \ > + qual type *qual *tqe_prev; /* address of previous next element */ \ > + } > +#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type, ) > + > +/* > + * Tail queue functions. > + */ > +#define QTAILQ_INIT(head) \ > + do { \ > + (head)->tqh_first = NULL; \ > + (head)->tqh_last = &(head)->tqh_first; \ > + } while (/*CONSTCOND*/ 0) > + > +#define QTAILQ_INSERT_HEAD(head, elm, field) \ > + do { \ > + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ > + (head)->tqh_first->field.tqe_prev = &(elm)->field.tqe_next; \ > + else \ > + (head)->tqh_last = &(elm)->field.tqe_next; \ > + (head)->tqh_first = (elm); \ > + (elm)->field.tqe_prev = &(head)->tqh_first; \ > + } while (/*CONSTCOND*/ 0) > + > +#define QTAILQ_INSERT_TAIL(head, elm, field) \ > + do { \ > + (elm)->field.tqe_next = NULL; \ > + (elm)->field.tqe_prev = (head)->tqh_last; \ > + *(head)->tqh_last = (elm); \ > + (head)->tqh_last = &(elm)->field.tqe_next; \ > + } while (/*CONSTCOND*/ 0) > + > +#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) \ > + do { \ > + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL) \ > + (elm)->field.tqe_next->field.tqe_prev = &(elm)->field.tqe_next; \ > + else \ > + (head)->tqh_last = &(elm)->field.tqe_next; \ > + (listelm)->field.tqe_next = (elm); \ > + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ > + } while (/*CONSTCOND*/ 0) > + > +#define QTAILQ_INSERT_BEFORE(listelm, elm, field) \ > + do { \ > + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ > + (elm)->field.tqe_next = (listelm); \ > + *(listelm)->field.tqe_prev = (elm); \ > + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ > + } while (/*CONSTCOND*/ 0) > + > +#define QTAILQ_REMOVE(head, elm, field) \ > + do { \ > + if (((elm)->field.tqe_next) != NULL) \ > + (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; \ > + else \ > + (head)->tqh_last = (elm)->field.tqe_prev; \ > + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ > + (elm)->field.tqe_prev = NULL; \ > + } while (/*CONSTCOND*/ 0) > + > +#define QTAILQ_FOREACH(var, head, field) \ > + for ((var) = ((head)->tqh_first); (var); (var) = ((var)->field.tqe_next)) > + > +#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \ > + for ((var) = ((head)->tqh_first); \ > + (var) && ((next_var) = ((var)->field.tqe_next), 1); \ > + (var) = (next_var)) > + > +#define QTAILQ_FOREACH_REVERSE(var, head, headname, field) \ > + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ > + (var); \ > + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) > + > +#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev_var) \ > + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ > + (var) && \ > + ((prev_var) = \ > + (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)), \ > + 1); \ > + (var) = (prev_var)) > + > +/* > + * Tail queue access methods. > + */ > +#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL) > +#define QTAILQ_FIRST(head) ((head)->tqh_first) > +#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next) > +#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_prev != NULL) > + > +#define QTAILQ_LAST(head, headname) \ > + (*(((struct headname *)((head)->tqh_last))->tqh_last)) > +#define QTAILQ_PREV(elm, headname, field) \ > + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) > + > +#define field_at_offset(base, offset, type) \ > + ((type)(((char *)(base)) + (offset))) > + > +typedef struct DUMMY_Q_ENTRY DUMMY_Q_ENTRY; > +typedef struct DUMMY_Q DUMMY_Q; > + > +struct DUMMY_Q_ENTRY { > + QTAILQ_ENTRY(DUMMY_Q_ENTRY) next; > +}; > + > +struct DUMMY_Q { > + QTAILQ_HEAD(DUMMY_Q_HEAD, DUMMY_Q_ENTRY) head; > +}; > + > +#define dummy_q ((DUMMY_Q *)0) > +#define dummy_qe ((DUMMY_Q_ENTRY *)0) > + > +/* > + * Offsets of layout of a tail queue head. > + */ > +#define QTAILQ_FIRST_OFFSET (offsetof(typeof(dummy_q->head), tqh_first)) > +#define QTAILQ_LAST_OFFSET (offsetof(typeof(dummy_q->head), tqh_last)) > +/* > + * Raw access of elements of a tail queue > + */ > +#define QTAILQ_RAW_FIRST(head) \ > + (*field_at_offset(head, QTAILQ_FIRST_OFFSET, void **)) > +#define QTAILQ_RAW_TQH_LAST(head) \ > + (*field_at_offset(head, QTAILQ_LAST_OFFSET, void ***)) > + > +/* > + * Offsets of layout of a tail queue element. > + */ > +#define QTAILQ_NEXT_OFFSET (offsetof(typeof(dummy_qe->next), tqe_next)) > +#define QTAILQ_PREV_OFFSET (offsetof(typeof(dummy_qe->next), tqe_prev)) > + > +/* > + * Raw access of elements of a tail entry > + */ > +#define QTAILQ_RAW_NEXT(elm, entry) \ > + (*field_at_offset(elm, entry + QTAILQ_NEXT_OFFSET, void **)) > +#define QTAILQ_RAW_TQE_PREV(elm, entry) \ > + (*field_at_offset(elm, entry + QTAILQ_PREV_OFFSET, void ***)) > +/* > + * Tail queue tranversal using pointer arithmetic. > + */ > +#define QTAILQ_RAW_FOREACH(elm, head, entry) \ > + for ((elm) = QTAILQ_RAW_FIRST(head); (elm); \ > + (elm) = QTAILQ_RAW_NEXT(elm, entry)) > +/* > + * Tail queue insertion using pointer arithmetic. > + */ > +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) \ > + do { \ > + QTAILQ_RAW_NEXT(elm, entry) = NULL; \ > + QTAILQ_RAW_TQE_PREV(elm, entry) = QTAILQ_RAW_TQH_LAST(head); \ > + *QTAILQ_RAW_TQH_LAST(head) = (elm); \ > + QTAILQ_RAW_TQH_LAST(head) = &QTAILQ_RAW_NEXT(elm, entry); \ > + } while (/*CONSTCOND*/ 0) > + > +#endif /* QTAILQ_H */ > diff --git a/slirp/slirp.h b/slirp/slirp.h > index 6e7a663b6f..08ec331ee5 100644 > --- a/slirp/slirp.h > +++ b/slirp/slirp.h > @@ -5,8 +5,8 @@ > > typedef char *caddr_t; > > -# include <windows.h> > # include <winsock2.h> > +# include <windows.h> > # include <ws2tcpip.h> > # include <sys/timeb.h> > # include <iphlpapi.h> > @@ -45,10 +45,8 @@ typedef char *caddr_t; > #define quehead slirp_quehead > > #include "debug.h" > - > -#include "qemu/queue.h" > -#include "qemu/sockets.h" > -#include "net/eth.h" > +#include "util.h" > +#include "qtailq.h" > > #include "libslirp.h" > #include "ip.h" > @@ -93,7 +91,7 @@ struct slirp_arphdr { > uint32_t ar_sip; /* sender IP address */ > unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ > uint32_t ar_tip; /* target IP address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > #define ARP_TABLE_SIZE 16 > > @@ -110,7 +108,7 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr, > struct ndpentry { > unsigned char eth_addr[ETH_ALEN]; /* sender hardware address */ > struct in6_addr ip_addr; /* sender IP address */ > -} QEMU_PACKED; > +} SLIRP_PACKED; > > #define NDP_TABLE_SIZE 16 > > diff --git a/slirp/util.h b/slirp/util.h > new file mode 100644 > index 0000000000..daf652d3e6 > --- /dev/null > +++ b/slirp/util.h > @@ -0,0 +1,148 @@ > +/* > + * Copyright (c) 2003-2008 Fabrice Bellard > + * Copyright (c) 2010-2016 Red Hat, Inc. > + * > + * 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. > + */ > +#ifndef UTIL_H_ > +#define UTIL_H_ > + > +#include <stdlib.h> > +#include <stdio.h> > +#include <assert.h> > +#include <errno.h> > +#include <unistd.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <unistd.h> > +#include <inttypes.h> > + > +#ifdef _WIN32 > +#include <winsock2.h> > +#include <windows.h> > +#else > +#include <sys/socket.h> > +#include <netinet/tcp.h> > +#include <netinet/in.h> > +#endif > + > +#if defined(_WIN32) > +# define SLIRP_PACKED __attribute__((gcc_struct, packed)) > +#else > +# define SLIRP_PACKED __attribute__((packed)) > +#endif > + > +#ifndef DIV_ROUND_UP > +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) > +#endif > + > +#define SCALE_MS 1000000 > + > +#ifndef container_of > +#define container_of(ptr, type, member) (__extension__({ \ > + const typeof(((type *) 0)->member) *__mptr = (ptr); \ > + (type *) ((char *) __mptr - offsetof(type, member));})) > +#endif > + > +#ifndef glue > +#define xglue(x, y) x ## y > +#define glue(x, y) xglue(x, y) > +#define stringify(s) tostring(s) > +#define tostring(s) #s > +#endif > + > +#if defined(_WIN32) /* CONFIG_IOVEC */ > +# if !defined(IOV_MAX) /* XXX: to avoid duplicate with QEMU osdep.h */ > +struct iovec { > + void *iov_base; > + size_t iov_len; > +}; > +# endif > +#else > +#include <sys/uio.h> > +#endif > + > +#define ETH_ALEN 6 > +#define ETH_HLEN 6 > +#define ETH_P_IP (0x0800) /* Internet Protocol packet */ > +#define ETH_P_ARP (0x0806) /* Address Resolution packet */ > +#define ETH_P_IPV6 (0x86dd) > +#define ETH_P_VLAN (0x8100) > +#define ETH_P_DVLAN (0x88a8) > +#define ETH_P_NCSI (0x88f8) > +#define ETH_P_UNKNOWN (0xffff) > + > +#ifdef _WIN32 > +int slirp_closesocket(int fd); > +int slirp_ioctlsocket(int fd, int req, void *val); > +int inet_aton(const char *cp, struct in_addr *ia); > +#define slirp_getsockopt(sockfd, level, optname, optval, optlen) \ > + getsockopt(sockfd, level, optname, (void *)optval, optlen) > +#define slirp_setsockopt(sockfd, level, optname, optval, optlen) \ > + setsockopt(sockfd, level, optname, (const void *)optval, optlen) > +#define slirp_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) > +#else > +#define slirp_setsockopt setsockopt > +#define slirp_getsockopt getsockopt > +#define slirp_recv recv > +#define slirp_closesocket close > +#define slirp_ioctlsocket ioctl > +#endif > + > +int slirp_socket(int domain, int type, int protocol); > + > +static inline int socket_set_nodelay(int fd) > +{ > + int v = 1; > + return slirp_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); > +} > + > +static inline int socket_set_fast_reuse(int fd) > +{ > +#ifndef _WIN32 > + int v = 1; > + return slirp_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)); > +#else > + /* Enabling the reuse of an endpoint that was used by a socket still in > + * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows > + * fast reuse is the default and SO_REUSEADDR does strange things. So we > + * don't have to do anything here. More info can be found at: > + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ > + return 0; > +#endif > +} > + > +static inline void pstrcpy(char *buf, int buf_size, const char *str) > +{ > + int c; > + char *q = buf; > + > + if (buf_size <= 0) > + return; > + > + for(;;) { > + c = *str++; > + if (c == 0 || q >= buf + buf_size - 1) > + break; > + *q++ = c; > + } > + *q = '\0'; > +} > + > +#endif > diff --git a/slirp/arp_table.c b/slirp/arp_table.c > index bf71b984ad..8ea655f79d 100644 > --- a/slirp/arp_table.c > +++ b/slirp/arp_table.c > @@ -22,7 +22,6 @@ > * THE SOFTWARE. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]) > diff --git a/slirp/bootp.c b/slirp/bootp.c > index 4c9a77eb98..d396849a05 100644 > --- a/slirp/bootp.c > +++ b/slirp/bootp.c > @@ -21,7 +21,6 @@ > * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > * THE SOFTWARE. > */ > -#include "qemu/osdep.h" > #include "slirp.h" > > #if defined(_WIN32) > diff --git a/slirp/cksum.c b/slirp/cksum.c > index 84c858fafb..25bfa67348 100644 > --- a/slirp/cksum.c > +++ b/slirp/cksum.c > @@ -30,7 +30,6 @@ > * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > /* > diff --git a/slirp/dhcpv6.c b/slirp/dhcpv6.c > index 752df40536..9ffba38e8f 100644 > --- a/slirp/dhcpv6.c > +++ b/slirp/dhcpv6.c > @@ -20,8 +20,6 @@ > * along with this program; if not, see <http://www.gnu.org/licenses/>. > */ > > -#include "qemu/osdep.h" > -#include "qemu/log.h" > #include "slirp.h" > #include "dhcpv6.h" > > diff --git a/slirp/dnssearch.c b/slirp/dnssearch.c > index 8fb563321b..c459cece8d 100644 > --- a/slirp/dnssearch.c > +++ b/slirp/dnssearch.c > @@ -22,7 +22,6 @@ > * THE SOFTWARE. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119; > diff --git a/slirp/if.c b/slirp/if.c > index 73e3705740..2ad03b8a79 100644 > --- a/slirp/if.c > +++ b/slirp/if.c > @@ -5,9 +5,7 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > -#include "qemu/timer.h" > > static void > ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) > diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c > index e72c57a81d..2a432ebbd4 100644 > --- a/slirp/ip6_icmp.c > +++ b/slirp/ip6_icmp.c > @@ -3,12 +3,8 @@ > * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > #include "ip6_icmp.h" > -#include "qemu/timer.h" > -#include "qemu/error-report.h" > -#include "qemu/log.h" > > #define NDP_Interval g_rand_int_range(slirp->grand, \ > NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval) > diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c > index ab656a0a9d..1b8c003c66 100644 > --- a/slirp/ip6_input.c > +++ b/slirp/ip6_input.c > @@ -3,7 +3,6 @@ > * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > #include "ip6_icmp.h" > > diff --git a/slirp/ip6_output.c b/slirp/ip6_output.c > index 52c88ad691..19d1ae7748 100644 > --- a/slirp/ip6_output.c > +++ b/slirp/ip6_output.c > @@ -3,8 +3,6 @@ > * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. > */ > > -#include "qemu/osdep.h" > -#include "qemu-common.h" > #include "slirp.h" > > /* Number of packets queued before we start sending > diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c > index 7c7e042049..e2e673ceaa 100644 > --- a/slirp/ip_icmp.c > +++ b/slirp/ip_icmp.c > @@ -30,7 +30,6 @@ > * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > #include "ip_icmp.h" > > @@ -83,7 +82,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) > struct ip *ip = mtod(m, struct ip *); > struct sockaddr_in addr; > > - so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); > + so->s = slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); > if (so->s == -1) { > return -1; > } > @@ -114,7 +113,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) > > void icmp_detach(struct socket *so) > { > - closesocket(so->s); > + slirp_closesocket(so->s); > sofree(so); > } > > @@ -421,7 +420,7 @@ void icmp_receive(struct socket *so) > icp = mtod(m, struct icmp *); > > id = icp->icmp_id; > - len = qemu_recv(so->s, icp, M_ROOM(m), 0); > + len = slirp_recv(so->s, icp, M_ROOM(m), 0); > /* > * The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsistent > * between host OSes. On Linux, only the ICMP header and payload is > diff --git a/slirp/ip_input.c b/slirp/ip_input.c > index 6831526320..cfda30fccd 100644 > --- a/slirp/ip_input.c > +++ b/slirp/ip_input.c > @@ -38,7 +38,6 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > #include "ip_icmp.h" > > diff --git a/slirp/ip_output.c b/slirp/ip_output.c > index db403f04c1..f6ec141df5 100644 > --- a/slirp/ip_output.c > +++ b/slirp/ip_output.c > @@ -38,7 +38,6 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > /* Number of packets queued before we start sending > diff --git a/slirp/mbuf.c b/slirp/mbuf.c > index d8d275e0e7..521c02c967 100644 > --- a/slirp/mbuf.c > +++ b/slirp/mbuf.c > @@ -15,7 +15,6 @@ > * the flags > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > #define MBUF_THRESH 30 > diff --git a/slirp/misc.c b/slirp/misc.c > index 7789cefefa..5b1c526f17 100644 > --- a/slirp/misc.c > +++ b/slirp/misc.c > @@ -5,11 +5,8 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > #include "libslirp.h" > -#include "qemu/error-report.h" > -#include "qemu/main-loop.h" > > inline void > insque(void *a, void *b) > @@ -83,14 +80,14 @@ slirp_socketpair_with_oob(int sv[2]) > int ret, s; > > sv[1] = -1; > - s = qemu_socket(AF_INET, SOCK_STREAM, 0); > + s = slirp_socket(AF_INET, SOCK_STREAM, 0); > if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || > listen(s, 1) < 0 || > getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) { > goto err; > } > > - sv[1] = qemu_socket(AF_INET, SOCK_STREAM, 0); > + sv[1] = slirp_socket(AF_INET, SOCK_STREAM, 0); > if (sv[1] < 0) { > goto err; > } > @@ -113,16 +110,16 @@ slirp_socketpair_with_oob(int sv[2]) > goto err; > } > > - closesocket(s); > + slirp_closesocket(s); > return 0; > > err: > g_critical("slirp_socketpair(): %s", strerror(errno)); > if (s >= 0) { > - closesocket(s); > + slirp_closesocket(s); > } > if (sv[1] >= 0) { > - closesocket(sv[1]); > + slirp_closesocket(sv[1]); > } > return -1; > } > @@ -162,16 +159,16 @@ fork_exec(struct socket *so, const char *ex) > if (err) { > g_critical("fork_exec: %s", err->message); > g_error_free(err); > - closesocket(sp[0]); > - closesocket(sp[1]); > + slirp_closesocket(sp[0]); > + slirp_closesocket(sp[1]); > return 0; > } > > so->s = sp[0]; > - closesocket(sp[1]); > + slirp_closesocket(sp[1]); > socket_set_fast_reuse(so->s); > opt = 1; > - qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); > + slirp_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); > so->slirp->cb->set_nonblock(so->s); > return 1; > } > diff --git a/slirp/ncsi.c b/slirp/ncsi.c > index 8594382270..327f17543c 100644 > --- a/slirp/ncsi.c > +++ b/slirp/ncsi.c > @@ -6,7 +6,6 @@ > * This code is licensed under the GPL version 2 or later. See the > * COPYING file in the top-level directory. > */ > -#include "qemu/osdep.h" > #include "slirp.h" > > #include "ncsi-pkt.h" > diff --git a/slirp/ndp_table.c b/slirp/ndp_table.c > index b7b73722f7..34ea4fdf1f 100644 > --- a/slirp/ndp_table.c > +++ b/slirp/ndp_table.c > @@ -3,8 +3,6 @@ > * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. > */ > > -#include "qemu/osdep.h" > -#include "qemu-common.h" > #include "slirp.h" > > void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, > diff --git a/slirp/sbuf.c b/slirp/sbuf.c > index 17f28e97a6..51a9f0cc7d 100644 > --- a/slirp/sbuf.c > +++ b/slirp/sbuf.c > @@ -5,9 +5,7 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > -#include "qemu/main-loop.h" > > static void sbappendsb(struct sbuf *sb, struct mbuf *m); > > diff --git a/slirp/slirp.c b/slirp/slirp.c > index a1f42c8b19..39c0370e19 100644 > --- a/slirp/slirp.c > +++ b/slirp/slirp.c > @@ -21,14 +21,7 @@ > * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > * THE SOFTWARE. > */ > -#include "qemu/osdep.h" > -#include "qemu-common.h" > -#include "qemu/timer.h" > -#include "qemu/error-report.h" > -#include "migration/register.h" > #include "slirp.h" > -#include "hw/hw.h" > -#include "qemu/cutils.h" > > #ifdef WITH_QEMU > #include "state.h" > diff --git a/slirp/socket.c b/slirp/socket.c > index 4d5be38747..7ae88b8e87 100644 > --- a/slirp/socket.c > +++ b/slirp/socket.c > @@ -5,8 +5,6 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > -#include "qemu-common.h" > #include "slirp.h" > #include "ip_icmp.h" > #ifdef __sun__ > @@ -187,7 +185,7 @@ soread(struct socket *so) > */ > sopreprbuf(so, iov, &n); > > - nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); > + nn = slirp_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); > if (nn <= 0) { > if (nn < 0 && (errno == EINTR || errno == EAGAIN)) > return 0; > @@ -203,7 +201,7 @@ soread(struct socket *so) > if (getpeername(so->s, paddr, &alen) < 0) { > err = errno; > } else { > - getsockopt(so->s, SOL_SOCKET, SO_ERROR, > + slirp_getsockopt(so->s, SOL_SOCKET, SO_ERROR, > &err, &elen); > } > } > @@ -233,7 +231,7 @@ soread(struct socket *so) > */ > if (n == 2 && nn == iov[0].iov_len) { > int ret; > - ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); > + ret = slirp_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); > if (ret > 0) > nn += ret; > } > @@ -554,7 +552,7 @@ sorecvfrom(struct socket *so) > */ > len = M_FREEROOM(m); > /* if (so->so_fport != htons(53)) { */ > - ioctlsocket(so->s, FIONREAD, &n); > + slirp_ioctlsocket(so->s, FIONREAD, &n); > > if (n > len) { > n = (m->m_data - m->m_dat) + m->m_len + n + 1; > @@ -719,14 +717,14 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, > addr.sin_addr.s_addr = haddr; > addr.sin_port = hport; > > - if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) || > + if (((s = slirp_socket(AF_INET,SOCK_STREAM,0)) < 0) || > (socket_set_fast_reuse(s) < 0) || > (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || > (listen(s,1) < 0)) { > int tmperrno = errno; /* Don't clobber the real reason we failed */ > > if (s >= 0) { > - closesocket(s); > + slirp_closesocket(s); > } > sofree(so); > /* Restore the real errno */ > @@ -737,9 +735,9 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, > #endif > return NULL; > } > - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); > + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); > opt = 1; > - qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)); > + slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)); > > getsockname(s,(struct sockaddr *)&addr,&addrlen); > so->so_ffamily = AF_INET; > diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c > index f205a1e6cb..3cd6277672 100644 > --- a/slirp/tcp_input.c > +++ b/slirp/tcp_input.c > @@ -38,7 +38,6 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > #include "ip_icmp.h" > > diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c > index 2f7f90d67e..f02b94b8f0 100644 > --- a/slirp/tcp_output.c > +++ b/slirp/tcp_output.c > @@ -38,7 +38,6 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > static const u_char tcp_outflags[TCP_NSTATES] = { > diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c > index 3b15148187..4e486093c0 100644 > --- a/slirp/tcp_subr.c > +++ b/slirp/tcp_subr.c > @@ -38,7 +38,6 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > /* patchable/settable parameters for tcp */ > @@ -337,7 +336,7 @@ tcp_close(struct tcpcb *tp) > /* clobber input socket cache if we're closing the cached connection */ > if (so == slirp->tcp_last_so) > slirp->tcp_last_so = &slirp->tcb; > - closesocket(so->s); > + slirp_closesocket(so->s); > sbfree(&so->so_rcv); > sbfree(&so->so_snd); > sofree(so); > @@ -407,7 +406,7 @@ int tcp_fconnect(struct socket *so, unsigned short af) > DEBUG_CALL("tcp_fconnect"); > DEBUG_ARG("so = %p", so); > > - ret = so->s = qemu_socket(af, SOCK_STREAM, 0); > + ret = so->s = slirp_socket(af, SOCK_STREAM, 0); > if (ret >= 0) { > int opt, s=so->s; > struct sockaddr_storage addr; > @@ -415,9 +414,9 @@ int tcp_fconnect(struct socket *so, unsigned short af) > so->slirp->cb->set_nonblock(s); > socket_set_fast_reuse(s); > opt = 1; > - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); > + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); > opt = 1; > - qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); > + slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); > > addr = so->fhost.ss; > DEBUG_CALL(" connect()ing"); > @@ -487,7 +486,7 @@ void tcp_connect(struct socket *inso) > so->slirp->cb->set_nonblock(s); > socket_set_fast_reuse(s); > opt = 1; > - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); > + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); > socket_set_nodelay(s); > > so->fhost.ss = addr; > @@ -496,7 +495,7 @@ void tcp_connect(struct socket *inso) > /* Close the accept() socket, set right state */ > if (inso->so_state & SS_FACCEPTONCE) { > /* If we only accept once, close the accept() socket */ > - closesocket(so->s); > + slirp_closesocket(so->s); > > /* Don't select it yet, even though we have an FD */ > /* if it's not FACCEPTONCE, it's already NOFDREF */ > diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c > index d953a16386..ebc9d16f06 100644 > --- a/slirp/tcp_timer.c > +++ b/slirp/tcp_timer.c > @@ -30,7 +30,6 @@ > * tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > > static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer); > diff --git a/slirp/tftp.c b/slirp/tftp.c > index 6fb381ef33..eae7f7c7f2 100644 > --- a/slirp/tftp.c > +++ b/slirp/tftp.c > @@ -22,10 +22,11 @@ > * THE SOFTWARE. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > -#include "qemu-common.h" > -#include "qemu/cutils.h" > + > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <fcntl.h> > > static inline int tftp_session_in_use(struct tftp_session *spt) > { > diff --git a/slirp/udp.c b/slirp/udp.c > index 4cf0d34d64..e49a8862d4 100644 > --- a/slirp/udp.c > +++ b/slirp/udp.c > @@ -38,7 +38,6 @@ > * terms and conditions of the copyright. > */ > > -#include "qemu/osdep.h" > #include "slirp.h" > #include "ip_icmp.h" > > @@ -281,7 +280,7 @@ int udp_output(struct socket *so, struct mbuf *m, > int > udp_attach(struct socket *so, unsigned short af) > { > - so->s = qemu_socket(af, SOCK_DGRAM, 0); > + so->s = slirp_socket(af, SOCK_DGRAM, 0); > if (so->s != -1) { > so->so_expire = curtime + SO_EXPIRE; > insque(so, &so->slirp->udb); > @@ -292,7 +291,7 @@ udp_attach(struct socket *so, unsigned short af) > void > udp_detach(struct socket *so) > { > - closesocket(so->s); > + slirp_closesocket(so->s); > sofree(so); > } > > @@ -327,7 +326,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, > socklen_t addrlen = sizeof(struct sockaddr_in); > > so = socreate(slirp); > - so->s = qemu_socket(AF_INET,SOCK_DGRAM,0); > + so->s = slirp_socket(AF_INET,SOCK_DGRAM,0); > if (so->s < 0) { > sofree(so); > return NULL; > diff --git a/slirp/udp6.c b/slirp/udp6.c > index fa531e03c4..be5cba1f54 100644 > --- a/slirp/udp6.c > +++ b/slirp/udp6.c > @@ -3,8 +3,6 @@ > * Guillaume Subiron > */ > > -#include "qemu/osdep.h" > -#include "qemu-common.h" > #include "slirp.h" > #include "udp.h" > #include "dhcpv6.h" > diff --git a/slirp/util.c b/slirp/util.c > new file mode 100644 > index 0000000000..b1a36b27bc > --- /dev/null > +++ b/slirp/util.c > @@ -0,0 +1,176 @@ > +/* > + * util.c (mostly based on QEMU os-win32.c) > + * > + * Copyright (c) 2003-2008 Fabrice Bellard > + * Copyright (c) 2010-2016 Red Hat, Inc. > + * > + * QEMU library functions for win32 which are shared between QEMU and > + * the QEMU tools. > + * > + * 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 "util.h" > + > +#include <glib.h> > +#include <fcntl.h> > +#include <stdint.h> > + > +#if defined(_WIN32) && !defined(WITH_QEMU) > +int inet_aton(const char *cp, struct in_addr *ia) > +{ > + uint32_t addr = inet_addr(cp); > + if (addr == 0xffffffff) { > + return 0; > + } > + ia->s_addr = addr; > + return 1; > +} > +#endif > + > +static void slirp_set_cloexec(int fd) > +{ > +#ifndef _WIN32 > + int f; > + f = fcntl(fd, F_GETFD); > + assert(f != -1); > + f = fcntl(fd, F_SETFD, f | FD_CLOEXEC); > + assert(f != -1); > +#endif > +} > + > +/* > + * Opens a socket with FD_CLOEXEC set > + */ > +int slirp_socket(int domain, int type, int protocol) > +{ > + int ret; > + > +#ifdef SOCK_CLOEXEC > + ret = socket(domain, type | SOCK_CLOEXEC, protocol); > + if (ret != -1 || errno != EINVAL) { > + return ret; > + } > +#endif > + ret = socket(domain, type, protocol); > + if (ret >= 0) { > + slirp_set_cloexec(ret); > + } > + > + return ret; > +} > + > +#ifdef _WIN32 > +static int socket_error(void) > +{ > + switch (WSAGetLastError()) { > + case 0: > + return 0; > + case WSAEINTR: > + return EINTR; > + case WSAEINVAL: > + return EINVAL; > + case WSA_INVALID_HANDLE: > + return EBADF; > + case WSA_NOT_ENOUGH_MEMORY: > + return ENOMEM; > + case WSA_INVALID_PARAMETER: > + return EINVAL; > + case WSAENAMETOOLONG: > + return ENAMETOOLONG; > + case WSAENOTEMPTY: > + return ENOTEMPTY; > + case WSAEWOULDBLOCK: > + /* not using EWOULDBLOCK as we don't want code to have > + * to check both EWOULDBLOCK and EAGAIN */ > + return EAGAIN; > + case WSAEINPROGRESS: > + return EINPROGRESS; > + case WSAEALREADY: > + return EALREADY; > + case WSAENOTSOCK: > + return ENOTSOCK; > + case WSAEDESTADDRREQ: > + return EDESTADDRREQ; > + case WSAEMSGSIZE: > + return EMSGSIZE; > + case WSAEPROTOTYPE: > + return EPROTOTYPE; > + case WSAENOPROTOOPT: > + return ENOPROTOOPT; > + case WSAEPROTONOSUPPORT: > + return EPROTONOSUPPORT; > + case WSAEOPNOTSUPP: > + return EOPNOTSUPP; > + case WSAEAFNOSUPPORT: > + return EAFNOSUPPORT; > + case WSAEADDRINUSE: > + return EADDRINUSE; > + case WSAEADDRNOTAVAIL: > + return EADDRNOTAVAIL; > + case WSAENETDOWN: > + return ENETDOWN; > + case WSAENETUNREACH: > + return ENETUNREACH; > + case WSAENETRESET: > + return ENETRESET; > + case WSAECONNABORTED: > + return ECONNABORTED; > + case WSAECONNRESET: > + return ECONNRESET; > + case WSAENOBUFS: > + return ENOBUFS; > + case WSAEISCONN: > + return EISCONN; > + case WSAENOTCONN: > + return ENOTCONN; > + case WSAETIMEDOUT: > + return ETIMEDOUT; > + case WSAECONNREFUSED: > + return ECONNREFUSED; > + case WSAELOOP: > + return ELOOP; > + case WSAEHOSTUNREACH: > + return EHOSTUNREACH; > + default: > + return EIO; > + } > +} > + > +#undef ioctlsocket > +int slirp_ioctlsocket(int fd, int req, void *val) > +{ > + int ret; > + ret = ioctlsocket(fd, req, val); > + if (ret < 0) { > + errno = socket_error(); > + } > + return ret; > +} > + > +#undef closesocket > +int slirp_closesocket(int fd) > +{ > + int ret; > + ret = closesocket(fd); > + if (ret < 0) { > + errno = socket_error(); > + } > + return ret; > +} > +#endif /* WIN32 */ > diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs > index 7abc7549ab..61cdcc6877 100644 > --- a/slirp/Makefile.objs > +++ b/slirp/Makefile.objs > @@ -28,6 +28,7 @@ slirp.mo-objs = \ > tftp.o \ > udp.o \ > udp6.o \ > + util.o \ > $(NULL) > > slirp.mo-cflags = -DG_LOG_DOMAIN=\"Slirp\" -DWITH_QEMU=1 > -- > 2.20.0.rc1 > >
diff --git a/slirp/ip.h b/slirp/ip.h index 243b6c8b24..cd6ddf2bb7 100644 --- a/slirp/ip.h +++ b/slirp/ip.h @@ -89,7 +89,7 @@ struct ip { uint8_t ip_p; /* protocol */ uint16_t ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ -} QEMU_PACKED; +} SLIRP_PACKED; #define IP_MAXPACKET 65535 /* maximum packet size */ @@ -151,7 +151,7 @@ struct ip_timestamp { n_long ipt_time; } ipt_ta[1]; } ipt_timestamp; -} QEMU_PACKED; +} SLIRP_PACKED; /* flag bits for ipt_flg */ #define IPOPT_TS_TSONLY 0 /* timestamps only */ @@ -181,11 +181,11 @@ struct ip_timestamp { struct mbuf_ptr { struct mbuf *mptr; uint32_t dummy; -} QEMU_PACKED; +} SLIRP_PACKED; #else struct mbuf_ptr { struct mbuf *mptr; -} QEMU_PACKED; +} SLIRP_PACKED; #endif struct qlink { void *next, *prev; @@ -201,7 +201,7 @@ struct ipovly { uint16_t ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ -} QEMU_PACKED; +} SLIRP_PACKED; /* * Ip reassembly queue structure. Each fragment @@ -217,7 +217,7 @@ struct ipq { uint8_t ipq_p; /* protocol of this fragment */ uint16_t ipq_id; /* sequence id for reassembly */ struct in_addr ipq_src,ipq_dst; -} QEMU_PACKED; +} SLIRP_PACKED; /* * Ip header, when holding a fragment. @@ -227,7 +227,7 @@ struct ipq { struct ipasfrag { struct qlink ipf_link; struct ip ipf_ip; -} QEMU_PACKED; +} SLIRP_PACKED; #define ipf_off ipf_ip.ip_off #define ipf_tos ipf_ip.ip_tos diff --git a/slirp/ip6.h b/slirp/ip6.h index 14e9c78735..e0a13dec1c 100644 --- a/slirp/ip6.h +++ b/slirp/ip6.h @@ -7,7 +7,6 @@ #define SLIRP_IP6_H #include <glib.h> -#include "net/eth.h" #define ALLNODES_MULTICAST { .s6_addr = \ { 0xff, 0x02, 0x00, 0x00,\ @@ -133,7 +132,7 @@ struct ip6 { uint8_t ip_nh; /* next header */ uint8_t ip_hl; /* hop limit */ struct in6_addr ip_src, ip_dst; /* source and dest address */ -} QEMU_PACKED; +} SLIRP_PACKED; /* * IPv6 pseudo-header used by upper-layer protocols @@ -145,7 +144,7 @@ struct ip6_pseudohdr { uint16_t ih_zero_hi; /* zero */ uint8_t ih_zero_lo; /* zero */ uint8_t ih_nh; /* next header */ -} QEMU_PACKED; +} SLIRP_PACKED; #endif diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h index 32b0914055..1f09b485e3 100644 --- a/slirp/ip6_icmp.h +++ b/slirp/ip6_icmp.h @@ -48,12 +48,12 @@ struct ndp_ra { /* Router Advertisement Message */ uint16_t lifetime; /* Router Lifetime */ uint32_t reach_time; /* Reachable Time */ uint32_t retrans_time; /* Retrans Timer */ -} QEMU_PACKED; +} SLIRP_PACKED; struct ndp_ns { /* Neighbor Solicitation Message */ uint32_t reserved; struct in6_addr target; /* Target Address */ -} QEMU_PACKED; +} SLIRP_PACKED; struct ndp_na { /* Neighbor Advertisement Message */ #if G_BYTE_ORDER == G_BIG_ENDIAN @@ -72,13 +72,13 @@ struct ndp_na { /* Neighbor Advertisement Message */ reserved_lo:24; #endif struct in6_addr target; /* Target Address */ -} QEMU_PACKED; +} SLIRP_PACKED; struct ndp_redirect { uint32_t reserved; struct in6_addr target; /* Target Address */ struct in6_addr dest; /* Destination Address */ -} QEMU_PACKED; +} SLIRP_PACKED; /* * Structure of an icmpv6 header. @@ -103,7 +103,7 @@ struct icmp6 { #define icmp6_nns icmp6_body.ndp_ns #define icmp6_nna icmp6_body.ndp_na #define icmp6_redirect icmp6_body.ndp_redirect -} QEMU_PACKED; +} SLIRP_PACKED; #define ICMP6_MINLEN 4 #define ICMP6_ERROR_MINLEN 8 @@ -134,16 +134,16 @@ struct ndpopt { uint32_t pref_lt; /* Preferred Lifetime */ uint32_t reserved2; struct in6_addr prefix; - } QEMU_PACKED prefixinfo; + } SLIRP_PACKED prefixinfo; #define ndpopt_prefixinfo ndpopt_body.prefixinfo struct rdnss { uint16_t reserved; uint32_t lifetime; struct in6_addr addr; - } QEMU_PACKED rdnss; + } SLIRP_PACKED rdnss; #define ndpopt_rdnss ndpopt_body.rdnss } ndpopt_body; -} QEMU_PACKED; +} SLIRP_PACKED; /* NDP options type */ #define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */ diff --git a/slirp/libslirp.h b/slirp/libslirp.h index f2d71bd1f6..2c90738f89 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -1,7 +1,17 @@ #ifndef LIBSLIRP_H #define LIBSLIRP_H -#include "qemu-common.h" +#include <glib.h> +#include <stdint.h> +#include <stdbool.h> + +#ifdef _WIN32 +#include <winsock2.h> +#include <in6addr.h> +#else +#include <netinet/in.h> +#include <arpa/inet.h> +#endif typedef struct Slirp Slirp; diff --git a/slirp/qtailq.h b/slirp/qtailq.h new file mode 100644 index 0000000000..7c1d73a5bd --- /dev/null +++ b/slirp/qtailq.h @@ -0,0 +1,218 @@ +/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */ + +/* + * slirp version: Copy from QEMU, removed all but tail queues. + */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef QTAILQ_H +#define QTAILQ_H + +/* + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + */ + +#define Q_TAILQ_HEAD(name, type, qual) \ + struct name { \ + qual type *tqh_first; /* first element */ \ + qual type *qual *tqh_last; /* addr of last next element */ \ + } +#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type, ) + +#define QTAILQ_HEAD_INITIALIZER(head) \ + { \ + NULL, &(head).tqh_first \ + } + +#define Q_TAILQ_ENTRY(type, qual) \ + struct { \ + qual type *tqe_next; /* next element */ \ + qual type *qual *tqe_prev; /* address of previous next element */ \ + } +#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type, ) + +/* + * Tail queue functions. + */ +#define QTAILQ_INIT(head) \ + do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ + } while (/*CONSTCOND*/ 0) + +#define QTAILQ_INSERT_HEAD(head, elm, field) \ + do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ + } while (/*CONSTCOND*/ 0) + +#define QTAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + } while (/*CONSTCOND*/ 0) + +#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) \ + do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ + } while (/*CONSTCOND*/ 0) + +#define QTAILQ_INSERT_BEFORE(listelm, elm, field) \ + do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ + } while (/*CONSTCOND*/ 0) + +#define QTAILQ_REMOVE(head, elm, field) \ + do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + (elm)->field.tqe_prev = NULL; \ + } while (/*CONSTCOND*/ 0) + +#define QTAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); (var); (var) = ((var)->field.tqe_next)) + +#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \ + for ((var) = ((head)->tqh_first); \ + (var) && ((next_var) = ((var)->field.tqe_next), 1); \ + (var) = (next_var)) + +#define QTAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) + +#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev_var) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var) && \ + ((prev_var) = \ + (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)), \ + 1); \ + (var) = (prev_var)) + +/* + * Tail queue access methods. + */ +#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL) +#define QTAILQ_FIRST(head) ((head)->tqh_first) +#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_prev != NULL) + +#define QTAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define QTAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define field_at_offset(base, offset, type) \ + ((type)(((char *)(base)) + (offset))) + +typedef struct DUMMY_Q_ENTRY DUMMY_Q_ENTRY; +typedef struct DUMMY_Q DUMMY_Q; + +struct DUMMY_Q_ENTRY { + QTAILQ_ENTRY(DUMMY_Q_ENTRY) next; +}; + +struct DUMMY_Q { + QTAILQ_HEAD(DUMMY_Q_HEAD, DUMMY_Q_ENTRY) head; +}; + +#define dummy_q ((DUMMY_Q *)0) +#define dummy_qe ((DUMMY_Q_ENTRY *)0) + +/* + * Offsets of layout of a tail queue head. + */ +#define QTAILQ_FIRST_OFFSET (offsetof(typeof(dummy_q->head), tqh_first)) +#define QTAILQ_LAST_OFFSET (offsetof(typeof(dummy_q->head), tqh_last)) +/* + * Raw access of elements of a tail queue + */ +#define QTAILQ_RAW_FIRST(head) \ + (*field_at_offset(head, QTAILQ_FIRST_OFFSET, void **)) +#define QTAILQ_RAW_TQH_LAST(head) \ + (*field_at_offset(head, QTAILQ_LAST_OFFSET, void ***)) + +/* + * Offsets of layout of a tail queue element. + */ +#define QTAILQ_NEXT_OFFSET (offsetof(typeof(dummy_qe->next), tqe_next)) +#define QTAILQ_PREV_OFFSET (offsetof(typeof(dummy_qe->next), tqe_prev)) + +/* + * Raw access of elements of a tail entry + */ +#define QTAILQ_RAW_NEXT(elm, entry) \ + (*field_at_offset(elm, entry + QTAILQ_NEXT_OFFSET, void **)) +#define QTAILQ_RAW_TQE_PREV(elm, entry) \ + (*field_at_offset(elm, entry + QTAILQ_PREV_OFFSET, void ***)) +/* + * Tail queue tranversal using pointer arithmetic. + */ +#define QTAILQ_RAW_FOREACH(elm, head, entry) \ + for ((elm) = QTAILQ_RAW_FIRST(head); (elm); \ + (elm) = QTAILQ_RAW_NEXT(elm, entry)) +/* + * Tail queue insertion using pointer arithmetic. + */ +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) \ + do { \ + QTAILQ_RAW_NEXT(elm, entry) = NULL; \ + QTAILQ_RAW_TQE_PREV(elm, entry) = QTAILQ_RAW_TQH_LAST(head); \ + *QTAILQ_RAW_TQH_LAST(head) = (elm); \ + QTAILQ_RAW_TQH_LAST(head) = &QTAILQ_RAW_NEXT(elm, entry); \ + } while (/*CONSTCOND*/ 0) + +#endif /* QTAILQ_H */ diff --git a/slirp/slirp.h b/slirp/slirp.h index 6e7a663b6f..08ec331ee5 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -5,8 +5,8 @@ typedef char *caddr_t; -# include <windows.h> # include <winsock2.h> +# include <windows.h> # include <ws2tcpip.h> # include <sys/timeb.h> # include <iphlpapi.h> @@ -45,10 +45,8 @@ typedef char *caddr_t; #define quehead slirp_quehead #include "debug.h" - -#include "qemu/queue.h" -#include "qemu/sockets.h" -#include "net/eth.h" +#include "util.h" +#include "qtailq.h" #include "libslirp.h" #include "ip.h" @@ -93,7 +91,7 @@ struct slirp_arphdr { uint32_t ar_sip; /* sender IP address */ unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ uint32_t ar_tip; /* target IP address */ -} QEMU_PACKED; +} SLIRP_PACKED; #define ARP_TABLE_SIZE 16 @@ -110,7 +108,7 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr, struct ndpentry { unsigned char eth_addr[ETH_ALEN]; /* sender hardware address */ struct in6_addr ip_addr; /* sender IP address */ -} QEMU_PACKED; +} SLIRP_PACKED; #define NDP_TABLE_SIZE 16 diff --git a/slirp/util.h b/slirp/util.h new file mode 100644 index 0000000000..daf652d3e6 --- /dev/null +++ b/slirp/util.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2010-2016 Red Hat, Inc. + * + * 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. + */ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <inttypes.h> + +#ifdef _WIN32 +#include <winsock2.h> +#include <windows.h> +#else +#include <sys/socket.h> +#include <netinet/tcp.h> +#include <netinet/in.h> +#endif + +#if defined(_WIN32) +# define SLIRP_PACKED __attribute__((gcc_struct, packed)) +#else +# define SLIRP_PACKED __attribute__((packed)) +#endif + +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#endif + +#define SCALE_MS 1000000 + +#ifndef container_of +#define container_of(ptr, type, member) (__extension__({ \ + const typeof(((type *) 0)->member) *__mptr = (ptr); \ + (type *) ((char *) __mptr - offsetof(type, member));})) +#endif + +#ifndef glue +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s +#endif + +#if defined(_WIN32) /* CONFIG_IOVEC */ +# if !defined(IOV_MAX) /* XXX: to avoid duplicate with QEMU osdep.h */ +struct iovec { + void *iov_base; + size_t iov_len; +}; +# endif +#else +#include <sys/uio.h> +#endif + +#define ETH_ALEN 6 +#define ETH_HLEN 6 +#define ETH_P_IP (0x0800) /* Internet Protocol packet */ +#define ETH_P_ARP (0x0806) /* Address Resolution packet */ +#define ETH_P_IPV6 (0x86dd) +#define ETH_P_VLAN (0x8100) +#define ETH_P_DVLAN (0x88a8) +#define ETH_P_NCSI (0x88f8) +#define ETH_P_UNKNOWN (0xffff) + +#ifdef _WIN32 +int slirp_closesocket(int fd); +int slirp_ioctlsocket(int fd, int req, void *val); +int inet_aton(const char *cp, struct in_addr *ia); +#define slirp_getsockopt(sockfd, level, optname, optval, optlen) \ + getsockopt(sockfd, level, optname, (void *)optval, optlen) +#define slirp_setsockopt(sockfd, level, optname, optval, optlen) \ + setsockopt(sockfd, level, optname, (const void *)optval, optlen) +#define slirp_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) +#else +#define slirp_setsockopt setsockopt +#define slirp_getsockopt getsockopt +#define slirp_recv recv +#define slirp_closesocket close +#define slirp_ioctlsocket ioctl +#endif + +int slirp_socket(int domain, int type, int protocol); + +static inline int socket_set_nodelay(int fd) +{ + int v = 1; + return slirp_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); +} + +static inline int socket_set_fast_reuse(int fd) +{ +#ifndef _WIN32 + int v = 1; + return slirp_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)); +#else + /* Enabling the reuse of an endpoint that was used by a socket still in + * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows + * fast reuse is the default and SO_REUSEADDR does strange things. So we + * don't have to do anything here. More info can be found at: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ + return 0; +#endif +} + +static inline void pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return; + + for(;;) { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} + +#endif diff --git a/slirp/arp_table.c b/slirp/arp_table.c index bf71b984ad..8ea655f79d 100644 --- a/slirp/arp_table.c +++ b/slirp/arp_table.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ -#include "qemu/osdep.h" #include "slirp.h" void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]) diff --git a/slirp/bootp.c b/slirp/bootp.c index 4c9a77eb98..d396849a05 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -21,7 +21,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "qemu/osdep.h" #include "slirp.h" #if defined(_WIN32) diff --git a/slirp/cksum.c b/slirp/cksum.c index 84c858fafb..25bfa67348 100644 --- a/slirp/cksum.c +++ b/slirp/cksum.c @@ -30,7 +30,6 @@ * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp */ -#include "qemu/osdep.h" #include "slirp.h" /* diff --git a/slirp/dhcpv6.c b/slirp/dhcpv6.c index 752df40536..9ffba38e8f 100644 --- a/slirp/dhcpv6.c +++ b/slirp/dhcpv6.c @@ -20,8 +20,6 @@ * along with this program; if not, see <http://www.gnu.org/licenses/>. */ -#include "qemu/osdep.h" -#include "qemu/log.h" #include "slirp.h" #include "dhcpv6.h" diff --git a/slirp/dnssearch.c b/slirp/dnssearch.c index 8fb563321b..c459cece8d 100644 --- a/slirp/dnssearch.c +++ b/slirp/dnssearch.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ -#include "qemu/osdep.h" #include "slirp.h" static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119; diff --git a/slirp/if.c b/slirp/if.c index 73e3705740..2ad03b8a79 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -5,9 +5,7 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" -#include "qemu/timer.h" static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead) diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c index e72c57a81d..2a432ebbd4 100644 --- a/slirp/ip6_icmp.c +++ b/slirp/ip6_icmp.c @@ -3,12 +3,8 @@ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. */ -#include "qemu/osdep.h" #include "slirp.h" #include "ip6_icmp.h" -#include "qemu/timer.h" -#include "qemu/error-report.h" -#include "qemu/log.h" #define NDP_Interval g_rand_int_range(slirp->grand, \ NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval) diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c index ab656a0a9d..1b8c003c66 100644 --- a/slirp/ip6_input.c +++ b/slirp/ip6_input.c @@ -3,7 +3,6 @@ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. */ -#include "qemu/osdep.h" #include "slirp.h" #include "ip6_icmp.h" diff --git a/slirp/ip6_output.c b/slirp/ip6_output.c index 52c88ad691..19d1ae7748 100644 --- a/slirp/ip6_output.c +++ b/slirp/ip6_output.c @@ -3,8 +3,6 @@ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. */ -#include "qemu/osdep.h" -#include "qemu-common.h" #include "slirp.h" /* Number of packets queued before we start sending diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 7c7e042049..e2e673ceaa 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -30,7 +30,6 @@ * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp */ -#include "qemu/osdep.h" #include "slirp.h" #include "ip_icmp.h" @@ -83,7 +82,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) struct ip *ip = mtod(m, struct ip *); struct sockaddr_in addr; - so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); + so->s = slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); if (so->s == -1) { return -1; } @@ -114,7 +113,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) void icmp_detach(struct socket *so) { - closesocket(so->s); + slirp_closesocket(so->s); sofree(so); } @@ -421,7 +420,7 @@ void icmp_receive(struct socket *so) icp = mtod(m, struct icmp *); id = icp->icmp_id; - len = qemu_recv(so->s, icp, M_ROOM(m), 0); + len = slirp_recv(so->s, icp, M_ROOM(m), 0); /* * The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsistent * between host OSes. On Linux, only the ICMP header and payload is diff --git a/slirp/ip_input.c b/slirp/ip_input.c index 6831526320..cfda30fccd 100644 --- a/slirp/ip_input.c +++ b/slirp/ip_input.c @@ -38,7 +38,6 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" #include "ip_icmp.h" diff --git a/slirp/ip_output.c b/slirp/ip_output.c index db403f04c1..f6ec141df5 100644 --- a/slirp/ip_output.c +++ b/slirp/ip_output.c @@ -38,7 +38,6 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" /* Number of packets queued before we start sending diff --git a/slirp/mbuf.c b/slirp/mbuf.c index d8d275e0e7..521c02c967 100644 --- a/slirp/mbuf.c +++ b/slirp/mbuf.c @@ -15,7 +15,6 @@ * the flags */ -#include "qemu/osdep.h" #include "slirp.h" #define MBUF_THRESH 30 diff --git a/slirp/misc.c b/slirp/misc.c index 7789cefefa..5b1c526f17 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -5,11 +5,8 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" #include "libslirp.h" -#include "qemu/error-report.h" -#include "qemu/main-loop.h" inline void insque(void *a, void *b) @@ -83,14 +80,14 @@ slirp_socketpair_with_oob(int sv[2]) int ret, s; sv[1] = -1; - s = qemu_socket(AF_INET, SOCK_STREAM, 0); + s = slirp_socket(AF_INET, SOCK_STREAM, 0); if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || listen(s, 1) < 0 || getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) { goto err; } - sv[1] = qemu_socket(AF_INET, SOCK_STREAM, 0); + sv[1] = slirp_socket(AF_INET, SOCK_STREAM, 0); if (sv[1] < 0) { goto err; } @@ -113,16 +110,16 @@ slirp_socketpair_with_oob(int sv[2]) goto err; } - closesocket(s); + slirp_closesocket(s); return 0; err: g_critical("slirp_socketpair(): %s", strerror(errno)); if (s >= 0) { - closesocket(s); + slirp_closesocket(s); } if (sv[1] >= 0) { - closesocket(sv[1]); + slirp_closesocket(sv[1]); } return -1; } @@ -162,16 +159,16 @@ fork_exec(struct socket *so, const char *ex) if (err) { g_critical("fork_exec: %s", err->message); g_error_free(err); - closesocket(sp[0]); - closesocket(sp[1]); + slirp_closesocket(sp[0]); + slirp_closesocket(sp[1]); return 0; } so->s = sp[0]; - closesocket(sp[1]); + slirp_closesocket(sp[1]); socket_set_fast_reuse(so->s); opt = 1; - qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); so->slirp->cb->set_nonblock(so->s); return 1; } diff --git a/slirp/ncsi.c b/slirp/ncsi.c index 8594382270..327f17543c 100644 --- a/slirp/ncsi.c +++ b/slirp/ncsi.c @@ -6,7 +6,6 @@ * This code is licensed under the GPL version 2 or later. See the * COPYING file in the top-level directory. */ -#include "qemu/osdep.h" #include "slirp.h" #include "ncsi-pkt.h" diff --git a/slirp/ndp_table.c b/slirp/ndp_table.c index b7b73722f7..34ea4fdf1f 100644 --- a/slirp/ndp_table.c +++ b/slirp/ndp_table.c @@ -3,8 +3,6 @@ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. */ -#include "qemu/osdep.h" -#include "qemu-common.h" #include "slirp.h" void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, diff --git a/slirp/sbuf.c b/slirp/sbuf.c index 17f28e97a6..51a9f0cc7d 100644 --- a/slirp/sbuf.c +++ b/slirp/sbuf.c @@ -5,9 +5,7 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" -#include "qemu/main-loop.h" static void sbappendsb(struct sbuf *sb, struct mbuf *m); diff --git a/slirp/slirp.c b/slirp/slirp.c index a1f42c8b19..39c0370e19 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -21,14 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "qemu/timer.h" -#include "qemu/error-report.h" -#include "migration/register.h" #include "slirp.h" -#include "hw/hw.h" -#include "qemu/cutils.h" #ifdef WITH_QEMU #include "state.h" diff --git a/slirp/socket.c b/slirp/socket.c index 4d5be38747..7ae88b8e87 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -5,8 +5,6 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" -#include "qemu-common.h" #include "slirp.h" #include "ip_icmp.h" #ifdef __sun__ @@ -187,7 +185,7 @@ soread(struct socket *so) */ sopreprbuf(so, iov, &n); - nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); + nn = slirp_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); if (nn <= 0) { if (nn < 0 && (errno == EINTR || errno == EAGAIN)) return 0; @@ -203,7 +201,7 @@ soread(struct socket *so) if (getpeername(so->s, paddr, &alen) < 0) { err = errno; } else { - getsockopt(so->s, SOL_SOCKET, SO_ERROR, + slirp_getsockopt(so->s, SOL_SOCKET, SO_ERROR, &err, &elen); } } @@ -233,7 +231,7 @@ soread(struct socket *so) */ if (n == 2 && nn == iov[0].iov_len) { int ret; - ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); + ret = slirp_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); if (ret > 0) nn += ret; } @@ -554,7 +552,7 @@ sorecvfrom(struct socket *so) */ len = M_FREEROOM(m); /* if (so->so_fport != htons(53)) { */ - ioctlsocket(so->s, FIONREAD, &n); + slirp_ioctlsocket(so->s, FIONREAD, &n); if (n > len) { n = (m->m_data - m->m_dat) + m->m_len + n + 1; @@ -719,14 +717,14 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, addr.sin_addr.s_addr = haddr; addr.sin_port = hport; - if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) || + if (((s = slirp_socket(AF_INET,SOCK_STREAM,0)) < 0) || (socket_set_fast_reuse(s) < 0) || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || (listen(s,1) < 0)) { int tmperrno = errno; /* Don't clobber the real reason we failed */ if (s >= 0) { - closesocket(s); + slirp_closesocket(s); } sofree(so); /* Restore the real errno */ @@ -737,9 +735,9 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, #endif return NULL; } - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); opt = 1; - qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)); + slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)); getsockname(s,(struct sockaddr *)&addr,&addrlen); so->so_ffamily = AF_INET; diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index f205a1e6cb..3cd6277672 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -38,7 +38,6 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" #include "ip_icmp.h" diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c index 2f7f90d67e..f02b94b8f0 100644 --- a/slirp/tcp_output.c +++ b/slirp/tcp_output.c @@ -38,7 +38,6 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" static const u_char tcp_outflags[TCP_NSTATES] = { diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 3b15148187..4e486093c0 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -38,7 +38,6 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" /* patchable/settable parameters for tcp */ @@ -337,7 +336,7 @@ tcp_close(struct tcpcb *tp) /* clobber input socket cache if we're closing the cached connection */ if (so == slirp->tcp_last_so) slirp->tcp_last_so = &slirp->tcb; - closesocket(so->s); + slirp_closesocket(so->s); sbfree(&so->so_rcv); sbfree(&so->so_snd); sofree(so); @@ -407,7 +406,7 @@ int tcp_fconnect(struct socket *so, unsigned short af) DEBUG_CALL("tcp_fconnect"); DEBUG_ARG("so = %p", so); - ret = so->s = qemu_socket(af, SOCK_STREAM, 0); + ret = so->s = slirp_socket(af, SOCK_STREAM, 0); if (ret >= 0) { int opt, s=so->s; struct sockaddr_storage addr; @@ -415,9 +414,9 @@ int tcp_fconnect(struct socket *so, unsigned short af) so->slirp->cb->set_nonblock(s); socket_set_fast_reuse(s); opt = 1; - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); opt = 1; - qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); + slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); addr = so->fhost.ss; DEBUG_CALL(" connect()ing"); @@ -487,7 +486,7 @@ void tcp_connect(struct socket *inso) so->slirp->cb->set_nonblock(s); socket_set_fast_reuse(s); opt = 1; - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); socket_set_nodelay(s); so->fhost.ss = addr; @@ -496,7 +495,7 @@ void tcp_connect(struct socket *inso) /* Close the accept() socket, set right state */ if (inso->so_state & SS_FACCEPTONCE) { /* If we only accept once, close the accept() socket */ - closesocket(so->s); + slirp_closesocket(so->s); /* Don't select it yet, even though we have an FD */ /* if it's not FACCEPTONCE, it's already NOFDREF */ diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c index d953a16386..ebc9d16f06 100644 --- a/slirp/tcp_timer.c +++ b/slirp/tcp_timer.c @@ -30,7 +30,6 @@ * tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp */ -#include "qemu/osdep.h" #include "slirp.h" static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer); diff --git a/slirp/tftp.c b/slirp/tftp.c index 6fb381ef33..eae7f7c7f2 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -22,10 +22,11 @@ * THE SOFTWARE. */ -#include "qemu/osdep.h" #include "slirp.h" -#include "qemu-common.h" -#include "qemu/cutils.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> static inline int tftp_session_in_use(struct tftp_session *spt) { diff --git a/slirp/udp.c b/slirp/udp.c index 4cf0d34d64..e49a8862d4 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -38,7 +38,6 @@ * terms and conditions of the copyright. */ -#include "qemu/osdep.h" #include "slirp.h" #include "ip_icmp.h" @@ -281,7 +280,7 @@ int udp_output(struct socket *so, struct mbuf *m, int udp_attach(struct socket *so, unsigned short af) { - so->s = qemu_socket(af, SOCK_DGRAM, 0); + so->s = slirp_socket(af, SOCK_DGRAM, 0); if (so->s != -1) { so->so_expire = curtime + SO_EXPIRE; insque(so, &so->slirp->udb); @@ -292,7 +291,7 @@ udp_attach(struct socket *so, unsigned short af) void udp_detach(struct socket *so) { - closesocket(so->s); + slirp_closesocket(so->s); sofree(so); } @@ -327,7 +326,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, socklen_t addrlen = sizeof(struct sockaddr_in); so = socreate(slirp); - so->s = qemu_socket(AF_INET,SOCK_DGRAM,0); + so->s = slirp_socket(AF_INET,SOCK_DGRAM,0); if (so->s < 0) { sofree(so); return NULL; diff --git a/slirp/udp6.c b/slirp/udp6.c index fa531e03c4..be5cba1f54 100644 --- a/slirp/udp6.c +++ b/slirp/udp6.c @@ -3,8 +3,6 @@ * Guillaume Subiron */ -#include "qemu/osdep.h" -#include "qemu-common.h" #include "slirp.h" #include "udp.h" #include "dhcpv6.h" diff --git a/slirp/util.c b/slirp/util.c new file mode 100644 index 0000000000..b1a36b27bc --- /dev/null +++ b/slirp/util.c @@ -0,0 +1,176 @@ +/* + * util.c (mostly based on QEMU os-win32.c) + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2010-2016 Red Hat, Inc. + * + * QEMU library functions for win32 which are shared between QEMU and + * the QEMU tools. + * + * 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 "util.h" + +#include <glib.h> +#include <fcntl.h> +#include <stdint.h> + +#if defined(_WIN32) && !defined(WITH_QEMU) +int inet_aton(const char *cp, struct in_addr *ia) +{ + uint32_t addr = inet_addr(cp); + if (addr == 0xffffffff) { + return 0; + } + ia->s_addr = addr; + return 1; +} +#endif + +static void slirp_set_cloexec(int fd) +{ +#ifndef _WIN32 + int f; + f = fcntl(fd, F_GETFD); + assert(f != -1); + f = fcntl(fd, F_SETFD, f | FD_CLOEXEC); + assert(f != -1); +#endif +} + +/* + * Opens a socket with FD_CLOEXEC set + */ +int slirp_socket(int domain, int type, int protocol) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socket(domain, type | SOCK_CLOEXEC, protocol); + if (ret != -1 || errno != EINVAL) { + return ret; + } +#endif + ret = socket(domain, type, protocol); + if (ret >= 0) { + slirp_set_cloexec(ret); + } + + return ret; +} + +#ifdef _WIN32 +static int socket_error(void) +{ + switch (WSAGetLastError()) { + case 0: + return 0; + case WSAEINTR: + return EINTR; + case WSAEINVAL: + return EINVAL; + case WSA_INVALID_HANDLE: + return EBADF; + case WSA_NOT_ENOUGH_MEMORY: + return ENOMEM; + case WSA_INVALID_PARAMETER: + return EINVAL; + case WSAENAMETOOLONG: + return ENAMETOOLONG; + case WSAENOTEMPTY: + return ENOTEMPTY; + case WSAEWOULDBLOCK: + /* not using EWOULDBLOCK as we don't want code to have + * to check both EWOULDBLOCK and EAGAIN */ + return EAGAIN; + case WSAEINPROGRESS: + return EINPROGRESS; + case WSAEALREADY: + return EALREADY; + case WSAENOTSOCK: + return ENOTSOCK; + case WSAEDESTADDRREQ: + return EDESTADDRREQ; + case WSAEMSGSIZE: + return EMSGSIZE; + case WSAEPROTOTYPE: + return EPROTOTYPE; + case WSAENOPROTOOPT: + return ENOPROTOOPT; + case WSAEPROTONOSUPPORT: + return EPROTONOSUPPORT; + case WSAEOPNOTSUPP: + return EOPNOTSUPP; + case WSAEAFNOSUPPORT: + return EAFNOSUPPORT; + case WSAEADDRINUSE: + return EADDRINUSE; + case WSAEADDRNOTAVAIL: + return EADDRNOTAVAIL; + case WSAENETDOWN: + return ENETDOWN; + case WSAENETUNREACH: + return ENETUNREACH; + case WSAENETRESET: + return ENETRESET; + case WSAECONNABORTED: + return ECONNABORTED; + case WSAECONNRESET: + return ECONNRESET; + case WSAENOBUFS: + return ENOBUFS; + case WSAEISCONN: + return EISCONN; + case WSAENOTCONN: + return ENOTCONN; + case WSAETIMEDOUT: + return ETIMEDOUT; + case WSAECONNREFUSED: + return ECONNREFUSED; + case WSAELOOP: + return ELOOP; + case WSAEHOSTUNREACH: + return EHOSTUNREACH; + default: + return EIO; + } +} + +#undef ioctlsocket +int slirp_ioctlsocket(int fd, int req, void *val) +{ + int ret; + ret = ioctlsocket(fd, req, val); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} + +#undef closesocket +int slirp_closesocket(int fd) +{ + int ret; + ret = closesocket(fd); + if (ret < 0) { + errno = socket_error(); + } + return ret; +} +#endif /* WIN32 */ diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs index 7abc7549ab..61cdcc6877 100644 --- a/slirp/Makefile.objs +++ b/slirp/Makefile.objs @@ -28,6 +28,7 @@ slirp.mo-objs = \ tftp.o \ udp.o \ udp6.o \ + util.o \ $(NULL) slirp.mo-cflags = -DG_LOG_DOMAIN=\"Slirp\" -DWITH_QEMU=1
Introduce utility header/object, and replace remaining qemu functions with SLIRP helpers. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- slirp/ip.h | 14 +-- slirp/ip6.h | 5 +- slirp/ip6_icmp.h | 16 ++-- slirp/libslirp.h | 12 ++- slirp/qtailq.h | 218 ++++++++++++++++++++++++++++++++++++++++++++ slirp/slirp.h | 12 +-- slirp/util.h | 148 ++++++++++++++++++++++++++++++ slirp/arp_table.c | 1 - slirp/bootp.c | 1 - slirp/cksum.c | 1 - slirp/dhcpv6.c | 2 - slirp/dnssearch.c | 1 - slirp/if.c | 2 - slirp/ip6_icmp.c | 4 - slirp/ip6_input.c | 1 - slirp/ip6_output.c | 2 - slirp/ip_icmp.c | 7 +- slirp/ip_input.c | 1 - slirp/ip_output.c | 1 - slirp/mbuf.c | 1 - slirp/misc.c | 21 ++--- slirp/ncsi.c | 1 - slirp/ndp_table.c | 2 - slirp/sbuf.c | 2 - slirp/slirp.c | 7 -- slirp/socket.c | 18 ++-- slirp/tcp_input.c | 1 - slirp/tcp_output.c | 1 - slirp/tcp_subr.c | 13 ++- slirp/tcp_timer.c | 1 - slirp/tftp.c | 7 +- slirp/udp.c | 7 +- slirp/udp6.c | 2 - slirp/util.c | 176 +++++++++++++++++++++++++++++++++++ slirp/Makefile.objs | 1 + 35 files changed, 609 insertions(+), 101 deletions(-) create mode 100644 slirp/qtailq.h create mode 100644 slirp/util.h create mode 100644 slirp/util.c