diff mbox

[06/18] slirp: Factorizing and cleaning solookup()

Message ID 20151211200241.GO2764@var.home
State New
Headers show

Commit Message

Samuel Thibault Dec. 11, 2015, 8:02 p.m. UTC
Samuel Thibault, on Fri 11 Dec 2015 20:51:02 +0100, wrote:
> Samuel Thibault, on Fri 11 Dec 2015 20:38:19 +0100, wrote:
> > I'll however have a look at introducing the optimizations etc. first, so
> > that both making solookup use sockaddr and introducing sockaddr_equal
> > looks natural.
> 
> Yes, it seems to be working very nicely.

Just FYI, here is how it looks like now.

Samuel

diff --git a/slirp/socket.c b/slirp/socket.c
index 6382b6d..a4db442 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -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;
         }
diff --git a/slirp/socket.h b/slirp/socket.h
index 3077581..8a23125 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -87,8 +87,27 @@ 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 socket *,
-        struct in_addr, u_int, struct in_addr, u_int);
+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 sockaddr_storage *, struct sockaddr_storage *);
 struct socket * socreate(Slirp *);
 void sofree(struct socket *);
 int soread(struct socket *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 5492061..8c4fa62 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -227,6 +227,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	int iss = 0;
 	u_long tiwin;
 	int ret;
+	struct sockaddr_storage lhost, fhost;
     struct ex_list *ex_ptr;
     Slirp *slirp;
 
@@ -320,9 +321,14 @@ 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;
+	((struct sockaddr_in *)&lhost)->sin_addr = ti->ti_src;
+	((struct sockaddr_in *)&lhost)->sin_port = ti->ti_sport;
+	fhost.ss_family = AF_INET;
+	((struct sockaddr_in *)&fhost)->sin_addr = ti->ti_dst;
+	((struct sockaddr_in *)&fhost)->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 +373,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;
diff --git a/slirp/udp.c b/slirp/udp.c
index 126ef82..f2dd773 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -70,6 +70,7 @@ udp_input(register struct mbuf *m, int iphlen)
 	int len;
 	struct ip save_ip;
 	struct socket *so;
+	struct sockaddr_storage lhost;
 
 	DEBUG_CALL("udp_input");
 	DEBUG_ARG("m = %p", m);
@@ -151,8 +152,11 @@ 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;
+	((struct sockaddr_in *)&lhost)->sin_addr = ip->ip_src;
+	((struct sockaddr_in *)&lhost)->sin_port = uh->uh_sport;
+
+	so = solookup(&slirp->udp_last_so, &slirp->udb, &lhost, NULL);
 
 	if (so == NULL) {
 	  /*
diff mbox

Patch

diff --git a/slirp/socket.c b/slirp/socket.c
index 97948e8..6382b6d 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -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;
 }
 
 /*
diff --git a/slirp/socket.h b/slirp/socket.h
index b27bbb2..3077581 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -87,7 +87,8 @@  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 * 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 *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 4c3191d..5492061 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -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
diff --git a/slirp/udp.c b/slirp/udp.c
index 8203eb1..126ef82 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -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) {
 	  /*