summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-12-30 23:05:52 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2010-12-30 23:05:52 (GMT)
commit96a65558a1b5a7bd3c4061ad64b1670b5def3f3b (patch)
treeefbe370f47c06e449c9fb81fc3fb488c9f2c7c19
parentcf59681183f01e88325c407f815347874985956a (diff)
downloadipxrelay-96a65558a1b5a7bd3c4061ad64b1670b5def3f3b.zip
ipxrelay-96a65558a1b5a7bd3c4061ad64b1670b5def3f3b.tar.gz
ipxrelay-96a65558a1b5a7bd3c4061ad64b1670b5def3f3b.tar.bz2
ipxrelay-96a65558a1b5a7bd3c4061ad64b1670b5def3f3b.tar.xz
Move cleanup_timeouts() to head of loop and before transmit
Move cleanup_timeouts() to the head of the loop, so we can use continue instead of goto; this is a cleanup. Also add a cleanup_timeouts() before we walk the client list, that way we avoid spending effort sending data to already-dead clients. This relies on the fact that cleanup_timeouts() can only remove clients from the tail end of the list and otherwise leaves the list order undisturbed. This may mean we execute cleanup_timeouts() twice on the same data, but that is a very cheap operation, so it doesn't matter.
-rw-r--r--ipxrelay.c64
1 files changed, 34 insertions, 30 deletions
diff --git a/ipxrelay.c b/ipxrelay.c
index 661b494..9467bed 100644
--- a/ipxrelay.c
+++ b/ipxrelay.c
@@ -273,66 +273,70 @@ static int ipx_relay_server(int fd)
struct ipx_client *s, *d;
prepare_timer();
+ now = time(NULL);
while (1) {
+ /* Potentially redundant, but if so very cheap so we don't care */
+ cleanup_timeouts(now);
+
fromlen = sizeof from;
len = recvfrom(fd, pkt.buf, sizeof pkt, 0, &from, &fromlen);
now = time(NULL);
if (fromlen < sizeof(struct sockaddr_in))
- goto bad_pkt; /* WTF? */
+ continue; /* WTF? */
if (len < (int)sizeof(struct ipx_header))
- goto bad_pkt;
+ continue;
if (pkt.hdr.checksum != 0xffff)
- goto bad_pkt;
+ continue;
hlen = ntohs(pkt.hdr.length);
if (hlen < 30 || hlen > len)
- goto bad_pkt;
+ continue;
/* No routers, it's all network zero */
if (pkt.hdr.dst_addr.network | pkt.hdr.src_addr.network)
- goto bad_pkt;
+ continue;
/* Reject routed packets */
if (pkt.hdr.transcontrol)
- goto bad_pkt;
+ continue;
if (is_ipx_null(&pkt.hdr.dst_addr)) {
/* Sent to the null address: registration packet */
- if (register_client(fd, &pkt.hdr, &from, now))
- goto bad_pkt;
- } else {
- s = find_client(&from, &pkt.hdr.src_addr);
- if (!s)
- goto bad_pkt;
+ register_client(fd, &pkt.hdr, &from, now);
+ continue;
+ }
- bump_timeout(s, now);
+ s = find_client(&from, &pkt.hdr.src_addr);
+ if (!s)
+ continue;
- /* Now s->next is a linked list of all *other* clients */
+ bump_timeout(s, now);
+
+ /* Handle timeouts here rather than sending to a dead client */
+ cleanup_timeouts(now);
+
+ /* Now s->next is a linked list of all *other* clients */
+
+ if (is_ipx_bcst(&pkt.hdr.dst_addr)) {
+ /* Broadcast packet */
- if (is_ipx_bcst(&pkt.hdr.dst_addr)) {
- /* Broadcast packet */
-
- for (d = s->next; d != &client_head; d = d->next)
+ for (d = s->next; d != &client_head; d = d->next)
+ send_ipx_packet(fd, d, pkt.buf, hlen);
+ } else {
+ /* Send to a single client */
+
+ for (d = s->next; d != &client_head; d = d->next) {
+ if (!memcmp(&d->ipx, &pkt.hdr.dst_addr,
+ sizeof pkt.hdr.dst_addr)) {
send_ipx_packet(fd, d, pkt.buf, hlen);
- } else {
- /* Send to a single client */
-
- for (d = s->next; d != &client_head; d = d->next) {
- if (!memcmp(&d->ipx, &pkt.hdr.dst_addr,
- sizeof pkt.hdr.dst_addr)) {
- send_ipx_packet(fd, d, pkt.buf, hlen);
- break;
- }
+ break;
}
}
}
-
- bad_pkt:
- cleanup_timeouts(now);
}
return -1;