slirp: Make Socket structure IPv6 compatible
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. Signed-off-by: Guillaume Subiron <maethor@subiron.org> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
		
							parent
							
								
									18137fba35
								
							
						
					
					
						commit
						eae303ff23
					
				| @ -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; | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
|  */ | ||||
| #include "qemu-common.h" | ||||
| #include "qemu/timer.h" | ||||
| #include "qemu/error-report.h" | ||||
| #include "sysemu/char.h" | ||||
| #include "slirp.h" | ||||
| #include "hw/hw.h" | ||||
| @ -234,7 +235,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, | ||||
| 
 | ||||
|     slirp->opaque = opaque; | ||||
| 
 | ||||
|     register_savevm(NULL, "slirp", 0, 3, | ||||
|     register_savevm(NULL, "slirp", 0, 4, | ||||
|                     slirp_state_save, slirp_state_load, slirp); | ||||
| 
 | ||||
|     QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry); | ||||
| @ -1046,10 +1047,26 @@ static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf) | ||||
| static void slirp_socket_save(QEMUFile *f, struct socket *so) | ||||
| { | ||||
|     qemu_put_be32(f, so->so_urgc); | ||||
|     qemu_put_be32(f, so->so_faddr.s_addr); | ||||
|     qemu_put_be32(f, so->so_laddr.s_addr); | ||||
|     qemu_put_be16(f, so->so_fport); | ||||
|     qemu_put_be16(f, so->so_lport); | ||||
|     qemu_put_be16(f, so->so_ffamily); | ||||
|     switch (so->so_ffamily) { | ||||
|     case AF_INET: | ||||
|         qemu_put_be32(f, so->so_faddr.s_addr); | ||||
|         qemu_put_be16(f, so->so_fport); | ||||
|         break; | ||||
|     default: | ||||
|         error_report( | ||||
|                 "so_ffamily unknown, unable to save so_faddr and so_fport\n"); | ||||
|     } | ||||
|     qemu_put_be16(f, so->so_lfamily); | ||||
|     switch (so->so_lfamily) { | ||||
|     case AF_INET: | ||||
|         qemu_put_be32(f, so->so_laddr.s_addr); | ||||
|         qemu_put_be16(f, so->so_lport); | ||||
|         break; | ||||
|     default: | ||||
|         error_report( | ||||
|                 "so_ffamily unknown, unable to save so_laddr and so_lport\n"); | ||||
|     } | ||||
|     qemu_put_byte(f, so->so_iptos); | ||||
|     qemu_put_byte(f, so->so_emu); | ||||
|     qemu_put_byte(f, so->so_type); | ||||
| @ -1169,10 +1186,26 @@ static int slirp_socket_load(QEMUFile *f, struct socket *so) | ||||
|         return -ENOMEM; | ||||
| 
 | ||||
|     so->so_urgc = qemu_get_be32(f); | ||||
|     so->so_faddr.s_addr = qemu_get_be32(f); | ||||
|     so->so_laddr.s_addr = qemu_get_be32(f); | ||||
|     so->so_fport = qemu_get_be16(f); | ||||
|     so->so_lport = qemu_get_be16(f); | ||||
|     so->so_ffamily = qemu_get_be16(f); | ||||
|     switch (so->so_ffamily) { | ||||
|     case AF_INET: | ||||
|         so->so_faddr.s_addr = qemu_get_be32(f); | ||||
|         so->so_fport = qemu_get_be16(f); | ||||
|         break; | ||||
|     default: | ||||
|         error_report( | ||||
|                 "so_ffamily unknown, unable to restore so_faddr and so_lport\n"); | ||||
|     } | ||||
|     so->so_lfamily = qemu_get_be16(f); | ||||
|     switch (so->so_lfamily) { | ||||
|     case AF_INET: | ||||
|         so->so_laddr.s_addr = qemu_get_be32(f); | ||||
|         so->so_lport = qemu_get_be16(f); | ||||
|         break; | ||||
|     default: | ||||
|         error_report( | ||||
|                 "so_ffamily unknown, unable to restore so_laddr and so_lport\n"); | ||||
|     } | ||||
|     so->so_iptos = qemu_get_byte(f); | ||||
|     so->so_emu = qemu_get_byte(f); | ||||
|     so->so_type = qemu_get_byte(f); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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_family | ||||
| 
 | ||||
|   uint8_t	so_iptos;	/* Type of service */ | ||||
|   uint8_t	so_emu;		/* Is the socket emulated? */ | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Guillaume Subiron
						Guillaume Subiron