diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2015-10-15 22:12:27 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2015-10-15 22:12:27 +0000 |
commit | 7231c3d0557db854c0bb1565cec8d6d205256865 (patch) | |
tree | 56e6fb3fa9197824d4d322a19e707d74298b83d2 | |
parent | d34caa49d0a4b589aa1426dd3dbd9418ecb2ef25 (diff) |
better memory handling of the request/cache chain
-rw-r--r-- | usr.sbin/rebound/rebound.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/usr.sbin/rebound/rebound.c b/usr.sbin/rebound/rebound.c index 28ea943ecff..a6ee07e8726 100644 --- a/usr.sbin/rebound/rebound.c +++ b/usr.sbin/rebound/rebound.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rebound.c,v 1.11 2015/10/15 21:59:54 tedu Exp $ */ +/* $OpenBSD: rebound.c,v 1.12 2015/10/15 22:12:26 tedu Exp $ */ /* * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org> * @@ -59,6 +59,12 @@ struct dnsrr { /* ... */ }; +/* + * requests will point to cache entries until a response is received. + * until then, the request owns the entry and must free it. + * after it's on the list, the request must not free it. + */ + struct dnscache { TAILQ_ENTRY(dnscache) cache; struct dnspacket *req; @@ -194,6 +200,7 @@ newrequest(int ud, struct sockaddr *remoteaddr) return req; fail: + free(hit); close(req->s); free(req); return NULL; @@ -204,6 +211,7 @@ sendreply(int ud, struct request *req) { uint8_t buf[65536]; struct dnspacket *resp; + struct dnscache *ent; size_t r; resp = (struct dnspacket *)buf; @@ -215,24 +223,30 @@ sendreply(int ud, struct request *req) return; resp->id = req->clientid; sendto(ud, buf, r, 0, &req->from, req->fromlen); - if (req->cacheent) { - req->cacheent->ts = now; - req->cacheent->ts.tv_sec += 10; - req->cacheent->resp = malloc(r); - if (!req->cacheent->resp) + if ((ent = req->cacheent)) { + ent->ts = now; + ent->ts.tv_sec += 10; + ent->resp = malloc(r); + if (!ent->resp) return; - memcpy(req->cacheent->resp, buf, r); - req->cacheent->resplen = r; - TAILQ_INSERT_TAIL(&cache, req->cacheent, cache); + memcpy(ent->resp, buf, r); + ent->resplen = r; + TAILQ_INSERT_TAIL(&cache, ent, cache); } } void freerequest(struct request *req) { + struct dnscache *ent; + TAILQ_REMOVE(&reqfifo, req, fifo); close(req->client); close(req->s); + if ((ent = req->cacheent) && !ent->resp) { + free(ent->req); + free(ent); + } free(req); } |