slirp: Adding IPv6 support to Qemu -net user mode
v7 cover slirp: Adding IPv6 support to Qemu -net user mode
Hello,
This is another respin of IPv6 in Qemu -net user mode.
The following patches first make some refactoring to make current code ready for IPv6, and do not change the behavior. The actual IPv6 support will then be submitted as a separate patch series.
Difference with version 6 is:
- Use error_report instead of printing to stderr
- Drop extra parentheses
- Use nicer-looking sockaddr casts.
All of this has been reviewed by Thomas Huth, thanks!
Here is a summary of the patches:
[PATCH 1/9] slirp: goto bad in udp_input if sosendto fails [PATCH 2/9] slirp: Generalizing and neutralizing ARP code [PATCH 3/9] slirp: Adding address family switch for incoming frames [PATCH 4/9] slirp: Make Socket structure IPv6 compatible [PATCH 5/9] slirp: Factorizing address translation
[PATCH 6/9] slirp: Factorizing and cleaning solookup() [PATCH 7/9] slirp: Add sockaddr_equal, make solookup family-agnostic [PATCH 8/9] slirp: Make udp_attach IPv6 compatible
[PATCH 9/9] slirp: Adding family argument to tcp_fconnect()
PATCH 1/9 slirp: goto bad in udp_input if sosendto fails
From: Guillaume Subiron <[email protected]>
Before this patch, if sosendto fails, udp_input is executed as if the packet was sent, recording the packet for icmp errors, which does not makes sense since the packet was not actually sent, errors would be related to a previous packet.
This patch adds a goto bad to cut the execution of this function.
--- slirp/udp.c | 1 + 1 file changed, 1 insertion(+)
slirp/udp.c +1 -0
@@ -218,6 +218,7 @@ udp_input(register struct mbuf *m, int iphlen) *ip=save_ip;DEBUG_MISC ((dfd,"udp tx errno = %d-%s\n" ,errno,strerror (errno)));icmp_error (m,ICMP_UNREACH ,ICMP_UNREACH_NET ,0 ,strerror (errno)); + goto bad; }m_free (so->so_m);/* used for ICMP if error on sorecvfrom */
Signature · 1 line
2.6.2
PATCH 2/9 slirp: Generalizing and neutralizing ARP code
From: Guillaume Subiron <[email protected]>
Basically, this patch replaces "arp" by "resolution" every time "arp" means "mac resolution" and not specifically ARP.
This prepares for IPv6 support.
--- slirp/mbuf.c | 2 +- slirp/mbuf.h | 2 +- slirp/slirp.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-)
slirp/mbuf.c +1 -1
@@ -91,7 +91,7 @@ m_get(Slirp *slirp) m->m_len =0 ; m->m_nextpkt =NULL ; m->m_prevpkt =NULL ; - m->arp_requested = false; + m->resolution_requested = false; m->expiration_date = (uint64_t )-1 ; end_error:DEBUG_ARG ("m = %p" , m);
slirp/mbuf.h +1 -1
@@ -79,7 +79,7 @@ struct mbuf {int m_len;/* Amount of data in this mbuf */ Slirp *slirp; -bool arp_requested; +bool resolution_requested;uint64_t expiration_date;/* start of dynamic buffer area, must be last element */ union {
slirp/slirp.c +2 -2
@@ -786,7 +786,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)struct ethhdr *reh = (struct ethhdr *)arp_req;struct arphdr *rah = (struct arphdr *)(arp_req +ETH_HLEN ); -if (!ifm->arp_requested) { +if (!ifm->resolution_requested) {/* If the client addr is not known, send an ARP request */ memset (reh->h_dest,0xff ,ETH_ALEN );memcpy (reh->h_source, special_ethaddr,ETH_ALEN -4 );
@@ -812,7 +812,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) rah->ar_tip = iph->ip_dst.s_addr; slirp->client_ipaddr = iph->ip_dst;slirp_output (slirp->opaque, arp_req,sizeof (arp_req)); - ifm->arp_requested = true; + ifm->resolution_requested = true;/* Expire request and drop outgoing packet after 1 second */ ifm->expiration_date =qemu_clock_get_ns (QEMU_CLOCK_REALTIME ) +1000000000ULL ;
Signature · 1 line
2.6.2
PATCH 3/9 slirp: Adding address family switch for produced frames
In reply to Samuel ThibaultFrom: Guillaume Subiron <[email protected]>
In if_encap, a switch is added to prepare for the IPv6 case. Some code is factorized.
This prepares for IPv6 support.
--- slirp/slirp.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 13 deletions(-)
slirp/slirp.c +48 -13
@@ -762,20 +762,15 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) } } -/* Output the IP packet to the ethernet device. Returns 0 if the packet must be -* re-queued. +/* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no +* packet should be sent, 0 if the packet must be re-queued, 2 if the packet +* is ready to go. */ -int if_encap (Slirp *slirp,struct mbuf *ifm) +static int if_encap4 (Slirp *slirp,struct mbuf *ifm,struct ethhdr *eh, +uint8_t ethaddr[ETH_ALEN ]) { -uint8_t buf[1600 ]; -struct ethhdr *eh = (struct ethhdr *)buf; -uint8_t ethaddr[ETH_ALEN ];const struct ip *iph = (const struct ip *)ifm->m_data; -if (ifm->m_len +ETH_HLEN >sizeof (buf)) { -return 1 ; - } -if (iph->ip_dst.s_addr ==0 ) {/* 0.0.0.0 can not be a destination address, something went wrong, * avoid making it worse */
@@ -819,15 +814,55 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) }return 0 ; }else { -memcpy (eh->h_dest, ethaddr,ETH_ALEN );memcpy (eh->h_source, special_ethaddr,ETH_ALEN -4 );/* XXX: not correct */ memcpy (&eh->h_source[2 ], &slirp->vhost_addr,4 ); eh->h_proto =htons (ETH_P_IP ); -memcpy (buf +sizeof (struct ethhdr ), ifm->m_data, ifm->m_len); -slirp_output (slirp->opaque, buf, ifm->m_len +ETH_HLEN ); + +/* Send this */ +return 2 ; + } +} + +/* Output the IP packet to the ethernet device. Returns 0 if the packet must be +* re-queued. +*/ +int if_encap (Slirp *slirp,struct mbuf *ifm) +{ +uint8_t buf[1600 ]; +struct ethhdr *eh = (struct ethhdr *)buf; +uint8_t ethaddr[ETH_ALEN ]; +const struct ip *iph = (const struct ip *)ifm->m_data; +int ret; + +if (ifm->m_len +ETH_HLEN >sizeof (buf)) {return 1 ; } + +switch (iph->ip_v) { +case IPVERSION : + ret =if_encap4 (slirp, ifm, eh, ethaddr); +if (ret <2 ) { +return ret; + } +break ; + +default : +/* Do not assert while we don't manage IP6VERSION */ +/* assert(0); */ +break ; + } + +memcpy (eh->h_dest, ethaddr,ETH_ALEN ); +DEBUG_ARGS ((dfd," src = %02x:%02x:%02x:%02x:%02x:%02x\n" , + eh->h_source[0 ], eh->h_source[1 ], eh->h_source[2 ], + eh->h_source[3 ], eh->h_source[4 ], eh->h_source[5 ])); +DEBUG_ARGS ((dfd," dst = %02x:%02x:%02x:%02x:%02x:%02x\n" , + eh->h_dest[0 ], eh->h_dest[1 ], eh->h_dest[2 ], + eh->h_dest[3 ], eh->h_dest[4 ], eh->h_dest[5 ])); +memcpy (buf +sizeof (struct ethhdr ), ifm->m_data, ifm->m_len); +slirp_output (slirp->opaque, buf, ifm->m_len +ETH_HLEN ); +return 1 ; }/* Drop host forwarding rule, return 0 if found. */
Signature · 1 line
2.6.2
PATCH 4/9 slirp: Make Socket structure IPv6 compatible
In reply to Samuel ThibaultFrom: Guillaume Subiron <[email protected]>
This patch replaces foreign and local address/port couples in Socket structure by 2 sockaddr_storage which can be casted in sockaddr_in. Direct access to address and port is still possible thanks to some \#define, so retrocompatibility of the existing code is assured.
The ss_family field of sockaddr_storage is declared after each socket creation.
The whole structure is also saved/restored when a Qemu session is saved/restored.
This prepares for IPv6 support.
--- slirp/ip_icmp.c | 2 ++ slirp/slirp.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- slirp/socket.c | 14 +++++++++++--- slirp/socket.h | 19 +++++++++++++++---- slirp/tcp_input.c | 2 ++ slirp/tcp_subr.c | 2 ++ slirp/udp.c | 4 ++++ 7 files changed, 78 insertions(+), 16 deletions(-)
slirp/ip_icmp.c +2 -0
@@ -170,8 +170,10 @@ icmp_input(struct mbuf *m, int hlen) goto end_error; } so->so_m = m; + so->so_ffamily =AF_INET ; so->so_faddr = ip->ip_dst; so->so_fport =htons (7 ); + so->so_lfamily =AF_INET ; so->so_laddr = ip->ip_src; so->so_lport =htons (9 ); so->so_iptos = ip->ip_tos;
slirp/slirp.c +42 -9
75 lines not on this page · raw message
slirp/socket.c +11 -3
@@ -437,8 +437,8 @@ sowrite(struct socket *so)void sorecvfrom (struct socket *so) { -struct sockaddr_in addr; -socklen_t addrlen =sizeof (struct sockaddr_in ); +struct sockaddr_storage addr; +socklen_t addrlen =sizeof (struct sockaddr_storage );DEBUG_CALL ("sorecvfrom" );DEBUG_ARG ("so = %p" , so);
@@ -527,7 +527,13 @@ sorecvfrom(struct socket *so)* If this packet was destined for CTL_ADDR, * make it look like that's where it came from, done by udp_output */ -udp_output (so, m, &addr); +switch (so->so_ffamily) { +case AF_INET : +udp_output (so, m, (struct sockaddr_in *) &addr); +break ; +default : +break ; + } }/* rx error */ }/* if ping packet */ }
@@ -619,6 +625,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, so->so_state &=SS_PERSISTENT_MASK ; so->so_state |= (SS_FACCEPTCONN | flags); + so->so_lfamily =AF_INET ; so->so_lport = lport;/* Kept in network format */ so->so_laddr.s_addr = laddr;/* Ditto */
@@ -645,6 +652,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,qemu_setsockopt (s,SOL_SOCKET ,SO_OOBINLINE , &opt,sizeof (int ));getsockname (s,(struct sockaddr *)&addr,&addrlen); + so->so_ffamily =AF_INET ; so->so_fport = addr.sin_port;if (addr.sin_addr.s_addr ==0 || addr.sin_addr.s_addr == loopback_addr.s_addr) so->so_faddr = slirp->vhost_addr;
slirp/socket.h +15 -4
@@ -31,10 +31,21 @@ struct socket {struct tcpiphdr *so_ti;/* Pointer to the original ti within * so_mconn, for non-blocking connections */ int so_urgc; -struct in_addr so_faddr;/* foreign host table entry */ -struct in_addr so_laddr;/* local host table entry */ -uint16_t so_fport;/* foreign port */ -uint16_t so_lport;/* local port */ +union {/* foreign host */ +struct sockaddr_storage ss; +struct sockaddr_in sin; + } fhost; +#define so_faddr fhost.sin.sin_addr +#define so_fport fhost.sin.sin_port +#define so_ffamily fhost.ss.ss_family + +union {/* local host */ +struct sockaddr_storage ss; +struct sockaddr_in sin; + } lhost; +#define so_laddr lhost.sin.sin_addr +#define so_lport lhost.sin.sin_port +#define so_lfamily lhost.ss.ss_familyuint8_t so_iptos;/* Type of service */ uint8_t so_emu;/* Is the socket emulated? */
slirp/tcp_input.c +2 -0
@@ -374,8 +374,10 @@ findso:sbreserve (&so->so_snd,TCP_SNDSPACE );sbreserve (&so->so_rcv,TCP_RCVSPACE ); + so->so_lfamily =AF_INET ; so->so_laddr = ti->ti_src; so->so_lport = ti->ti_sport; + so->so_ffamily =AF_INET ; so->so_faddr = ti->ti_dst; so->so_fport = ti->ti_dport;
slirp/tcp_subr.c +2 -0
@@ -413,6 +413,7 @@ void tcp_connect(struct socket *inso)free (so);/* NOT sofree */ return ; } + so->so_lfamily =AF_INET ; so->so_laddr = inso->so_laddr; so->so_lport = inso->so_lport; }
@@ -430,6 +431,7 @@ void tcp_connect(struct socket *inso)qemu_setsockopt (s,SOL_SOCKET ,SO_OOBINLINE , &opt,sizeof (int ));socket_set_nodelay (s); + so->so_ffamily =AF_INET ; so->so_fport = addr.sin_port; so->so_faddr = addr.sin_addr;/* Translate connections from localhost to the real hostname */
slirp/udp.c +4 -0
@@ -190,6 +190,7 @@ udp_input(register struct mbuf *m, int iphlen)/* * Setup fields */ + so->so_lfamily =AF_INET ; so->so_laddr = ip->ip_src; so->so_lport = uh->uh_sport;
@@ -202,6 +203,7 @@ udp_input(register struct mbuf *m, int iphlen)*/ } + so->so_ffamily =AF_INET ; so->so_faddr = ip->ip_dst;/* XXX */ so->so_fport = uh->uh_dport;/* XXX */
@@ -376,6 +378,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,socket_set_fast_reuse (so->s);getsockname (so->s,(struct sockaddr *)&addr,&addrlen); + so->so_ffamily =AF_INET ; so->so_fport = addr.sin_port;if (addr.sin_addr.s_addr ==0 || addr.sin_addr.s_addr == loopback_addr.s_addr) {
@@ -383,6 +386,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, }else { so->so_faddr = addr.sin_addr; } + so->so_lfamily =AF_INET ; so->so_lport = lport; so->so_laddr.s_addr = laddr;if (flags !=SS_FACCEPTONCE )
Signature · 1 line
2.6.2
PATCH 5/9 slirp: Factorizing address translation
In reply to Samuel ThibaultFrom: Guillaume Subiron <[email protected]>
This patch factorizes some duplicate code into a new function, sotranslate_out(). This function perform the address translation when a packet is transmitted to the host network. If the packet is destinated to the host, the loopback address is used, and if the packet is destinated to the virtual DNS, the real DNS address is used. This code is just a copy of the existent, but factorized and ready to manage the IPv6 case.
On the same model, the major part of udp_output() code is moved into a new sotranslate_in(). This function is directly used in sorecvfrom(), like sotranslate_out() in sosendto().udp_output() becoming useless, it is removed and udp_output2() is renamed into udp_output(). This adds consistency with the udp6_output() function introduced by further patches.
Lastly, this factorizes some duplicate code into sotranslate_accept(), which performs the address translation when a connection is established on the host for port forwarding: if it comes from localhost, the host virtual address is used instead.
This prepares for IPv6 support.
--- slirp/bootp.c | 2 +- slirp/ip_icmp.c | 19 ++-------- slirp/socket.c | 112 +++++++++++++++++++++++++++++++++++++++++++++---------- slirp/socket.h | 5 +++ slirp/tcp_subr.c | 35 ++++------------- slirp/tftp.c | 6 +-- slirp/udp.c | 37 ++---------------- slirp/udp.h | 3 +- 8 files changed, 116 insertions(+), 103 deletions(-)
slirp/bootp.c +1 -1
@@ -325,7 +325,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) m->m_len =sizeof (struct bootp_t ) -sizeof (struct ip ) -sizeof (struct udphdr ); -udp_output2 (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY ); +udp_output (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY ); }void bootp_input (struct mbuf *m)
slirp/ip_icmp.c +4 -15
@@ -157,7 +157,7 @@ icmp_input(struct mbuf *m, int hlen) goto freeit; }else {struct socket *so; -struct sockaddr_in addr; +struct sockaddr_storage addr;if ((so =socreate (slirp)) ==NULL ) goto freeit;if (icmp_send (so, m, hlen) ==0 ) {return ;
@@ -181,20 +181,9 @@ icmp_input(struct mbuf *m, int hlen) so->so_state =SS_ISFCONNECTED ;/* Send the packet */ - addr.sin_family =AF_INET ; -if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { -/* It's an alias */ -if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { -if (get_dns_addr (&addr.sin_addr) <0 ) - addr.sin_addr = loopback_addr; - }else { - addr.sin_addr = loopback_addr; - } - }else { - addr.sin_addr = so->so_faddr; - } - addr.sin_port = so->so_fport; + addr = so->fhost.ss; +sotranslate_out (so, &addr); +if (sendto (so->s, icmp_ping_msg,strlen (icmp_ping_msg),0 , (struct sockaddr *)&addr,sizeof (addr)) ==-1 ) { DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
slirp/socket.c +92 -20
145 lines not on this page · raw message
slirp/socket.h +5 -0
@@ -105,4 +105,9 @@ struct iovec; /* For win32 */size_t sopreprbuf (struct socket *so,struct iovec *iov,int *np);int soreadbuf (struct socket *so,const char *buf,int size); +void sotranslate_out (struct socket *,struct sockaddr_storage *); +void sotranslate_in (struct socket *,struct sockaddr_storage *); +void sotranslate_accept (struct socket *); + +#endif /* _SOCKET_H_ */
slirp/tcp_subr.c +7 -28
@@ -326,7 +326,6 @@ tcp_sockclosed(struct tcpcb *tp)*/ int tcp_fconnect (struct socket *so) { -Slirp *slirp = so->slirp;int ret=0 ;DEBUG_CALL ("tcp_fconnect" );
@@ -334,30 +333,17 @@ int tcp_fconnect(struct socket *so)if ( (ret = so->s =qemu_socket (AF_INET ,SOCK_STREAM ,0 )) >=0 ) {int opt, s=so->s; -struct sockaddr_in addr; +struct sockaddr_storage addr;qemu_set_nonblock (s);socket_set_fast_reuse (s); opt =1 ;qemu_setsockopt (s,SOL_SOCKET ,SO_OOBINLINE , &opt,sizeof (opt)); - addr.sin_family =AF_INET ; -if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { -/* It's an alias */ -if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { -if (get_dns_addr (&addr.sin_addr) <0 ) - addr.sin_addr = loopback_addr; - }else { - addr.sin_addr = loopback_addr; - } - }else - addr.sin_addr = so->so_faddr; - addr.sin_port = so->so_fport; - -DEBUG_MISC ((dfd," connect()ing, addr.sin_port=%d, " -"addr.sin_addr.s_addr=%.16s\n" , -ntohs (addr.sin_port),inet_ntoa (addr.sin_addr))); + addr = so->fhost.ss; + DEBUG_CALL(" connect()ing") +sotranslate_out (so, &addr); +/* We don't care what port we get */ ret =connect (s,(struct sockaddr *)&addr,sizeof (addr));
@@ -431,15 +417,8 @@ void tcp_connect(struct socket *inso)qemu_setsockopt (s,SOL_SOCKET ,SO_OOBINLINE , &opt,sizeof (int ));socket_set_nodelay (s); - so->so_ffamily =AF_INET ; - so->so_fport = addr.sin_port; - so->so_faddr = addr.sin_addr; -/* Translate connections from localhost to the real hostname */ -if (so->so_faddr.s_addr ==0 || - (so->so_faddr.s_addr & loopback_mask) == - (loopback_addr.s_addr & loopback_mask)) { - so->so_faddr = slirp->vhost_addr; - } + so->fhost.sin = addr; +sotranslate_accept (so);/* Close the accept() socket, set right state */ if (inso->so_state &SS_FACCEPTONCE ) {
slirp/tftp.c +3 -3
@@ -155,7 +155,7 @@ static int tftp_send_oack(struct tftp_session *spt, m->m_len =sizeof (struct tftp_t ) -514 + n -sizeof (struct ip ) -sizeof (struct udphdr ); -udp_output2 (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY ); +udp_output (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY );return 0 ; }
@@ -193,7 +193,7 @@ static void tftp_send_error(struct tftp_session *spt, m->m_len =sizeof (struct tftp_t ) -514 +3 +strlen (msg) -sizeof (struct ip ) -sizeof (struct udphdr ); -udp_output2 (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY ); +udp_output (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY ); out:tftp_session_terminate (spt);
@@ -243,7 +243,7 @@ static void tftp_send_next_block(struct tftp_session *spt, m->m_len =sizeof (struct tftp_t ) - (512 - nobytes) -sizeof (struct ip ) -sizeof (struct udphdr ); -udp_output2 (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY ); +udp_output (NULL , m, &saddr, &daddr,IPTOS_LOWDELAY );if (nobytes ==512 ) {tftp_session_update (spt);
slirp/udp.c +3 -34
@@ -236,7 +236,7 @@ bad:m_free (m); } -int udp_output2 (struct socket *so,struct mbuf *m, +int udp_output (struct socket *so,struct mbuf *m,struct sockaddr_in *saddr,struct sockaddr_in *daddr,int iptos) {
@@ -287,31 +287,6 @@ int udp_output2(struct socket *so, struct mbuf *m,return (error); } -int udp_output (struct socket *so,struct mbuf *m, -struct sockaddr_in *addr) - -{ -Slirp *slirp = so->slirp; -struct sockaddr_in saddr, daddr; - - saddr = *addr; -if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { -uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; - -if ((so->so_faddr.s_addr & inv_mask) == inv_mask) { - saddr.sin_addr = slirp->vhost_addr; - }else if (addr->sin_addr.s_addr == loopback_addr.s_addr || - so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { - saddr.sin_addr = so->so_faddr; - } - } - daddr.sin_addr = so->so_laddr; - daddr.sin_port = so->so_lport; - -return udp_output2 (so, m, &saddr, &daddr, so->so_iptos); -} -int udp_attach (struct socket *so) {
@@ -378,14 +353,8 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,socket_set_fast_reuse (so->s);getsockname (so->s,(struct sockaddr *)&addr,&addrlen); - so->so_ffamily =AF_INET ; - so->so_fport = addr.sin_port; -if (addr.sin_addr.s_addr ==0 || - addr.sin_addr.s_addr == loopback_addr.s_addr) { - so->so_faddr = slirp->vhost_addr; - }else { - so->so_faddr = addr.sin_addr; - } + so->fhost.sin = addr; +sotranslate_accept (so); so->so_lfamily =AF_INET ; so->so_lport = lport; so->so_laddr.s_addr = laddr;
slirp/udp.h +1 -2
@@ -76,12 +76,11 @@ struct mbuf;void udp_init (Slirp *);void udp_cleanup (Slirp *);void udp_input (registerstruct mbuf *,int ); -int udp_output (struct socket *,struct mbuf *,struct sockaddr_in *);int udp_attach (struct socket *);void udp_detach (struct socket *);struct socket *udp_listen (Slirp *,uint32_t ,u_int ,uint32_t ,u_int ,int ); -int udp_output2 (struct socket *so,struct mbuf *m, +int udp_output (struct socket *so,struct mbuf *m,struct sockaddr_in *saddr,struct sockaddr_in *daddr,int iptos);#endif
Signature · 1 line
2.6.2
PATCH 6/9 slirp: Factorizing and cleaning solookup()
In reply to Samuel ThibaultFrom: Guillaume Subiron <[email protected]>
solookup() was only compatible with TCP. Having the socket list in argument, it is now compatible with UDP too.
Some optimization code is factorized inside the function (the function look at the last returned result before browsing the complete socket list).
This prepares for IPv6 support.
--- slirp/socket.c | 37 ++++++++++++++++++++++++------------- slirp/socket.h | 5 +++-- slirp/tcp_input.c | 13 +++---------- slirp/udp.c | 21 ++------------------- 4 files changed, 32 insertions(+), 44 deletions(-)
slirp/socket.c +24 -13
@@ -16,23 +16,34 @@ static void sofcantrcvmore(struct socket *so);static void sofcantsendmore (struct socket *so);struct socket * -solookup (struct socket *head,struct in_addr laddr,u_int lport, +solookup (struct socket **last,struct socket *head, +struct in_addr laddr,u_int lport,struct in_addr faddr,u_int fport) { -struct socket *so; - -for (so = head->so_next; so != head; so = so->so_next) { -if (so->so_lport == lport && - so->so_laddr.s_addr == laddr.s_addr && - so->so_faddr.s_addr == faddr.s_addr && - so->so_fport == fport) -break ; - } +struct socket *so = *last; + +/* Optimisation */ +if (so != head && + so->so_lport == lport && + so->so_laddr.s_addr == laddr.s_addr && + (!faddr.s_addr || + (so->so_faddr.s_addr == faddr.s_addr && + so->so_fport == fport))) { +return so; + } -if (so == head) -return (struct socket *)NULL ; -return so; +for (so = head->so_next; so != head; so = so->so_next) { +if (so->so_lport == lport && + so->so_laddr.s_addr == laddr.s_addr && + (!faddr.s_addr || + (so->so_faddr.s_addr == faddr.s_addr && + so->so_fport == fport))) { + *last = so; +return so; + } + } +return (struct socket *)NULL ; }/*
slirp/socket.h +3 -2
@@ -87,8 +87,9 @@ struct socket {#define SS_HOSTFWD 0x1000/* Socket describes host->guest forwarding */ #define SS_INCOMING 0x2000/* Connection was initiated by a host on the internet */ -struct socket *solookup (struct socket *,struct in_addr ,u_int ,struct in_addr ,u_int ); -struct socket *socreate (Slirp *); +struct socket *solookup (struct socket **,struct socket *, +struct in_addr ,u_int ,struct in_addr ,u_int ); +struct socket *socreate (Slirp *);void sofree (struct socket *);int soread (struct socket *);void sorecvoob (struct socket *);
slirp/tcp_input.c +3 -10
@@ -320,16 +320,9 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)* Locate pcb for segment. */ findso: - so = slirp->tcp_last_so; -if (so->so_fport != ti->ti_dport || - so->so_lport != ti->ti_sport || - so->so_laddr.s_addr != ti->ti_src.s_addr || - so->so_faddr.s_addr != ti->ti_dst.s_addr) { - so =solookup (&slirp->tcb, ti->ti_src, ti->ti_sport, - ti->ti_dst, ti->ti_dport); -if (so) - slirp->tcp_last_so = so; - } + so =solookup (&slirp->tcp_last_so, &slirp->tcb, + ti->ti_src, ti->ti_sport, + ti->ti_dst, ti->ti_dport);/* * If the state is CLOSED (i.e., TCB does not exist) then
slirp/udp.c +2 -19
@@ -151,25 +151,8 @@ udp_input(register struct mbuf *m, int iphlen)/* * Locate pcb for datagram. */ - so = slirp->udp_last_so; -if (so == &slirp->udb || so->so_lport != uh->uh_sport || - so->so_laddr.s_addr != ip->ip_src.s_addr) { -struct socket *tmp; - -for (tmp = slirp->udb.so_next; tmp != &slirp->udb; - tmp = tmp->so_next) { -if (tmp->so_lport == uh->uh_sport && - tmp->so_laddr.s_addr == ip->ip_src.s_addr) { - so = tmp; -break ; - } - } -if (tmp == &slirp->udb) { - so =NULL ; - }else { - slirp->udp_last_so = so; - } - } + so =solookup (&slirp->udp_last_so, &slirp->udb, + ip->ip_src, uh->uh_sport, (struct in_addr ) {0 },0 );if (so ==NULL ) {/*
Signature · 1 line
2.6.2
PATCH 7/9 slirp: Add sockaddr_equal, make solookup family-agnostic
In reply to Samuel ThibaultFrom: Guillaume Subiron <[email protected]>
This patch makes solookup() compatible with varying address families, by using a new sockaddr_equal() function that compares two sockaddr_storage.
This prepares for IPv6 support.
--- slirp/socket.c | 21 ++++++--------------- slirp/socket.h | 22 +++++++++++++++++++++- slirp/tcp_input.c | 23 ++++++++++++++--------- slirp/udp.c | 10 ++++++++-- 4 files changed, 49 insertions(+), 27 deletions(-)
slirp/socket.c +6 -15
@@ -15,29 +15,20 @@static void sofcantrcvmore (struct socket *so);static void sofcantsendmore (struct socket *so); -struct socket * -solookup (struct socket **last,struct socket *head, -struct in_addr laddr,u_int lport, -struct in_addr faddr,u_int fport) +struct socket *solookup (struct socket **last,struct socket *head, +struct sockaddr_storage *lhost,struct sockaddr_storage *fhost) {struct socket *so = *last;/* Optimisation */ -if (so != head && - so->so_lport == lport && - so->so_laddr.s_addr == laddr.s_addr && - (!faddr.s_addr || - (so->so_faddr.s_addr == faddr.s_addr && - so->so_fport == fport))) { +if (so != head &&sockaddr_equal (&(so->lhost.ss), lhost) + && (!fhost ||sockaddr_equal (&so->fhost.ss, fhost))) {return so; }for (so = head->so_next; so != head; so = so->so_next) { -if (so->so_lport == lport && - so->so_laddr.s_addr == laddr.s_addr && - (!faddr.s_addr || - (so->so_faddr.s_addr == faddr.s_addr && - so->so_fport == fport))) { +if (sockaddr_equal (&(so->lhost.ss), lhost) + && (!fhost ||sockaddr_equal (&so->fhost.ss, fhost))) { *last = so;return so; }
slirp/socket.h +21 -1
@@ -87,8 +87,28 @@ struct socket {#define SS_HOSTFWD 0x1000/* Socket describes host->guest forwarding */ #define SS_INCOMING 0x2000/* Connection was initiated by a host on the internet */ +static inline int sockaddr_equal (struct sockaddr_storage *a, +struct sockaddr_storage *b) +{ +if (a->ss_family != b->ss_family) { +return 0 ; + } + +switch (a->ss_family) { +case AF_INET : + { +struct sockaddr_in *a4 = (struct sockaddr_in *) a; +struct sockaddr_in *b4 = (struct sockaddr_in *) b; +return a4->sin_addr.s_addr == b4->sin_addr.s_addr + && a4->sin_port == b4->sin_port; + } +default : +assert (0 ); + } +} +struct socket *solookup (struct socket **,struct socket *, -struct in_addr ,u_int ,struct in_addr ,u_int ); +struct sockaddr_storage *,struct sockaddr_storage *);struct socket *socreate (Slirp *);void sofree (struct socket *);int soread (struct socket *);
slirp/tcp_input.c +14 -9
@@ -227,6 +227,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)int iss =0 ;u_long tiwin;int ret; +struct sockaddr_storage lhost, fhost; +struct sockaddr_in *lhost4, *fhost4;struct ex_list *ex_ptr;Slirp *slirp;
@@ -320,9 +322,16 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)* Locate pcb for segment. */ findso: - so =solookup (&slirp->tcp_last_so, &slirp->tcb, - ti->ti_src, ti->ti_sport, - ti->ti_dst, ti->ti_dport); + lhost.ss_family =AF_INET ; + lhost4 = (struct sockaddr_in *) &lhost; + lhost4->sin_addr = ti->ti_src; + lhost4->sin_port = ti->ti_sport; + fhost.ss_family =AF_INET ; + fhost4 = (struct sockaddr_in *) &fhost; + fhost4->sin_addr = ti->ti_dst; + fhost4->sin_port = ti->ti_dport; + + so =solookup (&slirp->tcp_last_so, &slirp->tcb, &lhost, &fhost);/* * If the state is CLOSED (i.e., TCB does not exist) then
@@ -367,12 +376,8 @@ findso:sbreserve (&so->so_snd,TCP_SNDSPACE );sbreserve (&so->so_rcv,TCP_RCVSPACE ); - so->so_lfamily =AF_INET ; - so->so_laddr = ti->ti_src; - so->so_lport = ti->ti_sport; - so->so_ffamily =AF_INET ; - so->so_faddr = ti->ti_dst; - so->so_fport = ti->ti_dport; + so->lhost.ss = lhost; + so->fhost.ss = fhost;if ((so->so_iptos =tcp_tos (so)) ==0 ) so->so_iptos = ((struct ip *)ti)->ip_tos;
slirp/udp.c +8 -2
@@ -70,6 +70,8 @@ udp_input(register struct mbuf *m, int iphlen)int len;struct ip save_ip;struct socket *so; +struct sockaddr_storage lhost; +struct sockaddr_in *lhost4;DEBUG_CALL ("udp_input" );DEBUG_ARG ("m = %p" , m);
@@ -151,8 +153,12 @@ udp_input(register struct mbuf *m, int iphlen)/* * Locate pcb for datagram. */ - so =solookup (&slirp->udp_last_so, &slirp->udb, - ip->ip_src, uh->uh_sport, (struct in_addr ) {0 },0 ); + lhost.ss_family =AF_INET ; + lhost4 = (struct sockaddr_in *) &lhost; + lhost4->sin_addr = ip->ip_src; + lhost4->sin_port = uh->uh_sport; + + so =solookup (&slirp->udp_last_so, &slirp->udb, &lhost,NULL );if (so ==NULL ) {/*
Signature · 1 line
2.6.2
PATCH 8/9 slirp: Make udp_attach IPv6 compatible
In reply to Samuel ThibaultFrom: Guillaume Subiron <[email protected]>
A sa_family_t is now passed in argument to udp_attach instead of using a hardcoded "AF_INET" to call qemu_socket().
This prepares for IPv6 support.
--- slirp/ip_icmp.c | 2 +- slirp/udp.c | 7 ++++--- slirp/udp.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-)
slirp/ip_icmp.c +1 -1
@@ -162,7 +162,7 @@ icmp_input(struct mbuf *m, int hlen)if (icmp_send (so, m, hlen) ==0 ) {return ; } -if (udp_attach (so) ==-1 ) { +if (udp_attach (so,AF_INET ) ==-1 ) {DEBUG_MISC ((dfd,"icmp_input udp_attach errno = %d-%s\n" , errno,strerror (errno)));sofree (so);
slirp/udp.c +4 -3
@@ -169,7 +169,7 @@ udp_input(register struct mbuf *m, int iphlen)if (!so) { goto bad; } -if (udp_attach (so) ==-1 ) { +if (udp_attach (so,AF_INET ) ==-1 ) {DEBUG_MISC ((dfd," udp_attach errno = %d-%s\n" , errno,strerror (errno)));sofree (so);
@@ -277,9 +277,10 @@ int udp_output(struct socket *so, struct mbuf *m, }int -udp_attach (struct socket *so) +udp_attach (struct socket *so,sa_family_t af) { -if ((so->s =qemu_socket (AF_INET ,SOCK_DGRAM ,0 )) !=-1 ) { + so->s =qemu_socket (af,SOCK_DGRAM ,0 ); +if (so->s !=-1 ) { so->so_expire = curtime +SO_EXPIRE ;insque (so, &so->slirp->udb); }
slirp/udp.h +1 -1
@@ -76,7 +76,7 @@ struct mbuf;void udp_init (Slirp *);void udp_cleanup (Slirp *);void udp_input (registerstruct mbuf *,int ); -int udp_attach (struct socket *); +int udp_attach (struct socket *,sa_family_t af);void udp_detach (struct socket *);struct socket *udp_listen (Slirp *,uint32_t ,u_int ,uint32_t ,u_int ,int );
Signature · 1 line
2.6.2
PATCH 9/9 slirp: Adding family argument to tcp_fconnect()
In reply to Samuel ThibaultFrom: Guillaume Subiron <[email protected]>
This patch simply adds a sa_family_t argument to remove the hardcoded "AF_INET" in the call of qemu_socket().
This prepares for IPv6 support.
--- slirp/slirp.h | 2 +- slirp/tcp_input.c | 2 +- slirp/tcp_subr.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-)
slirp/slirp.h +1 -1
@@ -332,7 +332,7 @@ void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbustruct tcpcb *tcp_newtcpcb (struct socket *);struct tcpcb *tcp_close (registerstruct tcpcb *);void tcp_sockclosed (struct tcpcb *); -int tcp_fconnect (struct socket *); +int tcp_fconnect (struct socket *,sa_family_t af);void tcp_connect (struct socket *);int tcp_attach (struct socket *);uint8_t tcp_tos (struct socket *);
slirp/tcp_input.c +1 -1
@@ -584,7 +584,7 @@ findso: goto cont_input; } -if ((tcp_fconnect (so) ==-1 ) && +if ((tcp_fconnect (so, so->so_ffamily) ==-1 ) && #if defined(_WIN32)socket_error () !=WSAEWOULDBLOCK #else
slirp/tcp_subr.c +3 -2
@@ -324,14 +324,15 @@ tcp_sockclosed(struct tcpcb *tp)* nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ -int tcp_fconnect (struct socket *so) +int tcp_fconnect (struct socket *so,sa_family_t af) {int ret=0 ;DEBUG_CALL ("tcp_fconnect" );DEBUG_ARG ("so = %p" , so); -if ( (ret = so->s =qemu_socket (AF_INET ,SOCK_STREAM ,0 )) >=0 ) { + ret = so->s =qemu_socket (af,SOCK_STREAM ,0 ); +if (ret >=0 ) {int opt, s=so->s;struct sockaddr_storage addr;
Signature · 1 line
2.6.2
Quoted 1 line · Samuel Thibault
Hello,
meta-reply
Quoted 7 lines
This is another respin of IPv6 in Qemu -net user mode.
The following patches first make some refactoring to make current code ready for IPv6, and do not change the behavior. The actual IPv6 support will then be submitted as a separate patch series.
Quoted 6 lines
Difference with version 6 is:
- Useerror_reportinstead of printing to stderr
- Drop extra parentheses
- Use nicer-looking sockaddr casts.All of this has been reviewed by Thomas Huth, thanks!
It looks like you wrote your own cover letter, then supplied the git series in reply to your cover letter but with the git series still internally threaded. This resulted in the unusual reply tree of:
0/9
+ 1/9
+ 2/9
+ 3/9
+ ...
+ 9/9
and where clients that display trees based both on reply relationships and age would show:
0/9
+ 1/9
+ 2/9
| + Re: 2/9
+ ...
+ 9/9
| + Re: 9/9
+ Re: 1/9
That is, in your series, all of 2 through 9 were marked as children of 1, rather than a sibling of 1. The more typical flat threading looks like:
0/9
+ 1/9
+ 2/9
+ ...
+ 9/9
where replies to 1 are then threaded closer to the original:
0/9
+ 1/9
| + Re: 1/9
+ 2/9
| + Re: 2/9
+ ...
+ 9/9
+ Re: 9/9
You may want to look into using 'git format-patch --cover-letter'; easily done with 'git config format.coverLetter auto'. The git cover letter would include a diffstat that includes the names of all files touched by the series as well as relative sizing of the patch, which is helpful to users. Also, using git to produce the cover letter (producing all of 0 through 9 in one shot, with 1-9 all threaded as siblings to each other and children of 0), instead of producing the body with git (just 1 through 9, with 2-9 replying to 1) and then chaining that series to a hand-written cover letter, would solve the unusual threading.
Quoted 14 lines
Here is a summary of the patches:
[PATCH 1/9] slirp: goto bad in
udp_inputif sosendto fails [PATCH 2/9] slirp: Generalizing and neutralizing ARP code [PATCH 3/9] slirp: Adding address family switch for incoming frames [PATCH 4/9] slirp: Make Socket structure IPv6 compatible [PATCH 5/9] slirp: Factorizing address translation
[PATCH 6/9] slirp: Factorizing and cleaningsolookup()[PATCH 7/9] slirp: Addsockaddr_equal, make solookup family-agnostic [PATCH 8/9] slirp: Makeudp_attachIPv6 compatible
[PATCH 9/9] slirp: Adding family argument totcp_fconnect()
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Hello,
Quoted 5 lines · Samuel Thibault, on Sat 19 Dec 2015 22:24:40 +0100, wrote:
This is another respin of IPv6 in Qemu -net user mode.
The following patches first make some refactoring to make current code ready for IPv6, and do not change the behavior. The actual IPv6 support will then be submitted as a separate patch series.
Ping?
The whole series has been reviewed, it just needs a commit (for which I don't have access).
Samuel
Quoted 18 lines
Difference with version 6 is:
- Useerror_reportinstead of printing to stderr
- Drop extra parentheses
- Use nicer-looking sockaddr casts.All of this has been reviewed by Thomas Huth, thanks!
Here is a summary of the patches:
[PATCH 1/9] slirp: goto bad in
udp_inputif sosendto fails [PATCH 2/9] slirp: Generalizing and neutralizing ARP code [PATCH 3/9] slirp: Adding address family switch for incoming frames [PATCH 4/9] slirp: Make Socket structure IPv6 compatible [PATCH 5/9] slirp: Factorizing address translation
[PATCH 6/9] slirp: Factorizing and cleaningsolookup()[PATCH 7/9] slirp: Addsockaddr_equal, make solookup family-agnostic [PATCH 8/9] slirp: Makeudp_attachIPv6 compatible
[PATCH 9/9] slirp: Adding family argument totcp_fconnect()
Hi,
It seems that, Jan Kiszka is maintaining SLIRP (From MAINTAINERS file), Maybe he could make a help to merge this series.
TO: J. Kiszka <[email protected]>
Thanks,
Hailiang
Quoted 37 lines · Samuel Thibault
Hello,
Quoted 5 lines · Samuel Thibault, on Sat 19 Dec 2015 22:24:40 +0100, wrote:
This is another respin of IPv6 in Qemu -net user mode.
The following patches first make some refactoring to make current code ready for IPv6, and do not change the behavior. The actual IPv6 support will then be submitted as a separate patch series.
Ping?
The whole series has been reviewed, it just needs a commit (for which I don't have access).
Samuel
Quoted 9 lines
Difference with version 6 is:
- Useerror_reportinstead of printing to stderr
- Drop extra parentheses
- Use nicer-looking sockaddr casts.All of this has been reviewed by Thomas Huth, thanks!
Here is a summary of the patches:
Quoted 9 lines
[PATCH 1/9] slirp: goto bad in
udp_inputif sosendto fails [PATCH 2/9] slirp: Generalizing and neutralizing ARP code [PATCH 3/9] slirp: Adding address family switch for incoming frames [PATCH 4/9] slirp: Make Socket structure IPv6 compatible [PATCH 5/9] slirp: Factorizing address translation
[PATCH 6/9] slirp: Factorizing and cleaningsolookup()[PATCH 7/9] slirp: Addsockaddr_equal, make solookup family-agnostic [PATCH 8/9] slirp: Makeudp_attachIPv6 compatible
[PATCH 9/9] slirp: Adding family argument totcp_fconnect().
Quoted 9 lines · Hailiang Zhang
Hi,
It seems that, Jan Kiszka is maintaining SLIRP (From
MAINTAINERSfile), Maybe he could make a help to merge this series.TO: J. Kiszka <[email protected]>
Thanks,
Hailiang
Right, and I can take this series in my tree if Jan doesn't have time to do this.
Quoted 44 lines · Samuel Thibault
Quoted 39 lines
Hello,
Quoted 7 lines · Samuel Thibault, on Sat 19 Dec 2015 22:24:40 +0100, wrote:
This is another respin of IPv6 in Qemu -net user mode.
The following patches first make some refactoring to make current code ready
for IPv6, and do not change the behavior. The actual IPv6 support will then be
submitted as a separate patch series.Ping?
The whole series has been reviewed, it just needs a commit (for which I don't have access).
Samuel
Quoted 9 lines
Difference with version 6 is:
- Useerror_reportinstead of printing to stderr
- Drop extra parentheses
- Use nicer-looking sockaddr casts.All of this has been reviewed by Thomas Huth, thanks!
Here is a summary of the patches:
Quoted 9 lines
[PATCH 1/9] slirp: goto bad in
udp_inputif sosendto fails [PATCH 2/9] slirp: Generalizing and neutralizing ARP code [PATCH 3/9] slirp: Adding address family switch for incoming frames [PATCH 4/9] slirp: Make Socket structure IPv6 compatible [PATCH 5/9] slirp: Factorizing address translation
[PATCH 6/9] slirp: Factorizing and cleaningsolookup()[PATCH 7/9] slirp: Addsockaddr_equal, make solookup family-agnostic [PATCH 8/9] slirp: Makeudp_attachIPv6 compatible
[PATCH 9/9] slirp: Adding family argument totcp_fconnect().
Quoted 6 lines · Jason Wang
Quoted 5 lines · Hailiang Zhang
Quoted 5 lines
Hi,
It seems that, Jan Kiszka is maintaining SLIRP (From
MAINTAINERSfile), Maybe he could make a help to merge this series.
Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
TO: J. Kiszka <[email protected]>
Thanks,
HailiangRight, and I can take this series in my tree if Jan doesn't have time to do this.
Ok, apply to my -net.
Thanks