From: Wouter Wijngaards Date: Tue, 16 Oct 2007 12:26:09 +0000 (+0000) Subject: assertions, zero termination for gethostname, log_hex without malloc. X-Git-Tag: release-0.6~65 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4260a18fb13fbb274686637b9f1702b8b59ffef8;p=thirdparty%2Funbound.git assertions, zero termination for gethostname, log_hex without malloc. git-svn-id: file:///svn/unbound/trunk@679 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/daemon.c b/daemon/daemon.c index 5813a3e5d..5447e9f29 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -269,8 +269,6 @@ static void daemon_setup_modules(struct daemon* daemon) daemon->env->cfg = daemon->cfg; daemon->env->alloc = &daemon->superalloc; daemon->env->worker = NULL; - daemon->env->send_packet = &worker_send_packet; - daemon->env->send_query = &worker_send_query; daemon->env->need_to_validate = 0; /* set by module init below */ for(i=0; inum_modules; i++) { log_info("init module %d: %s", i, daemon->modfunc[i]->name); @@ -384,7 +382,7 @@ daemon_stop_others(struct daemon* daemon) worker_send_cmd(daemon->workers[i], daemon->workers[0]->front->udp_buff, worker_cmd_quit); } - /** wait for them to quit */ + /* wait for them to quit */ for(i=1; inum; i++) { /* join it to make sure its dead */ verbose(VERB_ALGO, "join %d", i); diff --git a/daemon/worker.c b/daemon/worker.c index c4f795383..25091f8e5 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -624,10 +624,11 @@ answer_chaos(struct worker* w, struct query_info* qinfo, if(cfg->hide_identity) return 0; if(cfg->identity==NULL || cfg->identity[0]==0) { - char buf[MAXHOSTNAMELEN]; - if (gethostname(buf, MAXHOSTNAMELEN) == 0) + char buf[MAXHOSTNAMELEN+1]; + if (gethostname(buf, MAXHOSTNAMELEN) == 0) { + buf[MAXHOSTNAMELEN] = 0; chaos_replystr(pkt, buf, edns); - else { + } else { log_err("gethostname: %s", strerror(errno)); chaos_replystr(pkt, "no hostname", edns); } @@ -797,22 +798,22 @@ worker_sighandler(int sig, void* arg) struct worker* worker = (struct worker*)arg; switch(sig) { case SIGHUP: - log_info("caught signal SIGHUP"); + verbose(VERB_DETAIL, "caught signal SIGHUP"); worker->need_to_restart = 1; comm_base_exit(worker->base); break; case SIGINT: - log_info("caught signal SIGINT"); + verbose(VERB_DETAIL, "caught signal SIGINT"); worker->need_to_restart = 0; comm_base_exit(worker->base); break; case SIGQUIT: - log_info("caught signal SIGQUIT"); + verbose(VERB_DETAIL, "caught signal SIGQUIT"); worker->need_to_restart = 0; comm_base_exit(worker->base); break; case SIGTERM: - log_info("caught signal SIGTERM"); + verbose(VERB_DETAIL, "caught signal SIGTERM"); worker->need_to_restart = 0; comm_base_exit(worker->base); break; @@ -949,6 +950,8 @@ worker_init(struct worker* worker, struct config_file *cfg, worker->thread_num); worker->env = *worker->daemon->env; worker->env.worker = worker; + worker->env.send_packet = &worker_send_packet; + worker->env.send_query = &worker_send_query; worker->env.alloc = &worker->alloc; worker->env.rnd = worker->rndstate; worker->env.scratch = worker->scratchpad; diff --git a/doc/Changelog b/doc/Changelog index 6a2d58c2b..638db8be6 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +16 October 2007: Wouter + - no malloc in log_hex. + - assertions around system calls. + - protect against gethostname without ending zero. + 15 October 2007: Wouter - nicer warning. - fix IP6 TCP, wrong definition check. With test package. diff --git a/services/outside_network.c b/services/outside_network.c index 986674875..cf1e347c3 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -91,7 +91,7 @@ serviced_cmp(const void* key1, const void* key2) if(q1->qbuflen > q2->qbuflen) return 1; log_assert(q1->qbuflen == q2->qbuflen); - /* FIXME: will not detect alternate casing of qname */ + /* will not detect alternate casing of qname */ if((r = memcmp(q1->qbuf, q2->qbuf, q1->qbuflen)) != 0) return r; if(q1->dnssec != q2->dnssec) { @@ -122,6 +122,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) int s; log_assert(pend); log_assert(pkt); + log_assert(w->addrlen > 0); /* open socket */ #ifdef INET6 if(addr_is_ip6(&w->addr, w->addrlen)) @@ -249,17 +250,12 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error, p = (struct pending*)rbtree_search(outnet->pending, &key); if(!p) { verbose(VERB_DETAIL, "received unwanted or unsolicited udp reply dropped."); - if(verbosity >= VERB_ALGO) - log_hex("dropped message", - ldns_buffer_begin(c->buffer), - ldns_buffer_limit(c->buffer)); + log_buf(VERB_ALGO, "dropped message", c->buffer); return 0; } verbose(VERB_ALGO, "received udp reply."); - if(verbosity >= VERB_ALGO) - log_hex("udp message", ldns_buffer_begin(c->buffer), - ldns_buffer_limit(c->buffer)); + log_buf(VERB_ALGO, "udp message", c->buffer); if(p->c != c) { verbose(VERB_DETAIL, "received reply id,addr on wrong port. " "dropped."); @@ -1125,6 +1121,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, int roundtime = (now.tv_sec - sq->last_sent_time.tv_sec)*1000 + ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000; verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime); + log_assert(roundtime >= 0); if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, roundtime, (time_t)now.tv_sec)) log_err("out of memory noting rtt."); diff --git a/testcode/unitmsgparse.c b/testcode/unitmsgparse.c index 784aaefb8..43e5c3723 100644 --- a/testcode/unitmsgparse.c +++ b/testcode/unitmsgparse.c @@ -206,10 +206,8 @@ test_buffers(ldns_buffer* pkt, ldns_buffer* out) s1 = ldns_buffer2pkt_wire(&p1, pkt); s2 = ldns_buffer2pkt_wire(&p2, out); if(vbmp) { - log_hex("orig in hex", ldns_buffer_begin(pkt), - ldns_buffer_limit(pkt)); - log_hex("unbound out in hex", ldns_buffer_begin(out), - ldns_buffer_limit(out)); + log_buf(0, "orig in hex", pkt); + log_buf(0, "unbound out in hex", out); printf("\npacket from unbound (%d):\n", (int)ldns_buffer_limit(out)); ldns_pkt_print(stdout, p2); diff --git a/util/data/msgparse.c b/util/data/msgparse.c index 383a1ceb0..f13c9c6d0 100644 --- a/util/data/msgparse.c +++ b/util/data/msgparse.c @@ -701,8 +701,7 @@ add_rr_to_rrset(struct rrset_parse* rrset, ldns_buffer* pkt, /* verbose(VERB_DETAIL, "Packet contains rrset data in " "multiple sections, dropped last part."); - log_hex("packet was: ", ldns_buffer_begin(pkt), - ldns_buffer_limit(pkt)); + log_buf(VERB_DETAIL, "packet was", pkt); */ /* forwards */ if(!skip_ttl_rdata(pkt)) diff --git a/util/locks.c b/util/locks.c index e78b22de6..b2b1f49e3 100644 --- a/util/locks.c +++ b/util/locks.c @@ -81,7 +81,7 @@ void ub_thread_sig_unblock(int sig) if((err=thr_sigsetmask(SIG_UNBLOCK, &sigset, NULL))) fatal_exit("thr_sigsetmask: %s", strerror(err)); # else - /* have nothing, do nothing */ + /* have nothing, do single thread case */ if((err=sigprocmask(SIG_UNBLOCK, &sigset, NULL))) fatal_exit("sigprocmask: %s", strerror(errno)); # endif /* HAVE_SOLARIS_THREADS */ diff --git a/util/log.c b/util/log.c index b596dbd66..a0b33a9ec 100644 --- a/util/log.c +++ b/util/log.c @@ -83,7 +83,7 @@ log_init(const char* filename, int use_syslog) || log_to_syslog #endif ) - verbose(VERB_DETAIL, "switching log to %s", + verbose(VERB_DETAIL, "switching log to %s", use_syslog?"syslog":(filename&&filename[0]?filename:"stderr")); if(logfile && logfile != stderr) fclose(logfile); @@ -218,23 +218,35 @@ verbose(enum verbosity_value level, const char* format, ...) void log_hex(const char* msg, void* data, size_t length) { - size_t i; + size_t i, j; uint8_t* data8 = (uint8_t*)data; const char* hexchar = "0123456789ABCDEF"; - char* buf = malloc(length*2 + 1); /* alloc hex chars + \0 */ - size_t blocksize = 1024; - for(i=0; i> 4 ]; - buf[i*2 + 1] = hexchar[ data8[i] & 0xF ]; + char buf[1024+1]; /* alloc blocksize hex chars + \0 */ + const size_t blocksize = 1024; + size_t len; + + if(length == 0) { + log_info("%s[%u]", msg, (unsigned)length); + return; } - buf[length*2] = 0; - if(length < blocksize/2) - log_info("%s[%u] %s", msg, (unsigned)length, buf); - else { - for(i=0; i> 4 ]; + buf[j*2 + 1] = hexchar[ data8[i+j] & 0xF ]; } + buf[len*2] = 0; + log_info("%s[%u:%u] %.*s", msg, (unsigned)length, + (unsigned)i, (int)len*2, buf); } - free(buf); +} + +void log_buf(enum verbosity_value level, const char* msg, ldns_buffer* buf) +{ + if(verbosity < level) + return; + log_hex(msg, ldns_buffer_begin(buf), ldns_buffer_limit(buf)); } diff --git a/util/log.h b/util/log.h index 12dc6bfe5..f14256f17 100644 --- a/util/log.h +++ b/util/log.h @@ -125,6 +125,15 @@ void log_warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2); */ void log_hex(const char* msg, void* data, size_t length); +/** + * Easy alternative for log_hex, takes a ldns_buffer. + * @param level: verbosity level for this message, compared to global + * verbosity setting. + * @param msg: string desc to print + * @param buf: the buffer. + */ +void log_buf(enum verbosity_value level, const char* msg, ldns_buffer* buf); + /** * Log fatal error message, and exit the current process. * Pass printf formatted arguments. No trailing newline is needed. diff --git a/util/net_help.c b/util/net_help.c index bddcf0dbe..7eadca4fd 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -61,11 +61,13 @@ write_socket(int s, const void *buf, size_t size) const char* data = (const char*)buf; size_t total_count = 0; + fd_set_block(s); while (total_count < size) { ssize_t count = write(s, data + total_count, size - total_count); if (count == -1) { if (errno != EAGAIN && errno != EINTR) { + fd_set_nonblock(s); return 0; } else { continue; @@ -73,6 +75,7 @@ write_socket(int s, const void *buf, size_t size) } total_count += count; } + fd_set_nonblock(s); return 1; } @@ -92,6 +95,22 @@ fd_set_nonblock(int s) return 1; } +int +fd_set_block(int s) +{ + int flag; + if((flag = fcntl(s, F_GETFL)) == -1) { + log_err("cannot fcntl F_GETFL: %s", strerror(errno)); + flag = 0; + } + flag &= ~O_NONBLOCK; + if(fcntl(s, F_SETFL, flag) == -1) { + log_err("cannot fcntl F_SETFL: %s", strerror(errno)); + return 0; + } + return 1; +} + int is_pow2(size_t num) { diff --git a/util/net_help.h b/util/net_help.h index 83e631e8e..aeb3802bc 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -98,7 +98,7 @@ int str_is_ip6(const char* str); /** * Write (blocking) to a nonblocking socket. - * @param s: fd. + * @param s: fd. Is set to be nonblocking at exit. * @param buf: data buffer. * @param size: length of data to send. * @return: 0 on error. errno is set. @@ -113,6 +113,13 @@ write_socket(int s, const void *buf, size_t size); */ int fd_set_nonblock(int s); +/** + * Set fd (back to) blocking. + * @param s: file descriptor. + * @return: 0 on error (error is printed to log). + */ +int fd_set_block(int s); + /** * See if number is a power of 2. * @param num: the value. diff --git a/util/netevent.c b/util/netevent.c index df3882760..696fd3144 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -161,6 +161,9 @@ comm_point_send_udp_msg(struct comm_point *c, ldns_buffer* packet, struct sockaddr* addr, socklen_t addrlen) { ssize_t sent; + log_assert(c->fd != -1); + log_assert(ldns_buffer_remaining(packet) > 0); + log_assert(addr && addrlen > 0); sent = sendto(c->fd, ldns_buffer_begin(packet), ldns_buffer_remaining(packet), 0, addr, addrlen); @@ -189,6 +192,8 @@ comm_point_udp_callback(int fd, short event, void* arg) log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); ldns_buffer_clear(rep.c->buffer); rep.addrlen = (socklen_t)sizeof(rep.addr); + log_assert(fd != -1); + log_assert(ldns_buffer_remaining(rep.c->buffer) > 0); recv = recvfrom(fd, ldns_buffer_begin(rep.c->buffer), ldns_buffer_remaining(rep.c->buffer), 0, (struct sockaddr*)&rep.addr, &rep.addrlen); @@ -234,6 +239,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) /* accept incoming connection. */ rep.c = NULL; rep.addrlen = (socklen_t)sizeof(rep.addr); + log_assert(fd != -1); new_fd = accept(fd, (struct sockaddr*)&rep.addr, &rep.addrlen); if(new_fd == -1) { /* EINTR is signal interrupt. others are closed connection. */ @@ -244,7 +250,8 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) && errno != EPROTO #endif /* EPROTO */ ) - log_err("accept failed: %s", strerror(errno)); + return; + log_err("accept failed: %s", strerror(errno)); return; } /* find free tcp handler. */ @@ -330,6 +337,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) if(!c->tcp_is_reading) return 0; + log_assert(fd != -1); if(c->tcp_byte_count < sizeof(uint16_t)) { /* read length bytes */ r = read(fd, ldns_buffer_at(c->buffer, c->tcp_byte_count), @@ -361,6 +369,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) (int)ldns_buffer_limit(c->buffer)); } + log_assert(ldns_buffer_remaining(c->buffer) > 0); r = read(fd, ldns_buffer_current(c->buffer), ldns_buffer_remaining(c->buffer)); if(r == 0) { @@ -391,6 +400,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) log_assert(c->type == comm_tcp); if(c->tcp_is_reading) return 0; + log_assert(fd != -1); if(c->tcp_byte_count == 0 && c->tcp_check_nb_connect) { /* check for pending error from nonblocking connect */ /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ @@ -414,6 +424,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count; iov[1].iov_base = ldns_buffer_begin(c->buffer); iov[1].iov_len = ldns_buffer_limit(c->buffer); + log_assert(iov[0].iov_len > 0); + log_assert(iov[1].iov_len > 0); r = writev(fd, iov, 2); if(r == -1) { if(errno == EINTR || errno == EAGAIN) @@ -431,6 +443,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) } return 1; } + log_assert(ldns_buffer_remaining(c->buffer) > 0); r = write(fd, ldns_buffer_current(c->buffer), ldns_buffer_remaining(c->buffer)); if(r == -1) { @@ -832,6 +845,8 @@ comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov, size_t iovlen) { log_assert(repinfo && repinfo->c); + log_assert(repinfo->c->fd != -1); + log_assert(repinfo->addrlen > 0); if(repinfo->c->type == comm_udp) { struct msghdr hdr; memset(&hdr, 0, sizeof(hdr)); @@ -1005,6 +1020,7 @@ comm_timer_disable(struct comm_timer* timer) void comm_timer_set(struct comm_timer* timer, struct timeval* tv) { + log_assert(tv); if(timer->ev_timer->enabled) comm_timer_disable(timer); evtimer_add(&timer->ev_timer->ev, tv);