summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--slirp/socket.c37
-rw-r--r--slirp/socket.h5
-rw-r--r--slirp/tcp_input.c13
-rw-r--r--slirp/udp.c21
4 files changed, 32 insertions, 44 deletions
diff --git a/slirp/socket.c b/slirp/socket.c
index d1034fb536..8f73e906e2 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 b27bbb2c59..1c8c24c16b 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -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 *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 4c3191d4fd..549206150c 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 8203eb1bb2..126ef82a8e 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) {
 	  /*